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/components/index.d.ts b/dist/components/index.d.ts new file mode 100644 index 0000000..5f4a114 --- /dev/null +++ b/dist/components/index.d.ts @@ -0,0 +1,2 @@ +export { RecentNotes, RecentNotesOptions } from '../index.js'; +import '@quartz-community/types'; diff --git a/dist/components/index.js b/dist/components/index.js new file mode 100644 index 0000000..8e38845 --- /dev/null +++ b/dist/components/index.js @@ -0,0 +1,117 @@ +import { joinSegments, simplifySlug as simplifySlug$1 } from '@quartz-community/utils'; +import { jsxs, jsx } from 'preact/jsx-runtime'; + +// src/util/lang.ts +function classNames(...classes) { + return classes.filter(Boolean).join(" "); +} + +// src/i18n/locales/en-US.ts +var en_US_default = { + components: { + recentNotes: { + title: "Recent Notes", + seeRemainingMore: ({ remaining }) => `See ${remaining} more \u2192` + } + } +}; + +// src/i18n/index.ts +var locales = { + "en-US": en_US_default +}; +function i18n(locale) { + return locales[locale] || en_US_default; +} +function simplifySlug(fp) { + return simplifySlug$1(fp); +} +function resolveRelative(current, target) { + const simplified = simplifySlug(target); + const rootPath = pathToRoot(current); + return joinSegments(rootPath, simplified); +} +function pathToRoot(slug) { + let rootPath = slug.split("/").filter((x) => x !== "").slice(0, -1).map((_) => "..").join("/"); + if (rootPath.length === 0) { + rootPath = "."; + } + return rootPath; +} + +// src/util/date.ts +function getDate(cfg, data) { + if (!cfg.defaultDateType) { + throw new Error( + "Field 'defaultDateType' was not set in the configuration object of quartz.config.ts." + ); + } + return data.dates?.[cfg.defaultDateType]; +} +function formatDate(d, locale = "en-US") { + return d.toLocaleDateString(locale, { + year: "numeric", + month: "short", + day: "2-digit" + }); +} + +// src/util/sort.ts +function byDateAndAlphabetical(cfg) { + return (f1, f2) => { + if (f1.dates && f2.dates) { + return getDate(cfg, f2).getTime() - getDate(cfg, f1).getTime(); + } 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); + }; +} + +// src/components/styles/recentNotes.scss +var recentNotes_default = ".recent-notes > h3 {\n margin: 0.5rem 0 0 0;\n font-size: 1rem;\n}\n.recent-notes > ul.recent-ul {\n list-style: none;\n margin-top: 1rem;\n padding-left: 0;\n}\n.recent-notes > ul.recent-ul > li {\n margin: 1rem 0;\n}\n.recent-notes > ul.recent-ul > li .section > .desc > h3 > a {\n background-color: transparent;\n}\n.recent-notes > ul.recent-ul > li .section > .meta {\n margin: 0 0 0.5rem 0;\n opacity: 0.6;\n}"; +var defaultOptions = (cfg) => ({ + limit: 3, + linkToMore: false, + showTags: true, + filter: () => true, + sort: byDateAndAlphabetical(cfg) +}); +var RecentNotes_default = ((userOpts) => { + const RecentNotes = ({ + allFiles, + fileData, + displayClass, + cfg + }) => { + const globalCfg = cfg; + const opts = { ...defaultOptions(globalCfg), ...userOpts }; + const pages = allFiles.filter(opts.filter).sort(opts.sort); + const remaining = Math.max(0, pages.length - opts.limit); + const slug = fileData.slug; + const locale = cfg.locale ?? "en-US"; + return /* @__PURE__ */ jsxs("div", { class: classNames(displayClass, "recent-notes"), children: [ + /* @__PURE__ */ jsx("h3", { children: opts.title ?? i18n(locale).components.recentNotes.title }), + /* @__PURE__ */ jsx("ul", { class: "recent-ul", children: pages.slice(0, opts.limit).map((page) => { + const title = page.frontmatter?.title ?? "Untitled"; + const tags = page.frontmatter?.tags ?? []; + return /* @__PURE__ */ jsx("li", { class: "recent-li", children: /* @__PURE__ */ jsxs("div", { class: "section", children: [ + /* @__PURE__ */ jsx("div", { class: "desc", children: /* @__PURE__ */ jsx("h3", { children: /* @__PURE__ */ jsx("a", { href: resolveRelative(slug, page.slug), class: "internal", children: title }) }) }), + page.dates && /* @__PURE__ */ jsx("p", { class: "meta", children: /* @__PURE__ */ jsx("time", { datetime: getDate(globalCfg, page)?.toISOString(), children: formatDate(getDate(globalCfg, page), locale) }) }), + opts.showTags && /* @__PURE__ */ jsx("ul", { class: "tags", children: tags.map((tag) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { class: "internal tag-link", href: resolveRelative(slug, `tags/${tag}`), children: tag }) })) }) + ] }) }); + }) }), + opts.linkToMore && remaining > 0 && /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("a", { href: resolveRelative(slug, opts.linkToMore), children: i18n(locale).components.recentNotes.seeRemainingMore({ remaining }) }) }) + ] }); + }; + RecentNotes.css = recentNotes_default; + return RecentNotes; +}); + +export { RecentNotes_default as RecentNotes }; +//# 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..2d7587c --- /dev/null +++ b/dist/components/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/util/lang.ts","../../src/i18n/locales/en-US.ts","../../src/i18n/index.ts","../../src/util/path.ts","../../src/util/date.ts","../../src/util/sort.ts","../../src/components/styles/recentNotes.scss","../../src/components/RecentNotes.tsx"],"names":["utilSimplifySlug"],"mappings":"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","file":"index.js","sourcesContent":["export function classNames(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","export default {\n components: {\n recentNotes: {\n title: \"Recent Notes\",\n seeRemainingMore: ({ remaining }: { remaining: number }) => `See ${remaining} more →`,\n },\n },\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","import { simplifySlug as utilSimplifySlug, joinSegments } from \"@quartz-community/utils\";\n\nexport function simplifySlug(fp: string): string {\n return utilSimplifySlug(fp);\n}\n\nexport function resolveRelative(current: string, target: string): string {\n const simplified = simplifySlug(target);\n const rootPath = pathToRoot(current);\n return joinSegments(rootPath, simplified);\n}\n\nfunction pathToRoot(slug: string): string {\n let rootPath = slug\n .split(\"/\")\n .filter((x) => x !== \"\")\n .slice(0, -1)\n .map((_) => \"..\")\n .join(\"/\");\n\n if (rootPath.length === 0) {\n rootPath = \".\";\n }\n\n return rootPath;\n}\n","interface GlobalConfiguration {\n defaultDateType: string;\n [key: string]: unknown;\n}\n\ninterface QuartzPluginData {\n dates?: Record;\n [key: string]: unknown;\n}\n\nexport function getDate(cfg: GlobalConfiguration, data: QuartzPluginData): Date | undefined {\n if (!cfg.defaultDateType) {\n throw new Error(\n \"Field 'defaultDateType' was not set in the configuration object of quartz.config.ts.\",\n );\n }\n return data.dates?.[cfg.defaultDateType];\n}\n\nexport function formatDate(d: Date, locale: string = \"en-US\"): string {\n return d.toLocaleDateString(locale, {\n year: \"numeric\",\n month: \"short\",\n day: \"2-digit\",\n });\n}\n","import { getDate } from \"./date\";\n\ninterface GlobalConfiguration {\n defaultDateType: string;\n [key: string]: unknown;\n}\n\ninterface QuartzPluginData {\n dates?: Record;\n frontmatter?: {\n title?: string;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\nexport type SortFn = (f1: QuartzPluginData, f2: QuartzPluginData) => number;\n\nexport function byDateAndAlphabetical(cfg: GlobalConfiguration): SortFn {\n return (f1, f2) => {\n if (f1.dates && f2.dates) {\n return getDate(cfg, f2)!.getTime() - getDate(cfg, f1)!.getTime();\n } else if (f1.dates && !f2.dates) {\n return -1;\n } else if (!f1.dates && f2.dates) {\n return 1;\n }\n\n const f1Title = f1.frontmatter?.title?.toLowerCase() ?? \"\";\n const f2Title = f2.frontmatter?.title?.toLowerCase() ?? \"\";\n return f1Title.localeCompare(f2Title);\n };\n}\n",".recent-notes > h3 {\n margin: 0.5rem 0 0 0;\n font-size: 1rem;\n}\n.recent-notes > ul.recent-ul {\n list-style: none;\n margin-top: 1rem;\n padding-left: 0;\n}\n.recent-notes > ul.recent-ul > li {\n margin: 1rem 0;\n}\n.recent-notes > ul.recent-ul > li .section > .desc > h3 > a {\n background-color: transparent;\n}\n.recent-notes > ul.recent-ul > li .section > .meta {\n margin: 0 0 0.5rem 0;\n opacity: 0.6;\n}","import type { QuartzComponent, QuartzComponentProps } from \"@quartz-community/types\";\nimport { classNames } from \"../util/lang\";\nimport { i18n } from \"../i18n\";\nimport { resolveRelative } from \"../util/path\";\nimport { getDate, formatDate } from \"../util/date\";\nimport { byDateAndAlphabetical } from \"../util/sort\";\nimport style from \"./styles/recentNotes.scss\";\n\ntype QuartzComponentConstructor = (\n opts: Options,\n) => QuartzComponent;\n\ninterface QuartzPluginData {\n slug?: string;\n filePath?: string;\n dates?: Record;\n frontmatter?: {\n title?: string;\n tags?: string[];\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\ninterface GlobalConfiguration {\n locale: string;\n defaultDateType: string;\n [key: string]: unknown;\n}\n\nexport interface RecentNotesOptions {\n title?: string;\n limit: number;\n linkToMore: string | false;\n showTags: boolean;\n filter: (f: QuartzPluginData) => boolean;\n sort: (f1: QuartzPluginData, f2: QuartzPluginData) => number;\n}\n\nconst defaultOptions = (cfg: GlobalConfiguration): RecentNotesOptions => ({\n limit: 3,\n linkToMore: false,\n showTags: true,\n filter: () => true,\n sort: byDateAndAlphabetical(cfg),\n});\n\nexport default ((userOpts?: Partial) => {\n const RecentNotes: QuartzComponent = ({\n allFiles,\n fileData,\n displayClass,\n cfg,\n }: QuartzComponentProps & { displayClass?: string }) => {\n const globalCfg = cfg as unknown as GlobalConfiguration;\n const opts = { ...defaultOptions(globalCfg), ...userOpts };\n const pages = (allFiles as QuartzPluginData[]).filter(opts.filter).sort(opts.sort);\n const remaining = Math.max(0, pages.length - opts.limit);\n const slug = fileData.slug as string | undefined;\n const locale = cfg.locale ?? \"en-US\";\n return (\n
\n

{opts.title ?? i18n(locale).components.recentNotes.title}

\n
    \n {pages.slice(0, opts.limit).map((page) => {\n const title = page.frontmatter?.title ?? \"Untitled\";\n const tags = page.frontmatter?.tags ?? [];\n\n return (\n
  • \n
    \n
    \n

    \n \n {title}\n \n

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

    \n \n

    \n )}\n {opts.showTags && (\n \n )}\n
    \n
  • \n );\n })}\n
\n {opts.linkToMore && remaining > 0 && (\n

\n \n {i18n(locale).components.recentNotes.seeRemainingMore({ remaining })}\n \n

\n )}\n
\n );\n };\n\n RecentNotes.css = style;\n return RecentNotes;\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..5703c96 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,25 @@ +import { QuartzComponent } from '@quartz-community/types'; +export { QuartzComponent, QuartzComponentProps, StringResource } from '@quartz-community/types'; + +interface QuartzPluginData { + slug?: string; + filePath?: string; + dates?: Record; + frontmatter?: { + title?: string; + tags?: string[]; + [key: string]: unknown; + }; + [key: string]: unknown; +} +interface RecentNotesOptions { + title?: string; + limit: number; + linkToMore: string | false; + showTags: boolean; + filter: (f: QuartzPluginData) => boolean; + sort: (f1: QuartzPluginData, f2: QuartzPluginData) => number; +} +declare const _default: (userOpts?: Partial) => QuartzComponent; + +export { _default as RecentNotes, type RecentNotesOptions }; diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..8e38845 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,117 @@ +import { joinSegments, simplifySlug as simplifySlug$1 } from '@quartz-community/utils'; +import { jsxs, jsx } from 'preact/jsx-runtime'; + +// src/util/lang.ts +function classNames(...classes) { + return classes.filter(Boolean).join(" "); +} + +// src/i18n/locales/en-US.ts +var en_US_default = { + components: { + recentNotes: { + title: "Recent Notes", + seeRemainingMore: ({ remaining }) => `See ${remaining} more \u2192` + } + } +}; + +// src/i18n/index.ts +var locales = { + "en-US": en_US_default +}; +function i18n(locale) { + return locales[locale] || en_US_default; +} +function simplifySlug(fp) { + return simplifySlug$1(fp); +} +function resolveRelative(current, target) { + const simplified = simplifySlug(target); + const rootPath = pathToRoot(current); + return joinSegments(rootPath, simplified); +} +function pathToRoot(slug) { + let rootPath = slug.split("/").filter((x) => x !== "").slice(0, -1).map((_) => "..").join("/"); + if (rootPath.length === 0) { + rootPath = "."; + } + return rootPath; +} + +// src/util/date.ts +function getDate(cfg, data) { + if (!cfg.defaultDateType) { + throw new Error( + "Field 'defaultDateType' was not set in the configuration object of quartz.config.ts." + ); + } + return data.dates?.[cfg.defaultDateType]; +} +function formatDate(d, locale = "en-US") { + return d.toLocaleDateString(locale, { + year: "numeric", + month: "short", + day: "2-digit" + }); +} + +// src/util/sort.ts +function byDateAndAlphabetical(cfg) { + return (f1, f2) => { + if (f1.dates && f2.dates) { + return getDate(cfg, f2).getTime() - getDate(cfg, f1).getTime(); + } 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); + }; +} + +// src/components/styles/recentNotes.scss +var recentNotes_default = ".recent-notes > h3 {\n margin: 0.5rem 0 0 0;\n font-size: 1rem;\n}\n.recent-notes > ul.recent-ul {\n list-style: none;\n margin-top: 1rem;\n padding-left: 0;\n}\n.recent-notes > ul.recent-ul > li {\n margin: 1rem 0;\n}\n.recent-notes > ul.recent-ul > li .section > .desc > h3 > a {\n background-color: transparent;\n}\n.recent-notes > ul.recent-ul > li .section > .meta {\n margin: 0 0 0.5rem 0;\n opacity: 0.6;\n}"; +var defaultOptions = (cfg) => ({ + limit: 3, + linkToMore: false, + showTags: true, + filter: () => true, + sort: byDateAndAlphabetical(cfg) +}); +var RecentNotes_default = ((userOpts) => { + const RecentNotes = ({ + allFiles, + fileData, + displayClass, + cfg + }) => { + const globalCfg = cfg; + const opts = { ...defaultOptions(globalCfg), ...userOpts }; + const pages = allFiles.filter(opts.filter).sort(opts.sort); + const remaining = Math.max(0, pages.length - opts.limit); + const slug = fileData.slug; + const locale = cfg.locale ?? "en-US"; + return /* @__PURE__ */ jsxs("div", { class: classNames(displayClass, "recent-notes"), children: [ + /* @__PURE__ */ jsx("h3", { children: opts.title ?? i18n(locale).components.recentNotes.title }), + /* @__PURE__ */ jsx("ul", { class: "recent-ul", children: pages.slice(0, opts.limit).map((page) => { + const title = page.frontmatter?.title ?? "Untitled"; + const tags = page.frontmatter?.tags ?? []; + return /* @__PURE__ */ jsx("li", { class: "recent-li", children: /* @__PURE__ */ jsxs("div", { class: "section", children: [ + /* @__PURE__ */ jsx("div", { class: "desc", children: /* @__PURE__ */ jsx("h3", { children: /* @__PURE__ */ jsx("a", { href: resolveRelative(slug, page.slug), class: "internal", children: title }) }) }), + page.dates && /* @__PURE__ */ jsx("p", { class: "meta", children: /* @__PURE__ */ jsx("time", { datetime: getDate(globalCfg, page)?.toISOString(), children: formatDate(getDate(globalCfg, page), locale) }) }), + opts.showTags && /* @__PURE__ */ jsx("ul", { class: "tags", children: tags.map((tag) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { class: "internal tag-link", href: resolveRelative(slug, `tags/${tag}`), children: tag }) })) }) + ] }) }); + }) }), + opts.linkToMore && remaining > 0 && /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("a", { href: resolveRelative(slug, opts.linkToMore), children: i18n(locale).components.recentNotes.seeRemainingMore({ remaining }) }) }) + ] }); + }; + RecentNotes.css = recentNotes_default; + return RecentNotes; +}); + +export { RecentNotes_default as RecentNotes }; +//# 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..1971494 --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/util/lang.ts","../src/i18n/locales/en-US.ts","../src/i18n/index.ts","../src/util/path.ts","../src/util/date.ts","../src/util/sort.ts","../src/components/styles/recentNotes.scss","../src/components/RecentNotes.tsx"],"names":["utilSimplifySlug"],"mappings":"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","file":"index.js","sourcesContent":["export function classNames(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","export default {\n components: {\n recentNotes: {\n title: \"Recent Notes\",\n seeRemainingMore: ({ remaining }: { remaining: number }) => `See ${remaining} more →`,\n },\n },\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","import { simplifySlug as utilSimplifySlug, joinSegments } from \"@quartz-community/utils\";\n\nexport function simplifySlug(fp: string): string {\n return utilSimplifySlug(fp);\n}\n\nexport function resolveRelative(current: string, target: string): string {\n const simplified = simplifySlug(target);\n const rootPath = pathToRoot(current);\n return joinSegments(rootPath, simplified);\n}\n\nfunction pathToRoot(slug: string): string {\n let rootPath = slug\n .split(\"/\")\n .filter((x) => x !== \"\")\n .slice(0, -1)\n .map((_) => \"..\")\n .join(\"/\");\n\n if (rootPath.length === 0) {\n rootPath = \".\";\n }\n\n return rootPath;\n}\n","interface GlobalConfiguration {\n defaultDateType: string;\n [key: string]: unknown;\n}\n\ninterface QuartzPluginData {\n dates?: Record;\n [key: string]: unknown;\n}\n\nexport function getDate(cfg: GlobalConfiguration, data: QuartzPluginData): Date | undefined {\n if (!cfg.defaultDateType) {\n throw new Error(\n \"Field 'defaultDateType' was not set in the configuration object of quartz.config.ts.\",\n );\n }\n return data.dates?.[cfg.defaultDateType];\n}\n\nexport function formatDate(d: Date, locale: string = \"en-US\"): string {\n return d.toLocaleDateString(locale, {\n year: \"numeric\",\n month: \"short\",\n day: \"2-digit\",\n });\n}\n","import { getDate } from \"./date\";\n\ninterface GlobalConfiguration {\n defaultDateType: string;\n [key: string]: unknown;\n}\n\ninterface QuartzPluginData {\n dates?: Record;\n frontmatter?: {\n title?: string;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\nexport type SortFn = (f1: QuartzPluginData, f2: QuartzPluginData) => number;\n\nexport function byDateAndAlphabetical(cfg: GlobalConfiguration): SortFn {\n return (f1, f2) => {\n if (f1.dates && f2.dates) {\n return getDate(cfg, f2)!.getTime() - getDate(cfg, f1)!.getTime();\n } else if (f1.dates && !f2.dates) {\n return -1;\n } else if (!f1.dates && f2.dates) {\n return 1;\n }\n\n const f1Title = f1.frontmatter?.title?.toLowerCase() ?? \"\";\n const f2Title = f2.frontmatter?.title?.toLowerCase() ?? \"\";\n return f1Title.localeCompare(f2Title);\n };\n}\n",".recent-notes > h3 {\n margin: 0.5rem 0 0 0;\n font-size: 1rem;\n}\n.recent-notes > ul.recent-ul {\n list-style: none;\n margin-top: 1rem;\n padding-left: 0;\n}\n.recent-notes > ul.recent-ul > li {\n margin: 1rem 0;\n}\n.recent-notes > ul.recent-ul > li .section > .desc > h3 > a {\n background-color: transparent;\n}\n.recent-notes > ul.recent-ul > li .section > .meta {\n margin: 0 0 0.5rem 0;\n opacity: 0.6;\n}","import type { QuartzComponent, QuartzComponentProps } from \"@quartz-community/types\";\nimport { classNames } from \"../util/lang\";\nimport { i18n } from \"../i18n\";\nimport { resolveRelative } from \"../util/path\";\nimport { getDate, formatDate } from \"../util/date\";\nimport { byDateAndAlphabetical } from \"../util/sort\";\nimport style from \"./styles/recentNotes.scss\";\n\ntype QuartzComponentConstructor = (\n opts: Options,\n) => QuartzComponent;\n\ninterface QuartzPluginData {\n slug?: string;\n filePath?: string;\n dates?: Record;\n frontmatter?: {\n title?: string;\n tags?: string[];\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\ninterface GlobalConfiguration {\n locale: string;\n defaultDateType: string;\n [key: string]: unknown;\n}\n\nexport interface RecentNotesOptions {\n title?: string;\n limit: number;\n linkToMore: string | false;\n showTags: boolean;\n filter: (f: QuartzPluginData) => boolean;\n sort: (f1: QuartzPluginData, f2: QuartzPluginData) => number;\n}\n\nconst defaultOptions = (cfg: GlobalConfiguration): RecentNotesOptions => ({\n limit: 3,\n linkToMore: false,\n showTags: true,\n filter: () => true,\n sort: byDateAndAlphabetical(cfg),\n});\n\nexport default ((userOpts?: Partial) => {\n const RecentNotes: QuartzComponent = ({\n allFiles,\n fileData,\n displayClass,\n cfg,\n }: QuartzComponentProps & { displayClass?: string }) => {\n const globalCfg = cfg as unknown as GlobalConfiguration;\n const opts = { ...defaultOptions(globalCfg), ...userOpts };\n const pages = (allFiles as QuartzPluginData[]).filter(opts.filter).sort(opts.sort);\n const remaining = Math.max(0, pages.length - opts.limit);\n const slug = fileData.slug as string | undefined;\n const locale = cfg.locale ?? \"en-US\";\n return (\n
\n

{opts.title ?? i18n(locale).components.recentNotes.title}

\n
    \n {pages.slice(0, opts.limit).map((page) => {\n const title = page.frontmatter?.title ?? \"Untitled\";\n const tags = page.frontmatter?.tags ?? [];\n\n return (\n
  • \n
    \n
    \n

    \n \n {title}\n \n

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

    \n \n

    \n )}\n {opts.showTags && (\n \n )}\n
    \n
  • \n );\n })}\n
\n {opts.linkToMore && remaining > 0 && (\n

\n \n {i18n(locale).components.recentNotes.seeRemainingMore({ remaining })}\n \n

\n )}\n
\n );\n };\n\n RecentNotes.css = style;\n return RecentNotes;\n}) satisfies QuartzComponentConstructor;\n"]} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b966d5f..32b5536 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +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" + "@quartz-community/utils": "github:quartz-community/utils" }, "devDependencies": { "@types/hast": "^3.0.4", @@ -26,6 +24,8 @@ "prettier": "^3.6.2", "sass": "^1.97.3", "sass-embedded": "^1.97.3", + "tsup": "^8.5.0", + "typescript": "^5.9.3", "vfile": "^6.0.3", "vitest": "^2.1.9" }, @@ -4061,7 +4061,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", diff --git a/package.json b/package.json index 99b4ba1..42fd6e6 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "sideEffects": false, "scripts": { "build": "tsup", - "prepare": "npm run build", "dev": "tsup --watch", "lint": "eslint . --max-warnings=0", "format": "prettier . --check",