]> Lady’s Gitweb - GitWikiWeb/blobdiff - build.js
List subpages in a see also section
[GitWikiWeb] / build.js
index ae250ca9e6d140c3a9a6ccd760b215ad79c4de3d..fa0b836190c555699758a895b6d62faf6c5e1cee 100644 (file)
--- a/build.js
+++ b/build.js
@@ -229,82 +229,6 @@ class GitWikiWebPage {
     djot.applyFilter(ast, () => {
       let titleSoFar = null; // used to collect strs from headings
       return {
-        doc: {
-          enter: (_) => {},
-          exit: (e) => {
-            const links_section = [];
-            if (internalLinks.size || externalLinks.size) {
-              links_section.push(
-                rawBlock`<nav id="links">`,
-                {
-                  tag: "heading",
-                  level: 2,
-                  children: [str`this page contains links`],
-                },
-              );
-              if (internalLinks.size) {
-                links_section.push(
-                  rawBlock`<details open="">`,
-                  rawBlock`<summary>on this wiki</summary>`,
-                  listOfInternalLinks(internalLinks),
-                  rawBlock`</details>`,
-                );
-              } else {
-                /* do nothing */
-              }
-              if (externalLinks.size) {
-                links_section.push(
-                  rawBlock`<details open="">`,
-                  rawBlock`<summary>elsewhere on the Web</summary>`,
-                  {
-                    tag: "bullet_list",
-                    tight: true,
-                    style: "*",
-                    children: Array.from(
-                      externalLinks,
-                      ([destination, text]) => ({
-                        tag: "list_item",
-                        children: [{
-                          tag: "para",
-                          children: [{
-                            tag: "link",
-                            attributes: { "data-realm": "external" },
-                            destination,
-                            children: text
-                              ? [
-                                rawInline`<cite>`,
-                                str`${text}`,
-                                rawInline`</cite>`,
-                              ]
-                              : [
-                                rawInline`<code>`,
-                                str`${destination}`,
-                                rawInline`</code>`,
-                              ],
-                          }],
-                        }],
-                      }),
-                    ),
-                  },
-                  rawBlock`</details>`,
-                );
-              } else {
-                /* do nothing */
-              }
-              links_section.push(
-                rawBlock`</nav>`,
-              );
-            } else {
-              /* do nothing */
-            }
-            e.children.push(
-              rawBlock`<footer>`,
-              rawBlock`${"\uFFFF"}`, // footnote placeholder
-              ...links_section,
-              rawBlock`</footer>`,
-            );
-          },
-        },
         hard_break: {
           enter: (_) => {
             if (titleSoFar != null) {
@@ -345,11 +269,20 @@ class GitWikiWebPage {
               const resolvedReference = pageName == ""
                 ? `Namespace:${expandedNamespace}`
                 : `${expandedNamespace}:${pageName}`;
-              this.#internalLinks.add(resolvedReference);
               e.reference = resolvedReference;
               attributes["data-realm"] = "internal";
               attributes["data-pagename"] = pageName;
               attributes["data-namespace"] = expandedNamespace;
+              if (
+                resolvedReference.startsWith("Editor:") &&
+                (attributes.class ?? "").split(/\s/gu).includes("sig")
+              ) {
+                // This is a special internal link; do not record it.
+                /* do nothing */
+              } else {
+                // This is a non‐special internal link; record it.
+                internalLinks.add(resolvedReference);
+              }
             } else {
               attributes["data-realm"] = "external";
               const remote = destination ??
@@ -729,28 +662,157 @@ class GitWikiWebPage {
       ),
     ]).then(logErrorsAndCollectResults);
     promises.length = 0;
-    const redLinks = (() => {
-      const result = new Set();
-      for (const page of pages.values()) {
+    const { redLinks, subpages } = (() => {
+      const redLinks = new Set();
+      const subpages = new Map();
+      for (const [pageRef, page] of pages) {
+        let superRef = pageRef;
+        while (
+          (superRef = superRef.substring(0, superRef.indexOf("/")))
+        ) {
+          // Iterate over potential superpages and record them if they
+          // actually exist.
+          if (pages.has(superRef)) {
+            // There is a superpage for the current page; record it.
+            if (subpages.has(superRef)) {
+              // The identified superpage already has other subpages.
+              subpages.get(superRef).add(pageRef);
+            } else {
+              // The identified superpage does not already have other
+              // subpages.
+              subpages.set(superRef, new Set([pageRef]));
+            }
+            break;
+          } else {
+            // The superpage for the current page has not been found
+            // yet.
+            /* do nothing */
+          }
+        }
         for (const link of page.internalLinks()) {
+          // Iterate over the internal links of the current page and
+          // ensure they are all defined.
           if (pages.has(link)) {
+            // The link was defined.
             continue;
           } else {
-            result.add(link);
+            // The link was not defined; it is a redlink.
+            redLinks.add(link);
           }
         }
       }
-      return result;
+      return { redLinks, subpages };
     })();
-    for (
-      const [pageRef, { ast, namespace, sections, source }] of pages
-    ) {
+    for (const [pageRef, page] of pages) {
+      const { ast, sections, source } = page;
       const title = sections.main?.title ?? pageRef;
+      const internalLinks = new Set(page.internalLinks());
+      const externalLinks = new Map(page.externalLinks());
+      const subpageRefs = subpages.get(pageRef) ?? new Set();
       djot.applyFilter(ast, () => {
         let isNavigationPage = true;
         return {
           doc: {
             enter: (e) => {
+              const seeAlsoSection = [];
+              const linksSection = [];
+              if (subpageRefs.size) {
+                seeAlsoSection.push(
+                  rawBlock`<nav id="seealso">`,
+                  {
+                    tag: "heading",
+                    level: 2,
+                    children: [
+                      str`see also`,
+                    ],
+                  },
+                  rawBlock`<section id="subpages">`,
+                  {
+                    tag: "heading",
+                    level: 3,
+                    children: [
+                      str`subpages`,
+                    ],
+                  },
+                  listOfInternalLinks(subpageRefs),
+                  rawBlock`</section>`,
+                  rawBlock`</nav>`,
+                );
+              } else {
+                /* do nothing */
+              }
+              if (internalLinks.size || externalLinks.size) {
+                linksSection.push(
+                  rawBlock`<nav id="links">`,
+                  {
+                    tag: "heading",
+                    level: 2,
+                    children: [str`this page contains links`],
+                  },
+                );
+                if (internalLinks.size) {
+                  linksSection.push(
+                    rawBlock`<details open="">`,
+                    rawBlock`<summary>on this wiki</summary>`,
+                    listOfInternalLinks(internalLinks),
+                    rawBlock`</details>`,
+                  );
+                } else {
+                  /* do nothing */
+                }
+                if (externalLinks.size) {
+                  linksSection.push(
+                    rawBlock`<details open="">`,
+                    rawBlock`<summary>elsewhere on the Web</summary>`,
+                    {
+                      tag: "bullet_list",
+                      tight: true,
+                      style: "*",
+                      children: Array.from(
+                        externalLinks,
+                        ([destination, text]) => ({
+                          tag: "list_item",
+                          children: [{
+                            tag: "para",
+                            children: [{
+                              tag: "link",
+                              attributes: { "data-realm": "external" },
+                              destination,
+                              children: text
+                                ? [
+                                  rawInline`<cite>`,
+                                  str`${text}`,
+                                  rawInline`</cite>`,
+                                ]
+                                : [
+                                  rawInline`<code>`,
+                                  str`${destination}`,
+                                  rawInline`</code>`,
+                                ],
+                            }],
+                          }],
+                        }),
+                      ),
+                    },
+                    rawBlock`</details>`,
+                  );
+                } else {
+                  /* do nothing */
+                }
+                linksSection.push(
+                  rawBlock`</nav>`,
+                );
+              } else {
+                /* do nothing */
+              }
+              const childrenAndLinks = [
+                ...e.children,
+                ...seeAlsoSection,
+                rawBlock`<footer>`,
+                rawBlock`${"\uFFFF"}`, // footnote placeholder
+                ...linksSection,
+                rawBlock`</footer>`,
+              ];
               const { content, navigation } = (() => {
                 const navigation = [];
                 if (pageRef == "Special:RecentlyChanged") {
@@ -791,7 +853,7 @@ class GitWikiWebPage {
                   });
                 } else {
                   isNavigationPage = false;
-                  return { content: e.children, navigation };
+                  return { content: childrenAndLinks, navigation };
                 }
                 return {
                   content: [
@@ -807,7 +869,7 @@ class GitWikiWebPage {
                     rawBlock`<details id="navigation-about" open="">`,
                     rawBlock`<summary>about this listing</summary>`,
                     rawBlock`<article>`,
-                    ...e.children,
+                    ...childrenAndLinks,
                     rawBlock`</article>`,
                     rawBlock`</details>`,
                   ],
This page took 0.029248 seconds and 4 git commands to generate.