« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/content/dependencies/generateAdditionalNamesBox.js12
-rw-r--r--src/content/dependencies/generatePageLayout.js13
-rw-r--r--src/content/dependencies/transformContent.js4
-rw-r--r--src/static/css/site.css2
-rw-r--r--src/write/build-modes/static-build.js69
5 files changed, 92 insertions, 8 deletions
diff --git a/src/content/dependencies/generateAdditionalNamesBox.js b/src/content/dependencies/generateAdditionalNamesBox.js
index b7392dfd..8bb61528 100644
--- a/src/content/dependencies/generateAdditionalNamesBox.js
+++ b/src/content/dependencies/generateAdditionalNamesBox.js
@@ -8,11 +8,21 @@ export default {
         .map(entry => relation('generateAdditionalNamesBoxItem', entry)),
   }),
 
-  generate: (relations, {html, language}) =>
+  slots: {
+    alwaysVisible: {
+      type: 'boolean',
+      default: false,
+    },
+  },
+
+  generate: (relations, slots, {html, language}) =>
     html.tag('div', {id: 'additional-names-box'},
       {class: 'drop'},
       {[html.onlyIfContent]: true},
 
+      slots.alwaysVisible &&
+        {class: 'always-visible'},
+
       [
         html.tag('p',
           {[html.onlyIfSiblings]: true},
diff --git a/src/content/dependencies/generatePageLayout.js b/src/content/dependencies/generatePageLayout.js
index 0326f415..4318f462 100644
--- a/src/content/dependencies/generatePageLayout.js
+++ b/src/content/dependencies/generatePageLayout.js
@@ -296,12 +296,17 @@ export default {
     const titleContentsHTML =
       (html.isBlank(slots.title)
         ? null
-     : html.isBlank(slots.additionalNames)
-        ? language.sanitize(slots.title)
-        : html.tag('a', {
+
+     : (!html.isBlank(slots.additionalNames) &&
+        !html.resolve(slots.additionalNames, {slots: ['alwaysVisible']})
+          .getSlotValue('alwaysVisible'))
+
+        ? html.tag('a', {
             href: '#additional-names-box',
             title: language.$('misc.additionalNames.tooltip').toString(),
-          }, language.sanitize(slots.title)));
+          }, language.sanitize(slots.title))
+
+        : language.sanitize(slots.title));
 
     const titleHTML =
       (html.isBlank(slots.title)
diff --git a/src/content/dependencies/transformContent.js b/src/content/dependencies/transformContent.js
index 3f738db2..a3df46cd 100644
--- a/src/content/dependencies/transformContent.js
+++ b/src/content/dependencies/transformContent.js
@@ -891,8 +891,8 @@ export default {
         extractNonTextNodes()
           // Compress multiple line breaks into single line breaks,
           // except when they're preceding or following indented
-          // text (by at least two spaces).
-          .replace(/(?<!  .*)\n{2,}(?!^  )/gm, '\n') /* eslint-disable-line no-regex-spaces */
+          // text (by at least two spaces) or blockquotes.
+          .replace(/(?<!^  .*|^>.*)\n{2,}(?!^  |^>)/gm, '\n') /* eslint-disable-line no-regex-spaces */
           // Expand line breaks which don't follow a list, quote,
           // or <br> / "  ", and which don't precede or follow
           // indented text (by at least two spaces).
diff --git a/src/static/css/site.css b/src/static/css/site.css
index 23d9eb32..7bf30a7e 100644
--- a/src/static/css/site.css
+++ b/src/static/css/site.css
@@ -2559,7 +2559,9 @@ h1 a[href="#additional-names-box"]:hover {
   max-width: min(60vw, 600px);
 
   padding: 15px 20px 10px 20px;
+}
 
+#additional-names-box:not(.always-visible) {
   display: none;
 }
 
diff --git a/src/write/build-modes/static-build.js b/src/write/build-modes/static-build.js
index b5ded04c..c0df2d35 100644
--- a/src/write/build-modes/static-build.js
+++ b/src/write/build-modes/static-build.js
@@ -1,6 +1,16 @@
-import {cp, mkdir, stat, symlink, writeFile, unlink} from 'node:fs/promises';
 import * as path from 'node:path';
 
+import {
+  copyFile,
+  cp,
+  mkdir,
+  readFile,
+  stat,
+  symlink,
+  writeFile,
+  unlink,
+} from 'node:fs/promises';
+
 import {rimraf} from 'rimraf';
 
 import {quickLoadContentDependencies} from '#content-dependencies';
@@ -86,6 +96,11 @@ export function getCLIOptions() {
       type: 'value',
     },
 
+    'paths': {
+      help: `Skip rest and build only pages matching paths in this text file`,
+      type: 'value',
+    },
+
     // NOT for neatly ena8ling or disa8ling specific features of the site!
     // This is only in charge of what general groups of files to write.
     // They're here to make development quicker when you're only working
@@ -117,6 +132,7 @@ export async function go({
   const outputPath = cliOptions['out-path'] || process.env.HSMUSIC_OUT;
   const appendIndexHTML = cliOptions['append-index-html'] ?? false;
   const writeOneLanguage = cliOptions['lang'] ?? null;
+  const pathsFromFile = cliOptions['paths'] ?? null;
 
   if (!outputPath) {
     logError`Expected ${'--out-path'} option or ${'HSMUSIC_OUT'} to be set`;
@@ -136,6 +152,36 @@ export async function go({
     logInfo`Writing all languages.`;
   }
 
+  let filterPaths = null;
+  if (pathsFromFile) {
+    let pathsText;
+    try {
+      pathsText = await readFile(pathsFromFile, 'utf8');
+    } catch (error) {
+      logError`Failed to read file specified in ${'--paths'}:`;
+      logError`${error.code}: ${pathsFromFile}`;
+      return false;
+    }
+
+    filterPaths = pathsText.split('\n').filter(Boolean);
+
+    if (empty(filterPaths)) {
+      logWarn`Specified to build only paths in file ${'--paths'}:`;
+      logWarn`${pathsFromFile}`;
+      logWarn`But this file is totally empty...`;
+    }
+
+    if (filterPaths.some(path => !path.startsWith('/'))) {
+      logError`All lines in ${'--paths'} file should start with slash ('${'/'}')`;
+      logError`These lines don't:`;
+      console.error(filterPaths.filter(path => !path.startsWith('/')).join('\n'));
+      logError`Please check file contents, or specified path, and try again.`;
+      return false;
+    }
+
+    logInfo`Writing ${filterPaths.length} paths specified in: ${pathsFromFile} (${'--paths'})`;
+  }
+
   const selectedPageFlags = Object.keys(cliOptions)
     .filter(key => pageFlags.includes(key));
 
@@ -209,6 +255,27 @@ export async function go({
           // TODO: Validate each pathsForTargets entry
         }
 
+        if (!empty(filterPaths)) {
+          paths =
+            paths.filter(path =>
+              filterPaths.includes(
+                (path.type === 'page'
+                  ? '/' +
+                    getPagePathname({
+                      baseDirectory: '',
+                      pagePath: path.path,
+                      urls,
+                    })
+               : path.type === 'redirect'
+                  ? '/' +
+                    getPagePathname({
+                      baseDirectory: '',
+                      pagePath: path.fromPath,
+                      urls,
+                    })
+                  : null)));
+        }
+
         paths =
           paths.filter(path => path.condition?.() ?? true);