@silicajs/next 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,7 @@ import { cacheLife, cacheTag } from "next/cache";
4
4
  import { notFound } from "next/navigation";
5
5
  import {
6
6
  getMetaDescription,
7
+ getResolvedPageProperties,
7
8
  renderMarkdown,
8
9
  renderMarkdownHtml
9
10
  } from "@silicajs/core/runtime";
@@ -120,10 +121,8 @@ async function VaultContent({
120
121
  }
121
122
  });
122
123
  const raw = await fs.readFile(entry.file, "utf8");
123
- const rendered = await renderMarkdown(
124
- raw,
125
- renderContext(slug, entry.sourcePath)
126
- );
124
+ const pageRenderContext = renderContext(slug, entry.sourcePath);
125
+ const rendered = await renderMarkdown(raw, pageRenderContext);
127
126
  return /* @__PURE__ */ jsx(
128
127
  theme.PageRenderer,
129
128
  {
@@ -136,6 +135,10 @@ async function VaultContent({
136
135
  description: entry.description,
137
136
  content: rendered.content,
138
137
  frontmatter: entry.frontmatter,
138
+ pageProperties: getResolvedPageProperties(
139
+ entry.frontmatter,
140
+ pageRenderContext
141
+ ),
139
142
  toc: rendered.toc,
140
143
  tags: entry.tags,
141
144
  entry
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/routes/page.tsx"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport type { AnchorHTMLAttributes } from \"react\";\nimport { cacheLife, cacheTag } from \"next/cache\";\nimport { notFound } from \"next/navigation\";\nimport {\n getMetaDescription,\n renderMarkdown,\n renderMarkdownHtml,\n type RenderContext,\n} from \"@silicajs/core/runtime\";\nimport { SilicaLink } from \"@silicajs/components/routing\";\nimport {\n getBacklinks,\n getBreadcrumbs,\n getPage,\n getPageRuntimeData,\n getPrerenderSlugs,\n getRenderKey,\n resolveAssetFromDb,\n resolveWikiLinkFromDb,\n normalizeRouteSlug,\n} from \"../server-data.js\";\nimport type { SilicaTheme } from \"@silicajs/core/theme\";\n\nfunction MarkdownLink({\n href,\n ...props\n}: AnchorHTMLAttributes<HTMLAnchorElement>) {\n if (href && href.startsWith(\"/\") && !href.startsWith(\"/silica/\")) {\n return <SilicaLink href={href} {...props} />;\n }\n\n return <a href={href} {...props} />;\n}\n\nexport async function generateStaticParams() {\n const prerenderSlugs = getPrerenderSlugs();\n const slugs = prerenderSlugs.length\n ? prerenderSlugs\n : [\"__silica_prerender_placeholder__\"];\n return slugs.map((slug) => ({\n slug: slug === \"index\" ? [] : slug.split(\"/\"),\n }));\n}\n\nexport async function generateMetadata({ params }: PageProps) {\n const resolvedParams = await params;\n const slug = normalizeRouteSlug(resolvedParams?.slug);\n const renderKey = getRenderKey(slug);\n const entry = await getPageMetadata(\n slug,\n renderKey.renderHash,\n renderKey.renderEnvironmentHash,\n );\n if (!entry) return {};\n return {\n title: entry.title,\n description: getMetaDescription(entry),\n };\n}\n\nasync function getPageMetadata(\n slug: string,\n renderHash: string,\n renderEnvironmentHash: string,\n) {\n \"use cache\";\n cacheLife(\"max\");\n cacheTag(\n `environment:${renderEnvironmentHash}`,\n `page:${slug}`,\n `render:${renderHash}`,\n );\n return getPage(slug);\n}\n\nexport type PageProps = {\n params: Promise<{ slug?: string[] }> | { slug?: string[] };\n};\n\nexport async function VaultContent({\n slug,\n renderHash,\n renderEnvironmentHash,\n theme,\n}: {\n slug: string;\n renderHash: string;\n renderEnvironmentHash: string;\n theme: SilicaTheme;\n}) {\n \"use cache\";\n cacheLife(\"max\");\n const data = getPageRuntimeData(slug);\n if (!data) notFound();\n const { entry, config } = data;\n cacheTag(\n `environment:${renderEnvironmentHash}`,\n `page:${slug}`,\n `render:${renderHash}`,\n );\n\n const renderContext = (\n currentSlug: string,\n currentSourcePath: string,\n embedDepth = 0,\n ): RenderContext => ({\n slug: currentSlug,\n sourcePath: currentSourcePath,\n resolveWikiLink: (_currentSlug, target) =>\n resolveWikiLinkFromDb(\n currentSlug,\n target,\n config.wikilinks.strategy,\n config.ordering,\n ),\n resolveAsset: (_currentSourcePath, target) =>\n resolveAssetFromDb(\n currentSourcePath,\n target,\n config.wikilinks.strategy,\n config.ordering,\n ),\n assetBaseUrl: \"/silica\",\n wikilinkStrategy: config.wikilinks.strategy,\n tags: config.tags,\n ordering: config.ordering,\n embedDepth,\n maxEmbedDepth: 3,\n components: {\n ...theme.components,\n a: MarkdownLink,\n },\n resolveEmbed: async (target) => {\n const resolved = resolveWikiLinkFromDb(\n currentSlug,\n target.path || currentSlug,\n config.wikilinks.strategy,\n config.ordering,\n );\n if (!resolved || embedDepth >= 3) return;\n const embeddedEntry = getPage(resolved);\n if (!embeddedEntry) return;\n const embeddedRaw = await fs.readFile(embeddedEntry.file, \"utf8\");\n const scopedRaw = scopeEmbedMarkdown(embeddedRaw, target);\n return renderMarkdownHtml(\n scopedRaw,\n renderContext(resolved, embeddedEntry.sourcePath, embedDepth + 1),\n );\n },\n });\n\n const raw = await fs.readFile(entry.file, \"utf8\");\n const rendered = await renderMarkdown(\n raw,\n renderContext(slug, entry.sourcePath),\n );\n\n return (\n <theme.PageRenderer\n config={config}\n breadcrumbs={getBreadcrumbs(slug)}\n backlinks={getBacklinks(slug)}\n page={{\n slug,\n title: entry.title,\n description: entry.description,\n content: rendered.content,\n frontmatter: entry.frontmatter,\n toc: rendered.toc,\n tags: entry.tags,\n entry,\n }}\n />\n );\n}\n\nfunction scopeEmbedMarkdown(\n raw: string,\n target: Parameters<NonNullable<RenderContext[\"resolveEmbed\"]>>[0],\n): string {\n if (target.blockId) return extractBlock(raw, target.blockId) ?? raw;\n if (target.heading) return extractHeadingSection(raw, target.heading) ?? raw;\n return raw;\n}\n\nfunction extractHeadingSection(\n raw: string,\n heading: string,\n): string | undefined {\n const lines = raw.split(/\\r?\\n/);\n const expected = normalizeHeading(heading);\n const start = lines.findIndex((line) => {\n const parsed = parseHeading(line);\n return parsed ? normalizeHeading(parsed.text) === expected : false;\n });\n if (start === -1) return;\n\n const startHeading = parseHeading(lines[start] ?? \"\");\n if (!startHeading) return;\n let end = lines.length;\n for (let index = start + 1; index < lines.length; index += 1) {\n const nextHeading = parseHeading(lines[index] ?? \"\");\n if (nextHeading && nextHeading.depth <= startHeading.depth) {\n end = index;\n break;\n }\n }\n\n return lines.slice(start, end).join(\"\\n\").trim();\n}\n\nfunction extractBlock(raw: string, blockId: string): string | undefined {\n const lines = raw.split(/\\r?\\n/);\n const blockIdPattern = new RegExp(\n `(^|\\\\s)\\\\^${escapeRegExp(blockId)}(?=\\\\s|$)`,\n );\n const matchIndex = lines.findIndex((line) => blockIdPattern.test(line));\n if (matchIndex === -1) return;\n\n let start = matchIndex;\n while (start > 0 && lines[start - 1]?.trim()) start -= 1;\n\n let end = matchIndex + 1;\n while (end < lines.length && lines[end]?.trim()) end += 1;\n\n return lines.slice(start, end).join(\"\\n\").replace(blockIdPattern, \"\").trim();\n}\n\nfunction parseHeading(\n line: string,\n): { depth: number; text: string } | undefined {\n const match = /^(#{1,6})\\s+(.+?)\\s*#*\\s*$/.exec(line);\n if (!match) return;\n return {\n depth: match[1]!.length,\n text: match[2]!,\n };\n}\n\nfunction normalizeHeading(value: string): string {\n return value.trim().replace(/\\s+/g, \" \").toLowerCase();\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/routes/page.tsx"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport type { AnchorHTMLAttributes } from \"react\";\nimport { cacheLife, cacheTag } from \"next/cache\";\nimport { notFound } from \"next/navigation\";\nimport {\n getMetaDescription,\n getResolvedPageProperties,\n renderMarkdown,\n renderMarkdownHtml,\n type RenderContext,\n} from \"@silicajs/core/runtime\";\nimport { SilicaLink } from \"@silicajs/components/routing\";\nimport {\n getBacklinks,\n getBreadcrumbs,\n getPage,\n getPageRuntimeData,\n getPrerenderSlugs,\n getRenderKey,\n resolveAssetFromDb,\n resolveWikiLinkFromDb,\n normalizeRouteSlug,\n} from \"../server-data.js\";\nimport type { SilicaTheme } from \"@silicajs/core/theme\";\n\nfunction MarkdownLink({\n href,\n ...props\n}: AnchorHTMLAttributes<HTMLAnchorElement>) {\n if (href && href.startsWith(\"/\") && !href.startsWith(\"/silica/\")) {\n return <SilicaLink href={href} {...props} />;\n }\n\n return <a href={href} {...props} />;\n}\n\nexport async function generateStaticParams() {\n const prerenderSlugs = getPrerenderSlugs();\n const slugs = prerenderSlugs.length\n ? prerenderSlugs\n : [\"__silica_prerender_placeholder__\"];\n return slugs.map((slug) => ({\n slug: slug === \"index\" ? [] : slug.split(\"/\"),\n }));\n}\n\nexport async function generateMetadata({ params }: PageProps) {\n const resolvedParams = await params;\n const slug = normalizeRouteSlug(resolvedParams?.slug);\n const renderKey = getRenderKey(slug);\n const entry = await getPageMetadata(\n slug,\n renderKey.renderHash,\n renderKey.renderEnvironmentHash,\n );\n if (!entry) return {};\n return {\n title: entry.title,\n description: getMetaDescription(entry),\n };\n}\n\nasync function getPageMetadata(\n slug: string,\n renderHash: string,\n renderEnvironmentHash: string,\n) {\n \"use cache\";\n cacheLife(\"max\");\n cacheTag(\n `environment:${renderEnvironmentHash}`,\n `page:${slug}`,\n `render:${renderHash}`,\n );\n return getPage(slug);\n}\n\nexport type PageProps = {\n params: Promise<{ slug?: string[] }> | { slug?: string[] };\n};\n\nexport async function VaultContent({\n slug,\n renderHash,\n renderEnvironmentHash,\n theme,\n}: {\n slug: string;\n renderHash: string;\n renderEnvironmentHash: string;\n theme: SilicaTheme;\n}) {\n \"use cache\";\n cacheLife(\"max\");\n const data = getPageRuntimeData(slug);\n if (!data) notFound();\n const { entry, config } = data;\n cacheTag(\n `environment:${renderEnvironmentHash}`,\n `page:${slug}`,\n `render:${renderHash}`,\n );\n\n const renderContext = (\n currentSlug: string,\n currentSourcePath: string,\n embedDepth = 0,\n ): RenderContext => ({\n slug: currentSlug,\n sourcePath: currentSourcePath,\n resolveWikiLink: (_currentSlug, target) =>\n resolveWikiLinkFromDb(\n currentSlug,\n target,\n config.wikilinks.strategy,\n config.ordering,\n ),\n resolveAsset: (_currentSourcePath, target) =>\n resolveAssetFromDb(\n currentSourcePath,\n target,\n config.wikilinks.strategy,\n config.ordering,\n ),\n assetBaseUrl: \"/silica\",\n wikilinkStrategy: config.wikilinks.strategy,\n tags: config.tags,\n ordering: config.ordering,\n embedDepth,\n maxEmbedDepth: 3,\n components: {\n ...theme.components,\n a: MarkdownLink,\n },\n resolveEmbed: async (target) => {\n const resolved = resolveWikiLinkFromDb(\n currentSlug,\n target.path || currentSlug,\n config.wikilinks.strategy,\n config.ordering,\n );\n if (!resolved || embedDepth >= 3) return;\n const embeddedEntry = getPage(resolved);\n if (!embeddedEntry) return;\n const embeddedRaw = await fs.readFile(embeddedEntry.file, \"utf8\");\n const scopedRaw = scopeEmbedMarkdown(embeddedRaw, target);\n return renderMarkdownHtml(\n scopedRaw,\n renderContext(resolved, embeddedEntry.sourcePath, embedDepth + 1),\n );\n },\n });\n\n const raw = await fs.readFile(entry.file, \"utf8\");\n const pageRenderContext = renderContext(slug, entry.sourcePath);\n const rendered = await renderMarkdown(raw, pageRenderContext);\n\n return (\n <theme.PageRenderer\n config={config}\n breadcrumbs={getBreadcrumbs(slug)}\n backlinks={getBacklinks(slug)}\n page={{\n slug,\n title: entry.title,\n description: entry.description,\n content: rendered.content,\n frontmatter: entry.frontmatter,\n pageProperties: getResolvedPageProperties(\n entry.frontmatter,\n pageRenderContext,\n ),\n toc: rendered.toc,\n tags: entry.tags,\n entry,\n }}\n />\n );\n}\n\nfunction scopeEmbedMarkdown(\n raw: string,\n target: Parameters<NonNullable<RenderContext[\"resolveEmbed\"]>>[0],\n): string {\n if (target.blockId) return extractBlock(raw, target.blockId) ?? raw;\n if (target.heading) return extractHeadingSection(raw, target.heading) ?? raw;\n return raw;\n}\n\nfunction extractHeadingSection(\n raw: string,\n heading: string,\n): string | undefined {\n const lines = raw.split(/\\r?\\n/);\n const expected = normalizeHeading(heading);\n const start = lines.findIndex((line) => {\n const parsed = parseHeading(line);\n return parsed ? normalizeHeading(parsed.text) === expected : false;\n });\n if (start === -1) return;\n\n const startHeading = parseHeading(lines[start] ?? \"\");\n if (!startHeading) return;\n let end = lines.length;\n for (let index = start + 1; index < lines.length; index += 1) {\n const nextHeading = parseHeading(lines[index] ?? \"\");\n if (nextHeading && nextHeading.depth <= startHeading.depth) {\n end = index;\n break;\n }\n }\n\n return lines.slice(start, end).join(\"\\n\").trim();\n}\n\nfunction extractBlock(raw: string, blockId: string): string | undefined {\n const lines = raw.split(/\\r?\\n/);\n const blockIdPattern = new RegExp(\n `(^|\\\\s)\\\\^${escapeRegExp(blockId)}(?=\\\\s|$)`,\n );\n const matchIndex = lines.findIndex((line) => blockIdPattern.test(line));\n if (matchIndex === -1) return;\n\n let start = matchIndex;\n while (start > 0 && lines[start - 1]?.trim()) start -= 1;\n\n let end = matchIndex + 1;\n while (end < lines.length && lines[end]?.trim()) end += 1;\n\n return lines.slice(start, end).join(\"\\n\").replace(blockIdPattern, \"\").trim();\n}\n\nfunction parseHeading(\n line: string,\n): { depth: number; text: string } | undefined {\n const match = /^(#{1,6})\\s+(.+?)\\s*#*\\s*$/.exec(line);\n if (!match) return;\n return {\n depth: match[1]!.length,\n text: match[2]!,\n };\n}\n\nfunction normalizeHeading(value: string): string {\n return value.trim().replace(/\\s+/g, \" \").toLowerCase();\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n"],"mappings":"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","names":[]}
@@ -170,7 +170,11 @@ function resolveWikiLinkFromDb(currentSlug, target, strategy, ordering) {
170
170
  const resolved = lookupAlias(db, "absolute", relative);
171
171
  if (resolved) return resolved;
172
172
  }
173
- return lookupAlias(db, "absolute", normalizedTarget) ?? lookupAlias(db, "absolute", `${normalizedTarget}/index`) ?? lookupAlias(db, "shortest", normalizedTarget.split("/").at(-1) ?? "");
173
+ return lookupAlias(db, "absolute", normalizedTarget) ?? lookupAlias(db, "absolute", `${normalizedTarget}/index`) ?? lookupClosestAlias(
174
+ db,
175
+ currentSlug,
176
+ normalizedTarget.split("/").at(-1) ?? ""
177
+ );
174
178
  }
175
179
  function resolveAssetFromDb(currentSourcePath, target, strategy, ordering) {
176
180
  const assetOptions = ordering ?? getConfig().ordering;
@@ -246,6 +250,21 @@ function lookupAlias(db, strategy, alias) {
246
250
  ).all(strategy, alias);
247
251
  return row.length === 1 ? row[0]?.slug : void 0;
248
252
  }
253
+ function lookupClosestAlias(db, currentSlug, alias) {
254
+ const rows = db.prepare(
255
+ `
256
+ SELECT slug
257
+ FROM slug_aliases
258
+ WHERE strategy_key = 'shortest'
259
+ AND alias = ?
260
+ ORDER BY slug
261
+ `
262
+ ).all(alias);
263
+ return closestWikiLinkCandidate(
264
+ currentSlug,
265
+ rows.map((row) => row.slug)
266
+ );
267
+ }
249
268
  function lookupAssetAlias(db, strategy, alias) {
250
269
  const row = db.prepare(
251
270
  `
@@ -259,6 +278,41 @@ function lookupAssetAlias(db, strategy, alias) {
259
278
  ).all(strategy, alias);
260
279
  return row.length === 1 ? row[0]?.asset_path : void 0;
261
280
  }
281
+ function closestWikiLinkCandidate(currentSlug, candidates) {
282
+ if (candidates.length === 0) return void 0;
283
+ const currentDirectory = normalizeSlug(currentSlug, {
284
+ numericPrefixes: false
285
+ }).split("/").slice(0, -1);
286
+ const [bestCandidate] = [...candidates].sort((left, right) => {
287
+ const leftScore = wikiLinkCandidateScore(currentDirectory, left);
288
+ const rightScore = wikiLinkCandidateScore(currentDirectory, right);
289
+ return rightScore.sharedPrefixLength - leftScore.sharedPrefixLength || leftScore.depth - rightScore.depth || compareSlugs(left, right);
290
+ });
291
+ return bestCandidate;
292
+ }
293
+ function wikiLinkCandidateScore(currentDirectory, slug) {
294
+ const simplified = slug === "index" ? "" : slug.replace(/\/index$/, "");
295
+ const segments = simplified ? simplified.split("/") : [];
296
+ return {
297
+ sharedPrefixLength: sharedPrefixLength(
298
+ currentDirectory,
299
+ segments.slice(0, -1)
300
+ ),
301
+ depth: segments.length
302
+ };
303
+ }
304
+ function sharedPrefixLength(left, right) {
305
+ let length = 0;
306
+ while (left[length] !== void 0 && left[length] === right[length]) {
307
+ length += 1;
308
+ }
309
+ return length;
310
+ }
311
+ function compareSlugs(left, right) {
312
+ if (left < right) return -1;
313
+ if (left > right) return 1;
314
+ return 0;
315
+ }
262
316
  function isExplicitRelativeAssetReference(value) {
263
317
  const withoutSuffix = value.split(/[?#]/)[0] ?? "";
264
318
  const normalized = withoutSuffix.replace(/\\/g, "/").replace(/^\/+/, "").replace(/\/+$/, "");
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server-data.ts"],"sourcesContent":["import path from \"node:path\";\nimport fs from \"node:fs\";\nimport Database from \"better-sqlite3\";\nimport type { LoadedSearchIndex } from \"@silicajs/search\";\nimport type {\n Navigation,\n ManifestEntry,\n RenderCacheState,\n ResolvedSilicaConfig,\n} from \"@silicajs/core/runtime\";\nimport {\n asFullSlug,\n normalizeAssetReference,\n normalizeSlug,\n resolveRelativeAsset,\n resolveRelative,\n slugToHref,\n} from \"@silicajs/core/runtime\";\n\nconst VAULT_DATABASE_FILENAME = \"vault.db\";\n\nexport type LoadedVaultDb = {\n databasePath: string;\n generatedAt: string;\n renderEnvironmentHash: string;\n config: ResolvedSilicaConfig;\n cacheState: RenderCacheState;\n mtimeMs: number;\n db: Database.Database;\n close(): void;\n};\n\nexport type VaultPageData = {\n cacheState: RenderCacheState;\n config: ResolvedSilicaConfig;\n entry: ManifestEntry;\n};\n\ntype MetadataRows = {\n generatedAt: string;\n renderEnvironmentHash: string;\n config: ResolvedSilicaConfig;\n cacheState: RenderCacheState;\n};\n\ntype NoteRow = {\n slug: string;\n file: string;\n source_path: string;\n title: string;\n menu_label: string;\n description: string | null;\n generated_description: string | null;\n frontmatter_json: string;\n tags_json: string;\n created: string | null;\n modified: string | null;\n sort_key: string | null;\n listed: 0 | 1;\n content_hash: string;\n render_hash: string;\n prerender: 0 | 1;\n};\n\ntype NavigationRow = {\n slug: string;\n title: string;\n sort_key: string | null;\n};\n\ntype BacklinkRow = {\n slug: string;\n title: string;\n};\n\nlet loadedVaultDb: LoadedVaultDb | undefined;\n\nexport function getProjectRoot(): string {\n const projectRoot = process.env.SILICA_PROJECT_ROOT;\n if (!projectRoot) {\n throw new Error(\"SILICA_PROJECT_ROOT must be set by the Silica CLI.\");\n }\n\n return projectRoot;\n}\n\nexport function getSilicaRoot(): string {\n return path.join(getProjectRoot(), \".silica\");\n}\n\nexport function getVaultDatabasePath(): string {\n return path.join(getSilicaRoot(), VAULT_DATABASE_FILENAME);\n}\n\nexport function loadVaultDb(): LoadedVaultDb {\n const databasePath = getVaultDatabasePath();\n const stat = fs.statSync(databasePath);\n if (\n loadedVaultDb?.databasePath === databasePath &&\n loadedVaultDb.mtimeMs === stat.mtimeMs\n ) {\n return loadedVaultDb;\n }\n\n loadedVaultDb?.close();\n\n const db = new Database(databasePath, {\n fileMustExist: true,\n readonly: true,\n });\n db.pragma(\"query_only = ON\");\n const metadata = readMetadata(db);\n loadedVaultDb = {\n databasePath,\n generatedAt: metadata.generatedAt,\n renderEnvironmentHash: metadata.renderEnvironmentHash,\n config: metadata.config,\n cacheState: metadata.cacheState,\n mtimeMs: stat.mtimeMs,\n db,\n close: () => {\n db.close();\n if (loadedVaultDb?.db === db) loadedVaultDb = undefined;\n },\n };\n return loadedVaultDb;\n}\n\nexport function getPage(slug: string): ManifestEntry | undefined {\n const row = loadVaultDb()\n .db.prepare(\"SELECT * FROM notes WHERE slug = ?\")\n .get(slug) as NoteRow | undefined;\n return row ? noteRowToEntry(row) : undefined;\n}\n\nexport function getPageRuntimeData(slug: string): VaultPageData | undefined {\n const entry = getPage(slug);\n if (!entry) return undefined;\n return {\n entry,\n config: getConfig(),\n cacheState: getCacheState(),\n };\n}\n\nexport function getRenderKey(slug: string): {\n renderHash: string;\n renderEnvironmentHash: string;\n} {\n const loaded = loadVaultDb();\n const row = loaded.db\n .prepare(\"SELECT render_hash FROM notes WHERE slug = ?\")\n .get(slug) as { render_hash: string } | undefined;\n return {\n renderHash: row?.render_hash ?? \"missing\",\n renderEnvironmentHash: loaded.renderEnvironmentHash,\n };\n}\n\nexport function loadRenderEnvironmentHash(): string {\n return loadVaultDb().renderEnvironmentHash;\n}\n\nexport function getPrerenderSlugs(): string[] {\n return loadVaultDb()\n .db.prepare(\n \"SELECT slug FROM notes WHERE prerender = 1 ORDER BY COALESCE(sort_key, slug), slug\",\n )\n .all()\n .map((row) => (row as { slug: string }).slug);\n}\n\nexport function getAllSlugs(): string[] {\n return loadVaultDb()\n .db.prepare(\"SELECT slug FROM notes ORDER BY slug\")\n .all()\n .map((row) => (row as { slug: string }).slug);\n}\n\nexport function getNavigation(): Navigation {\n const entries = loadVaultDb()\n .db.prepare(\n `\n SELECT slug, menu_label AS title, sort_key\n FROM notes\n WHERE listed = 1\n ORDER BY COALESCE(sort_key, slug), slug\n `,\n )\n .all() as NavigationRow[];\n return {\n version: 1,\n entries: entries.map((entry) => ({\n slug: entry.slug,\n title: entry.title,\n sortKey: entry.sort_key ?? undefined,\n })),\n };\n}\n\nexport function getBacklinks(slug: string): BacklinkRow[] {\n return loadVaultDb()\n .db.prepare(\n `\n SELECT n.slug, n.title\n FROM links l\n JOIN notes n ON n.slug = l.source_slug\n WHERE l.target_slug = ?\n AND l.kind = 'link'\n ORDER BY n.title COLLATE NOCASE ASC, n.slug\n `,\n )\n .all(slug) as BacklinkRow[];\n}\n\nexport function getConfig(): ResolvedSilicaConfig {\n return loadVaultDb().config;\n}\n\nexport function getCacheState(): RenderCacheState {\n return loadVaultDb().cacheState;\n}\n\nexport function getTagSlugs(): string[] {\n return loadVaultDb()\n .db.prepare(\"SELECT DISTINCT tag FROM note_tags ORDER BY tag\")\n .all()\n .map((row) => (row as { tag: string }).tag);\n}\n\nexport function getEntriesForTag(tag: string): ManifestEntry[] {\n return loadVaultDb()\n .db.prepare(\n `\n SELECT n.*\n FROM notes n\n WHERE n.listed = 1\n AND EXISTS (\n SELECT 1\n FROM note_tags nt\n WHERE nt.slug = n.slug\n AND nt.tag = ?\n )\n ORDER BY n.title COLLATE NOCASE ASC, n.slug\n `,\n )\n .all(tag)\n .map((row) => noteRowToEntry(row as NoteRow));\n}\n\nexport function getRelatedTagsForEntries(\n slugs: string[],\n tag: string,\n): string[] {\n if (slugs.length === 0) return [];\n return loadVaultDb()\n .db.prepare(\n `\n SELECT nt.tag, COUNT(*) AS count\n FROM note_tags nt\n WHERE nt.slug IN (${slugs.map(() => \"?\").join(\", \")})\n AND nt.tag != ?\n GROUP BY nt.tag\n ORDER BY count DESC, nt.tag ASC\n LIMIT 12\n `,\n )\n .all(...slugs, tag)\n .map((row) => (row as { tag: string }).tag);\n}\n\nexport function resolveWikiLinkFromDb(\n currentSlug: string,\n target: string,\n strategy: \"absolute\" | \"relative\" | \"shortest\",\n ordering?: { numericPrefixes?: boolean },\n): string | undefined {\n const [rawPath] = target.split(\"#\");\n const slugOptions = ordering ?? getConfig().ordering;\n const normalizedTarget = normalizeSlug(rawPath ?? target, slugOptions);\n const db = loadVaultDb().db;\n\n if (strategy === \"absolute\") {\n return lookupAlias(db, \"absolute\", normalizedTarget);\n }\n\n if (strategy === \"relative\") {\n const relative = resolveRelative(\n asFullSlug(currentSlug),\n normalizedTarget,\n slugOptions,\n );\n const resolved = lookupAlias(db, \"absolute\", relative);\n if (resolved) return resolved;\n }\n\n return (\n lookupAlias(db, \"absolute\", normalizedTarget) ??\n lookupAlias(db, \"absolute\", `${normalizedTarget}/index`) ??\n lookupAlias(db, \"shortest\", normalizedTarget.split(\"/\").at(-1) ?? \"\")\n );\n}\n\nexport function resolveAssetFromDb(\n currentSourcePath: string,\n target: string,\n strategy: \"absolute\" | \"relative\" | \"shortest\",\n ordering?: { numericPrefixes?: boolean },\n): string | undefined {\n const assetOptions = ordering ?? getConfig().ordering;\n const normalizedTarget = normalizeAssetReference(target, assetOptions);\n if (!normalizedTarget) return undefined;\n const db = loadVaultDb().db;\n const isExplicitRelative = isExplicitRelativeAssetReference(target);\n\n if (isExplicitRelative || strategy === \"relative\") {\n const relative = resolveRelativeAsset(\n currentSourcePath,\n target,\n assetOptions,\n );\n const resolved = lookupAssetAlias(db, \"absolute\", relative);\n if (resolved || isExplicitRelative) return resolved;\n }\n\n if (strategy === \"absolute\") {\n return lookupAssetAlias(db, \"absolute\", normalizedTarget);\n }\n\n return (\n lookupAssetAlias(db, \"absolute\", normalizedTarget) ??\n lookupAssetAlias(db, \"shortest\", normalizedTarget.split(\"/\").at(-1) ?? \"\")\n );\n}\n\nexport function getBreadcrumbs(slug: string) {\n if (slug === \"index\" || !slug.includes(\"/\")) return [];\n\n const breadcrumbs: Array<{ label: string; href?: string }> = [\n { label: \"Home\", href: \"/\" },\n ];\n const segments = slug.split(\"/\").slice(0, -1);\n let acc = \"\";\n for (const segment of segments) {\n acc = acc ? `${acc}/${segment}` : segment;\n breadcrumbs.push({\n label: prettySegment(segment),\n href: breadcrumbSegmentHref(acc),\n });\n }\n return breadcrumbs;\n}\n\nexport function loadSearchIndex(): LoadedSearchIndex {\n const loaded = loadVaultDb();\n return {\n databasePath: loaded.databasePath,\n db: loaded.db,\n close: () => undefined,\n };\n}\n\nexport function normalizeRouteSlug(slug?: string[]): string {\n return slug?.length ? slug.join(\"/\") : \"index\";\n}\n\nfunction readMetadata(db: Database.Database): MetadataRows {\n const rows = db\n .prepare(\"SELECT key, value FROM vault_metadata\")\n .all() as Array<{ key: string; value: string }>;\n const metadata = Object.fromEntries(rows.map((row) => [row.key, row.value]));\n return {\n generatedAt: metadata.generatedAt ?? \"\",\n renderEnvironmentHash: metadata.renderEnvironmentHash ?? \"silica\",\n config: parseConfigMetadata(metadata.configJson),\n cacheState: JSON.parse(metadata.cacheStateJson ?? \"{}\") as RenderCacheState,\n };\n}\n\nfunction parseConfigMetadata(value: string | undefined): ResolvedSilicaConfig {\n if (!value) throw new Error(\"vault.db is missing configJson metadata.\");\n return JSON.parse(value) as ResolvedSilicaConfig;\n}\n\nfunction lookupAlias(\n db: Database.Database,\n strategy: string,\n alias: string,\n): string | undefined {\n const row = db\n .prepare(\n `\n SELECT slug\n FROM slug_aliases\n WHERE strategy_key = ?\n AND alias = ?\n ORDER BY sort_key, slug\n LIMIT 2\n `,\n )\n .all(strategy, alias) as Array<{ slug: string }>;\n return row.length === 1 ? row[0]?.slug : undefined;\n}\n\nfunction lookupAssetAlias(\n db: Database.Database,\n strategy: string,\n alias: string,\n): string | undefined {\n const row = db\n .prepare(\n `\n SELECT asset_path\n FROM asset_aliases\n WHERE strategy_key = ?\n AND alias = ?\n ORDER BY sort_key, asset_path\n LIMIT 2\n `,\n )\n .all(strategy, alias) as Array<{ asset_path: string }>;\n return row.length === 1 ? row[0]?.asset_path : undefined;\n}\n\nfunction isExplicitRelativeAssetReference(value: string): boolean {\n const withoutSuffix = value.split(/[?#]/)[0] ?? \"\";\n const normalized = withoutSuffix\n .replace(/\\\\/g, \"/\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n return /^\\.{1,2}\\//.test(normalized);\n}\n\nfunction noteRowToEntry(row: NoteRow): ManifestEntry {\n return {\n slug: row.slug,\n title: row.title,\n menuLabel: row.menu_label,\n description: row.description ?? undefined,\n generatedDescription: row.generated_description ?? undefined,\n tags: parseJsonArray(row.tags_json),\n file: path.isAbsolute(row.file)\n ? row.file\n : path.join(getProjectRoot(), row.file),\n sourcePath: row.source_path,\n sortKey: row.sort_key ?? undefined,\n created: row.created ?? undefined,\n modified: row.modified ?? undefined,\n frontmatter: parseObject(row.frontmatter_json),\n contentHash: row.content_hash,\n embeds: getEmbeds(row.slug),\n };\n}\n\nfunction getEmbeds(slug: string): string[] {\n return loadVaultDb()\n .db.prepare(\n \"SELECT target_slug FROM links WHERE source_slug = ? AND kind = 'embed' ORDER BY target_slug\",\n )\n .all(slug)\n .map((row) => (row as { target_slug: string }).target_slug);\n}\n\nfunction breadcrumbSegmentHref(segmentPath: string): string | undefined {\n if (getPage(segmentPath)) return slugToHref(segmentPath);\n const indexSlug = `${segmentPath}/index`;\n if (getPage(indexSlug)) return slugToHref(indexSlug);\n return undefined;\n}\n\nfunction prettySegment(segment: string): string {\n return segment\n .replace(/[-_]/g, \" \")\n .replace(/\\b\\w/g, (letter) => letter.toUpperCase());\n}\n\nfunction parseObject(value: string): Record<string, unknown> {\n return JSON.parse(value) as Record<string, unknown>;\n}\n\nfunction parseJsonArray(value: string): string[] {\n return JSON.parse(value) as string[];\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/server-data.ts"],"sourcesContent":["import path from \"node:path\";\nimport fs from \"node:fs\";\nimport Database from \"better-sqlite3\";\nimport type { LoadedSearchIndex } from \"@silicajs/search\";\nimport type {\n Navigation,\n ManifestEntry,\n RenderCacheState,\n ResolvedSilicaConfig,\n} from \"@silicajs/core/runtime\";\nimport {\n asFullSlug,\n normalizeAssetReference,\n normalizeSlug,\n resolveRelativeAsset,\n resolveRelative,\n slugToHref,\n} from \"@silicajs/core/runtime\";\n\nconst VAULT_DATABASE_FILENAME = \"vault.db\";\n\nexport type LoadedVaultDb = {\n databasePath: string;\n generatedAt: string;\n renderEnvironmentHash: string;\n config: ResolvedSilicaConfig;\n cacheState: RenderCacheState;\n mtimeMs: number;\n db: Database.Database;\n close(): void;\n};\n\nexport type VaultPageData = {\n cacheState: RenderCacheState;\n config: ResolvedSilicaConfig;\n entry: ManifestEntry;\n};\n\ntype MetadataRows = {\n generatedAt: string;\n renderEnvironmentHash: string;\n config: ResolvedSilicaConfig;\n cacheState: RenderCacheState;\n};\n\ntype NoteRow = {\n slug: string;\n file: string;\n source_path: string;\n title: string;\n menu_label: string;\n description: string | null;\n generated_description: string | null;\n frontmatter_json: string;\n tags_json: string;\n created: string | null;\n modified: string | null;\n sort_key: string | null;\n listed: 0 | 1;\n content_hash: string;\n render_hash: string;\n prerender: 0 | 1;\n};\n\ntype NavigationRow = {\n slug: string;\n title: string;\n sort_key: string | null;\n};\n\ntype BacklinkRow = {\n slug: string;\n title: string;\n};\n\nlet loadedVaultDb: LoadedVaultDb | undefined;\n\nexport function getProjectRoot(): string {\n const projectRoot = process.env.SILICA_PROJECT_ROOT;\n if (!projectRoot) {\n throw new Error(\"SILICA_PROJECT_ROOT must be set by the Silica CLI.\");\n }\n\n return projectRoot;\n}\n\nexport function getSilicaRoot(): string {\n return path.join(getProjectRoot(), \".silica\");\n}\n\nexport function getVaultDatabasePath(): string {\n return path.join(getSilicaRoot(), VAULT_DATABASE_FILENAME);\n}\n\nexport function loadVaultDb(): LoadedVaultDb {\n const databasePath = getVaultDatabasePath();\n const stat = fs.statSync(databasePath);\n if (\n loadedVaultDb?.databasePath === databasePath &&\n loadedVaultDb.mtimeMs === stat.mtimeMs\n ) {\n return loadedVaultDb;\n }\n\n loadedVaultDb?.close();\n\n const db = new Database(databasePath, {\n fileMustExist: true,\n readonly: true,\n });\n db.pragma(\"query_only = ON\");\n const metadata = readMetadata(db);\n loadedVaultDb = {\n databasePath,\n generatedAt: metadata.generatedAt,\n renderEnvironmentHash: metadata.renderEnvironmentHash,\n config: metadata.config,\n cacheState: metadata.cacheState,\n mtimeMs: stat.mtimeMs,\n db,\n close: () => {\n db.close();\n if (loadedVaultDb?.db === db) loadedVaultDb = undefined;\n },\n };\n return loadedVaultDb;\n}\n\nexport function getPage(slug: string): ManifestEntry | undefined {\n const row = loadVaultDb()\n .db.prepare(\"SELECT * FROM notes WHERE slug = ?\")\n .get(slug) as NoteRow | undefined;\n return row ? noteRowToEntry(row) : undefined;\n}\n\nexport function getPageRuntimeData(slug: string): VaultPageData | undefined {\n const entry = getPage(slug);\n if (!entry) return undefined;\n return {\n entry,\n config: getConfig(),\n cacheState: getCacheState(),\n };\n}\n\nexport function getRenderKey(slug: string): {\n renderHash: string;\n renderEnvironmentHash: string;\n} {\n const loaded = loadVaultDb();\n const row = loaded.db\n .prepare(\"SELECT render_hash FROM notes WHERE slug = ?\")\n .get(slug) as { render_hash: string } | undefined;\n return {\n renderHash: row?.render_hash ?? \"missing\",\n renderEnvironmentHash: loaded.renderEnvironmentHash,\n };\n}\n\nexport function loadRenderEnvironmentHash(): string {\n return loadVaultDb().renderEnvironmentHash;\n}\n\nexport function getPrerenderSlugs(): string[] {\n return loadVaultDb()\n .db.prepare(\n \"SELECT slug FROM notes WHERE prerender = 1 ORDER BY COALESCE(sort_key, slug), slug\",\n )\n .all()\n .map((row) => (row as { slug: string }).slug);\n}\n\nexport function getAllSlugs(): string[] {\n return loadVaultDb()\n .db.prepare(\"SELECT slug FROM notes ORDER BY slug\")\n .all()\n .map((row) => (row as { slug: string }).slug);\n}\n\nexport function getNavigation(): Navigation {\n const entries = loadVaultDb()\n .db.prepare(\n `\n SELECT slug, menu_label AS title, sort_key\n FROM notes\n WHERE listed = 1\n ORDER BY COALESCE(sort_key, slug), slug\n `,\n )\n .all() as NavigationRow[];\n return {\n version: 1,\n entries: entries.map((entry) => ({\n slug: entry.slug,\n title: entry.title,\n sortKey: entry.sort_key ?? undefined,\n })),\n };\n}\n\nexport function getBacklinks(slug: string): BacklinkRow[] {\n return loadVaultDb()\n .db.prepare(\n `\n SELECT n.slug, n.title\n FROM links l\n JOIN notes n ON n.slug = l.source_slug\n WHERE l.target_slug = ?\n AND l.kind = 'link'\n ORDER BY n.title COLLATE NOCASE ASC, n.slug\n `,\n )\n .all(slug) as BacklinkRow[];\n}\n\nexport function getConfig(): ResolvedSilicaConfig {\n return loadVaultDb().config;\n}\n\nexport function getCacheState(): RenderCacheState {\n return loadVaultDb().cacheState;\n}\n\nexport function getTagSlugs(): string[] {\n return loadVaultDb()\n .db.prepare(\"SELECT DISTINCT tag FROM note_tags ORDER BY tag\")\n .all()\n .map((row) => (row as { tag: string }).tag);\n}\n\nexport function getEntriesForTag(tag: string): ManifestEntry[] {\n return loadVaultDb()\n .db.prepare(\n `\n SELECT n.*\n FROM notes n\n WHERE n.listed = 1\n AND EXISTS (\n SELECT 1\n FROM note_tags nt\n WHERE nt.slug = n.slug\n AND nt.tag = ?\n )\n ORDER BY n.title COLLATE NOCASE ASC, n.slug\n `,\n )\n .all(tag)\n .map((row) => noteRowToEntry(row as NoteRow));\n}\n\nexport function getRelatedTagsForEntries(\n slugs: string[],\n tag: string,\n): string[] {\n if (slugs.length === 0) return [];\n return loadVaultDb()\n .db.prepare(\n `\n SELECT nt.tag, COUNT(*) AS count\n FROM note_tags nt\n WHERE nt.slug IN (${slugs.map(() => \"?\").join(\", \")})\n AND nt.tag != ?\n GROUP BY nt.tag\n ORDER BY count DESC, nt.tag ASC\n LIMIT 12\n `,\n )\n .all(...slugs, tag)\n .map((row) => (row as { tag: string }).tag);\n}\n\nexport function resolveWikiLinkFromDb(\n currentSlug: string,\n target: string,\n strategy: \"absolute\" | \"relative\" | \"shortest\",\n ordering?: { numericPrefixes?: boolean },\n): string | undefined {\n const [rawPath] = target.split(\"#\");\n const slugOptions = ordering ?? getConfig().ordering;\n const normalizedTarget = normalizeSlug(rawPath ?? target, slugOptions);\n const db = loadVaultDb().db;\n\n if (strategy === \"absolute\") {\n return lookupAlias(db, \"absolute\", normalizedTarget);\n }\n\n if (strategy === \"relative\") {\n const relative = resolveRelative(\n asFullSlug(currentSlug),\n normalizedTarget,\n slugOptions,\n );\n const resolved = lookupAlias(db, \"absolute\", relative);\n if (resolved) return resolved;\n }\n\n return (\n lookupAlias(db, \"absolute\", normalizedTarget) ??\n lookupAlias(db, \"absolute\", `${normalizedTarget}/index`) ??\n lookupClosestAlias(\n db,\n currentSlug,\n normalizedTarget.split(\"/\").at(-1) ?? \"\",\n )\n );\n}\n\nexport function resolveAssetFromDb(\n currentSourcePath: string,\n target: string,\n strategy: \"absolute\" | \"relative\" | \"shortest\",\n ordering?: { numericPrefixes?: boolean },\n): string | undefined {\n const assetOptions = ordering ?? getConfig().ordering;\n const normalizedTarget = normalizeAssetReference(target, assetOptions);\n if (!normalizedTarget) return undefined;\n const db = loadVaultDb().db;\n const isExplicitRelative = isExplicitRelativeAssetReference(target);\n\n if (isExplicitRelative || strategy === \"relative\") {\n const relative = resolveRelativeAsset(\n currentSourcePath,\n target,\n assetOptions,\n );\n const resolved = lookupAssetAlias(db, \"absolute\", relative);\n if (resolved || isExplicitRelative) return resolved;\n }\n\n if (strategy === \"absolute\") {\n return lookupAssetAlias(db, \"absolute\", normalizedTarget);\n }\n\n return (\n lookupAssetAlias(db, \"absolute\", normalizedTarget) ??\n lookupAssetAlias(db, \"shortest\", normalizedTarget.split(\"/\").at(-1) ?? \"\")\n );\n}\n\nexport function getBreadcrumbs(slug: string) {\n if (slug === \"index\" || !slug.includes(\"/\")) return [];\n\n const breadcrumbs: Array<{ label: string; href?: string }> = [\n { label: \"Home\", href: \"/\" },\n ];\n const segments = slug.split(\"/\").slice(0, -1);\n let acc = \"\";\n for (const segment of segments) {\n acc = acc ? `${acc}/${segment}` : segment;\n breadcrumbs.push({\n label: prettySegment(segment),\n href: breadcrumbSegmentHref(acc),\n });\n }\n return breadcrumbs;\n}\n\nexport function loadSearchIndex(): LoadedSearchIndex {\n const loaded = loadVaultDb();\n return {\n databasePath: loaded.databasePath,\n db: loaded.db,\n close: () => undefined,\n };\n}\n\nexport function normalizeRouteSlug(slug?: string[]): string {\n return slug?.length ? slug.join(\"/\") : \"index\";\n}\n\nfunction readMetadata(db: Database.Database): MetadataRows {\n const rows = db\n .prepare(\"SELECT key, value FROM vault_metadata\")\n .all() as Array<{ key: string; value: string }>;\n const metadata = Object.fromEntries(rows.map((row) => [row.key, row.value]));\n return {\n generatedAt: metadata.generatedAt ?? \"\",\n renderEnvironmentHash: metadata.renderEnvironmentHash ?? \"silica\",\n config: parseConfigMetadata(metadata.configJson),\n cacheState: JSON.parse(metadata.cacheStateJson ?? \"{}\") as RenderCacheState,\n };\n}\n\nfunction parseConfigMetadata(value: string | undefined): ResolvedSilicaConfig {\n if (!value) throw new Error(\"vault.db is missing configJson metadata.\");\n return JSON.parse(value) as ResolvedSilicaConfig;\n}\n\nfunction lookupAlias(\n db: Database.Database,\n strategy: string,\n alias: string,\n): string | undefined {\n const row = db\n .prepare(\n `\n SELECT slug\n FROM slug_aliases\n WHERE strategy_key = ?\n AND alias = ?\n ORDER BY sort_key, slug\n LIMIT 2\n `,\n )\n .all(strategy, alias) as Array<{ slug: string }>;\n return row.length === 1 ? row[0]?.slug : undefined;\n}\n\nfunction lookupClosestAlias(\n db: Database.Database,\n currentSlug: string,\n alias: string,\n): string | undefined {\n const rows = db\n .prepare(\n `\n SELECT slug\n FROM slug_aliases\n WHERE strategy_key = 'shortest'\n AND alias = ?\n ORDER BY slug\n `,\n )\n .all(alias) as Array<{ slug: string }>;\n\n return closestWikiLinkCandidate(\n currentSlug,\n rows.map((row) => row.slug),\n );\n}\n\nfunction lookupAssetAlias(\n db: Database.Database,\n strategy: string,\n alias: string,\n): string | undefined {\n const row = db\n .prepare(\n `\n SELECT asset_path\n FROM asset_aliases\n WHERE strategy_key = ?\n AND alias = ?\n ORDER BY sort_key, asset_path\n LIMIT 2\n `,\n )\n .all(strategy, alias) as Array<{ asset_path: string }>;\n return row.length === 1 ? row[0]?.asset_path : undefined;\n}\n\nfunction closestWikiLinkCandidate(\n currentSlug: string,\n candidates: readonly string[],\n): string | undefined {\n if (candidates.length === 0) return undefined;\n\n const currentDirectory = normalizeSlug(currentSlug, {\n numericPrefixes: false,\n })\n .split(\"/\")\n .slice(0, -1);\n const [bestCandidate] = [...candidates].sort((left, right) => {\n const leftScore = wikiLinkCandidateScore(currentDirectory, left);\n const rightScore = wikiLinkCandidateScore(currentDirectory, right);\n\n return (\n rightScore.sharedPrefixLength - leftScore.sharedPrefixLength ||\n leftScore.depth - rightScore.depth ||\n compareSlugs(left, right)\n );\n });\n\n return bestCandidate;\n}\n\nfunction wikiLinkCandidateScore(currentDirectory: string[], slug: string) {\n const simplified = slug === \"index\" ? \"\" : slug.replace(/\\/index$/, \"\");\n const segments = simplified ? simplified.split(\"/\") : [];\n\n return {\n sharedPrefixLength: sharedPrefixLength(\n currentDirectory,\n segments.slice(0, -1),\n ),\n depth: segments.length,\n };\n}\n\nfunction sharedPrefixLength(left: readonly string[], right: readonly string[]) {\n let length = 0;\n while (left[length] !== undefined && left[length] === right[length]) {\n length += 1;\n }\n return length;\n}\n\nfunction compareSlugs(left: string, right: string) {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nfunction isExplicitRelativeAssetReference(value: string): boolean {\n const withoutSuffix = value.split(/[?#]/)[0] ?? \"\";\n const normalized = withoutSuffix\n .replace(/\\\\/g, \"/\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n return /^\\.{1,2}\\//.test(normalized);\n}\n\nfunction noteRowToEntry(row: NoteRow): ManifestEntry {\n return {\n slug: row.slug,\n title: row.title,\n menuLabel: row.menu_label,\n description: row.description ?? undefined,\n generatedDescription: row.generated_description ?? undefined,\n tags: parseJsonArray(row.tags_json),\n file: path.isAbsolute(row.file)\n ? row.file\n : path.join(getProjectRoot(), row.file),\n sourcePath: row.source_path,\n sortKey: row.sort_key ?? undefined,\n created: row.created ?? undefined,\n modified: row.modified ?? undefined,\n frontmatter: parseObject(row.frontmatter_json),\n contentHash: row.content_hash,\n embeds: getEmbeds(row.slug),\n };\n}\n\nfunction getEmbeds(slug: string): string[] {\n return loadVaultDb()\n .db.prepare(\n \"SELECT target_slug FROM links WHERE source_slug = ? AND kind = 'embed' ORDER BY target_slug\",\n )\n .all(slug)\n .map((row) => (row as { target_slug: string }).target_slug);\n}\n\nfunction breadcrumbSegmentHref(segmentPath: string): string | undefined {\n if (getPage(segmentPath)) return slugToHref(segmentPath);\n const indexSlug = `${segmentPath}/index`;\n if (getPage(indexSlug)) return slugToHref(indexSlug);\n return undefined;\n}\n\nfunction prettySegment(segment: string): string {\n return segment\n .replace(/[-_]/g, \" \")\n .replace(/\\b\\w/g, (letter) => letter.toUpperCase());\n}\n\nfunction parseObject(value: string): Record<string, unknown> {\n return JSON.parse(value) as Record<string, unknown>;\n}\n\nfunction parseJsonArray(value: string): string[] {\n return JSON.parse(value) as string[];\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silicajs/next",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Next.js runtime, routes, templates, and proxy for Silica.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -96,8 +96,8 @@
96
96
  },
97
97
  "dependencies": {
98
98
  "@silicajs/auth": "^0.1.2",
99
- "@silicajs/components": "^0.2.4",
100
- "@silicajs/core": "^0.6.1",
99
+ "@silicajs/components": "^0.3.0",
100
+ "@silicajs/core": "^0.7.0",
101
101
  "@silicajs/remark-obsidian": "^0.1.0",
102
102
  "@silicajs/search": "^0.3.1",
103
103
  "better-auth": "1.6.16",