mirror of
https://github.com/runbear-io/beardrive.git
synced 2026-08-25 08:08:08 +02:00
fix(webapp): a wikilink is a real link, not a wiki: string (BEA-136) (#151)
[[guide]] rendered as href="wiki:guide" — a pseudo-scheme no browser can resolve. The delegated click handler rescued a plain left-click, so the feature looked fine until someone copied the link, middle-clicked it, or opened it in a new tab and got a dead string. Resolution moves from click time to transform time: transformHTML (the pass that already rewrites this HTML before the mount) matches the target against flatFiles and writes the real urlForPath() URL, plus a data-wiki marker. A wikilink matching no file loses its href entirely and renders as .wiki-missing, so no "wiki:" survives into the DOM either way. The matching rules didn't change — they moved into a pure resolveWiki() in util.ts, where node --test covers the whole matrix without a browser. The consequence to get right is the click: real hrefs mean a plain click must be intercepted (or it does a full document load) and every modified click must be let through (or the fix buys nothing) — the same rule nav.ts:linkProps applies everywhere else. The guard sits above both branches, so cmd-clicking a relative markdown link now opens a tab too instead of SPA-navigating the current one. markdown.go is unchanged: wiki: stays the marker the server leaves behind because RenderMarkdown has no file tree. /s/<token> share pages keep their dead wikilinks by the spec's decision — the target isn't part of the share. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fd392aa9b0
commit
398f30d64b
@@ -96,7 +96,7 @@ classDiagram
|
||||
}
|
||||
note for components "NewProjectDialog replaced ProjectNav's name-only modalPrompt: name + starting point, POSTing {name, template}. Its options come from useConfig()'s `templates`, never a hardcoded list, so a hub shipping another template needs no frontend change; the initial selection is options[0].value — the same array element the RECOMMENDED badge indexes, so the badged row and the checked row are one row by construction (on a template-less hub that row is 'I already have a folder', which still creates an empty project). modal.tsx keeps its one-field API — teaching it about choices would tax every other caller"
|
||||
note for components "HistoryFilters drives the SERVER (?q=/?user=/?since=/?until= on the history API), never the loaded page — filtering what is on screen would lie about everything below the fold and break next_cursor. Its state is Route.filters, so a narrowed feed is linkable, survives reload, and Back undoes it; the author list accumulates across fetches, because filtering by one author leaves only their rows loaded"
|
||||
note for components "FileView's transformHTML now drops `data:image/svg` from any rendered img and any `data:` href from any rendered link — goldmark admits them, and an inline SVG is a document rather than a picture (the same property the server's sandboxInline walls off). Insights builds its per-device folder bag with Object.create(null), since folder names come off a peer's journal and one named __proto__ silently emptied the matrix. style.css sets unicode-bidi isolate-override on the peer-authored strings a reader is expected to CHECK (listing rows, breadcrumb, history path/note/device) — journal.SafeText refuses the bidi CONTROLS, but a single strong-RTL LETTER is legal and still reorders a row"
|
||||
note for components "FileView's transformHTML resolves the server's `wiki:` marker against flatFiles into a real urlForPath() href (unresolvable ones lose the href and get .wiki-missing), so copy-link/middle-click/new-tab work and only a plain click reaches the delegated handler — resolution used to happen at click time, which left a dead `wiki:guide` string in the DOM (BEA-136). It also drops `data:image/svg` from any rendered img and any `data:` href from any rendered link — goldmark admits them, and an inline SVG is a document rather than a picture (the same property the server's sandboxInline walls off). Insights builds its per-device folder bag with Object.create(null), since folder names come off a peer's journal and one named __proto__ silently emptied the matrix. style.css sets unicode-bidi isolate-override on the peer-authored strings a reader is expected to CHECK (listing rows, breadcrumb, history path/note/device) — journal.SafeText refuses the bidi CONTROLS, but a single strong-RTL LETTER is legal and still reorders a row"
|
||||
note for components "HistoryView's RunGroup header carries the run-wide undo (POST undo-run, gated by the same write permission as the per-row restore/remove). It asks the SERVER for the file list first (preview: true) rather than deriving it from the loaded feed — that window is paged and filterable, so a client-computed list is wrong exactly when the run is old. modal.tsx's Confirm.message widened from string to ReactNode for it (the prompt's one-field API is untouched), so the dialog can show every path, its action, and the "changed after this run" warning inline"
|
||||
note for components "components/ui — shadcn/ui primitives (Radix, copied in), themed from BearDrive tokens in tw.css; rendered markdown is transformed as a string before mounting, link clicks delegated on the container — never patch the dangerouslySetInnerHTML subtree"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user