@dirwell/core 0.0.1-alpha → 0.0.1
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/README.md +27 -2
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +1 -0
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +23 -14
- package/dist/index.mjs +476 -98
- package/dist/index.mjs.map +1 -1
- package/dist/{listing-CnkSglVT.d.mts → listing-B_6TbWuz.d.mts} +40 -3
- package/package.json +7 -2
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/filesystem.ts","../src/listing.ts","../src/filters.ts","../src/generator.ts","../src/html.ts","../src/file-identity.ts","../src/service.ts"],"sourcesContent":["import { lstat, readlink, realpath, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Stats } from \"node:fs\";\nimport type { EntryKind, FileMetadata, FileSystemEntry, SymlinkMetadata } from \"./model.ts\";\nfunction entryKind(stats: Stats): EntryKind {\n if (stats.isDirectory()) return \"directory\";\n if (stats.isFile()) return \"file\";\n if (stats.isSymbolicLink()) return \"symlink\";\n return \"other\";\n}\n\nfunction metadata(stats: Stats): FileMetadata {\n return {\n device: stats.dev,\n groupId: stats.gid,\n hardLinkCount: stats.nlink,\n inode: stats.ino,\n mode: stats.mode,\n ownerId: stats.uid,\n size: stats.size,\n times: {\n accessedAt: stats.atime.toISOString(),\n changedAt: stats.ctime.toISOString(),\n createdAt: stats.birthtime.toISOString(),\n modifiedAt: stats.mtime.toISOString(),\n },\n };\n}\n\nexport function isInsideRoot(rootPath: string, candidatePath: string): boolean {\n const relative = path.relative(rootPath, candidatePath);\n return (\n relative === \"\" ||\n (relative !== \"..\" && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative))\n );\n}\n\nexport async function describeEntry({\n absolutePath,\n relativePath,\n rootRealPath,\n ancestors,\n followSymlinks,\n selectedPaths,\n}: {\n absolutePath: string;\n relativePath: string;\n rootRealPath: string;\n ancestors: ReadonlySet<string>;\n followSymlinks: boolean;\n selectedPaths: ReadonlySet<string> | null;\n}): Promise<FileSystemEntry> {\n const linkStats = await lstat(absolutePath);\n const kind = entryKind(linkStats);\n let symlink: SymlinkMetadata | null = null;\n\n if (kind === \"symlink\") {\n const target = await readlink(absolutePath);\n let resolvedPath: string | null = null;\n let targetKind: Exclude<EntryKind, \"symlink\"> | null = null;\n let targetSize: number | null = null;\n try {\n resolvedPath = await realpath(absolutePath);\n const targetStats = await stat(absolutePath);\n targetKind = entryKind(targetStats) as Exclude<EntryKind, \"symlink\">;\n targetSize = targetStats.size;\n } catch {\n // Broken and inaccessible links are represented as data.\n }\n const isOutsideRoot = resolvedPath === null || !isInsideRoot(rootRealPath, resolvedPath);\n const isCycle = resolvedPath !== null && ancestors.has(resolvedPath);\n const targetRelativePath =\n resolvedPath !== null && !isOutsideRoot\n ? path.relative(rootRealPath, resolvedPath).split(path.sep).join(\"/\")\n : null;\n const isTargetExcluded =\n targetRelativePath !== null &&\n selectedPaths !== null &&\n !selectedPaths.has(targetRelativePath);\n symlink = {\n target,\n resolvedPath,\n targetRelativePath,\n targetKind,\n targetSize:\n isOutsideRoot || isTargetExcluded || targetKind === \"directory\" ? null : targetSize,\n isBroken: resolvedPath === null,\n isCycle,\n isOutsideRoot,\n isTargetExcluded,\n wasFollowed:\n followSymlinks &&\n targetKind === \"directory\" &&\n !isCycle &&\n !isOutsideRoot &&\n !isTargetExcluded,\n };\n }\n\n return {\n name: path.basename(absolutePath),\n absolutePath,\n relativePath,\n kind,\n metadata: metadata(linkStats),\n symlink,\n };\n}\n","import type { JsonObject } from \"./json.ts\";\nimport { createHash } from \"node:crypto\";\nimport type { EntryKind, FileSystemEntry, ThemeContext, SortOptions } from \"./model.ts\";\n\n/** Public transport fields only. Internal filesystem metadata must never be spread here. */\nexport interface ListingEntry {\n readonly presentation?: JsonObject;\n readonly id: string;\n readonly name: string;\n readonly kind: EntryKind;\n readonly href: string | null;\n readonly exitsExplorer: boolean;\n readonly size: number;\n readonly modifiedAt: string;\n readonly link: null | {\n readonly target: string;\n readonly targetKind: Exclude<EntryKind, \"symlink\"> | null;\n readonly targetSize: number | null;\n readonly unavailable: boolean;\n readonly cycle: boolean;\n };\n}\nexport interface ListingPlan {\n readonly html:\n | { readonly strategy: \"all\" }\n | { readonly strategy: \"paged\"; readonly pageSize: number };\n readonly data:\n | { readonly strategy: \"all\" }\n | { readonly strategy: \"blocks\"; readonly blockSize: number };\n}\nexport interface ListingPolicyContext {\n readonly operation?: \"build\" | \"server\";\n readonly directoryPath: string;\n readonly visibleCount: number;\n readonly dataBytes: number;\n readonly mode: \"ssg\" | \"mpa\";\n readonly supportsPagination: boolean;\n}\nexport type ListingPolicy = ListingPlan | ((context: ListingPolicyContext) => ListingPlan);\nexport interface ListingPage {\n readonly number: number;\n readonly count: number;\n readonly offset: number;\n readonly total: number;\n readonly href: string;\n readonly previousHref: string | null;\n readonly nextHref: string | null;\n}\nexport interface ListingContext {\n readonly revision: string;\n readonly manifestHref: string;\n readonly page: ListingPage;\n}\nexport interface ListingBlock {\n readonly version: 1;\n readonly revision: string;\n readonly offset: number;\n readonly total: number;\n readonly entries: readonly ListingEntry[];\n}\nexport interface ListingManifest {\n readonly version: 1;\n readonly revision: string;\n readonly directory: string;\n /** Resolve entry hrefs against this URL, resolved relative to the manifest URL. */\n readonly hrefBase: string;\n readonly total: number;\n readonly sort: Required<SortOptions>;\n /** Block hrefs are relative to the manifest URL. */\n readonly blocks: readonly {\n readonly href: string;\n readonly offset: number;\n readonly count: number;\n }[];\n}\n\nexport function projectListingEntry(\n entry: FileSystemEntry,\n context: Pick<ThemeContext, \"hrefFor\" | \"exitsExplorerFor\">,\n): ListingEntry {\n const link = entry.symlink;\n return {\n id: entry.relativePath,\n name: entry.name,\n kind: entry.kind,\n href: context.hrefFor(entry),\n exitsExplorer: context.exitsExplorerFor(entry),\n size: entry.metadata.size,\n modifiedAt: entry.metadata.times.modifiedAt,\n link:\n link === null\n ? null\n : {\n target: link.target,\n targetKind: link.targetKind,\n targetSize: link.targetSize ?? null,\n unavailable: link.isBroken || link.isOutsideRoot || Boolean(link.isTargetExcluded),\n cycle: link.isCycle,\n },\n };\n}\nfunction record(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\nfunction positiveInteger(value: unknown, key: string): void {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 1)\n throw new TypeError(`${key} must be a positive safe integer`);\n}\nexport function validateListingPlan(value: unknown): asserts value is ListingPlan {\n if (!record(value) || !record(value.html) || !record(value.data))\n throw new TypeError(\"listing must contain html and data plans\");\n if (value.html.strategy === \"paged\")\n positiveInteger(value.html.pageSize, \"listing.html.pageSize\");\n else if (value.html.strategy !== \"all\")\n throw new TypeError('listing.html.strategy must be \"all\" or \"paged\"');\n if (value.data.strategy === \"blocks\")\n positiveInteger(value.data.blockSize, \"listing.data.blockSize\");\n else if (value.data.strategy !== \"all\")\n throw new TypeError('listing.data.strategy must be \"all\" or \"blocks\"');\n}\nexport function listingRevision(\n entries: readonly ListingEntry[],\n sort: Required<SortOptions>,\n hrefBase: string,\n blockSize: number,\n): string {\n return createHash(\"sha256\")\n .update(JSON.stringify({ version: 1, entries, sort, hrefBase, blockSize }))\n .digest(\"hex\");\n}\n","import { readdir, readlink } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport picomatch from \"picomatch\";\n\nexport function normalizePathPatterns(value: unknown, name: string): readonly string[] {\n if (value === undefined) return [];\n const patterns = typeof value === \"string\" ? [value] : value;\n if (\n !Array.isArray(patterns) ||\n patterns.some(\n (pattern) =>\n typeof pattern !== \"string\" ||\n pattern.length === 0 ||\n pattern.startsWith(\"/\") ||\n /^[A-Za-z]:/.test(pattern) ||\n pattern.startsWith(\"!\") ||\n pattern.includes(\"\\\\\") ||\n pattern.split(\"/\").some((segment) => segment === \".\" || segment === \"..\"),\n )\n ) {\n throw new TypeError(`${name} must contain root-relative glob patterns using forward slashes`);\n }\n return patterns as readonly string[];\n}\n\nfunction isWithin(parent: string, candidate: string): boolean {\n const relative = path.relative(parent, candidate);\n return (\n relative === \"\" ||\n (relative !== \"..\" && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative))\n );\n}\n\nexport interface SourceSelection {\n readonly selected: ReadonlySet<string>;\n readonly symlinks: ReadonlySet<string>;\n readonly mirroredSymlinks: ReadonlySet<string>;\n}\n\n/** Select physical source paths; parent directories remain when a descendant matches. */\nexport async function selectSourcePaths(\n sourceDir: string,\n outputDir: string,\n include: unknown,\n exclude: unknown,\n ignoredPaths: readonly string[] = [],\n): Promise<SourceSelection> {\n const ignored = ignoredPaths.map((value) => path.resolve(value));\n const included = normalizePathPatterns(include, \"include\").map((pattern) =>\n picomatch(pattern, { dot: true, nonegate: true }),\n );\n const excluded = normalizePathPatterns(exclude, \"exclude\").map((pattern) =>\n picomatch(pattern, { dot: true, nonegate: true }),\n );\n const selected = new Set<string>([\"\"]);\n const symlinks = new Map<string, string>();\n\n async function visit(\n directory: string,\n relativeDir: string,\n inheritedInclude: boolean,\n ): Promise<boolean> {\n let hasSelected = false;\n for (const entry of await readdir(directory, { withFileTypes: true })) {\n const absolutePath = path.join(directory, entry.name);\n if (\n isWithin(outputDir, absolutePath) ||\n ignored.some((value) => isWithin(value, absolutePath))\n )\n continue;\n const relativePath = path.posix.join(relativeDir, entry.name);\n const directoryLike = entry.isDirectory();\n const matches = (matcher: (value: string) => boolean) =>\n matcher(relativePath) || (directoryLike && matcher(`${relativePath}/`));\n if (excluded.some(matches)) continue;\n const includedHere = inheritedInclude || included.some(matches);\n if (directoryLike) {\n const hasSelectedChild = await visit(absolutePath, relativePath, includedHere);\n if (included.length === 0 || includedHere || hasSelectedChild) {\n selected.add(relativePath);\n hasSelected = true;\n }\n } else if (included.length === 0 || includedHere) {\n selected.add(relativePath);\n hasSelected = true;\n if (entry.isSymbolicLink()) symlinks.set(relativePath, await readlink(absolutePath));\n }\n }\n return hasSelected;\n }\n\n await visit(sourceDir, \"\", false);\n // Absolute, escaping, and filtered targets cannot remain valid inside the copied tree.\n const mirroredSymlinks = new Set<string>();\n for (const [relativePath, target] of symlinks) {\n if (path.isAbsolute(target)) continue;\n const targetPath = path.resolve(sourceDir, path.dirname(relativePath), target);\n if (!isWithin(sourceDir, targetPath)) continue;\n const targetRelativePath = path.relative(sourceDir, targetPath).split(path.sep).join(\"/\");\n if (selected.has(targetRelativePath)) mirroredSymlinks.add(relativePath);\n }\n return { selected, symlinks: new Set(symlinks.keys()), mirroredSymlinks };\n}\n","import { copyJsonObject } from \"./json.ts\";\nimport { describeEntry, isInsideRoot } from \"./filesystem.ts\";\nimport {\n listingRevision,\n projectListingEntry,\n validateListingPlan,\n type ListingManifest,\n} from \"./listing.ts\";\nimport {\n cp,\n lstat,\n mkdtemp,\n mkdir,\n readFile,\n readdir,\n realpath,\n rename,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport type {\n DirectoryData,\n EntryKind,\n ExplorerTheme,\n FileSystemEntry,\n GenerateOptions,\n NameSortMode,\n OutputNameResolver,\n SortOptions,\n ThemeContext,\n} from \"./model.ts\";\nimport { selectSourcePaths } from \"./filters.ts\";\n\nconst indexPattern = /^index\\.html?$/i;\n\nconst defaultSort = {\n direction: \"asc\",\n directoriesFirst: true,\n field: \"name\",\n nameMode: \"natural\",\n} as const satisfies Required<SortOptions>;\n\nexport const defaultOutputName: OutputNameResolver = ({ entries }) =>\n entries.some((entry) => entry.kind === \"file\" && indexPattern.test(entry.name))\n ? entries.some((entry) => entry.name.toLowerCase() === \"_dirwell.html\")\n ? null\n : \"_dirwell.html\"\n : \"index.html\";\n\nfunction assertSafeOutputName(name: string): void {\n if (name.length === 0 || path.basename(name) !== name || name === \".\" || name === \"..\") {\n throw new Error(`Output name must be a single safe filename: ${name}`);\n }\n}\n\nfunction normalizeBase(value: string): string {\n if (value.includes(\"?\") || value.includes(\"#\")) {\n throw new TypeError(\"base must not contain a query string or fragment\");\n }\n if (/^https?:\\/\\//i.test(value)) {\n const url = new URL(value);\n url.pathname = `${url.pathname.replace(/\\/+$/, \"\")}/`;\n return url.href;\n }\n if (!value.startsWith(\"/\")) {\n throw new TypeError('base must start with \"/\" or be an absolute HTTP(S) URL');\n }\n return `${value.replace(/\\/+$/, \"\")}/`;\n}\n\nfunction encodeLogicalPath(value: string): string {\n return value\n .split(\"/\")\n .filter((segment) => segment.length > 0)\n .map((segment) => encodeURIComponent(segment))\n .join(\"/\");\n}\n\nfunction isDirectoryLike(entry: FileSystemEntry): boolean {\n return entry.kind === \"directory\" || entry.symlink?.targetKind === \"directory\";\n}\n\nfunction isUnavailableSymlink(entry: FileSystemEntry): boolean {\n return Boolean(\n entry.symlink?.isBroken || entry.symlink?.isOutsideRoot || entry.symlink?.isTargetExcluded,\n );\n}\n\nfunction compareUnicode(left: string, right: string): number {\n const leftPoints = [...left];\n const rightPoints = [...right];\n const length = Math.min(leftPoints.length, rightPoints.length);\n for (let index = 0; index < length; index += 1) {\n const difference =\n (leftPoints[index]?.codePointAt(0) ?? 0) - (rightPoints[index]?.codePointAt(0) ?? 0);\n if (difference !== 0) return difference;\n }\n return leftPoints.length - rightPoints.length;\n}\n\nfunction compareNames(left: string, right: string, mode: NameSortMode): number {\n if (mode === \"unicode\") return compareUnicode(left, right);\n return left.localeCompare(right, undefined, {\n numeric: mode === \"natural\",\n sensitivity: \"base\",\n });\n}\n\nexport function compareEntries(\n left: FileSystemEntry,\n right: FileSystemEntry,\n options: SortOptions = {},\n): number {\n const resolved = { ...defaultSort, ...options };\n if (resolved.directoriesFirst && isDirectoryLike(left) !== isDirectoryLike(right)) {\n return isDirectoryLike(left) ? -1 : 1;\n }\n let result: number;\n if (resolved.field === \"modified\") {\n result = left.metadata.times.modifiedAt.localeCompare(right.metadata.times.modifiedAt);\n } else if (resolved.field === \"size\") {\n result =\n (left.kind === \"directory\" ? 0 : left.metadata.size) -\n (right.kind === \"directory\" ? 0 : right.metadata.size);\n } else {\n result = compareNames(left.name, right.name, resolved.nameMode);\n }\n if (result === 0) result = compareNames(left.name, right.name, resolved.nameMode);\n return resolved.direction === \"asc\" ? result : -result;\n}\n\nfunction rawLinkFilename(entry: FileSystemEntry): string {\n return `${createHash(\"sha256\")\n .update(entry.relativePath)\n .update(\"\\0\")\n .update(entry.symlink?.target ?? \"\")\n .digest(\"hex\")\n .slice(0, 16)}.txt`;\n}\n\nexport async function generateExplorer(options: GenerateOptions): Promise<void> {\n return generateExplorerSkippingPaths(options, []);\n}\n\n/** Internal entry point for hosts that stage previews outside their published output. */\nexport async function generateExplorerSkippingPaths(\n options: GenerateOptions,\n ignoredPaths: readonly string[],\n): Promise<void> {\n const sourceDir = path.resolve(options.sourceDir);\n const outputDir = path.resolve(options.outputDir);\n const ignoredSourcePaths = ignoredPaths.map((value) => path.resolve(value));\n const rootRealPath = await realpath(sourceDir);\n const outputName = options.outputName ?? defaultOutputName;\n const resolveOutputName: OutputNameResolver =\n typeof outputName === \"string\" ? () => outputName : outputName;\n const theme: ExplorerTheme = options.theme;\n if (theme === undefined) throw new TypeError(\"Core requires an explicit theme\");\n const mode = options.mode ?? \"ssg\";\n const urlStrategy = options.urlStrategy ?? \"relative\";\n const base = normalizeBase(options.base ?? \"/\");\n const followSymlinks = options.symlinks?.follow ?? false;\n const boundary = options.symlinks?.boundary ?? \"root\";\n const onCycle = options.symlinks?.onCycle ?? \"skip\";\n const filtersActive =\n options.include !== undefined || options.exclude !== undefined || ignoredSourcePaths.length > 0;\n const plans: Array<{\n readonly directory: DirectoryData;\n readonly logicalDir: string;\n readonly outputName: string | null;\n }> = [];\n if (isInsideRoot(outputDir, sourceDir)) {\n throw new Error(\"outputDir must not contain the sourceDir\");\n }\n try {\n await lstat(path.join(sourceDir, \"__dirwell\"));\n throw new Error('Dirwell reserves the source-root path \"__dirwell\"');\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n // The reserved asset path is available.\n } else {\n throw error;\n }\n }\n const outputIsWithinSource = isInsideRoot(sourceDir, outputDir);\n const selection = await selectSourcePaths(\n sourceDir,\n outputDir,\n options.include,\n options.exclude,\n ignoredSourcePaths,\n );\n const stageParent = outputIsWithinSource ? path.dirname(sourceDir) : path.dirname(outputDir);\n await mkdir(stageParent, { recursive: true });\n const stagedOutputDir = await mkdtemp(\n path.join(stageParent, `.${path.basename(outputDir)}-dirwell-`),\n );\n const buildOutputDir = stagedOutputDir;\n\n try {\n if (options.mirror ?? true) {\n await rm(buildOutputDir, { recursive: true, force: true });\n await mkdir(buildOutputDir, { recursive: true });\n await cp(sourceDir, buildOutputDir, {\n recursive: true,\n dereference: false,\n preserveTimestamps: true,\n filter: (sourcePath) => {\n const relativePath = path.relative(sourceDir, sourcePath).split(path.sep).join(\"/\");\n return (\n selection.selected.has(relativePath) &&\n (!selection.symlinks.has(relativePath) || selection.mirroredSymlinks.has(relativePath))\n );\n },\n });\n }\n } catch (error) {\n await rm(stagedOutputDir, { recursive: true, force: true });\n throw error;\n }\n\n async function visit(\n logicalDir: string,\n physicalDir: string,\n ancestors: ReadonlySet<string>,\n ): Promise<void> {\n const physicalRealPath = await realpath(physicalDir);\n if (ancestors.has(physicalRealPath)) {\n if (onCycle === \"error\") throw new Error(`Symlink cycle at ${logicalDir}`);\n return;\n }\n\n const nextAncestors = new Set(ancestors).add(physicalRealPath);\n const names = (await readdir(physicalDir)).filter((name) => {\n if (outputIsWithinSource && isInsideRoot(outputDir, path.join(physicalDir, name)))\n return false;\n if (ignoredSourcePaths.some((value) => isInsideRoot(value, path.join(physicalDir, name))))\n return false;\n if (!filtersActive) return true;\n const relativePath = path.relative(rootRealPath, path.join(physicalRealPath, name));\n return selection.selected.has(relativePath.split(path.sep).join(\"/\"));\n });\n const entries = await Promise.all(\n names.map((name) =>\n describeEntry({\n absolutePath: path.join(physicalDir, name),\n relativePath: path.posix.join(logicalDir, name),\n rootRealPath,\n ancestors: nextAncestors,\n followSymlinks,\n selectedPaths: filtersActive ? selection.selected : null,\n }),\n ),\n );\n entries.sort(\n (left, right) =>\n compareEntries(left, right, options.sort) ||\n (options.listing === undefined ? 0 : compareUnicode(left.relativePath, right.relativePath)),\n );\n\n const describedCurrent = await describeEntry({\n absolutePath: physicalDir,\n relativePath: logicalDir,\n rootRealPath,\n ancestors,\n followSymlinks,\n selectedPaths: filtersActive ? selection.selected : null,\n });\n if (describedCurrent.kind !== \"directory\") {\n throw new Error(`${physicalDir} is not a directory`);\n }\n const current: DirectoryData[\"current\"] = {\n ...describedCurrent,\n kind: \"directory\",\n };\n\n const root = await describeEntry({\n absolutePath: sourceDir,\n relativePath: \"\",\n rootRealPath,\n ancestors: new Set(),\n followSymlinks,\n selectedPaths: filtersActive ? selection.selected : null,\n });\n const parent =\n logicalDir === \"\"\n ? null\n : await describeEntry({\n absolutePath: path.dirname(physicalDir),\n relativePath:\n path.posix.dirname(logicalDir) === \".\" ? \"\" : path.posix.dirname(logicalDir),\n rootRealPath,\n ancestors,\n followSymlinks,\n selectedPaths: filtersActive ? selection.selected : null,\n });\n const directory: DirectoryData = {\n root,\n current,\n parent,\n depth: logicalDir === \"\" ? 0 : logicalDir.split(\"/\").length,\n entries,\n };\n\n const name = await resolveOutputName(directory);\n if (name !== null) assertSafeOutputName(name);\n plans.push({ directory, logicalDir, outputName: name });\n\n for (const entry of entries) {\n if (entry.kind === \"directory\") {\n await visit(path.posix.join(logicalDir, entry.name), entry.absolutePath, nextAncestors);\n continue;\n }\n if (!followSymlinks || entry.symlink?.targetKind !== \"directory\") continue;\n const physicalLinkPath = path\n .relative(rootRealPath, path.join(physicalRealPath, entry.name))\n .split(path.sep)\n .join(\"/\");\n if ((options.mirror ?? true) && !selection.mirroredSymlinks.has(physicalLinkPath)) continue;\n if (entry.symlink.isCycle) {\n if (onCycle === \"error\") throw new Error(`Symlink cycle at ${entry.relativePath}`);\n continue;\n }\n if (entry.symlink.resolvedPath === null) continue;\n if (boundary === \"root\" && entry.symlink.isOutsideRoot) continue;\n if (\n filtersActive &&\n (entry.symlink.targetRelativePath === null ||\n !selection.selected.has(entry.symlink.targetRelativePath))\n )\n continue;\n // Mirrored internal aliases already resolve to the target's generated page.\n // Writing an alias page through the copied symlink would overwrite that page.\n if (\n (options.mirror ?? true) &&\n entry.symlink.targetRelativePath !== null &&\n !entry.symlink.isOutsideRoot\n )\n continue;\n await visit(\n path.posix.join(logicalDir, entry.name),\n entry.symlink.resolvedPath,\n nextAncestors,\n );\n }\n }\n\n try {\n await visit(\"\", sourceDir, new Set());\n\n const generatedPages = new Map(\n plans\n .filter(\n (plan): plan is typeof plan & { readonly outputName: string } => plan.outputName !== null,\n )\n .map((plan) => [plan.logicalDir, plan.outputName]),\n );\n const generatedDirectories = new Set(generatedPages.keys());\n const pagePathForDirectory = (logicalPath: string): string => {\n const pageName = generatedPages.get(logicalPath);\n return pageName === undefined || pageName === \"index.html\"\n ? logicalPath\n : path.posix.join(logicalPath, pageName);\n };\n const sourceKinds = new Map<string, string>();\n for (const { directory } of plans)\n for (const entry of directory.entries) {\n const sourcePath = path.relative(sourceDir, entry.absolutePath).split(path.sep).join(\"/\");\n if (selection.selected.has(sourcePath)) sourceKinds.set(sourcePath, entry.kind);\n }\n const metadataResolver = await options.metadata?.({ sourceDir, sourceKinds });\n const sharedAssets = new Map<string, string | Uint8Array>();\n const rawLinkFiles = new Map<string, string>();\n const searchEntries = new Map<\n string,\n {\n href: string | null;\n exitsExplorer: boolean;\n isLink: boolean;\n kind: EntryKind;\n modifiedAt: string;\n name: string;\n path: string;\n size: number;\n target: string | null;\n targetKind: Exclude<EntryKind, \"symlink\"> | null;\n targetSize: number | null;\n isTargetUnavailable: boolean;\n isCycle: boolean;\n }\n >();\n\n for (const { directory, logicalDir } of theme.searchIndex === false ? [] : plans) {\n for (const entry of directory.entries) {\n if (searchEntries.has(entry.relativePath)) continue;\n const targetLogicalPath = isUnavailableSymlink(entry)\n ? null\n : entry.symlink?.targetRelativePath !== null && entry.symlink !== null\n ? entry.symlink.targetRelativePath\n : path.posix.join(logicalDir, entry.name);\n const directoryLike = isDirectoryLike(entry);\n const linkedPath =\n directoryLike && targetLogicalPath !== null\n ? pagePathForDirectory(targetLogicalPath)\n : targetLogicalPath;\n let href: string | null = null;\n if (entry.symlink !== null && isUnavailableSymlink(entry)) {\n const filename = rawLinkFilename(entry);\n rawLinkFiles.set(filename, entry.symlink.target);\n href = `raw-links/${filename}`;\n } else if (linkedPath !== null) {\n href =\n linkedPath === \"\"\n ? \"../\"\n : `../${encodeLogicalPath(linkedPath)}${directoryLike && linkedPath === targetLogicalPath ? \"/\" : \"\"}`;\n }\n searchEntries.set(entry.relativePath, {\n exitsExplorer:\n isUnavailableSymlink(entry) ||\n (targetLogicalPath !== null &&\n (!directoryLike || !generatedDirectories.has(targetLogicalPath))),\n href,\n isLink: entry.kind === \"symlink\",\n kind: entry.kind,\n modifiedAt: entry.metadata.times.modifiedAt,\n name: entry.name,\n path: entry.relativePath,\n size: entry.metadata.size,\n target: entry.symlink?.target ?? null,\n targetKind: entry.symlink?.targetKind ?? null,\n targetSize: entry.symlink?.targetSize ?? null,\n isTargetUnavailable: isUnavailableSymlink(entry),\n isCycle: entry.symlink?.isCycle ?? false,\n });\n }\n }\n\n for (const plan of plans) {\n const { directory, logicalDir, outputName: name } = plan;\n const sourceEntryNames = new Set(directory.entries.map((entry) => entry.name.toLowerCase()));\n if (name === null) continue;\n\n const targetLogicalPathFor = (entry: FileSystemEntry): string | null => {\n if (isUnavailableSymlink(entry)) return null;\n if (entry.symlink?.targetRelativePath !== null && entry.symlink !== null) {\n return entry.symlink.targetRelativePath;\n }\n return path.posix.join(logicalDir, entry.name);\n };\n const hrefForLogicalPath = (targetPath: string, directoryLike: boolean): string => {\n const linkedPath = directoryLike ? pagePathForDirectory(targetPath) : targetPath;\n const linkToDirectory = directoryLike && linkedPath === targetPath;\n if (urlStrategy === \"relative\") {\n const relativeTarget = path.posix.relative(\n logicalDir === \"\" ? \".\" : logicalDir,\n linkedPath === \"\" ? \".\" : linkedPath,\n );\n const encodedTarget = relativeTarget\n .split(\"/\")\n .map((segment) =>\n segment === \".\" || segment === \"..\" ? segment : encodeURIComponent(segment),\n )\n .join(\"/\");\n return `${encodedTarget || \".\"}${linkToDirectory ? \"/\" : \"\"}`;\n }\n const encodedTarget = encodeLogicalPath(linkedPath);\n if (encodedTarget === \"\") {\n return urlStrategy === \"base\" ? base : \"./\";\n }\n const suffix = `${encodedTarget}${linkToDirectory ? \"/\" : \"\"}`;\n return urlStrategy === \"base\" ? `${base}${suffix}` : suffix;\n };\n const hrefFor = (entry: FileSystemEntry): string | null => {\n if (entry.symlink !== null && isUnavailableSymlink(entry)) {\n const filename = rawLinkFilename(entry);\n rawLinkFiles.set(filename, entry.symlink.target);\n return hrefForLogicalPath(path.posix.join(\"__dirwell\", \"raw-links\", filename), false);\n }\n const targetLogicalPath = targetLogicalPathFor(entry);\n if (targetLogicalPath === null) return null;\n const directoryLike =\n entry.kind === \"directory\" || entry.symlink?.targetKind === \"directory\";\n return hrefForLogicalPath(targetLogicalPath, directoryLike);\n };\n const baseContext: ThemeContext = {\n operation: \"build\",\n directory,\n documentBaseHref: urlStrategy === \"html-base\" ? base : null,\n outputName: name,\n mode,\n searchIndexHref: hrefForLogicalPath(\n path.posix.join(\"__dirwell\", \"search-index.json\"),\n false,\n ),\n sort: { ...defaultSort, ...options.sort },\n assetHref: (assetName) => {\n assertSafeOutputName(assetName);\n return hrefForLogicalPath(\n mode === \"ssg\"\n ? path.posix.join(logicalDir, assetName)\n : path.posix.join(\"__dirwell\", assetName),\n false,\n );\n },\n hrefFor,\n hrefForDirectory: (relativePath) => hrefForLogicalPath(relativePath, true),\n hasPageForDirectory: (relativePath) => generatedDirectories.has(relativePath),\n exitsExplorerFor: (entry) => {\n if (isUnavailableSymlink(entry)) return true;\n const targetLogicalPath = targetLogicalPathFor(entry);\n const directoryLike =\n entry.kind === \"directory\" || entry.symlink?.targetKind === \"directory\";\n return (\n targetLogicalPath !== null &&\n (!directoryLike || !generatedDirectories.has(targetLogicalPath))\n );\n },\n };\n const targetDir = path.join(buildOutputDir, logicalDir);\n await mkdir(targetDir, { recursive: true });\n const sort = baseContext.sort;\n let revision = \"\";\n let manifestHref = \"\";\n let pageSize = Math.max(1, directory.entries.length);\n if (options.listing !== undefined) {\n const records = directory.entries.map((entry) => {\n const projected = projectListingEntry(entry, baseContext);\n return theme.entryData === undefined\n ? projected\n : {\n ...projected,\n presentation: copyJsonObject(\n theme.entryData(projected, {\n mode: baseContext.mode,\n outputName: baseContext.outputName,\n assetHref: baseContext.assetHref,\n hrefForDirectory: baseContext.hrefForDirectory,\n documentBaseHref: baseContext.documentBaseHref,\n directoryPath: logicalDir,\n }),\n ),\n };\n });\n const candidate =\n typeof options.listing === \"function\"\n ? options.listing({\n directoryPath: logicalDir,\n visibleCount: records.length,\n dataBytes: Buffer.byteLength(JSON.stringify(records)),\n mode,\n operation: \"build\",\n supportsPagination: theme.listing?.pagination === true,\n })\n : options.listing;\n validateListingPlan(candidate);\n if (candidate.html.strategy === \"paged\") {\n if (theme.listing?.pagination !== true)\n throw new Error(`Theme ${theme.name} does not support listing pagination`);\n pageSize = candidate.html.pageSize;\n }\n const directoryId = createHash(\"sha256\").update(logicalDir).digest(\"hex\");\n const manifestDirectory = path.posix.join(\"__dirwell\", \"listing\", directoryId);\n // Relative records belong to the document directory, not to the JSON asset directory.\n const hrefBase =\n urlStrategy === \"relative\"\n ? `../../../${encodeLogicalPath(logicalDir)}${logicalDir ? \"/\" : \"\"}`\n : base;\n const manifestPath = path.posix.join(manifestDirectory, \"manifest.json\");\n manifestHref = hrefForLogicalPath(manifestPath, false);\n const blocks: Array<ListingManifest[\"blocks\"][number]> = [];\n const blockSize =\n candidate.data.strategy === \"blocks\"\n ? candidate.data.blockSize\n : Math.max(1, records.length);\n revision = listingRevision(records, sort, hrefBase, blockSize);\n const outputListingDir = path.join(buildOutputDir, manifestDirectory);\n await mkdir(outputListingDir, { recursive: true });\n for (let offset = 0; offset < records.length || offset === 0; offset += blockSize) {\n const entries = records.slice(offset, offset + blockSize);\n const filename = `${revision}-${blocks.length}.json`;\n blocks.push({ href: filename, offset, count: entries.length });\n await writeFile(\n path.join(outputListingDir, filename),\n JSON.stringify({ version: 1, revision, offset, total: records.length, entries }),\n );\n }\n const manifest: ListingManifest = {\n version: 1,\n revision,\n directory: logicalDir,\n hrefBase,\n total: records.length,\n sort,\n blocks,\n };\n await writeFile(path.join(outputListingDir, \"manifest.json\"), JSON.stringify(manifest));\n }\n const pageCount = Math.max(1, Math.ceil(directory.entries.length / pageSize));\n const pagePrefix = `__dirwell-page-${createHash(\"sha256\").update(name).digest(\"hex\").slice(0, 16)}`;\n const pageNames = Array.from({ length: pageCount }, (_, index) =>\n index === 0 ? name : `${pagePrefix}-${index + 1}.html`,\n );\n for (const pageName of pageNames.slice(1)) {\n if (directory.entries.some((entry) => entry.name.toLowerCase() === pageName.toLowerCase()))\n throw new Error(\n `Listing page conflicts with source entry: ${path.posix.join(logicalDir, pageName)}`,\n );\n }\n const pagedAssets = new Map<string, Buffer>();\n for (const [index, pageName] of pageNames.entries()) {\n const pagePath = path.posix.join(logicalDir, pageName);\n const metadata = await metadataResolver?.resolve(\n directory,\n (outputPath) => hrefForLogicalPath(outputPath, false),\n pageName === \"index.html\" ? (logicalDir ? `${logicalDir}/` : \"\") : pagePath,\n );\n const pageHref = (number: number): string =>\n hrefForLogicalPath(path.posix.join(logicalDir, pageNames[number] ?? name), false);\n const page = await theme.render({\n ...baseContext,\n ...(metadata === undefined ? {} : { metadata }),\n outputName: pageName,\n directory:\n options.listing === undefined\n ? directory\n : {\n ...directory,\n entries: directory.entries.slice(index * pageSize, (index + 1) * pageSize),\n },\n ...(options.listing === undefined\n ? {}\n : {\n listing: {\n revision,\n manifestHref,\n page: {\n number: index + 1,\n count: pageCount,\n offset: index * pageSize,\n total: directory.entries.length,\n href: pageHref(index),\n previousHref: index === 0 ? null : pageHref(index - 1),\n nextHref: index + 1 === pageCount ? null : pageHref(index + 1),\n },\n },\n }),\n });\n await writeFile(path.join(targetDir, pageName), page.html);\n for (const [assetName, contents] of Object.entries(page.assets ?? {})) {\n assertSafeOutputName(assetName);\n if (\n (options.listing !== undefined || theme.listing?.pagination === true) &&\n mode === \"ssg\" &&\n sourceEntryNames.has(assetName.toLowerCase())\n )\n throw new Error(`Theme asset conflicts with source entry: ${assetName}`);\n if (\n options.listing !== undefined &&\n pageNames.some((pageName) => pageName.toLowerCase() === assetName.toLowerCase())\n )\n throw new Error(`Theme asset conflicts with listing page: ${assetName}`);\n if (options.listing !== undefined && pageCount > 1) {\n const bytes = Buffer.from(contents);\n const existing = pagedAssets.get(assetName);\n if (existing !== undefined && !existing.equals(bytes))\n throw new Error(`Theme emitted conflicting paginated asset: ${assetName}`);\n pagedAssets.set(assetName, bytes);\n }\n if (mode === \"ssg\") {\n await writeFile(path.join(targetDir, assetName), contents);\n } else {\n const bytes = Buffer.from(contents);\n const existing = sharedAssets.get(assetName);\n if (existing !== undefined && !Buffer.from(existing).equals(bytes)) {\n throw new Error(`Theme emitted conflicting shared asset: ${assetName}`);\n }\n sharedAssets.set(assetName, bytes);\n }\n }\n }\n }\n\n if (mode === \"mpa\" && sharedAssets.size > 0) {\n const assetDirectory = path.join(buildOutputDir, \"__dirwell\");\n await mkdir(assetDirectory, { recursive: true });\n for (const [assetName, contents] of sharedAssets) {\n await writeFile(path.join(assetDirectory, assetName), contents);\n }\n }\n\n for (const [filename, bytes] of metadataResolver?.assets ?? []) {\n const parts = filename.split(\"/\");\n for (let index = 1; index <= parts.length; index++) {\n const prefix = parts.slice(0, index).join(\"/\");\n if (selection.selected.has(prefix))\n throw new Error(`Metadata image conflicts with source entry: ${filename}`);\n const candidate = path.join(buildOutputDir, prefix);\n try {\n const info = await lstat(candidate);\n if (info.isSymbolicLink() || index === parts.length || !info.isDirectory())\n throw new Error(`Metadata image conflicts with generated output: ${filename}`);\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n }\n }\n const destination = path.join(buildOutputDir, filename);\n await mkdir(path.dirname(destination), { recursive: true });\n await writeFile(destination, bytes);\n }\n\n if (rawLinkFiles.size > 0) {\n const rawLinkDirectory = path.join(buildOutputDir, \"__dirwell\", \"raw-links\");\n await mkdir(rawLinkDirectory, { recursive: true });\n for (const [filename, target] of rawLinkFiles) {\n await writeFile(path.join(rawLinkDirectory, filename), target);\n }\n }\n if (theme.searchIndex !== false) {\n const generatedAssetDirectory = path.join(buildOutputDir, \"__dirwell\");\n await mkdir(generatedAssetDirectory, { recursive: true });\n const indexedEntries = [...searchEntries.values()];\n const shards: string[] = [];\n for (let offset = 0; offset < indexedEntries.length; offset += 512) {\n const filename = `search-${String(shards.length).padStart(5, \"0\")}.json`;\n shards.push(filename);\n await writeFile(\n path.join(generatedAssetDirectory, filename),\n JSON.stringify({ entries: indexedEntries.slice(offset, offset + 512) }),\n );\n }\n await writeFile(\n path.join(generatedAssetDirectory, \"search-index.json\"),\n JSON.stringify({ count: indexedEntries.length, shards, version: 3 }),\n );\n }\n\n await rm(outputDir, { recursive: true, force: true });\n await mkdir(path.dirname(outputDir), { recursive: true });\n await rename(stagedOutputDir, outputDir);\n } finally {\n await rm(stagedOutputDir, { recursive: true, force: true });\n }\n}\n\nexport async function readGeneratedPage(filePath: string): Promise<string> {\n return readFile(filePath, \"utf8\");\n}\n","/** Escape untrusted text for HTML/XML text nodes and double-quoted attributes. */\nexport function escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\");\n}\n","/** Some Windows Node/libuv versions omit the path-stat device ID but retain the file ID. */\nexport function fileIdentityMatches(\n before: { readonly device: number; readonly inode: number },\n descriptor: { readonly dev: number; readonly ino: number },\n platform = process.platform,\n): boolean {\n if (before.inode !== descriptor.ino) return false;\n if (before.device === descriptor.dev) return true;\n return platform === \"win32\" && before.device === 0 && before.inode !== 0;\n}\n","import { readdir, realpath, open, type FileHandle } from \"node:fs/promises\";\nimport { constants } from \"node:fs\";\nimport { fileIdentityMatches } from \"./file-identity.ts\";\nimport path from \"node:path\";\nimport { describeEntry, isInsideRoot } from \"./filesystem.ts\";\nimport { selectSourcePaths } from \"./filters.ts\";\nimport { compareEntries } from \"./generator.ts\";\nimport type { DirectoryData, FileSystemEntry, SortOptions } from \"./model.ts\";\n\nexport interface DirectoryServiceOptions {\n readonly root: string;\n readonly include?: string | readonly string[];\n readonly exclude?: string | readonly string[];\n readonly sort?: SortOptions;\n}\nexport interface DirectoryService {\n readonly resolvePath: (logicalPath: string) => Promise<string>;\n readonly openFile: (logicalPath: string) => Promise<{\n readonly entry: FileSystemEntry;\n readonly handle: FileHandle;\n readonly canonicalPath: string;\n }>;\n readonly getEntry: (logicalPath: string) => Promise<FileSystemEntry>;\n readonly listDirectory: (logicalPath: string) => Promise<DirectoryData>;\n}\nexport class DirectoryAccessError extends Error {\n override readonly name = \"DirectoryAccessError\";\n}\nfunction assertLogicalPath(value: string): void {\n if (\n value.startsWith(\"/\") ||\n value.includes(\"\\\\\") ||\n value.includes(\"\\0\") ||\n value\n .split(\"/\")\n .some((segment) => segment === \".\" || segment === \"..\" || (segment === \"\" && value !== \"\")) ||\n /^[a-z]:/i.test(value) ||\n value === \"__dirwell\" ||\n value.startsWith(\"__dirwell/\")\n )\n throw new DirectoryAccessError(\"Unavailable path\");\n}\n/** Live reads; no watcher, recursive stat snapshot, output tree or implicit cache. */\nexport async function createDirectoryService(\n options: DirectoryServiceOptions,\n): Promise<DirectoryService> {\n const root = await realpath(options.root);\n const selected = async () =>\n options.include === undefined && options.exclude === undefined\n ? null\n : (\n await selectSourcePaths(\n root,\n path.join(root, \"__dirwell\"),\n options.include,\n options.exclude,\n )\n ).selected;\n async function describe(\n logicalPath: string,\n selection: ReadonlySet<string> | null,\n ): Promise<FileSystemEntry> {\n assertLogicalPath(logicalPath);\n if (selection !== null && !selection.has(logicalPath))\n throw new DirectoryAccessError(\"Unavailable path\");\n const absolutePath = path.join(root, logicalPath);\n const parent = logicalPath === \"\" ? root : await realpath(path.dirname(absolutePath));\n if (!isInsideRoot(root, parent)) throw new DirectoryAccessError(\"Unavailable path\");\n const ancestors = new Set<string>([root]);\n if (logicalPath !== \"\") {\n const segments = logicalPath.split(\"/\").slice(0, -1);\n for (let length = 1; length <= segments.length; length++)\n ancestors.add(await realpath(path.join(root, ...segments.slice(0, length))));\n }\n return describeEntry({\n absolutePath,\n relativePath: logicalPath,\n rootRealPath: root,\n ancestors,\n followSymlinks: false,\n selectedPaths: selection,\n });\n }\n return {\n async resolvePath(logicalPath) {\n const selection = await selected();\n const entry = await describe(logicalPath, selection);\n if (\n entry.symlink &&\n (entry.symlink.isBroken || entry.symlink.isOutsideRoot || entry.symlink.isTargetExcluded)\n )\n throw new DirectoryAccessError(\"Unavailable target\");\n const resolved = await realpath(entry.absolutePath);\n if (!isInsideRoot(root, resolved)) throw new DirectoryAccessError(\"Unavailable target\");\n const canonical = path.relative(root, resolved).split(path.sep).join(\"/\");\n if (selection !== null && !selection.has(canonical))\n throw new DirectoryAccessError(\"Unavailable target\");\n return canonical;\n },\n async openFile(logicalPath) {\n assertLogicalPath(logicalPath);\n const selection = await selected();\n let entry = await describe(logicalPath, selection);\n if (entry.symlink !== null) {\n if (\n entry.symlink.isBroken ||\n entry.symlink.isOutsideRoot ||\n entry.symlink.isTargetExcluded ||\n entry.symlink.targetRelativePath === null\n )\n throw new DirectoryAccessError(\"Unavailable file\");\n entry = await describe(entry.symlink.targetRelativePath, selection);\n }\n if (entry.kind !== \"file\") throw new DirectoryAccessError(\"Unavailable file\");\n const handle = await open(\n entry.absolutePath,\n constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0),\n );\n try {\n const stats = await handle.stat();\n const resolved = await realpath(entry.absolutePath);\n if (\n !stats.isFile() ||\n !isInsideRoot(root, resolved) ||\n !fileIdentityMatches(entry.metadata, stats)\n )\n throw new DirectoryAccessError(\"File changed before opening\");\n return {\n entry,\n handle,\n canonicalPath: path.relative(root, resolved).split(path.sep).join(\"/\"),\n };\n } catch (error) {\n await handle.close();\n throw error;\n }\n },\n async getEntry(logicalPath) {\n assertLogicalPath(logicalPath);\n return describe(logicalPath, await selected());\n },\n async listDirectory(logicalPath) {\n assertLogicalPath(logicalPath);\n const selection = await selected();\n const entry = await describe(logicalPath, selection);\n if (entry.kind !== \"directory\") throw new DirectoryAccessError(\"Unavailable directory\");\n const physical = await realpath(entry.absolutePath);\n if (!isInsideRoot(root, physical)) throw new DirectoryAccessError(\"Unavailable directory\");\n const names = (await readdir(physical)).filter(\n (name) => logicalPath !== \"\" || name !== \"__dirwell\",\n );\n const entries = await Promise.all(\n names\n .filter((name) => selection === null || selection.has(path.posix.join(logicalPath, name)))\n .map((name) => describe(path.posix.join(logicalPath, name), selection)),\n );\n entries.sort(\n (left, right) =>\n compareEntries(left, right, options.sort) ||\n (left.relativePath < right.relativePath\n ? -1\n : left.relativePath > right.relativePath\n ? 1\n : 0),\n );\n return {\n root: await describe(\"\", selection),\n current: { ...entry, kind: \"directory\" },\n parent:\n logicalPath === \"\"\n ? null\n : await describe(\n path.posix.dirname(logicalPath) === \".\" ? \"\" : path.posix.dirname(logicalPath),\n selection,\n ),\n depth: logicalPath === \"\" ? 0 : logicalPath.split(\"/\").length,\n entries,\n };\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/filters.ts","../src/validation.ts","../src/filesystem.ts","../src/listing.ts","../src/publication.ts","../src/generator.ts","../src/html.ts","../src/file-identity.ts","../src/service.ts"],"sourcesContent":["import { readdir, readlink, readFile, realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport picomatch from \"picomatch\";\nimport ignore from \"ignore\";\nimport type { IgnoreFile } from \"./model.ts\";\n\n/** Resolve configuration paths once, before a host changes working directories. */\nexport function resolveIgnoreFiles(\n value: unknown = [],\n cwd = process.cwd(),\n): readonly Exclude<IgnoreFile, string>[] {\n if (!Array.isArray(value)) throw new TypeError(\"ignoreFiles must be an array\");\n return value.map((input) => {\n const file = typeof input === \"string\" ? { path: input } : input;\n if (typeof file !== \"object\" || file === null || Array.isArray(file))\n throw new TypeError(\"ignoreFiles entries must be paths or objects\");\n for (const key of Object.keys(file))\n if (![\"path\", \"baseDir\", \"optional\"].includes(key))\n throw new TypeError(`Unsupported ignoreFiles key \"${key}\"`);\n for (const key of [\"path\", \"baseDir\"] as const)\n if (\n (key === \"path\" || file[key] !== undefined) &&\n (typeof file[key] !== \"string\" || file[key].length === 0)\n )\n throw new TypeError(`ignoreFiles.${key} must be a non-empty string`);\n if (file.optional !== undefined && typeof file.optional !== \"boolean\")\n throw new TypeError(\"ignoreFiles.optional must be a boolean\");\n const filename = path.resolve(cwd, file.path);\n return {\n path: filename,\n baseDir: path.resolve(cwd, file.baseDir ?? path.dirname(filename)),\n optional: file.optional ?? false,\n };\n });\n}\n\nexport async function createIgnoreMatcher(files: readonly IgnoreFile[]) {\n const rules: { base: string; matcher: ReturnType<typeof ignore> }[] = [];\n const scopes = new Map<string, ReturnType<typeof ignore>>();\n let hasRules = false;\n for (const file of resolveIgnoreFiles(files)) {\n let contents: string;\n try {\n contents = await readFile(file.path, \"utf8\");\n } catch (error) {\n if (file.optional && error instanceof Error && \"code\" in error && error.code === \"ENOENT\")\n continue;\n throw error;\n }\n const base = await realpath(file.baseDir!);\n if (contents.split(/\\r?\\n/).some((line) => line.trim() !== \"\" && !line.startsWith(\"#\")))\n hasRules = true;\n let matcher = scopes.get(base);\n if (matcher === undefined) {\n matcher = ignore();\n scopes.set(base, matcher);\n rules.push({ base, matcher });\n }\n matcher.add(contents);\n }\n // Preserve Git's parent-directory negation behavior across files in one scope.\n // Explicit deeper scopes override applicable parent-scope rules.\n rules.sort((left, right) => left.base.split(path.sep).length - right.base.split(path.sep).length);\n const matches = (filename: string, directory: boolean): boolean => {\n let ignored = false;\n for (const rule of rules) {\n if (!isWithin(rule.base, filename)) continue;\n const relative = path.relative(rule.base, filename).split(path.sep).join(\"/\");\n if (relative === \"\") continue;\n const result = rule.matcher.test(relative + (directory ? \"/\" : \"\"));\n if (result.ignored) ignored = true;\n else if (result.unignored) ignored = false;\n }\n return ignored;\n };\n return Object.assign(matches, { hasRules });\n}\n\nexport function normalizePathPatterns(value: unknown, name: string): readonly string[] {\n if (value === undefined) return [];\n const patterns = typeof value === \"string\" ? [value] : value;\n if (\n !Array.isArray(patterns) ||\n patterns.some(\n (pattern) =>\n typeof pattern !== \"string\" ||\n pattern.length === 0 ||\n pattern.startsWith(\"/\") ||\n /^[A-Za-z]:/.test(pattern) ||\n pattern.startsWith(\"!\") ||\n pattern.includes(\"\\\\\") ||\n pattern.split(\"/\").some((segment) => segment === \".\" || segment === \"..\"),\n )\n ) {\n throw new TypeError(`${name} must contain root-relative glob patterns using forward slashes`);\n }\n return patterns as readonly string[];\n}\n\nfunction isWithin(parent: string, candidate: string): boolean {\n const relative = path.relative(parent, candidate);\n return (\n relative === \"\" ||\n (relative !== \"..\" && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative))\n );\n}\n\nexport interface SourceSelection {\n readonly selected: ReadonlySet<string>;\n readonly symlinks: ReadonlySet<string>;\n readonly mirroredSymlinks: ReadonlySet<string>;\n}\n\n/** Select physical source paths; parent directories remain when a descendant matches. */\nexport async function selectSourcePaths(\n sourceDir: string,\n outputDir: string,\n include: unknown,\n exclude: unknown,\n ignoredPaths: readonly string[] = [],\n ignoreFiles: readonly IgnoreFile[] = [],\n preparedIgnore?: Awaited<ReturnType<typeof createIgnoreMatcher>>,\n): Promise<SourceSelection> {\n const isIgnored = preparedIgnore ?? (await createIgnoreMatcher(ignoreFiles));\n const canonicalRoot = await realpath(sourceDir);\n const ignored = ignoredPaths.map((value) => path.resolve(value));\n const included = normalizePathPatterns(include, \"include\").map((pattern) =>\n picomatch(pattern, { dot: true, nonegate: true }),\n );\n const excluded = normalizePathPatterns(exclude, \"exclude\").map((pattern) =>\n picomatch(pattern, { dot: true, nonegate: true }),\n );\n const selected = new Set<string>([\"\"]);\n const symlinks = new Map<string, string>();\n\n async function visit(\n directory: string,\n relativeDir: string,\n inheritedInclude: boolean,\n ): Promise<boolean> {\n let hasSelected = false;\n for (const entry of await readdir(directory, { withFileTypes: true })) {\n const absolutePath = path.join(directory, entry.name);\n if (\n isWithin(outputDir, absolutePath) ||\n ignored.some((value) => isWithin(value, absolutePath))\n )\n continue;\n const relativePath = path.posix.join(relativeDir, entry.name);\n const directoryLike = entry.isDirectory();\n const matches = (matcher: (value: string) => boolean) =>\n matcher(relativePath) || (directoryLike && matcher(`${relativePath}/`));\n if (\n excluded.some(matches) ||\n isIgnored(path.join(canonicalRoot, relativePath), directoryLike)\n )\n continue;\n const includedHere = inheritedInclude || included.some(matches);\n if (directoryLike) {\n const hasSelectedChild = await visit(absolutePath, relativePath, includedHere);\n if (included.length === 0 || includedHere || hasSelectedChild) {\n selected.add(relativePath);\n hasSelected = true;\n }\n } else if (included.length === 0 || includedHere) {\n selected.add(relativePath);\n hasSelected = true;\n if (entry.isSymbolicLink()) symlinks.set(relativePath, await readlink(absolutePath));\n }\n }\n return hasSelected;\n }\n\n if (!isIgnored(canonicalRoot, true)) await visit(sourceDir, \"\", false);\n // Absolute, escaping, and filtered targets cannot remain valid inside the copied tree.\n const mirroredSymlinks = new Set<string>();\n for (const [relativePath, target] of symlinks) {\n if (path.isAbsolute(target)) continue;\n const targetPath = path.resolve(sourceDir, path.dirname(relativePath), target);\n if (!isWithin(sourceDir, targetPath)) continue;\n const targetRelativePath = path.relative(sourceDir, targetPath).split(path.sep).join(\"/\");\n if (selected.has(targetRelativePath)) mirroredSymlinks.add(relativePath);\n }\n return { selected, symlinks: new Set(symlinks.keys()), mirroredSymlinks };\n}\n","import type { GenerateOptions, ExplorerTheme } from \"./model.ts\";\nimport type { DirectoryServiceOptions } from \"./service.ts\";\nimport type { ListingPlan } from \"./listing.ts\";\nimport { resolveIgnoreFiles } from \"./filters.ts\";\n\ntype Options = Record<string, unknown>;\nexport function optionObject(value: unknown, name: string): Options {\n if (typeof value !== \"object\" || value === null || Array.isArray(value))\n throw new TypeError(`${name} must be an object`);\n return value as Options;\n}\nfunction distance(left: string, right: string): number {\n let previous = Array.from({ length: right.length + 1 }, (_, index) => index);\n for (let i = 1; i <= left.length; i++) {\n const current = [i];\n for (let j = 1; j <= right.length; j++)\n current[j] = Math.min(\n current[j - 1]! + 1,\n previous[j]! + 1,\n previous[j - 1]! + (left[i - 1] === right[j - 1] ? 0 : 1),\n );\n previous = current;\n }\n return previous[right.length]!;\n}\nexport function optionKeys(value: Options, allowed: readonly string[], name: string): void {\n for (const key of Object.keys(value)) {\n if (allowed.includes(key)) continue;\n const suggestion = allowed\n .map((candidate) => ({ candidate, distance: distance(key, candidate) }))\n .sort((left, right) => left.distance - right.distance)\n .find((item) => item.distance <= 2)?.candidate;\n throw new TypeError(\n `Unsupported option \"${name}.${key}\".${suggestion ? ` Did you mean \"${name}.${suggestion}\"?` : ` Supported keys: ${allowed.join(\", \")}.`}`,\n );\n }\n}\nfunction scalar(value: unknown, type: \"boolean\" | \"string\" | \"function\", name: string): void {\n if (value !== undefined && typeof value !== type)\n throw new TypeError(`${name} must be a ${type}`);\n}\nfunction choice(value: unknown, allowed: readonly unknown[], name: string): void {\n if (value !== undefined && !allowed.includes(value))\n throw new TypeError(`${name} must be one of ${allowed.join(\", \")}`);\n}\nfunction positiveInteger(value: unknown, name: string): void {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 1)\n throw new TypeError(`${name} must be a positive safe integer`);\n}\nexport function validateListingPlan(value: unknown): asserts value is ListingPlan {\n const plan = optionObject(value, \"listing\");\n optionKeys(plan, [\"html\", \"data\"], \"listing\");\n for (const [key, strategy, size] of [\n [\"html\", \"paged\", \"pageSize\"],\n [\"data\", \"blocks\", \"blockSize\"],\n ] as const) {\n const section = optionObject(plan[key], `listing.${key}`);\n optionKeys(\n section,\n section.strategy === strategy ? [\"strategy\", size] : [\"strategy\"],\n `listing.${key}`,\n );\n if (section.strategy !== \"all\" && section.strategy !== strategy)\n throw new TypeError(`listing.${key}.strategy must be all or ${strategy}`);\n if (section.strategy === strategy) positiveInteger(section[size], `listing.${key}.${size}`);\n }\n}\nfunction selection(value: Options, name: string): void {\n for (const key of [\"include\", \"exclude\"])\n if (\n value[key] !== undefined &&\n typeof value[key] !== \"string\" &&\n (!Array.isArray(value[key]) || value[key].some((item: unknown) => typeof item !== \"string\"))\n )\n throw new TypeError(`${name}.${key} must be a string or array of strings`);\n resolveIgnoreFiles(value.ignoreFiles);\n scalar(value.entryData, \"function\", `${name}.entryData`);\n if (value.sort !== undefined) {\n const sort = optionObject(value.sort, `${name}.sort`);\n optionKeys(sort, [\"field\", \"direction\", \"directoriesFirst\", \"nameMode\"], `${name}.sort`);\n scalar(sort.directoriesFirst, \"boolean\", `${name}.sort.directoriesFirst`);\n choice(sort.field, [\"name\", \"size\", \"modified\"], `${name}.sort.field`);\n choice(sort.direction, [\"asc\", \"desc\"], `${name}.sort.direction`);\n choice(sort.nameMode, [\"natural\", \"locale\", \"unicode\"], `${name}.sort.nameMode`);\n }\n}\nfunction requiredString(value: unknown, name: string): void {\n if (typeof value !== \"string\" || !value.length)\n throw new TypeError(`${name} must be a non-empty string`);\n}\nexport function validateTheme(\n value: unknown,\n name = \"options.theme\",\n): asserts value is ExplorerTheme {\n if (value === undefined) throw new TypeError(\"Core requires an explicit theme\");\n const theme = optionObject(value, name);\n requiredString(theme.name, `${name}.name`);\n if (typeof theme.render !== \"function\") throw new TypeError(`${name}.render must be a function`);\n scalar(theme.entryData, \"function\", `${name}.entryData`);\n scalar(theme.searchIndex, \"boolean\", `${name}.searchIndex`);\n if (theme.listing !== undefined) {\n const listing = optionObject(theme.listing, `${name}.listing`);\n optionKeys(listing, [\"pagination\"], `${name}.listing`);\n if (typeof listing.pagination !== \"boolean\")\n throw new TypeError(`${name}.listing.pagination must be a boolean`);\n }\n}\nconst generateKeys = {\n sourceDir: true,\n outputDir: true,\n theme: true,\n include: true,\n exclude: true,\n ignoreFiles: true,\n sort: true,\n entryData: true,\n fileHref: true,\n dryRun: true,\n outputPolicy: true,\n listing: true,\n metadata: true,\n base: true,\n mode: true,\n mirror: true,\n outputName: true,\n urlStrategy: true,\n symlinks: true,\n} satisfies Record<keyof GenerateOptions, true>;\nexport function validateGenerateOptions(value: unknown): asserts value is GenerateOptions {\n const options = optionObject(value, \"options\");\n optionKeys(options, Object.keys(generateKeys), \"options\");\n requiredString(options.sourceDir, \"options.sourceDir\");\n requiredString(options.outputDir, \"options.outputDir\");\n validateTheme(options.theme);\n selection(options, \"options\");\n for (const key of [\"fileHref\", \"metadata\"]) scalar(options[key], \"function\", `options.${key}`);\n for (const key of [\"dryRun\", \"mirror\"]) scalar(options[key], \"boolean\", `options.${key}`);\n scalar(options.base, \"string\", \"options.base\");\n choice(options.mode, [\"ssg\", \"mpa\"], \"options.mode\");\n choice(\n options.urlStrategy,\n Object.keys({\n base: true,\n \"html-base\": true,\n relative: true,\n } satisfies Record<NonNullable<GenerateOptions[\"urlStrategy\"]>, true>),\n \"options.urlStrategy\",\n );\n choice(options.outputPolicy, [\"owned\", \"replace\"], \"options.outputPolicy\");\n if (\n options.outputName !== undefined &&\n typeof options.outputName !== \"string\" &&\n typeof options.outputName !== \"function\"\n )\n throw new TypeError(\"options.outputName must be a string or function\");\n if (options.listing !== undefined && typeof options.listing !== \"function\")\n validateListingPlan(options.listing);\n if (options.symlinks !== undefined) {\n const links = optionObject(options.symlinks, \"options.symlinks\");\n optionKeys(links, [\"follow\", \"boundary\", \"onCycle\"], \"options.symlinks\");\n scalar(links.follow, \"boolean\", \"options.symlinks.follow\");\n choice(links.boundary, [\"root\", \"anywhere\"], \"options.symlinks.boundary\");\n choice(links.onCycle, [\"error\", \"skip\"], \"options.symlinks.onCycle\");\n }\n}\nconst serviceKeys = {\n root: true,\n include: true,\n exclude: true,\n ignoreFiles: true,\n sort: true,\n entryData: true,\n} satisfies Record<keyof DirectoryServiceOptions, true>;\nexport function validateDirectoryOptions(value: unknown): asserts value is DirectoryServiceOptions {\n const options = optionObject(value, \"options\");\n optionKeys(options, Object.keys(serviceKeys), \"options\");\n requiredString(options.root, \"options.root\");\n selection(options, \"options\");\n}\n","import { lstat, readlink, realpath, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Stats } from \"node:fs\";\nimport type { EntryKind, FileMetadata, FileSystemEntry, SymlinkMetadata } from \"./model.ts\";\nfunction entryKind(stats: Stats): EntryKind {\n if (stats.isDirectory()) return \"directory\";\n if (stats.isFile()) return \"file\";\n if (stats.isSymbolicLink()) return \"symlink\";\n return \"other\";\n}\n\nfunction metadata(stats: Stats): FileMetadata {\n return {\n device: stats.dev,\n groupId: stats.gid,\n hardLinkCount: stats.nlink,\n inode: stats.ino,\n mode: stats.mode,\n ownerId: stats.uid,\n size: stats.size,\n times: {\n accessedAt: stats.atime.toISOString(),\n changedAt: stats.ctime.toISOString(),\n createdAt: stats.birthtime.toISOString(),\n modifiedAt: stats.mtime.toISOString(),\n },\n };\n}\n\nexport function isInsideRoot(rootPath: string, candidatePath: string): boolean {\n const relative = path.relative(rootPath, candidatePath);\n return (\n relative === \"\" ||\n (relative !== \"..\" && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative))\n );\n}\n\nexport async function describeEntry({\n absolutePath,\n relativePath,\n rootRealPath,\n ancestors,\n followSymlinks,\n selectedPaths,\n}: {\n absolutePath: string;\n relativePath: string;\n rootRealPath: string;\n ancestors: ReadonlySet<string>;\n followSymlinks: boolean;\n selectedPaths: ReadonlySet<string> | null;\n}): Promise<FileSystemEntry> {\n const linkStats = await lstat(absolutePath);\n const kind = entryKind(linkStats);\n let symlink: SymlinkMetadata | null = null;\n\n if (kind === \"symlink\") {\n const target = await readlink(absolutePath);\n let resolvedPath: string | null = null;\n let targetKind: Exclude<EntryKind, \"symlink\"> | null = null;\n let targetSize: number | null = null;\n try {\n resolvedPath = await realpath(absolutePath);\n const targetStats = await stat(absolutePath);\n targetKind = entryKind(targetStats) as Exclude<EntryKind, \"symlink\">;\n targetSize = targetStats.size;\n } catch {\n // Broken and inaccessible links are represented as data.\n }\n const isOutsideRoot = resolvedPath === null || !isInsideRoot(rootRealPath, resolvedPath);\n const isCycle = resolvedPath !== null && ancestors.has(resolvedPath);\n const targetRelativePath =\n resolvedPath !== null && !isOutsideRoot\n ? path.relative(rootRealPath, resolvedPath).split(path.sep).join(\"/\")\n : null;\n const isTargetExcluded =\n targetRelativePath !== null &&\n selectedPaths !== null &&\n !selectedPaths.has(targetRelativePath);\n symlink = {\n target,\n resolvedPath,\n targetRelativePath,\n targetKind,\n targetSize:\n isOutsideRoot || isTargetExcluded || targetKind === \"directory\" ? null : targetSize,\n isBroken: resolvedPath === null,\n isCycle,\n isOutsideRoot,\n isTargetExcluded,\n wasFollowed:\n followSymlinks &&\n targetKind === \"directory\" &&\n !isCycle &&\n !isOutsideRoot &&\n !isTargetExcluded,\n };\n }\n\n return {\n name: path.basename(absolutePath),\n absolutePath,\n relativePath,\n kind,\n metadata: metadata(linkStats),\n symlink,\n };\n}\n","import type { JsonObject } from \"./json.ts\";\nimport { createHash } from \"node:crypto\";\nimport type { EntryKind, FileSystemEntry, ThemeContext, SortOptions } from \"./model.ts\";\nimport { copyJsonObject } from \"./json.ts\";\n\n/** Public transport fields only. Internal filesystem metadata must never be spread here. */\nexport interface ListingEntry {\n readonly data?: JsonObject;\n readonly presentation?: JsonObject;\n readonly id: string;\n readonly name: string;\n readonly kind: EntryKind;\n readonly href: string | null;\n readonly exitsExplorer: boolean;\n readonly size: number;\n readonly modifiedAt: string;\n readonly link: null | {\n readonly target: string;\n readonly targetKind: Exclude<EntryKind, \"symlink\"> | null;\n readonly targetSize: number | null;\n readonly unavailable: boolean;\n readonly cycle: boolean;\n };\n}\nexport interface ListingPlan {\n readonly html:\n | { readonly strategy: \"all\" }\n | { readonly strategy: \"paged\"; readonly pageSize: number };\n readonly data:\n | { readonly strategy: \"all\" }\n | { readonly strategy: \"blocks\"; readonly blockSize: number };\n}\nexport interface ListingPolicyContext {\n readonly operation?: \"build\" | \"server\";\n readonly directoryPath: string;\n readonly visibleCount: number;\n readonly dataBytes: number;\n readonly mode: \"ssg\" | \"mpa\";\n readonly supportsPagination: boolean;\n}\nexport type ListingPolicy = ListingPlan | ((context: ListingPolicyContext) => ListingPlan);\nexport interface ListingPage {\n readonly number: number;\n readonly count: number;\n readonly offset: number;\n readonly total: number;\n readonly href: string;\n readonly previousHref: string | null;\n readonly nextHref: string | null;\n}\nexport interface ListingContext {\n readonly revision: string;\n readonly manifestHref: string;\n readonly page: ListingPage;\n}\nexport interface ListingBlock {\n readonly version: 1;\n readonly revision: string;\n readonly offset: number;\n readonly total: number;\n readonly entries: readonly ListingEntry[];\n}\nexport interface ListingManifest {\n readonly version: 1;\n readonly revision: string;\n readonly directory: string;\n /** Resolve entry hrefs against this URL, resolved relative to the manifest URL. */\n readonly hrefBase: string;\n readonly total: number;\n readonly sort: Required<SortOptions>;\n /** Block hrefs are relative to the manifest URL. */\n readonly blocks: readonly {\n readonly href: string;\n readonly offset: number;\n readonly count: number;\n }[];\n}\n\nexport function projectListingEntry(\n entry: FileSystemEntry,\n context: Pick<ThemeContext, \"hrefFor\" | \"exitsExplorerFor\">,\n): ListingEntry {\n const link = entry.symlink;\n return {\n ...(entry.publicData === undefined ? {} : { data: copyJsonObject(entry.publicData) }),\n id: entry.relativePath,\n name: entry.name,\n kind: entry.kind,\n href: context.hrefFor(entry),\n exitsExplorer: context.exitsExplorerFor(entry),\n size: entry.metadata.size,\n modifiedAt: entry.metadata.times.modifiedAt,\n link:\n link === null\n ? null\n : {\n target: link.target,\n targetKind: link.targetKind,\n targetSize: link.targetSize ?? null,\n unavailable: link.isBroken || link.isOutsideRoot || Boolean(link.isTargetExcluded),\n cycle: link.isCycle,\n },\n };\n}\n\n/** Annotation providers receive public facts, not transport URLs or raw stat objects. */\nexport function entryDataFacts(\n entry: FileSystemEntry,\n): Omit<ListingEntry, \"href\" | \"exitsExplorer\" | \"presentation\" | \"data\"> {\n const {\n href: _href,\n exitsExplorer: _exits,\n data: _data,\n ...facts\n } = projectListingEntry(entry, { hrefFor: () => null, exitsExplorerFor: () => false });\n return facts;\n}\nexport { validateListingPlan } from \"./validation.ts\";\nexport function listingRevision(\n entries: readonly ListingEntry[],\n sort: Required<SortOptions>,\n hrefBase: string,\n blockSize: number,\n): string {\n return createHash(\"sha256\")\n .update(JSON.stringify({ version: 1, entries, sort, hrefBase, blockSize }))\n .digest(\"hex\");\n}\n","import { lstat, readdir, readFile, realpath, rename, rm, mkdir, open } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { isInsideRoot } from \"./filesystem.ts\";\n\nexport const outputMarker = \"__dirwell/ownership.json\";\nexport const outputMarkerContents = '{\"type\":\"dirwell-output\",\"version\":1}\\n';\n\nexport async function lockOutput(output: string) {\n const canonical = await canonicalPath(output);\n const lockPath = path.join(path.dirname(canonical), `.${path.basename(canonical)}-dirwell.lock`);\n await mkdir(path.dirname(lockPath), { recursive: true });\n let handle;\n try {\n handle = await open(lockPath, \"wx\");\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"EEXIST\")\n throw new Error(\n `Output is locked by another build: ${lockPath}. Wait for it to finish. Remove a stale lock only after confirming its owner has stopped; --force does not bypass locks.`,\n );\n throw error;\n }\n try {\n await handle.writeFile(JSON.stringify({ pid: process.pid }));\n } catch (error) {\n await handle.close();\n await rm(lockPath);\n throw error;\n }\n return {\n lockPath,\n async release() {\n await handle.close();\n await rm(lockPath);\n },\n };\n}\n\nexport async function canonicalPath(filename: string): Promise<string> {\n try {\n return await realpath(filename);\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n const parent = path.dirname(filename);\n if (parent === filename) throw error;\n return path.join(await canonicalPath(parent), path.basename(filename));\n }\n}\n\n/** Force permits output ownership replacement, never source containment violations. */\nexport async function checkOutput(\n source: string,\n output: string,\n policy: \"owned\" | \"replace\" = \"owned\",\n): Promise<boolean> {\n if (policy !== \"owned\" && policy !== \"replace\")\n throw new TypeError(\"outputPolicy must be owned or replace\");\n if (isInsideRoot(await canonicalPath(output), await realpath(source)))\n throw new Error(\"outputDir must not contain the sourceDir\");\n let stat;\n try {\n stat = await lstat(output);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") return false;\n throw error;\n }\n if (stat.isSymbolicLink() || !stat.isDirectory())\n throw new Error(\"outputDir must be a directory, not a file or symlink\");\n if ((await readdir(output)).length === 0 || policy === \"replace\") return true;\n try {\n const marker = path.join(output, outputMarker);\n if (\n !(await lstat(path.dirname(marker))).isSymbolicLink() &&\n !(await lstat(marker)).isSymbolicLink() &&\n (await readFile(marker, \"utf8\")) === outputMarkerContents\n )\n return true;\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n }\n throw new Error(\n \"Output is nonempty and not owned by Dirwell. Choose another directory or explicitly replace it with --force (-f) / outputPolicy: 'replace'.\",\n );\n}\n\n/** Keep a recoverable previous tree until the new tree is installed. */\nexport async function publishOutput(\n staged: string,\n output: string,\n source: string,\n policy: \"owned\" | \"replace\" = \"owned\",\n): Promise<void> {\n const exists = await checkOutput(source, output, policy);\n await mkdir(path.dirname(output), { recursive: true });\n const backup = path.join(\n path.dirname(output),\n `.${path.basename(output)}-previous-${randomUUID()}`,\n );\n if (exists) await rename(output, backup);\n try {\n await rename(staged, output);\n } catch (error) {\n if (exists) {\n try {\n await rename(backup, output);\n } catch (restoreError) {\n throw new AggregateError(\n [error, restoreError],\n `Publication failed; previous output is retained at ${backup}`,\n );\n }\n }\n throw error;\n }\n if (exists) await rm(backup, { recursive: true, force: true });\n}\n","import { validateGenerateOptions } from \"./validation.ts\";\nimport { copyJsonObject } from \"./json.ts\";\nimport { describeEntry, isInsideRoot } from \"./filesystem.ts\";\nimport {\n listingRevision,\n projectListingEntry,\n entryDataFacts,\n validateListingPlan,\n type ListingManifest,\n} from \"./listing.ts\";\nimport {\n cp,\n lstat,\n mkdtemp,\n mkdir,\n readFile,\n readdir,\n realpath,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport type {\n DirectoryData,\n EntryKind,\n ExplorerTheme,\n FileSystemEntry,\n GenerateOptions,\n NameSortMode,\n OutputNameResolver,\n SortOptions,\n ThemeContext,\n} from \"./model.ts\";\nimport { selectSourcePaths } from \"./filters.ts\";\nimport {\n checkOutput,\n publishOutput,\n outputMarker,\n outputMarkerContents,\n lockOutput,\n canonicalPath,\n} from \"./publication.ts\";\nimport type { BuildReport } from \"./model.ts\";\n\nconst indexPattern = /^index\\.html?$/i;\n\nconst defaultSort = {\n direction: \"asc\",\n directoriesFirst: true,\n field: \"name\",\n nameMode: \"natural\",\n} as const satisfies Required<SortOptions>;\n\nexport const defaultOutputName: OutputNameResolver = ({ entries }) =>\n entries.some((entry) => entry.kind === \"file\" && indexPattern.test(entry.name))\n ? entries.some((entry) => entry.name.toLowerCase() === \"_dirwell.html\")\n ? null\n : \"_dirwell.html\"\n : \"index.html\";\n\nfunction assertSafeOutputName(name: string): void {\n if (name.length === 0 || path.basename(name) !== name || name === \".\" || name === \"..\") {\n throw new Error(`Output name must be a single safe filename: ${name}`);\n }\n}\n\nfunction normalizeBase(value: string): string {\n if (value.includes(\"?\") || value.includes(\"#\")) {\n throw new TypeError(\"base must not contain a query string or fragment\");\n }\n if (/^https?:\\/\\//i.test(value)) {\n const url = new URL(value);\n url.pathname = `${url.pathname.replace(/\\/+$/, \"\")}/`;\n return url.href;\n }\n if (!value.startsWith(\"/\")) {\n throw new TypeError('base must start with \"/\" or be an absolute HTTP(S) URL');\n }\n return `${value.replace(/\\/+$/, \"\")}/`;\n}\n\nfunction encodeLogicalPath(value: string): string {\n return value\n .split(\"/\")\n .filter((segment) => segment.length > 0)\n .map((segment) => encodeURIComponent(segment))\n .join(\"/\");\n}\n\nfunction isDirectoryLike(entry: FileSystemEntry): boolean {\n return entry.kind === \"directory\" || entry.symlink?.targetKind === \"directory\";\n}\n\nfunction isUnavailableSymlink(entry: FileSystemEntry): boolean {\n return Boolean(\n entry.symlink?.isBroken || entry.symlink?.isOutsideRoot || entry.symlink?.isTargetExcluded,\n );\n}\n\nfunction compareUnicode(left: string, right: string): number {\n const leftPoints = [...left];\n const rightPoints = [...right];\n const length = Math.min(leftPoints.length, rightPoints.length);\n for (let index = 0; index < length; index += 1) {\n const difference =\n (leftPoints[index]?.codePointAt(0) ?? 0) - (rightPoints[index]?.codePointAt(0) ?? 0);\n if (difference !== 0) return difference;\n }\n return leftPoints.length - rightPoints.length;\n}\n\nfunction compareNames(left: string, right: string, mode: NameSortMode): number {\n if (mode === \"unicode\") return compareUnicode(left, right);\n return left.localeCompare(right, undefined, {\n numeric: mode === \"natural\",\n sensitivity: \"base\",\n });\n}\n\nexport function compareEntries(\n left: FileSystemEntry,\n right: FileSystemEntry,\n options: SortOptions = {},\n): number {\n const resolved = { ...defaultSort, ...options };\n if (resolved.directoriesFirst && isDirectoryLike(left) !== isDirectoryLike(right)) {\n return isDirectoryLike(left) ? -1 : 1;\n }\n let result: number;\n if (resolved.field === \"modified\") {\n result = left.metadata.times.modifiedAt.localeCompare(right.metadata.times.modifiedAt);\n } else if (resolved.field === \"size\") {\n result =\n (left.kind === \"directory\" ? 0 : left.metadata.size) -\n (right.kind === \"directory\" ? 0 : right.metadata.size);\n } else {\n result = compareNames(left.name, right.name, resolved.nameMode);\n }\n if (result === 0) result = compareNames(left.name, right.name, resolved.nameMode);\n return resolved.direction === \"asc\" ? result : -result;\n}\n\nfunction rawLinkFilename(entry: FileSystemEntry): string {\n return `${createHash(\"sha256\")\n .update(entry.relativePath)\n .update(\"\\0\")\n .update(entry.symlink?.target ?? \"\")\n .digest(\"hex\")\n .slice(0, 16)}.txt`;\n}\n\nexport async function generateExplorer(options: GenerateOptions): Promise<BuildReport> {\n return generateExplorerSkippingPaths(options, []);\n}\n\n/** Internal entry point for hosts that stage previews outside their published output. */\nexport async function generateExplorerSkippingPaths(\n options: GenerateOptions,\n ignoredPaths: readonly string[],\n): Promise<BuildReport> {\n validateGenerateOptions(options);\n const source = path.resolve(options.sourceDir),\n output = path.resolve(options.outputDir);\n await checkOutput(source, output, options.outputPolicy);\n if (options.dryRun) return generateExplorerUnlocked(options, ignoredPaths);\n const lock = await lockOutput(output);\n const lexicalLock = path.join(path.dirname(output), path.basename(lock.lockPath));\n try {\n return await generateExplorerUnlocked(options, [...ignoredPaths, lock.lockPath, lexicalLock]);\n } finally {\n await lock.release();\n }\n}\n\nasync function generateExplorerUnlocked(\n options: GenerateOptions,\n ignoredPaths: readonly string[],\n): Promise<BuildReport> {\n const sourceDir = await realpath(path.resolve(options.sourceDir));\n const outputDir = await canonicalPath(path.resolve(options.outputDir));\n const ignoredSourcePaths = ignoredPaths.map((value) => path.resolve(value));\n const rootRealPath = await realpath(sourceDir);\n const replacesOutput = await checkOutput(sourceDir, outputDir, options.outputPolicy);\n const outputName = options.outputName ?? defaultOutputName;\n const resolveOutputName: OutputNameResolver =\n typeof outputName === \"string\" ? () => outputName : outputName;\n const theme: ExplorerTheme = options.theme;\n if (theme === undefined) throw new TypeError(\"Core requires an explicit theme\");\n const mode = options.mode ?? \"ssg\";\n const urlStrategy = options.urlStrategy ?? \"relative\";\n const base = normalizeBase(options.base ?? \"/\");\n const followSymlinks = options.symlinks?.follow ?? false;\n const boundary = options.symlinks?.boundary ?? \"root\";\n const onCycle = options.symlinks?.onCycle ?? \"skip\";\n const filtersActive =\n options.include !== undefined ||\n options.exclude !== undefined ||\n (options.ignoreFiles?.length ?? 0) > 0 ||\n ignoredSourcePaths.length > 0;\n const plans: Array<{\n readonly directory: DirectoryData;\n readonly logicalDir: string;\n readonly outputName: string | null;\n }> = [];\n if (isInsideRoot(outputDir, sourceDir)) {\n throw new Error(\"outputDir must not contain the sourceDir\");\n }\n try {\n await lstat(path.join(sourceDir, \"__dirwell\"));\n throw new Error('Dirwell reserves the source-root path \"__dirwell\"');\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n // The reserved asset path is available.\n } else {\n throw error;\n }\n }\n const outputIsWithinSource = isInsideRoot(sourceDir, outputDir);\n const selection = await selectSourcePaths(\n sourceDir,\n outputDir,\n options.include,\n options.exclude,\n ignoredSourcePaths,\n options.ignoreFiles,\n );\n const stageParent = outputIsWithinSource ? path.dirname(sourceDir) : path.dirname(outputDir);\n if (!options.dryRun) await mkdir(stageParent, { recursive: true });\n const stagedOutputDir = options.dryRun\n ? null\n : await mkdtemp(path.join(stageParent, `.${path.basename(outputDir)}-dirwell-`));\n const buildOutputDir = stagedOutputDir!;\n\n try {\n if (!options.dryRun && (options.mirror ?? true)) {\n await rm(buildOutputDir, { recursive: true, force: true });\n await mkdir(buildOutputDir, { recursive: true });\n await cp(sourceDir, buildOutputDir, {\n recursive: true,\n dereference: false,\n preserveTimestamps: true,\n filter: (sourcePath) => {\n const relativePath = path.relative(sourceDir, sourcePath).split(path.sep).join(\"/\");\n return (\n selection.selected.has(relativePath) &&\n (!selection.symlinks.has(relativePath) || selection.mirroredSymlinks.has(relativePath))\n );\n },\n });\n }\n } catch (error) {\n if (stagedOutputDir !== null) await rm(stagedOutputDir, { recursive: true, force: true });\n throw error;\n }\n\n async function visit(\n logicalDir: string,\n physicalDir: string,\n ancestors: ReadonlySet<string>,\n ): Promise<void> {\n const physicalRealPath = await realpath(physicalDir);\n if (ancestors.has(physicalRealPath)) {\n if (onCycle === \"error\") throw new Error(`Symlink cycle at ${logicalDir}`);\n return;\n }\n\n const nextAncestors = new Set(ancestors).add(physicalRealPath);\n const names = (await readdir(physicalDir)).filter((name) => {\n if (outputIsWithinSource && isInsideRoot(outputDir, path.join(physicalDir, name)))\n return false;\n if (ignoredSourcePaths.some((value) => isInsideRoot(value, path.join(physicalDir, name))))\n return false;\n if (!filtersActive) return true;\n const relativePath = path.relative(rootRealPath, path.join(physicalRealPath, name));\n return selection.selected.has(relativePath.split(path.sep).join(\"/\"));\n });\n const entries = await Promise.all(\n names.map(async (name) => {\n const entry = await describeEntry({\n absolutePath: path.join(physicalDir, name),\n relativePath: path.posix.join(logicalDir, name),\n rootRealPath,\n ancestors: nextAncestors,\n followSymlinks,\n selectedPaths: filtersActive ? selection.selected : null,\n });\n return options.entryData === undefined\n ? entry\n : {\n ...entry,\n publicData: copyJsonObject(\n await options.entryData(entryDataFacts(entry), {\n operation: \"build\",\n directoryPath: logicalDir,\n }),\n ),\n };\n }),\n );\n entries.sort(\n (left, right) =>\n compareEntries(left, right, options.sort) ||\n (options.listing === undefined ? 0 : compareUnicode(left.relativePath, right.relativePath)),\n );\n\n const describedCurrent = await describeEntry({\n absolutePath: physicalDir,\n relativePath: logicalDir,\n rootRealPath,\n ancestors,\n followSymlinks,\n selectedPaths: filtersActive ? selection.selected : null,\n });\n if (describedCurrent.kind !== \"directory\") {\n throw new Error(`${physicalDir} is not a directory`);\n }\n const current: DirectoryData[\"current\"] = {\n ...describedCurrent,\n kind: \"directory\",\n };\n\n const root = await describeEntry({\n absolutePath: sourceDir,\n relativePath: \"\",\n rootRealPath,\n ancestors: new Set(),\n followSymlinks,\n selectedPaths: filtersActive ? selection.selected : null,\n });\n const parent =\n logicalDir === \"\"\n ? null\n : await describeEntry({\n absolutePath: path.dirname(physicalDir),\n relativePath:\n path.posix.dirname(logicalDir) === \".\" ? \"\" : path.posix.dirname(logicalDir),\n rootRealPath,\n ancestors,\n followSymlinks,\n selectedPaths: filtersActive ? selection.selected : null,\n });\n const directory: DirectoryData = {\n root,\n current,\n parent,\n depth: logicalDir === \"\" ? 0 : logicalDir.split(\"/\").length,\n entries,\n };\n\n const name = await resolveOutputName(directory);\n if (name !== null) assertSafeOutputName(name);\n plans.push({ directory, logicalDir, outputName: name });\n\n for (const entry of entries) {\n if (entry.kind === \"directory\") {\n await visit(path.posix.join(logicalDir, entry.name), entry.absolutePath, nextAncestors);\n continue;\n }\n if (!followSymlinks || entry.symlink?.targetKind !== \"directory\") continue;\n const physicalLinkPath = path\n .relative(rootRealPath, path.join(physicalRealPath, entry.name))\n .split(path.sep)\n .join(\"/\");\n if ((options.mirror ?? true) && !selection.mirroredSymlinks.has(physicalLinkPath)) continue;\n if (entry.symlink.isCycle) {\n if (onCycle === \"error\") throw new Error(`Symlink cycle at ${entry.relativePath}`);\n continue;\n }\n if (entry.symlink.resolvedPath === null) continue;\n if (boundary === \"root\" && entry.symlink.isOutsideRoot) continue;\n if (\n filtersActive &&\n (entry.symlink.targetRelativePath === null ||\n !selection.selected.has(entry.symlink.targetRelativePath))\n )\n continue;\n // Mirrored internal aliases already resolve to the target's generated page.\n // Writing an alias page through the copied symlink would overwrite that page.\n if (\n (options.mirror ?? true) &&\n entry.symlink.targetRelativePath !== null &&\n !entry.symlink.isOutsideRoot\n )\n continue;\n await visit(\n path.posix.join(logicalDir, entry.name),\n entry.symlink.resolvedPath,\n nextAncestors,\n );\n }\n }\n\n try {\n await visit(\"\", sourceDir, new Set());\n\n const report: BuildReport = {\n sourceDir,\n outputDir,\n theme: theme.name,\n dryRun: options.dryRun ?? false,\n mirror: options.mirror ?? true,\n replacesOutput,\n selectedPaths: [...selection.selected].filter(Boolean).sort(),\n pages: plans.map((plan) => ({ directory: plan.logicalDir, outputName: plan.outputName })),\n };\n if (options.dryRun) return report;\n\n const generatedPages = new Map(\n plans\n .filter(\n (plan): plan is typeof plan & { readonly outputName: string } => plan.outputName !== null,\n )\n .map((plan) => [plan.logicalDir, plan.outputName]),\n );\n const generatedDirectories = new Set(generatedPages.keys());\n const pagePathForDirectory = (logicalPath: string): string => {\n const pageName = generatedPages.get(logicalPath);\n return pageName === undefined || pageName === \"index.html\"\n ? logicalPath\n : path.posix.join(logicalPath, pageName);\n };\n const sourceKinds = new Map<string, string>();\n for (const { directory } of plans)\n for (const entry of directory.entries) {\n const sourcePath = path.relative(sourceDir, entry.absolutePath).split(path.sep).join(\"/\");\n if (selection.selected.has(sourcePath)) sourceKinds.set(sourcePath, entry.kind);\n }\n const metadataResolver = await options.metadata?.({ sourceDir, sourceKinds });\n const sharedAssets = new Map<string, string | Uint8Array>();\n const rawLinkFiles = new Map<string, string>();\n const searchEntries = new Map<\n string,\n {\n href: string | null;\n exitsExplorer: boolean;\n isLink: boolean;\n kind: EntryKind;\n modifiedAt: string;\n name: string;\n path: string;\n size: number;\n target: string | null;\n targetKind: Exclude<EntryKind, \"symlink\"> | null;\n targetSize: number | null;\n isTargetUnavailable: boolean;\n isCycle: boolean;\n }\n >();\n\n const fileHrefs = new Map<string, string | null>();\n const mappedFileHref = (logicalPath: string): string | null => {\n if (!fileHrefs.has(logicalPath)) {\n const href = options.fileHref!(logicalPath);\n if (\n href !== null &&\n (typeof href !== \"string\" ||\n href.length === 0 ||\n href.includes(\"\\\\\") ||\n Array.from(href).some((character) => character.charCodeAt(0) < 32) ||\n ![\"http:\", \"https:\"].includes(new URL(href, \"https://dirwell.invalid/\").protocol))\n )\n throw new TypeError(\n \"fileHref must return a synchronous HTTP(S), root-relative or relative URL, or null\",\n );\n fileHrefs.set(logicalPath, href);\n }\n return fileHrefs.get(logicalPath)!;\n };\n\n for (const { directory, logicalDir } of theme.searchIndex === false ? [] : plans) {\n for (const entry of directory.entries) {\n if (searchEntries.has(entry.relativePath)) continue;\n const targetLogicalPath = isUnavailableSymlink(entry)\n ? null\n : entry.symlink?.targetRelativePath !== null && entry.symlink !== null\n ? entry.symlink.targetRelativePath\n : path.posix.join(logicalDir, entry.name);\n const directoryLike = isDirectoryLike(entry);\n const linkedPath =\n directoryLike && targetLogicalPath !== null\n ? pagePathForDirectory(targetLogicalPath)\n : targetLogicalPath;\n let href: string | null = null;\n if (entry.symlink !== null && isUnavailableSymlink(entry)) {\n const filename = rawLinkFilename(entry);\n rawLinkFiles.set(filename, entry.symlink.target);\n href = `raw-links/${filename}`;\n } else if (linkedPath !== null) {\n href =\n linkedPath === \"\"\n ? \"../\"\n : `../${encodeLogicalPath(linkedPath)}${directoryLike && linkedPath === targetLogicalPath ? \"/\" : \"\"}`;\n if (!directoryLike && options.fileHref !== undefined) href = mappedFileHref(linkedPath);\n }\n searchEntries.set(entry.relativePath, {\n exitsExplorer:\n isUnavailableSymlink(entry) ||\n (targetLogicalPath !== null &&\n (!directoryLike || !generatedDirectories.has(targetLogicalPath))),\n href,\n isLink: entry.kind === \"symlink\",\n kind: entry.kind,\n modifiedAt: entry.metadata.times.modifiedAt,\n name: entry.name,\n path: entry.relativePath,\n size: entry.metadata.size,\n target: entry.symlink?.target ?? null,\n targetKind: entry.symlink?.targetKind ?? null,\n targetSize: entry.symlink?.targetSize ?? null,\n isTargetUnavailable: isUnavailableSymlink(entry),\n isCycle: entry.symlink?.isCycle ?? false,\n });\n }\n }\n\n for (const plan of plans) {\n const { directory, logicalDir, outputName: name } = plan;\n const sourceEntryNames = new Set(directory.entries.map((entry) => entry.name.toLowerCase()));\n if (name === null) continue;\n\n const targetLogicalPathFor = (entry: FileSystemEntry): string | null => {\n if (isUnavailableSymlink(entry)) return null;\n if (entry.symlink?.targetRelativePath !== null && entry.symlink !== null) {\n return entry.symlink.targetRelativePath;\n }\n return path.posix.join(logicalDir, entry.name);\n };\n const hrefForLogicalPath = (targetPath: string, directoryLike: boolean): string => {\n const linkedPath = directoryLike ? pagePathForDirectory(targetPath) : targetPath;\n const linkToDirectory = directoryLike && linkedPath === targetPath;\n if (urlStrategy === \"relative\") {\n const relativeTarget = path.posix.relative(\n logicalDir === \"\" ? \".\" : logicalDir,\n linkedPath === \"\" ? \".\" : linkedPath,\n );\n const encodedTarget = relativeTarget\n .split(\"/\")\n .map((segment) =>\n segment === \".\" || segment === \"..\" ? segment : encodeURIComponent(segment),\n )\n .join(\"/\");\n return `${encodedTarget || \".\"}${linkToDirectory ? \"/\" : \"\"}`;\n }\n const encodedTarget = encodeLogicalPath(linkedPath);\n if (encodedTarget === \"\") {\n return urlStrategy === \"base\" ? base : \"./\";\n }\n const suffix = `${encodedTarget}${linkToDirectory ? \"/\" : \"\"}`;\n return urlStrategy === \"base\" ? `${base}${suffix}` : suffix;\n };\n const hrefFor = (entry: FileSystemEntry): string | null => {\n if (entry.symlink !== null && isUnavailableSymlink(entry)) {\n const filename = rawLinkFilename(entry);\n rawLinkFiles.set(filename, entry.symlink.target);\n return hrefForLogicalPath(path.posix.join(\"__dirwell\", \"raw-links\", filename), false);\n }\n const targetLogicalPath = targetLogicalPathFor(entry);\n if (targetLogicalPath === null) return null;\n const directoryLike =\n entry.kind === \"directory\" || entry.symlink?.targetKind === \"directory\";\n if (!directoryLike && options.fileHref !== undefined)\n return mappedFileHref(targetLogicalPath);\n return hrefForLogicalPath(targetLogicalPath, directoryLike);\n };\n const baseContext: ThemeContext = {\n operation: \"build\",\n directory,\n documentBaseHref: urlStrategy === \"html-base\" ? base : null,\n outputName: name,\n mode,\n searchIndexHref: hrefForLogicalPath(\n path.posix.join(\"__dirwell\", \"search-index.json\"),\n false,\n ),\n sort: { ...defaultSort, ...options.sort },\n assetHref: (assetName) => {\n assertSafeOutputName(assetName);\n return hrefForLogicalPath(\n mode === \"ssg\"\n ? path.posix.join(logicalDir, assetName)\n : path.posix.join(\"__dirwell\", assetName),\n false,\n );\n },\n hrefFor,\n hrefForDirectory: (relativePath) => hrefForLogicalPath(relativePath, true),\n hasPageForDirectory: (relativePath) => generatedDirectories.has(relativePath),\n exitsExplorerFor: (entry) => {\n if (isUnavailableSymlink(entry)) return true;\n const targetLogicalPath = targetLogicalPathFor(entry);\n const directoryLike =\n entry.kind === \"directory\" || entry.symlink?.targetKind === \"directory\";\n return (\n targetLogicalPath !== null &&\n (!directoryLike || !generatedDirectories.has(targetLogicalPath))\n );\n },\n };\n const targetDir = path.join(buildOutputDir, logicalDir);\n await mkdir(targetDir, { recursive: true });\n const sort = baseContext.sort;\n let revision = \"\";\n let manifestHref = \"\";\n let pageSize = Math.max(1, directory.entries.length);\n if (options.listing !== undefined) {\n const records = directory.entries.map((entry) => {\n const projected = projectListingEntry(entry, baseContext);\n return theme.entryData === undefined\n ? projected\n : {\n ...projected,\n presentation: copyJsonObject(\n theme.entryData(projected, {\n mode: baseContext.mode,\n outputName: baseContext.outputName,\n assetHref: baseContext.assetHref,\n hrefForDirectory: baseContext.hrefForDirectory,\n documentBaseHref: baseContext.documentBaseHref,\n directoryPath: logicalDir,\n }),\n ),\n };\n });\n const candidate =\n typeof options.listing === \"function\"\n ? options.listing({\n directoryPath: logicalDir,\n visibleCount: records.length,\n dataBytes: Buffer.byteLength(JSON.stringify(records)),\n mode,\n operation: \"build\",\n supportsPagination: theme.listing?.pagination === true,\n })\n : options.listing;\n validateListingPlan(candidate);\n if (candidate.html.strategy === \"paged\") {\n if (theme.listing?.pagination !== true)\n throw new Error(`Theme ${theme.name} does not support listing pagination`);\n pageSize = candidate.html.pageSize;\n }\n const directoryId = createHash(\"sha256\").update(logicalDir).digest(\"hex\");\n const manifestDirectory = path.posix.join(\"__dirwell\", \"listing\", directoryId);\n // Relative records belong to the document directory, not to the JSON asset directory.\n const hrefBase =\n urlStrategy === \"relative\"\n ? `../../../${encodeLogicalPath(logicalDir)}${logicalDir ? \"/\" : \"\"}`\n : base;\n const manifestPath = path.posix.join(manifestDirectory, \"manifest.json\");\n manifestHref = hrefForLogicalPath(manifestPath, false);\n const blocks: Array<ListingManifest[\"blocks\"][number]> = [];\n const blockSize =\n candidate.data.strategy === \"blocks\"\n ? candidate.data.blockSize\n : Math.max(1, records.length);\n revision = listingRevision(records, sort, hrefBase, blockSize);\n const outputListingDir = path.join(buildOutputDir, manifestDirectory);\n await mkdir(outputListingDir, { recursive: true });\n for (let offset = 0; offset < records.length || offset === 0; offset += blockSize) {\n const entries = records.slice(offset, offset + blockSize);\n const filename = `${revision}-${blocks.length}.json`;\n blocks.push({ href: filename, offset, count: entries.length });\n await writeFile(\n path.join(outputListingDir, filename),\n JSON.stringify({ version: 1, revision, offset, total: records.length, entries }),\n );\n }\n const manifest: ListingManifest = {\n version: 1,\n revision,\n directory: logicalDir,\n hrefBase,\n total: records.length,\n sort,\n blocks,\n };\n await writeFile(path.join(outputListingDir, \"manifest.json\"), JSON.stringify(manifest));\n }\n const pageCount = Math.max(1, Math.ceil(directory.entries.length / pageSize));\n const pagePrefix = `__dirwell-page-${createHash(\"sha256\").update(name).digest(\"hex\").slice(0, 16)}`;\n const pageNames = Array.from({ length: pageCount }, (_, index) =>\n index === 0 ? name : `${pagePrefix}-${index + 1}.html`,\n );\n for (const pageName of pageNames.slice(1)) {\n if (directory.entries.some((entry) => entry.name.toLowerCase() === pageName.toLowerCase()))\n throw new Error(\n `Listing page conflicts with source entry: ${path.posix.join(logicalDir, pageName)}`,\n );\n }\n const pagedAssets = new Map<string, Buffer>();\n for (const [index, pageName] of pageNames.entries()) {\n const pagePath = path.posix.join(logicalDir, pageName);\n const metadata = await metadataResolver?.resolve(\n directory,\n (outputPath) => hrefForLogicalPath(outputPath, false),\n pageName === \"index.html\" ? (logicalDir ? `${logicalDir}/` : \"\") : pagePath,\n );\n const pageHref = (number: number): string =>\n hrefForLogicalPath(path.posix.join(logicalDir, pageNames[number] ?? name), false);\n const page = await theme.render({\n ...baseContext,\n ...(metadata === undefined ? {} : { metadata }),\n outputName: pageName,\n directory:\n options.listing === undefined\n ? directory\n : {\n ...directory,\n entries: directory.entries.slice(index * pageSize, (index + 1) * pageSize),\n },\n ...(options.listing === undefined\n ? {}\n : {\n listing: {\n revision,\n manifestHref,\n page: {\n number: index + 1,\n count: pageCount,\n offset: index * pageSize,\n total: directory.entries.length,\n href: pageHref(index),\n previousHref: index === 0 ? null : pageHref(index - 1),\n nextHref: index + 1 === pageCount ? null : pageHref(index + 1),\n },\n },\n }),\n });\n await writeFile(path.join(targetDir, pageName), page.html);\n for (const [assetName, contents] of Object.entries(page.assets ?? {})) {\n assertSafeOutputName(assetName);\n if (\n (options.listing !== undefined || theme.listing?.pagination === true) &&\n mode === \"ssg\" &&\n sourceEntryNames.has(assetName.toLowerCase())\n )\n throw new Error(`Theme asset conflicts with source entry: ${assetName}`);\n if (\n options.listing !== undefined &&\n pageNames.some((pageName) => pageName.toLowerCase() === assetName.toLowerCase())\n )\n throw new Error(`Theme asset conflicts with listing page: ${assetName}`);\n if (options.listing !== undefined && pageCount > 1) {\n const bytes = Buffer.from(contents);\n const existing = pagedAssets.get(assetName);\n if (existing !== undefined && !existing.equals(bytes))\n throw new Error(`Theme emitted conflicting paginated asset: ${assetName}`);\n pagedAssets.set(assetName, bytes);\n }\n if (mode === \"ssg\") {\n await writeFile(path.join(targetDir, assetName), contents);\n } else {\n const bytes = Buffer.from(contents);\n const existing = sharedAssets.get(assetName);\n if (existing !== undefined && !Buffer.from(existing).equals(bytes)) {\n throw new Error(`Theme emitted conflicting shared asset: ${assetName}`);\n }\n sharedAssets.set(assetName, bytes);\n }\n }\n }\n }\n\n if (mode === \"mpa\" && sharedAssets.size > 0) {\n const assetDirectory = path.join(buildOutputDir, \"__dirwell\");\n await mkdir(assetDirectory, { recursive: true });\n for (const [assetName, contents] of sharedAssets) {\n await writeFile(path.join(assetDirectory, assetName), contents);\n }\n }\n\n for (const [filename, bytes] of metadataResolver?.assets ?? []) {\n const parts = filename.split(\"/\");\n for (let index = 1; index <= parts.length; index++) {\n const prefix = parts.slice(0, index).join(\"/\");\n if (selection.selected.has(prefix))\n throw new Error(`Metadata image conflicts with source entry: ${filename}`);\n const candidate = path.join(buildOutputDir, prefix);\n try {\n const info = await lstat(candidate);\n if (info.isSymbolicLink() || index === parts.length || !info.isDirectory())\n throw new Error(`Metadata image conflicts with generated output: ${filename}`);\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n }\n }\n const destination = path.join(buildOutputDir, filename);\n await mkdir(path.dirname(destination), { recursive: true });\n await writeFile(destination, bytes);\n }\n\n if (rawLinkFiles.size > 0) {\n const rawLinkDirectory = path.join(buildOutputDir, \"__dirwell\", \"raw-links\");\n await mkdir(rawLinkDirectory, { recursive: true });\n for (const [filename, target] of rawLinkFiles) {\n await writeFile(path.join(rawLinkDirectory, filename), target);\n }\n }\n if (theme.searchIndex !== false) {\n const generatedAssetDirectory = path.join(buildOutputDir, \"__dirwell\");\n await mkdir(generatedAssetDirectory, { recursive: true });\n const indexedEntries = [...searchEntries.values()];\n const shards: string[] = [];\n for (let offset = 0; offset < indexedEntries.length; offset += 512) {\n const filename = `search-${String(shards.length).padStart(5, \"0\")}.json`;\n shards.push(filename);\n await writeFile(\n path.join(generatedAssetDirectory, filename),\n JSON.stringify({ entries: indexedEntries.slice(offset, offset + 512) }),\n );\n }\n await writeFile(\n path.join(generatedAssetDirectory, \"search-index.json\"),\n JSON.stringify({ count: indexedEntries.length, shards, version: 3 }),\n );\n }\n\n await mkdir(path.join(buildOutputDir, \"__dirwell\"), { recursive: true });\n await writeFile(path.join(buildOutputDir, outputMarker), outputMarkerContents);\n await publishOutput(buildOutputDir, outputDir, sourceDir, options.outputPolicy);\n return report;\n } finally {\n if (stagedOutputDir !== null) await rm(stagedOutputDir, { recursive: true, force: true });\n }\n}\n\nexport async function readGeneratedPage(filePath: string): Promise<string> {\n return readFile(filePath, \"utf8\");\n}\n","/** Escape untrusted text for HTML/XML text nodes and double-quoted attributes. */\nexport function escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\");\n}\n","/** Some Windows Node/libuv versions omit the path-stat device ID but retain the file ID. */\nexport function fileIdentityMatches(\n before: { readonly device: number; readonly inode: number },\n descriptor: { readonly dev: number; readonly ino: number },\n platform = process.platform,\n): boolean {\n if (before.inode !== descriptor.ino) return false;\n if (before.device === descriptor.dev) return true;\n return platform === \"win32\" && before.device === 0 && before.inode !== 0;\n}\n","import { validateDirectoryOptions } from \"./validation.ts\";\nimport { readdir, realpath, open, type FileHandle } from \"node:fs/promises\";\nimport { constants } from \"node:fs\";\nimport { fileIdentityMatches } from \"./file-identity.ts\";\nimport path from \"node:path\";\nimport { describeEntry, isInsideRoot } from \"./filesystem.ts\";\nimport {\n selectSourcePaths,\n resolveIgnoreFiles,\n createIgnoreMatcher,\n normalizePathPatterns,\n} from \"./filters.ts\";\nimport { compareEntries } from \"./generator.ts\";\nimport { entryDataFacts } from \"./listing.ts\";\nimport { copyJsonObject } from \"./json.ts\";\nimport type {\n DirectoryData,\n FileSystemEntry,\n SortOptions,\n IgnoreFile,\n EntryDataProvider,\n} from \"./model.ts\";\n\nexport interface DirectoryServiceOptions {\n readonly entryData?: EntryDataProvider;\n readonly root: string;\n readonly include?: string | readonly string[];\n readonly exclude?: string | readonly string[];\n readonly ignoreFiles?: readonly IgnoreFile[];\n readonly sort?: SortOptions;\n}\nexport interface DirectoryService {\n readonly resolvePath: (logicalPath: string) => Promise<string>;\n readonly openFile: (logicalPath: string) => Promise<{\n readonly entry: FileSystemEntry;\n readonly handle: FileHandle;\n readonly canonicalPath: string;\n }>;\n readonly getEntry: (logicalPath: string) => Promise<FileSystemEntry>;\n readonly listDirectory: (logicalPath: string) => Promise<DirectoryData>;\n}\nexport class DirectoryAccessError extends Error {\n override readonly name = \"DirectoryAccessError\";\n}\nfunction assertLogicalPath(value: string): void {\n if (\n value.startsWith(\"/\") ||\n value.includes(\"\\\\\") ||\n value.includes(\"\\0\") ||\n value\n .split(\"/\")\n .some((segment) => segment === \".\" || segment === \"..\" || (segment === \"\" && value !== \"\")) ||\n /^[a-z]:/i.test(value) ||\n value === \"__dirwell\" ||\n value.startsWith(\"__dirwell/\")\n )\n throw new DirectoryAccessError(\"Unavailable path\");\n}\n/** Live reads; no watcher, recursive stat snapshot, output tree or implicit cache. */\nexport async function createDirectoryService(\n options: DirectoryServiceOptions,\n): Promise<DirectoryService> {\n validateDirectoryOptions(options);\n const root = await realpath(options.root);\n const ignoreFiles = resolveIgnoreFiles(options.ignoreFiles);\n // Validate explicit sources before an HTTP host starts accepting requests.\n await createIgnoreMatcher(ignoreFiles);\n normalizePathPatterns(options.include, \"include\");\n normalizePathPatterns(options.exclude, \"exclude\");\n const selected = async () => {\n const matcher = await createIgnoreMatcher(ignoreFiles);\n if (\n normalizePathPatterns(options.include, \"include\").length === 0 &&\n normalizePathPatterns(options.exclude, \"exclude\").length === 0 &&\n !matcher.hasRules\n )\n return null;\n return (\n await selectSourcePaths(\n root,\n path.join(root, \"__dirwell\"),\n options.include,\n options.exclude,\n [],\n ignoreFiles,\n matcher,\n )\n ).selected;\n };\n async function describe(\n logicalPath: string,\n selection: ReadonlySet<string> | null,\n ): Promise<FileSystemEntry> {\n assertLogicalPath(logicalPath);\n if (selection !== null && !selection.has(logicalPath))\n throw new DirectoryAccessError(\"Unavailable path\");\n const absolutePath = path.join(root, logicalPath);\n const parent = logicalPath === \"\" ? root : await realpath(path.dirname(absolutePath));\n if (!isInsideRoot(root, parent)) throw new DirectoryAccessError(\"Unavailable path\");\n const ancestors = new Set<string>([root]);\n if (logicalPath !== \"\") {\n const segments = logicalPath.split(\"/\").slice(0, -1);\n for (let length = 1; length <= segments.length; length++)\n ancestors.add(await realpath(path.join(root, ...segments.slice(0, length))));\n }\n return describeEntry({\n absolutePath,\n relativePath: logicalPath,\n rootRealPath: root,\n ancestors,\n followSymlinks: false,\n selectedPaths: selection,\n });\n }\n return {\n async resolvePath(logicalPath) {\n const selection = await selected();\n const entry = await describe(logicalPath, selection);\n if (\n entry.symlink &&\n (entry.symlink.isBroken || entry.symlink.isOutsideRoot || entry.symlink.isTargetExcluded)\n )\n throw new DirectoryAccessError(\"Unavailable target\");\n const resolved = await realpath(entry.absolutePath);\n if (!isInsideRoot(root, resolved)) throw new DirectoryAccessError(\"Unavailable target\");\n const canonical = path.relative(root, resolved).split(path.sep).join(\"/\");\n if (selection !== null && !selection.has(canonical))\n throw new DirectoryAccessError(\"Unavailable target\");\n return canonical;\n },\n async openFile(logicalPath) {\n assertLogicalPath(logicalPath);\n const selection = await selected();\n let entry = await describe(logicalPath, selection);\n if (entry.symlink !== null) {\n if (\n entry.symlink.isBroken ||\n entry.symlink.isOutsideRoot ||\n entry.symlink.isTargetExcluded ||\n entry.symlink.targetRelativePath === null\n )\n throw new DirectoryAccessError(\"Unavailable file\");\n entry = await describe(entry.symlink.targetRelativePath, selection);\n }\n if (entry.kind !== \"file\") throw new DirectoryAccessError(\"Unavailable file\");\n const handle = await open(\n entry.absolutePath,\n constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0),\n );\n try {\n const stats = await handle.stat();\n const resolved = await realpath(entry.absolutePath);\n if (\n !stats.isFile() ||\n !isInsideRoot(root, resolved) ||\n !fileIdentityMatches(entry.metadata, stats)\n )\n throw new DirectoryAccessError(\"File changed before opening\");\n return {\n entry,\n handle,\n canonicalPath: path.relative(root, resolved).split(path.sep).join(\"/\"),\n };\n } catch (error) {\n await handle.close();\n throw error;\n }\n },\n async getEntry(logicalPath) {\n assertLogicalPath(logicalPath);\n return describe(logicalPath, await selected());\n },\n async listDirectory(logicalPath) {\n assertLogicalPath(logicalPath);\n const selection = await selected();\n const entry = await describe(logicalPath, selection);\n if (entry.kind !== \"directory\") throw new DirectoryAccessError(\"Unavailable directory\");\n const physical = await realpath(entry.absolutePath);\n if (!isInsideRoot(root, physical)) throw new DirectoryAccessError(\"Unavailable directory\");\n const names = (await readdir(physical)).filter(\n (name) => logicalPath !== \"\" || name !== \"__dirwell\",\n );\n const described = await Promise.all(\n names\n .filter((name) => selection === null || selection.has(path.posix.join(logicalPath, name)))\n .map(async (name) => {\n let entry: FileSystemEntry;\n try {\n entry = await describe(path.posix.join(logicalPath, name), selection);\n } catch (error) {\n // An enumerated child may disappear before stat; the directory is still available.\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") return null;\n throw error;\n }\n return options.entryData === undefined\n ? entry\n : {\n ...entry,\n publicData: copyJsonObject(\n await options.entryData(entryDataFacts(entry), {\n operation: \"server\",\n directoryPath: logicalPath,\n }),\n ),\n };\n }),\n );\n const entries = described.filter((entry): entry is FileSystemEntry => entry !== null);\n entries.sort(\n (left, right) =>\n compareEntries(left, right, options.sort) ||\n (left.relativePath < right.relativePath\n ? -1\n : left.relativePath > right.relativePath\n ? 1\n : 0),\n );\n return {\n root: await describe(\"\", selection),\n current: { ...entry, kind: \"directory\" },\n parent:\n logicalPath === \"\"\n ? null\n : await describe(\n path.posix.dirname(logicalPath) === \".\" ? \"\" : path.posix.dirname(logicalPath),\n selection,\n ),\n depth: logicalPath === \"\" ? 0 : logicalPath.split(\"/\").length,\n entries,\n };\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -96,6 +96,8 @@ interface SymlinkMetadata {
|
|
|
96
96
|
readonly wasFollowed: boolean;
|
|
97
97
|
}
|
|
98
98
|
interface FileSystemEntry {
|
|
99
|
+
/** Explicitly supplied public annotations, distinct from private filesystem facts. */
|
|
100
|
+
readonly publicData?: JsonObject;
|
|
99
101
|
readonly name: string;
|
|
100
102
|
/** Node-side source path; custom themes must not serialize it into public output. */
|
|
101
103
|
readonly absolutePath: string;
|
|
@@ -122,6 +124,17 @@ interface RenderedPage {
|
|
|
122
124
|
type SortField = "modified" | "name" | "size";
|
|
123
125
|
type NameSortMode = "locale" | "natural" | "unicode";
|
|
124
126
|
type SortDirection = "asc" | "desc";
|
|
127
|
+
type EntryDataProvider = (entry: Omit<ListingEntry, "href" | "exitsExplorer" | "presentation" | "data">, context: {
|
|
128
|
+
readonly operation: "build" | "server";
|
|
129
|
+
readonly directoryPath: string;
|
|
130
|
+
}) => JsonObject | Promise<JsonObject>;
|
|
131
|
+
type IgnoreFile = string | {
|
|
132
|
+
readonly path: string;
|
|
133
|
+
/** Pattern base; defaults to the ignore file's directory. Paths resolve from cwd. */
|
|
134
|
+
readonly baseDir?: string;
|
|
135
|
+
/** Missing optional files are skipped; unreadable files always fail. */
|
|
136
|
+
readonly optional?: boolean;
|
|
137
|
+
};
|
|
125
138
|
interface SortOptions {
|
|
126
139
|
readonly direction?: SortDirection;
|
|
127
140
|
readonly directoriesFirst?: boolean;
|
|
@@ -165,6 +178,13 @@ interface ExplorerTheme {
|
|
|
165
178
|
readonly render: (context: ThemeContext) => RenderedPage | Promise<RenderedPage>;
|
|
166
179
|
}
|
|
167
180
|
interface GenerateOptions {
|
|
181
|
+
/** Synchronous public file URL mapping, independent of explorer/data/asset URLs. */
|
|
182
|
+
readonly fileHref?: (logicalPath: string) => string | null;
|
|
183
|
+
readonly entryData?: EntryDataProvider;
|
|
184
|
+
/** Inspect filesystem selection and planned directory pages without writing output. */
|
|
185
|
+
readonly dryRun?: boolean;
|
|
186
|
+
/** Nonempty outputs require an ownership marker unless replacement is explicit. */
|
|
187
|
+
readonly outputPolicy?: "owned" | "replace";
|
|
168
188
|
/** Opt-in data publication and independently planned HTML pagination. */
|
|
169
189
|
readonly listing?: ListingPolicy;
|
|
170
190
|
/** Optional Node-side metadata provider; core supplies no image implementation. */
|
|
@@ -172,6 +192,8 @@ interface GenerateOptions {
|
|
|
172
192
|
readonly base?: string;
|
|
173
193
|
readonly include?: string | readonly string[];
|
|
174
194
|
readonly exclude?: string | readonly string[];
|
|
195
|
+
/** Ordered Git-style ignore files; none are discovered by Core. */
|
|
196
|
+
readonly ignoreFiles?: readonly IgnoreFile[];
|
|
175
197
|
readonly sourceDir: string;
|
|
176
198
|
/** Dedicated output tree, replaced after a successful build. Keep unrelated files elsewhere. */
|
|
177
199
|
readonly outputDir: string;
|
|
@@ -188,6 +210,19 @@ interface GenerateOptions {
|
|
|
188
210
|
};
|
|
189
211
|
readonly sort?: SortOptions;
|
|
190
212
|
}
|
|
213
|
+
interface BuildReport {
|
|
214
|
+
readonly sourceDir: string;
|
|
215
|
+
readonly outputDir: string;
|
|
216
|
+
readonly theme: string;
|
|
217
|
+
readonly dryRun: boolean;
|
|
218
|
+
readonly mirror: boolean;
|
|
219
|
+
readonly replacesOutput: boolean;
|
|
220
|
+
readonly selectedPaths: readonly string[];
|
|
221
|
+
readonly pages: readonly {
|
|
222
|
+
readonly directory: string;
|
|
223
|
+
readonly outputName: string | null;
|
|
224
|
+
}[];
|
|
225
|
+
}
|
|
191
226
|
interface MetadataProvider {
|
|
192
227
|
readonly assets: ReadonlyMap<string, Uint8Array>;
|
|
193
228
|
readonly resolve: (directory: DirectoryData, hrefForFile: (path: string) => string, pagePath: string) => PageMetadata | Promise<PageMetadata>;
|
|
@@ -200,6 +235,7 @@ type MetadataProviderFactory = (context: {
|
|
|
200
235
|
//#region src/listing.d.ts
|
|
201
236
|
/** Public transport fields only. Internal filesystem metadata must never be spread here. */
|
|
202
237
|
interface ListingEntry {
|
|
238
|
+
readonly data?: JsonObject;
|
|
203
239
|
readonly presentation?: JsonObject;
|
|
204
240
|
readonly id: string;
|
|
205
241
|
readonly name: string;
|
|
@@ -276,8 +312,9 @@ interface ListingManifest {
|
|
|
276
312
|
}[];
|
|
277
313
|
}
|
|
278
314
|
declare function projectListingEntry(entry: FileSystemEntry, context: Pick<ThemeContext, "hrefFor" | "exitsExplorerFor">): ListingEntry;
|
|
279
|
-
|
|
315
|
+
/** Annotation providers receive public facts, not transport URLs or raw stat objects. */
|
|
316
|
+
declare function entryDataFacts(entry: FileSystemEntry): Omit<ListingEntry, "href" | "exitsExplorer" | "presentation" | "data">;
|
|
280
317
|
declare function listingRevision(entries: readonly ListingEntry[], sort: Required<SortOptions>, hrefBase: string, blockSize: number): string;
|
|
281
318
|
//#endregion
|
|
282
|
-
export {
|
|
283
|
-
//# sourceMappingURL=listing-
|
|
319
|
+
export { SymlinkMetadata as A, ResolvedMetadataContext as B, MetadataProviderFactory as C, SortDirection as D, RenderedPage as E, MetadataImage as F, JsonObject as H, MetadataImageValue as I, MetadataOptions as L, ContentCounts as M, ImageSource as N, SortField as O, MetadataContext as P, MetadataValue as R, MetadataProvider as S, OutputNameResolver as T, JsonValue as U, ThemeMetadataDefaults as V, copyJsonObject as W, FileMetadata as _, ListingPage as a, GenerateOptions as b, ListingPolicyContext as c, projectListingEntry as d, BuildReport as f, ExplorerTheme as g, EntryKind as h, ListingManifest as i, ThemeContext as j, SortOptions as k, entryDataFacts as l, EntryDataProvider as m, ListingContext as n, ListingPlan as o, DirectoryData as p, ListingEntry as r, ListingPolicy as s, ListingBlock as t, listingRevision as u, FileSystemEntry as v, NameSortMode as w, IgnoreFile as x, FileTimes as y, PageMetadata as z };
|
|
320
|
+
//# sourceMappingURL=listing-B_6TbWuz.d.mts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dirwell/core",
|
|
3
|
-
"version": "0.0.1
|
|
3
|
+
"version": "0.0.1",
|
|
4
4
|
"description": "Framework-neutral directory listing and static publication kernel.",
|
|
5
|
+
"homepage": "https://vp-tw.github.io/dirwell/api-reference/",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/vp-tw/dirwell/issues"
|
|
8
|
+
},
|
|
5
9
|
"license": "MIT",
|
|
6
10
|
"repository": {
|
|
7
11
|
"type": "git",
|
|
@@ -27,9 +31,10 @@
|
|
|
27
31
|
"publishConfig": {
|
|
28
32
|
"access": "public",
|
|
29
33
|
"provenance": true,
|
|
30
|
-
"tag": "
|
|
34
|
+
"tag": "latest"
|
|
31
35
|
},
|
|
32
36
|
"dependencies": {
|
|
37
|
+
"ignore": "7.0.12",
|
|
33
38
|
"picomatch": "4.0.7"
|
|
34
39
|
},
|
|
35
40
|
"engines": {
|