Architecture#
Source layout#
All of the plugin’s logic lives under src/:
File |
Responsibility |
|---|---|
|
Plugin entry point: loads settings, wires up the settings tab, the code block processor, paste handler, attachment upload handler, and link tracker; adds the Convert selected Nextcloud internal link to a file block command. |
|
Shared types: |
|
The settings tab: profile list, the “Add new profile” form, and the Login Flow v2 handshake (start / poll / cancel) for both new and reconnected profiles. |
|
Looks up the current Obsidian UI language via the official
|
|
Implements Nextcloud’s Login Flow v2:
|
|
|
|
A WebDAV client for the parts of the Nextcloud API the plugin
needs, all over Obsidian’s |
|
Registers the |
|
Listens for the editor’s paste event; when the pasted plain text
is a recognized Nextcloud internal link, replaces it with a
|
|
Listens for the same paste event for pasted files. Skips
images (so Obsidian’s normal image-paste behavior is untouched),
requires the active note to have an |
|
Tracks each open markdown note’s set of |
|
The confirmation modal shown by the link tracker: Keep on Nextcloud or Move to trash. Closing it without an explicit choice (Esc / outside click) defaults to the non-destructive “keep” option. |
|
|
Data flow#
settings.ts --> NextcloudProfile[] (server URL, login name, app password)
| via nextcloud/loginFlow.ts (Login Flow v2)
v
nextcloud/link.ts --> parses a pasted URL / nc-folder value
|
v
nextcloud/client.ts --> SEARCH/PROPFIND/MKCOL/PUT/DELETE over requestUrl
|
+--> paste-handler.ts --> URL paste --> ```nextcloud-file``` block
|
+--> attachment-upload.ts --> file paste --> upload, then ```nextcloud-file``` block
|
+--> block-view.ts --> renders the block: icon, name, path, size, date, Open-in-browser
|
+--> link-tracker.ts --> block removed from a note --> confirm-delete-modal.ts
--> optional deleteFile (moves to Nextcloud trash)
Reference syntax#
A resolved reference is stored as a fenced code block:
```nextcloud-file
https://cloud.example.com/f/12345
```
The block’s content is the original Nextcloud internal link, unmodified —
there is no separate ID scheme to keep in sync. Re-resolving a block only
needs findProfileForLink (matching the link’s host against a
profile’s server URL) and the file id already embedded in the link, so a
block keeps rendering correctly even if the file is renamed or moved on
the server, and continues to work if a profile is deleted and re-added
under the same server URL.
Only the numeric Nextcloud file id is stored, not a path — this is why
metadata lookup uses WebDAV SEARCH (fetchFileMeta) rather than a
plain PROPFIND on a path: the plugin has to ask the server “what file
has this id” rather than “what’s at this path,” since the path isn’t
known until the server answers.
Date field: “Created” vs. “Modified”#
The rendered card labels its date either Created or Modified.
fetchFileMeta/fetchFileMetaByPath prefer WebDAV’s
creationdate property, but some Nextcloud/storage backends return a
placeholder value there (e.g. the Unix epoch) instead of leaving it
absent. Any creationdate at or before the year 2000 — well before
Nextcloud existed — is treated as “not actually known,” and the card
falls back to getlastmodified labeled Modified instead.
No runtime dependencies#
Beyond what Obsidian itself provides (the obsidian package), the
plugin has no runtime dependencies — the WebDAV client, login flow, and
internal-link parsing are all hand-written rather than pulled in from
npm, keeping the bundle small and avoiding exposure to a third-party HTTP
library’s own vulnerabilities.