« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/common-util
diff options
context:
space:
mode:
Diffstat (limited to 'src/common-util')
-rw-r--r--src/common-util/sugar.js47
-rw-r--r--src/common-util/wiki-data.js88
2 files changed, 72 insertions, 63 deletions
diff --git a/src/common-util/sugar.js b/src/common-util/sugar.js
index 4dd34785..c988156c 100644
--- a/src/common-util/sugar.js
+++ b/src/common-util/sugar.js
@@ -418,39 +418,28 @@ export function escapeRegex(string) {
 }
 
 // Adapted from here: https://emnudge.dev/notes/multiline-regex/
+// ...with a lot of changes
 export function re(...args) {
-  let flags = '';
-
-  const fn = (strings, ...substitutions) => {
-    strings = strings
-      .map(str => str.replace(/(?:\/\/.+)/gm, ''))
-      .map(str => str.replace(/\s+/g, ''));
-
-    substitutions = substitutions
-      .map(sub => [sub].flat(Infinity))
-      .map(sub => sub
-        .map(item =>
-          (item instanceof RegExp
-            ? item.source
-            : item.toString())))
-      .map(sub => sub.join(''));
-
-    const source =
-      String.raw({raw: strings}, ...substitutions);
-
-    return new RegExp(source, flags);
-  };
-
-  if (
-    args.length === 1 &&
-    typeof args[0] === 'string' &&
-    args[0].match(/^[a-z]+$/)
-  ) {
+  let flags, parts;
+  if (args.length === 2) {
     flags = args[0];
-    return fn;
+    parts = args[1];
+  } else if (args.length === 1) {
+    flags = '';
+    parts = args[0];
   } else {
-    return fn(...args);
+    throw new Error(`Expected 1 or 2 arguments`);
   }
+
+  const source = parts
+    .flat(Infinity)
+    .map(item =>
+      (item instanceof RegExp
+        ? item.source
+        : item.toString()))
+    .join('');
+
+  return new RegExp(source, flags);
 }
 
 export function splitKeys(key) {
diff --git a/src/common-util/wiki-data.js b/src/common-util/wiki-data.js
index 4c7f66f4..ff325b7a 100644
--- a/src/common-util/wiki-data.js
+++ b/src/common-util/wiki-data.js
@@ -1,6 +1,6 @@
 // Utility functions for interacting with wiki data.
 
-import {accumulateSum, chunkByConditions, empty, unique} from './sugar.js';
+import {accumulateSum, chunkByConditions, empty, re, unique} from './sugar.js';
 import {sortByDate} from './sort.js';
 
 // This is a duplicate binding of filterMultipleArrays that's included purely
@@ -76,42 +76,48 @@ export function compareKebabCase(name1, name2) {
 //   by slashes or dashes (only valid orders are MM/DD/YYYY and YYYY/MM/DD)
 //
 const dateRegex = groupName =>
-  String.raw`(?<${groupName}>` +
-    String.raw`[a-zA-Z]+ [0-9]{1,2}, [0-9]{4,4}|` +
-    String.raw`[0-9]{1,2} [^,]*[0-9]{4,4}|` +
-    String.raw`[0-9]{1,4}[-/][0-9]{1,4}[-/][0-9]{1,4}` +
-  String.raw`)`;
-
-const contentEntryHeadingRegexRaw =
-  String.raw`^(?:` +
-    String.raw`(?:` +
-      String.raw`<i>(?<artists>.+?):<\/i>` +
-      String.raw`(?: \((?<annotation1>.*)\))?` +
-    String.raw`)` +
-    String.raw`|` +
-    String.raw`(?:` +
-      String.raw`@@ (?<annotation2>.*)` +
-    String.raw`)` +
-  String.raw`)$`;
+  re([
+    `(?<${groupName}>`,
+      /[a-zA-Z]+ [0-9]{1,2}, [0-9]{4,4}/, '|',
+      /[0-9]{1,2} [^,]*[0-9]{4,4}/, '|',
+      /[0-9]{1,4}[-/][0-9]{1,4}[-/][0-9]{1,4}/,
+    `)`,
+  ]);
 
 const contentEntryHeadingRegex =
-  new RegExp(contentEntryHeadingRegexRaw, 'gm');
-
-const contentEntryAnnotationTailRegexRaw =
-  String.raw`(?:, |^)` +
-
-  String.raw`(?:(?<dateKind>sometime|throughout|around) )?` +
-  String.raw`${dateRegex('date')}` +
-  String.raw`(?: ?- ?${dateRegex('secondDate')})?` +
-
-  String.raw`(?: ?(?<= )` +
-    String.raw`(?<accessKind>captured|accessed) ${dateRegex('accessDate')}` +
-  String.raw`)?` +
-
-  String.raw`$`;
+  re('gm', [
+    '^(?:',
+      '(?:',
+        /<i>(?<artists>.+?):<\/i>/,
+        /(?: \((?<annotation1>.*)\))?/,
+      ')',
+      '|',
+      '(?:',
+        /@@ (?<annotation2>.*)/,
+      ')',
+    ')$',
+  ]);
 
 const contentEntryAnnotationTailRegex =
-  new RegExp(contentEntryAnnotationTailRegexRaw);
+  re([
+    /(?:, |^)/,
+
+    /(?:(?<dateKind>sometime|throughout|around) )?/,
+    dateRegex('date'),
+
+    '(?:',
+      ' ?',
+      '-',
+      ' ?',
+      dateRegex('secondDate'),
+    ')?',
+
+    '(?: ?(?<= )',
+      /(?<accessKind>captured|accessed)/,
+      ' ',
+      dateRegex('accessDate'),
+    ')?',
+  ]);
 
 export function* matchContentEntries(sourceText) {
   let workingEntry = null;
@@ -593,7 +599,21 @@ export function* matchMarkdownLinks(markdownSource, {marked}) {
 }
 
 export function* matchInlineLinks(source) {
-  const plausibleLinkRegexp = /\b[a-z]*:\/\/[^ ]*?(?=(?:[,.!?]*)(?:\s|$))/gm;
+  const plausibleLinkRegexp =
+    re('gmi', [
+      /\b[a-z]*:\/\//,
+      /.*?/,
+
+      '(?=',
+        // Ordinary in-sentence punctuation doesn't terminate the
+        // un-greedy URL match above, but it shouldn't be counted
+        // as part of the link either, if it's at the end.
+        /(?:[,.!?]*)/,
+
+        // Actual terminators.
+        /(?:\s|$|<br>)/,
+      ')',
+    ]);
 
   let plausibleMatch = null;
   while (plausibleMatch = plausibleLinkRegexp.exec(source)) {