When mermaid.render fails, suppress mermaid's "Syntax error"
overlay and show our own small warning above the original code
block so the source stays visible. Subsequent diagrams in the
same document still render.
Hoist the dynamic import and initialize() into a
module-scoped promise. Previous code re-ran initialize()
on every afterUpdate that had a mermaid block.
Switch to a dynamic import in afterUpdate and drop
manualChunks so Rolldown auto-splits the lazy chunk.
Eager bundle drops from 1.3 MB to 610 KB gzipped.
Replace global setConfig with an exported sanitizeConfig passed
inline. The global config leaked into mermaid's internal
strict-mode sanitization, stripping valid SVG diagrams.
To allow some very basic hyperlinking in commit descriptions we can
replace fully specified urls with a valid scheme into
`radicle-external-link` components within patches and git history.
GitHub and GitLab will prefix archive payloads with the name of the repo
and the refspec. This patch naively applies a prefix in similar fashion.
The refspec might contain filesystem path separators, like a forward
slash (`/`). GitHub and GitLab replace that with a hyphen (`-`). This
patch applies that same replacement.
The file name that is suggested to browsers (via the HTTP header
`Content-Disposition`) is changed to match the prefix.
The additional archive formats `tar` and `zip` are now supported as
well.
Users that relied on the archive *not* carrying the prefix introduced
here, may pass the query `?prefix=false` to get the old behavior.
This does not affect the `Content-Disposition` header, though. Users
who relied on the downloaded file be named in a certain way after,
and also used the file name from `Content-Disposition` for the name,
cannot get back the old behavior, but must instead rename the file.
Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.dev>
- Without strong, **bold** rendered as plain text since marked
emits <strong> and DOMPurify stripped the unknown tag
- Add strong, b, i, del, s to DOMPurify allow-list
- Cover the other inline emphasis tags authors may write as raw
HTML or that GFM strikethrough emits (<del>)
Changes which were needed after the upgrade:
- Replace vite-plugin-virtual (vite 8 incompatible) with vite's
built-in `define` for the buildTimeConfig injection
- tsconfig: drop deprecated `baseUrl` (TS 5+ resolves `paths`
relative to tsconfig)
- Vitest 4: import `defineConfig` from `vitest/config` so `test`
is valid in vite configs
- Zod 4: rename `.errors` to `.issues`, make `ZodSchema` a
type-only import, drop the removed `SafeParseReturnType`
- Tighten/loosen generic casts in localStore to match stricter
zod 4 inference
- ESLint 9 `no-useless-assignment`: remove redundant initializers
and dead reassignments; disable the rule where Svelte's reactive
blocks confuse the analyser
- Svelte/eslint `prefer-svelte-reactivity`: disable for legacy
Svelte usages of URL / Set
- Misc naming-convention and prefer-const fixes
Playwright 1.52 hangs under Node 24 when loading test files that
transitively import modules with top-level await (tests/support/
support.ts). Node 24 enables require(esm) by default, and the old
CJS-based .ts transformer deadlocks on TLA.
Also update CLAUDE.md: playwright 1.59's --project flag is variadic
and greedily consumes trailing args, so the file path must come
before --project.
This also drops .tool-versions to keep a single source of truth for the
node version in .nvmrc. We also point the github actions to .nvmrc now.
I'm the only dev who's using asdf to manage my tooling and I decided to
just configure it to fall back to .nvmrc via `legacy_version_file =
yes`.
The `flake.nix` file used `heartwood` as its source of truth for a lot
of tooling.
The `heartwood` library was pinned to its `1.0.0` version, causing
issues when attempting run `nix develop`.
Instead, modify the inputs to grab the tooling from their source of truth.
The `heartwood` binaries can now be retrieved via the `radicle-node`
entry in the Nix packages registry.
Deploys two workers: og-injector intercepts social crawler requests and
injects Open Graph meta tags; open-graph renders 1200×630 PNG cards
using Satori with repo/user avatars ported from avatar.ts.
Svelte 5's signal system can evaluate derived signals in child
components before parent {#if} blocks destroy them. When the
route store changes (e.g. from repo.commit to repo.patch), the
spread props update before the old component is unmounted, causing
commit to become undefined and Changeset to throw accessing
undefined.files.
Use optional chaining on Commit prop expressions so getters
return undefined instead of throwing, and guard Changeset
template with {#if diff} plus optional chaining on files
lookups.