From 3d5f3338fbbbcc9e40f333c2773fd4d476cb6774 Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Sat, 14 Mar 2026 21:58:38 +0100 Subject: [PATCH] chore: commit dist/ and remove prepare script Pre-built output is now committed to the repository so that Quartz can skip the build step during plugin installation. The prepare script is removed to prevent redundant builds when installing from npm/git. --- .gitignore | 1 - dist/PageList-DncPcZ4-.d.ts | 21 +++ dist/components/index.d.ts | 12 ++ dist/components/index.js | 291 ++++++++++++++++++++++++++++++ dist/components/index.js.map | 1 + dist/index.d.ts | 4 + dist/index.js | 333 +++++++++++++++++++++++++++++++++++ dist/index.js.map | 1 + dist/types-DjXd6K7r.d.ts | 11 ++ dist/types.d.ts | 3 + dist/types.js | 3 + dist/types.js.map | 1 + package-lock.json | 14 +- package.json | 1 - 14 files changed, 689 insertions(+), 8 deletions(-) create mode 100644 dist/PageList-DncPcZ4-.d.ts create mode 100644 dist/components/index.d.ts create mode 100644 dist/components/index.js create mode 100644 dist/components/index.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/types-DjXd6K7r.d.ts create mode 100644 dist/types.d.ts create mode 100644 dist/types.js create mode 100644 dist/types.js.map diff --git a/.gitignore b/.gitignore index 657842b..ef88793 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ node_modules/ .pnp.js # Build output -dist/ build/ *.tsbuildinfo diff --git a/dist/PageList-DncPcZ4-.d.ts b/dist/PageList-DncPcZ4-.d.ts new file mode 100644 index 0000000..98cb085 --- /dev/null +++ b/dist/PageList-DncPcZ4-.d.ts @@ -0,0 +1,21 @@ +import { QuartzComponent } from '@quartz-community/types'; + +interface PageData { + slug?: string; + frontmatter?: { + title?: string; + tags?: string[]; + }; + dates?: { + created: Date; + modified: Date; + published: Date; + }; + [key: string]: unknown; +} +type SortFn = (f1: PageData, f2: PageData) => number; +declare function byDateAndAlphabetical(cfg: unknown): SortFn; +declare function byDateAndAlphabeticalFolderFirst(cfg: unknown): SortFn; +declare const PageList: QuartzComponent; + +export { PageList as P, type SortFn as S, byDateAndAlphabeticalFolderFirst as a, byDateAndAlphabetical as b }; diff --git a/dist/components/index.d.ts b/dist/components/index.d.ts new file mode 100644 index 0000000..5d341b4 --- /dev/null +++ b/dist/components/index.d.ts @@ -0,0 +1,12 @@ +import { QuartzComponent } from '@quartz-community/types'; +import { S as SortFn } from '../PageList-DncPcZ4-.js'; +export { P as PageList, b as byDateAndAlphabetical, a as byDateAndAlphabeticalFolderFirst } from '../PageList-DncPcZ4-.js'; + +interface FolderContentOptions { + showFolderCount: boolean; + showSubfolders: boolean; + sort?: SortFn; +} +declare const _default: (opts?: Partial) => QuartzComponent; + +export { _default as FolderContent, SortFn }; diff --git a/dist/components/index.js b/dist/components/index.js new file mode 100644 index 0000000..8fcf2b4 --- /dev/null +++ b/dist/components/index.js @@ -0,0 +1,291 @@ +import { jsx, jsxs } from 'preact/jsx-runtime'; +import { htmlToJsx } from '@quartz-community/utils/jsx'; + +// src/util/path.ts +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 stripSlashes(s, onlyStripPrefix) { + if (s.startsWith("/")) s = s.substring(1); + if (!onlyStripPrefix && s.endsWith("/")) s = s.slice(0, -1); + return s; +} +function simplifySlug(fp) { + const res = stripSlashes(trimSuffix(fp, "index"), true); + return res.length === 0 ? "/" : res; +} +function trimSuffix(s, suffix) { + if (endsWith(s, suffix)) s = s.slice(0, -suffix.length); + return s; +} +function endsWith(s, suffix) { + return s === suffix || s.endsWith("/" + suffix); +} +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) { + return joinSegments(pathToRoot(current), simplifySlug(target)); +} +function isFolderPath(fplike) { + return fplike.endsWith("/") || endsWith(fplike, "index") || endsWith(fplike, "index.md") || endsWith(fplike, "index.html"); +} +function getDate(cfg, data) { + const type = cfg?.defaultDateType ?? "created"; + return data.dates?.[type]; +} +function byDateAndAlphabetical(cfg) { + return (f1, f2) => { + if (f1.dates && f2.dates) { + return (getDate(cfg, f2)?.getTime() ?? 0) - (getDate(cfg, f1)?.getTime() ?? 0); + } else if (f1.dates && !f2.dates) { + return -1; + } else if (!f1.dates && f2.dates) { + return 1; + } + const f1Title = f1.frontmatter?.title?.toLowerCase() ?? ""; + const f2Title = f2.frontmatter?.title?.toLowerCase() ?? ""; + return f1Title.localeCompare(f2Title); + }; +} +function byDateAndAlphabeticalFolderFirst(cfg) { + return (f1, f2) => { + const f1IsFolder = isFolderPath(f1.slug ?? ""); + const f2IsFolder = isFolderPath(f2.slug ?? ""); + if (f1IsFolder && !f2IsFolder) return -1; + if (!f1IsFolder && f2IsFolder) return 1; + if (f1.dates && f2.dates) { + return (getDate(cfg, f2)?.getTime() ?? 0) - (getDate(cfg, f1)?.getTime() ?? 0); + } else if (f1.dates && !f2.dates) { + return -1; + } else if (!f1.dates && f2.dates) { + return 1; + } + const f1Title = f1.frontmatter?.title?.toLowerCase() ?? ""; + const f2Title = f2.frontmatter?.title?.toLowerCase() ?? ""; + return f1Title.localeCompare(f2Title); + }; +} +function DateDisplay({ date, locale }) { + return /* @__PURE__ */ jsx("time", { dateTime: date.toISOString(), children: date.toLocaleDateString(locale, { + year: "numeric", + month: "short", + day: "2-digit" + }) }); +} +var PageList = ({ + cfg, + fileData, + allFiles, + limit, + sort +}) => { + const sorter = sort ?? byDateAndAlphabeticalFolderFirst(cfg); + let list = [...allFiles].sort(sorter); + if (limit) { + list = list.slice(0, limit); + } + const fileSlug = fileData?.slug; + return /* @__PURE__ */ jsx("ul", { class: "section-ul", children: list.map((page) => { + const title = page.frontmatter?.title; + const tags = page.frontmatter?.tags ?? []; + return /* @__PURE__ */ jsx("li", { class: "section-li", children: /* @__PURE__ */ jsxs("div", { class: "section", children: [ + /* @__PURE__ */ jsx("p", { class: "meta", children: page.dates && /* @__PURE__ */ jsx( + DateDisplay, + { + date: getDate(cfg, page), + locale: cfg?.locale ?? "en-US" + } + ) }), + /* @__PURE__ */ jsx("div", { class: "desc", children: /* @__PURE__ */ jsx("h3", { children: /* @__PURE__ */ jsx( + "a", + { + href: resolveRelative(fileSlug ?? "", page.slug), + class: "internal", + children: title + } + ) }) }), + /* @__PURE__ */ jsx("ul", { class: "tags", children: tags.map((tag) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx( + "a", + { + class: "internal tag-link", + href: resolveRelative( + fileSlug ?? "", + `tags/${tag}` + ), + children: tag + } + ) })) }) + ] }) }); + }) }); +}; +PageList.css = ` +.section h3 { + margin: 0; +} + +.section > .tags { + margin: 0; +} +`; + +// src/i18n/locales/en-US.ts +var en_US_default = { + pages: { + folderContent: { + folder: "Folder", + itemsUnderFolder: ({ count }) => count === 1 ? "1 item under this folder." : `${count} items under this folder.` + } + }, + components: {} +}; + +// src/i18n/index.ts +var locales = { + "en-US": en_US_default +}; +function i18n(locale) { + return locales[locale] || en_US_default; +} + +// src/components/styles/listPage.scss +var listPage_default = "ul.section-ul {\n list-style: none;\n margin-top: 2em;\n padding-left: 0;\n}\n\nli.section-li {\n margin-bottom: 1em;\n}\nli.section-li > .section {\n display: grid;\n grid-template-columns: fit-content(8em) 3fr 1fr;\n}\n@media all and (max-width: 600px) {\n li.section-li > .section > .tags {\n display: none;\n }\n}\nli.section-li > .section > .desc > h3 > a {\n background-color: transparent;\n}\nli.section-li > .section .meta {\n margin: 0 1em 0 0;\n opacity: 0.6;\n}\n\n.popover .section {\n grid-template-columns: fit-content(8em) 1fr !important;\n}\n.popover .section > .tags {\n display: none;\n}"; +var defaultOptions = { + showFolderCount: true, + showSubfolders: true +}; +function concatenateResources(...resources) { + const result = resources.filter((r) => r !== void 0).flat(); + return result.length === 0 ? void 0 : result; +} +function pagesFromTrie(folder, showSubfolders) { + return folder.children.map((node) => { + const nodeData = node.data; + if (nodeData) return nodeData; + if (node.isFolder && showSubfolders) { + return { + slug: node.slug, + dates: mostRecentDatesFromChildren(node.children), + frontmatter: { title: node.displayName, tags: [] } + }; + } + return void 0; + }).filter((page) => page !== void 0); +} +function pagesFromAllFiles(allFiles, folderSlug, showSubfolders) { + const folderPrefix = folderSlug.endsWith("/index") ? folderSlug.slice(0, -"index".length) : folderSlug.endsWith("/") ? folderSlug : folderSlug + "/"; + const directChildren = []; + const subfolderFiles = /* @__PURE__ */ new Map(); + for (const file of allFiles) { + const fileSlug = file.slug; + if (!fileSlug || !fileSlug.startsWith(folderPrefix)) continue; + const relativePath = fileSlug.slice(folderPrefix.length); + if (!relativePath || relativePath === "index") continue; + const segments = relativePath.split("/"); + if (segments.length === 1) { + directChildren.push(file); + } else if (showSubfolders) { + const subfolderName = segments[0]; + if (!subfolderFiles.has(subfolderName)) { + subfolderFiles.set(subfolderName, []); + } + subfolderFiles.get(subfolderName).push(file); + } + } + for (const [subfolderName, files] of subfolderFiles) { + const indexFile = files.find((f) => f.slug === `${folderPrefix}${subfolderName}/index`); + if (indexFile) continue; + directChildren.push({ + slug: `${folderPrefix}${subfolderName}/index`, + dates: mostRecentDatesFromEntries(files), + frontmatter: { title: subfolderName, tags: [] } + }); + } + return directChildren; +} +function mostRecentDatesFromChildren(children) { + let maybeDates; + for (const child of children) { + const childDates = child.data?.dates; + if (childDates) { + if (!maybeDates) { + maybeDates = { ...childDates }; + } else { + if (childDates.created > maybeDates.created) maybeDates.created = childDates.created; + if (childDates.modified > maybeDates.modified) maybeDates.modified = childDates.modified; + if (childDates.published > maybeDates.published) + maybeDates.published = childDates.published; + } + } + } + return maybeDates ?? { created: /* @__PURE__ */ new Date(), modified: /* @__PURE__ */ new Date(), published: /* @__PURE__ */ new Date() }; +} +function mostRecentDatesFromEntries(entries) { + let maybeDates; + for (const entry of entries) { + if (entry.dates) { + if (!maybeDates) { + maybeDates = { ...entry.dates }; + } else { + if (entry.dates.created > maybeDates.created) maybeDates.created = entry.dates.created; + if (entry.dates.modified > maybeDates.modified) maybeDates.modified = entry.dates.modified; + if (entry.dates.published > maybeDates.published) + maybeDates.published = entry.dates.published; + } + } + } + return maybeDates ?? { created: /* @__PURE__ */ new Date(), modified: /* @__PURE__ */ new Date(), published: /* @__PURE__ */ new Date() }; +} +var FolderContent_default = ((opts) => { + const options = { ...defaultOptions, ...opts }; + const FolderContent = (props) => { + const { tree, fileData, allFiles, cfg } = props; + const ctx = props.ctx; + const slug = fileData?.slug; + if (!slug) return null; + const trie = ctx?.trie; + let allPagesInFolder; + if (trie) { + const folder = trie.findNode(slug.split("/")); + if (!folder) return null; + allPagesInFolder = pagesFromTrie(folder, options.showSubfolders); + } else { + allPagesInFolder = pagesFromAllFiles(allFiles ?? [], slug, options.showSubfolders); + } + const cssClasses = fileData?.frontmatter?.cssclasses ?? []; + const classes = cssClasses.join(" "); + const listProps = { + ...props, + sort: options.sort, + allFiles: allPagesInFolder + }; + const hastRoot = tree; + const content = hastRoot.children.length === 0 ? fileData?.description : htmlToJsx(hastRoot); + const pageListContent = PageList(listProps); + return /* @__PURE__ */ jsxs("div", { class: "popover-hint", children: [ + /* @__PURE__ */ jsx("article", { class: classes, children: content }), + /* @__PURE__ */ jsxs("div", { class: "page-listing", children: [ + options.showFolderCount && /* @__PURE__ */ jsx("p", { children: i18n( + cfg?.locale ?? "en-US" + ).pages.folderContent.itemsUnderFolder({ + count: allPagesInFolder.length + }) }), + /* @__PURE__ */ jsx("div", { children: pageListContent }) + ] }) + ] }); + }; + FolderContent.css = concatenateResources(listPage_default, PageList.css); + return FolderContent; +}); + +export { FolderContent_default as FolderContent, PageList, byDateAndAlphabetical, byDateAndAlphabeticalFolderFirst }; +//# sourceMappingURL=index.js.map +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/components/index.js.map b/dist/components/index.js.map new file mode 100644 index 0000000..c113526 --- /dev/null +++ b/dist/components/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/util/path.ts","../../src/components/PageList.tsx","../../src/i18n/locales/en-US.ts","../../src/i18n/index.ts","../../src/components/styles/listPage.scss","../../src/components/FolderContent.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"index.js","sourcesContent":["export type FullSlug = string & { __brand: \"FullSlug\" };\nexport type SimpleSlug = string & { __brand: \"SimpleSlug\" };\nexport type RelativeURL = string & { __brand: \"relative\" };\n\nexport function joinSegments(...args: string[]): string {\n if (args.length === 0) return \"\";\n let joined = args\n .filter((segment) => segment !== \"\" && segment !== \"/\")\n .map((segment) => stripSlashes(segment))\n .join(\"/\");\n const first = args[0];\n const last = args[args.length - 1];\n if (first?.startsWith(\"/\")) joined = \"/\" + joined;\n if (last?.endsWith(\"/\")) joined = joined + \"/\";\n return joined;\n}\n\nexport function stripSlashes(s: string, onlyStripPrefix?: boolean): string {\n if (s.startsWith(\"/\")) s = s.substring(1);\n if (!onlyStripPrefix && s.endsWith(\"/\")) s = s.slice(0, -1);\n return s;\n}\n\nexport function simplifySlug(fp: FullSlug): SimpleSlug {\n const res = stripSlashes(trimSuffix(fp, \"index\"), true);\n return (res.length === 0 ? \"/\" : res) as SimpleSlug;\n}\n\nexport function trimSuffix(s: string, suffix: string): string {\n if (endsWith(s, suffix)) s = s.slice(0, -suffix.length);\n return s;\n}\n\nexport function endsWith(s: string, suffix: string): boolean {\n return s === suffix || s.endsWith(\"/\" + suffix);\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 if (rootPath.length === 0) rootPath = \".\";\n return rootPath as RelativeURL;\n}\n\nexport function resolveRelative(current: FullSlug, target: FullSlug | SimpleSlug): RelativeURL {\n return joinSegments(pathToRoot(current), simplifySlug(target as FullSlug)) as RelativeURL;\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","import type { QuartzComponent, QuartzComponentProps } from \"@quartz-community/types\";\nimport { resolveRelative, isFolderPath } from \"../util/path\";\nimport type { FullSlug } from \"../util/path\";\n\ninterface PageData {\n slug?: string;\n frontmatter?: { title?: string; tags?: string[] };\n dates?: {\n created: Date;\n modified: Date;\n published: Date;\n };\n [key: string]: unknown;\n}\n\nexport type SortFn = (f1: PageData, f2: PageData) => number;\n\nfunction getDate(cfg: unknown, data: PageData): Date | undefined {\n const type = (cfg as { defaultDateType?: string } | undefined)?.defaultDateType ?? \"created\";\n return data.dates?.[type as keyof typeof data.dates] as Date | undefined;\n}\n\nexport function byDateAndAlphabetical(cfg: unknown): SortFn {\n return (f1, f2) => {\n if (f1.dates && f2.dates) {\n return (getDate(cfg, f2)?.getTime() ?? 0) - (getDate(cfg, f1)?.getTime() ?? 0);\n } else if (f1.dates && !f2.dates) {\n return -1;\n } else if (!f1.dates && f2.dates) {\n return 1;\n }\n const f1Title = f1.frontmatter?.title?.toLowerCase() ?? \"\";\n const f2Title = f2.frontmatter?.title?.toLowerCase() ?? \"\";\n return f1Title.localeCompare(f2Title);\n };\n}\n\nexport function byDateAndAlphabeticalFolderFirst(cfg: unknown): SortFn {\n return (f1, f2) => {\n const f1IsFolder = isFolderPath(f1.slug ?? \"\");\n const f2IsFolder = isFolderPath(f2.slug ?? \"\");\n if (f1IsFolder && !f2IsFolder) return -1;\n if (!f1IsFolder && f2IsFolder) return 1;\n\n if (f1.dates && f2.dates) {\n return (getDate(cfg, f2)?.getTime() ?? 0) - (getDate(cfg, f1)?.getTime() ?? 0);\n } else if (f1.dates && !f2.dates) {\n return -1;\n } else if (!f1.dates && f2.dates) {\n return 1;\n }\n const f1Title = f1.frontmatter?.title?.toLowerCase() ?? \"\";\n const f2Title = f2.frontmatter?.title?.toLowerCase() ?? \"\";\n return f1Title.localeCompare(f2Title);\n };\n}\n\ntype DateComponentProps = {\n date: Date;\n locale: string;\n};\n\nfunction DateDisplay({ date, locale }: DateComponentProps) {\n return (\n \n );\n}\n\ntype PageListProps = {\n limit?: number;\n sort?: SortFn;\n} & QuartzComponentProps;\n\nexport const PageList: QuartzComponent = ({\n cfg,\n fileData,\n allFiles,\n limit,\n sort,\n}: PageListProps) => {\n const sorter = sort ?? byDateAndAlphabeticalFolderFirst(cfg);\n let list = [...(allFiles as PageData[])].sort(sorter);\n if (limit) {\n list = list.slice(0, limit);\n }\n\n const fileSlug = (fileData as { slug?: string } | undefined)?.slug as FullSlug | undefined;\n\n return (\n \n );\n};\n\nPageList.css = `\n.section h3 {\n margin: 0;\n}\n\n.section > .tags {\n margin: 0;\n}\n`;\n","export default {\n pages: {\n folderContent: {\n folder: \"Folder\",\n itemsUnderFolder: ({ count }: { count: number }) =>\n count === 1 ? \"1 item under this folder.\" : `${count} items under this folder.`,\n },\n },\n components: {},\n};\n","import enUS from \"./locales/en-US\";\n\nconst locales: Record = {\n \"en-US\": enUS,\n};\n\nexport function i18n(locale: string) {\n return locales[locale] || enUS;\n}\n","ul.section-ul {\n list-style: none;\n margin-top: 2em;\n padding-left: 0;\n}\n\nli.section-li {\n margin-bottom: 1em;\n}\nli.section-li > .section {\n display: grid;\n grid-template-columns: fit-content(8em) 3fr 1fr;\n}\n@media all and (max-width: 600px) {\n li.section-li > .section > .tags {\n display: none;\n }\n}\nli.section-li > .section > .desc > h3 > a {\n background-color: transparent;\n}\nli.section-li > .section .meta {\n margin: 0 1em 0 0;\n opacity: 0.6;\n}\n\n.popover .section {\n grid-template-columns: fit-content(8em) 1fr !important;\n}\n.popover .section > .tags {\n display: none;\n}","import type {\n QuartzComponent,\n QuartzComponentConstructor,\n QuartzComponentProps,\n} from \"@quartz-community/types\";\nimport { PageList } from \"./PageList\";\nimport type { SortFn } from \"./PageList\";\nimport { htmlToJsx } from \"@quartz-community/utils/jsx\";\nimport type { ComponentChildren } from \"preact\";\nimport type { Root } from \"hast\";\nimport { i18n } from \"../i18n\";\nimport style from \"./styles/listPage.scss\";\n\ninterface FolderContentOptions {\n showFolderCount: boolean;\n showSubfolders: boolean;\n sort?: SortFn;\n}\n\nconst defaultOptions: FolderContentOptions = {\n showFolderCount: true,\n showSubfolders: true,\n};\n\ninterface TrieNode {\n isFolder: boolean;\n children: TrieNode[];\n data: unknown;\n slug: string;\n displayName: string;\n findNode(path: string[]): TrieNode | undefined;\n}\n\ntype PageEntry = {\n slug?: string;\n dates?: { created: Date; modified: Date; published: Date };\n frontmatter?: { title?: string; tags?: string[] };\n};\n\nfunction concatenateResources(\n ...resources: (string | string[] | undefined)[]\n): string | string[] | undefined {\n const result = resources.filter((r): r is string | string[] => r !== undefined).flat();\n return result.length === 0 ? undefined : result;\n}\n\nfunction pagesFromTrie(folder: TrieNode, showSubfolders: boolean): PageEntry[] {\n return folder.children\n .map((node) => {\n const nodeData = node.data as PageEntry | null;\n if (nodeData) return nodeData;\n\n if (node.isFolder && showSubfolders) {\n return {\n slug: node.slug,\n dates: mostRecentDatesFromChildren(node.children),\n frontmatter: { title: node.displayName, tags: [] },\n };\n }\n return undefined;\n })\n .filter((page): page is PageEntry => page !== undefined);\n}\n\nfunction pagesFromAllFiles(\n allFiles: unknown[],\n folderSlug: string,\n showSubfolders: boolean,\n): PageEntry[] {\n const folderPrefix = folderSlug.endsWith(\"/index\")\n ? folderSlug.slice(0, -\"index\".length)\n : folderSlug.endsWith(\"/\")\n ? folderSlug\n : folderSlug + \"/\";\n\n const directChildren: PageEntry[] = [];\n const subfolderFiles = new Map();\n\n for (const file of allFiles as PageEntry[]) {\n const fileSlug = file.slug;\n if (!fileSlug || !fileSlug.startsWith(folderPrefix)) continue;\n\n const relativePath = fileSlug.slice(folderPrefix.length);\n if (!relativePath || relativePath === \"index\") continue;\n\n const segments = relativePath.split(\"/\");\n\n if (segments.length === 1) {\n directChildren.push(file);\n } else if (showSubfolders) {\n const subfolderName = segments[0]!;\n if (!subfolderFiles.has(subfolderName)) {\n subfolderFiles.set(subfolderName, []);\n }\n subfolderFiles.get(subfolderName)!.push(file);\n }\n }\n\n for (const [subfolderName, files] of subfolderFiles) {\n const indexFile = files.find((f) => f.slug === `${folderPrefix}${subfolderName}/index`);\n if (indexFile) continue;\n\n directChildren.push({\n slug: `${folderPrefix}${subfolderName}/index`,\n dates: mostRecentDatesFromEntries(files),\n frontmatter: { title: subfolderName, tags: [] },\n });\n }\n\n return directChildren;\n}\n\nfunction mostRecentDatesFromChildren(children: TrieNode[]): PageEntry[\"dates\"] {\n let maybeDates: PageEntry[\"dates\"] | undefined;\n for (const child of children) {\n const childDates = (child.data as { dates?: PageEntry[\"dates\"] } | null)?.dates;\n if (childDates) {\n if (!maybeDates) {\n maybeDates = { ...childDates };\n } else {\n if (childDates.created > maybeDates.created) maybeDates.created = childDates.created;\n if (childDates.modified > maybeDates.modified) maybeDates.modified = childDates.modified;\n if (childDates.published > maybeDates.published)\n maybeDates.published = childDates.published;\n }\n }\n }\n return maybeDates ?? { created: new Date(), modified: new Date(), published: new Date() };\n}\n\nfunction mostRecentDatesFromEntries(entries: PageEntry[]): PageEntry[\"dates\"] {\n let maybeDates: PageEntry[\"dates\"] | undefined;\n for (const entry of entries) {\n if (entry.dates) {\n if (!maybeDates) {\n maybeDates = { ...entry.dates };\n } else {\n if (entry.dates.created > maybeDates.created) maybeDates.created = entry.dates.created;\n if (entry.dates.modified > maybeDates.modified) maybeDates.modified = entry.dates.modified;\n if (entry.dates.published > maybeDates.published)\n maybeDates.published = entry.dates.published;\n }\n }\n }\n return maybeDates ?? { created: new Date(), modified: new Date(), published: new Date() };\n}\n\nexport default ((opts?: Partial) => {\n const options: FolderContentOptions = { ...defaultOptions, ...opts };\n\n const FolderContent: QuartzComponent = (props: QuartzComponentProps) => {\n const { tree, fileData, allFiles, cfg } = props;\n const ctx = props.ctx as { trie?: TrieNode } | undefined;\n const slug = (fileData as { slug?: string } | undefined)?.slug;\n\n if (!slug) return null;\n\n const trie = ctx?.trie;\n let allPagesInFolder: PageEntry[];\n\n if (trie) {\n const folder = trie.findNode(slug.split(\"/\"));\n if (!folder) return null;\n allPagesInFolder = pagesFromTrie(folder, options.showSubfolders);\n } else {\n allPagesInFolder = pagesFromAllFiles(allFiles ?? [], slug, options.showSubfolders);\n }\n\n const cssClasses =\n ((fileData as { frontmatter?: { cssclasses?: string[] } } | undefined)?.frontmatter\n ?.cssclasses as string[] | undefined) ?? [];\n const classes = cssClasses.join(\" \");\n const listProps = {\n ...props,\n sort: options.sort,\n allFiles: allPagesInFolder,\n };\n\n const hastRoot = tree as Root;\n const content =\n hastRoot.children.length === 0\n ? (fileData as { description?: unknown } | undefined)?.description\n : htmlToJsx(hastRoot);\n\n const pageListContent = PageList(listProps) as unknown as ComponentChildren;\n\n return (\n
\n
{content}
\n
\n {options.showFolderCount && (\n

\n {i18n(\n (cfg as { locale?: string } | undefined)?.locale ?? \"en-US\",\n ).pages.folderContent.itemsUnderFolder({\n count: allPagesInFolder.length,\n })}\n

\n )}\n
{pageListContent}
\n
\n
\n );\n };\n\n FolderContent.css = concatenateResources(style, PageList.css);\n return FolderContent;\n}) satisfies QuartzComponentConstructor;\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..d857875 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,4 @@ +export { F as FolderPage, a as FolderPageOptions } from './types-DjXd6K7r.js'; +export { FolderContent } from './components/index.js'; +export { PageGenerator, PageMatcher, QuartzComponent, QuartzComponentConstructor, QuartzComponentProps, QuartzPageTypePlugin, QuartzPageTypePluginInstance, VirtualPage } from '@quartz-community/types'; +import './PageList-DncPcZ4-.js'; diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..1f0eabd --- /dev/null +++ b/dist/index.js @@ -0,0 +1,333 @@ +import { jsxs, jsx } from 'preact/jsx-runtime'; +import { htmlToJsx } from '@quartz-community/utils/jsx'; +import path from 'path'; + +// src/util/path.ts +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 stripSlashes(s, onlyStripPrefix) { + if (s.startsWith("/")) s = s.substring(1); + if (!onlyStripPrefix && s.endsWith("/")) s = s.slice(0, -1); + return s; +} +function simplifySlug(fp) { + const res = stripSlashes(trimSuffix(fp, "index"), true); + return res.length === 0 ? "/" : res; +} +function trimSuffix(s, suffix) { + if (endsWith(s, suffix)) s = s.slice(0, -suffix.length); + return s; +} +function endsWith(s, suffix) { + return s === suffix || s.endsWith("/" + suffix); +} +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) { + return joinSegments(pathToRoot(current), simplifySlug(target)); +} +function isFolderPath(fplike) { + return fplike.endsWith("/") || endsWith(fplike, "index") || endsWith(fplike, "index.md") || endsWith(fplike, "index.html"); +} +function getDate(cfg, data) { + const type = cfg?.defaultDateType ?? "created"; + return data.dates?.[type]; +} +function byDateAndAlphabeticalFolderFirst(cfg) { + return (f1, f2) => { + const f1IsFolder = isFolderPath(f1.slug ?? ""); + const f2IsFolder = isFolderPath(f2.slug ?? ""); + if (f1IsFolder && !f2IsFolder) return -1; + if (!f1IsFolder && f2IsFolder) return 1; + if (f1.dates && f2.dates) { + return (getDate(cfg, f2)?.getTime() ?? 0) - (getDate(cfg, f1)?.getTime() ?? 0); + } else if (f1.dates && !f2.dates) { + return -1; + } else if (!f1.dates && f2.dates) { + return 1; + } + const f1Title = f1.frontmatter?.title?.toLowerCase() ?? ""; + const f2Title = f2.frontmatter?.title?.toLowerCase() ?? ""; + return f1Title.localeCompare(f2Title); + }; +} +function DateDisplay({ date, locale }) { + return /* @__PURE__ */ jsx("time", { dateTime: date.toISOString(), children: date.toLocaleDateString(locale, { + year: "numeric", + month: "short", + day: "2-digit" + }) }); +} +var PageList = ({ + cfg, + fileData, + allFiles, + limit, + sort +}) => { + const sorter = sort ?? byDateAndAlphabeticalFolderFirst(cfg); + let list = [...allFiles].sort(sorter); + if (limit) { + list = list.slice(0, limit); + } + const fileSlug = fileData?.slug; + return /* @__PURE__ */ jsx("ul", { class: "section-ul", children: list.map((page) => { + const title = page.frontmatter?.title; + const tags = page.frontmatter?.tags ?? []; + return /* @__PURE__ */ jsx("li", { class: "section-li", children: /* @__PURE__ */ jsxs("div", { class: "section", children: [ + /* @__PURE__ */ jsx("p", { class: "meta", children: page.dates && /* @__PURE__ */ jsx( + DateDisplay, + { + date: getDate(cfg, page), + locale: cfg?.locale ?? "en-US" + } + ) }), + /* @__PURE__ */ jsx("div", { class: "desc", children: /* @__PURE__ */ jsx("h3", { children: /* @__PURE__ */ jsx( + "a", + { + href: resolveRelative(fileSlug ?? "", page.slug), + class: "internal", + children: title + } + ) }) }), + /* @__PURE__ */ jsx("ul", { class: "tags", children: tags.map((tag) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx( + "a", + { + class: "internal tag-link", + href: resolveRelative( + fileSlug ?? "", + `tags/${tag}` + ), + children: tag + } + ) })) }) + ] }) }); + }) }); +}; +PageList.css = ` +.section h3 { + margin: 0; +} + +.section > .tags { + margin: 0; +} +`; + +// src/i18n/locales/en-US.ts +var en_US_default = { + pages: { + folderContent: { + folder: "Folder", + itemsUnderFolder: ({ count }) => count === 1 ? "1 item under this folder." : `${count} items under this folder.` + } + }, + components: {} +}; + +// src/i18n/index.ts +var locales = { + "en-US": en_US_default +}; +function i18n(locale) { + return locales[locale] || en_US_default; +} + +// src/components/styles/listPage.scss +var listPage_default = "ul.section-ul {\n list-style: none;\n margin-top: 2em;\n padding-left: 0;\n}\n\nli.section-li {\n margin-bottom: 1em;\n}\nli.section-li > .section {\n display: grid;\n grid-template-columns: fit-content(8em) 3fr 1fr;\n}\n@media all and (max-width: 600px) {\n li.section-li > .section > .tags {\n display: none;\n }\n}\nli.section-li > .section > .desc > h3 > a {\n background-color: transparent;\n}\nli.section-li > .section .meta {\n margin: 0 1em 0 0;\n opacity: 0.6;\n}\n\n.popover .section {\n grid-template-columns: fit-content(8em) 1fr !important;\n}\n.popover .section > .tags {\n display: none;\n}"; +var defaultOptions = { + showFolderCount: true, + showSubfolders: true +}; +function concatenateResources(...resources) { + const result = resources.filter((r) => r !== void 0).flat(); + return result.length === 0 ? void 0 : result; +} +function pagesFromTrie(folder, showSubfolders) { + return folder.children.map((node) => { + const nodeData = node.data; + if (nodeData) return nodeData; + if (node.isFolder && showSubfolders) { + return { + slug: node.slug, + dates: mostRecentDatesFromChildren(node.children), + frontmatter: { title: node.displayName, tags: [] } + }; + } + return void 0; + }).filter((page) => page !== void 0); +} +function pagesFromAllFiles(allFiles, folderSlug, showSubfolders) { + const folderPrefix = folderSlug.endsWith("/index") ? folderSlug.slice(0, -"index".length) : folderSlug.endsWith("/") ? folderSlug : folderSlug + "/"; + const directChildren = []; + const subfolderFiles = /* @__PURE__ */ new Map(); + for (const file of allFiles) { + const fileSlug = file.slug; + if (!fileSlug || !fileSlug.startsWith(folderPrefix)) continue; + const relativePath = fileSlug.slice(folderPrefix.length); + if (!relativePath || relativePath === "index") continue; + const segments = relativePath.split("/"); + if (segments.length === 1) { + directChildren.push(file); + } else if (showSubfolders) { + const subfolderName = segments[0]; + if (!subfolderFiles.has(subfolderName)) { + subfolderFiles.set(subfolderName, []); + } + subfolderFiles.get(subfolderName).push(file); + } + } + for (const [subfolderName, files] of subfolderFiles) { + const indexFile = files.find((f) => f.slug === `${folderPrefix}${subfolderName}/index`); + if (indexFile) continue; + directChildren.push({ + slug: `${folderPrefix}${subfolderName}/index`, + dates: mostRecentDatesFromEntries(files), + frontmatter: { title: subfolderName, tags: [] } + }); + } + return directChildren; +} +function mostRecentDatesFromChildren(children) { + let maybeDates; + for (const child of children) { + const childDates = child.data?.dates; + if (childDates) { + if (!maybeDates) { + maybeDates = { ...childDates }; + } else { + if (childDates.created > maybeDates.created) maybeDates.created = childDates.created; + if (childDates.modified > maybeDates.modified) maybeDates.modified = childDates.modified; + if (childDates.published > maybeDates.published) + maybeDates.published = childDates.published; + } + } + } + return maybeDates ?? { created: /* @__PURE__ */ new Date(), modified: /* @__PURE__ */ new Date(), published: /* @__PURE__ */ new Date() }; +} +function mostRecentDatesFromEntries(entries) { + let maybeDates; + for (const entry of entries) { + if (entry.dates) { + if (!maybeDates) { + maybeDates = { ...entry.dates }; + } else { + if (entry.dates.created > maybeDates.created) maybeDates.created = entry.dates.created; + if (entry.dates.modified > maybeDates.modified) maybeDates.modified = entry.dates.modified; + if (entry.dates.published > maybeDates.published) + maybeDates.published = entry.dates.published; + } + } + } + return maybeDates ?? { created: /* @__PURE__ */ new Date(), modified: /* @__PURE__ */ new Date(), published: /* @__PURE__ */ new Date() }; +} +var FolderContent_default = ((opts) => { + const options = { ...defaultOptions, ...opts }; + const FolderContent = (props) => { + const { tree, fileData, allFiles, cfg } = props; + const ctx = props.ctx; + const slug = fileData?.slug; + if (!slug) return null; + const trie = ctx?.trie; + let allPagesInFolder; + if (trie) { + const folder = trie.findNode(slug.split("/")); + if (!folder) return null; + allPagesInFolder = pagesFromTrie(folder, options.showSubfolders); + } else { + allPagesInFolder = pagesFromAllFiles(allFiles ?? [], slug, options.showSubfolders); + } + const cssClasses = fileData?.frontmatter?.cssclasses ?? []; + const classes = cssClasses.join(" "); + const listProps = { + ...props, + sort: options.sort, + allFiles: allPagesInFolder + }; + const hastRoot = tree; + const content = hastRoot.children.length === 0 ? fileData?.description : htmlToJsx(hastRoot); + const pageListContent = PageList(listProps); + return /* @__PURE__ */ jsxs("div", { class: "popover-hint", children: [ + /* @__PURE__ */ jsx("article", { class: classes, children: content }), + /* @__PURE__ */ jsxs("div", { class: "page-listing", children: [ + options.showFolderCount && /* @__PURE__ */ jsx("p", { children: i18n( + cfg?.locale ?? "en-US" + ).pages.folderContent.itemsUnderFolder({ + count: allPagesInFolder.length + }) }), + /* @__PURE__ */ jsx("div", { children: pageListContent }) + ] }) + ] }); + }; + FolderContent.css = concatenateResources(listPage_default, PageList.css); + return FolderContent; +}); +var folderMatcher = ({ slug }) => { + return slug.endsWith("/index"); +}; +function getFolders(slug) { + let folderName = path.dirname(slug ?? ""); + const parentFolderNames = [folderName]; + while (folderName !== ".") { + folderName = path.dirname(folderName ?? ""); + parentFolderNames.push(folderName); + } + return parentFolderNames; +} +var FolderPage = (opts) => { + const body = () => FolderContent_default(opts); + return { + name: "FolderPage", + priority: 10, + match: folderMatcher, + generate({ content, cfg }) { + const allFiles = content.map((c) => c[1].data); + const locale = cfg?.locale ?? "en-US"; + const folders = /* @__PURE__ */ new Set(); + for (const file of allFiles) { + const slug = file?.slug; + if (!slug) continue; + const fileFolders = getFolders(slug).filter((f) => f !== "." && f !== "tags"); + for (const f of fileFolders) { + folders.add(f); + } + } + const foldersWithIndex = /* @__PURE__ */ new Set(); + for (const [, file] of content) { + const slug = file.data?.slug; + if (slug && slug.endsWith("/index")) { + const folder = slug.slice(0, -"/index".length); + foldersWithIndex.add(folder); + } + } + const virtualPages = []; + for (const folder of folders) { + if (foldersWithIndex.has(folder)) continue; + const slug = joinSegments(folder, "index"); + const title = `${i18n(locale).pages.folderContent.folder}: ${folder}`; + virtualPages.push({ + slug, + title, + data: {} + }); + } + return virtualPages; + }, + layout: "folder", + body + }; +}; + +export { FolderContent_default as FolderContent, FolderPage }; +//# 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..1933b8a --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/util/path.ts","../src/components/PageList.tsx","../src/i18n/locales/en-US.ts","../src/i18n/index.ts","../src/components/styles/listPage.scss","../src/components/FolderContent.tsx","../src/pageType.ts"],"names":["jsxs","jsx"],"mappings":"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","file":"index.js","sourcesContent":["export type FullSlug = string & { __brand: \"FullSlug\" };\nexport type SimpleSlug = string & { __brand: \"SimpleSlug\" };\nexport type RelativeURL = string & { __brand: \"relative\" };\n\nexport function joinSegments(...args: string[]): string {\n if (args.length === 0) return \"\";\n let joined = args\n .filter((segment) => segment !== \"\" && segment !== \"/\")\n .map((segment) => stripSlashes(segment))\n .join(\"/\");\n const first = args[0];\n const last = args[args.length - 1];\n if (first?.startsWith(\"/\")) joined = \"/\" + joined;\n if (last?.endsWith(\"/\")) joined = joined + \"/\";\n return joined;\n}\n\nexport function stripSlashes(s: string, onlyStripPrefix?: boolean): string {\n if (s.startsWith(\"/\")) s = s.substring(1);\n if (!onlyStripPrefix && s.endsWith(\"/\")) s = s.slice(0, -1);\n return s;\n}\n\nexport function simplifySlug(fp: FullSlug): SimpleSlug {\n const res = stripSlashes(trimSuffix(fp, \"index\"), true);\n return (res.length === 0 ? \"/\" : res) as SimpleSlug;\n}\n\nexport function trimSuffix(s: string, suffix: string): string {\n if (endsWith(s, suffix)) s = s.slice(0, -suffix.length);\n return s;\n}\n\nexport function endsWith(s: string, suffix: string): boolean {\n return s === suffix || s.endsWith(\"/\" + suffix);\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 if (rootPath.length === 0) rootPath = \".\";\n return rootPath as RelativeURL;\n}\n\nexport function resolveRelative(current: FullSlug, target: FullSlug | SimpleSlug): RelativeURL {\n return joinSegments(pathToRoot(current), simplifySlug(target as FullSlug)) as RelativeURL;\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","import type { QuartzComponent, QuartzComponentProps } from \"@quartz-community/types\";\nimport { resolveRelative, isFolderPath } from \"../util/path\";\nimport type { FullSlug } from \"../util/path\";\n\ninterface PageData {\n slug?: string;\n frontmatter?: { title?: string; tags?: string[] };\n dates?: {\n created: Date;\n modified: Date;\n published: Date;\n };\n [key: string]: unknown;\n}\n\nexport type SortFn = (f1: PageData, f2: PageData) => number;\n\nfunction getDate(cfg: unknown, data: PageData): Date | undefined {\n const type = (cfg as { defaultDateType?: string } | undefined)?.defaultDateType ?? \"created\";\n return data.dates?.[type as keyof typeof data.dates] as Date | undefined;\n}\n\nexport function byDateAndAlphabetical(cfg: unknown): SortFn {\n return (f1, f2) => {\n if (f1.dates && f2.dates) {\n return (getDate(cfg, f2)?.getTime() ?? 0) - (getDate(cfg, f1)?.getTime() ?? 0);\n } else if (f1.dates && !f2.dates) {\n return -1;\n } else if (!f1.dates && f2.dates) {\n return 1;\n }\n const f1Title = f1.frontmatter?.title?.toLowerCase() ?? \"\";\n const f2Title = f2.frontmatter?.title?.toLowerCase() ?? \"\";\n return f1Title.localeCompare(f2Title);\n };\n}\n\nexport function byDateAndAlphabeticalFolderFirst(cfg: unknown): SortFn {\n return (f1, f2) => {\n const f1IsFolder = isFolderPath(f1.slug ?? \"\");\n const f2IsFolder = isFolderPath(f2.slug ?? \"\");\n if (f1IsFolder && !f2IsFolder) return -1;\n if (!f1IsFolder && f2IsFolder) return 1;\n\n if (f1.dates && f2.dates) {\n return (getDate(cfg, f2)?.getTime() ?? 0) - (getDate(cfg, f1)?.getTime() ?? 0);\n } else if (f1.dates && !f2.dates) {\n return -1;\n } else if (!f1.dates && f2.dates) {\n return 1;\n }\n const f1Title = f1.frontmatter?.title?.toLowerCase() ?? \"\";\n const f2Title = f2.frontmatter?.title?.toLowerCase() ?? \"\";\n return f1Title.localeCompare(f2Title);\n };\n}\n\ntype DateComponentProps = {\n date: Date;\n locale: string;\n};\n\nfunction DateDisplay({ date, locale }: DateComponentProps) {\n return (\n \n );\n}\n\ntype PageListProps = {\n limit?: number;\n sort?: SortFn;\n} & QuartzComponentProps;\n\nexport const PageList: QuartzComponent = ({\n cfg,\n fileData,\n allFiles,\n limit,\n sort,\n}: PageListProps) => {\n const sorter = sort ?? byDateAndAlphabeticalFolderFirst(cfg);\n let list = [...(allFiles as PageData[])].sort(sorter);\n if (limit) {\n list = list.slice(0, limit);\n }\n\n const fileSlug = (fileData as { slug?: string } | undefined)?.slug as FullSlug | undefined;\n\n return (\n
    \n {list.map((page) => {\n const title = page.frontmatter?.title;\n const tags = page.frontmatter?.tags ?? [];\n\n return (\n
  • \n
    \n

    \n {page.dates && (\n \n )}\n

    \n
    \n

    \n \n {title}\n \n

    \n
    \n
      \n {tags.map((tag) => (\n
    • \n \n {tag}\n \n
    • \n ))}\n
    \n
    \n
  • \n );\n })}\n
\n );\n};\n\nPageList.css = `\n.section h3 {\n margin: 0;\n}\n\n.section > .tags {\n margin: 0;\n}\n`;\n","export default {\n pages: {\n folderContent: {\n folder: \"Folder\",\n itemsUnderFolder: ({ count }: { count: number }) =>\n count === 1 ? \"1 item under this folder.\" : `${count} items under this folder.`,\n },\n },\n components: {},\n};\n","import enUS from \"./locales/en-US\";\n\nconst locales: Record = {\n \"en-US\": enUS,\n};\n\nexport function i18n(locale: string) {\n return locales[locale] || enUS;\n}\n","ul.section-ul {\n list-style: none;\n margin-top: 2em;\n padding-left: 0;\n}\n\nli.section-li {\n margin-bottom: 1em;\n}\nli.section-li > .section {\n display: grid;\n grid-template-columns: fit-content(8em) 3fr 1fr;\n}\n@media all and (max-width: 600px) {\n li.section-li > .section > .tags {\n display: none;\n }\n}\nli.section-li > .section > .desc > h3 > a {\n background-color: transparent;\n}\nli.section-li > .section .meta {\n margin: 0 1em 0 0;\n opacity: 0.6;\n}\n\n.popover .section {\n grid-template-columns: fit-content(8em) 1fr !important;\n}\n.popover .section > .tags {\n display: none;\n}","import type {\n QuartzComponent,\n QuartzComponentConstructor,\n QuartzComponentProps,\n} from \"@quartz-community/types\";\nimport { PageList } from \"./PageList\";\nimport type { SortFn } from \"./PageList\";\nimport { htmlToJsx } from \"@quartz-community/utils/jsx\";\nimport type { ComponentChildren } from \"preact\";\nimport type { Root } from \"hast\";\nimport { i18n } from \"../i18n\";\nimport style from \"./styles/listPage.scss\";\n\ninterface FolderContentOptions {\n showFolderCount: boolean;\n showSubfolders: boolean;\n sort?: SortFn;\n}\n\nconst defaultOptions: FolderContentOptions = {\n showFolderCount: true,\n showSubfolders: true,\n};\n\ninterface TrieNode {\n isFolder: boolean;\n children: TrieNode[];\n data: unknown;\n slug: string;\n displayName: string;\n findNode(path: string[]): TrieNode | undefined;\n}\n\ntype PageEntry = {\n slug?: string;\n dates?: { created: Date; modified: Date; published: Date };\n frontmatter?: { title?: string; tags?: string[] };\n};\n\nfunction concatenateResources(\n ...resources: (string | string[] | undefined)[]\n): string | string[] | undefined {\n const result = resources.filter((r): r is string | string[] => r !== undefined).flat();\n return result.length === 0 ? undefined : result;\n}\n\nfunction pagesFromTrie(folder: TrieNode, showSubfolders: boolean): PageEntry[] {\n return folder.children\n .map((node) => {\n const nodeData = node.data as PageEntry | null;\n if (nodeData) return nodeData;\n\n if (node.isFolder && showSubfolders) {\n return {\n slug: node.slug,\n dates: mostRecentDatesFromChildren(node.children),\n frontmatter: { title: node.displayName, tags: [] },\n };\n }\n return undefined;\n })\n .filter((page): page is PageEntry => page !== undefined);\n}\n\nfunction pagesFromAllFiles(\n allFiles: unknown[],\n folderSlug: string,\n showSubfolders: boolean,\n): PageEntry[] {\n const folderPrefix = folderSlug.endsWith(\"/index\")\n ? folderSlug.slice(0, -\"index\".length)\n : folderSlug.endsWith(\"/\")\n ? folderSlug\n : folderSlug + \"/\";\n\n const directChildren: PageEntry[] = [];\n const subfolderFiles = new Map();\n\n for (const file of allFiles as PageEntry[]) {\n const fileSlug = file.slug;\n if (!fileSlug || !fileSlug.startsWith(folderPrefix)) continue;\n\n const relativePath = fileSlug.slice(folderPrefix.length);\n if (!relativePath || relativePath === \"index\") continue;\n\n const segments = relativePath.split(\"/\");\n\n if (segments.length === 1) {\n directChildren.push(file);\n } else if (showSubfolders) {\n const subfolderName = segments[0]!;\n if (!subfolderFiles.has(subfolderName)) {\n subfolderFiles.set(subfolderName, []);\n }\n subfolderFiles.get(subfolderName)!.push(file);\n }\n }\n\n for (const [subfolderName, files] of subfolderFiles) {\n const indexFile = files.find((f) => f.slug === `${folderPrefix}${subfolderName}/index`);\n if (indexFile) continue;\n\n directChildren.push({\n slug: `${folderPrefix}${subfolderName}/index`,\n dates: mostRecentDatesFromEntries(files),\n frontmatter: { title: subfolderName, tags: [] },\n });\n }\n\n return directChildren;\n}\n\nfunction mostRecentDatesFromChildren(children: TrieNode[]): PageEntry[\"dates\"] {\n let maybeDates: PageEntry[\"dates\"] | undefined;\n for (const child of children) {\n const childDates = (child.data as { dates?: PageEntry[\"dates\"] } | null)?.dates;\n if (childDates) {\n if (!maybeDates) {\n maybeDates = { ...childDates };\n } else {\n if (childDates.created > maybeDates.created) maybeDates.created = childDates.created;\n if (childDates.modified > maybeDates.modified) maybeDates.modified = childDates.modified;\n if (childDates.published > maybeDates.published)\n maybeDates.published = childDates.published;\n }\n }\n }\n return maybeDates ?? { created: new Date(), modified: new Date(), published: new Date() };\n}\n\nfunction mostRecentDatesFromEntries(entries: PageEntry[]): PageEntry[\"dates\"] {\n let maybeDates: PageEntry[\"dates\"] | undefined;\n for (const entry of entries) {\n if (entry.dates) {\n if (!maybeDates) {\n maybeDates = { ...entry.dates };\n } else {\n if (entry.dates.created > maybeDates.created) maybeDates.created = entry.dates.created;\n if (entry.dates.modified > maybeDates.modified) maybeDates.modified = entry.dates.modified;\n if (entry.dates.published > maybeDates.published)\n maybeDates.published = entry.dates.published;\n }\n }\n }\n return maybeDates ?? { created: new Date(), modified: new Date(), published: new Date() };\n}\n\nexport default ((opts?: Partial) => {\n const options: FolderContentOptions = { ...defaultOptions, ...opts };\n\n const FolderContent: QuartzComponent = (props: QuartzComponentProps) => {\n const { tree, fileData, allFiles, cfg } = props;\n const ctx = props.ctx as { trie?: TrieNode } | undefined;\n const slug = (fileData as { slug?: string } | undefined)?.slug;\n\n if (!slug) return null;\n\n const trie = ctx?.trie;\n let allPagesInFolder: PageEntry[];\n\n if (trie) {\n const folder = trie.findNode(slug.split(\"/\"));\n if (!folder) return null;\n allPagesInFolder = pagesFromTrie(folder, options.showSubfolders);\n } else {\n allPagesInFolder = pagesFromAllFiles(allFiles ?? [], slug, options.showSubfolders);\n }\n\n const cssClasses =\n ((fileData as { frontmatter?: { cssclasses?: string[] } } | undefined)?.frontmatter\n ?.cssclasses as string[] | undefined) ?? [];\n const classes = cssClasses.join(\" \");\n const listProps = {\n ...props,\n sort: options.sort,\n allFiles: allPagesInFolder,\n };\n\n const hastRoot = tree as Root;\n const content =\n hastRoot.children.length === 0\n ? (fileData as { description?: unknown } | undefined)?.description\n : htmlToJsx(hastRoot);\n\n const pageListContent = PageList(listProps) as unknown as ComponentChildren;\n\n return (\n
\n
{content}
\n
\n {options.showFolderCount && (\n

\n {i18n(\n (cfg as { locale?: string } | undefined)?.locale ?? \"en-US\",\n ).pages.folderContent.itemsUnderFolder({\n count: allPagesInFolder.length,\n })}\n

\n )}\n
{pageListContent}
\n
\n
\n );\n };\n\n FolderContent.css = concatenateResources(style, PageList.css);\n return FolderContent;\n}) satisfies QuartzComponentConstructor;\n","import type {\n QuartzPageTypePlugin,\n QuartzComponentConstructor,\n PageMatcher,\n FullSlug,\n VirtualPage,\n} from \"@quartz-community/types\";\nimport FolderContentComponent from \"./components/FolderContent\";\nimport { i18n } from \"./i18n\";\nimport { joinSegments } from \"./util/path\";\nimport type { SortFn } from \"./components/PageList\";\nimport path from \"path\";\n\nexport interface FolderPageOptions {\n showFolderCount?: boolean;\n showSubfolders?: boolean;\n sort?: SortFn;\n}\n\nconst folderMatcher: PageMatcher = ({ slug }) => {\n return slug.endsWith(\"/index\");\n};\n\nfunction getFolders(slug: string): string[] {\n let folderName = path.dirname(slug ?? \"\");\n const parentFolderNames = [folderName];\n while (folderName !== \".\") {\n folderName = path.dirname(folderName ?? \"\");\n parentFolderNames.push(folderName);\n }\n return parentFolderNames;\n}\n\nexport const FolderPage: QuartzPageTypePlugin = (opts) => {\n const body: QuartzComponentConstructor = () => FolderContentComponent(opts);\n\n return {\n name: \"FolderPage\",\n priority: 10,\n match: folderMatcher,\n generate({ content, cfg }) {\n const allFiles = content.map((c) => c[1].data);\n const locale = (cfg as { locale?: string } | undefined)?.locale ?? \"en-US\";\n\n const folders = new Set();\n for (const file of allFiles) {\n const slug = (file as { slug?: string } | undefined)?.slug;\n if (!slug) continue;\n const fileFolders = getFolders(slug).filter((f) => f !== \".\" && f !== \"tags\");\n for (const f of fileFolders) {\n folders.add(f);\n }\n }\n\n const foldersWithIndex = new Set();\n for (const [, file] of content) {\n const slug = (file.data as { slug?: string } | undefined)?.slug;\n if (slug && slug.endsWith(\"/index\")) {\n const folder = slug.slice(0, -\"/index\".length);\n foldersWithIndex.add(folder);\n }\n }\n\n const virtualPages: VirtualPage[] = [];\n for (const folder of folders) {\n if (foldersWithIndex.has(folder)) continue;\n\n const slug = joinSegments(folder, \"index\") as unknown as FullSlug;\n const title = `${i18n(locale).pages.folderContent.folder}: ${folder}`;\n\n virtualPages.push({\n slug,\n title,\n data: {},\n });\n }\n\n return virtualPages;\n },\n layout: \"folder\",\n body,\n };\n};\n"]} \ No newline at end of file diff --git a/dist/types-DjXd6K7r.d.ts b/dist/types-DjXd6K7r.d.ts new file mode 100644 index 0000000..5787259 --- /dev/null +++ b/dist/types-DjXd6K7r.d.ts @@ -0,0 +1,11 @@ +import { QuartzPageTypePlugin } from '@quartz-community/types'; +import { S as SortFn } from './PageList-DncPcZ4-.js'; + +interface FolderPageOptions { + showFolderCount?: boolean; + showSubfolders?: boolean; + sort?: SortFn; +} +declare const FolderPage: QuartzPageTypePlugin; + +export { FolderPage as F, type FolderPageOptions as a }; diff --git a/dist/types.d.ts b/dist/types.d.ts new file mode 100644 index 0000000..be33444 --- /dev/null +++ b/dist/types.d.ts @@ -0,0 +1,3 @@ +export { BuildCtx, PageGenerator, PageMatcher, ProcessedContent, QuartzPageTypePlugin, QuartzPageTypePluginInstance, QuartzPluginData, StaticResources, VirtualPage } from '@quartz-community/types'; +export { a as FolderPageOptions } from './types-DjXd6K7r.js'; +export { S as SortFn } from './PageList-DncPcZ4-.js'; diff --git a/dist/types.js b/dist/types.js new file mode 100644 index 0000000..6bd95cc --- /dev/null +++ b/dist/types.js @@ -0,0 +1,3 @@ + +//# sourceMappingURL=types.js.map +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/dist/types.js.map b/dist/types.js.map new file mode 100644 index 0000000..efc9e48 --- /dev/null +++ b/dist/types.js.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"names":[],"mappings":"","file":"types.js"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 56e88ae..be8ab11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,10 +10,7 @@ "license": "MIT", "dependencies": { "@quartz-community/types": "github:quartz-community/types", - "@quartz-community/utils": "github:quartz-community/utils", - "tsup": "^8.5.0", - "typescript": "^5.9.3", - "vfile": "^6.0.3" + "@quartz-community/utils": "github:quartz-community/utils" }, "devDependencies": { "@types/hast": "^3.0.4", @@ -26,6 +23,8 @@ "preact": "^10.28.2", "prettier": "^3.6.2", "sass": "^1.97.3", + "tsup": "^8.5.0", + "typescript": "^5.9.3", "vitest": "^2.1.9" }, "engines": { @@ -34,7 +33,8 @@ }, "peerDependencies": { "@jackyzha0/quartz": "^4.5.2", - "preact": "^10.0.0" + "preact": "^10.0.0", + "vfile": "^6.0.3" }, "peerDependenciesMeta": { "@jackyzha0/quartz": { @@ -42,6 +42,9 @@ }, "preact": { "optional": false + }, + "vfile": { + "optional": true } } }, @@ -4046,7 +4049,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", diff --git a/package.json b/package.json index eeb0047..07b3bb3 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "sideEffects": false, "scripts": { "build": "tsup", - "prepare": "npm run build", "dev": "tsup --watch", "lint": "eslint . --max-warnings=0", "format": "prettier . --check",