@quartz-community/folder-page 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -273,12 +273,26 @@ function getDate(data) {
273
273
  const dates = data.dates;
274
274
  return dates?.[defaultDateType];
275
275
  }
276
-
277
- // node_modules/@quartz-community/utils/dist/path.js
278
276
  function simplifySlug(fp) {
279
277
  const res = stripSlashes(trimSuffix(fp, "index"), true);
280
278
  return res.length === 0 ? "/" : res;
281
279
  }
280
+ function slugifyFilePath(fp, excludeExt) {
281
+ fp = stripSlashes(fp);
282
+ const ext = getFileExtension(fp);
283
+ const withoutFileExt = fp.replace(new RegExp(ext + "$"), "");
284
+ const finalExt = [".md", ".html", void 0].includes(ext) ? "" : ext;
285
+ let slug2 = _sluggify(withoutFileExt);
286
+ if (endsWith(slug2, "_index")) {
287
+ slug2 = slug2.replace(/_index$/, "index");
288
+ }
289
+ const segments = slug2.split("/");
290
+ if (segments.length >= 2 && segments[segments.length - 1] === segments[segments.length - 2]) {
291
+ segments[segments.length - 1] = "index";
292
+ slug2 = segments.join("/");
293
+ }
294
+ return slug2 + (finalExt ?? "");
295
+ }
282
296
  function joinSegments(...args) {
283
297
  if (args.length === 0) {
284
298
  return "";
@@ -312,6 +326,9 @@ function stripSlashes(s2, onlyStripPrefix) {
312
326
  }
313
327
  return s2;
314
328
  }
329
+ function getFileExtension(s2) {
330
+ return s2.match(/\.[A-Za-z0-9]+$/)?.[0];
331
+ }
315
332
  function isFolderPath(fplike) {
316
333
  return fplike.endsWith("/") || endsWith(fplike, "index") || endsWith(fplike, "index.md") || endsWith(fplike, "index.html");
317
334
  }
@@ -326,6 +343,14 @@ function resolveRelative(current, target) {
326
343
  const res = joinSegments(pathToRoot(current), simplifySlug(target));
327
344
  return res;
328
345
  }
346
+ function slugifyPath(s2) {
347
+ return s2.split("/").map(
348
+ (segment) => segment.replace(/\s/g, "-").replace(/&/g, "-and-").replace(/%/g, "-percent").replace(/\?/g, "").replace(/#/g, "").replace(/[<>:"|*]/g, "").toLowerCase()
349
+ ).join("/").replace(/\/$/, "");
350
+ }
351
+ function _sluggify(s2) {
352
+ return slugifyPath(s2);
353
+ }
329
354
 
330
355
  // node_modules/preact/dist/preact.mjs
331
356
  var n;
@@ -2723,7 +2748,8 @@ function pagesFromAllFiles(allFiles, folderSlug, showSubfolders) {
2723
2748
  const subfolderFiles = /* @__PURE__ */ new Map();
2724
2749
  for (const file of allFiles) {
2725
2750
  if (file.unlisted === true) continue;
2726
- const fileSlug = file.slug;
2751
+ const rel = file.relativePath;
2752
+ const fileSlug = rel ? slugifyFilePath(rel) : file.slug;
2727
2753
  if (!fileSlug || !fileSlug.startsWith(folderPrefix)) continue;
2728
2754
  const relativePath = fileSlug.slice(folderPrefix.length);
2729
2755
  if (!relativePath || relativePath === "index") continue;
@@ -2740,7 +2766,10 @@ function pagesFromAllFiles(allFiles, folderSlug, showSubfolders) {
2740
2766
  }
2741
2767
  for (const [subfolderName, files] of subfolderFiles) {
2742
2768
  const indexFile = files.find((f3) => f3.slug === `${folderPrefix}${subfolderName}/index`);
2743
- if (indexFile) continue;
2769
+ if (indexFile) {
2770
+ if (indexFile.unlisted !== true) directChildren.push(indexFile);
2771
+ continue;
2772
+ }
2744
2773
  directChildren.push({
2745
2774
  slug: `${folderPrefix}${subfolderName}/index`,
2746
2775
  dates: mostRecentDatesFromEntries(files),
@@ -2787,16 +2816,15 @@ var FolderContent_default = ((opts) => {
2787
2816
  const FolderContent = (props) => {
2788
2817
  const { tree, fileData, allFiles, cfg } = props;
2789
2818
  const ctx = props.ctx;
2790
- const slug2 = fileData?.slug;
2791
- if (!slug2) return null;
2819
+ const slug = fileData?.slug;
2820
+ if (!slug) return null;
2792
2821
  const trie = ctx?.trie;
2793
2822
  let allPagesInFolder;
2794
- if (trie) {
2795
- const folder = trie.findNode(slug2.split("/"));
2796
- if (!folder) return null;
2823
+ const folder = trie?.findNode(slug.split("/"));
2824
+ if (folder) {
2797
2825
  allPagesInFolder = pagesFromTrie(folder, options.showSubfolders);
2798
2826
  } else {
2799
- allPagesInFolder = pagesFromAllFiles(allFiles ?? [], slug2, options.showSubfolders);
2827
+ allPagesInFolder = pagesFromAllFiles(allFiles ?? [], slug, options.showSubfolders);
2800
2828
  }
2801
2829
  const cssClasses = fileData?.frontmatter?.cssclasses ?? [];
2802
2830
  const classes = cssClasses.join(" ");
@@ -2823,11 +2851,11 @@ var FolderContent_default = ((opts) => {
2823
2851
  FolderContent.css = concatenateResources(listPage_default, PageList.css);
2824
2852
  return FolderContent;
2825
2853
  });
2826
- var folderMatcher = ({ slug: slug2 }) => {
2827
- return slug2.endsWith("/index");
2854
+ var folderMatcher = ({ slug }) => {
2855
+ return slug.endsWith("/index");
2828
2856
  };
2829
- function getFolders(slug2) {
2830
- let folderName = path.dirname(slug2 ?? "");
2857
+ function getFolders(slug) {
2858
+ let folderName = path.dirname(slug ?? "");
2831
2859
  const parentFolderNames = [folderName];
2832
2860
  while (folderName !== ".") {
2833
2861
  folderName = path.dirname(folderName ?? "");
@@ -2835,27 +2863,38 @@ function getFolders(slug2) {
2835
2863
  }
2836
2864
  return parentFolderNames;
2837
2865
  }
2866
+ function virtualPagesOf(ctx) {
2867
+ const pages = ctx?.virtualPages;
2868
+ return Array.isArray(pages) ? pages : [];
2869
+ }
2838
2870
  var FolderPage = (opts) => {
2839
2871
  const body = () => FolderContent_default(opts);
2840
2872
  return {
2841
2873
  name: "FolderPage",
2842
2874
  priority: 10,
2843
2875
  match: folderMatcher,
2844
- generate({ content, cfg }) {
2845
- const allFiles = content.map((c2) => c2[1].data).filter((d2) => d2?.unlisted !== true);
2876
+ generate({ content, cfg, ctx }) {
2877
+ const virtual = virtualPagesOf(ctx).filter((c2) => {
2878
+ const slug = c2[1].data?.slug;
2879
+ return !!slug && slug !== "tags" && !slug.startsWith("tags/");
2880
+ });
2881
+ const files = [...content, ...virtual];
2882
+ const allFiles = files.map((c2) => c2[1].data).filter((d2) => d2?.unlisted !== true);
2846
2883
  const locale = cfg?.locale ?? "en-US";
2847
2884
  const folders = /* @__PURE__ */ new Set();
2848
2885
  const folderDisplayNames = /* @__PURE__ */ new Map();
2849
2886
  for (const file of allFiles) {
2850
- const slug2 = file?.slug;
2851
- if (!slug2) continue;
2852
- const fileFolders = getFolders(slug2).filter((f3) => f3 !== "." && f3 !== "tags");
2887
+ const slug = file?.slug;
2888
+ if (!slug) continue;
2889
+ const rel = file?.relativePath;
2890
+ const position3 = rel ? slugifyFilePath(rel) : slug;
2891
+ const fileFolders = getFolders(position3).filter((f3) => f3 !== "." && f3 !== "tags");
2853
2892
  for (const f3 of fileFolders) {
2854
2893
  folders.add(f3);
2855
2894
  }
2856
2895
  const relativePath = file?.relativePath;
2857
2896
  if (relativePath) {
2858
- const slugParts = path.dirname(slug2).split("/").filter((s2) => s2 !== ".");
2897
+ const slugParts = path.dirname(slug).split("/").filter((s2) => s2 !== ".");
2859
2898
  const pathParts = path.dirname(relativePath).split("/").filter((s2) => s2 !== ".");
2860
2899
  for (let i2 = 0; i2 < slugParts.length && i2 < pathParts.length; i2++) {
2861
2900
  const slugPart = slugParts[i2];
@@ -2867,21 +2906,21 @@ var FolderPage = (opts) => {
2867
2906
  }
2868
2907
  }
2869
2908
  const foldersWithIndex = /* @__PURE__ */ new Set();
2870
- for (const [, file] of content) {
2909
+ for (const [, file] of files) {
2871
2910
  const data = file.data;
2872
2911
  if (data?.unlisted === true) continue;
2873
- const slug2 = data?.slug;
2874
- if (slug2 && slug2.endsWith("/index")) {
2875
- const folder = slug2.slice(0, -"/index".length);
2912
+ const slug = data?.slug;
2913
+ if (slug && slug.endsWith("/index")) {
2914
+ const folder = slug.slice(0, -"/index".length);
2876
2915
  foldersWithIndex.add(folder);
2877
2916
  }
2878
2917
  }
2879
2918
  for (const [, file] of content) {
2880
- const slug2 = file.data?.slug;
2881
- if (!slug2 || !slug2.endsWith("/index")) continue;
2919
+ const slug = file.data?.slug;
2920
+ if (!slug || !slug.endsWith("/index")) continue;
2882
2921
  const frontmatter = file.data.frontmatter;
2883
2922
  if (!frontmatter || frontmatter.title && frontmatter.title !== "index") continue;
2884
- const folder = slug2.slice(0, -"/index".length);
2923
+ const folder = slug.slice(0, -"/index".length);
2885
2924
  const slugSegment = folder.split("/").pop() ?? folder;
2886
2925
  const folderName = folderDisplayNames.get(slugSegment) ?? slugSegment;
2887
2926
  frontmatter.title = opts?.prefixFolders ? `${i18n(locale).pages.folderContent.folder}: ${folderName}` : folderName;
@@ -2889,12 +2928,12 @@ var FolderPage = (opts) => {
2889
2928
  const virtualPages = [];
2890
2929
  for (const folder of folders) {
2891
2930
  if (foldersWithIndex.has(folder)) continue;
2892
- const slug2 = joinSegments(folder, "index");
2931
+ const slug = joinSegments(folder, "index");
2893
2932
  const slugSegment = folder.split("/").pop() ?? folder;
2894
2933
  const folderName = folderDisplayNames.get(slugSegment) ?? slugSegment;
2895
2934
  const title = opts?.prefixFolders ? `${i18n(locale).pages.folderContent.folder}: ${folderName}` : folderName;
2896
2935
  virtualPages.push({
2897
- slug: slug2,
2936
+ slug,
2898
2937
  title,
2899
2938
  data: {}
2900
2939
  });