- 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
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.
Convert the vertical sidebar navigation (Source, Issues, Patches) into
a horizontal tab bar above the content area. The ContextRepo info moves
into a popover behind an info button in the tab bar.
Mobile footer navigation is preserved for small screens, with the tab
bar hidden on mobile.
When a saved node (e.g. localhost) is down, the app previously showed a
dead-end "Node not found" page with no way to navigate away.
Now the not-found page displays the seed selector inline with the error
title, showing which node failed and letting users switch to a different
one directly. The same treatment applies when navigating to a repo on an
unreachable node.
They were not run by the test suite at all, because they lacked the
.spec.ts suffix. This change makes sure they're run again and fixes a
all failing specs.
Allow radicle-explorer to connect to a locally running radicle-httpd via
https://app.radicle.xyz/nodes/localhost. This was previously disabled to
encourage use of Radicle Desktop, but is now useful for testing the new
always-on node in local development environments.
Remove support for /nodes/radicle.local, an undocumented and unused convention.
Fix remote node loading when Cloudflare URL-encodes port separator (: → %3A).
Seemed to me there was no way to browse all the repositories being seeded on a node.
On the massive public nodes this is not that useful a feature since there are too many
and too jumbled an assortment, but for a smaller personal node, this feature might be
valuable to make the explorer's contents a bit easier to explore.
Went with the most unintrusive implementation of this idea for now; just enough
that it "does the job" (you can access this view, and paginate the results)
but does not have any of the bells and whistles it should have (search/filtering,
sorting, page query parameters support).
As part of this work, since the repos section gets much more complex, I extracted
the repos part of the page into its own component. Otherwise, it is just very simply
allowing the parameters to the `fetchRepoInfos` call to be manipulated from the page.
The previous CSS was setting the task-list element to be `display: flex`, but this
does not play well with a task list item that contains further nodes. Commonly,
a sub-list, but even a bolded bit of text is rendered with a bit of unpleasant
extra spacing.
Example:
- [ ] Task 1
- Step 1: Do *thing*
- Step 2: Do __another__ thing
Or since I'm not sure if that's going to be rendered via this interface,
just find such a file on the hosted version. [This](https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az28AWjUMmH9kFFCw7W9GMSCHoA9zZ)
repository of mine is particularly offensive in this category.
To solve the issue, I have removed the flex, and additional turned the icon component
itself into an inline flex element, as it being a block element was likely part of
the reason the list became a flex container to begin with.
We recently moved app.radicle.xyz to Cloudflare, which by default
normalizes all URLs to be encoded on redirect. The redirects happen
because we run in SPA mode.
Instead of only displaying a comment, we need to make sure users know
that this has been a line comment.
Linking to changes for the display of the comment is a bit trickier,
will do so in a follow up
Based on the work done in commit
`a73c5490b160435a0ef5408b54185c9f698cb73f` there are a few places that
make the app not load in case dom storage aka localStorage is disabled.
To allow some very basic hyperlinking in commit descriptions we can
replace fully specified urls with a valid scheme into
`radicle-external-link` components.
Instead of panicking when trying to handle non utf8 lines we should
return `null` as line output.
This way we can on the frontend detect if a file has any lines the api
wasn't able to parse and fallback to show a file as a `Binary File`
Changes the display of embeds from being markdown images to markdown
links.
Mimics the way embeds work on the desktop app and allows other embeds to
work too like pdfs, videos, etc.
We don't really need the `clipboard` prop.
By switching between stats in patches and issue listings the clipboard
props aren't been recomputed.
Wrote a test that should make sure this doesn't break in the future.
Previously assignees were displayed using a chip, which while it looked
nice had the following issues:
- It only showed the node ID rather than the alias (and actually the
node ID was cut off)
- It wasn't clickable to go to the user's profile
- It was not a consistent experience with the rest of the users
displayed around the application (e.g. in reviews, uploader, branches
view).