@silicajs/core 0.5.0 → 0.6.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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/logo.ts","../src/files.ts","../src/precompute.ts","../src/vault-db.ts"],"sourcesContent":["import path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { createJiti } from \"jiti\";\nimport { resolvePublicAssetPath } from \"./logo.js\";\nimport type {\n ResolvedSilicaConfig,\n ResolvedSilicaPrerenderConfig,\n SilicaConfig,\n SilicaPrerenderConfig,\n} from \"./types.js\";\n\nexport function defineConfig(config: SilicaConfig): SilicaConfig {\n return config;\n}\n\nexport async function loadConfig(\n projectRoot = process.cwd(),\n): Promise<ResolvedSilicaConfig> {\n const configPath = path.join(projectRoot, \"silica.config.ts\");\n const jsConfigPath = path.join(projectRoot, \"silica.config.js\");\n const configFile = existsSync(configPath)\n ? configPath\n : existsSync(jsConfigPath)\n ? jsConfigPath\n : undefined;\n\n let userConfig: SilicaConfig = {};\n if (configFile) {\n const jiti = createJiti(projectRoot, { interopDefault: true });\n const loaded = await jiti.import<SilicaConfig | { default: SilicaConfig }>(\n configFile,\n );\n userConfig = \"default\" in loaded ? loaded.default : loaded;\n }\n\n return resolveConfig(userConfig, projectRoot);\n}\n\nexport function resolveConfig(\n config: SilicaConfig = {},\n projectRoot = process.cwd(),\n): ResolvedSilicaConfig {\n const auth = config.auth === false ? undefined : config.auth;\n const authEnabled = Boolean(\n auth?.enabled ??\n auth?.provider ??\n auth?.allowedDomains?.length ??\n auth?.allowedEmails?.length,\n );\n const allowedDomains = auth?.allowedDomains ?? [];\n const allowedEmails = auth?.allowedEmails ?? [];\n\n if (\n authEnabled &&\n allowedDomains.length === 0 &&\n allowedEmails.length === 0\n ) {\n throw new Error(\n \"Silica auth requires at least one allowedDomains or allowedEmails entry.\",\n );\n }\n\n return {\n projectRoot,\n title: config.title ?? \"Silica\",\n description: config.description ?? \"A Silica knowledge site\",\n logo: resolvePublicAssetPath(config.logo),\n baseUrl: config.baseUrl,\n contentDir: config.contentDir ?? \"content\",\n theme: config.theme ?? \"default\",\n auth: authEnabled\n ? {\n provider: auth?.provider ?? \"google\",\n enabled: true,\n allowedDomains,\n allowedEmails,\n }\n : undefined,\n wikilinks: {\n strategy: config.wikilinks?.strategy ?? \"shortest\",\n strict: config.wikilinks?.strict ?? false,\n },\n tags: {\n inline: config.tags?.inline ?? true,\n },\n ordering: {\n numericPrefixes: config.ordering?.numericPrefixes ?? true,\n },\n filters: {\n removeDrafts: config.filters?.removeDrafts ?? true,\n explicitPublish: config.filters?.explicitPublish ?? false,\n },\n render: {\n prerender: resolvePrerenderConfig(config.render?.prerender),\n cache: {\n storage: config.render?.cache?.storage ?? \"filesystem\",\n directory: config.render?.cache?.directory,\n },\n },\n };\n}\n\nfunction resolvePrerenderConfig(\n prerender: SilicaPrerenderConfig | undefined,\n): ResolvedSilicaPrerenderConfig {\n if (!prerender || prerender === \"all\") return { strategy: \"all\" };\n if (prerender === \"none\") return { strategy: \"none\" };\n if (\"strategy\" in prerender && prerender.strategy === \"all\") {\n return { ...prerender, strategy: \"all\" };\n }\n if (\"strategy\" in prerender && prerender.strategy === \"none\") {\n return { ...prerender, strategy: \"none\" };\n }\n if (\"strategy\" in prerender && prerender.strategy === \"custom\") {\n return { ...prerender, strategy: \"custom\" };\n }\n return { ...prerender, strategy: \"depth\" };\n}\n","/** Normalize a public asset path or pass through absolute URLs. */\nexport function resolvePublicAssetPath(asset?: string): string | undefined {\n const trimmed = asset?.trim();\n if (!trimmed) return undefined;\n if (trimmed.startsWith(\"http://\") || trimmed.startsWith(\"https://\")) {\n return trimmed;\n }\n return trimmed.startsWith(\"/\") ? trimmed : `/${trimmed}`;\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport fs from \"fs-extra\";\nimport matter from \"gray-matter\";\nimport type { ResolvedSilicaConfig } from \"./types.js\";\nimport { asFilePath, slugifyFilePath } from \"./path.js\";\n\nexport type ContentMarkdownFile = {\n absolutePath: string;\n relativePath: string;\n slug: string;\n raw: string;\n body: string;\n frontmatter: Record<string, unknown>;\n stats: {\n birthtime?: Date;\n mtime?: Date;\n };\n};\n\nexport type ContentAssetFile = {\n absolutePath: string;\n relativePath: string;\n};\n\nexport type ContentScan = {\n markdown: ContentMarkdownFile[];\n assets: ContentAssetFile[];\n};\n\nexport async function scanContent(\n projectRoot: string,\n config: ResolvedSilicaConfig,\n): Promise<ContentScan> {\n const contentRoot = path.join(projectRoot, config.contentDir);\n const realContentRoot = await fs.realpath(contentRoot);\n const entries = await fg(\"**/*\", {\n cwd: contentRoot,\n dot: false,\n followSymbolicLinks: false,\n onlyFiles: true,\n unique: true,\n });\n\n const markdown: ContentMarkdownFile[] = [];\n const assets: ContentAssetFile[] = [];\n\n for (const relativePath of entries.sort()) {\n const absolutePath = path.join(contentRoot, relativePath);\n const stats = await fs.lstat(absolutePath);\n if (!stats.isFile()) continue;\n if (!(await isWithinRoot(absolutePath, realContentRoot))) continue;\n\n if (isMarkdownFile(relativePath)) {\n const raw = await fs.readFile(absolutePath, \"utf8\");\n const parsed = matter(raw);\n markdown.push({\n absolutePath,\n relativePath: relativePath.replace(/\\\\/g, \"/\"),\n slug: slugifyFilePath(\n asFilePath(relativePath),\n config.contentDir,\n config.ordering,\n ),\n raw,\n body: parsed.content,\n frontmatter: parsed.data,\n stats: {\n birthtime: stats.birthtime,\n mtime: stats.mtime,\n },\n });\n } else {\n assets.push({\n absolutePath,\n relativePath: relativePath.replace(/\\\\/g, \"/\"),\n });\n }\n }\n\n return { markdown, assets };\n}\n\nasync function isWithinRoot(\n absolutePath: string,\n realRoot: string,\n): Promise<boolean> {\n const realPath = await fs.realpath(absolutePath);\n const relative = path.relative(realRoot, realPath);\n return (\n relative === \"\" ||\n (!relative.startsWith(\"..\") && !path.isAbsolute(relative))\n );\n}\n\nexport function isMarkdownFile(filePath: string): boolean {\n return /\\.(md|markdown|mdx)$/i.test(filePath);\n}\n","import crypto from \"node:crypto\";\nimport { execFile } from \"node:child_process\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { Worker } from \"node:worker_threads\";\nimport fs from \"fs-extra\";\nimport { type SearchRecord } from \"@silicajs/search\";\nimport { loadConfig } from \"./config.js\";\nimport { scanContent, type ContentMarkdownFile } from \"./files.js\";\nimport {\n asFullSlug,\n createWikiLinkResolutionIndex,\n hasNumericPrefixInPath,\n numericPrefixSortKey,\n stripNumericPrefix,\n slugToHref,\n type WikiLinkResolutionIndex,\n} from \"./path.js\";\nimport { getMenuLabel } from \"./pipeline/frontmatter.js\";\nimport { analyzeMarkdown } from \"./pipeline/index.js\";\nimport type {\n AnalyzeResult,\n BrokenLink,\n Graph,\n Manifest,\n ManifestEntry,\n PrecomputeResult,\n PrerenderManifest,\n RenderCacheState,\n ResolvedSilicaConfig,\n} from \"./types.js\";\nimport { writeVaultDatabase } from \"./vault-db.js\";\n\nconst execFileAsync = promisify(execFile);\nconst MIN_PARALLEL_ANALYSIS_FILES = 64;\nconst ANALYSIS_BATCH_SIZE = 16;\nconst MAX_ANALYSIS_WORKERS = 12;\nconst RENDER_CACHE_SCHEMA_VERSION = \"silica-render-v1\";\n\nexport type PrecomputeOptions = {\n projectRoot?: string;\n config?: ResolvedSilicaConfig;\n analysisConcurrency?: number;\n};\n\nexport async function precompute(\n options: PrecomputeOptions = {},\n): Promise<PrecomputeResult> {\n const projectRoot = options.projectRoot ?? process.cwd();\n const config = options.config ?? (await loadConfig(projectRoot));\n const scan = await scanContent(projectRoot, config);\n const markdownFiles = filterPublished(scan.markdown, config);\n const allSlugs = markdownFiles.map((file) => file.slug);\n const wikilinkIndex = createWikiLinkResolutionIndex(\n allSlugs,\n config.ordering,\n );\n const entries: ManifestEntry[] = [];\n const graphLinks: Record<string, string[]> = {};\n const brokenLinks: BrokenLink[] = [];\n const searchRecords: SearchRecord[] = [];\n const runtimeContentRoot = path.join(projectRoot, \".silica/content\");\n const relativeGitPaths = markdownFiles.map((file) =>\n normalizeGitPath(path.join(config.contentDir, file.relativePath)),\n );\n const gitDatesByPath = await getGitDatesForFiles(\n projectRoot,\n relativeGitPaths,\n );\n\n await fs.ensureDir(path.join(projectRoot, \".silica\"));\n await fs.ensureDir(path.join(projectRoot, \".silica/next/public/silica\"));\n await writeRuntimeMarkdown(runtimeContentRoot, markdownFiles);\n const analyses = await analyzeMarkdownFiles(markdownFiles, config, allSlugs, {\n concurrency: options.analysisConcurrency,\n wikilinkIndex,\n });\n\n for (const [index, file] of markdownFiles.entries()) {\n const gitDates =\n gitDatesByPath.get(\n normalizeGitPath(path.join(config.contentDir, file.relativePath)),\n ) ?? {};\n const analysis = analyses[index]!;\n\n const title =\n analysis.title ?? titleFromFilePath(file.relativePath, config.ordering);\n const menuLabel = getMenuLabel(file.frontmatter, title);\n const sortKey =\n config.ordering.numericPrefixes &&\n hasNumericPrefixInPath(file.relativePath)\n ? numericPrefixSortKey(file.relativePath)\n : undefined;\n const entry: ManifestEntry = {\n slug: file.slug,\n title,\n menuLabel,\n description: analysis.description,\n generatedDescription: analysis.generatedDescription,\n tags: analysis.tags,\n file: normalizeGitPath(path.join(\".silica/content\", file.relativePath)),\n relativeFile: file.relativePath,\n sortKey,\n created: stringifyDate(\n getDate(file.frontmatter.created) ??\n getDate(file.frontmatter.date) ??\n gitDates.created ??\n file.stats.birthtime,\n ),\n modified: stringifyDate(\n getDate(file.frontmatter.modified) ??\n gitDates.modified ??\n file.stats.mtime,\n ),\n frontmatter: file.frontmatter,\n contentHash: hashString(file.raw),\n embeds: analysis.embeds,\n };\n entries.push(entry);\n graphLinks[file.slug] = analysis.links;\n brokenLinks.push(...analysis.brokenLinks);\n if (isListedEntry(entry)) {\n searchRecords.push({\n id: file.slug,\n slug: file.slug,\n title,\n content: analysis.plainText,\n description: analysis.description,\n tags: analysis.tags,\n });\n }\n }\n\n await copyAssets(projectRoot, config, scan.assets);\n\n const manifest = makeManifest(config, entries);\n const graph = makeGraph(graphLinks, brokenLinks);\n const renderHashes = makeRenderHashes(manifest, graph);\n const cacheState = await makeRenderCacheState(projectRoot, config, manifest);\n const prerender = makePrerenderManifest(manifest, graph, config);\n await writeVaultDatabase(projectRoot, {\n config,\n manifest,\n graph,\n renderHashes,\n cacheState,\n prerender,\n searchRecords,\n });\n await writeSitemapAndRobots(projectRoot, config, manifest);\n\n if (config.wikilinks.strict && brokenLinks.length > 0) {\n const message = brokenLinks\n .map((link) => `${link.source} -> ${link.target}`)\n .join(\"\\n\");\n throw new Error(`Broken wikilinks detected:\\n${message}`);\n }\n\n return {\n manifest,\n graph,\n searchRecords,\n prerender,\n cacheState,\n brokenLinks,\n };\n}\n\ntype AnalyzeMarkdownFilesOptions = {\n concurrency?: number;\n wikilinkIndex: WikiLinkResolutionIndex;\n};\n\ntype AnalysisWorkerFile = {\n index: number;\n slug: string;\n raw: string;\n};\n\ntype AnalysisWorkerMessage = {\n id: number;\n files: AnalysisWorkerFile[];\n};\n\ntype AnalysisWorkerResult = {\n id: number;\n results?: Array<{ index: number; analysis: AnalyzeResult }>;\n error?: string;\n};\n\nasync function analyzeMarkdownFiles(\n files: ContentMarkdownFile[],\n config: ResolvedSilicaConfig,\n allSlugs: string[],\n options: AnalyzeMarkdownFilesOptions,\n): Promise<AnalyzeResult[]> {\n const workerCount = getAnalysisWorkerCount(files.length, options.concurrency);\n if (workerCount <= 1) {\n return analyzeMarkdownFilesSerial(files, config, options.wikilinkIndex);\n }\n\n return analyzeMarkdownFilesParallel(files, config, allSlugs, workerCount);\n}\n\nasync function analyzeMarkdownFilesSerial(\n files: ContentMarkdownFile[],\n config: ResolvedSilicaConfig,\n wikilinkIndex: WikiLinkResolutionIndex,\n): Promise<AnalyzeResult[]> {\n const analyses: AnalyzeResult[] = [];\n for (const file of files) {\n analyses.push(\n await analyzeMarkdown(file.raw, {\n slug: asFullSlug(file.slug),\n wikilinkIndex,\n assetBaseUrl: \"/silica\",\n wikilinkStrategy: config.wikilinks.strategy,\n tags: config.tags,\n ordering: config.ordering,\n }),\n );\n }\n return analyses;\n}\n\nfunction analyzeMarkdownFilesParallel(\n files: ContentMarkdownFile[],\n config: ResolvedSilicaConfig,\n allSlugs: string[],\n workerCount: number,\n): Promise<AnalyzeResult[]> {\n return new Promise((resolve, reject) => {\n const workerUrl = new URL(\"./precompute-worker.js\", import.meta.url);\n const workers: Worker[] = [];\n const analyses: AnalyzeResult[] = new Array(files.length);\n let nextIndex = 0;\n let completed = 0;\n let settled = false;\n\n const rejectOnce = (error: unknown) => {\n if (settled) return;\n settled = true;\n for (const worker of workers) {\n void worker.terminate();\n }\n reject(error);\n };\n\n const resolveIfDone = () => {\n if (completed < files.length || settled) return;\n settled = true;\n for (const worker of workers) {\n void worker.terminate();\n }\n resolve(analyses);\n };\n\n const sendNext = (worker: Worker) => {\n if (settled || nextIndex >= files.length) return;\n const start = nextIndex;\n const batch = files\n .slice(start, start + ANALYSIS_BATCH_SIZE)\n .map((file, offset) => ({\n index: start + offset,\n slug: file.slug,\n raw: file.raw,\n }));\n nextIndex += batch.length;\n worker.postMessage({\n id: start,\n files: batch,\n } satisfies AnalysisWorkerMessage);\n };\n\n for (let index = 0; index < workerCount; index += 1) {\n const worker = new Worker(workerUrl, {\n workerData: {\n allSlugs,\n wikilinkStrategy: config.wikilinks.strategy,\n tags: config.tags,\n ordering: config.ordering,\n },\n });\n workers.push(worker);\n worker.on(\"message\", (message: AnalysisWorkerResult) => {\n if (message.error) {\n rejectOnce(new Error(message.error));\n return;\n }\n for (const result of message.results ?? []) {\n analyses[result.index] = result.analysis;\n }\n completed += message.results?.length ?? 0;\n resolveIfDone();\n sendNext(worker);\n });\n worker.on(\"error\", rejectOnce);\n worker.on(\"exit\", (code) => {\n if (!settled && code !== 0) {\n rejectOnce(\n new Error(`Precompute analysis worker exited with ${code}`),\n );\n }\n });\n sendNext(worker);\n }\n });\n}\n\nfunction getAnalysisWorkerCount(\n fileCount: number,\n requestedConcurrency: number | undefined,\n): number {\n if (fileCount === 0) return 1;\n if (\n requestedConcurrency === undefined &&\n fileCount < MIN_PARALLEL_ANALYSIS_FILES\n ) {\n return 1;\n }\n\n const available = Math.max(\n 1,\n os.availableParallelism?.() ?? os.cpus().length,\n );\n const requested = getRequestedAnalysisConcurrency(\n requestedConcurrency,\n available,\n );\n const usefulWorkers = Math.ceil(fileCount / ANALYSIS_BATCH_SIZE);\n return Math.max(1, Math.min(fileCount, requested, usefulWorkers));\n}\n\nfunction getRequestedAnalysisConcurrency(\n requestedConcurrency: number | undefined,\n available: number,\n): number {\n if (requestedConcurrency === undefined) {\n return Math.min(available, MAX_ANALYSIS_WORKERS);\n }\n if (!Number.isFinite(requestedConcurrency)) return 1;\n return Math.max(1, Math.floor(requestedConcurrency));\n}\n\nasync function writeRuntimeMarkdown(\n runtimeContentRoot: string,\n files: ContentMarkdownFile[],\n): Promise<void> {\n await fs.emptyDir(runtimeContentRoot);\n for (const file of files) {\n const destination = path.join(runtimeContentRoot, file.relativePath);\n await fs.ensureDir(path.dirname(destination));\n await fs.writeFile(destination, file.raw);\n }\n}\n\nasync function makeRenderCacheState(\n projectRoot: string,\n config: ResolvedSilicaConfig,\n manifest: Manifest,\n): Promise<RenderCacheState> {\n const themeHash = await getThemeHash(projectRoot, config.theme);\n const configHash = hashStable({\n title: config.title,\n description: config.description,\n logo: config.logo,\n baseUrl: config.baseUrl,\n contentDir: config.contentDir,\n theme: config.theme,\n auth: config.auth,\n wikilinks: config.wikilinks,\n tags: config.tags,\n ordering: config.ordering,\n filters: config.filters,\n });\n const navigationHash = hashStable({\n entries: manifest.entries.filter(isListedEntry).map((entry) => ({\n slug: entry.slug,\n menuLabel: entry.menuLabel,\n sortKey: entry.sortKey,\n })),\n });\n const tagIndexHash = hashStable({\n entries: manifest.entries.filter(isListedEntry).map((entry) => ({\n slug: entry.slug,\n title: entry.title,\n description: entry.description,\n tags: entry.tags,\n })),\n });\n return {\n version: 1,\n renderEnvironmentHash: hashStable({\n version: RENDER_CACHE_SCHEMA_VERSION,\n configHash,\n themeHash,\n }),\n configHash,\n navigationHash,\n tagIndexHash,\n themeHash,\n rendererVersion: RENDER_CACHE_SCHEMA_VERSION,\n generatedAt: new Date().toISOString(),\n };\n}\n\nfunction makeRenderHashes(\n manifest: Manifest,\n graph: Graph,\n): Record<string, string> {\n const memo = new Map<string, string>();\n const renderHashForSlug = (\n slug: string,\n seen = new Set<string>(),\n ): string => {\n const cached = memo.get(slug);\n if (cached) return cached;\n const entry = manifest.bySlug[slug];\n if (!entry) return hashStable({ missing: slug });\n if (seen.has(slug)) {\n return hashStable({ slug, contentHash: entry.contentHash, cycle: true });\n }\n const nextSeen = new Set(seen).add(slug);\n const embedded = entry.embeds.map((target) => ({\n slug: target,\n renderHash: renderHashForSlug(target, nextSeen),\n }));\n const backlinks = (graph.backlinks[slug] ?? []).map((source) => ({\n slug: source,\n title: manifest.bySlug[source]?.title ?? source,\n }));\n const renderHash = hashStable({\n entry: {\n slug: entry.slug,\n title: entry.title,\n menuLabel: entry.menuLabel,\n description: entry.description,\n generatedDescription: entry.generatedDescription,\n tags: entry.tags,\n relativeFile: entry.relativeFile,\n sortKey: entry.sortKey,\n created: entry.created,\n modified: entry.modified,\n frontmatter: entry.frontmatter,\n contentHash: entry.contentHash,\n },\n embedded,\n backlinks,\n });\n memo.set(slug, renderHash);\n return renderHash;\n };\n\n for (const slug of manifest.allSlugs) {\n renderHashForSlug(slug);\n }\n return Object.fromEntries(memo);\n}\n\nfunction makePrerenderManifest(\n manifest: Manifest,\n graph: Graph,\n config: ResolvedSilicaConfig,\n): PrerenderManifest {\n return {\n version: 1,\n slugs: selectPrerenderSlugs(manifest, graph, config),\n };\n}\n\nfunction selectPrerenderSlugs(\n manifest: Manifest,\n graph: Graph,\n config: ResolvedSilicaConfig,\n): string[] {\n const prerender = config.render.prerender;\n const entries = manifest.entries;\n const scoreBySlug = new Map<string, number>();\n let candidates: ManifestEntry[] = [];\n\n if (prerender.strategy === \"all\") {\n candidates = entries;\n } else if (prerender.strategy === \"depth\") {\n candidates = entries.filter(\n (entry) =>\n entry.slug === \"index\" || getSlugDepth(entry.slug) <= prerender.depth,\n );\n } else if (prerender.strategy === \"custom\") {\n const context = { manifest, graph };\n candidates = entries.filter((entry) => {\n const selected = prerender.select?.(entry, context);\n if (typeof selected === \"number\" && Number.isFinite(selected)) {\n scoreBySlug.set(entry.slug, selected);\n return true;\n }\n return selected === true;\n });\n }\n\n const selected = new Set(\n [...candidates]\n .sort((left, right) => {\n const scoreDelta =\n (scoreBySlug.get(right.slug) ?? 0) -\n (scoreBySlug.get(left.slug) ?? 0);\n return scoreDelta || compareManifestEntries(left, right);\n })\n .slice(0, prerender.limit ?? candidates.length)\n .map((entry) => entry.slug),\n );\n\n for (const slug of prerender.include ?? []) {\n if (manifest.bySlug[slug]) selected.add(slug);\n }\n for (const slug of prerender.exclude ?? []) {\n selected.delete(slug);\n }\n\n return manifest.entries\n .map((entry) => entry.slug)\n .filter((slug) => selected.has(slug));\n}\n\nfunction getSlugDepth(slug: string): number {\n const segments = slug.split(\"/\").filter(Boolean);\n return Math.max(0, segments.length - 1);\n}\n\nasync function getThemeHash(\n projectRoot: string,\n theme: ResolvedSilicaConfig[\"theme\"],\n): Promise<string | undefined> {\n const themeName = getThemeName(theme);\n if (!themeName?.startsWith(\".\")) return undefined;\n const themeRoot = path.resolve(projectRoot, themeName);\n if (!(await fs.pathExists(themeRoot))) return undefined;\n const files = await readThemeFiles(themeRoot);\n return hashStable(files);\n}\n\nfunction getThemeName(\n theme: ResolvedSilicaConfig[\"theme\"],\n): string | undefined {\n if (typeof theme === \"string\") return theme;\n if (typeof theme === \"object\" && theme !== null) return theme.name;\n return undefined;\n}\n\nasync function readThemeFiles(\n root: string,\n current = root,\n): Promise<Array<{ path: string; content: string }>> {\n const entries = await fs.readdir(current, { withFileTypes: true });\n const results: Array<{ path: string; content: string }> = [];\n for (const entry of entries.sort((left, right) =>\n left.name.localeCompare(right.name),\n )) {\n const absolutePath = path.join(current, entry.name);\n if (entry.isDirectory()) {\n results.push(...(await readThemeFiles(root, absolutePath)));\n } else if (entry.isFile()) {\n results.push({\n path: normalizeGitPath(path.relative(root, absolutePath)),\n content: await fs.readFile(absolutePath, \"utf8\"),\n });\n }\n }\n return results;\n}\n\nexport async function getGitDates(\n projectRoot: string,\n relativePath: string,\n): Promise<{ created?: Date; modified?: Date }> {\n return (\n (\n await getGitDatesForFiles(projectRoot, [normalizeGitPath(relativePath)])\n ).get(normalizeGitPath(relativePath)) ?? {}\n );\n}\n\nasync function getGitDatesForFiles(\n projectRoot: string,\n relativePaths: string[],\n): Promise<Map<string, { created?: Date; modified?: Date }>> {\n const wanted = new Set(relativePaths.map(normalizeGitPath));\n const datesByPath = new Map<string, { created?: Date; modified?: Date }>();\n if (wanted.size === 0) return datesByPath;\n\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"log\", \"--format=__SILICA_COMMIT__%aI\", \"--name-only\", \"--\", ...wanted],\n {\n cwd: projectRoot,\n timeout: 2_000,\n },\n );\n let commitDate: Date | undefined;\n for (const line of stdout.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n if (trimmed.startsWith(\"__SILICA_COMMIT__\")) {\n const parsed = new Date(trimmed.slice(\"__SILICA_COMMIT__\".length));\n commitDate = Number.isNaN(parsed.valueOf()) ? undefined : parsed;\n continue;\n }\n const relativePath = normalizeGitPath(trimmed);\n if (!commitDate || !wanted.has(relativePath)) continue;\n const dates = datesByPath.get(relativePath) ?? {};\n dates.modified ??= commitDate;\n dates.created = commitDate;\n datesByPath.set(relativePath, dates);\n }\n } catch {\n return datesByPath;\n }\n return datesByPath;\n}\n\nfunction normalizeGitPath(relativePath: string): string {\n return relativePath.replace(/\\\\/g, \"/\");\n}\n\nfunction hashString(value: string): string {\n return crypto.createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction hashStable(value: unknown): string {\n return hashString(stableStringify(value));\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === undefined) return \"undefined\";\n if (value instanceof Date) return JSON.stringify(value.toISOString());\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n if (value && typeof value === \"object\") {\n const entries = Object.entries(value)\n .filter(([, entryValue]) => typeof entryValue !== \"function\")\n .sort(([left], [right]) => left.localeCompare(right));\n return `{${entries\n .map(\n ([key, entryValue]) =>\n `${JSON.stringify(key)}:${stableStringify(entryValue)}`,\n )\n .join(\",\")}}`;\n }\n return JSON.stringify(value);\n}\n\nfunction filterPublished(\n files: ContentMarkdownFile[],\n config: ResolvedSilicaConfig,\n): ContentMarkdownFile[] {\n return files.filter((file) => {\n if (config.filters.removeDrafts && file.frontmatter.draft === true)\n return false;\n if (config.filters.explicitPublish && file.frontmatter.publish !== true)\n return false;\n return true;\n });\n}\n\nfunction makeManifest(\n config: ResolvedSilicaConfig,\n entries: ManifestEntry[],\n): Manifest {\n const sorted = [...entries].sort(compareManifestEntries);\n return {\n version: 1,\n generatedAt: new Date().toISOString(),\n contentDir: config.contentDir,\n allSlugs: sorted.map((entry) => entry.slug),\n entries: sorted,\n bySlug: Object.fromEntries(sorted.map((entry) => [entry.slug, entry])),\n };\n}\n\nfunction compareManifestEntries(a: ManifestEntry, b: ManifestEntry): number {\n if (a.sortKey || b.sortKey) {\n return (\n (a.sortKey ?? fallbackSortKey(a.slug)).localeCompare(\n b.sortKey ?? fallbackSortKey(b.slug),\n ) || a.slug.localeCompare(b.slug)\n );\n }\n\n return a.slug.localeCompare(b.slug);\n}\n\nfunction fallbackSortKey(slug: string): string {\n return slug\n .split(\"/\")\n .map((segment) => `~~~~~~~~~~:${segment}`)\n .join(\"/\");\n}\n\nfunction makeGraph(\n links: Record<string, string[]>,\n brokenLinks: BrokenLink[],\n): Graph {\n const backlinks: Record<string, string[]> = {};\n for (const [source, targets] of Object.entries(links)) {\n links[source] = [...new Set(targets)].sort();\n for (const target of targets) {\n backlinks[target] ??= [];\n backlinks[target]!.push(source);\n }\n }\n\n for (const [target, sources] of Object.entries(backlinks)) {\n backlinks[target] = [...new Set(sources)].sort();\n }\n\n return {\n version: 1,\n links,\n backlinks,\n brokenLinks,\n };\n}\n\nasync function copyAssets(\n projectRoot: string,\n config: ResolvedSilicaConfig,\n assets: Array<{ absolutePath: string; relativePath: string }>,\n): Promise<void> {\n const destinationRoot = path.join(projectRoot, \".silica/next/public/silica\");\n await fs.emptyDir(destinationRoot);\n for (const asset of assets) {\n await fs.ensureDir(\n path.dirname(path.join(destinationRoot, asset.relativePath)),\n );\n await fs.copyFile(\n asset.absolutePath,\n path.join(destinationRoot, asset.relativePath),\n );\n }\n\n await fs.ensureDir(path.join(projectRoot, \".silica/next/public\"));\n await fs.writeFile(path.join(destinationRoot, \".gitkeep\"), \"\");\n}\n\nasync function writeSitemapAndRobots(\n projectRoot: string,\n config: ResolvedSilicaConfig,\n manifest: Manifest,\n): Promise<void> {\n const publicRoot = path.join(projectRoot, \".silica/next/public\");\n await fs.ensureDir(publicRoot);\n const baseUrl = (config.baseUrl ?? \"http://localhost:3000\").replace(\n /\\/$/,\n \"\",\n );\n const urls = manifest.entries\n .filter(isListedEntry)\n .map(\n (entry) => ` <url><loc>${baseUrl}${slugToHref(entry.slug)}</loc></url>`,\n )\n .join(\"\\n\");\n if (!(await fs.pathExists(path.join(projectRoot, \"public/sitemap.xml\")))) {\n await fs.writeFile(\n path.join(publicRoot, \"sitemap.xml\"),\n `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${urls}\\n</urlset>\\n`,\n );\n }\n if (!(await fs.pathExists(path.join(projectRoot, \"public/robots.txt\")))) {\n await fs.writeFile(\n path.join(publicRoot, \"robots.txt\"),\n `User-agent: *\\nAllow: /\\nSitemap: ${baseUrl}/sitemap.xml\\n`,\n );\n }\n}\n\nfunction getDate(value: unknown): Date | undefined {\n if (value instanceof Date) return value;\n if (typeof value === \"string\" || typeof value === \"number\") {\n const parsed = new Date(value);\n if (!Number.isNaN(parsed.valueOf())) return parsed;\n }\n return undefined;\n}\n\nexport function isListedEntry(entry: ManifestEntry): boolean {\n return entry.frontmatter.listed !== false;\n}\n\nfunction stringifyDate(value?: Date): string | undefined {\n return value?.toISOString();\n}\n\nfunction titleFromFilePath(\n relativePath: string,\n ordering: ResolvedSilicaConfig[\"ordering\"],\n): string {\n const stem = path.posix\n .basename(normalizeGitPath(relativePath))\n .replace(/\\.(md|markdown|mdx)$/i, \"\");\n const title = ordering.numericPrefixes ? stripNumericPrefix(stem) : stem;\n return /^index$/i.test(title) ? \"Home\" : title;\n}\n","import path from \"node:path\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs-extra\";\nimport {\n buildSearchTables,\n makeExcerpt,\n type SearchRecord,\n} from \"@silicajs/search\";\nimport type {\n Graph,\n Manifest,\n ManifestEntry,\n PrerenderManifest,\n RenderCacheState,\n ResolvedSilicaConfig,\n} from \"./types.js\";\n\nexport const VAULT_DATABASE_FILENAME = \"vault.db\";\nexport const VAULT_DATABASE_VERSION = \"1\";\n\nexport type VaultDbBuildInput = {\n config: ResolvedSilicaConfig;\n manifest: Manifest;\n graph: Graph;\n renderHashes: Record<string, string>;\n cacheState: RenderCacheState;\n prerender: PrerenderManifest;\n searchRecords: SearchRecord[];\n};\n\nexport type VaultDbNote = {\n slug: string;\n file: string;\n relativeFile: string;\n title: string;\n menuLabel: string;\n description?: string;\n generatedDescription?: string;\n frontmatter: Record<string, unknown>;\n tags: string[];\n created?: string;\n modified?: string;\n sortKey?: string;\n listed: boolean;\n contentHash: string;\n renderHash: string;\n prerender: boolean;\n};\n\nexport async function writeVaultDatabase(\n projectRoot: string,\n input: VaultDbBuildInput,\n): Promise<string> {\n const silicaRoot = path.join(projectRoot, \".silica\");\n await fs.ensureDir(silicaRoot);\n\n const databasePath = path.join(silicaRoot, VAULT_DATABASE_FILENAME);\n const temporaryPath = path.join(silicaRoot, `${VAULT_DATABASE_FILENAME}.tmp`);\n await removeDatabaseFiles(temporaryPath);\n\n const db = new Database(temporaryPath);\n try {\n db.pragma(\"journal_mode = DELETE\");\n db.pragma(\"foreign_keys = ON\");\n db.pragma(\"synchronous = OFF\");\n createVaultDatabaseSchema(db);\n populateVaultDatabase(db, input);\n db.exec(\"VACUUM\");\n } finally {\n db.close();\n }\n\n await removeDatabaseFiles(databasePath);\n await fs.rename(temporaryPath, databasePath);\n await removeDatabaseSidecars(temporaryPath);\n return databasePath;\n}\n\nexport function createVaultDatabaseSchema(db: Database.Database): void {\n db.exec(`\n CREATE TABLE vault_metadata (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\n CREATE TABLE notes (\n slug TEXT PRIMARY KEY,\n file TEXT NOT NULL,\n relative_file TEXT NOT NULL,\n title TEXT NOT NULL,\n menu_label TEXT NOT NULL,\n description TEXT,\n generated_description TEXT,\n frontmatter_json TEXT NOT NULL,\n tags_json TEXT NOT NULL,\n search_excerpt TEXT NOT NULL DEFAULT '',\n created TEXT,\n modified TEXT,\n sort_key TEXT,\n listed INTEGER NOT NULL,\n content_hash TEXT NOT NULL,\n render_hash TEXT NOT NULL,\n prerender INTEGER NOT NULL\n );\n\n CREATE TABLE note_tags (\n slug TEXT NOT NULL,\n tag TEXT NOT NULL,\n PRIMARY KEY (slug, tag),\n FOREIGN KEY (slug) REFERENCES notes(slug) ON DELETE CASCADE\n );\n\n CREATE TABLE links (\n source_slug TEXT NOT NULL,\n target_slug TEXT NOT NULL,\n kind TEXT NOT NULL CHECK (kind IN ('link', 'embed')),\n PRIMARY KEY (source_slug, target_slug, kind)\n );\n\n CREATE TABLE broken_links (\n source_slug TEXT NOT NULL,\n target TEXT NOT NULL\n );\n\n CREATE TABLE slug_aliases (\n strategy_key TEXT NOT NULL,\n alias TEXT NOT NULL,\n slug TEXT NOT NULL,\n sort_key TEXT,\n PRIMARY KEY (strategy_key, alias, slug)\n );\n\n CREATE INDEX notes_prerender_idx ON notes(prerender, slug);\n CREATE INDEX notes_listed_sort_idx ON notes(listed, sort_key, slug);\n CREATE INDEX links_target_idx ON links(target_slug, kind, source_slug);\n CREATE INDEX links_source_idx ON links(source_slug, kind, target_slug);\n CREATE INDEX note_tags_tag_idx ON note_tags(tag, slug);\n CREATE INDEX slug_aliases_lookup_idx\n ON slug_aliases(strategy_key, alias, sort_key, slug);\n `);\n}\n\nexport function populateVaultDatabase(\n db: Database.Database,\n input: VaultDbBuildInput,\n): void {\n const prerenderSlugs = new Set(input.prerender.slugs);\n const searchBySlug = new Map(\n input.searchRecords.map((record) => [record.slug, record]),\n );\n\n const insertMetadata = db.prepare(`\n INSERT INTO vault_metadata (key, value) VALUES (?, ?)\n `);\n const insertNote = db.prepare(`\n INSERT INTO notes (\n slug,\n file,\n relative_file,\n title,\n menu_label,\n description,\n generated_description,\n frontmatter_json,\n tags_json,\n search_excerpt,\n created,\n modified,\n sort_key,\n listed,\n content_hash,\n render_hash,\n prerender\n )\n VALUES (\n @slug,\n @file,\n @relativeFile,\n @title,\n @menuLabel,\n @description,\n @generatedDescription,\n @frontmatterJson,\n @tagsJson,\n @searchExcerpt,\n @created,\n @modified,\n @sortKey,\n @listed,\n @contentHash,\n @renderHash,\n @prerender\n )\n `);\n const insertTag = db.prepare(`\n INSERT OR IGNORE INTO note_tags (slug, tag) VALUES (?, ?)\n `);\n const insertLink = db.prepare(`\n INSERT OR IGNORE INTO links (source_slug, target_slug, kind)\n VALUES (?, ?, ?)\n `);\n const insertBrokenLink = db.prepare(`\n INSERT INTO broken_links (source_slug, target) VALUES (?, ?)\n `);\n const insertAlias = db.prepare(`\n INSERT OR IGNORE INTO slug_aliases (strategy_key, alias, slug, sort_key)\n VALUES (?, ?, ?, ?)\n `);\n\n const insertAll = db.transaction(() => {\n insertMetadata.run(\"version\", VAULT_DATABASE_VERSION);\n insertMetadata.run(\"generatedAt\", input.manifest.generatedAt);\n insertMetadata.run(\"contentDir\", input.manifest.contentDir);\n insertMetadata.run(\"configJson\", JSON.stringify(input.config));\n insertMetadata.run(\n \"renderEnvironmentHash\",\n input.cacheState.renderEnvironmentHash,\n );\n insertMetadata.run(\"configHash\", input.cacheState.configHash);\n insertMetadata.run(\"navigationHash\", input.cacheState.navigationHash);\n insertMetadata.run(\"tagIndexHash\", input.cacheState.tagIndexHash);\n insertMetadata.run(\"rendererVersion\", input.cacheState.rendererVersion);\n insertMetadata.run(\"cacheStateJson\", JSON.stringify(input.cacheState));\n\n for (const entry of input.manifest.entries) {\n const searchRecord = searchBySlug.get(entry.slug);\n insertNote.run({\n slug: entry.slug,\n file: entry.file,\n relativeFile: entry.relativeFile,\n title: entry.title,\n menuLabel: entry.menuLabel,\n description: entry.description,\n generatedDescription: entry.generatedDescription,\n frontmatterJson: JSON.stringify(entry.frontmatter),\n tagsJson: JSON.stringify(entry.tags),\n searchExcerpt: searchRecord\n ? makeExcerpt(\n searchRecord.content,\n searchRecord.description ?? searchRecord.title,\n )\n : \"\",\n created: entry.created,\n modified: entry.modified,\n sortKey: entry.sortKey,\n listed: isListedEntry(entry) ? 1 : 0,\n contentHash: entry.contentHash,\n renderHash: input.renderHashes[entry.slug] ?? \"missing\",\n prerender: prerenderSlugs.has(entry.slug) ? 1 : 0,\n });\n\n for (const tag of entry.tags) {\n for (const hierarchyTag of tagHierarchy(tag)) {\n insertTag.run(entry.slug, hierarchyTag);\n }\n }\n }\n\n for (const [source, targets] of Object.entries(input.graph.links)) {\n for (const target of targets) {\n insertLink.run(source, target, \"link\");\n }\n }\n for (const entry of input.manifest.entries) {\n for (const target of entry.embeds) {\n insertLink.run(entry.slug, target, \"embed\");\n }\n }\n for (const brokenLink of input.graph.brokenLinks) {\n insertBrokenLink.run(brokenLink.source, brokenLink.target);\n }\n for (const entry of input.manifest.entries) {\n for (const [strategy, alias] of makeSlugAliases(entry.slug)) {\n insertAlias.run(\n strategy,\n alias,\n entry.slug,\n entry.sortKey ?? entry.slug,\n );\n }\n }\n });\n\n insertAll();\n buildSearchTables(db, input.searchRecords);\n}\n\nfunction isListedEntry(entry: ManifestEntry): boolean {\n return entry.frontmatter.listed !== false;\n}\n\nfunction tagHierarchy(tag: string): string[] {\n const normalized = tag.trim().replace(/^#/, \"\").toLowerCase();\n const segments = normalized.split(\"/\").filter(Boolean);\n return segments.map((_, index) => segments.slice(0, index + 1).join(\"/\"));\n}\n\nfunction makeSlugAliases(slug: string): Array<[string, string]> {\n const aliases = new Map<string, string>();\n const simplified = slug === \"index\" ? \"\" : slug.replace(/\\/index$/, \"\");\n const basename = simplified.split(\"/\").at(-1) ?? \"\";\n aliases.set(`absolute:${slug}`, slug);\n if (simplified) aliases.set(`absolute:${simplified}`, simplified);\n if (basename) aliases.set(`shortest:${basename}`, basename);\n return [...aliases.entries()].map(([key, alias]) => [\n key.split(\":\")[0] ?? \"shortest\",\n alias,\n ]);\n}\n\nasync function removeDatabaseFiles(databasePath: string): Promise<void> {\n await fs.remove(databasePath);\n await removeDatabaseSidecars(databasePath);\n}\n\nasync function removeDatabaseSidecars(databasePath: string): Promise<void> {\n await Promise.all([\n fs.remove(`${databasePath}-wal`),\n fs.remove(`${databasePath}-shm`),\n fs.remove(`${databasePath}-journal`),\n ]);\n}\n"],"mappings":"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","names":["path","path","path","fs","path","fs","path","fs","isListedEntry","selected"]}
1
+ {"version":3,"sources":["../src/config.ts","../src/logo.ts","../src/files.ts","../src/precompute.ts","../src/vault-db.ts"],"sourcesContent":["import path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { createJiti } from \"jiti\";\nimport { resolvePublicAssetPath } from \"./logo.js\";\nimport type {\n ResolvedSilicaConfig,\n ResolvedSilicaPrerenderConfig,\n SilicaConfig,\n SilicaPrerenderConfig,\n} from \"./types.js\";\n\nexport function defineConfig(config: SilicaConfig): SilicaConfig {\n return config;\n}\n\nexport async function loadConfig(\n projectRoot = process.cwd(),\n): Promise<ResolvedSilicaConfig> {\n const configPath = path.join(projectRoot, \"silica.config.ts\");\n const jsConfigPath = path.join(projectRoot, \"silica.config.js\");\n const configFile = existsSync(configPath)\n ? configPath\n : existsSync(jsConfigPath)\n ? jsConfigPath\n : undefined;\n\n let userConfig: SilicaConfig = {};\n if (configFile) {\n const jiti = createJiti(projectRoot, { interopDefault: true });\n const loaded = await jiti.import<SilicaConfig | { default: SilicaConfig }>(\n configFile,\n );\n userConfig = \"default\" in loaded ? loaded.default : loaded;\n }\n\n return resolveConfig(userConfig, projectRoot);\n}\n\nexport function resolveConfig(\n config: SilicaConfig = {},\n projectRoot = process.cwd(),\n): ResolvedSilicaConfig {\n const auth = config.auth === false ? undefined : config.auth;\n const authEnabled = Boolean(\n auth?.enabled ??\n auth?.provider ??\n auth?.allowedDomains?.length ??\n auth?.allowedEmails?.length,\n );\n const allowedDomains = auth?.allowedDomains ?? [];\n const allowedEmails = auth?.allowedEmails ?? [];\n\n if (\n authEnabled &&\n allowedDomains.length === 0 &&\n allowedEmails.length === 0\n ) {\n throw new Error(\n \"Silica auth requires at least one allowedDomains or allowedEmails entry.\",\n );\n }\n\n return {\n projectRoot,\n title: config.title ?? \"Silica\",\n description: config.description ?? \"A Silica knowledge site\",\n logo: resolvePublicAssetPath(config.logo),\n baseUrl: config.baseUrl,\n contentDir: config.contentDir ?? \"content\",\n theme: config.theme ?? \"default\",\n auth: authEnabled\n ? {\n provider: auth?.provider ?? \"google\",\n enabled: true,\n allowedDomains,\n allowedEmails,\n }\n : undefined,\n wikilinks: {\n strategy: config.wikilinks?.strategy ?? \"shortest\",\n strict: config.wikilinks?.strict ?? false,\n },\n tags: {\n inline: config.tags?.inline ?? true,\n },\n ordering: {\n numericPrefixes: config.ordering?.numericPrefixes ?? true,\n },\n filters: {\n removeDrafts: config.filters?.removeDrafts ?? true,\n explicitPublish: config.filters?.explicitPublish ?? false,\n },\n render: {\n prerender: resolvePrerenderConfig(config.render?.prerender),\n cache: {\n storage: config.render?.cache?.storage ?? \"filesystem\",\n directory: config.render?.cache?.directory,\n },\n },\n };\n}\n\nfunction resolvePrerenderConfig(\n prerender: SilicaPrerenderConfig | undefined,\n): ResolvedSilicaPrerenderConfig {\n if (!prerender || prerender === \"all\") return { strategy: \"all\" };\n if (prerender === \"none\") return { strategy: \"none\" };\n if (\"strategy\" in prerender && prerender.strategy === \"all\") {\n return { ...prerender, strategy: \"all\" };\n }\n if (\"strategy\" in prerender && prerender.strategy === \"none\") {\n return { ...prerender, strategy: \"none\" };\n }\n if (\"strategy\" in prerender && prerender.strategy === \"custom\") {\n return { ...prerender, strategy: \"custom\" };\n }\n return { ...prerender, strategy: \"depth\" };\n}\n","/** Normalize a public asset path or pass through absolute URLs. */\nexport function resolvePublicAssetPath(asset?: string): string | undefined {\n const trimmed = asset?.trim();\n if (!trimmed) return undefined;\n if (trimmed.startsWith(\"http://\") || trimmed.startsWith(\"https://\")) {\n return trimmed;\n }\n return trimmed.startsWith(\"/\") ? trimmed : `/${trimmed}`;\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\nimport fs from \"fs-extra\";\nimport matter from \"gray-matter\";\nimport type { ResolvedSilicaConfig } from \"./types.js\";\nimport { asFilePath, slugifyAssetPath, slugifyFilePath } from \"./path.js\";\n\nexport type ContentMarkdownFile = {\n absolutePath: string;\n sourcePath: string;\n slug: string;\n raw: string;\n body: string;\n frontmatter: Record<string, unknown>;\n stats: {\n birthtime?: Date;\n mtime?: Date;\n };\n};\n\nexport type ContentAssetFile = {\n absolutePath: string;\n sourcePath: string;\n assetPath: string;\n};\n\nexport type ContentScan = {\n markdown: ContentMarkdownFile[];\n assets: ContentAssetFile[];\n};\n\nexport async function scanContent(\n projectRoot: string,\n config: ResolvedSilicaConfig,\n): Promise<ContentScan> {\n const contentRoot = path.join(projectRoot, config.contentDir);\n const realContentRoot = await fs.realpath(contentRoot);\n const entries = await fg(\"**/*\", {\n cwd: contentRoot,\n dot: false,\n followSymbolicLinks: false,\n onlyFiles: true,\n unique: true,\n });\n\n const markdown: ContentMarkdownFile[] = [];\n const assets: ContentAssetFile[] = [];\n\n for (const relativePath of entries.sort()) {\n const sourcePath = relativePath.replace(/\\\\/g, \"/\");\n const absolutePath = path.join(contentRoot, relativePath);\n const stats = await fs.lstat(absolutePath);\n if (!stats.isFile()) continue;\n if (!(await isWithinRoot(absolutePath, realContentRoot))) continue;\n\n if (isMarkdownFile(relativePath)) {\n const raw = await fs.readFile(absolutePath, \"utf8\");\n const parsed = matter(raw);\n markdown.push({\n absolutePath,\n sourcePath,\n slug: slugifyFilePath(\n asFilePath(relativePath),\n config.contentDir,\n config.ordering,\n ),\n raw,\n body: parsed.content,\n frontmatter: parsed.data,\n stats: {\n birthtime: stats.birthtime,\n mtime: stats.mtime,\n },\n });\n } else {\n assets.push({\n absolutePath,\n sourcePath,\n assetPath: slugifyAssetPath(sourcePath, config.ordering),\n });\n }\n }\n\n assertUniqueAssetPaths(assets);\n\n return { markdown, assets };\n}\n\nfunction assertUniqueAssetPaths(assets: ContentAssetFile[]) {\n const sourcePathByAssetPath = new Map<string, string>();\n for (const asset of assets) {\n const existing = sourcePathByAssetPath.get(asset.assetPath);\n if (existing && existing !== asset.sourcePath) {\n throw new Error(\n `Asset path collision: ${existing} and ${asset.sourcePath} both map to ${asset.assetPath}`,\n );\n }\n sourcePathByAssetPath.set(asset.assetPath, asset.sourcePath);\n }\n}\n\nasync function isWithinRoot(\n absolutePath: string,\n realRoot: string,\n): Promise<boolean> {\n const realPath = await fs.realpath(absolutePath);\n const relative = path.relative(realRoot, realPath);\n return (\n relative === \"\" ||\n (!relative.startsWith(\"..\") && !path.isAbsolute(relative))\n );\n}\n\nexport function isMarkdownFile(filePath: string): boolean {\n return /\\.(md|markdown|mdx)$/i.test(filePath);\n}\n","import crypto from \"node:crypto\";\nimport { execFile } from \"node:child_process\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { Worker } from \"node:worker_threads\";\nimport fs from \"fs-extra\";\nimport { type SearchRecord } from \"@silicajs/search\";\nimport { loadConfig } from \"./config.js\";\nimport { scanContent, type ContentMarkdownFile } from \"./files.js\";\nimport {\n asFullSlug,\n createAssetResolutionIndex,\n createWikiLinkResolutionIndex,\n hasNumericPrefixInPath,\n numericPrefixSortKey,\n stripNumericPrefix,\n type AssetResolutionIndex,\n slugToHref,\n type WikiLinkResolutionIndex,\n} from \"./path.js\";\nimport { getMenuLabel } from \"./pipeline/frontmatter.js\";\nimport { analyzeMarkdown } from \"./pipeline/index.js\";\nimport type {\n AnalyzeResult,\n BrokenLink,\n Graph,\n Manifest,\n ManifestEntry,\n PrecomputeResult,\n PrerenderManifest,\n RenderCacheState,\n ResolvedSilicaConfig,\n} from \"./types.js\";\nimport { writeVaultDatabase } from \"./vault-db.js\";\n\nconst execFileAsync = promisify(execFile);\nconst MIN_PARALLEL_ANALYSIS_FILES = 64;\nconst ANALYSIS_BATCH_SIZE = 16;\nconst MAX_ANALYSIS_WORKERS = 12;\nconst RENDER_CACHE_SCHEMA_VERSION = \"silica-render-v1\";\n\nexport type PrecomputeOptions = {\n projectRoot?: string;\n config?: ResolvedSilicaConfig;\n analysisConcurrency?: number;\n};\n\nexport async function precompute(\n options: PrecomputeOptions = {},\n): Promise<PrecomputeResult> {\n const projectRoot = options.projectRoot ?? process.cwd();\n const config = options.config ?? (await loadConfig(projectRoot));\n const scan = await scanContent(projectRoot, config);\n const markdownFiles = filterPublished(scan.markdown, config);\n const assetEntries = scan.assets.map(({ sourcePath, assetPath }) => ({\n sourcePath,\n assetPath,\n }));\n const allSlugs = markdownFiles.map((file) => file.slug);\n const wikilinkIndex = createWikiLinkResolutionIndex(\n allSlugs,\n config.ordering,\n );\n const assetIndex = createAssetResolutionIndex(assetEntries, config.ordering);\n const entries: ManifestEntry[] = [];\n const graphLinks: Record<string, string[]> = {};\n const brokenLinks: BrokenLink[] = [];\n const searchRecords: SearchRecord[] = [];\n const runtimeContentRoot = path.join(projectRoot, \".silica/content\");\n const relativeGitPaths = markdownFiles.map((file) =>\n normalizeGitPath(path.join(config.contentDir, file.sourcePath)),\n );\n const gitDatesByPath = await getGitDatesForFiles(\n projectRoot,\n relativeGitPaths,\n );\n\n await fs.ensureDir(path.join(projectRoot, \".silica\"));\n await fs.ensureDir(path.join(projectRoot, \".silica/next/public/silica\"));\n await writeRuntimeMarkdown(runtimeContentRoot, markdownFiles);\n const analyses = await analyzeMarkdownFiles(markdownFiles, config, allSlugs, {\n concurrency: options.analysisConcurrency,\n wikilinkIndex,\n assetIndex,\n assetEntries,\n });\n\n for (const [index, file] of markdownFiles.entries()) {\n const gitDates =\n gitDatesByPath.get(\n normalizeGitPath(path.join(config.contentDir, file.sourcePath)),\n ) ?? {};\n const analysis = analyses[index]!;\n\n const title =\n analysis.title ?? titleFromFilePath(file.sourcePath, config.ordering);\n const menuLabel = getMenuLabel(file.frontmatter, title);\n const sortKey =\n config.ordering.numericPrefixes && hasNumericPrefixInPath(file.sourcePath)\n ? numericPrefixSortKey(file.sourcePath)\n : undefined;\n const entry: ManifestEntry = {\n slug: file.slug,\n title,\n menuLabel,\n description: analysis.description,\n generatedDescription: analysis.generatedDescription,\n tags: analysis.tags,\n file: normalizeGitPath(path.join(\".silica/content\", file.sourcePath)),\n sourcePath: file.sourcePath,\n sortKey,\n created: stringifyDate(\n getDate(file.frontmatter.created) ??\n getDate(file.frontmatter.date) ??\n gitDates.created ??\n file.stats.birthtime,\n ),\n modified: stringifyDate(\n getDate(file.frontmatter.modified) ??\n gitDates.modified ??\n file.stats.mtime,\n ),\n frontmatter: file.frontmatter,\n contentHash: hashString(file.raw),\n embeds: analysis.embeds,\n };\n entries.push(entry);\n graphLinks[file.slug] = analysis.links;\n brokenLinks.push(...analysis.brokenLinks);\n if (isListedEntry(entry)) {\n searchRecords.push({\n id: file.slug,\n slug: file.slug,\n title,\n content: analysis.plainText,\n description: analysis.description,\n tags: analysis.tags,\n });\n }\n }\n\n await copyAssets(projectRoot, config, scan.assets);\n\n const manifest = makeManifest(config, entries);\n const graph = makeGraph(graphLinks, brokenLinks);\n const renderHashes = makeRenderHashes(manifest, graph);\n const cacheState = await makeRenderCacheState(projectRoot, config, manifest);\n const prerender = makePrerenderManifest(manifest, graph, config);\n await writeVaultDatabase(projectRoot, {\n config,\n manifest,\n graph,\n renderHashes,\n cacheState,\n prerender,\n searchRecords,\n assets: assetEntries,\n });\n await writeSitemapAndRobots(projectRoot, config, manifest);\n\n if (config.wikilinks.strict && brokenLinks.length > 0) {\n const message = brokenLinks\n .map((link) => `${link.source} -> ${link.target}`)\n .join(\"\\n\");\n throw new Error(`Broken wikilinks detected:\\n${message}`);\n }\n\n return {\n manifest,\n graph,\n searchRecords,\n prerender,\n cacheState,\n brokenLinks,\n };\n}\n\ntype AnalyzeMarkdownFilesOptions = {\n concurrency?: number;\n wikilinkIndex: WikiLinkResolutionIndex;\n assetIndex: AssetResolutionIndex;\n assetEntries: Array<{ sourcePath: string; assetPath: string }>;\n};\n\ntype AnalysisWorkerFile = {\n index: number;\n slug: string;\n sourcePath: string;\n raw: string;\n};\n\ntype AnalysisWorkerMessage = {\n id: number;\n files: AnalysisWorkerFile[];\n};\n\ntype AnalysisWorkerResult = {\n id: number;\n results?: Array<{ index: number; analysis: AnalyzeResult }>;\n error?: string;\n};\n\nasync function analyzeMarkdownFiles(\n files: ContentMarkdownFile[],\n config: ResolvedSilicaConfig,\n allSlugs: string[],\n options: AnalyzeMarkdownFilesOptions,\n): Promise<AnalyzeResult[]> {\n const workerCount = getAnalysisWorkerCount(files.length, options.concurrency);\n if (workerCount <= 1) {\n return analyzeMarkdownFilesSerial(\n files,\n config,\n options.wikilinkIndex,\n options.assetIndex,\n );\n }\n\n return analyzeMarkdownFilesParallel(\n files,\n config,\n allSlugs,\n options.assetEntries,\n workerCount,\n );\n}\n\nasync function analyzeMarkdownFilesSerial(\n files: ContentMarkdownFile[],\n config: ResolvedSilicaConfig,\n wikilinkIndex: WikiLinkResolutionIndex,\n assetIndex: AssetResolutionIndex,\n): Promise<AnalyzeResult[]> {\n const analyses: AnalyzeResult[] = [];\n for (const file of files) {\n analyses.push(\n await analyzeMarkdown(file.raw, {\n slug: asFullSlug(file.slug),\n sourcePath: file.sourcePath,\n wikilinkIndex,\n assetIndex,\n assetBaseUrl: \"/silica\",\n wikilinkStrategy: config.wikilinks.strategy,\n tags: config.tags,\n ordering: config.ordering,\n }),\n );\n }\n return analyses;\n}\n\nfunction analyzeMarkdownFilesParallel(\n files: ContentMarkdownFile[],\n config: ResolvedSilicaConfig,\n allSlugs: string[],\n assetEntries: Array<{ sourcePath: string; assetPath: string }>,\n workerCount: number,\n): Promise<AnalyzeResult[]> {\n return new Promise((resolve, reject) => {\n const workerUrl = new URL(\"./precompute-worker.js\", import.meta.url);\n const workers: Worker[] = [];\n const analyses: AnalyzeResult[] = new Array(files.length);\n let nextIndex = 0;\n let completed = 0;\n let settled = false;\n\n const rejectOnce = (error: unknown) => {\n if (settled) return;\n settled = true;\n for (const worker of workers) {\n void worker.terminate();\n }\n reject(error);\n };\n\n const resolveIfDone = () => {\n if (completed < files.length || settled) return;\n settled = true;\n for (const worker of workers) {\n void worker.terminate();\n }\n resolve(analyses);\n };\n\n const sendNext = (worker: Worker) => {\n if (settled || nextIndex >= files.length) return;\n const start = nextIndex;\n const batch = files\n .slice(start, start + ANALYSIS_BATCH_SIZE)\n .map((file, offset) => ({\n index: start + offset,\n slug: file.slug,\n sourcePath: file.sourcePath,\n raw: file.raw,\n }));\n nextIndex += batch.length;\n worker.postMessage({\n id: start,\n files: batch,\n } satisfies AnalysisWorkerMessage);\n };\n\n for (let index = 0; index < workerCount; index += 1) {\n const worker = new Worker(workerUrl, {\n workerData: {\n allSlugs,\n assetEntries,\n wikilinkStrategy: config.wikilinks.strategy,\n tags: config.tags,\n ordering: config.ordering,\n },\n });\n workers.push(worker);\n worker.on(\"message\", (message: AnalysisWorkerResult) => {\n if (message.error) {\n rejectOnce(new Error(message.error));\n return;\n }\n for (const result of message.results ?? []) {\n analyses[result.index] = result.analysis;\n }\n completed += message.results?.length ?? 0;\n resolveIfDone();\n sendNext(worker);\n });\n worker.on(\"error\", rejectOnce);\n worker.on(\"exit\", (code) => {\n if (!settled && code !== 0) {\n rejectOnce(\n new Error(`Precompute analysis worker exited with ${code}`),\n );\n }\n });\n sendNext(worker);\n }\n });\n}\n\nfunction getAnalysisWorkerCount(\n fileCount: number,\n requestedConcurrency: number | undefined,\n): number {\n if (fileCount === 0) return 1;\n if (\n requestedConcurrency === undefined &&\n fileCount < MIN_PARALLEL_ANALYSIS_FILES\n ) {\n return 1;\n }\n\n const available = Math.max(\n 1,\n os.availableParallelism?.() ?? os.cpus().length,\n );\n const requested = getRequestedAnalysisConcurrency(\n requestedConcurrency,\n available,\n );\n const usefulWorkers = Math.ceil(fileCount / ANALYSIS_BATCH_SIZE);\n return Math.max(1, Math.min(fileCount, requested, usefulWorkers));\n}\n\nfunction getRequestedAnalysisConcurrency(\n requestedConcurrency: number | undefined,\n available: number,\n): number {\n if (requestedConcurrency === undefined) {\n return Math.min(available, MAX_ANALYSIS_WORKERS);\n }\n if (!Number.isFinite(requestedConcurrency)) return 1;\n return Math.max(1, Math.floor(requestedConcurrency));\n}\n\nasync function writeRuntimeMarkdown(\n runtimeContentRoot: string,\n files: ContentMarkdownFile[],\n): Promise<void> {\n await fs.emptyDir(runtimeContentRoot);\n for (const file of files) {\n const destination = path.join(runtimeContentRoot, file.sourcePath);\n await fs.ensureDir(path.dirname(destination));\n await fs.writeFile(destination, file.raw);\n }\n}\n\nasync function makeRenderCacheState(\n projectRoot: string,\n config: ResolvedSilicaConfig,\n manifest: Manifest,\n): Promise<RenderCacheState> {\n const themeHash = await getThemeHash(projectRoot, config.theme);\n const configHash = hashStable({\n title: config.title,\n description: config.description,\n logo: config.logo,\n baseUrl: config.baseUrl,\n contentDir: config.contentDir,\n theme: config.theme,\n auth: config.auth,\n wikilinks: config.wikilinks,\n tags: config.tags,\n ordering: config.ordering,\n filters: config.filters,\n });\n const navigationHash = hashStable({\n entries: manifest.entries.filter(isListedEntry).map((entry) => ({\n slug: entry.slug,\n menuLabel: entry.menuLabel,\n sortKey: entry.sortKey,\n })),\n });\n const tagIndexHash = hashStable({\n entries: manifest.entries.filter(isListedEntry).map((entry) => ({\n slug: entry.slug,\n title: entry.title,\n description: entry.description,\n tags: entry.tags,\n })),\n });\n return {\n version: 1,\n renderEnvironmentHash: hashStable({\n version: RENDER_CACHE_SCHEMA_VERSION,\n configHash,\n themeHash,\n }),\n configHash,\n navigationHash,\n tagIndexHash,\n themeHash,\n rendererVersion: RENDER_CACHE_SCHEMA_VERSION,\n generatedAt: new Date().toISOString(),\n };\n}\n\nfunction makeRenderHashes(\n manifest: Manifest,\n graph: Graph,\n): Record<string, string> {\n const memo = new Map<string, string>();\n const renderHashForSlug = (\n slug: string,\n seen = new Set<string>(),\n ): string => {\n const cached = memo.get(slug);\n if (cached) return cached;\n const entry = manifest.bySlug[slug];\n if (!entry) return hashStable({ missing: slug });\n if (seen.has(slug)) {\n return hashStable({ slug, contentHash: entry.contentHash, cycle: true });\n }\n const nextSeen = new Set(seen).add(slug);\n const embedded = entry.embeds.map((target) => ({\n slug: target,\n renderHash: renderHashForSlug(target, nextSeen),\n }));\n const backlinks = (graph.backlinks[slug] ?? []).map((source) => ({\n slug: source,\n title: manifest.bySlug[source]?.title ?? source,\n }));\n const renderHash = hashStable({\n entry: {\n slug: entry.slug,\n title: entry.title,\n menuLabel: entry.menuLabel,\n description: entry.description,\n generatedDescription: entry.generatedDescription,\n tags: entry.tags,\n sourcePath: entry.sourcePath,\n sortKey: entry.sortKey,\n created: entry.created,\n modified: entry.modified,\n frontmatter: entry.frontmatter,\n contentHash: entry.contentHash,\n },\n embedded,\n backlinks,\n });\n memo.set(slug, renderHash);\n return renderHash;\n };\n\n for (const slug of manifest.allSlugs) {\n renderHashForSlug(slug);\n }\n return Object.fromEntries(memo);\n}\n\nfunction makePrerenderManifest(\n manifest: Manifest,\n graph: Graph,\n config: ResolvedSilicaConfig,\n): PrerenderManifest {\n return {\n version: 1,\n slugs: selectPrerenderSlugs(manifest, graph, config),\n };\n}\n\nfunction selectPrerenderSlugs(\n manifest: Manifest,\n graph: Graph,\n config: ResolvedSilicaConfig,\n): string[] {\n const prerender = config.render.prerender;\n const entries = manifest.entries;\n const scoreBySlug = new Map<string, number>();\n let candidates: ManifestEntry[] = [];\n\n if (prerender.strategy === \"all\") {\n candidates = entries;\n } else if (prerender.strategy === \"depth\") {\n candidates = entries.filter(\n (entry) =>\n entry.slug === \"index\" || getSlugDepth(entry.slug) <= prerender.depth,\n );\n } else if (prerender.strategy === \"custom\") {\n const context = { manifest, graph };\n candidates = entries.filter((entry) => {\n const selected = prerender.select?.(entry, context);\n if (typeof selected === \"number\" && Number.isFinite(selected)) {\n scoreBySlug.set(entry.slug, selected);\n return true;\n }\n return selected === true;\n });\n }\n\n const selected = new Set(\n [...candidates]\n .sort((left, right) => {\n const scoreDelta =\n (scoreBySlug.get(right.slug) ?? 0) -\n (scoreBySlug.get(left.slug) ?? 0);\n return scoreDelta || compareManifestEntries(left, right);\n })\n .slice(0, prerender.limit ?? candidates.length)\n .map((entry) => entry.slug),\n );\n\n for (const slug of prerender.include ?? []) {\n if (manifest.bySlug[slug]) selected.add(slug);\n }\n for (const slug of prerender.exclude ?? []) {\n selected.delete(slug);\n }\n\n return manifest.entries\n .map((entry) => entry.slug)\n .filter((slug) => selected.has(slug));\n}\n\nfunction getSlugDepth(slug: string): number {\n const segments = slug.split(\"/\").filter(Boolean);\n return Math.max(0, segments.length - 1);\n}\n\nasync function getThemeHash(\n projectRoot: string,\n theme: ResolvedSilicaConfig[\"theme\"],\n): Promise<string | undefined> {\n const themeName = getThemeName(theme);\n if (!themeName?.startsWith(\".\")) return undefined;\n const themeRoot = path.resolve(projectRoot, themeName);\n if (!(await fs.pathExists(themeRoot))) return undefined;\n const files = await readThemeFiles(themeRoot);\n return hashStable(files);\n}\n\nfunction getThemeName(\n theme: ResolvedSilicaConfig[\"theme\"],\n): string | undefined {\n if (typeof theme === \"string\") return theme;\n if (typeof theme === \"object\" && theme !== null) return theme.name;\n return undefined;\n}\n\nasync function readThemeFiles(\n root: string,\n current = root,\n): Promise<Array<{ path: string; content: string }>> {\n const entries = await fs.readdir(current, { withFileTypes: true });\n const results: Array<{ path: string; content: string }> = [];\n for (const entry of entries.sort((left, right) =>\n left.name.localeCompare(right.name),\n )) {\n const absolutePath = path.join(current, entry.name);\n if (entry.isDirectory()) {\n results.push(...(await readThemeFiles(root, absolutePath)));\n } else if (entry.isFile()) {\n results.push({\n path: normalizeGitPath(path.relative(root, absolutePath)),\n content: await fs.readFile(absolutePath, \"utf8\"),\n });\n }\n }\n return results;\n}\n\nexport async function getGitDates(\n projectRoot: string,\n relativePath: string,\n): Promise<{ created?: Date; modified?: Date }> {\n return (\n (\n await getGitDatesForFiles(projectRoot, [normalizeGitPath(relativePath)])\n ).get(normalizeGitPath(relativePath)) ?? {}\n );\n}\n\nasync function getGitDatesForFiles(\n projectRoot: string,\n relativePaths: string[],\n): Promise<Map<string, { created?: Date; modified?: Date }>> {\n const wanted = new Set(relativePaths.map(normalizeGitPath));\n const datesByPath = new Map<string, { created?: Date; modified?: Date }>();\n if (wanted.size === 0) return datesByPath;\n\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"log\", \"--format=__SILICA_COMMIT__%aI\", \"--name-only\", \"--\", ...wanted],\n {\n cwd: projectRoot,\n timeout: 2_000,\n },\n );\n let commitDate: Date | undefined;\n for (const line of stdout.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n if (trimmed.startsWith(\"__SILICA_COMMIT__\")) {\n const parsed = new Date(trimmed.slice(\"__SILICA_COMMIT__\".length));\n commitDate = Number.isNaN(parsed.valueOf()) ? undefined : parsed;\n continue;\n }\n const relativePath = normalizeGitPath(trimmed);\n if (!commitDate || !wanted.has(relativePath)) continue;\n const dates = datesByPath.get(relativePath) ?? {};\n dates.modified ??= commitDate;\n dates.created = commitDate;\n datesByPath.set(relativePath, dates);\n }\n } catch {\n return datesByPath;\n }\n return datesByPath;\n}\n\nfunction normalizeGitPath(relativePath: string): string {\n return relativePath.replace(/\\\\/g, \"/\");\n}\n\nfunction hashString(value: string): string {\n return crypto.createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction hashStable(value: unknown): string {\n return hashString(stableStringify(value));\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === undefined) return \"undefined\";\n if (value instanceof Date) return JSON.stringify(value.toISOString());\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n if (value && typeof value === \"object\") {\n const entries = Object.entries(value)\n .filter(([, entryValue]) => typeof entryValue !== \"function\")\n .sort(([left], [right]) => left.localeCompare(right));\n return `{${entries\n .map(\n ([key, entryValue]) =>\n `${JSON.stringify(key)}:${stableStringify(entryValue)}`,\n )\n .join(\",\")}}`;\n }\n return JSON.stringify(value);\n}\n\nfunction filterPublished(\n files: ContentMarkdownFile[],\n config: ResolvedSilicaConfig,\n): ContentMarkdownFile[] {\n return files.filter((file) => {\n if (config.filters.removeDrafts && file.frontmatter.draft === true)\n return false;\n if (config.filters.explicitPublish && file.frontmatter.publish !== true)\n return false;\n return true;\n });\n}\n\nfunction makeManifest(\n config: ResolvedSilicaConfig,\n entries: ManifestEntry[],\n): Manifest {\n const sorted = [...entries].sort(compareManifestEntries);\n return {\n version: 1,\n generatedAt: new Date().toISOString(),\n contentDir: config.contentDir,\n allSlugs: sorted.map((entry) => entry.slug),\n entries: sorted,\n bySlug: Object.fromEntries(sorted.map((entry) => [entry.slug, entry])),\n };\n}\n\nfunction compareManifestEntries(a: ManifestEntry, b: ManifestEntry): number {\n if (a.sortKey || b.sortKey) {\n return (\n (a.sortKey ?? fallbackSortKey(a.slug)).localeCompare(\n b.sortKey ?? fallbackSortKey(b.slug),\n ) || a.slug.localeCompare(b.slug)\n );\n }\n\n return a.slug.localeCompare(b.slug);\n}\n\nfunction fallbackSortKey(slug: string): string {\n return slug\n .split(\"/\")\n .map((segment) => `~~~~~~~~~~:${segment}`)\n .join(\"/\");\n}\n\nfunction makeGraph(\n links: Record<string, string[]>,\n brokenLinks: BrokenLink[],\n): Graph {\n const backlinks: Record<string, string[]> = {};\n for (const [source, targets] of Object.entries(links)) {\n links[source] = [...new Set(targets)].sort();\n for (const target of targets) {\n backlinks[target] ??= [];\n backlinks[target]!.push(source);\n }\n }\n\n for (const [target, sources] of Object.entries(backlinks)) {\n backlinks[target] = [...new Set(sources)].sort();\n }\n\n return {\n version: 1,\n links,\n backlinks,\n brokenLinks,\n };\n}\n\nasync function copyAssets(\n projectRoot: string,\n config: ResolvedSilicaConfig,\n assets: Array<{ absolutePath: string; assetPath: string }>,\n): Promise<void> {\n const destinationRoot = path.join(projectRoot, \".silica/next/public/silica\");\n await fs.emptyDir(destinationRoot);\n for (const asset of assets) {\n await fs.ensureDir(\n path.dirname(path.join(destinationRoot, asset.assetPath)),\n );\n await fs.copyFile(\n asset.absolutePath,\n path.join(destinationRoot, asset.assetPath),\n );\n }\n\n await fs.ensureDir(path.join(projectRoot, \".silica/next/public\"));\n await fs.writeFile(path.join(destinationRoot, \".gitkeep\"), \"\");\n}\n\nasync function writeSitemapAndRobots(\n projectRoot: string,\n config: ResolvedSilicaConfig,\n manifest: Manifest,\n): Promise<void> {\n const publicRoot = path.join(projectRoot, \".silica/next/public\");\n await fs.ensureDir(publicRoot);\n const baseUrl = (config.baseUrl ?? \"http://localhost:3000\").replace(\n /\\/$/,\n \"\",\n );\n const urls = manifest.entries\n .filter(isListedEntry)\n .map(\n (entry) => ` <url><loc>${baseUrl}${slugToHref(entry.slug)}</loc></url>`,\n )\n .join(\"\\n\");\n if (!(await fs.pathExists(path.join(projectRoot, \"public/sitemap.xml\")))) {\n await fs.writeFile(\n path.join(publicRoot, \"sitemap.xml\"),\n `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${urls}\\n</urlset>\\n`,\n );\n }\n if (!(await fs.pathExists(path.join(projectRoot, \"public/robots.txt\")))) {\n await fs.writeFile(\n path.join(publicRoot, \"robots.txt\"),\n `User-agent: *\\nAllow: /\\nSitemap: ${baseUrl}/sitemap.xml\\n`,\n );\n }\n}\n\nfunction getDate(value: unknown): Date | undefined {\n if (value instanceof Date) return value;\n if (typeof value === \"string\" || typeof value === \"number\") {\n const parsed = new Date(value);\n if (!Number.isNaN(parsed.valueOf())) return parsed;\n }\n return undefined;\n}\n\nexport function isListedEntry(entry: ManifestEntry): boolean {\n return entry.frontmatter.listed !== false;\n}\n\nfunction stringifyDate(value?: Date): string | undefined {\n return value?.toISOString();\n}\n\nfunction titleFromFilePath(\n relativePath: string,\n ordering: ResolvedSilicaConfig[\"ordering\"],\n): string {\n const stem = path.posix\n .basename(normalizeGitPath(relativePath))\n .replace(/\\.(md|markdown|mdx)$/i, \"\");\n const title = ordering.numericPrefixes ? stripNumericPrefix(stem) : stem;\n return /^index$/i.test(title) ? \"Home\" : title;\n}\n","import path from \"node:path\";\nimport Database from \"better-sqlite3\";\nimport fs from \"fs-extra\";\nimport {\n buildSearchTables,\n makeExcerpt,\n type SearchRecord,\n} from \"@silicajs/search\";\nimport type { ContentAssetFile } from \"./files.js\";\nimport type {\n Graph,\n Manifest,\n ManifestEntry,\n PrerenderManifest,\n RenderCacheState,\n ResolvedSilicaConfig,\n} from \"./types.js\";\nimport { normalizeAssetReference } from \"./path.js\";\n\nexport const VAULT_DATABASE_FILENAME = \"vault.db\";\nexport const VAULT_DATABASE_VERSION = \"2\";\n\nexport type VaultDbBuildInput = {\n config: ResolvedSilicaConfig;\n manifest: Manifest;\n graph: Graph;\n renderHashes: Record<string, string>;\n cacheState: RenderCacheState;\n prerender: PrerenderManifest;\n searchRecords: SearchRecord[];\n assets: Array<Pick<ContentAssetFile, \"sourcePath\" | \"assetPath\">>;\n};\n\nexport type VaultDbNote = {\n slug: string;\n file: string;\n sourcePath: string;\n title: string;\n menuLabel: string;\n description?: string;\n generatedDescription?: string;\n frontmatter: Record<string, unknown>;\n tags: string[];\n created?: string;\n modified?: string;\n sortKey?: string;\n listed: boolean;\n contentHash: string;\n renderHash: string;\n prerender: boolean;\n};\n\nexport async function writeVaultDatabase(\n projectRoot: string,\n input: VaultDbBuildInput,\n): Promise<string> {\n const silicaRoot = path.join(projectRoot, \".silica\");\n await fs.ensureDir(silicaRoot);\n\n const databasePath = path.join(silicaRoot, VAULT_DATABASE_FILENAME);\n const temporaryPath = path.join(silicaRoot, `${VAULT_DATABASE_FILENAME}.tmp`);\n await removeDatabaseFiles(temporaryPath);\n\n const db = new Database(temporaryPath);\n try {\n db.pragma(\"journal_mode = DELETE\");\n db.pragma(\"foreign_keys = ON\");\n db.pragma(\"synchronous = OFF\");\n createVaultDatabaseSchema(db);\n populateVaultDatabase(db, input);\n db.exec(\"VACUUM\");\n } finally {\n db.close();\n }\n\n await removeDatabaseFiles(databasePath);\n await fs.rename(temporaryPath, databasePath);\n await removeDatabaseSidecars(temporaryPath);\n return databasePath;\n}\n\nexport function createVaultDatabaseSchema(db: Database.Database): void {\n db.exec(`\n CREATE TABLE vault_metadata (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\n CREATE TABLE notes (\n slug TEXT PRIMARY KEY,\n file TEXT NOT NULL,\n source_path TEXT NOT NULL,\n title TEXT NOT NULL,\n menu_label TEXT NOT NULL,\n description TEXT,\n generated_description TEXT,\n frontmatter_json TEXT NOT NULL,\n tags_json TEXT NOT NULL,\n search_excerpt TEXT NOT NULL DEFAULT '',\n created TEXT,\n modified TEXT,\n sort_key TEXT,\n listed INTEGER NOT NULL,\n content_hash TEXT NOT NULL,\n render_hash TEXT NOT NULL,\n prerender INTEGER NOT NULL\n );\n\n CREATE TABLE note_tags (\n slug TEXT NOT NULL,\n tag TEXT NOT NULL,\n PRIMARY KEY (slug, tag),\n FOREIGN KEY (slug) REFERENCES notes(slug) ON DELETE CASCADE\n );\n\n CREATE TABLE links (\n source_slug TEXT NOT NULL,\n target_slug TEXT NOT NULL,\n kind TEXT NOT NULL CHECK (kind IN ('link', 'embed')),\n PRIMARY KEY (source_slug, target_slug, kind)\n );\n\n CREATE TABLE broken_links (\n source_slug TEXT NOT NULL,\n target TEXT NOT NULL\n );\n\n CREATE TABLE slug_aliases (\n strategy_key TEXT NOT NULL,\n alias TEXT NOT NULL,\n slug TEXT NOT NULL,\n sort_key TEXT,\n PRIMARY KEY (strategy_key, alias, slug)\n );\n\n CREATE TABLE asset_aliases (\n strategy_key TEXT NOT NULL,\n alias TEXT NOT NULL,\n asset_path TEXT NOT NULL,\n sort_key TEXT,\n PRIMARY KEY (strategy_key, alias, asset_path)\n );\n\n CREATE INDEX notes_prerender_idx ON notes(prerender, slug);\n CREATE INDEX notes_listed_sort_idx ON notes(listed, sort_key, slug);\n CREATE INDEX links_target_idx ON links(target_slug, kind, source_slug);\n CREATE INDEX links_source_idx ON links(source_slug, kind, target_slug);\n CREATE INDEX note_tags_tag_idx ON note_tags(tag, slug);\n CREATE INDEX slug_aliases_lookup_idx\n ON slug_aliases(strategy_key, alias, sort_key, slug);\n CREATE INDEX asset_aliases_lookup_idx\n ON asset_aliases(strategy_key, alias, sort_key, asset_path);\n `);\n}\n\nexport function populateVaultDatabase(\n db: Database.Database,\n input: VaultDbBuildInput,\n): void {\n const prerenderSlugs = new Set(input.prerender.slugs);\n const searchBySlug = new Map(\n input.searchRecords.map((record) => [record.slug, record]),\n );\n\n const insertMetadata = db.prepare(`\n INSERT INTO vault_metadata (key, value) VALUES (?, ?)\n `);\n const insertNote = db.prepare(`\n INSERT INTO notes (\n slug,\n file,\n source_path,\n title,\n menu_label,\n description,\n generated_description,\n frontmatter_json,\n tags_json,\n search_excerpt,\n created,\n modified,\n sort_key,\n listed,\n content_hash,\n render_hash,\n prerender\n )\n VALUES (\n @slug,\n @file,\n @sourcePath,\n @title,\n @menuLabel,\n @description,\n @generatedDescription,\n @frontmatterJson,\n @tagsJson,\n @searchExcerpt,\n @created,\n @modified,\n @sortKey,\n @listed,\n @contentHash,\n @renderHash,\n @prerender\n )\n `);\n const insertTag = db.prepare(`\n INSERT OR IGNORE INTO note_tags (slug, tag) VALUES (?, ?)\n `);\n const insertLink = db.prepare(`\n INSERT OR IGNORE INTO links (source_slug, target_slug, kind)\n VALUES (?, ?, ?)\n `);\n const insertBrokenLink = db.prepare(`\n INSERT INTO broken_links (source_slug, target) VALUES (?, ?)\n `);\n const insertAlias = db.prepare(`\n INSERT OR IGNORE INTO slug_aliases (strategy_key, alias, slug, sort_key)\n VALUES (?, ?, ?, ?)\n `);\n const insertAssetAlias = db.prepare(`\n INSERT OR IGNORE INTO asset_aliases (\n strategy_key,\n alias,\n asset_path,\n sort_key\n )\n VALUES (?, ?, ?, ?)\n `);\n\n const insertAll = db.transaction(() => {\n insertMetadata.run(\"version\", VAULT_DATABASE_VERSION);\n insertMetadata.run(\"generatedAt\", input.manifest.generatedAt);\n insertMetadata.run(\"contentDir\", input.manifest.contentDir);\n insertMetadata.run(\"configJson\", JSON.stringify(input.config));\n insertMetadata.run(\n \"renderEnvironmentHash\",\n input.cacheState.renderEnvironmentHash,\n );\n insertMetadata.run(\"configHash\", input.cacheState.configHash);\n insertMetadata.run(\"navigationHash\", input.cacheState.navigationHash);\n insertMetadata.run(\"tagIndexHash\", input.cacheState.tagIndexHash);\n insertMetadata.run(\"rendererVersion\", input.cacheState.rendererVersion);\n insertMetadata.run(\"cacheStateJson\", JSON.stringify(input.cacheState));\n\n for (const entry of input.manifest.entries) {\n const searchRecord = searchBySlug.get(entry.slug);\n insertNote.run({\n slug: entry.slug,\n file: entry.file,\n sourcePath: entry.sourcePath,\n title: entry.title,\n menuLabel: entry.menuLabel,\n description: entry.description,\n generatedDescription: entry.generatedDescription,\n frontmatterJson: JSON.stringify(entry.frontmatter),\n tagsJson: JSON.stringify(entry.tags),\n searchExcerpt: searchRecord\n ? makeExcerpt(\n searchRecord.content,\n searchRecord.description ?? searchRecord.title,\n )\n : \"\",\n created: entry.created,\n modified: entry.modified,\n sortKey: entry.sortKey,\n listed: isListedEntry(entry) ? 1 : 0,\n contentHash: entry.contentHash,\n renderHash: input.renderHashes[entry.slug] ?? \"missing\",\n prerender: prerenderSlugs.has(entry.slug) ? 1 : 0,\n });\n\n for (const tag of entry.tags) {\n for (const hierarchyTag of tagHierarchy(tag)) {\n insertTag.run(entry.slug, hierarchyTag);\n }\n }\n }\n\n for (const [source, targets] of Object.entries(input.graph.links)) {\n for (const target of targets) {\n insertLink.run(source, target, \"link\");\n }\n }\n for (const entry of input.manifest.entries) {\n for (const target of entry.embeds) {\n insertLink.run(entry.slug, target, \"embed\");\n }\n }\n for (const brokenLink of input.graph.brokenLinks) {\n insertBrokenLink.run(brokenLink.source, brokenLink.target);\n }\n for (const entry of input.manifest.entries) {\n for (const [strategy, alias] of makeSlugAliases(entry.slug)) {\n insertAlias.run(\n strategy,\n alias,\n entry.slug,\n entry.sortKey ?? entry.slug,\n );\n }\n }\n for (const asset of input.assets) {\n for (const [strategy, alias] of makeAssetAliases(\n asset.sourcePath,\n input.config.ordering,\n )) {\n insertAssetAlias.run(strategy, alias, asset.assetPath, asset.assetPath);\n }\n }\n });\n\n insertAll();\n buildSearchTables(db, input.searchRecords);\n}\n\nfunction isListedEntry(entry: ManifestEntry): boolean {\n return entry.frontmatter.listed !== false;\n}\n\nfunction tagHierarchy(tag: string): string[] {\n const normalized = tag.trim().replace(/^#/, \"\").toLowerCase();\n const segments = normalized.split(\"/\").filter(Boolean);\n return segments.map((_, index) => segments.slice(0, index + 1).join(\"/\"));\n}\n\nfunction makeSlugAliases(slug: string): Array<[string, string]> {\n const aliases = new Map<string, string>();\n const simplified = slug === \"index\" ? \"\" : slug.replace(/\\/index$/, \"\");\n const basename = simplified.split(\"/\").at(-1) ?? \"\";\n aliases.set(`absolute:${slug}`, slug);\n if (simplified) aliases.set(`absolute:${simplified}`, simplified);\n if (basename) aliases.set(`shortest:${basename}`, basename);\n return [...aliases.entries()].map(([key, alias]) => [\n key.split(\":\")[0] ?? \"shortest\",\n alias,\n ]);\n}\n\nfunction makeAssetAliases(\n sourcePath: string,\n ordering: ResolvedSilicaConfig[\"ordering\"],\n): Array<[string, string]> {\n const aliases = new Map<string, string>();\n const normalized = normalizeAssetReference(sourcePath, ordering);\n const basename = normalizeAssetReference(\n path.posix.basename(sourcePath),\n ordering,\n );\n if (normalized) aliases.set(`absolute:${normalized}`, normalized);\n if (basename) aliases.set(`shortest:${basename}`, basename);\n return [...aliases.entries()].map(([key, alias]) => [\n key.split(\":\")[0] ?? \"shortest\",\n alias,\n ]);\n}\n\nasync function removeDatabaseFiles(databasePath: string): Promise<void> {\n await fs.remove(databasePath);\n await removeDatabaseSidecars(databasePath);\n}\n\nasync function removeDatabaseSidecars(databasePath: string): Promise<void> {\n await Promise.all([\n fs.remove(`${databasePath}-wal`),\n fs.remove(`${databasePath}-shm`),\n fs.remove(`${databasePath}-journal`),\n ]);\n}\n"],"mappings":"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","names":["path","path","path","fs","path","fs","path","fs","path","fs","isListedEntry","selected"]}
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  analyzeMarkdown,
3
3
  asFullSlug,
4
+ createAssetResolutionIndex,
4
5
  createWikiLinkResolutionIndex
5
- } from "./chunk-BEINUFYU.js";
6
+ } from "./chunk-2EKH4A4V.js";
6
7
 
7
8
  // src/precompute-worker.ts
8
9
  import { parentPort, workerData } from "worker_threads";
@@ -11,6 +12,7 @@ var wikilinkIndex = createWikiLinkResolutionIndex(
11
12
  data.allSlugs,
12
13
  data.ordering
13
14
  );
15
+ var assetIndex = createAssetResolutionIndex(data.assetEntries, data.ordering);
14
16
  parentPort?.on("message", async (message) => {
15
17
  try {
16
18
  const results = [];
@@ -19,7 +21,9 @@ parentPort?.on("message", async (message) => {
19
21
  index: file.index,
20
22
  analysis: await analyzeMarkdown(file.raw, {
21
23
  slug: asFullSlug(file.slug),
24
+ sourcePath: file.sourcePath,
22
25
  wikilinkIndex,
26
+ assetIndex,
23
27
  assetBaseUrl: "/silica",
24
28
  wikilinkStrategy: data.wikilinkStrategy,
25
29
  tags: data.tags,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/precompute-worker.ts"],"sourcesContent":["import { parentPort, workerData } from \"node:worker_threads\";\nimport { asFullSlug, createWikiLinkResolutionIndex } from \"./path.js\";\nimport { analyzeMarkdown } from \"./pipeline/index.js\";\nimport type { AnalyzeResult, ResolvedSilicaConfig } from \"./types.js\";\n\ntype WorkerData = {\n allSlugs: string[];\n wikilinkStrategy: ResolvedSilicaConfig[\"wikilinks\"][\"strategy\"];\n tags: ResolvedSilicaConfig[\"tags\"];\n ordering: ResolvedSilicaConfig[\"ordering\"];\n};\n\ntype AnalysisWorkerFile = {\n index: number;\n slug: string;\n raw: string;\n};\n\ntype AnalysisWorkerMessage = {\n id: number;\n files: AnalysisWorkerFile[];\n};\n\ntype AnalysisWorkerResult = {\n id: number;\n results?: Array<{ index: number; analysis: AnalyzeResult }>;\n error?: string;\n};\n\nconst data = workerData as WorkerData;\nconst wikilinkIndex = createWikiLinkResolutionIndex(\n data.allSlugs,\n data.ordering,\n);\n\nparentPort?.on(\"message\", async (message: AnalysisWorkerMessage) => {\n try {\n const results: NonNullable<AnalysisWorkerResult[\"results\"]> = [];\n for (const file of message.files) {\n results.push({\n index: file.index,\n analysis: await analyzeMarkdown(file.raw, {\n slug: asFullSlug(file.slug),\n wikilinkIndex,\n assetBaseUrl: \"/silica\",\n wikilinkStrategy: data.wikilinkStrategy,\n tags: data.tags,\n ordering: data.ordering,\n }),\n });\n }\n parentPort?.postMessage({\n id: message.id,\n results,\n } satisfies AnalysisWorkerResult);\n } catch (error) {\n parentPort?.postMessage({\n id: message.id,\n error:\n error instanceof Error ? error.stack || error.message : String(error),\n } satisfies AnalysisWorkerResult);\n }\n});\n"],"mappings":";;;;;;;AAAA,SAAS,YAAY,kBAAkB;AA6BvC,IAAM,OAAO;AACb,IAAM,gBAAgB;AAAA,EACpB,KAAK;AAAA,EACL,KAAK;AACP;AAEA,YAAY,GAAG,WAAW,OAAO,YAAmC;AAClE,MAAI;AACF,UAAM,UAAwD,CAAC;AAC/D,eAAW,QAAQ,QAAQ,OAAO;AAChC,cAAQ,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,QACZ,UAAU,MAAM,gBAAgB,KAAK,KAAK;AAAA,UACxC,MAAM,WAAW,KAAK,IAAI;AAAA,UAC1B;AAAA,UACA,cAAc;AAAA,UACd,kBAAkB,KAAK;AAAA,UACvB,MAAM,KAAK;AAAA,UACX,UAAU,KAAK;AAAA,QACjB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AACA,gBAAY,YAAY;AAAA,MACtB,IAAI,QAAQ;AAAA,MACZ;AAAA,IACF,CAAgC;AAAA,EAClC,SAAS,OAAO;AACd,gBAAY,YAAY;AAAA,MACtB,IAAI,QAAQ;AAAA,MACZ,OACE,iBAAiB,QAAQ,MAAM,SAAS,MAAM,UAAU,OAAO,KAAK;AAAA,IACxE,CAAgC;AAAA,EAClC;AACF,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/precompute-worker.ts"],"sourcesContent":["import { parentPort, workerData } from \"node:worker_threads\";\nimport {\n asFullSlug,\n createAssetResolutionIndex,\n createWikiLinkResolutionIndex,\n} from \"./path.js\";\nimport { analyzeMarkdown } from \"./pipeline/index.js\";\nimport type { AnalyzeResult, ResolvedSilicaConfig } from \"./types.js\";\n\ntype WorkerData = {\n allSlugs: string[];\n assetEntries: Array<{ sourcePath: string; assetPath: string }>;\n wikilinkStrategy: ResolvedSilicaConfig[\"wikilinks\"][\"strategy\"];\n tags: ResolvedSilicaConfig[\"tags\"];\n ordering: ResolvedSilicaConfig[\"ordering\"];\n};\n\ntype AnalysisWorkerFile = {\n index: number;\n slug: string;\n sourcePath: string;\n raw: string;\n};\n\ntype AnalysisWorkerMessage = {\n id: number;\n files: AnalysisWorkerFile[];\n};\n\ntype AnalysisWorkerResult = {\n id: number;\n results?: Array<{ index: number; analysis: AnalyzeResult }>;\n error?: string;\n};\n\nconst data = workerData as WorkerData;\nconst wikilinkIndex = createWikiLinkResolutionIndex(\n data.allSlugs,\n data.ordering,\n);\nconst assetIndex = createAssetResolutionIndex(data.assetEntries, data.ordering);\n\nparentPort?.on(\"message\", async (message: AnalysisWorkerMessage) => {\n try {\n const results: NonNullable<AnalysisWorkerResult[\"results\"]> = [];\n for (const file of message.files) {\n results.push({\n index: file.index,\n analysis: await analyzeMarkdown(file.raw, {\n slug: asFullSlug(file.slug),\n sourcePath: file.sourcePath,\n wikilinkIndex,\n assetIndex,\n assetBaseUrl: \"/silica\",\n wikilinkStrategy: data.wikilinkStrategy,\n tags: data.tags,\n ordering: data.ordering,\n }),\n });\n }\n parentPort?.postMessage({\n id: message.id,\n results,\n } satisfies AnalysisWorkerResult);\n } catch (error) {\n parentPort?.postMessage({\n id: message.id,\n error:\n error instanceof Error ? error.stack || error.message : String(error),\n } satisfies AnalysisWorkerResult);\n }\n});\n"],"mappings":";;;;;;;;AAAA,SAAS,YAAY,kBAAkB;AAmCvC,IAAM,OAAO;AACb,IAAM,gBAAgB;AAAA,EACpB,KAAK;AAAA,EACL,KAAK;AACP;AACA,IAAM,aAAa,2BAA2B,KAAK,cAAc,KAAK,QAAQ;AAE9E,YAAY,GAAG,WAAW,OAAO,YAAmC;AAClE,MAAI;AACF,UAAM,UAAwD,CAAC;AAC/D,eAAW,QAAQ,QAAQ,OAAO;AAChC,cAAQ,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,QACZ,UAAU,MAAM,gBAAgB,KAAK,KAAK;AAAA,UACxC,MAAM,WAAW,KAAK,IAAI;AAAA,UAC1B,YAAY,KAAK;AAAA,UACjB;AAAA,UACA;AAAA,UACA,cAAc;AAAA,UACd,kBAAkB,KAAK;AAAA,UACvB,MAAM,KAAK;AAAA,UACX,UAAU,KAAK;AAAA,QACjB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AACA,gBAAY,YAAY;AAAA,MACtB,IAAI,QAAQ;AAAA,MACZ;AAAA,IACF,CAAgC;AAAA,EAClC,SAAS,OAAO;AACd,gBAAY,YAAY;AAAA,MACtB,IAAI,QAAQ;AAAA,MACZ,OACE,iBAAiB,QAAQ,MAAM,SAAS,MAAM,UAAU,OAAO,KAAK;AAAA,IACxE,CAAgC;AAAA,EAClC;AACF,CAAC;","names":[]}
package/dist/runtime.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { h as RenderContext, A as AnalyzeResult, i as RenderResult } from './theme-BK5ZRXFG.js';
2
- export { B as BrokenLink, G as Graph, M as Manifest, b as ManifestEntry, c as MarkdownComponents, N as Navigation, d as NavigationEntry, e as PrerenderManifest, g as RenderCacheState, j as ResolvedSilicaConfig, m as SilicaCalloutProps, n as SilicaCodeBlockProps, p as SilicaEmbedProps, q as SilicaMermaidProps, w as SilicaTheme, T as ThemeBacklink, y as ThemeBreadcrumb, C as ThemeLayoutConfig, D as ThemePage, E as ThemePageProps, H as ThemeProviderComponent, I as ThemeRootLayoutProps, J as ThemeSiteLayoutProps, K as TocItem, W as WikiLinkResolutionIndex, O as asFullSlug, V as createWikiLinkResolutionIndex, X as hrefToSlug, _ as normalizeSlug, a0 as resolveRelative, a1 as resolveWikiLink, a2 as simplifySlug, a3 as slugToHref } from './theme-BK5ZRXFG.js';
1
+ import { j as RenderContext, A as AnalyzeResult, k as RenderResult } from './theme-DuygYyeF.js';
2
+ export { a as AssetResolutionEntry, b as AssetResolutionIndex, B as BrokenLink, G as Graph, M as Manifest, d as ManifestEntry, e as MarkdownComponents, N as Navigation, f as NavigationEntry, g as PrerenderManifest, i as RenderCacheState, l as ResolvedSilicaConfig, o as SilicaCalloutProps, p as SilicaCodeBlockProps, r as SilicaEmbedProps, s as SilicaMermaidProps, y as SilicaTheme, T as ThemeBacklink, C as ThemeBreadcrumb, E as ThemeLayoutConfig, H as ThemePage, I as ThemePageProps, J as ThemeProviderComponent, K as ThemeRootLayoutProps, L as ThemeSiteLayoutProps, O as TocItem, W as WikiLinkResolutionIndex, U as asFullSlug, Y as createAssetResolutionIndex, Z as createWikiLinkResolutionIndex, _ as hrefToSlug, a0 as normalizeAssetReference, a2 as normalizeSlug, a4 as resolveAssetPath, a5 as resolveRelative, a6 as resolveRelativeAsset, a7 as resolveWikiLink, a8 as simplifySlug, a9 as slugToHref, aa as slugifyAssetPath } from './theme-DuygYyeF.js';
3
3
  import 'react';
4
4
  import '@silicajs/search';
5
5
  import '@silicajs/remark-obsidian';
package/dist/runtime.js CHANGED
@@ -7,24 +7,30 @@ import {
7
7
  import {
8
8
  analyzeMarkdown,
9
9
  asFullSlug,
10
+ createAssetResolutionIndex,
10
11
  createWikiLinkResolutionIndex,
11
12
  generateDescriptionFromContent,
12
13
  getDescription,
13
14
  getMetaDescription,
14
15
  getTitle,
15
16
  hrefToSlug,
17
+ normalizeAssetReference,
16
18
  normalizeSlug,
17
19
  renderMarkdown,
18
20
  renderMarkdownHtml,
21
+ resolveAssetPath,
19
22
  resolveRelative,
23
+ resolveRelativeAsset,
20
24
  resolveWikiLink,
21
25
  simplifySlug,
22
26
  slugToHref,
27
+ slugifyAssetPath,
23
28
  tagToHref
24
- } from "./chunk-BEINUFYU.js";
29
+ } from "./chunk-2EKH4A4V.js";
25
30
  export {
26
31
  analyzeMarkdown,
27
32
  asFullSlug,
33
+ createAssetResolutionIndex,
28
34
  createWikiLinkResolutionIndex,
29
35
  formatPropertyLabel,
30
36
  formatPropertyValue,
@@ -35,13 +41,17 @@ export {
35
41
  getPageProperties,
36
42
  getTitle,
37
43
  hrefToSlug,
44
+ normalizeAssetReference,
38
45
  normalizeSlug,
39
46
  renderMarkdown,
40
47
  renderMarkdownHtml,
48
+ resolveAssetPath,
41
49
  resolveRelative,
50
+ resolveRelativeAsset,
42
51
  resolveWikiLink,
43
52
  simplifySlug,
44
53
  slugToHref,
54
+ slugifyAssetPath,
45
55
  tagToHref
46
56
  };
47
57
  //# sourceMappingURL=runtime.js.map
@@ -25,6 +25,14 @@ type WikiLinkResolutionIndex = {
25
25
  candidates: ReadonlySet<string>;
26
26
  uniqueSlugByBasename: ReadonlyMap<string, string | null>;
27
27
  };
28
+ type AssetResolutionIndex = {
29
+ assetPathBySourcePath: ReadonlyMap<string, string | null>;
30
+ assetPathByBasename: ReadonlyMap<string, string | null>;
31
+ };
32
+ type AssetResolutionEntry = {
33
+ sourcePath: string;
34
+ assetPath: string;
35
+ };
28
36
  declare function asFilePath(value: string): FilePath;
29
37
  declare function asFullSlug(value: string): FullSlug;
30
38
  declare function asSimpleSlug(value: string): SimpleSlug;
@@ -32,6 +40,8 @@ declare function asRelativeURL(value: string): RelativeURL;
32
40
  declare function normalizePath(value: string): string;
33
41
  declare function slugifySegment(segment: string, options?: SlugifyOptions): string;
34
42
  declare function normalizeSlug(value: string, options?: SlugifyOptions): string;
43
+ declare function normalizeAssetReference(value: string, options?: SlugifyOptions): string;
44
+ declare function slugifyAssetPath(sourcePath: string, options?: SlugifyOptions): string;
35
45
  declare function slugifyFilePath(filePath: FilePath | string, contentDir?: string, options?: SlugifyOptions): FullSlug;
36
46
  declare function simplifySlug(slug: FullSlug | string): SimpleSlug;
37
47
  declare function slugToHref(slug: FullSlug | string): string;
@@ -39,7 +49,10 @@ declare function hrefToSlug(href: string): FullSlug;
39
49
  declare function pathToRoot(slug: FullSlug | string): RelativeURL;
40
50
  declare function resolveRelative(currentSlug: FullSlug | string, target: string, options?: SlugifyOptions): FullSlug;
41
51
  declare function createWikiLinkResolutionIndex(allSlugs: readonly string[], options?: SlugifyOptions): WikiLinkResolutionIndex;
52
+ declare function createAssetResolutionIndex(assets: readonly AssetResolutionEntry[], options?: SlugifyOptions): AssetResolutionIndex;
42
53
  declare function resolveWikiLink(currentSlug: FullSlug | string, target: string, index: WikiLinkResolutionIndex, strategy?: "absolute" | "relative" | "shortest", options?: SlugifyOptions): FullSlug | undefined;
54
+ declare function resolveAssetPath(currentSourcePath: string, target: string, index: AssetResolutionIndex, strategy?: "absolute" | "relative" | "shortest", options?: SlugifyOptions): string | undefined;
55
+ declare function resolveRelativeAsset(currentSourcePath: string, target: string, options?: SlugifyOptions): string;
43
56
  declare function joinSegments(...segments: string[]): string;
44
57
 
45
58
  type ThemeConfig = "default" | string | {
@@ -163,7 +176,7 @@ type ManifestEntry = {
163
176
  generatedDescription?: string;
164
177
  tags: string[];
165
178
  file: string;
166
- relativeFile: string;
179
+ sourcePath: string;
167
180
  sortKey?: string;
168
181
  created?: string;
169
182
  modified?: string;
@@ -200,8 +213,11 @@ type BrokenLink = {
200
213
  };
201
214
  type RenderContext = {
202
215
  slug: FullSlug | string;
216
+ sourcePath?: string;
203
217
  wikilinkIndex?: WikiLinkResolutionIndex;
204
218
  resolveWikiLink?: (currentSlug: FullSlug | string, target: string) => string | undefined;
219
+ assetIndex?: AssetResolutionIndex;
220
+ resolveAsset?: (currentSourcePath: string, target: string) => string | undefined;
205
221
  assetBaseUrl?: string;
206
222
  resolveEmbed?: (target: ObsidianLinkTarget) => Promise<string | undefined> | string | undefined;
207
223
  embedDepth?: number;
@@ -329,4 +345,4 @@ type SilicaTheme = {
329
345
  components?: MarkdownComponents;
330
346
  };
331
347
 
332
- export { pathToRoot as $, type AnalyzeResult as A, type BrokenLink as B, type ThemeLayoutConfig as C, type ThemePage as D, type ThemePageProps as E, type FilePath as F, type Graph as G, type ThemeProviderComponent as H, type ThemeRootLayoutProps as I, type ThemeSiteLayoutProps as J, type TocItem as K, asFilePath as L, type Manifest as M, type Navigation as N, asFullSlug as O, type PrecomputeResult as P, asRelativeURL as Q, type RelativeURL as R, type SilicaAuthConfig as S, type ThemeBacklink as T, asSimpleSlug as U, createWikiLinkResolutionIndex as V, type WikiLinkResolutionIndex as W, hrefToSlug as X, joinSegments as Y, normalizePath as Z, normalizeSlug as _, type FullSlug as a, resolveRelative as a0, resolveWikiLink as a1, simplifySlug as a2, slugToHref as a3, slugifyFilePath as a4, slugifySegment as a5, type ManifestEntry as b, type MarkdownComponents as c, type NavigationEntry as d, type PrerenderManifest as e, type PrerenderSelectorContext as f, type RenderCacheState as g, type RenderContext as h, type RenderResult as i, type ResolvedSilicaConfig as j, type ResolvedSilicaPrerenderConfig as k, type ResolvedSilicaRenderConfig as l, type SilicaCalloutProps as m, type SilicaCodeBlockProps as n, type SilicaConfig as o, type SilicaEmbedProps as p, type SilicaMermaidProps as q, type SilicaNextConfig as r, type SilicaNextConfigOverride as s, type SilicaPrerenderConfig as t, type SilicaPrerenderSelectionOptions as u, type SilicaRenderConfig as v, type SilicaTheme as w, type SimpleSlug as x, type ThemeBreadcrumb as y, type ThemeConfig as z };
348
+ export { joinSegments as $, type AnalyzeResult as A, type BrokenLink as B, type ThemeBreadcrumb as C, type ThemeConfig as D, type ThemeLayoutConfig as E, type FilePath as F, type Graph as G, type ThemePage as H, type ThemePageProps as I, type ThemeProviderComponent as J, type ThemeRootLayoutProps as K, type ThemeSiteLayoutProps as L, type Manifest as M, type Navigation as N, type TocItem as O, type PrecomputeResult as P, asFilePath as Q, type RelativeURL as R, type SilicaAuthConfig as S, type ThemeBacklink as T, asFullSlug as U, asRelativeURL as V, type WikiLinkResolutionIndex as W, asSimpleSlug as X, createAssetResolutionIndex as Y, createWikiLinkResolutionIndex as Z, hrefToSlug as _, type AssetResolutionEntry as a, normalizeAssetReference as a0, normalizePath as a1, normalizeSlug as a2, pathToRoot as a3, resolveAssetPath as a4, resolveRelative as a5, resolveRelativeAsset as a6, resolveWikiLink as a7, simplifySlug as a8, slugToHref as a9, slugifyAssetPath as aa, slugifyFilePath as ab, slugifySegment as ac, type AssetResolutionIndex as b, type FullSlug as c, type ManifestEntry as d, type MarkdownComponents as e, type NavigationEntry as f, type PrerenderManifest as g, type PrerenderSelectorContext as h, type RenderCacheState as i, type RenderContext as j, type RenderResult as k, type ResolvedSilicaConfig as l, type ResolvedSilicaPrerenderConfig as m, type ResolvedSilicaRenderConfig as n, type SilicaCalloutProps as o, type SilicaCodeBlockProps as p, type SilicaConfig as q, type SilicaEmbedProps as r, type SilicaMermaidProps as s, type SilicaNextConfig as t, type SilicaNextConfigOverride as u, type SilicaPrerenderConfig as v, type SilicaPrerenderSelectionOptions as w, type SilicaRenderConfig as x, type SilicaTheme as y, type SimpleSlug as z };
package/dist/theme.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import 'react';
2
- export { c as MarkdownComponents, m as SilicaCalloutProps, n as SilicaCodeBlockProps, p as SilicaEmbedProps, q as SilicaMermaidProps, w as SilicaTheme, T as ThemeBacklink, y as ThemeBreadcrumb, C as ThemeLayoutConfig, D as ThemePage, E as ThemePageProps, H as ThemeProviderComponent, I as ThemeRootLayoutProps, J as ThemeSiteLayoutProps } from './theme-BK5ZRXFG.js';
2
+ export { e as MarkdownComponents, o as SilicaCalloutProps, p as SilicaCodeBlockProps, r as SilicaEmbedProps, s as SilicaMermaidProps, y as SilicaTheme, T as ThemeBacklink, C as ThemeBreadcrumb, E as ThemeLayoutConfig, H as ThemePage, I as ThemePageProps, J as ThemeProviderComponent, K as ThemeRootLayoutProps, L as ThemeSiteLayoutProps } from './theme-DuygYyeF.js';
3
3
  import '@silicajs/search';
4
4
  import '@silicajs/remark-obsidian';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silicajs/core",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Markdown pipeline, slug system, and precompute artifacts for Silica.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -33,7 +33,7 @@
33
33
  "dependencies": {
34
34
  "@shikijs/rehype": "^4.1.0",
35
35
  "@silicajs/remark-obsidian": "^0.1.0",
36
- "@silicajs/search": "^0.3.0",
36
+ "@silicajs/search": "^0.3.1",
37
37
  "better-sqlite3": "^12.10.0",
38
38
  "fast-glob": "^3.3.3",
39
39
  "fs-extra": "^11.3.5",