diff --git a/appview/sitefeed/feed_test.go b/appview/sitefeed/feed_test.go index f6b197c77..416427c26 100644 --- a/appview/sitefeed/feed_test.go +++ b/appview/sitefeed/feed_test.go @@ -14,8 +14,8 @@ import ( "tangled.org/core/appview/db" "tangled.org/core/appview/models" "tangled.org/core/knotfeed" - "tangled.org/core/tapc" "tangled.org/core/log" + "tangled.org/core/tapc" cbg "github.com/whyrusleeping/cbor-gen" ) diff --git a/flake.nix b/flake.nix index 075b7ed84..082e2a84e 100644 --- a/flake.nix +++ b/flake.nix @@ -298,49 +298,14 @@ includes = ["*.go"]; }; + # web formats via pnpm lint (pinned prettier, svelte-aware); treefmt + # prettier would fight it on union types rustfmt = { command = pkgs.lib.getExe' fenix.packages.${system}.stable.rustfmt "rustfmt"; options = ["--edition" "2024"]; includes = ["*.rs"]; excludes = ["**/src/_lex/**" "**/src/gen/**"]; }; - - prettier = { - command = pkgs.writeShellScript "prettier-wrapper" '' - cd web - args=() - for arg in "$@"; do - if [[ "$arg" == web/* ]]; then - args+=("''${arg#web/}") - else - args+=("$arg") - fi - done - exec ${pkgs.lib.getExe pkgs.prettier} "''${args[@]}" - ''; - options = ["-w"]; - includes = [ - "web/**/*.cjs" - "web/**/*.css" - "web/**/*.html" - "web/**/*.js" - "web/**/*.json" - "web/**/*.json5" - "web/**/*.jsx" - "web/**/*.mdx" - "web/**/*.mjs" - "web/**/*.scss" - "web/**/*.ts" - "web/**/*.tsx" - "web/**/*.vue" - "web/**/*.yaml" - "web/**/*.yml" - ]; - excludes = [ - "web/static/**" - "web/src/lib/api/lexicons/**" - ]; - }; }; }; diff --git a/gitmirror/crates/gitmirror-xrpc/src/routes/git.rs b/gitmirror/crates/gitmirror-xrpc/src/routes/git.rs index 6d2651acc..8c8a7447c 100644 --- a/gitmirror/crates/gitmirror-xrpc/src/routes/git.rs +++ b/gitmirror/crates/gitmirror-xrpc/src/routes/git.rs @@ -11,9 +11,9 @@ use gix::revision::plumbing::Spec as RevSpec; use gix::revision::walk::Sorting; use jacquard_axum::{ExtractXrpc, XrpcResponse}; use jacquard_common::ToSmolStr; -use jacquard_common::types::string::Datetime; use jacquard_common::service_auth::ServiceAuthClaims; use jacquard_common::types::did::Did; +use jacquard_common::types::string::Datetime; use jacquard_identity::resolver::IdentityResolver as _; use lexicons::org_tangled::temp::git::delete_branch; use lexicons::sh_tangled; @@ -787,11 +787,12 @@ pub(crate) async fn delete_branch( let refname = head_ref(input.branch.as_str())?; let expected_old = { - let repo = state.layout.open(&input.repo).map_err(|e| { - XrpcError::RepoNotFound { + let repo = state + .layout + .open(&input.repo) + .map_err(|e| XrpcError::RepoNotFound { detail: e.to_string(), - } - })?; + })?; let reference = repo .try_find_reference(refname.as_ref().as_partial_name()) .map_err(|e| XrpcError::Internal(e.to_string()))? diff --git a/spindle/db/mill_state.go b/spindle/db/mill_state.go index 36a2ea322..6b79fda62 100644 --- a/spindle/db/mill_state.go +++ b/spindle/db/mill_state.go @@ -446,8 +446,8 @@ func ApplyEventBatchCtx[T any](ctx context.Context, d *DB, n *notifier.Notifier, defer tx.Rollback() batchTx := &EventBatchTx{ - tx: tx, - db: d, + tx: tx, + db: d, } v, err := fn(batchTx) if err != nil { diff --git a/spindle/xrpc/ci_pipeline_subscribe_logs.go b/spindle/xrpc/ci_pipeline_subscribe_logs.go index 23cb60ad8..0ad7765f6 100644 --- a/spindle/xrpc/ci_pipeline_subscribe_logs.go +++ b/spindle/xrpc/ci_pipeline_subscribe_logs.go @@ -135,7 +135,7 @@ func (x *Xrpc) handleSubscribeLogs(w http.ResponseWriter, r *http.Request, pipel wid := models.WorkflowId{ PipelineId: pipeline, - Name: wfName, + Name: wfName, } // check if finished, but poll database to know when it finishes diff --git a/web/package.json b/web/package.json index 3ed86d4c0..706657f9c 100644 --- a/web/package.json +++ b/web/package.json @@ -51,6 +51,8 @@ "prettier": "^3.9.5", "prettier-plugin-svelte": "^4.1.1", "prettier-plugin-tailwindcss": "^0.8.1", + "react": "^19.2.8", + "react-dom": "^19.2.8", "storybook": "^10.5.0", "svelte": "^5.56.9", "svelte-check": "^4.7.2", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index e21fda9ae..d3a7c7b5e 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + aria-query: 5.3.2 + patchedDependencies: '@pierre/diffs@1.4.1': b08596641b783a2c462c36e037f02db2505428aaa2f439c216330d5a09553f3f boneyard-js@1.9.0: e9bda6b0720bed34eefee605bd041784ac2849ae4d27120d9815663d342f694f @@ -166,6 +169,12 @@ importers: prettier-plugin-tailwindcss: specifier: ^0.8.1 version: 0.8.1(prettier-plugin-svelte@4.1.1(prettier@3.9.5)(svelte@5.56.9(@typescript-eslint/types@8.64.0)))(prettier@3.9.5) + react: + specifier: ^19.2.8 + version: 19.2.8 + react-dom: + specifier: ^19.2.8 + version: 19.2.8(react@19.2.8) storybook: specifier: ^10.5.0 version: 10.5.0(@types/react@19.2.18)(prettier@3.9.5)(react@19.2.8) @@ -2014,13 +2023,6 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - - aria-query@5.3.1: - resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} - engines: {node: '>= 0.4'} - aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} @@ -4889,7 +4891,7 @@ snapshots: '@babel/code-frame': 7.29.7 '@babel/runtime': 7.29.7 '@types/aria-query': 5.0.4 - aria-query: 5.3.0 + aria-query: 5.3.2 dom-accessibility-api: 0.5.16 lz-string: 1.5.0 picocolors: 1.1.1 @@ -5209,12 +5211,6 @@ snapshots: argparse@2.0.1: {} - aria-query@5.3.0: - dependencies: - dequal: 2.0.3 - - aria-query@5.3.1: {} - aria-query@5.3.2: {} assertion-error@2.0.1: {} @@ -6419,7 +6415,7 @@ snapshots: '@types/estree': 1.0.9 '@types/trusted-types': 2.0.7 acorn: 8.17.0 - aria-query: 5.3.1 + aria-query: 5.3.2 axobject-query: 4.1.0 clsx: 2.1.1 devalue: 5.8.1 diff --git a/web/pnpm-workspace.yaml b/web/pnpm-workspace.yaml index 27d375c68..864e85836 100644 --- a/web/pnpm-workspace.yaml +++ b/web/pnpm-workspace.yaml @@ -1,6 +1,10 @@ allowBuilds: esbuild: true workerd: true +overrides: + # @testing-library/dom pins 5.3.0, whose named exports the esm interop can't + # see; 5.3.2 assigns them where the cjs lexer finds them + aria-query: 5.3.2 patchedDependencies: "@pierre/diffs@1.4.1": patches/@pierre__diffs@1.4.1.patch boneyard-js@1.9.0: patches/boneyard-js@1.9.0.patch diff --git a/web/src/app.html b/web/src/app.html index c86f1febe..02b064f09 100644 --- a/web/src/app.html +++ b/web/src/app.html @@ -26,18 +26,18 @@ %sveltekit.head% diff --git a/web/src/hooks.server.ts b/web/src/hooks.server.ts index 954ae8205..c75c2845e 100644 --- a/web/src/hooks.server.ts +++ b/web/src/hooks.server.ts @@ -19,7 +19,9 @@ export const handle: Handle = async ({ event, resolve }) => { upstream.hostname = "sitemap.internal"; return sitemap.fetch(new Request(upstream, event.request)); } - console.warn("[hooks.server] SITEMAP service binding not configured; sitemap request unhandled"); + console.warn( + "[hooks.server] SITEMAP service binding not configured; sitemap request unhandled" + ); } return resolve(event, { diff --git a/web/src/lib/components/profile/ProfileActivity.stories.svelte b/web/src/lib/components/profile/ProfileActivity.stories.svelte index 8b7c73651..614765d0e 100644 --- a/web/src/lib/components/profile/ProfileActivity.stories.svelte +++ b/web/src/lib/components/profile/ProfileActivity.stories.svelte @@ -1,8 +1,8 @@ @@ -62,7 +60,8 @@ {#if noindex} {/if} - {#each schemas as schema} + {#each schemas as schema (schema)} + {@html ` {#if !isCustomOgChildRoute} - + {/if} {#if repoMeta} diff --git a/web/src/routes/[handle]/[repo]/commit/[ref]/+page.svelte b/web/src/routes/[handle]/[repo]/commit/[ref]/+page.svelte index 028744740..276c84708 100644 --- a/web/src/routes/[handle]/[repo]/commit/[ref]/+page.svelte +++ b/web/src/routes/[handle]/[repo]/commit/[ref]/+page.svelte @@ -41,9 +41,7 @@ }); const resolvedRepo = $derived(asyncRepo ?? synchronousRepo); - const repoName = $derived( - resolvedRepo?.name ?? decodeURIComponent(page.params.repo ?? "") - ); + const repoName = $derived(resolvedRepo?.name ?? decodeURIComponent(page.params.repo ?? "")); const commitSummary = $derived( asyncCommitPage?.commit?.subject || `Commit ${data.ref.slice(0, 8)}` ); @@ -51,7 +49,7 @@ const authorLabel = $derived( asyncAuthor?.handle ? `@${asyncAuthor.handle}` - : (asyncCommitPage?.commit?.authorName || "Unknown author") + : asyncCommitPage?.commit?.authorName || "Unknown author" ); const commitBodyText = $derived(asyncCommitPage?.commit?.body?.trim()); const commitDesc = $derived( diff --git a/web/src/routes/[handle]/[repo]/fork/+page.svelte b/web/src/routes/[handle]/[repo]/fork/+page.svelte index b7731475d..c5b2c2b3a 100644 --- a/web/src/routes/[handle]/[repo]/fork/+page.svelte +++ b/web/src/routes/[handle]/[repo]/fork/+page.svelte @@ -9,7 +9,12 @@ let { data } = $props(); - + {#snippet skeleton()} diff --git a/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.svelte b/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.svelte index de703767a..c08aec805 100644 --- a/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.svelte +++ b/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.svelte @@ -11,7 +11,6 @@ import Pending from "$lib/components/ui/Pending.svelte"; import Meta from "$lib/components/seo/Meta.svelte"; import { issueCard } from "$lib/seo/og"; - import { avatarUrl } from "$lib/avatar"; let { data }: { data: PageData } = $props(); @@ -33,13 +32,9 @@ }); const resolvedRepo = $derived(asyncRepo ?? synchronousRepo); - const repoName = $derived( - resolvedRepo?.name ?? decodeURIComponent(page.params.repo ?? "") - ); - const currentResult = $derived(asyncPageResult ?? (data as any).initialResult); - const issueData = $derived( - currentResult?.kind === "ok" ? currentResult.issue : null - ); + const repoName = $derived(resolvedRepo?.name ?? decodeURIComponent(page.params.repo ?? "")); + const currentResult = $derived(asyncPageResult ?? data.initialResult); + const issueData = $derived(currentResult?.kind === "ok" ? currentResult.issue : null); const issueTitle = $derived(issueData?.title || "Issue"); const pageTitle = $derived(`${issueTitle} · ${repoName} · Tangled`); const issueDesc = $derived( @@ -49,7 +44,21 @@ ); - + {#snippet skeleton()} diff --git a/web/src/routes/[handle]/[repo]/issues/new/+page.svelte b/web/src/routes/[handle]/[repo]/issues/new/+page.svelte index 60cda02d6..bfa5f4e67 100644 --- a/web/src/routes/[handle]/[repo]/issues/new/+page.svelte +++ b/web/src/routes/[handle]/[repo]/issues/new/+page.svelte @@ -32,7 +32,12 @@ }; - +

Create a new issue

diff --git a/web/src/routes/[handle]/[repo]/pulls/[aturi]/[version]/[[range]]/PullViewPage.svelte b/web/src/routes/[handle]/[repo]/pulls/[aturi]/[version]/[[range]]/PullViewPage.svelte index 189c0cd07..d24a96b41 100644 --- a/web/src/routes/[handle]/[repo]/pulls/[aturi]/[version]/[[range]]/PullViewPage.svelte +++ b/web/src/routes/[handle]/[repo]/pulls/[aturi]/[version]/[[range]]/PullViewPage.svelte @@ -2,7 +2,6 @@ import { browser } from "$app/environment"; import Meta from "$lib/components/seo/Meta.svelte"; import { pullCard } from "$lib/seo/og"; - import { avatarUrl } from "$lib/avatar"; import { goto, replaceState } from "$app/navigation"; import { page } from "$app/state"; import { resolve } from "$app/paths"; @@ -548,7 +547,12 @@ ); - +
diff --git a/web/src/routes/[handle]/[repo]/pulls/new/+page.svelte b/web/src/routes/[handle]/[repo]/pulls/new/+page.svelte index 4c843f163..fca1016f3 100644 --- a/web/src/routes/[handle]/[repo]/pulls/new/+page.svelte +++ b/web/src/routes/[handle]/[repo]/pulls/new/+page.svelte @@ -19,7 +19,12 @@ }); - + diff --git a/web/src/routes/[handle]/[repo]/tree/[ref]/[...path]/+page.svelte b/web/src/routes/[handle]/[repo]/tree/[ref]/[...path]/+page.svelte index 5faea38fe..9cbbd3e36 100644 --- a/web/src/routes/[handle]/[repo]/tree/[ref]/[...path]/+page.svelte +++ b/web/src/routes/[handle]/[repo]/tree/[ref]/[...path]/+page.svelte @@ -28,9 +28,7 @@ }); const resolvedRepo = $derived(asyncRepo ?? synchronousRepo); - const repoName = $derived( - resolvedRepo?.name ?? decodeURIComponent(page.params.repo ?? "") - ); + const repoName = $derived(resolvedRepo?.name ?? decodeURIComponent(page.params.repo ?? "")); const filePath = $derived(data.path); const treeTitle = $derived(`${filePath} · ${repoName} · Tangled`); const treeDesc = $derived(`Viewing ${filePath} in ${repoName} on Tangled.`); diff --git a/web/src/routes/_internal/indexnow/+server.ts b/web/src/routes/_internal/indexnow/+server.ts index 89b2a6bb3..947eddc09 100644 --- a/web/src/routes/_internal/indexnow/+server.ts +++ b/web/src/routes/_internal/indexnow/+server.ts @@ -22,7 +22,7 @@ export const POST: RequestHandler = async (event) => { return json({ error: "unauthorized" }, { status: 401 }); } - let body: { urls?: string[] | string } = {}; + let body: { urls?: string[] | string }; try { body = await event.request.json(); } catch { @@ -47,7 +47,9 @@ export const POST: RequestHandler = async (event) => { const parsed = new URL(trimmed, allowedOrigin); if (parsed.origin !== allowedOrigin) { return json( - { error: `invalid url domain: ${parsed.origin}. Only ${allowedOrigin} is permitted.` }, + { + error: `invalid url domain: ${parsed.origin}. Only ${allowedOrigin} is permitted.` + }, { status: 400 } ); } diff --git a/web/vite.config.ts b/web/vite.config.ts index 5970eb02a..57a7c2b2c 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -86,6 +86,12 @@ export default defineConfig({ configDir: path.join(dirname, ".storybook") }) ], + // vite only crawls kit routes here, so undeclared story deps would + // optimize mid-run and wedge chromium; sanitize-html is cjs + optimizeDeps: { + noDiscovery: true, + include: ["storybook/test", "sanitize-html"] + }, test: { name: "storybook", browser: { diff --git a/web/wrangler.dev.jsonc b/web/wrangler.dev.jsonc index 97fc67bc6..f263a8c0a 100644 --- a/web/wrangler.dev.jsonc +++ b/web/wrangler.dev.jsonc @@ -4,9 +4,7 @@ "main": ".svelte-kit/cloudflare/_worker.js", "workers_dev": false, "compatibility_date": "2026-07-30", - "compatibility_flags": [ - "nodejs_compat" - ], + "compatibility_flags": ["nodejs_compat"], "placement": { "region": "aws:eu-central-1" }, @@ -16,9 +14,7 @@ "assets": { "binding": "ASSETS", "directory": ".svelte-kit/cloudflare", - "run_worker_first": [ - "/oauth-client-metadata.json" - ] + "run_worker_first": ["/oauth-client-metadata.json"] }, "services": [ {