« 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--package-lock.json14
-rw-r--r--package.json1
-rw-r--r--src/data/language.js4
-rw-r--r--src/data/things/language.js31
4 files changed, 17 insertions, 33 deletions
diff --git a/package-lock.json b/package-lock.json
index e8bff8f4..3a4d23b4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,7 +16,6 @@
                 "compress-json": "3.4.0",
                 "eslint": "9.37.0",
                 "flexsearch": "0.7.43",
-                "he": "1.2.0",
                 "image-size": "2.0.2",
                 "js-yaml": "4.1.0",
                 "marked": "16.4.1",
@@ -3014,14 +3013,6 @@
                 "node": ">=8"
             }
         },
-        "node_modules/he": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
-            "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
-            "bin": {
-                "he": "bin/he"
-            }
-        },
         "node_modules/hosted-git-info": {
             "version": "9.0.2",
             "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.2.tgz",
@@ -8045,11 +8036,6 @@
             "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
             "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
         },
-        "he": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
-            "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
-        },
         "hosted-git-info": {
             "version": "9.0.2",
             "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.2.tgz",
diff --git a/package.json b/package.json
index 70e66192..6d548ef0 100644
--- a/package.json
+++ b/package.json
@@ -71,7 +71,6 @@
         "compress-json": "3.4.0",
         "eslint": "9.37.0",
         "flexsearch": "0.7.43",
-        "he": "1.2.0",
         "image-size": "2.0.2",
         "js-yaml": "4.1.0",
         "marked": "16.4.1",
diff --git a/src/data/language.js b/src/data/language.js
index 3edf7e51..8dc06e7e 100644
--- a/src/data/language.js
+++ b/src/data/language.js
@@ -4,7 +4,6 @@ import path from 'node:path';
 import {fileURLToPath} from 'node:url';
 
 import chokidar from 'chokidar';
-import he from 'he'; // It stands for "HTML Entities", apparently. Cursed.
 import yaml from 'js-yaml';
 
 import {annotateError, annotateErrorWithFile, showAggregate, withAggregate}
@@ -251,9 +250,6 @@ async function processLanguageSpecFromFile(file, processLanguageSpecOpts) {
 export function initializeLanguageObject() {
   const language = new Language();
 
-  language.escapeHTML = string =>
-    he.encode(string, {useNamedReferences: true});
-
   language.externalLinkSpec = externalLinkSpec;
 
   return language;
diff --git a/src/data/things/language.js b/src/data/things/language.js
index 08c52cb8..7750a1b3 100644
--- a/src/data/things/language.js
+++ b/src/data/things/language.js
@@ -123,10 +123,6 @@ export class Language extends Thing {
       update: {validate: isExternalLinkSpec},
     },
 
-    // Update only
-
-    escapeHTML: externalFunction(),
-
     // Expose only
 
     isLanguage: [
@@ -170,12 +166,12 @@ export class Language extends Thing {
     strings_htmlEscaped: {
       flags: {expose: true},
       expose: {
-        dependencies: ['strings', 'inheritedStrings', 'escapeHTML'],
-        compute({strings, inheritedStrings, escapeHTML}) {
-          if (!(strings || inheritedStrings) || !escapeHTML) return null;
+        dependencies: ['strings', 'inheritedStrings'],
+        compute({strings, inheritedStrings}) {
+          if (!(strings || inheritedStrings)) return null;
           const allStrings = {...inheritedStrings, ...strings};
           return Object.fromEntries(
-            Object.entries(allStrings).map(([k, v]) => [k, escapeHTML(v)])
+            Object.entries(allStrings).map(([k, v]) => [k, this.escapeHTML(v)])
           );
         },
       },
@@ -206,6 +202,18 @@ export class Language extends Thing {
     }
   }
 
+  escapeHTML(string) {
+    // https://html.spec.whatwg.org/multipage/parsing.html#escapingString
+
+    string = string
+      .replaceAll('&', '&')
+      .replaceAll('\u00a0', ' ')
+      .replaceAll('<', '&lt;')
+      .replaceAll('>', '&gt;');
+
+    return string;
+  }
+
   getUnitForm(value) {
     this.assertIntlAvailable('intl_pluralCardinal');
     return this.intl_pluralCardinal.select(value);
@@ -428,14 +436,9 @@ export class Language extends Thing {
   // html.Tag objects - gets left as-is, preserving the value exactly as it's
   // provided.
   #sanitizeValueForInsertion(value) {
-    const escapeHTML = CacheableObject.getUpdateValue(this, 'escapeHTML');
-    if (!escapeHTML) {
-      throw new Error(`escapeHTML unavailable`);
-    }
-
     switch (typeof value) {
       case 'string':
-        return escapeHTML(value);
+        return this.escapeHTML(value);
 
       case 'number':
       case 'boolean':