fetchLatestSha and queryFileContent were silently catching every error
(including expired-token 401s) and returning null, so the freshness
badge could stay on "offline" with no UI hint that re-auth was needed.
Wrap both calls in runWithAuthRetry to recover from refreshable tokens
transparently, and switch fetchLatestSha to a tagged result so the
freshness hook can distinguish auth failure from network failure.
Moves the user identity element out of the tabs bar (where it was
absolutely positioned over the tabs) into a proper header row next to
the home button, and switches it from SignInAtproto to the shared
UserPill so the same atproto-first identity shows everywhere.
Replaces the duplicated profile-chip button and profile_modal dialog in
WelcomeWorld and RepoList with the shared components, and removes the
now-orphaned profile-chip, hw-modal, hw-ms-label, hw-btn-ghost, and
hw-rule styles. As a side effect the displayed identity now prefers the
ATProto handle over the GitHub username.
UserPill renders an avatar + display name button, preferring the ATProto
handle over the GitHub username, and emits @click so each view decides
what to open. ProfileModal extracts the previously duplicated
profile_modal dialog with self-contained DaisyUI-token styling.
Use RFC 6570 reserved expansion ({+path}) so slashes stay literal in
the request URL, and pin the contents call to API version 2026-03-10
to clear the Sunset: 2028-03-10 header on the deprecated 2022-11-28
version. The only breaking change in 2026-03-10 (submodule type in
directory listings) doesn't affect us — fetchLatestSha is per-file
and the array branch already short-circuits.
Starred section used to intersect favorites with the paginated GitHub
repo list, so favorites past the first page only appeared after the user
scrolled. Derive RepoBase directly from PouchDB favorites and exclude
them from "all repos" by both id and name.
Stale FavoriteRepo docs with old GitHub IDs (e.g. from deleted or
recreated repos) surfaced as duplicates once the prefix scan started
returning every doc.
Expose a failures list alongside the existing failedNotes counter so each
failure carries kind/path/sha/message. Also catches throws from
buildNoteDocs and bulkUpdate that previously aborted the whole loop.
Replace the failure counter with a list of typed failures (fetch,
build, save, readme, unknown) carrying path, sha, message, and
affected doc ids so callers can surface diagnostics instead of just
a count.
Switch from /search/repositories (best-match order) to /user/repos
with sort=full_name so infinite scroll appends in A–Z order instead
of injecting new pages into earlier letters.
Fetch blobs with a concurrency of 8 instead of one at a time, batch
PouchDB writes via bulkUpdate, filter already-cached files up front,
and run the README fetch in parallel with the worker loop.
The home page reads README via getCachedMainReadme, which uses
Note-{owner}-{repo}-README, not the blob SHA. Cache-all only wrote
SHA-keyed entries, so the homepage README was empty offline.
A single null from queryFileContent silently exited cacheAllNotes,
leaving every later note uncached while the success toast still fired.
Skip the failing file, count failures, and surface them via errorMessage.
Before, every GitHub call awaited indefinitely with no AbortSignal,
so a "lie-fi" connection (technically online, effectively dead) left
FluxNote stuck on the skeleton loader and the freshness badge spinning
forever. Inject an 8s AbortSignal.timeout via octokit.hook.before
(20s override on the recursive tree fetch), classify failures in the
userRepo store as auth vs network, and surface a "Couldn't reach
GitHub" retry button when no cached content is available.
Cached GitHub responses resolved so fast that the spinner state was
overwritten before Vue could render it, so clicking the badge from
"Not checked" looked like nothing happened.
The exported SVG carries font-family="cmr7"/"cmsy7"/… attributes but
no @font-face, so standalone viewers fall back to system fonts. That
scatters TikZ glyphs (precomputed x positions assume Computer Modern
metrics) and turns cmsy7 minus signs into ¡ (custom symbol encoding).
Inline only the rules for font-families the SVG actually uses, and
await document.fonts.ready before rasterizing to PNG.
Attach SVG and PNG (×2) download buttons to every rendered SVG (TikZ,
Mermaid, …) once post-render finishes. Exports always use the original
colors with a white background baked in, regardless of theme.
useMarkdown.hook.ts imports types from shikiji-core, but it was only
present transitively via markdown-it-shikiji. pnpm's strict resolution
blocks importing undeclared transitives, breaking type-check.
Pinned to 0.10.2 to match the version markdown-it-shikiji@0.10.2 pulls
in. The shikiji line is deprecated upstream in favor of shiki; a real
migration is out of scope here.
pnpm resolves every package via a symlink into .pnpm/; preserveSymlinks
pinned resolution to those symlink paths, blocking the vue ->
@vue/runtime-dom -> @vue/runtime-core re-export chain and surfacing
"has no exported member" errors for Ref, toValue, computed, etc.
The obsidian-tikzjax bundle emits SVG referencing Computer Modern font
families like cmbx7 but ships the @font-face declarations in a separate
styles.css. Without it the browser substitutes a default font whose
glyph widths don't match TeX's, leaving visible gaps between each
kerned text run. Lazy-load the stylesheet alongside the engine on
first TikZ render so cache hits and misses both see correct fonts.
Four components duplicated the watch -> nextTick -> listenToClick -> runTikz
shape. Collapse to useMarkdownPostRender, which also accepts optional flags
for Mermaid, Shikiji and image hydration so StackedNote no longer needs its
own inline conditional chain.
Adds a markdown-it extractor for ```tikz blocks that emits a sanitized
placeholder, plus a runTikz() that lazy-loads the obsidian-tikzjax 0.5.2
bundle from jsdelivr on first encounter, sanitizes the produced SVG with
DOMPurify, and caches it in PouchDB keyed by sha256(source) so repeat
views are instant and offline-capable.
Align the repo manager with WelcomeWorld and PublicNoteView: editorial
top nav, serif hero, pastel favorite tiles, A-Z grouped list, skeleton
and credential-error states, and a name filter.
The 401 flag and cached repo list were module-level and only reset
after a 20-min stale window, so re-authenticating left the
"credentials are invalid or expired" message pinned on. Watch the
access token: reset state and refetch on change. Also await
saveCredentials before redirecting so refs are settled.
pnpm 11.x reads the per-package allowBuilds boolean map, not the
pnpm 10 onlyBuiltDependencies arrays. The array form is silently
ignored, so every build script falls through as 'ignored' and
strict CI mode fails. Confirmed by reproducing locally and by
inspecting what 'pnpm approve-builds --all' writes back.
The build-allow config lives in pnpm-workspace.yaml, but the deps
stage only copied package.json and pnpm-lock.yaml — so the
container saw no allowlist and pnpm install failed on ignored
build scripts.
Drop the explicit pnpm@latest prepare step and let corepack pick
up the pinned version from package.json on first invocation, so
the Docker build can't drift away from the local toolchain.
The allowBuilds map syntax only works in pnpm 11.x, but the
Dockerfile resolves pnpm@latest to a 10.x that doesn't recognize
it, so install fails on unapproved build scripts. Switch to the
onlyBuiltDependencies/ignoredBuiltDependencies arrays and pin
packageManager so CI and local stay in sync.
queryFileContent threw on octokit errors (stale SHA 404, expired token,
network blip) and the rejection bubbled up unhandled through pullLatest
and onBadgeClick, leaving the badge stuck on "Outdated" with no log or
toast. Wrap the octokit call, log on failure, clear the cached SHA so
the next click re-resolves it, and show an error toast.
Also fix a dead `if (!user || !repo) { null }` that did nothing.
Cache miss wrote null into store.readme before getMainReadme finished,
collapsing isLoading and surfacing the not-accessible UI mid-fetch.
Also branch that UI on auth state so signed-in users aren't told to
sign in when access fails.