mirror of
https://github.com/quartz-community/utils.git
synced 2026-07-22 02:50:27 +00:00
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.
This commit is contained in:
parent
61cbfb9807
commit
81189f697c
20 changed files with 682 additions and 2 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -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
|
||||
|
||||
|
|
|
|||
5
dist/dom.d.ts
vendored
Normal file
5
dist/dom.d.ts
vendored
Normal file
|
|
@ -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 };
|
||||
56
dist/dom.js
vendored
Normal file
56
dist/dom.js
vendored
Normal file
|
|
@ -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
|
||||
1
dist/dom.js.map
vendored
Normal file
1
dist/dom.js.map
vendored
Normal file
|
|
@ -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<HTMLElement>(\"[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"]}
|
||||
23
dist/escape.d.ts
vendored
Normal file
23
dist/escape.d.ts
vendored
Normal file
|
|
@ -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>') // '<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>') // '<div>'
|
||||
*/
|
||||
declare function unescapeHTML(html: string): string;
|
||||
|
||||
export { escapeHTML, unescapeHTML };
|
||||
11
dist/escape.js
vendored
Normal file
11
dist/escape.js
vendored
Normal file
|
|
@ -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
|
||||
1
dist/escape.js.map
vendored
Normal file
1
dist/escape.js.map
vendored
Normal file
|
|
@ -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>') // '<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>') // '<div>'\n */\nexport function unescapeHTML(html: string): string {\n return html\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll(\""\", '\"')\n .replaceAll(\"'\", \"'\");\n}\n"]}
|
||||
8
dist/index.d.ts
vendored
Normal file
8
dist/index.d.ts
vendored
Normal file
|
|
@ -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';
|
||||
280
dist/index.js
vendored
Normal file
280
dist/index.js
vendored
Normal file
|
|
@ -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
|
||||
1
dist/index.js.map
vendored
Normal file
1
dist/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
20
dist/jsx.d.ts
vendored
Normal file
20
dist/jsx.d.ts
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { Components } from 'hast-util-to-jsx-runtime';
|
||||
import { Node } from 'hast';
|
||||
|
||||
/**
|
||||
* Convert a HAST tree to Preact JSX, with sensible defaults for Quartz plugins.
|
||||
*
|
||||
* This is the canonical way for pageType body components (and any other code
|
||||
* that renders a HAST tree to JSX) to produce output that is safe for
|
||||
* `preact-render-to-string`. It applies built-in component overrides for
|
||||
* `<table>`, `<style>`, and `<script>` elements, preventing the common
|
||||
* pitfall where inline CSS / JS gets HTML-escaped.
|
||||
*
|
||||
* @param tree The HAST root (or node) to render.
|
||||
* @param components Optional additional component overrides. These are
|
||||
* merged with (and override) the built-in defaults.
|
||||
* @returns A Preact JSX element ready for `render()`.
|
||||
*/
|
||||
declare function htmlToJsx(tree: Node, components?: Partial<Components>): JSX.Element;
|
||||
|
||||
export { htmlToJsx };
|
||||
28
dist/jsx.js
vendored
Normal file
28
dist/jsx.js
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { toJsxRuntime } from 'hast-util-to-jsx-runtime';
|
||||
import { jsxs, jsx, Fragment } from 'preact/jsx-runtime';
|
||||
import { h } from 'preact';
|
||||
|
||||
// src/jsx.tsx
|
||||
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 { htmlToJsx };
|
||||
//# sourceMappingURL=jsx.js.map
|
||||
//# sourceMappingURL=jsx.js.map
|
||||
1
dist/jsx.js.map
vendored
Normal file
1
dist/jsx.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../src/jsx.tsx"],"names":["jsx"],"mappings":";;;;;AAcA,SAAS,iBAAiB,QAAA,EAA2B;AACnD,EAAA,IAAI,OAAO,QAAA,KAAa,QAAA,EAAU,OAAO,QAAA;AACzC,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA,EAAG,OAAO,SAAS,GAAA,CAAI,gBAAgB,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AAC1E,EAAA,OAAO,MAAA,CAAO,YAAY,EAAE,CAAA;AAC9B;AASA,IAAM,iBAAA,GAAgC;AAAA,EACpC,KAAA,EAAO,CAAC,KAAA,qBACNA,GAAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,iBAAA,EACT,QAAA,kBAAAA,GAAAA,CAAC,OAAA,EAAA,EAAO,GAAG,OAAO,CAAA,EACpB,CAAA;AAAA,EAEF,OAAO,CAAC,EAAE,UAAU,GAAG,IAAA,OACrB,CAAA,CAAE,OAAA,EAAS,EAAE,GAAG,IAAA,EAAM,yBAAyB,EAAE,MAAA,EAAQ,iBAAiB,QAAQ,CAAA,IAAK,CAAA;AAAA,EACzF,QAAQ,CAAC,EAAE,UAAU,GAAG,IAAA,OACtB,CAAA,CAAE,QAAA,EAAU,EAAE,GAAG,IAAA,EAAM,yBAAyB,EAAE,MAAA,EAAQ,iBAAiB,QAAQ,CAAA,IAAK;AAC5F,CAAA;AAgBO,SAAS,SAAA,CAAU,MAAY,UAAA,EAAkC;AACtE,EAAA,OAAO,aAAa,IAAA,EAAc;AAAA,IAChC,QAAA;AAAA,IACA,GAAA;AAAA,IACA,IAAA;AAAA,IACA,wBAAA,EAA0B,MAAA;AAAA,IAC1B,UAAA,EAAY,EAAE,GAAG,iBAAA,EAAmB,GAAG,UAAA;AAAW,GACnD,CAAA;AACH","file":"jsx.js","sourcesContent":["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 `<style>` / `<script>` elements as\n * the `children` prop. This helper normalises the various shapes it can take\n * (string, array of strings, or other) into a single string so we can feed it\n * to `dangerouslySetInnerHTML`.\n */\nfunction childrenToString(children: unknown): string {\n if (typeof children === \"string\") return children;\n if (Array.isArray(children)) return children.map(childrenToString).join(\"\");\n return String(children ?? \"\");\n}\n\n/**\n * Default component overrides applied by {@link htmlToJsx}.\n *\n * - **table** – wrapped in a scrollable `<div class=\"table-container\">`\n * - **style** / **script** – rendered with `dangerouslySetInnerHTML` so that\n * special characters (`\"`, `&`, etc.) are *not* HTML-escaped by preact.\n */\nconst builtinComponents: Components = {\n table: (props) => (\n <div class=\"table-container\">\n <table {...props} />\n </div>\n ),\n style: ({ children, ...rest }) =>\n h(\"style\", { ...rest, dangerouslySetInnerHTML: { __html: childrenToString(children) } }),\n script: ({ children, ...rest }) =>\n h(\"script\", { ...rest, dangerouslySetInnerHTML: { __html: childrenToString(children) } }),\n};\n\n/**\n * Convert a HAST tree to Preact JSX, with sensible defaults for Quartz plugins.\n *\n * This is the canonical way for pageType body components (and any other code\n * that renders a HAST tree to JSX) to produce output that is safe for\n * `preact-render-to-string`. It applies built-in component overrides for\n * `<table>`, `<style>`, and `<script>` elements, preventing the common\n * pitfall where inline CSS / JS gets HTML-escaped.\n *\n * @param tree The HAST root (or node) to render.\n * @param components Optional additional component overrides. These are\n * merged with (and override) the built-in defaults.\n * @returns A Preact JSX element ready for `render()`.\n */\nexport function htmlToJsx(tree: Node, components?: Partial<Components>) {\n return toJsxRuntime(tree as Root, {\n Fragment,\n jsx: jsx as Jsx,\n jsxs: jsxs as Jsx,\n elementAttributeNameCase: \"html\",\n components: { ...builtinComponents, ...components },\n });\n}\n"]}
|
||||
4
dist/lang.d.ts
vendored
Normal file
4
dist/lang.d.ts
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
declare function capitalize(s: string): string;
|
||||
declare function classNames(...classes: (string | undefined | null | false)[]): string;
|
||||
|
||||
export { capitalize, classNames };
|
||||
11
dist/lang.js
vendored
Normal file
11
dist/lang.js
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// src/lang.ts
|
||||
function capitalize(s) {
|
||||
return s.substring(0, 1).toUpperCase() + s.substring(1);
|
||||
}
|
||||
function classNames(...classes) {
|
||||
return classes.filter(Boolean).join(" ");
|
||||
}
|
||||
|
||||
export { capitalize, classNames };
|
||||
//# sourceMappingURL=lang.js.map
|
||||
//# sourceMappingURL=lang.js.map
|
||||
1
dist/lang.js.map
vendored
Normal file
1
dist/lang.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../src/lang.ts"],"names":[],"mappings":";AAAO,SAAS,WAAW,CAAA,EAAmB;AAC5C,EAAA,OAAO,CAAA,CAAE,UAAU,CAAA,EAAG,CAAC,EAAE,WAAA,EAAY,GAAI,CAAA,CAAE,SAAA,CAAU,CAAC,CAAA;AACxD;AAEO,SAAS,cAAc,OAAA,EAAwD;AACpF,EAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AACzC","file":"lang.js","sourcesContent":["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"]}
|
||||
40
dist/path.d.ts
vendored
Normal file
40
dist/path.d.ts
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import { FullSlug, FilePath } from '@quartz-community/types';
|
||||
export { FilePath, FullSlug } from '@quartz-community/types';
|
||||
|
||||
/** No '/index' ending, no file extension, can have trailing slash for folders. */
|
||||
type SimpleSlug = string & {
|
||||
_brand: "SimpleSlug";
|
||||
};
|
||||
/** Starts with './' or '../', used for navigation. */
|
||||
type RelativeURL = string & {
|
||||
_brand: "RelativeURL";
|
||||
};
|
||||
interface TransformOptions {
|
||||
strategy: "absolute" | "relative" | "shortest";
|
||||
allSlugs: FullSlug[];
|
||||
}
|
||||
declare function isFilePath(s: string): s is FilePath;
|
||||
declare function isFullSlug(s: string): s is FullSlug;
|
||||
declare function isSimpleSlug(s: string): s is SimpleSlug;
|
||||
declare function isRelativeURL(s: string): s is RelativeURL;
|
||||
declare function isAbsoluteURL(s: string): boolean;
|
||||
declare function simplifySlug(fp: FullSlug | string): SimpleSlug;
|
||||
declare function getFullSlug(window: Window): FullSlug;
|
||||
declare function getFullSlugFromUrl(): FullSlug;
|
||||
declare function slugifyFilePath(fp: FilePath, excludeExt?: boolean): FullSlug;
|
||||
declare function joinSegments(...args: string[]): string;
|
||||
declare function resolvePath(to: string): string;
|
||||
declare function endsWith(s: string, suffix: string): boolean;
|
||||
declare function trimSuffix(s: string, suffix: string): string;
|
||||
declare function stripSlashes(s: string, onlyStripPrefix?: boolean): string;
|
||||
declare function getFileExtension(s: string): string | undefined;
|
||||
declare function isFolderPath(fplike: string): boolean;
|
||||
declare function getAllSegmentPrefixes(path: string): string[];
|
||||
declare function pathToRoot(slug: FullSlug): RelativeURL;
|
||||
declare function resolveRelative(current: FullSlug, target: FullSlug | SimpleSlug): RelativeURL;
|
||||
declare function splitAnchor(link: string): [string, string];
|
||||
declare function slugTag(tag: string): string;
|
||||
declare function transformInternalLink(link: string): RelativeURL;
|
||||
declare function transformLink(src: FullSlug, target: string, opts: TransformOptions): RelativeURL;
|
||||
|
||||
export { type RelativeURL, type SimpleSlug, type TransformOptions, endsWith, getAllSegmentPrefixes, getFileExtension, getFullSlug, getFullSlugFromUrl, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, pathToRoot, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix };
|
||||
189
dist/path.js
vendored
Normal file
189
dist/path.js
vendored
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
import { slug } from 'github-slugger';
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
export { endsWith, getAllSegmentPrefixes, getFileExtension, getFullSlug, getFullSlugFromUrl, isAbsoluteURL, isFilePath, isFolderPath, isFullSlug, isRelativeURL, isSimpleSlug, joinSegments, pathToRoot, resolvePath, resolveRelative, simplifySlug, slugTag, slugifyFilePath, splitAnchor, stripSlashes, transformInternalLink, transformLink, trimSuffix };
|
||||
//# sourceMappingURL=path.js.map
|
||||
//# sourceMappingURL=path.js.map
|
||||
1
dist/path.js.map
vendored
Normal file
1
dist/path.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -58,7 +58,6 @@
|
|||
},
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"prepare": "npm run build",
|
||||
"dev": "tsup --watch",
|
||||
"lint": "eslint . --max-warnings=0",
|
||||
"format": "prettier . --check",
|
||||
|
|
|
|||
Loading…
Reference in a new issue