@mzebley/mark-down 1.2.2 → 1.2.4
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 +18 -22
- package/dist/angular/index.d.ts +3 -1
- package/dist/angular/index.js +18 -8
- package/dist/angular/index.js.map +1 -1
- package/dist/browser.js +222 -31
- package/dist/browser.js.map +1 -1
- package/dist/{chunk-MWZFQXNW.js → chunk-WZCXKUXV.js} +128 -3
- package/dist/chunk-WZCXKUXV.js.map +1 -0
- package/dist/{chunk-35YHML5Z.js → chunk-X5L6GGFF.js} +69 -25
- package/dist/chunk-X5L6GGFF.js.map +1 -0
- package/dist/{chunk-GWLMADTU.js → chunk-ZEQXN4ZD.js} +4 -2
- package/dist/{chunk-GWLMADTU.js.map → chunk-ZEQXN4ZD.js.map} +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +7 -5
- package/dist/inline.d.ts +4 -0
- package/dist/inline.js +20 -6
- package/dist/inline.js.map +1 -1
- package/dist/mark-down-inline.umd.js +8951 -14
- package/dist/mark-down-inline.umd.js.map +1 -1
- package/dist/sanitize-DI2uKnlG.d.ts +10 -0
- package/dist/slug.js +1 -1
- package/dist/{snippet-client-CiQX2Zcn.d.ts → snippet-client-S6E_j24g.d.ts} +3 -0
- package/package.json +5 -2
- package/dist/chunk-35YHML5Z.js.map +0 -1
- package/dist/chunk-MWZFQXNW.js.map +0 -1
package/dist/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/slug.ts","../src/front-matter.ts","../src/errors.ts","../src/markdown.ts","../src/snippet-client.ts","../src/browser.ts"],"sourcesContent":["const NON_ALPHANUMERIC = /[^a-z0-9]+/gi;\nconst LEADING_TRAILING_DASH = /^-+|-+$/g;\n\nexport function normalizeSlug(input: string): string {\n const value = input?.trim();\n if (!value) {\n throw new Error(\"Cannot normalize an empty slug\");\n }\n\n const normalized = value\n .toLowerCase()\n .replace(NON_ALPHANUMERIC, \"-\")\n .replace(/-{2,}/g, \"-\")\n .replace(LEADING_TRAILING_DASH, \"\");\n\n if (!normalized) {\n throw new Error(`Slug '${input}' does not contain any alphanumeric characters`);\n }\n\n return normalized;\n}\n","import { parse as parseYaml } from \"yaml\";\nimport { ManifestLoadError } from \"./errors\";\nimport type { SnippetMeta } from \"./types\";\n\nexport interface FrontMatterResult {\n content: string;\n meta: Partial<SnippetMeta>;\n extra: Record<string, unknown>;\n slug?: string;\n hasFrontMatter: boolean;\n}\n\nconst FRONT_MATTER_PATTERN = /^(?:\\uFEFF)?[ \\t\\r\\n]*---\\s*\\r?\\n([\\s\\S]*?)\\r?\\n---\\s*\\r?\\n?/;\n\nexport function parseFrontMatter(raw: string): FrontMatterResult {\n const match = FRONT_MATTER_PATTERN.exec(raw);\n if (!match) {\n return { content: raw, meta: {}, extra: {}, hasFrontMatter: false };\n }\n\n const yamlSection = match[1];\n let data: unknown;\n try {\n data = parseYaml(yamlSection) ?? {};\n } catch (error) {\n throw new ManifestLoadError(\"Failed to parse snippet front-matter.\", error);\n }\n\n if (!isRecord(data)) {\n return { content: raw.slice(match[0].length), meta: {}, extra: {}, hasFrontMatter: true };\n }\n\n const { known, extra } = splitFrontMatter(data);\n\n return {\n content: raw.slice(match[0].length),\n meta: known.meta,\n extra,\n slug: known.slug,\n hasFrontMatter: true\n };\n}\n\nfunction splitFrontMatter(\n data: Record<string, unknown>\n): { known: { meta: Partial<SnippetMeta>; slug?: string }; extra: Record<string, unknown> } {\n const meta: Partial<SnippetMeta> = {};\n const extra: Record<string, unknown> = {};\n let slug: string | undefined;\n\n for (const [key, value] of Object.entries(data)) {\n switch (key) {\n case \"slug\":\n slug = typeof value === \"string\" ? value : undefined;\n break;\n case \"title\":\n if (typeof value === \"string\") {\n meta.title = value;\n }\n break;\n case \"type\":\n if (typeof value === \"string\") {\n meta.type = value;\n }\n break;\n case \"order\":\n if (typeof value === \"number\") {\n meta.order = value;\n }\n break;\n case \"tags\":\n meta.tags = normalizeTags(value);\n break;\n case \"group\":\n if (typeof value === \"string\" || value === null) {\n meta.group = value;\n }\n break;\n case \"draft\":\n if (typeof value === \"boolean\") {\n meta.draft = value;\n }\n break;\n default:\n extra[key] = value;\n break;\n }\n }\n\n return { known: { meta, slug }, extra };\n}\n\nfunction normalizeTags(value: unknown): string[] | undefined {\n if (!value) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return value.map((item) => String(item));\n }\n if (typeof value === \"string\") {\n return value\n .split(\",\")\n .map((tag) => tag.trim())\n .filter(Boolean);\n }\n return undefined;\n}\n\nfunction isRecord(candidate: unknown): candidate is Record<string, unknown> {\n return Boolean(candidate) && typeof candidate === \"object\" && !Array.isArray(candidate);\n}\n","export class SnippetNotFoundError extends Error {\n readonly slug: string;\n\n constructor(slug: string) {\n super(`Snippet with slug '${slug}' was not found in the manifest.`);\n this.name = \"SnippetNotFoundError\";\n this.slug = slug;\n }\n}\n\nexport class ManifestLoadError extends Error {\n readonly cause?: unknown;\n\n constructor(message: string, cause?: unknown) {\n super(message);\n this.name = \"ManifestLoadError\";\n this.cause = cause instanceof Error ? cause : cause ? new Error(String(cause)) : undefined;\n }\n}\n","import { marked } from \"marked\";\n\nexport function renderMarkdown(markdown: string): string {\n const html = marked.parse(markdown);\n\n if (typeof html === \"string\") {\n return html;\n }\n\n throw new Error(\"renderMarkdown unexpectedly returned a Promise\");\n}\n","import { normalizeSlug } from \"./slug\";\nimport { parseFrontMatter } from \"./front-matter\";\nimport { renderMarkdown } from \"./markdown\";\nimport { ManifestLoadError, SnippetNotFoundError } from \"./errors\";\nimport type {\n ManifestSource,\n ResponseLike,\n Snippet,\n SnippetClientOptions,\n SnippetFetcherResult,\n SnippetMeta,\n SnippetSearchFilter\n} from \"./types\";\n\nexport { ManifestLoadError, SnippetNotFoundError } from \"./errors\";\n\ninterface SnippetClientInternalOptions {\n manifest: ManifestSource;\n base?: string;\n fetch: (url: string) => Promise<string>;\n frontMatter: boolean;\n cache: boolean;\n verbose: boolean;\n render: (markdown: string) => Promise<string>;\n}\n\nconst HTTP_PATTERN = /^https?:\\/\\//i;\n\nexport class SnippetClient {\n private readonly options: SnippetClientInternalOptions;\n private readonly manifestUrl?: string;\n private readonly inferredBase?: string;\n\n private manifestPromise?: Promise<SnippetMeta[]>;\n private readonly snippetCache = new Map<string, Promise<Snippet>>();\n\n constructor(options: SnippetClientOptions) {\n if (!options || !options.manifest) {\n throw new ManifestLoadError(\"A manifest source must be provided to SnippetClient.\");\n }\n\n this.manifestUrl = typeof options.manifest === \"string\" ? options.manifest : undefined;\n this.inferredBase = this.manifestUrl ? deriveBaseFromManifest(this.manifestUrl) : undefined;\n\n const fetcher = options.fetch ?? defaultFetch;\n\n const renderOption = options.render;\n\n const renderer = renderOption\n ? async (markdown: string) => Promise.resolve(renderOption(markdown))\n : async (markdown: string) => Promise.resolve(renderMarkdown(markdown));\n\n this.options = {\n manifest: options.manifest,\n base: options.base,\n fetch: async (url: string) => {\n const response = await fetcher(url);\n if (typeof response === \"string\") {\n return response;\n }\n return resolveResponseText(response, url);\n },\n frontMatter: options.frontMatter !== false,\n cache: options.cache !== false,\n verbose: options.verbose === true,\n render: renderer\n };\n }\n\n async get(slug: string): Promise<Snippet> {\n const manifest = await this.loadManifest();\n const entry = manifest.find((item) => item.slug === slug);\n if (!entry) {\n throw new SnippetNotFoundError(slug);\n }\n return this.loadSnippet(entry);\n }\n\n async listAll(): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n return manifest.map(cloneMeta);\n }\n\n async listByGroup(group: string): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n return manifest\n .filter((item) => (item.group ?? null) === group)\n .map(cloneMeta);\n }\n\n async listByType(type: string): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n return manifest\n .filter((item) => item.type === type)\n .map(cloneMeta);\n }\n\n async search(filter: SnippetSearchFilter): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n const tags = filter.tags ?? [];\n const mode = filter.tagsMode ?? \"any\";\n\n return manifest\n .filter((item) => {\n if (filter.type && item.type !== filter.type) {\n return false;\n }\n if (filter.group && (item.group ?? undefined) !== filter.group) {\n return false;\n }\n if (!tags.length) {\n return true;\n }\n const metaTags = item.tags ?? [];\n if (!metaTags.length) {\n return false;\n }\n if (mode === \"all\") {\n return tags.every((tag) => metaTags.includes(tag));\n }\n return tags.some((tag) => metaTags.includes(tag));\n })\n .map(cloneMeta);\n }\n\n async getHtml(slug: string): Promise<string> {\n const snippet = await this.get(slug);\n return snippet.html;\n }\n\n invalidate(): void {\n this.manifestPromise = undefined;\n this.snippetCache.clear();\n }\n\n invalidateSlug(slug: string): void {\n this.snippetCache.delete(slug);\n }\n\n private async loadManifest(): Promise<SnippetMeta[]> {\n if (this.options.cache && this.manifestPromise) {\n return this.manifestPromise;\n }\n\n const promise = this.resolveManifest();\n if (this.options.cache) {\n this.manifestPromise = promise;\n }\n return promise;\n }\n\n private async resolveManifest(): Promise<SnippetMeta[]> {\n const source = this.options.manifest;\n let entries: SnippetMeta[];\n\n try {\n if (Array.isArray(source)) {\n entries = source.map(normalizeManifestEntry);\n } else if (typeof source === \"function\") {\n const result = await source();\n if (!Array.isArray(result)) {\n throw new ManifestLoadError(\"Manifest loader must resolve to an array of snippet metadata.\");\n }\n entries = result.map(normalizeManifestEntry);\n } else {\n const raw = await this.options.fetch(source);\n entries = parseManifest(raw, source).map(normalizeManifestEntry);\n }\n } catch (error) {\n if (error instanceof ManifestLoadError) {\n throw error;\n }\n throw new ManifestLoadError(\"Failed to load snippet manifest.\", error);\n }\n\n return entries.map(cloneMeta);\n }\n\n private loadSnippet(meta: SnippetMeta): Promise<Snippet> {\n const cached = this.options.cache ? this.snippetCache.get(meta.slug) : undefined;\n if (cached) {\n return cached;\n }\n const promise = this.fetchSnippet(meta);\n if (this.options.cache) {\n this.snippetCache.set(meta.slug, promise);\n }\n return promise;\n }\n\n private async fetchSnippet(meta: SnippetMeta): Promise<Snippet> {\n const url = this.resolveSnippetPath(meta.path);\n let raw: string;\n try {\n raw = await this.options.fetch(url);\n } catch (error) {\n throw new ManifestLoadError(`Failed to fetch snippet at '${url}'.`, error);\n }\n\n const frontMatter = this.options.frontMatter ? parseFrontMatter(raw) : undefined;\n const body = frontMatter?.content ?? raw;\n const html = await this.options.render(body);\n\n const merged: SnippetMeta = {\n ...meta,\n ...pickMeta(frontMatter?.meta),\n extra: mergeExtra(meta.extra, frontMatter?.extra)\n };\n\n if (frontMatter?.slug) {\n try {\n const normalizedFrontSlug = normalizeSlug(frontMatter.slug);\n if (normalizedFrontSlug !== meta.slug && this.options.verbose) {\n console.warn(\n `Front-matter slug '${frontMatter.slug}' (normalized: '${normalizedFrontSlug}') differs from manifest slug '${meta.slug}'.`\n );\n }\n } catch (error) {\n if (this.options.verbose) {\n console.warn(`Failed to normalize front-matter slug '${frontMatter.slug}':`, error);\n }\n }\n }\n\n const snippet: Snippet = { ...merged, html, raw: body, markdown: body };\n if (merged.tags) {\n snippet.tags = [...merged.tags];\n }\n return snippet;\n }\n\n private resolveSnippetPath(path: string): string {\n if (HTTP_PATTERN.test(path)) {\n return normalizeForwardSlashes(path);\n }\n\n const base = this.options.base ?? this.inferredBase ?? \"\";\n\n if (path.startsWith(\"/\")) {\n if (base) {\n return joinPaths(base, path);\n }\n return normalizeForwardSlashes(path);\n }\n\n if (base) {\n return joinPaths(base, path);\n }\n return normalizeForwardSlashes(path);\n }\n}\n\nfunction parseManifest(raw: string, source: string): SnippetMeta[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new ManifestLoadError(`Manifest at '${source}' is not valid JSON.`, error);\n }\n\n if (!Array.isArray(parsed)) {\n throw new ManifestLoadError(`Manifest at '${source}' must be a JSON array.`);\n }\n\n return parsed as SnippetMeta[];\n}\n\nfunction normalizeManifestEntry(entry: SnippetMeta): SnippetMeta {\n if (!entry.slug) {\n throw new ManifestLoadError(\"Manifest entry is missing required 'slug' property.\");\n }\n if (!entry.path) {\n throw new ManifestLoadError(`Manifest entry for '${entry.slug}' is missing required 'path'.`);\n }\n const normalized: SnippetMeta = {\n slug: entry.slug,\n title: entry.title,\n type: entry.type,\n order: entry.order,\n tags: entry.tags ? [...entry.tags] : undefined,\n path: normalizeForwardSlashes(entry.path),\n group: entry.group ?? null,\n draft: entry.draft,\n extra: cloneRecord(entry.extra)\n };\n return normalized;\n}\n\nfunction deriveBaseFromManifest(manifest: string): string | undefined {\n if (HTTP_PATTERN.test(manifest)) {\n try {\n const url = new URL(manifest);\n url.hash = \"\";\n url.search = \"\";\n const path = url.pathname;\n url.pathname = path.replace(/[^/]*$/, \"\");\n return url.toString();\n } catch (error) {\n console.warn(`Unable to derive base from manifest '${manifest}':`, error);\n return undefined;\n }\n }\n\n const sanitized = manifest.replace(/[?#].*$/, \"\");\n const index = sanitized.lastIndexOf(\"/\");\n if (index === -1) {\n return undefined;\n }\n return sanitized.slice(0, index + 1);\n}\n\nfunction joinPaths(base: string, relative: string): string {\n if (HTTP_PATTERN.test(base)) {\n return new URL(relative, base).toString();\n }\n const leading = base.endsWith(\"/\") ? base : `${base}/`;\n const trimmed = relative.startsWith(\"/\") ? relative.slice(1) : relative;\n return normalizeForwardSlashes(`${leading}${trimmed}`);\n}\n\nfunction normalizeForwardSlashes(value: string): string {\n if (HTTP_PATTERN.test(value)) {\n try {\n const url = new URL(value);\n url.pathname = url.pathname.replace(/\\/{2,}/g, \"/\");\n return url.toString();\n } catch {\n // fall back to manual normalization below\n }\n }\n\n if (value.startsWith(\"//\")) {\n return `//${value.slice(2).replace(/\\/{2,}/g, \"/\")}`;\n }\n\n if (value.startsWith(\"/\")) {\n return `/${value\n .slice(1)\n .replace(/\\/{2,}/g, \"/\")}`;\n }\n\n return value.replace(/\\/{2,}/g, \"/\");\n}\n\nfunction mergeExtra(\n base: Record<string, unknown> | undefined,\n overrides: Record<string, unknown> | undefined\n): Record<string, unknown> | undefined {\n if (!base && !overrides) {\n return undefined;\n }\n return { ...(base ?? {}), ...(overrides ?? {}) };\n}\n\nfunction cloneRecord<T extends Record<string, unknown> | undefined>(value: T): T {\n if (!value) {\n return value;\n }\n return { ...value } as T;\n}\n\nfunction cloneMeta(meta: SnippetMeta): SnippetMeta {\n return {\n ...meta,\n tags: meta.tags ? [...meta.tags] : undefined,\n extra: cloneRecord(meta.extra)\n };\n}\n\nasync function defaultFetch(url: string): Promise<SnippetFetcherResult> {\n const runtimeFetch = (globalThis as typeof globalThis & { fetch?: typeof fetch }).fetch;\n if (!runtimeFetch) {\n throw new ManifestLoadError(\"No global fetch implementation is available. Provide a custom fetch function.\");\n }\n return runtimeFetch(url);\n}\n\nasync function resolveResponseText(response: ResponseLike, url: string): Promise<string> {\n if (!response.ok) {\n throw new ManifestLoadError(`Request to '${url}' failed with status ${response.status}.`);\n }\n return response.text();\n}\n\nfunction pickMeta(meta?: Partial<SnippetMeta>): Partial<SnippetMeta> {\n if (!meta) {\n return {};\n }\n const result: Partial<SnippetMeta> = {};\n if (meta.title !== undefined) {\n result.title = meta.title;\n }\n if (meta.type !== undefined) {\n result.type = meta.type;\n }\n if (meta.order !== undefined) {\n result.order = meta.order;\n }\n if (meta.tags !== undefined) {\n result.tags = [...meta.tags];\n }\n if (meta.group !== undefined) {\n result.group = meta.group;\n }\n if (meta.draft !== undefined) {\n result.draft = meta.draft;\n }\n if (meta.path !== undefined) {\n result.path = meta.path;\n }\n return result;\n}\n","installBufferShim();\n\nexport * from \"./index\";\n\nfunction installBufferShim() {\n const globalRef = globalThis as typeof globalThis & { Buffer?: BufferConstructor };\n\n if (typeof globalRef.Buffer !== \"undefined\") {\n return;\n }\n\n const textEncoder = new TextEncoder();\n const textDecoder = new TextDecoder();\n\n class BrowserBuffer extends Uint8Array {\n constructor(value: number | ArrayBufferLike | ArrayBufferView | ArrayLike<number>) {\n if (typeof value === \"number\") {\n super(value);\n return;\n }\n\n if (isArrayBufferLike(value)) {\n super(new Uint8Array(value));\n return;\n }\n\n if (ArrayBuffer.isView(value)) {\n super(\n new Uint8Array(value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength))\n );\n return;\n }\n\n super(Array.from(value));\n }\n\n override toString(encoding: BufferEncoding = \"utf-8\") {\n if (encoding !== \"utf-8\" && encoding !== \"utf8\") {\n throw new Error(`Unsupported encoding '${encoding}' in browser Buffer shim`);\n }\n return textDecoder.decode(this);\n }\n }\n\n const from = (value: string | ArrayLike<number> | BufferSource, encoding: BufferEncoding = \"utf-8\") => {\n if (typeof value === \"string\") {\n if (encoding !== \"utf-8\" && encoding !== \"utf8\") {\n throw new Error(`Unsupported encoding '${encoding}' in browser Buffer shim`);\n }\n return new BrowserBuffer(textEncoder.encode(value));\n }\n\n if (isArrayBufferLike(value)) {\n return new BrowserBuffer(new Uint8Array(value));\n }\n\n if (ArrayBuffer.isView(value)) {\n return new BrowserBuffer(value);\n }\n\n if (typeof (value as ArrayLike<number>).length === \"number\") {\n return new BrowserBuffer(Array.from(value as ArrayLike<number>));\n }\n\n throw new TypeError(\"Unsupported input passed to Buffer.from in browser shim\");\n };\n\n const alloc = (size: number, fill?: number | string) => {\n if (size < 0) {\n throw new RangeError(\"Invalid Buffer size\");\n }\n const buffer = new BrowserBuffer(size);\n if (typeof fill === \"number\") {\n buffer.fill(fill);\n } else if (typeof fill === \"string\") {\n if (!fill.length) {\n buffer.fill(0);\n } else {\n const pattern = textEncoder.encode(fill);\n for (let i = 0; i < buffer.length; i++) {\n buffer[i] = pattern[i % pattern.length];\n }\n }\n } else {\n buffer.fill(0);\n }\n return buffer;\n };\n\n const concat = (buffers: ArrayLike<Uint8Array>, totalLength?: number) => {\n const sanitized = Array.from(buffers, (buffer) =>\n buffer instanceof BrowserBuffer ? buffer : new BrowserBuffer(buffer)\n );\n const length = totalLength ?? sanitized.reduce((acc, current) => acc + current.length, 0);\n const result = new BrowserBuffer(length);\n let offset = 0;\n for (const buffer of sanitized) {\n result.set(buffer, offset);\n offset += buffer.length;\n }\n return result;\n };\n\n const byteLength = (value: string | ArrayBuffer | ArrayBufferView) => {\n if (typeof value === \"string\") {\n return textEncoder.encode(value).length;\n }\n if (value instanceof ArrayBuffer) {\n return value.byteLength;\n }\n if (ArrayBuffer.isView(value)) {\n return value.byteLength;\n }\n throw new TypeError(\"Unable to determine byte length for provided value\");\n };\n\n Object.defineProperties(BrowserBuffer, {\n from: { value: from },\n isBuffer: { value: (candidate: unknown) => candidate instanceof BrowserBuffer },\n alloc: { value: alloc },\n concat: { value: concat },\n byteLength: { value: byteLength }\n });\n\n BrowserBuffer.prototype.valueOf = function valueOf() {\n return this;\n };\n\n globalRef.Buffer = BrowserBuffer as unknown as BufferConstructor;\n\n if (typeof window !== \"undefined\" && typeof (window as typeof globalThis).Buffer === \"undefined\") {\n (window as typeof globalThis & { Buffer?: BufferConstructor }).Buffer = globalRef.Buffer;\n }\n}\n\nfunction isArrayBufferLike(value: unknown): value is ArrayBufferLike {\n if (value instanceof ArrayBuffer) {\n return true;\n }\n return typeof SharedArrayBuffer !== \"undefined\" && value instanceof SharedArrayBuffer;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/slug.ts","../src/front-matter.ts","../src/errors.ts","../src/markdown.ts","../src/sanitize.ts","../src/snippet-client.ts","../src/browser.ts"],"sourcesContent":["const NON_ALPHANUMERIC = /[^a-z0-9]+/gi;\nconst LEADING_TRAILING_DASH = /^-+|-+$/g;\n\nexport function normalizeSlug(input: string): string {\n const value = input?.trim();\n if (!value) {\n throw new Error(\"Cannot normalize an empty slug\");\n }\n\n const normalized = value\n .toLowerCase()\n .replace(NON_ALPHANUMERIC, \"-\")\n .replace(/-{2,}/g, \"-\")\n .replace(LEADING_TRAILING_DASH, \"\");\n\n if (!normalized) {\n throw new Error(\n `Slug '${input}' does not contain any alphanumeric characters`,\n );\n }\n\n return normalized;\n}\n","import { parse as parseYaml } from \"yaml\";\nimport { ManifestLoadError } from \"./errors\";\nimport type { SnippetMeta } from \"./types\";\n\nexport interface FrontMatterResult {\n content: string;\n meta: Partial<SnippetMeta>;\n extra: Record<string, unknown>;\n slug?: string;\n hasFrontMatter: boolean;\n}\n\nconst FRONT_MATTER_PATTERN =\n /^(?:\\uFEFF)?[ \\t\\r\\n]*---\\s*\\r?\\n([\\s\\S]*?)\\r?\\n---\\s*\\r?\\n?/;\n\nexport function parseFrontMatter(raw: string): FrontMatterResult {\n const match = FRONT_MATTER_PATTERN.exec(raw);\n if (!match) {\n return { content: raw, meta: {}, extra: {}, hasFrontMatter: false };\n }\n\n const yamlSection = match[1];\n let data: unknown;\n try {\n data = parseYaml(yamlSection) ?? {};\n } catch (error) {\n throw new ManifestLoadError(\"Failed to parse snippet front-matter.\", error);\n }\n\n if (!isRecord(data)) {\n return {\n content: raw.slice(match[0].length),\n meta: {},\n extra: {},\n hasFrontMatter: true,\n };\n }\n\n const { known, extra } = splitFrontMatter(data);\n\n return {\n content: raw.slice(match[0].length),\n meta: known.meta,\n extra,\n slug: known.slug,\n hasFrontMatter: true,\n };\n}\n\nfunction splitFrontMatter(data: Record<string, unknown>): {\n known: { meta: Partial<SnippetMeta>; slug?: string };\n extra: Record<string, unknown>;\n} {\n const meta: Partial<SnippetMeta> = {};\n const extra: Record<string, unknown> = {};\n let slug: string | undefined;\n\n for (const [key, value] of Object.entries(data)) {\n switch (key) {\n case \"slug\":\n slug = typeof value === \"string\" ? value : undefined;\n break;\n case \"title\":\n if (typeof value === \"string\") {\n meta.title = value;\n }\n break;\n case \"type\":\n if (typeof value === \"string\") {\n meta.type = value;\n }\n break;\n case \"order\":\n if (typeof value === \"number\") {\n meta.order = value;\n }\n break;\n case \"tags\":\n meta.tags = normalizeTags(value);\n break;\n case \"group\":\n if (typeof value === \"string\" || value === null) {\n meta.group = value;\n }\n break;\n case \"draft\":\n if (typeof value === \"boolean\") {\n meta.draft = value;\n }\n break;\n default:\n extra[key] = value;\n break;\n }\n }\n\n return { known: { meta, slug }, extra };\n}\n\nfunction normalizeTags(value: unknown): string[] | undefined {\n if (!value) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return value.map((item) => String(item));\n }\n if (typeof value === \"string\") {\n return value\n .split(\",\")\n .map((tag) => tag.trim())\n .filter(Boolean);\n }\n return undefined;\n}\n\nfunction isRecord(candidate: unknown): candidate is Record<string, unknown> {\n return (\n Boolean(candidate) &&\n typeof candidate === \"object\" &&\n !Array.isArray(candidate)\n );\n}\n","export class SnippetNotFoundError extends Error {\n readonly slug: string;\n\n constructor(slug: string) {\n super(`Snippet with slug '${slug}' was not found in the manifest.`);\n this.name = \"SnippetNotFoundError\";\n this.slug = slug;\n }\n}\n\nexport class ManifestLoadError extends Error {\n readonly cause?: unknown;\n\n constructor(message: string, cause?: unknown) {\n super(message);\n this.name = \"ManifestLoadError\";\n this.cause =\n cause instanceof Error\n ? cause\n : cause\n ? new Error(String(cause))\n : undefined;\n }\n}\n","import { marked } from \"marked\";\n\nexport function renderMarkdown(markdown: string): string {\n const html = marked.parse(markdown);\n\n if (typeof html === \"string\") {\n return html;\n }\n\n throw new Error(\"renderMarkdown unexpectedly returned a Promise\");\n}\n","import sanitizeHtml, { type IOptions } from \"sanitize-html\";\n\nexport type SanitizePolicy = \"default\" | \"strict\" | \"permissive\";\n\nexport interface SanitizeOptions {\n policy?: SanitizePolicy;\n config?: IOptions;\n}\n\nconst DEFAULT_ALLOWED_TAGS = [\n \"a\",\n \"b\",\n \"blockquote\",\n \"br\",\n \"code\",\n \"del\",\n \"em\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"hr\",\n \"i\",\n \"img\",\n \"li\",\n \"ol\",\n \"p\",\n \"pre\",\n \"span\",\n \"strong\",\n \"sub\",\n \"sup\",\n \"table\",\n \"tbody\",\n \"td\",\n \"th\",\n \"thead\",\n \"tr\",\n \"ul\",\n];\n\nconst STRICT_ALLOWED_TAGS = [\n \"a\",\n \"blockquote\",\n \"br\",\n \"code\",\n \"em\",\n \"li\",\n \"ol\",\n \"p\",\n \"pre\",\n \"strong\",\n \"ul\",\n];\n\nconst DEFAULT_ALLOWED_ATTRIBUTES: IOptions[\"allowedAttributes\"] = {\n a: [\"href\", \"name\", \"target\", \"rel\"],\n img: [\"src\", \"alt\", \"title\", \"width\", \"height\"],\n code: [\"class\"],\n pre: [\"class\"],\n span: [\"class\"],\n \"*\": [\"id\", \"title\", \"aria-*\", \"data-*\"],\n};\n\nconst STRICT_ALLOWED_ATTRIBUTES: IOptions[\"allowedAttributes\"] = {\n a: [\"href\", \"name\", \"target\", \"rel\"],\n};\n\nconst POLICY_CONFIG: Record<SanitizePolicy, IOptions> = {\n default: {\n allowedTags: DEFAULT_ALLOWED_TAGS,\n allowedAttributes: DEFAULT_ALLOWED_ATTRIBUTES,\n allowedSchemes: [\"http\", \"https\", \"mailto\"],\n allowedSchemesByTag: {\n img: [\"http\", \"https\", \"data\"],\n },\n },\n strict: {\n allowedTags: STRICT_ALLOWED_TAGS,\n allowedAttributes: STRICT_ALLOWED_ATTRIBUTES,\n allowedSchemes: [\"http\", \"https\", \"mailto\"],\n },\n permissive: {\n ...sanitizeHtml.defaults,\n allowedTags: sanitizeHtml.defaults.allowedTags\n ? [...sanitizeHtml.defaults.allowedTags]\n : undefined,\n allowedAttributes: sanitizeHtml.defaults.allowedAttributes\n ? { ...sanitizeHtml.defaults.allowedAttributes }\n : undefined,\n },\n};\n\nexport function sanitizeMarkup(\n html: string,\n options: SanitizeOptions = {},\n): string {\n const policy = options.policy ?? \"default\";\n const base = POLICY_CONFIG[policy];\n const merged = mergeOptions(base, options.config);\n return sanitizeHtml(html, merged);\n}\n\nfunction mergeOptions(base: IOptions, overrides?: IOptions): IOptions {\n if (!overrides) {\n return base;\n }\n return {\n ...base,\n ...overrides,\n allowedAttributes: mergeAllowedAttributes(\n base.allowedAttributes,\n overrides.allowedAttributes,\n ),\n allowedClasses: mergeRecord(base.allowedClasses, overrides.allowedClasses),\n allowedStyles: mergeRecord(base.allowedStyles, overrides.allowedStyles),\n };\n}\n\nfunction mergeAllowedAttributes(\n base?: IOptions[\"allowedAttributes\"],\n overrides?: IOptions[\"allowedAttributes\"],\n): IOptions[\"allowedAttributes\"] {\n if (overrides === false) {\n return false;\n }\n if (base === false) {\n return overrides ?? false;\n }\n if (!base && !overrides) {\n return undefined;\n }\n return { ...(base ?? {}), ...(overrides ?? {}) };\n}\n\nfunction mergeRecord<T extends Record<string, unknown>>(\n base?: T,\n overrides?: T,\n): T | undefined {\n if (!base && !overrides) {\n return undefined;\n }\n return { ...(base ?? {}), ...(overrides ?? {}) } as T;\n}\n","import { normalizeSlug } from \"./slug\";\nimport { parseFrontMatter } from \"./front-matter\";\nimport { renderMarkdown } from \"./markdown\";\nimport { sanitizeMarkup } from \"./sanitize\";\nimport { ManifestLoadError, SnippetNotFoundError } from \"./errors\";\nimport type {\n ManifestSource,\n ResponseLike,\n Snippet,\n SnippetClientOptions,\n SnippetFetcherResult,\n SnippetMeta,\n SnippetSearchFilter,\n} from \"./types\";\n\nexport { ManifestLoadError, SnippetNotFoundError } from \"./errors\";\n\ninterface SnippetClientInternalOptions {\n manifest: ManifestSource;\n base?: string;\n fetch: (url: string) => Promise<string>;\n frontMatter: boolean;\n cache: boolean;\n verbose: boolean;\n render: (markdown: string) => Promise<string>;\n sanitize?: SnippetClientOptions[\"sanitize\"];\n}\n\nconst HTTP_PATTERN = /^https?:\\/\\//i;\n\nexport class SnippetClient {\n private readonly options: SnippetClientInternalOptions;\n private readonly manifestUrl?: string;\n private readonly inferredBase?: string;\n\n private manifestPromise?: Promise<SnippetMeta[]>;\n private readonly snippetCache = new Map<string, Promise<Snippet>>();\n\n constructor(options: SnippetClientOptions) {\n if (!options || !options.manifest) {\n throw new ManifestLoadError(\n \"A manifest source must be provided to SnippetClient.\",\n );\n }\n\n this.manifestUrl =\n typeof options.manifest === \"string\" ? options.manifest : undefined;\n this.inferredBase = this.manifestUrl\n ? deriveBaseFromManifest(this.manifestUrl)\n : undefined;\n\n const fetcher = options.fetch ?? defaultFetch;\n\n const renderOption = options.render;\n\n const renderer = renderOption\n ? async (markdown: string) => Promise.resolve(renderOption(markdown))\n : async (markdown: string) => Promise.resolve(renderMarkdown(markdown));\n\n this.options = {\n manifest: options.manifest,\n base: options.base,\n fetch: async (url: string) => {\n const response = await fetcher(url);\n if (typeof response === \"string\") {\n return response;\n }\n return resolveResponseText(response, url);\n },\n frontMatter: options.frontMatter !== false,\n cache: options.cache !== false,\n verbose: options.verbose === true,\n render: renderer,\n sanitize: options.sanitize,\n };\n }\n\n async get(slug: string): Promise<Snippet> {\n const manifest = await this.loadManifest();\n const entry = manifest.find((item) => item.slug === slug);\n if (!entry) {\n throw new SnippetNotFoundError(slug);\n }\n return this.loadSnippet(entry);\n }\n\n async listAll(): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n return manifest.map(cloneMeta);\n }\n\n async listByGroup(group: string): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n return manifest\n .filter((item) => (item.group ?? null) === group)\n .map(cloneMeta);\n }\n\n async listByType(type: string): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n return manifest.filter((item) => item.type === type).map(cloneMeta);\n }\n\n async search(filter: SnippetSearchFilter): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n const tags = filter.tags ?? [];\n const mode = filter.tagsMode ?? \"any\";\n\n return manifest\n .filter((item) => {\n if (filter.type && item.type !== filter.type) {\n return false;\n }\n if (filter.group && (item.group ?? undefined) !== filter.group) {\n return false;\n }\n if (!tags.length) {\n return true;\n }\n const metaTags = item.tags ?? [];\n if (!metaTags.length) {\n return false;\n }\n if (mode === \"all\") {\n return tags.every((tag) => metaTags.includes(tag));\n }\n return tags.some((tag) => metaTags.includes(tag));\n })\n .map(cloneMeta);\n }\n\n async getHtml(slug: string): Promise<string> {\n const snippet = await this.get(slug);\n return snippet.html;\n }\n\n invalidate(): void {\n this.manifestPromise = undefined;\n this.snippetCache.clear();\n }\n\n invalidateSlug(slug: string): void {\n this.snippetCache.delete(slug);\n }\n\n private async loadManifest(): Promise<SnippetMeta[]> {\n if (this.options.cache && this.manifestPromise) {\n return this.manifestPromise;\n }\n\n const promise = this.resolveManifest();\n if (this.options.cache) {\n this.manifestPromise = promise;\n }\n return promise;\n }\n\n private async resolveManifest(): Promise<SnippetMeta[]> {\n const source = this.options.manifest;\n let entries: SnippetMeta[];\n\n try {\n if (Array.isArray(source)) {\n entries = source.map(normalizeManifestEntry);\n } else if (typeof source === \"function\") {\n const result = await source();\n if (!Array.isArray(result)) {\n throw new ManifestLoadError(\n \"Manifest loader must resolve to an array of snippet metadata.\",\n );\n }\n entries = result.map(normalizeManifestEntry);\n } else {\n const raw = await this.options.fetch(source);\n entries = parseManifest(raw, source).map(normalizeManifestEntry);\n }\n } catch (error) {\n if (error instanceof ManifestLoadError) {\n throw error;\n }\n throw new ManifestLoadError(\"Failed to load snippet manifest.\", error);\n }\n\n return entries.map(cloneMeta);\n }\n\n private loadSnippet(meta: SnippetMeta): Promise<Snippet> {\n const cached = this.options.cache\n ? this.snippetCache.get(meta.slug)\n : undefined;\n if (cached) {\n return cached;\n }\n const promise = this.fetchSnippet(meta);\n if (this.options.cache) {\n this.snippetCache.set(meta.slug, promise);\n }\n return promise;\n }\n\n private async fetchSnippet(meta: SnippetMeta): Promise<Snippet> {\n const url = this.resolveSnippetPath(meta.path);\n let raw: string;\n try {\n raw = await this.options.fetch(url);\n } catch (error) {\n throw new ManifestLoadError(\n `Failed to fetch snippet at '${url}'.`,\n error,\n );\n }\n\n const frontMatter = this.options.frontMatter\n ? parseFrontMatter(raw)\n : undefined;\n const body = frontMatter?.content ?? raw;\n let html = await this.options.render(body);\n if (this.options.sanitize) {\n html = sanitizeMarkup(html, this.options.sanitize);\n }\n\n const merged: SnippetMeta = {\n ...meta,\n ...pickMeta(frontMatter?.meta),\n extra: mergeExtra(meta.extra, frontMatter?.extra),\n };\n\n if (frontMatter?.slug) {\n try {\n const normalizedFrontSlug = normalizeSlug(frontMatter.slug);\n if (normalizedFrontSlug !== meta.slug && this.options.verbose) {\n console.warn(\n `Front-matter slug '${frontMatter.slug}' (normalized: '${normalizedFrontSlug}') differs from manifest slug '${meta.slug}'.`,\n );\n }\n } catch (error) {\n if (this.options.verbose) {\n console.warn(\n `Failed to normalize front-matter slug '${frontMatter.slug}':`,\n error,\n );\n }\n }\n }\n\n const snippet: Snippet = { ...merged, html, raw: body, markdown: body };\n if (merged.tags) {\n snippet.tags = [...merged.tags];\n }\n return snippet;\n }\n\n private resolveSnippetPath(path: string): string {\n if (HTTP_PATTERN.test(path)) {\n return normalizeForwardSlashes(path);\n }\n\n const base = this.options.base ?? this.inferredBase ?? \"\";\n\n if (path.startsWith(\"/\")) {\n if (base) {\n return joinPaths(base, path);\n }\n return normalizeForwardSlashes(path);\n }\n\n if (base) {\n return joinPaths(base, path);\n }\n return normalizeForwardSlashes(path);\n }\n}\n\nfunction parseManifest(raw: string, source: string): SnippetMeta[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new ManifestLoadError(\n `Manifest at '${source}' is not valid JSON.`,\n error,\n );\n }\n\n if (!Array.isArray(parsed)) {\n throw new ManifestLoadError(\n `Manifest at '${source}' must be a JSON array.`,\n );\n }\n\n return parsed as SnippetMeta[];\n}\n\nfunction normalizeManifestEntry(entry: SnippetMeta): SnippetMeta {\n if (!entry || typeof entry !== \"object\") {\n throw new ManifestLoadError(\"Manifest entry must be an object.\");\n }\n if (!entry.slug) {\n throw new ManifestLoadError(\n \"Manifest entry is missing required 'slug' property.\",\n );\n }\n if (!entry.path) {\n throw new ManifestLoadError(\n `Manifest entry for '${entry.slug}' is missing required 'path'.`,\n );\n }\n const normalized: SnippetMeta = {\n slug: entry.slug,\n title: entry.title,\n type: entry.type,\n order: entry.order,\n tags: normalizeTags(entry.tags),\n path: normalizeForwardSlashes(entry.path),\n group: entry.group ?? null,\n draft: entry.draft,\n extra: cloneRecord(entry.extra),\n };\n return normalized;\n}\n\nfunction deriveBaseFromManifest(manifest: string): string | undefined {\n if (HTTP_PATTERN.test(manifest)) {\n try {\n const url = new URL(manifest);\n url.hash = \"\";\n url.search = \"\";\n const path = url.pathname;\n url.pathname = path.replace(/[^/]*$/, \"\");\n return url.toString();\n } catch (error) {\n console.warn(`Unable to derive base from manifest '${manifest}':`, error);\n return undefined;\n }\n }\n\n const sanitized = manifest.replace(/[?#].*$/, \"\");\n const index = sanitized.lastIndexOf(\"/\");\n if (index === -1) {\n return undefined;\n }\n return sanitized.slice(0, index + 1);\n}\n\nfunction joinPaths(base: string, relative: string): string {\n if (HTTP_PATTERN.test(base)) {\n return new URL(relative, base).toString();\n }\n const leading = base.endsWith(\"/\") ? base : `${base}/`;\n const trimmed = relative.startsWith(\"/\") ? relative.slice(1) : relative;\n return normalizeForwardSlashes(`${leading}${trimmed}`);\n}\n\nfunction normalizeForwardSlashes(value: string): string {\n const sanitized = value.replace(/\\\\/g, \"/\");\n if (HTTP_PATTERN.test(sanitized)) {\n try {\n const url = new URL(sanitized);\n url.pathname = url.pathname.replace(/\\/{2,}/g, \"/\");\n return url.toString();\n } catch {\n // fall back to manual normalization below\n }\n }\n\n if (sanitized.startsWith(\"//\")) {\n return `//${sanitized.slice(2).replace(/\\/{2,}/g, \"/\")}`;\n }\n\n if (sanitized.startsWith(\"/\")) {\n return `/${sanitized.slice(1).replace(/\\/{2,}/g, \"/\")}`;\n }\n\n return sanitized.replace(/\\/{2,}/g, \"/\");\n}\n\nfunction mergeExtra(\n base: Record<string, unknown> | undefined,\n overrides: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n if (!base && !overrides) {\n return undefined;\n }\n return { ...(base ?? {}), ...(overrides ?? {}) };\n}\n\nfunction cloneRecord<T extends Record<string, unknown> | undefined>(\n value: T,\n): T {\n if (!value) {\n return value;\n }\n return { ...value } as T;\n}\n\nfunction cloneMeta(meta: SnippetMeta): SnippetMeta {\n return {\n ...meta,\n tags: normalizeTags(meta.tags),\n extra: cloneRecord(meta.extra),\n };\n}\n\nfunction normalizeTags(value: unknown): string[] | undefined {\n if (!value) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return value.map((entry) => String(entry));\n }\n if (typeof value === \"string\") {\n return value\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean);\n }\n return undefined;\n}\n\nasync function defaultFetch(url: string): Promise<SnippetFetcherResult> {\n const runtimeFetch = (\n globalThis as typeof globalThis & { fetch?: typeof fetch }\n ).fetch;\n if (!runtimeFetch) {\n throw new ManifestLoadError(\n \"No global fetch implementation is available. Provide a custom fetch function.\",\n );\n }\n return runtimeFetch(url);\n}\n\nasync function resolveResponseText(\n response: ResponseLike,\n url: string,\n): Promise<string> {\n if (!response.ok) {\n throw new ManifestLoadError(\n `Request to '${url}' failed with status ${response.status}.`,\n );\n }\n return response.text();\n}\n\nfunction pickMeta(meta?: Partial<SnippetMeta>): Partial<SnippetMeta> {\n if (!meta) {\n return {};\n }\n const result: Partial<SnippetMeta> = {};\n if (meta.title !== undefined) {\n result.title = meta.title;\n }\n if (meta.type !== undefined) {\n result.type = meta.type;\n }\n if (meta.order !== undefined) {\n result.order = meta.order;\n }\n if (meta.tags !== undefined) {\n result.tags = [...meta.tags];\n }\n if (meta.group !== undefined) {\n result.group = meta.group;\n }\n if (meta.draft !== undefined) {\n result.draft = meta.draft;\n }\n if (meta.path !== undefined) {\n result.path = meta.path;\n }\n return result;\n}\n","installBufferShim();\n\nexport * from \"./index\";\n\nfunction installBufferShim() {\n const globalRef = globalThis as typeof globalThis & {\n Buffer?: BufferConstructor;\n };\n\n if (typeof globalRef.Buffer !== \"undefined\") {\n return;\n }\n\n const textEncoder = new TextEncoder();\n const textDecoder = new TextDecoder();\n\n class BrowserBuffer extends Uint8Array {\n constructor(\n value: number | ArrayBufferLike | ArrayBufferView | ArrayLike<number>,\n ) {\n if (typeof value === \"number\") {\n super(value);\n return;\n }\n\n if (isArrayBufferLike(value)) {\n super(new Uint8Array(value));\n return;\n }\n\n if (ArrayBuffer.isView(value)) {\n super(\n new Uint8Array(\n value.buffer.slice(\n value.byteOffset,\n value.byteOffset + value.byteLength,\n ),\n ),\n );\n return;\n }\n\n super(Array.from(value));\n }\n\n override toString(encoding: BufferEncoding = \"utf-8\") {\n if (encoding !== \"utf-8\" && encoding !== \"utf8\") {\n throw new Error(\n `Unsupported encoding '${encoding}' in browser Buffer shim`,\n );\n }\n return textDecoder.decode(this);\n }\n }\n\n const from = (\n value: string | ArrayLike<number> | BufferSource,\n encoding: BufferEncoding = \"utf-8\",\n ) => {\n if (typeof value === \"string\") {\n if (encoding !== \"utf-8\" && encoding !== \"utf8\") {\n throw new Error(\n `Unsupported encoding '${encoding}' in browser Buffer shim`,\n );\n }\n return new BrowserBuffer(textEncoder.encode(value));\n }\n\n if (isArrayBufferLike(value)) {\n return new BrowserBuffer(new Uint8Array(value));\n }\n\n if (ArrayBuffer.isView(value)) {\n return new BrowserBuffer(value);\n }\n\n if (typeof (value as ArrayLike<number>).length === \"number\") {\n return new BrowserBuffer(Array.from(value as ArrayLike<number>));\n }\n\n throw new TypeError(\n \"Unsupported input passed to Buffer.from in browser shim\",\n );\n };\n\n const alloc = (size: number, fill?: number | string) => {\n if (size < 0) {\n throw new RangeError(\"Invalid Buffer size\");\n }\n const buffer = new BrowserBuffer(size);\n if (typeof fill === \"number\") {\n buffer.fill(fill);\n } else if (typeof fill === \"string\") {\n if (!fill.length) {\n buffer.fill(0);\n } else {\n const pattern = textEncoder.encode(fill);\n for (let i = 0; i < buffer.length; i++) {\n buffer[i] = pattern[i % pattern.length];\n }\n }\n } else {\n buffer.fill(0);\n }\n return buffer;\n };\n\n const concat = (buffers: ArrayLike<Uint8Array>, totalLength?: number) => {\n const sanitized = Array.from(buffers, (buffer) =>\n buffer instanceof BrowserBuffer ? buffer : new BrowserBuffer(buffer),\n );\n const length =\n totalLength ??\n sanitized.reduce((acc, current) => acc + current.length, 0);\n if (length < 0) {\n throw new RangeError(\"Invalid Buffer length\");\n }\n const result = new BrowserBuffer(length);\n let offset = 0;\n for (const buffer of sanitized) {\n const remaining = length - offset;\n if (remaining <= 0) {\n break;\n }\n const slice =\n buffer.length > remaining ? buffer.subarray(0, remaining) : buffer;\n result.set(slice, offset);\n offset += slice.length;\n }\n return result;\n };\n\n const byteLength = (value: string | ArrayBuffer | ArrayBufferView) => {\n if (typeof value === \"string\") {\n return textEncoder.encode(value).length;\n }\n if (value instanceof ArrayBuffer) {\n return value.byteLength;\n }\n if (ArrayBuffer.isView(value)) {\n return value.byteLength;\n }\n throw new TypeError(\"Unable to determine byte length for provided value\");\n };\n\n Object.defineProperties(BrowserBuffer, {\n from: { value: from },\n isBuffer: {\n value: (candidate: unknown) => candidate instanceof BrowserBuffer,\n },\n alloc: { value: alloc },\n concat: { value: concat },\n byteLength: { value: byteLength },\n });\n\n BrowserBuffer.prototype.valueOf = function valueOf() {\n return this;\n };\n\n globalRef.Buffer = BrowserBuffer as unknown as BufferConstructor;\n\n if (\n typeof window !== \"undefined\" &&\n typeof (window as typeof globalThis).Buffer === \"undefined\"\n ) {\n (window as typeof globalThis & { Buffer?: BufferConstructor }).Buffer =\n globalRef.Buffer;\n }\n}\n\nfunction isArrayBufferLike(value: unknown): value is ArrayBufferLike {\n if (value instanceof ArrayBuffer) {\n return true;\n }\n return (\n typeof SharedArrayBuffer !== \"undefined\" &&\n value instanceof SharedArrayBuffer\n );\n}\n"],"mappings":"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","names":["normalizeTags"]}
|
|
@@ -30,7 +30,12 @@ function parseFrontMatter(raw) {
|
|
|
30
30
|
throw new ManifestLoadError("Failed to parse snippet front-matter.", error);
|
|
31
31
|
}
|
|
32
32
|
if (!isRecord(data)) {
|
|
33
|
-
return {
|
|
33
|
+
return {
|
|
34
|
+
content: raw.slice(match[0].length),
|
|
35
|
+
meta: {},
|
|
36
|
+
extra: {},
|
|
37
|
+
hasFrontMatter: true
|
|
38
|
+
};
|
|
34
39
|
}
|
|
35
40
|
const { known, extra } = splitFrontMatter(data);
|
|
36
41
|
return {
|
|
@@ -111,10 +116,130 @@ function renderMarkdown(markdown) {
|
|
|
111
116
|
throw new Error("renderMarkdown unexpectedly returned a Promise");
|
|
112
117
|
}
|
|
113
118
|
|
|
119
|
+
// src/sanitize.ts
|
|
120
|
+
import sanitizeHtml from "sanitize-html";
|
|
121
|
+
var DEFAULT_ALLOWED_TAGS = [
|
|
122
|
+
"a",
|
|
123
|
+
"b",
|
|
124
|
+
"blockquote",
|
|
125
|
+
"br",
|
|
126
|
+
"code",
|
|
127
|
+
"del",
|
|
128
|
+
"em",
|
|
129
|
+
"h1",
|
|
130
|
+
"h2",
|
|
131
|
+
"h3",
|
|
132
|
+
"h4",
|
|
133
|
+
"h5",
|
|
134
|
+
"h6",
|
|
135
|
+
"hr",
|
|
136
|
+
"i",
|
|
137
|
+
"img",
|
|
138
|
+
"li",
|
|
139
|
+
"ol",
|
|
140
|
+
"p",
|
|
141
|
+
"pre",
|
|
142
|
+
"span",
|
|
143
|
+
"strong",
|
|
144
|
+
"sub",
|
|
145
|
+
"sup",
|
|
146
|
+
"table",
|
|
147
|
+
"tbody",
|
|
148
|
+
"td",
|
|
149
|
+
"th",
|
|
150
|
+
"thead",
|
|
151
|
+
"tr",
|
|
152
|
+
"ul"
|
|
153
|
+
];
|
|
154
|
+
var STRICT_ALLOWED_TAGS = [
|
|
155
|
+
"a",
|
|
156
|
+
"blockquote",
|
|
157
|
+
"br",
|
|
158
|
+
"code",
|
|
159
|
+
"em",
|
|
160
|
+
"li",
|
|
161
|
+
"ol",
|
|
162
|
+
"p",
|
|
163
|
+
"pre",
|
|
164
|
+
"strong",
|
|
165
|
+
"ul"
|
|
166
|
+
];
|
|
167
|
+
var DEFAULT_ALLOWED_ATTRIBUTES = {
|
|
168
|
+
a: ["href", "name", "target", "rel"],
|
|
169
|
+
img: ["src", "alt", "title", "width", "height"],
|
|
170
|
+
code: ["class"],
|
|
171
|
+
pre: ["class"],
|
|
172
|
+
span: ["class"],
|
|
173
|
+
"*": ["id", "title", "aria-*", "data-*"]
|
|
174
|
+
};
|
|
175
|
+
var STRICT_ALLOWED_ATTRIBUTES = {
|
|
176
|
+
a: ["href", "name", "target", "rel"]
|
|
177
|
+
};
|
|
178
|
+
var POLICY_CONFIG = {
|
|
179
|
+
default: {
|
|
180
|
+
allowedTags: DEFAULT_ALLOWED_TAGS,
|
|
181
|
+
allowedAttributes: DEFAULT_ALLOWED_ATTRIBUTES,
|
|
182
|
+
allowedSchemes: ["http", "https", "mailto"],
|
|
183
|
+
allowedSchemesByTag: {
|
|
184
|
+
img: ["http", "https", "data"]
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
strict: {
|
|
188
|
+
allowedTags: STRICT_ALLOWED_TAGS,
|
|
189
|
+
allowedAttributes: STRICT_ALLOWED_ATTRIBUTES,
|
|
190
|
+
allowedSchemes: ["http", "https", "mailto"]
|
|
191
|
+
},
|
|
192
|
+
permissive: {
|
|
193
|
+
...sanitizeHtml.defaults,
|
|
194
|
+
allowedTags: sanitizeHtml.defaults.allowedTags ? [...sanitizeHtml.defaults.allowedTags] : void 0,
|
|
195
|
+
allowedAttributes: sanitizeHtml.defaults.allowedAttributes ? { ...sanitizeHtml.defaults.allowedAttributes } : void 0
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
function sanitizeMarkup(html, options = {}) {
|
|
199
|
+
const policy = options.policy ?? "default";
|
|
200
|
+
const base = POLICY_CONFIG[policy];
|
|
201
|
+
const merged = mergeOptions(base, options.config);
|
|
202
|
+
return sanitizeHtml(html, merged);
|
|
203
|
+
}
|
|
204
|
+
function mergeOptions(base, overrides) {
|
|
205
|
+
if (!overrides) {
|
|
206
|
+
return base;
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
...base,
|
|
210
|
+
...overrides,
|
|
211
|
+
allowedAttributes: mergeAllowedAttributes(
|
|
212
|
+
base.allowedAttributes,
|
|
213
|
+
overrides.allowedAttributes
|
|
214
|
+
),
|
|
215
|
+
allowedClasses: mergeRecord(base.allowedClasses, overrides.allowedClasses),
|
|
216
|
+
allowedStyles: mergeRecord(base.allowedStyles, overrides.allowedStyles)
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function mergeAllowedAttributes(base, overrides) {
|
|
220
|
+
if (overrides === false) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
if (base === false) {
|
|
224
|
+
return overrides ?? false;
|
|
225
|
+
}
|
|
226
|
+
if (!base && !overrides) {
|
|
227
|
+
return void 0;
|
|
228
|
+
}
|
|
229
|
+
return { ...base ?? {}, ...overrides ?? {} };
|
|
230
|
+
}
|
|
231
|
+
function mergeRecord(base, overrides) {
|
|
232
|
+
if (!base && !overrides) {
|
|
233
|
+
return void 0;
|
|
234
|
+
}
|
|
235
|
+
return { ...base ?? {}, ...overrides ?? {} };
|
|
236
|
+
}
|
|
237
|
+
|
|
114
238
|
export {
|
|
115
239
|
SnippetNotFoundError,
|
|
116
240
|
ManifestLoadError,
|
|
117
241
|
parseFrontMatter,
|
|
118
|
-
renderMarkdown
|
|
242
|
+
renderMarkdown,
|
|
243
|
+
sanitizeMarkup
|
|
119
244
|
};
|
|
120
|
-
//# sourceMappingURL=chunk-
|
|
245
|
+
//# sourceMappingURL=chunk-WZCXKUXV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/front-matter.ts","../src/markdown.ts","../src/sanitize.ts"],"sourcesContent":["export class SnippetNotFoundError extends Error {\n readonly slug: string;\n\n constructor(slug: string) {\n super(`Snippet with slug '${slug}' was not found in the manifest.`);\n this.name = \"SnippetNotFoundError\";\n this.slug = slug;\n }\n}\n\nexport class ManifestLoadError extends Error {\n readonly cause?: unknown;\n\n constructor(message: string, cause?: unknown) {\n super(message);\n this.name = \"ManifestLoadError\";\n this.cause =\n cause instanceof Error\n ? cause\n : cause\n ? new Error(String(cause))\n : undefined;\n }\n}\n","import { parse as parseYaml } from \"yaml\";\nimport { ManifestLoadError } from \"./errors\";\nimport type { SnippetMeta } from \"./types\";\n\nexport interface FrontMatterResult {\n content: string;\n meta: Partial<SnippetMeta>;\n extra: Record<string, unknown>;\n slug?: string;\n hasFrontMatter: boolean;\n}\n\nconst FRONT_MATTER_PATTERN =\n /^(?:\\uFEFF)?[ \\t\\r\\n]*---\\s*\\r?\\n([\\s\\S]*?)\\r?\\n---\\s*\\r?\\n?/;\n\nexport function parseFrontMatter(raw: string): FrontMatterResult {\n const match = FRONT_MATTER_PATTERN.exec(raw);\n if (!match) {\n return { content: raw, meta: {}, extra: {}, hasFrontMatter: false };\n }\n\n const yamlSection = match[1];\n let data: unknown;\n try {\n data = parseYaml(yamlSection) ?? {};\n } catch (error) {\n throw new ManifestLoadError(\"Failed to parse snippet front-matter.\", error);\n }\n\n if (!isRecord(data)) {\n return {\n content: raw.slice(match[0].length),\n meta: {},\n extra: {},\n hasFrontMatter: true,\n };\n }\n\n const { known, extra } = splitFrontMatter(data);\n\n return {\n content: raw.slice(match[0].length),\n meta: known.meta,\n extra,\n slug: known.slug,\n hasFrontMatter: true,\n };\n}\n\nfunction splitFrontMatter(data: Record<string, unknown>): {\n known: { meta: Partial<SnippetMeta>; slug?: string };\n extra: Record<string, unknown>;\n} {\n const meta: Partial<SnippetMeta> = {};\n const extra: Record<string, unknown> = {};\n let slug: string | undefined;\n\n for (const [key, value] of Object.entries(data)) {\n switch (key) {\n case \"slug\":\n slug = typeof value === \"string\" ? value : undefined;\n break;\n case \"title\":\n if (typeof value === \"string\") {\n meta.title = value;\n }\n break;\n case \"type\":\n if (typeof value === \"string\") {\n meta.type = value;\n }\n break;\n case \"order\":\n if (typeof value === \"number\") {\n meta.order = value;\n }\n break;\n case \"tags\":\n meta.tags = normalizeTags(value);\n break;\n case \"group\":\n if (typeof value === \"string\" || value === null) {\n meta.group = value;\n }\n break;\n case \"draft\":\n if (typeof value === \"boolean\") {\n meta.draft = value;\n }\n break;\n default:\n extra[key] = value;\n break;\n }\n }\n\n return { known: { meta, slug }, extra };\n}\n\nfunction normalizeTags(value: unknown): string[] | undefined {\n if (!value) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return value.map((item) => String(item));\n }\n if (typeof value === \"string\") {\n return value\n .split(\",\")\n .map((tag) => tag.trim())\n .filter(Boolean);\n }\n return undefined;\n}\n\nfunction isRecord(candidate: unknown): candidate is Record<string, unknown> {\n return (\n Boolean(candidate) &&\n typeof candidate === \"object\" &&\n !Array.isArray(candidate)\n );\n}\n","import { marked } from \"marked\";\n\nexport function renderMarkdown(markdown: string): string {\n const html = marked.parse(markdown);\n\n if (typeof html === \"string\") {\n return html;\n }\n\n throw new Error(\"renderMarkdown unexpectedly returned a Promise\");\n}\n","import sanitizeHtml, { type IOptions } from \"sanitize-html\";\n\nexport type SanitizePolicy = \"default\" | \"strict\" | \"permissive\";\n\nexport interface SanitizeOptions {\n policy?: SanitizePolicy;\n config?: IOptions;\n}\n\nconst DEFAULT_ALLOWED_TAGS = [\n \"a\",\n \"b\",\n \"blockquote\",\n \"br\",\n \"code\",\n \"del\",\n \"em\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"hr\",\n \"i\",\n \"img\",\n \"li\",\n \"ol\",\n \"p\",\n \"pre\",\n \"span\",\n \"strong\",\n \"sub\",\n \"sup\",\n \"table\",\n \"tbody\",\n \"td\",\n \"th\",\n \"thead\",\n \"tr\",\n \"ul\",\n];\n\nconst STRICT_ALLOWED_TAGS = [\n \"a\",\n \"blockquote\",\n \"br\",\n \"code\",\n \"em\",\n \"li\",\n \"ol\",\n \"p\",\n \"pre\",\n \"strong\",\n \"ul\",\n];\n\nconst DEFAULT_ALLOWED_ATTRIBUTES: IOptions[\"allowedAttributes\"] = {\n a: [\"href\", \"name\", \"target\", \"rel\"],\n img: [\"src\", \"alt\", \"title\", \"width\", \"height\"],\n code: [\"class\"],\n pre: [\"class\"],\n span: [\"class\"],\n \"*\": [\"id\", \"title\", \"aria-*\", \"data-*\"],\n};\n\nconst STRICT_ALLOWED_ATTRIBUTES: IOptions[\"allowedAttributes\"] = {\n a: [\"href\", \"name\", \"target\", \"rel\"],\n};\n\nconst POLICY_CONFIG: Record<SanitizePolicy, IOptions> = {\n default: {\n allowedTags: DEFAULT_ALLOWED_TAGS,\n allowedAttributes: DEFAULT_ALLOWED_ATTRIBUTES,\n allowedSchemes: [\"http\", \"https\", \"mailto\"],\n allowedSchemesByTag: {\n img: [\"http\", \"https\", \"data\"],\n },\n },\n strict: {\n allowedTags: STRICT_ALLOWED_TAGS,\n allowedAttributes: STRICT_ALLOWED_ATTRIBUTES,\n allowedSchemes: [\"http\", \"https\", \"mailto\"],\n },\n permissive: {\n ...sanitizeHtml.defaults,\n allowedTags: sanitizeHtml.defaults.allowedTags\n ? [...sanitizeHtml.defaults.allowedTags]\n : undefined,\n allowedAttributes: sanitizeHtml.defaults.allowedAttributes\n ? { ...sanitizeHtml.defaults.allowedAttributes }\n : undefined,\n },\n};\n\nexport function sanitizeMarkup(\n html: string,\n options: SanitizeOptions = {},\n): string {\n const policy = options.policy ?? \"default\";\n const base = POLICY_CONFIG[policy];\n const merged = mergeOptions(base, options.config);\n return sanitizeHtml(html, merged);\n}\n\nfunction mergeOptions(base: IOptions, overrides?: IOptions): IOptions {\n if (!overrides) {\n return base;\n }\n return {\n ...base,\n ...overrides,\n allowedAttributes: mergeAllowedAttributes(\n base.allowedAttributes,\n overrides.allowedAttributes,\n ),\n allowedClasses: mergeRecord(base.allowedClasses, overrides.allowedClasses),\n allowedStyles: mergeRecord(base.allowedStyles, overrides.allowedStyles),\n };\n}\n\nfunction mergeAllowedAttributes(\n base?: IOptions[\"allowedAttributes\"],\n overrides?: IOptions[\"allowedAttributes\"],\n): IOptions[\"allowedAttributes\"] {\n if (overrides === false) {\n return false;\n }\n if (base === false) {\n return overrides ?? false;\n }\n if (!base && !overrides) {\n return undefined;\n }\n return { ...(base ?? {}), ...(overrides ?? {}) };\n}\n\nfunction mergeRecord<T extends Record<string, unknown>>(\n base?: T,\n overrides?: T,\n): T | undefined {\n if (!base && !overrides) {\n return undefined;\n }\n return { ...(base ?? {}), ...(overrides ?? {}) } as T;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
normalizeSlug
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZEQXN4ZD.js";
|
|
4
4
|
import {
|
|
5
5
|
ManifestLoadError,
|
|
6
6
|
SnippetNotFoundError,
|
|
7
7
|
parseFrontMatter,
|
|
8
|
-
renderMarkdown
|
|
9
|
-
|
|
8
|
+
renderMarkdown,
|
|
9
|
+
sanitizeMarkup
|
|
10
|
+
} from "./chunk-WZCXKUXV.js";
|
|
10
11
|
|
|
11
12
|
// src/snippet-client.ts
|
|
12
13
|
var HTTP_PATTERN = /^https?:\/\//i;
|
|
@@ -14,7 +15,9 @@ var SnippetClient = class {
|
|
|
14
15
|
constructor(options) {
|
|
15
16
|
this.snippetCache = /* @__PURE__ */ new Map();
|
|
16
17
|
if (!options || !options.manifest) {
|
|
17
|
-
throw new ManifestLoadError(
|
|
18
|
+
throw new ManifestLoadError(
|
|
19
|
+
"A manifest source must be provided to SnippetClient."
|
|
20
|
+
);
|
|
18
21
|
}
|
|
19
22
|
this.manifestUrl = typeof options.manifest === "string" ? options.manifest : void 0;
|
|
20
23
|
this.inferredBase = this.manifestUrl ? deriveBaseFromManifest(this.manifestUrl) : void 0;
|
|
@@ -34,7 +37,8 @@ var SnippetClient = class {
|
|
|
34
37
|
frontMatter: options.frontMatter !== false,
|
|
35
38
|
cache: options.cache !== false,
|
|
36
39
|
verbose: options.verbose === true,
|
|
37
|
-
render: renderer
|
|
40
|
+
render: renderer,
|
|
41
|
+
sanitize: options.sanitize
|
|
38
42
|
};
|
|
39
43
|
}
|
|
40
44
|
async get(slug) {
|
|
@@ -111,7 +115,9 @@ var SnippetClient = class {
|
|
|
111
115
|
} else if (typeof source === "function") {
|
|
112
116
|
const result = await source();
|
|
113
117
|
if (!Array.isArray(result)) {
|
|
114
|
-
throw new ManifestLoadError(
|
|
118
|
+
throw new ManifestLoadError(
|
|
119
|
+
"Manifest loader must resolve to an array of snippet metadata."
|
|
120
|
+
);
|
|
115
121
|
}
|
|
116
122
|
entries = result.map(normalizeManifestEntry);
|
|
117
123
|
} else {
|
|
@@ -143,11 +149,17 @@ var SnippetClient = class {
|
|
|
143
149
|
try {
|
|
144
150
|
raw = await this.options.fetch(url);
|
|
145
151
|
} catch (error) {
|
|
146
|
-
throw new ManifestLoadError(
|
|
152
|
+
throw new ManifestLoadError(
|
|
153
|
+
`Failed to fetch snippet at '${url}'.`,
|
|
154
|
+
error
|
|
155
|
+
);
|
|
147
156
|
}
|
|
148
157
|
const frontMatter = this.options.frontMatter ? parseFrontMatter(raw) : void 0;
|
|
149
158
|
const body = frontMatter?.content ?? raw;
|
|
150
|
-
|
|
159
|
+
let html = await this.options.render(body);
|
|
160
|
+
if (this.options.sanitize) {
|
|
161
|
+
html = sanitizeMarkup(html, this.options.sanitize);
|
|
162
|
+
}
|
|
151
163
|
const merged = {
|
|
152
164
|
...meta,
|
|
153
165
|
...pickMeta(frontMatter?.meta),
|
|
@@ -163,7 +175,10 @@ var SnippetClient = class {
|
|
|
163
175
|
}
|
|
164
176
|
} catch (error) {
|
|
165
177
|
if (this.options.verbose) {
|
|
166
|
-
console.warn(
|
|
178
|
+
console.warn(
|
|
179
|
+
`Failed to normalize front-matter slug '${frontMatter.slug}':`,
|
|
180
|
+
error
|
|
181
|
+
);
|
|
167
182
|
}
|
|
168
183
|
}
|
|
169
184
|
}
|
|
@@ -195,26 +210,38 @@ function parseManifest(raw, source) {
|
|
|
195
210
|
try {
|
|
196
211
|
parsed = JSON.parse(raw);
|
|
197
212
|
} catch (error) {
|
|
198
|
-
throw new ManifestLoadError(
|
|
213
|
+
throw new ManifestLoadError(
|
|
214
|
+
`Manifest at '${source}' is not valid JSON.`,
|
|
215
|
+
error
|
|
216
|
+
);
|
|
199
217
|
}
|
|
200
218
|
if (!Array.isArray(parsed)) {
|
|
201
|
-
throw new ManifestLoadError(
|
|
219
|
+
throw new ManifestLoadError(
|
|
220
|
+
`Manifest at '${source}' must be a JSON array.`
|
|
221
|
+
);
|
|
202
222
|
}
|
|
203
223
|
return parsed;
|
|
204
224
|
}
|
|
205
225
|
function normalizeManifestEntry(entry) {
|
|
226
|
+
if (!entry || typeof entry !== "object") {
|
|
227
|
+
throw new ManifestLoadError("Manifest entry must be an object.");
|
|
228
|
+
}
|
|
206
229
|
if (!entry.slug) {
|
|
207
|
-
throw new ManifestLoadError(
|
|
230
|
+
throw new ManifestLoadError(
|
|
231
|
+
"Manifest entry is missing required 'slug' property."
|
|
232
|
+
);
|
|
208
233
|
}
|
|
209
234
|
if (!entry.path) {
|
|
210
|
-
throw new ManifestLoadError(
|
|
235
|
+
throw new ManifestLoadError(
|
|
236
|
+
`Manifest entry for '${entry.slug}' is missing required 'path'.`
|
|
237
|
+
);
|
|
211
238
|
}
|
|
212
239
|
const normalized = {
|
|
213
240
|
slug: entry.slug,
|
|
214
241
|
title: entry.title,
|
|
215
242
|
type: entry.type,
|
|
216
243
|
order: entry.order,
|
|
217
|
-
tags: entry.tags
|
|
244
|
+
tags: normalizeTags(entry.tags),
|
|
218
245
|
path: normalizeForwardSlashes(entry.path),
|
|
219
246
|
group: entry.group ?? null,
|
|
220
247
|
draft: entry.draft,
|
|
@@ -252,21 +279,22 @@ function joinPaths(base, relative) {
|
|
|
252
279
|
return normalizeForwardSlashes(`${leading}${trimmed}`);
|
|
253
280
|
}
|
|
254
281
|
function normalizeForwardSlashes(value) {
|
|
255
|
-
|
|
282
|
+
const sanitized = value.replace(/\\/g, "/");
|
|
283
|
+
if (HTTP_PATTERN.test(sanitized)) {
|
|
256
284
|
try {
|
|
257
|
-
const url = new URL(
|
|
285
|
+
const url = new URL(sanitized);
|
|
258
286
|
url.pathname = url.pathname.replace(/\/{2,}/g, "/");
|
|
259
287
|
return url.toString();
|
|
260
288
|
} catch {
|
|
261
289
|
}
|
|
262
290
|
}
|
|
263
|
-
if (
|
|
264
|
-
return `//${
|
|
291
|
+
if (sanitized.startsWith("//")) {
|
|
292
|
+
return `//${sanitized.slice(2).replace(/\/{2,}/g, "/")}`;
|
|
265
293
|
}
|
|
266
|
-
if (
|
|
267
|
-
return `/${
|
|
294
|
+
if (sanitized.startsWith("/")) {
|
|
295
|
+
return `/${sanitized.slice(1).replace(/\/{2,}/g, "/")}`;
|
|
268
296
|
}
|
|
269
|
-
return
|
|
297
|
+
return sanitized.replace(/\/{2,}/g, "/");
|
|
270
298
|
}
|
|
271
299
|
function mergeExtra(base, overrides) {
|
|
272
300
|
if (!base && !overrides) {
|
|
@@ -283,20 +311,36 @@ function cloneRecord(value) {
|
|
|
283
311
|
function cloneMeta(meta) {
|
|
284
312
|
return {
|
|
285
313
|
...meta,
|
|
286
|
-
tags: meta.tags
|
|
314
|
+
tags: normalizeTags(meta.tags),
|
|
287
315
|
extra: cloneRecord(meta.extra)
|
|
288
316
|
};
|
|
289
317
|
}
|
|
318
|
+
function normalizeTags(value) {
|
|
319
|
+
if (!value) {
|
|
320
|
+
return void 0;
|
|
321
|
+
}
|
|
322
|
+
if (Array.isArray(value)) {
|
|
323
|
+
return value.map((entry) => String(entry));
|
|
324
|
+
}
|
|
325
|
+
if (typeof value === "string") {
|
|
326
|
+
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
327
|
+
}
|
|
328
|
+
return void 0;
|
|
329
|
+
}
|
|
290
330
|
async function defaultFetch(url) {
|
|
291
331
|
const runtimeFetch = globalThis.fetch;
|
|
292
332
|
if (!runtimeFetch) {
|
|
293
|
-
throw new ManifestLoadError(
|
|
333
|
+
throw new ManifestLoadError(
|
|
334
|
+
"No global fetch implementation is available. Provide a custom fetch function."
|
|
335
|
+
);
|
|
294
336
|
}
|
|
295
337
|
return runtimeFetch(url);
|
|
296
338
|
}
|
|
297
339
|
async function resolveResponseText(response, url) {
|
|
298
340
|
if (!response.ok) {
|
|
299
|
-
throw new ManifestLoadError(
|
|
341
|
+
throw new ManifestLoadError(
|
|
342
|
+
`Request to '${url}' failed with status ${response.status}.`
|
|
343
|
+
);
|
|
300
344
|
}
|
|
301
345
|
return response.text();
|
|
302
346
|
}
|
|
@@ -332,4 +376,4 @@ function pickMeta(meta) {
|
|
|
332
376
|
export {
|
|
333
377
|
SnippetClient
|
|
334
378
|
};
|
|
335
|
-
//# sourceMappingURL=chunk-
|
|
379
|
+
//# sourceMappingURL=chunk-X5L6GGFF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/snippet-client.ts"],"sourcesContent":["import { normalizeSlug } from \"./slug\";\nimport { parseFrontMatter } from \"./front-matter\";\nimport { renderMarkdown } from \"./markdown\";\nimport { sanitizeMarkup } from \"./sanitize\";\nimport { ManifestLoadError, SnippetNotFoundError } from \"./errors\";\nimport type {\n ManifestSource,\n ResponseLike,\n Snippet,\n SnippetClientOptions,\n SnippetFetcherResult,\n SnippetMeta,\n SnippetSearchFilter,\n} from \"./types\";\n\nexport { ManifestLoadError, SnippetNotFoundError } from \"./errors\";\n\ninterface SnippetClientInternalOptions {\n manifest: ManifestSource;\n base?: string;\n fetch: (url: string) => Promise<string>;\n frontMatter: boolean;\n cache: boolean;\n verbose: boolean;\n render: (markdown: string) => Promise<string>;\n sanitize?: SnippetClientOptions[\"sanitize\"];\n}\n\nconst HTTP_PATTERN = /^https?:\\/\\//i;\n\nexport class SnippetClient {\n private readonly options: SnippetClientInternalOptions;\n private readonly manifestUrl?: string;\n private readonly inferredBase?: string;\n\n private manifestPromise?: Promise<SnippetMeta[]>;\n private readonly snippetCache = new Map<string, Promise<Snippet>>();\n\n constructor(options: SnippetClientOptions) {\n if (!options || !options.manifest) {\n throw new ManifestLoadError(\n \"A manifest source must be provided to SnippetClient.\",\n );\n }\n\n this.manifestUrl =\n typeof options.manifest === \"string\" ? options.manifest : undefined;\n this.inferredBase = this.manifestUrl\n ? deriveBaseFromManifest(this.manifestUrl)\n : undefined;\n\n const fetcher = options.fetch ?? defaultFetch;\n\n const renderOption = options.render;\n\n const renderer = renderOption\n ? async (markdown: string) => Promise.resolve(renderOption(markdown))\n : async (markdown: string) => Promise.resolve(renderMarkdown(markdown));\n\n this.options = {\n manifest: options.manifest,\n base: options.base,\n fetch: async (url: string) => {\n const response = await fetcher(url);\n if (typeof response === \"string\") {\n return response;\n }\n return resolveResponseText(response, url);\n },\n frontMatter: options.frontMatter !== false,\n cache: options.cache !== false,\n verbose: options.verbose === true,\n render: renderer,\n sanitize: options.sanitize,\n };\n }\n\n async get(slug: string): Promise<Snippet> {\n const manifest = await this.loadManifest();\n const entry = manifest.find((item) => item.slug === slug);\n if (!entry) {\n throw new SnippetNotFoundError(slug);\n }\n return this.loadSnippet(entry);\n }\n\n async listAll(): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n return manifest.map(cloneMeta);\n }\n\n async listByGroup(group: string): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n return manifest\n .filter((item) => (item.group ?? null) === group)\n .map(cloneMeta);\n }\n\n async listByType(type: string): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n return manifest.filter((item) => item.type === type).map(cloneMeta);\n }\n\n async search(filter: SnippetSearchFilter): Promise<SnippetMeta[]> {\n const manifest = await this.loadManifest();\n const tags = filter.tags ?? [];\n const mode = filter.tagsMode ?? \"any\";\n\n return manifest\n .filter((item) => {\n if (filter.type && item.type !== filter.type) {\n return false;\n }\n if (filter.group && (item.group ?? undefined) !== filter.group) {\n return false;\n }\n if (!tags.length) {\n return true;\n }\n const metaTags = item.tags ?? [];\n if (!metaTags.length) {\n return false;\n }\n if (mode === \"all\") {\n return tags.every((tag) => metaTags.includes(tag));\n }\n return tags.some((tag) => metaTags.includes(tag));\n })\n .map(cloneMeta);\n }\n\n async getHtml(slug: string): Promise<string> {\n const snippet = await this.get(slug);\n return snippet.html;\n }\n\n invalidate(): void {\n this.manifestPromise = undefined;\n this.snippetCache.clear();\n }\n\n invalidateSlug(slug: string): void {\n this.snippetCache.delete(slug);\n }\n\n private async loadManifest(): Promise<SnippetMeta[]> {\n if (this.options.cache && this.manifestPromise) {\n return this.manifestPromise;\n }\n\n const promise = this.resolveManifest();\n if (this.options.cache) {\n this.manifestPromise = promise;\n }\n return promise;\n }\n\n private async resolveManifest(): Promise<SnippetMeta[]> {\n const source = this.options.manifest;\n let entries: SnippetMeta[];\n\n try {\n if (Array.isArray(source)) {\n entries = source.map(normalizeManifestEntry);\n } else if (typeof source === \"function\") {\n const result = await source();\n if (!Array.isArray(result)) {\n throw new ManifestLoadError(\n \"Manifest loader must resolve to an array of snippet metadata.\",\n );\n }\n entries = result.map(normalizeManifestEntry);\n } else {\n const raw = await this.options.fetch(source);\n entries = parseManifest(raw, source).map(normalizeManifestEntry);\n }\n } catch (error) {\n if (error instanceof ManifestLoadError) {\n throw error;\n }\n throw new ManifestLoadError(\"Failed to load snippet manifest.\", error);\n }\n\n return entries.map(cloneMeta);\n }\n\n private loadSnippet(meta: SnippetMeta): Promise<Snippet> {\n const cached = this.options.cache\n ? this.snippetCache.get(meta.slug)\n : undefined;\n if (cached) {\n return cached;\n }\n const promise = this.fetchSnippet(meta);\n if (this.options.cache) {\n this.snippetCache.set(meta.slug, promise);\n }\n return promise;\n }\n\n private async fetchSnippet(meta: SnippetMeta): Promise<Snippet> {\n const url = this.resolveSnippetPath(meta.path);\n let raw: string;\n try {\n raw = await this.options.fetch(url);\n } catch (error) {\n throw new ManifestLoadError(\n `Failed to fetch snippet at '${url}'.`,\n error,\n );\n }\n\n const frontMatter = this.options.frontMatter\n ? parseFrontMatter(raw)\n : undefined;\n const body = frontMatter?.content ?? raw;\n let html = await this.options.render(body);\n if (this.options.sanitize) {\n html = sanitizeMarkup(html, this.options.sanitize);\n }\n\n const merged: SnippetMeta = {\n ...meta,\n ...pickMeta(frontMatter?.meta),\n extra: mergeExtra(meta.extra, frontMatter?.extra),\n };\n\n if (frontMatter?.slug) {\n try {\n const normalizedFrontSlug = normalizeSlug(frontMatter.slug);\n if (normalizedFrontSlug !== meta.slug && this.options.verbose) {\n console.warn(\n `Front-matter slug '${frontMatter.slug}' (normalized: '${normalizedFrontSlug}') differs from manifest slug '${meta.slug}'.`,\n );\n }\n } catch (error) {\n if (this.options.verbose) {\n console.warn(\n `Failed to normalize front-matter slug '${frontMatter.slug}':`,\n error,\n );\n }\n }\n }\n\n const snippet: Snippet = { ...merged, html, raw: body, markdown: body };\n if (merged.tags) {\n snippet.tags = [...merged.tags];\n }\n return snippet;\n }\n\n private resolveSnippetPath(path: string): string {\n if (HTTP_PATTERN.test(path)) {\n return normalizeForwardSlashes(path);\n }\n\n const base = this.options.base ?? this.inferredBase ?? \"\";\n\n if (path.startsWith(\"/\")) {\n if (base) {\n return joinPaths(base, path);\n }\n return normalizeForwardSlashes(path);\n }\n\n if (base) {\n return joinPaths(base, path);\n }\n return normalizeForwardSlashes(path);\n }\n}\n\nfunction parseManifest(raw: string, source: string): SnippetMeta[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new ManifestLoadError(\n `Manifest at '${source}' is not valid JSON.`,\n error,\n );\n }\n\n if (!Array.isArray(parsed)) {\n throw new ManifestLoadError(\n `Manifest at '${source}' must be a JSON array.`,\n );\n }\n\n return parsed as SnippetMeta[];\n}\n\nfunction normalizeManifestEntry(entry: SnippetMeta): SnippetMeta {\n if (!entry || typeof entry !== \"object\") {\n throw new ManifestLoadError(\"Manifest entry must be an object.\");\n }\n if (!entry.slug) {\n throw new ManifestLoadError(\n \"Manifest entry is missing required 'slug' property.\",\n );\n }\n if (!entry.path) {\n throw new ManifestLoadError(\n `Manifest entry for '${entry.slug}' is missing required 'path'.`,\n );\n }\n const normalized: SnippetMeta = {\n slug: entry.slug,\n title: entry.title,\n type: entry.type,\n order: entry.order,\n tags: normalizeTags(entry.tags),\n path: normalizeForwardSlashes(entry.path),\n group: entry.group ?? null,\n draft: entry.draft,\n extra: cloneRecord(entry.extra),\n };\n return normalized;\n}\n\nfunction deriveBaseFromManifest(manifest: string): string | undefined {\n if (HTTP_PATTERN.test(manifest)) {\n try {\n const url = new URL(manifest);\n url.hash = \"\";\n url.search = \"\";\n const path = url.pathname;\n url.pathname = path.replace(/[^/]*$/, \"\");\n return url.toString();\n } catch (error) {\n console.warn(`Unable to derive base from manifest '${manifest}':`, error);\n return undefined;\n }\n }\n\n const sanitized = manifest.replace(/[?#].*$/, \"\");\n const index = sanitized.lastIndexOf(\"/\");\n if (index === -1) {\n return undefined;\n }\n return sanitized.slice(0, index + 1);\n}\n\nfunction joinPaths(base: string, relative: string): string {\n if (HTTP_PATTERN.test(base)) {\n return new URL(relative, base).toString();\n }\n const leading = base.endsWith(\"/\") ? base : `${base}/`;\n const trimmed = relative.startsWith(\"/\") ? relative.slice(1) : relative;\n return normalizeForwardSlashes(`${leading}${trimmed}`);\n}\n\nfunction normalizeForwardSlashes(value: string): string {\n const sanitized = value.replace(/\\\\/g, \"/\");\n if (HTTP_PATTERN.test(sanitized)) {\n try {\n const url = new URL(sanitized);\n url.pathname = url.pathname.replace(/\\/{2,}/g, \"/\");\n return url.toString();\n } catch {\n // fall back to manual normalization below\n }\n }\n\n if (sanitized.startsWith(\"//\")) {\n return `//${sanitized.slice(2).replace(/\\/{2,}/g, \"/\")}`;\n }\n\n if (sanitized.startsWith(\"/\")) {\n return `/${sanitized.slice(1).replace(/\\/{2,}/g, \"/\")}`;\n }\n\n return sanitized.replace(/\\/{2,}/g, \"/\");\n}\n\nfunction mergeExtra(\n base: Record<string, unknown> | undefined,\n overrides: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n if (!base && !overrides) {\n return undefined;\n }\n return { ...(base ?? {}), ...(overrides ?? {}) };\n}\n\nfunction cloneRecord<T extends Record<string, unknown> | undefined>(\n value: T,\n): T {\n if (!value) {\n return value;\n }\n return { ...value } as T;\n}\n\nfunction cloneMeta(meta: SnippetMeta): SnippetMeta {\n return {\n ...meta,\n tags: normalizeTags(meta.tags),\n extra: cloneRecord(meta.extra),\n };\n}\n\nfunction normalizeTags(value: unknown): string[] | undefined {\n if (!value) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return value.map((entry) => String(entry));\n }\n if (typeof value === \"string\") {\n return value\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean);\n }\n return undefined;\n}\n\nasync function defaultFetch(url: string): Promise<SnippetFetcherResult> {\n const runtimeFetch = (\n globalThis as typeof globalThis & { fetch?: typeof fetch }\n ).fetch;\n if (!runtimeFetch) {\n throw new ManifestLoadError(\n \"No global fetch implementation is available. Provide a custom fetch function.\",\n );\n }\n return runtimeFetch(url);\n}\n\nasync function resolveResponseText(\n response: ResponseLike,\n url: string,\n): Promise<string> {\n if (!response.ok) {\n throw new ManifestLoadError(\n `Request to '${url}' failed with status ${response.status}.`,\n );\n }\n return response.text();\n}\n\nfunction pickMeta(meta?: Partial<SnippetMeta>): Partial<SnippetMeta> {\n if (!meta) {\n return {};\n }\n const result: Partial<SnippetMeta> = {};\n if (meta.title !== undefined) {\n result.title = meta.title;\n }\n if (meta.type !== undefined) {\n result.type = meta.type;\n }\n if (meta.order !== undefined) {\n result.order = meta.order;\n }\n if (meta.tags !== undefined) {\n result.tags = [...meta.tags];\n }\n if (meta.group !== undefined) {\n result.group = meta.group;\n }\n if (meta.draft !== undefined) {\n result.draft = meta.draft;\n }\n if (meta.path !== undefined) {\n result.path = meta.path;\n }\n return result;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -8,7 +8,9 @@ function normalizeSlug(input) {
|
|
|
8
8
|
}
|
|
9
9
|
const normalized = value.toLowerCase().replace(NON_ALPHANUMERIC, "-").replace(/-{2,}/g, "-").replace(LEADING_TRAILING_DASH, "");
|
|
10
10
|
if (!normalized) {
|
|
11
|
-
throw new Error(
|
|
11
|
+
throw new Error(
|
|
12
|
+
`Slug '${input}' does not contain any alphanumeric characters`
|
|
13
|
+
);
|
|
12
14
|
}
|
|
13
15
|
return normalized;
|
|
14
16
|
}
|
|
@@ -16,4 +18,4 @@ function normalizeSlug(input) {
|
|
|
16
18
|
export {
|
|
17
19
|
normalizeSlug
|
|
18
20
|
};
|
|
19
|
-
//# sourceMappingURL=chunk-
|
|
21
|
+
//# sourceMappingURL=chunk-ZEQXN4ZD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/slug.ts"],"sourcesContent":["const NON_ALPHANUMERIC = /[^a-z0-9]+/gi;\nconst LEADING_TRAILING_DASH = /^-+|-+$/g;\n\nexport function normalizeSlug(input: string): string {\n const value = input?.trim();\n if (!value) {\n throw new Error(\"Cannot normalize an empty slug\");\n }\n\n const normalized = value\n .toLowerCase()\n .replace(NON_ALPHANUMERIC, \"-\")\n .replace(/-{2,}/g, \"-\")\n .replace(LEADING_TRAILING_DASH, \"\");\n\n if (!normalized) {\n throw new Error(`Slug '${input}' does not contain any alphanumeric characters
|
|
1
|
+
{"version":3,"sources":["../src/slug.ts"],"sourcesContent":["const NON_ALPHANUMERIC = /[^a-z0-9]+/gi;\nconst LEADING_TRAILING_DASH = /^-+|-+$/g;\n\nexport function normalizeSlug(input: string): string {\n const value = input?.trim();\n if (!value) {\n throw new Error(\"Cannot normalize an empty slug\");\n }\n\n const normalized = value\n .toLowerCase()\n .replace(NON_ALPHANUMERIC, \"-\")\n .replace(/-{2,}/g, \"-\")\n .replace(LEADING_TRAILING_DASH, \"\");\n\n if (!normalized) {\n throw new Error(\n `Slug '${input}' does not contain any alphanumeric characters`,\n );\n }\n\n return normalized;\n}\n"],"mappings":";AAAA,IAAM,mBAAmB;AACzB,IAAM,wBAAwB;AAEvB,SAAS,cAAc,OAAuB;AACnD,QAAM,QAAQ,OAAO,KAAK;AAC1B,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AAEA,QAAM,aAAa,MAChB,YAAY,EACZ,QAAQ,kBAAkB,GAAG,EAC7B,QAAQ,UAAU,GAAG,EACrB,QAAQ,uBAAuB,EAAE;AAEpC,MAAI,CAAC,YAAY;AACf,UAAM,IAAI;AAAA,MACR,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
|