From 81189f697c813648b318f4d8ae681723b4453a76 Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Sat, 14 Mar 2026 21:30:17 +0100 Subject: [PATCH] chore: commit dist/ and remove prepare script With build tools (tsup, typescript) moved to devDependencies, the prepare script can no longer build when npm fetches this package from GitHub (npm does not install devDependencies for git dependencies). Commit the pre-built dist/ output so GitHub-based installs work without a build step. --- .gitignore | 2 +- dist/dom.d.ts | 5 + dist/dom.js | 56 +++++++++ dist/dom.js.map | 1 + dist/escape.d.ts | 23 ++++ dist/escape.js | 11 ++ dist/escape.js.map | 1 + dist/index.d.ts | 8 ++ dist/index.js | 280 +++++++++++++++++++++++++++++++++++++++++++++ dist/index.js.map | 1 + dist/jsx.d.ts | 20 ++++ dist/jsx.js | 28 +++++ dist/jsx.js.map | 1 + dist/lang.d.ts | 4 + dist/lang.js | 11 ++ dist/lang.js.map | 1 + dist/path.d.ts | 40 +++++++ dist/path.js | 189 ++++++++++++++++++++++++++++++ dist/path.js.map | 1 + package.json | 1 - 20 files changed, 682 insertions(+), 2 deletions(-) create mode 100644 dist/dom.d.ts create mode 100644 dist/dom.js create mode 100644 dist/dom.js.map create mode 100644 dist/escape.d.ts create mode 100644 dist/escape.js create mode 100644 dist/escape.js.map create mode 100644 dist/index.d.ts create mode 100644 dist/index.js create mode 100644 dist/index.js.map create mode 100644 dist/jsx.d.ts create mode 100644 dist/jsx.js create mode 100644 dist/jsx.js.map create mode 100644 dist/lang.d.ts create mode 100644 dist/lang.js create mode 100644 dist/lang.js.map create mode 100644 dist/path.d.ts create mode 100644 dist/path.js create mode 100644 dist/path.js.map diff --git a/.gitignore b/.gitignore index 657842b..c75c89e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ node_modules/ .pnp.js # Build output -dist/ +# dist/ is committed so that GitHub-based installs work without build tools build/ *.tsbuildinfo diff --git a/dist/dom.d.ts b/dist/dom.d.ts new file mode 100644 index 0000000..434236c --- /dev/null +++ b/dist/dom.d.ts @@ -0,0 +1,5 @@ +declare function removeAllChildren(el: HTMLElement): void; +declare function registerEscapeHandler(outsideContainer: HTMLElement | null, onEscape: () => void): () => void; +declare function normalizeRelativeURLs(html: Document, baseUrl: string): void; + +export { normalizeRelativeURLs, registerEscapeHandler, removeAllChildren }; diff --git a/dist/dom.js b/dist/dom.js new file mode 100644 index 0000000..e4fae17 --- /dev/null +++ b/dist/dom.js @@ -0,0 +1,56 @@ +// src/dom.ts +function removeAllChildren(el) { + while (el.firstChild) { + el.removeChild(el.firstChild); + } +} +function registerEscapeHandler(outsideContainer, onEscape) { + if (!outsideContainer) return () => { + }; + const onClick = (e) => { + if (!outsideContainer.classList.contains("active")) { + return; + } + if (e.target === outsideContainer) { + e.preventDefault(); + e.stopPropagation(); + onEscape(); + } + }; + const onKeydown = (e) => { + if (!outsideContainer.classList.contains("active")) { + return; + } + if (e.key === "Escape") { + e.preventDefault(); + onEscape(); + } + }; + outsideContainer.addEventListener("click", onClick); + document.addEventListener("keydown", onKeydown); + return () => { + outsideContainer.removeEventListener("click", onClick); + document.removeEventListener("keydown", onKeydown); + }; +} +function normalizeRelativeURLs(html, baseUrl) { + const elements = html.querySelectorAll("[src], [href]"); + for (const el of Array.from(elements)) { + const attr = el.hasAttribute("href") ? "href" : "src"; + const val = el.getAttribute(attr); + if (!val) continue; + if (val.startsWith("http://") || val.startsWith("https://") || val.startsWith("mailto:") || val.startsWith("tel:") || val.startsWith("#") || val.startsWith("/") || val.startsWith("data:")) { + continue; + } + try { + const normalized = new URL(val, baseUrl).toString(); + el.setAttribute(attr, normalized); + } catch { + continue; + } + } +} + +export { normalizeRelativeURLs, registerEscapeHandler, removeAllChildren }; +//# sourceMappingURL=dom.js.map +//# sourceMappingURL=dom.js.map \ No newline at end of file diff --git a/dist/dom.js.map b/dist/dom.js.map new file mode 100644 index 0000000..7e5e5f1 --- /dev/null +++ b/dist/dom.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/dom.ts"],"names":[],"mappings":";AAAO,SAAS,kBAAkB,EAAA,EAAuB;AACvD,EAAA,OAAO,GAAG,UAAA,EAAY;AACpB,IAAA,EAAA,CAAG,WAAA,CAAY,GAAG,UAAU,CAAA;AAAA,EAC9B;AACF;AAEO,SAAS,qBAAA,CACd,kBACA,QAAA,EACY;AACZ,EAAA,IAAI,CAAC,gBAAA,EAAkB,OAAO,MAAM;AAAA,EAAC,CAAA;AAErC,EAAA,MAAM,OAAA,GAAU,CAAC,CAAA,KAAkB;AACjC,IAAA,IAAI,CAAC,gBAAA,CAAiB,SAAA,CAAU,QAAA,CAAS,QAAQ,CAAA,EAAG;AAClD,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAA,CAAE,WAAW,gBAAA,EAAkB;AACjC,MAAA,CAAA,CAAE,cAAA,EAAe;AACjB,MAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,MAAA,QAAA,EAAS;AAAA,IACX;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAqB;AACtC,IAAA,IAAI,CAAC,gBAAA,CAAiB,SAAA,CAAU,QAAA,CAAS,QAAQ,CAAA,EAAG;AAClD,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,EAAU;AACtB,MAAA,CAAA,CAAE,cAAA,EAAe;AACjB,MAAA,QAAA,EAAS;AAAA,IACX;AAAA,EACF,CAAA;AAEA,EAAA,gBAAA,CAAiB,gBAAA,CAAiB,SAAS,OAAO,CAAA;AAClD,EAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAE9C,EAAA,OAAO,MAAM;AACX,IAAA,gBAAA,CAAiB,mBAAA,CAAoB,SAAS,OAAO,CAAA;AACrD,IAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,SAAS,CAAA;AAAA,EACnD,CAAA;AACF;AAEO,SAAS,qBAAA,CAAsB,MAAgB,OAAA,EAAuB;AAC3E,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,gBAAA,CAA8B,eAAe,CAAA;AACnE,EAAA,KAAA,MAAW,EAAA,IAAM,KAAA,CAAM,IAAA,CAAK,QAAQ,CAAA,EAAG;AACrC,IAAA,MAAM,IAAA,GAAO,EAAA,CAAG,YAAA,CAAa,MAAM,IAAI,MAAA,GAAS,KAAA;AAChD,IAAA,MAAM,GAAA,GAAM,EAAA,CAAG,YAAA,CAAa,IAAI,CAAA;AAChC,IAAA,IAAI,CAAC,GAAA,EAAK;AACV,IAAA,IACE,GAAA,CAAI,UAAA,CAAW,SAAS,CAAA,IACxB,GAAA,CAAI,UAAA,CAAW,UAAU,CAAA,IACzB,GAAA,CAAI,UAAA,CAAW,SAAS,CAAA,IACxB,GAAA,CAAI,UAAA,CAAW,MAAM,CAAA,IACrB,GAAA,CAAI,UAAA,CAAW,GAAG,CAAA,IAClB,GAAA,CAAI,UAAA,CAAW,GAAG,CAAA,IAClB,GAAA,CAAI,UAAA,CAAW,OAAO,CAAA,EACtB;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAI;AACF,MAAA,MAAM,aAAa,IAAI,GAAA,CAAI,GAAA,EAAK,OAAO,EAAE,QAAA,EAAS;AAClD,MAAA,EAAA,CAAG,YAAA,CAAa,MAAM,UAAU,CAAA;AAAA,IAClC,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AAAA,EACF;AACF","file":"dom.js","sourcesContent":["export function removeAllChildren(el: HTMLElement): void {\n while (el.firstChild) {\n el.removeChild(el.firstChild);\n }\n}\n\nexport function registerEscapeHandler(\n outsideContainer: HTMLElement | null,\n onEscape: () => void,\n): () => void {\n if (!outsideContainer) return () => {};\n\n const onClick = (e: MouseEvent) => {\n if (!outsideContainer.classList.contains(\"active\")) {\n return;\n }\n if (e.target === outsideContainer) {\n e.preventDefault();\n e.stopPropagation();\n onEscape();\n }\n };\n\n const onKeydown = (e: KeyboardEvent) => {\n if (!outsideContainer.classList.contains(\"active\")) {\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n onEscape();\n }\n };\n\n outsideContainer.addEventListener(\"click\", onClick);\n document.addEventListener(\"keydown\", onKeydown);\n\n return () => {\n outsideContainer.removeEventListener(\"click\", onClick);\n document.removeEventListener(\"keydown\", onKeydown);\n };\n}\n\nexport function normalizeRelativeURLs(html: Document, baseUrl: string): void {\n const elements = html.querySelectorAll(\"[src], [href]\");\n for (const el of Array.from(elements)) {\n const attr = el.hasAttribute(\"href\") ? \"href\" : \"src\";\n const val = el.getAttribute(attr);\n if (!val) continue;\n if (\n val.startsWith(\"http://\") ||\n val.startsWith(\"https://\") ||\n val.startsWith(\"mailto:\") ||\n val.startsWith(\"tel:\") ||\n val.startsWith(\"#\") ||\n val.startsWith(\"/\") ||\n val.startsWith(\"data:\")\n ) {\n continue;\n }\n try {\n const normalized = new URL(val, baseUrl).toString();\n el.setAttribute(attr, normalized);\n } catch {\n continue;\n }\n }\n}\n"]} \ No newline at end of file diff --git a/dist/escape.d.ts b/dist/escape.d.ts new file mode 100644 index 0000000..9be4286 --- /dev/null +++ b/dist/escape.d.ts @@ -0,0 +1,23 @@ +/** + * HTML escape utilities for safe string rendering. + */ +/** + * Escapes HTML special characters in a string to prevent XSS. + * @param unsafe - The string to escape + * @returns The escaped string safe for HTML rendering + * + * @example + * escapeHTML('') // '<script>alert("xss")</script>' + */ +declare function escapeHTML(unsafe: string): string; +/** + * Unescapes HTML entities back to their original characters. + * @param html - The HTML-escaped string + * @returns The unescaped string + * + * @example + * unescapeHTML('<div>') // '
' + */ +declare function unescapeHTML(html: string): string; + +export { escapeHTML, unescapeHTML }; diff --git a/dist/escape.js b/dist/escape.js new file mode 100644 index 0000000..5740e9a --- /dev/null +++ b/dist/escape.js @@ -0,0 +1,11 @@ +// src/escape.ts +function escapeHTML(unsafe) { + return unsafe.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'"); +} +function unescapeHTML(html) { + return html.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll(""", '"').replaceAll("'", "'"); +} + +export { escapeHTML, unescapeHTML }; +//# sourceMappingURL=escape.js.map +//# sourceMappingURL=escape.js.map \ No newline at end of file diff --git a/dist/escape.js.map b/dist/escape.js.map new file mode 100644 index 0000000..4aa4ee7 --- /dev/null +++ b/dist/escape.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/escape.ts"],"names":[],"mappings":";AAYO,SAAS,WAAW,MAAA,EAAwB;AACjD,EAAA,OAAO,OACJ,UAAA,CAAW,GAAA,EAAK,OAAO,CAAA,CACvB,UAAA,CAAW,KAAK,MAAM,CAAA,CACtB,WAAW,GAAA,EAAK,MAAM,EACtB,UAAA,CAAW,GAAA,EAAK,QAAQ,CAAA,CACxB,UAAA,CAAW,KAAK,QAAQ,CAAA;AAC7B;AAUO,SAAS,aAAa,IAAA,EAAsB;AACjD,EAAA,OAAO,KACJ,UAAA,CAAW,OAAA,EAAS,GAAG,CAAA,CACvB,UAAA,CAAW,QAAQ,GAAG,CAAA,CACtB,WAAW,MAAA,EAAQ,GAAG,EACtB,UAAA,CAAW,QAAA,EAAU,GAAG,CAAA,CACxB,UAAA,CAAW,UAAU,GAAG,CAAA;AAC7B","file":"escape.js","sourcesContent":["/**\n * HTML escape utilities for safe string rendering.\n */\n\n/**\n * Escapes HTML special characters in a string to prevent XSS.\n * @param unsafe - The string to escape\n * @returns The escaped string safe for HTML rendering\n *\n * @example\n * escapeHTML('') // '<script>alert("xss")</script>'\n */\nexport function escapeHTML(unsafe: string): string {\n return unsafe\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n}\n\n/**\n * Unescapes HTML entities back to their original characters.\n * @param html - The HTML-escaped string\n * @returns The unescaped string\n *\n * @example\n * unescapeHTML('<div>') // '
'\n */\nexport function unescapeHTML(html: string): string {\n return html\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll(\""\", '\"')\n .replaceAll(\"'\", \"'\");\n}\n"]} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..4ec3dec --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,8 @@ +export { RelativeURL, SimpleSlug, TransformOptions, endsWith, getAllSegmentPrefixes, getFileExtension, getFullSlug, getFullSlugFromUrl, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, pathToRoot, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix } from './path.js'; +export { normalizeRelativeURLs, registerEscapeHandler, removeAllChildren } from './dom.js'; +export { capitalize, classNames } from './lang.js'; +export { escapeHTML, unescapeHTML } from './escape.js'; +export { htmlToJsx } from './jsx.js'; +export { FilePath, FullSlug } from '@quartz-community/types'; +import 'hast-util-to-jsx-runtime'; +import 'hast'; diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..875a5db --- /dev/null +++ b/dist/index.js @@ -0,0 +1,280 @@ +import { slug } from 'github-slugger'; +import { toJsxRuntime } from 'hast-util-to-jsx-runtime'; +import { jsxs, jsx, Fragment } from 'preact/jsx-runtime'; +import { h } from 'preact'; + +// src/path.ts +function isFilePath(s) { + const validStart = !s.startsWith("."); + return validStart && _hasFileExtension(s); +} +function isFullSlug(s) { + const validStart = !(s.startsWith(".") || s.startsWith("/")); + const validEnding = !s.endsWith("/"); + return validStart && validEnding && !_containsForbiddenCharacters(s); +} +function isSimpleSlug(s) { + const validStart = !(s.startsWith(".") || s.length > 1 && s.startsWith("/")); + const validEnding = !endsWith(s, "index"); + return validStart && !_containsForbiddenCharacters(s) && validEnding && !_hasFileExtension(s); +} +function isRelativeURL(s) { + const validStart = /^\.{1,2}/.test(s); + const validEnding = !endsWith(s, "index"); + return validStart && validEnding && ![".md", ".html"].includes(getFileExtension(s) ?? ""); +} +function isAbsoluteURL(s) { + try { + new URL(s); + } catch { + return false; + } + return true; +} +function simplifySlug(fp) { + const res = stripSlashes(trimSuffix(fp, "index"), true); + return res.length === 0 ? "/" : res; +} +function getFullSlug(window2) { + const res = window2.document.body.dataset.slug; + return res; +} +function getFullSlugFromUrl() { + let rawSlug = window.location.pathname; + if (rawSlug.endsWith("/")) rawSlug = rawSlug.slice(0, -1); + if (rawSlug.startsWith("/")) rawSlug = rawSlug.slice(1); + return rawSlug; +} +function slugifyFilePath(fp, excludeExt) { + fp = stripSlashes(fp); + const ext = getFileExtension(fp); + const withoutFileExt = fp.replace(new RegExp(ext + "$"), ""); + const finalExt = excludeExt || [".md", ".html", void 0].includes(ext) ? "" : ext; + let slug = _sluggify(withoutFileExt); + if (endsWith(slug, "_index")) { + slug = slug.replace(/_index$/, "index"); + } + return slug + (finalExt ?? ""); +} +function joinSegments(...args) { + if (args.length === 0) { + return ""; + } + let joined = args.filter((segment) => segment !== "" && segment !== "/").map((segment) => stripSlashes(segment)).join("/"); + const first = args[0]; + const last = args[args.length - 1]; + if (first?.startsWith("/")) { + joined = "/" + joined; + } + if (last?.endsWith("/")) { + joined = joined + "/"; + } + return joined; +} +function resolvePath(to) { + if (to.startsWith("/")) return to; + return "/" + to; +} +function endsWith(s, suffix) { + return s === suffix || s.endsWith("/" + suffix); +} +function trimSuffix(s, suffix) { + if (endsWith(s, suffix)) { + s = s.slice(0, -suffix.length); + } + return s; +} +function stripSlashes(s, onlyStripPrefix) { + if (s.startsWith("/")) { + s = s.substring(1); + } + if (!onlyStripPrefix && s.endsWith("/")) { + s = s.slice(0, -1); + } + return s; +} +function getFileExtension(s) { + return s.match(/\.[A-Za-z0-9]+$/)?.[0]; +} +function isFolderPath(fplike) { + return fplike.endsWith("/") || endsWith(fplike, "index") || endsWith(fplike, "index.md") || endsWith(fplike, "index.html"); +} +function getAllSegmentPrefixes(path) { + const segments = path.split("/"); + const results = []; + for (let i = 0; i < segments.length; i++) { + results.push(segments.slice(0, i + 1).join("/")); + } + return results; +} +function pathToRoot(slug) { + let rootPath = slug.split("/").filter((x) => x !== "").slice(0, -1).map((_) => "..").join("/"); + if (rootPath.length === 0) { + rootPath = "."; + } + return rootPath; +} +function resolveRelative(current, target) { + const res = joinSegments(pathToRoot(current), simplifySlug(target)); + return res; +} +function splitAnchor(link) { + const [fp, anchor] = link.split("#", 2); + if (fp.endsWith(".pdf")) { + return [fp, anchor === void 0 ? "" : `#${anchor}`]; + } + const slugged = anchor === void 0 ? "" : "#" + slug(anchor); + return [fp, slugged]; +} +function slugTag(tag) { + return tag.split("/").map((tagSegment) => _sluggify(tagSegment)).join("/"); +} +function transformInternalLink(link) { + const [fplike, anchor] = splitAnchor(decodeURI(link)); + const folderPath = isFolderPath(fplike); + const segments = fplike.split("/").filter((x) => x.length > 0); + const prefix = segments.filter(_isRelativeSegment).join("/"); + const fp = segments.filter((seg) => !_isRelativeSegment(seg) && seg !== "").join("/"); + const simpleSlug = simplifySlug(slugifyFilePath(fp)); + const joined = joinSegments(stripSlashes(prefix), stripSlashes(simpleSlug)); + const trail = folderPath ? "/" : ""; + const res = _addRelativeToStart(joined) + trail + anchor; + return res; +} +function transformLink(src, target, opts) { + const targetSlug = transformInternalLink(target); + if (opts.strategy === "relative") { + return targetSlug; + } else { + const folderTail = isFolderPath(targetSlug) ? "/" : ""; + const canonicalSlug = stripSlashes(targetSlug.slice(".".length)); + const [targetCanonical, targetAnchor] = splitAnchor(canonicalSlug); + if (opts.strategy === "shortest") { + const matchingFileNames = opts.allSlugs.filter((slug) => { + const parts = slug.split("/"); + const fileName = parts.at(-1); + return targetCanonical === fileName; + }); + if (matchingFileNames.length === 1) { + const matchedSlug = matchingFileNames[0]; + return resolveRelative(src, matchedSlug) + targetAnchor; + } + } + return joinSegments(pathToRoot(src), canonicalSlug) + folderTail; + } +} +function _sluggify(s) { + return s.split("/").map( + (segment) => segment.replace(/\s/g, "-").replace(/&/g, "-and-").replace(/%/g, "-percent").replace(/\?/g, "").replace(/#/g, "") + ).join("/").replace(/\/$/, ""); +} +function _containsForbiddenCharacters(s) { + return s.includes(" ") || s.includes("#") || s.includes("?") || s.includes("&"); +} +function _hasFileExtension(s) { + return getFileExtension(s) !== void 0; +} +function _isRelativeSegment(s) { + return /^\.{0,2}$/.test(s); +} +function _addRelativeToStart(s) { + if (s === "") { + s = "."; + } + if (!s.startsWith(".")) { + s = joinSegments(".", s); + } + return s; +} + +// src/dom.ts +function removeAllChildren(el) { + while (el.firstChild) { + el.removeChild(el.firstChild); + } +} +function registerEscapeHandler(outsideContainer, onEscape) { + if (!outsideContainer) return () => { + }; + const onClick = (e) => { + if (!outsideContainer.classList.contains("active")) { + return; + } + if (e.target === outsideContainer) { + e.preventDefault(); + e.stopPropagation(); + onEscape(); + } + }; + const onKeydown = (e) => { + if (!outsideContainer.classList.contains("active")) { + return; + } + if (e.key === "Escape") { + e.preventDefault(); + onEscape(); + } + }; + outsideContainer.addEventListener("click", onClick); + document.addEventListener("keydown", onKeydown); + return () => { + outsideContainer.removeEventListener("click", onClick); + document.removeEventListener("keydown", onKeydown); + }; +} +function normalizeRelativeURLs(html, baseUrl) { + const elements = html.querySelectorAll("[src], [href]"); + for (const el of Array.from(elements)) { + const attr = el.hasAttribute("href") ? "href" : "src"; + const val = el.getAttribute(attr); + if (!val) continue; + if (val.startsWith("http://") || val.startsWith("https://") || val.startsWith("mailto:") || val.startsWith("tel:") || val.startsWith("#") || val.startsWith("/") || val.startsWith("data:")) { + continue; + } + try { + const normalized = new URL(val, baseUrl).toString(); + el.setAttribute(attr, normalized); + } catch { + continue; + } + } +} + +// src/lang.ts +function capitalize(s) { + return s.substring(0, 1).toUpperCase() + s.substring(1); +} +function classNames(...classes) { + return classes.filter(Boolean).join(" "); +} + +// src/escape.ts +function escapeHTML(unsafe) { + return unsafe.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'"); +} +function unescapeHTML(html) { + return html.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll(""", '"').replaceAll("'", "'"); +} +function childrenToString(children) { + if (typeof children === "string") return children; + if (Array.isArray(children)) return children.map(childrenToString).join(""); + return String(children ?? ""); +} +var builtinComponents = { + table: (props) => /* @__PURE__ */ jsx("div", { class: "table-container", children: /* @__PURE__ */ jsx("table", { ...props }) }), + style: ({ children, ...rest }) => h("style", { ...rest, dangerouslySetInnerHTML: { __html: childrenToString(children) } }), + script: ({ children, ...rest }) => h("script", { ...rest, dangerouslySetInnerHTML: { __html: childrenToString(children) } }) +}; +function htmlToJsx(tree, components) { + return toJsxRuntime(tree, { + Fragment, + jsx, + jsxs, + elementAttributeNameCase: "html", + components: { ...builtinComponents, ...components } + }); +} + +export { capitalize, classNames, endsWith, escapeHTML, getAllSegmentPrefixes, getFileExtension, getFullSlug, getFullSlugFromUrl, htmlToJsx, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, normalizeRelativeURLs, pathToRoot, registerEscapeHandler, removeAllChildren, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix, unescapeHTML }; +//# sourceMappingURL=index.js.map +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 0000000..78d7cbd --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/path.ts","../src/dom.ts","../src/lang.ts","../src/escape.ts","../src/jsx.tsx"],"names":["window","slugAnchor","jsx"],"mappings":"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","file":"index.js","sourcesContent":["import { slug as slugAnchor } from \"github-slugger\";\nimport type { FilePath, FullSlug } from \"@quartz-community/types\";\n\nexport type { FilePath, FullSlug };\n\n/** No '/index' ending, no file extension, can have trailing slash for folders. */\nexport type SimpleSlug = string & { _brand: \"SimpleSlug\" };\n\n/** Starts with './' or '../', used for navigation. */\nexport type RelativeURL = string & { _brand: \"RelativeURL\" };\n\nexport interface TransformOptions {\n strategy: \"absolute\" | \"relative\" | \"shortest\";\n allSlugs: FullSlug[];\n}\n\nexport function isFilePath(s: string): s is FilePath {\n const validStart = !s.startsWith(\".\");\n return validStart && _hasFileExtension(s);\n}\n\nexport function isFullSlug(s: string): s is FullSlug {\n const validStart = !(s.startsWith(\".\") || s.startsWith(\"/\"));\n const validEnding = !s.endsWith(\"/\");\n return validStart && validEnding && !_containsForbiddenCharacters(s);\n}\n\nexport function isSimpleSlug(s: string): s is SimpleSlug {\n const validStart = !(s.startsWith(\".\") || (s.length > 1 && s.startsWith(\"/\")));\n const validEnding = !endsWith(s, \"index\");\n return validStart && !_containsForbiddenCharacters(s) && validEnding && !_hasFileExtension(s);\n}\n\nexport function isRelativeURL(s: string): s is RelativeURL {\n const validStart = /^\\.{1,2}/.test(s);\n const validEnding = !endsWith(s, \"index\");\n return validStart && validEnding && ![\".md\", \".html\"].includes(getFileExtension(s) ?? \"\");\n}\n\nexport function isAbsoluteURL(s: string): boolean {\n try {\n new URL(s);\n } catch {\n return false;\n }\n return true;\n}\n\nexport function simplifySlug(fp: FullSlug | string): SimpleSlug {\n const res = stripSlashes(trimSuffix(fp, \"index\"), true);\n return (res.length === 0 ? \"/\" : res) as SimpleSlug;\n}\n\nexport function getFullSlug(window: Window): FullSlug {\n const res = window.document.body.dataset.slug! as FullSlug;\n return res;\n}\n\nexport function getFullSlugFromUrl(): FullSlug {\n let rawSlug = window.location.pathname;\n if (rawSlug.endsWith(\"/\")) rawSlug = rawSlug.slice(0, -1);\n if (rawSlug.startsWith(\"/\")) rawSlug = rawSlug.slice(1);\n return rawSlug as FullSlug;\n}\n\nexport function slugifyFilePath(fp: FilePath, excludeExt?: boolean): FullSlug {\n fp = stripSlashes(fp) as FilePath;\n const ext = getFileExtension(fp);\n const withoutFileExt = fp.replace(new RegExp(ext + \"$\"), \"\");\n const finalExt = excludeExt || [\".md\", \".html\", undefined].includes(ext) ? \"\" : ext;\n\n let slug = _sluggify(withoutFileExt);\n\n if (endsWith(slug, \"_index\")) {\n slug = slug.replace(/_index$/, \"index\");\n }\n\n return (slug + (finalExt ?? \"\")) as FullSlug;\n}\n\nexport function joinSegments(...args: string[]): string {\n if (args.length === 0) {\n return \"\";\n }\n\n let joined = args\n .filter((segment) => segment !== \"\" && segment !== \"/\")\n .map((segment) => stripSlashes(segment))\n .join(\"/\");\n\n const first = args[0];\n const last = args[args.length - 1];\n\n if (first?.startsWith(\"/\")) {\n joined = \"/\" + joined;\n }\n\n if (last?.endsWith(\"/\")) {\n joined = joined + \"/\";\n }\n\n return joined;\n}\n\nexport function resolvePath(to: string): string {\n if (to.startsWith(\"/\")) return to;\n return \"/\" + to;\n}\n\nexport function endsWith(s: string, suffix: string): boolean {\n return s === suffix || s.endsWith(\"/\" + suffix);\n}\n\nexport function trimSuffix(s: string, suffix: string): string {\n if (endsWith(s, suffix)) {\n s = s.slice(0, -suffix.length);\n }\n return s;\n}\n\nexport function stripSlashes(s: string, onlyStripPrefix?: boolean): string {\n if (s.startsWith(\"/\")) {\n s = s.substring(1);\n }\n\n if (!onlyStripPrefix && s.endsWith(\"/\")) {\n s = s.slice(0, -1);\n }\n\n return s;\n}\n\nexport function getFileExtension(s: string): string | undefined {\n return s.match(/\\.[A-Za-z0-9]+$/)?.[0];\n}\n\nexport function isFolderPath(fplike: string): boolean {\n return (\n fplike.endsWith(\"/\") ||\n endsWith(fplike, \"index\") ||\n endsWith(fplike, \"index.md\") ||\n endsWith(fplike, \"index.html\")\n );\n}\n\nexport function getAllSegmentPrefixes(path: string): string[] {\n const segments = path.split(\"/\");\n const results: string[] = [];\n for (let i = 0; i < segments.length; i++) {\n results.push(segments.slice(0, i + 1).join(\"/\"));\n }\n return results;\n}\n\nexport function pathToRoot(slug: FullSlug): RelativeURL {\n let rootPath = slug\n .split(\"/\")\n .filter((x) => x !== \"\")\n .slice(0, -1)\n .map((_) => \"..\")\n .join(\"/\");\n\n if (rootPath.length === 0) {\n rootPath = \".\";\n }\n\n return rootPath as RelativeURL;\n}\n\nexport function resolveRelative(current: FullSlug, target: FullSlug | SimpleSlug): RelativeURL {\n const res = joinSegments(pathToRoot(current), simplifySlug(target as FullSlug)) as RelativeURL;\n return res;\n}\n\nexport function splitAnchor(link: string): [string, string] {\n const [fp, anchor] = link.split(\"#\", 2);\n if (fp!.endsWith(\".pdf\")) {\n return [fp!, anchor === undefined ? \"\" : `#${anchor}`];\n }\n const slugged = anchor === undefined ? \"\" : \"#\" + slugAnchor(anchor);\n return [fp!, slugged];\n}\n\nexport function slugTag(tag: string): string {\n return tag\n .split(\"/\")\n .map((tagSegment) => _sluggify(tagSegment))\n .join(\"/\");\n}\n\nexport function transformInternalLink(link: string): RelativeURL {\n const [fplike, anchor] = splitAnchor(decodeURI(link));\n\n const folderPath = isFolderPath(fplike);\n const segments = fplike.split(\"/\").filter((x) => x.length > 0);\n const prefix = segments.filter(_isRelativeSegment).join(\"/\");\n const fp = segments.filter((seg) => !_isRelativeSegment(seg) && seg !== \"\").join(\"/\");\n\n const simpleSlug = simplifySlug(slugifyFilePath(fp as FilePath));\n const joined = joinSegments(stripSlashes(prefix), stripSlashes(simpleSlug));\n const trail = folderPath ? \"/\" : \"\";\n const res = (_addRelativeToStart(joined) + trail + anchor) as RelativeURL;\n return res;\n}\n\nexport function transformLink(src: FullSlug, target: string, opts: TransformOptions): RelativeURL {\n const targetSlug = transformInternalLink(target);\n\n if (opts.strategy === \"relative\") {\n return targetSlug as RelativeURL;\n } else {\n const folderTail = isFolderPath(targetSlug) ? \"/\" : \"\";\n const canonicalSlug = stripSlashes(targetSlug.slice(\".\".length));\n const [targetCanonical, targetAnchor] = splitAnchor(canonicalSlug);\n\n if (opts.strategy === \"shortest\") {\n const matchingFileNames = opts.allSlugs.filter((slug) => {\n const parts = slug.split(\"/\");\n const fileName = parts.at(-1);\n return targetCanonical === fileName;\n });\n\n if (matchingFileNames.length === 1) {\n const matchedSlug = matchingFileNames[0]!;\n return (resolveRelative(src, matchedSlug) + targetAnchor) as RelativeURL;\n }\n }\n\n return (joinSegments(pathToRoot(src), canonicalSlug) + folderTail) as RelativeURL;\n }\n}\n\nfunction _sluggify(s: string): string {\n return s\n .split(\"/\")\n .map((segment) =>\n segment\n .replace(/\\s/g, \"-\")\n .replace(/&/g, \"-and-\")\n .replace(/%/g, \"-percent\")\n .replace(/\\?/g, \"\")\n .replace(/#/g, \"\"),\n )\n .join(\"/\")\n .replace(/\\/$/, \"\");\n}\n\nfunction _containsForbiddenCharacters(s: string): boolean {\n return s.includes(\" \") || s.includes(\"#\") || s.includes(\"?\") || s.includes(\"&\");\n}\n\nfunction _hasFileExtension(s: string): boolean {\n return getFileExtension(s) !== undefined;\n}\n\nfunction _isRelativeSegment(s: string): boolean {\n return /^\\.{0,2}$/.test(s);\n}\n\nfunction _addRelativeToStart(s: string): string {\n if (s === \"\") {\n s = \".\";\n }\n\n if (!s.startsWith(\".\")) {\n s = joinSegments(\".\", s);\n }\n\n return s;\n}\n","export function removeAllChildren(el: HTMLElement): void {\n while (el.firstChild) {\n el.removeChild(el.firstChild);\n }\n}\n\nexport function registerEscapeHandler(\n outsideContainer: HTMLElement | null,\n onEscape: () => void,\n): () => void {\n if (!outsideContainer) return () => {};\n\n const onClick = (e: MouseEvent) => {\n if (!outsideContainer.classList.contains(\"active\")) {\n return;\n }\n if (e.target === outsideContainer) {\n e.preventDefault();\n e.stopPropagation();\n onEscape();\n }\n };\n\n const onKeydown = (e: KeyboardEvent) => {\n if (!outsideContainer.classList.contains(\"active\")) {\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n onEscape();\n }\n };\n\n outsideContainer.addEventListener(\"click\", onClick);\n document.addEventListener(\"keydown\", onKeydown);\n\n return () => {\n outsideContainer.removeEventListener(\"click\", onClick);\n document.removeEventListener(\"keydown\", onKeydown);\n };\n}\n\nexport function normalizeRelativeURLs(html: Document, baseUrl: string): void {\n const elements = html.querySelectorAll(\"[src], [href]\");\n for (const el of Array.from(elements)) {\n const attr = el.hasAttribute(\"href\") ? \"href\" : \"src\";\n const val = el.getAttribute(attr);\n if (!val) continue;\n if (\n val.startsWith(\"http://\") ||\n val.startsWith(\"https://\") ||\n val.startsWith(\"mailto:\") ||\n val.startsWith(\"tel:\") ||\n val.startsWith(\"#\") ||\n val.startsWith(\"/\") ||\n val.startsWith(\"data:\")\n ) {\n continue;\n }\n try {\n const normalized = new URL(val, baseUrl).toString();\n el.setAttribute(attr, normalized);\n } catch {\n continue;\n }\n }\n}\n","export function capitalize(s: string): string {\n return s.substring(0, 1).toUpperCase() + s.substring(1);\n}\n\nexport function classNames(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","/**\n * HTML escape utilities for safe string rendering.\n */\n\n/**\n * Escapes HTML special characters in a string to prevent XSS.\n * @param unsafe - The string to escape\n * @returns The escaped string safe for HTML rendering\n *\n * @example\n * escapeHTML('') // '<script>alert("xss")</script>'\n */\nexport function escapeHTML(unsafe: string): string {\n return unsafe\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n}\n\n/**\n * Unescapes HTML entities back to their original characters.\n * @param html - The HTML-escaped string\n * @returns The unescaped string\n *\n * @example\n * unescapeHTML('<div>') // '
'\n */\nexport function unescapeHTML(html: string): string {\n return html\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll(\""\", '\"')\n .replaceAll(\"'\", \"'\");\n}\n","import type { Components, Jsx } from \"hast-util-to-jsx-runtime\";\nimport { toJsxRuntime } from \"hast-util-to-jsx-runtime\";\nimport type { Root, Node } from \"hast\";\nimport { Fragment, jsx, jsxs } from \"preact/jsx-runtime\";\nimport { h } from \"preact\";\n\n/**\n * Extract text content from JSX children.\n *\n * `toJsxRuntime` passes the inner text of `