From a10e27f93c8e7965c51b2e0372a7f4b19640452e Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 7 Nov 2023 08:09:14 -0400 Subject: upd8: infer custom default language from internal default code --- src/upd8.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/upd8.js b/src/upd8.js index c011b660..7d7e48b9 100755 --- a/src/upd8.js +++ b/src/upd8.js @@ -1233,11 +1233,6 @@ async function main() { timeStart: Date.now(), }); - const customDefaultLanguage = - (wikiData.wikiInfo.defaultLanguage - ? languages[wikiData.wikiInfo.defaultLanguage] - : null); - let finalDefaultLanguage; let finalDefaultLanguageWatcher; let finalDefaultLanguageAnnotation; @@ -1262,14 +1257,25 @@ async function main() { return false; } - customDefaultLanguage.inheritedStrings = internalDefaultLanguage.strings; - logInfo`Applying new default strings from custom ${customDefaultLanguage.code} language file.`; + // The custom default language will be the new one providing fallback strings + // for other languages, but on its own, it still might not be a complete list + // of strings. So it falls back to the internal default language - which won't + // otherwise be presented on the site. + customDefaultLanguage.inheritedStrings = internalDefaultLanguage.strings; + finalDefaultLanguage = customDefaultLanguage; finalDefaultLanguageWatcher = customLanguageWatchers.find(({language}) => language === customDefaultLanguage); finalDefaultLanguageAnnotation = `using wiki-specified custom default language`; + } else if (languages[internalDefaultLanguage.code]) { + const customDefaultLanguage = languages[internalDefaultLanguage.code]; + customDefaultLanguage.inheritedStrings = internalDefaultLanguage.strings; + finalDefaultLanguage = customDefaultLanguage; + finalDefaultLanguageWatcher = + customLanguageWatchers.find(({language}) => language === customDefaultLanguage); + finalDefaultLanguageAnnotation = `using inferred custom default language`; } else { languages[internalDefaultLanguage.code] = internalDefaultLanguage; -- cgit 1.3.0-6-gf8a5 From 4001e3c16c0acacc6c6d89589e57996701058dc0 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 7 Nov 2023 08:17:01 -0400 Subject: upd8: handle internal language updates in custom default language --- src/upd8.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/upd8.js b/src/upd8.js index 7d7e48b9..91f9a090 100755 --- a/src/upd8.js +++ b/src/upd8.js @@ -1259,19 +1259,12 @@ async function main() { logInfo`Applying new default strings from custom ${customDefaultLanguage.code} language file.`; - // The custom default language will be the new one providing fallback strings - // for other languages, but on its own, it still might not be a complete list - // of strings. So it falls back to the internal default language - which won't - // otherwise be presented on the site. - customDefaultLanguage.inheritedStrings = internalDefaultLanguage.strings; - finalDefaultLanguage = customDefaultLanguage; finalDefaultLanguageWatcher = customLanguageWatchers.find(({language}) => language === customDefaultLanguage); finalDefaultLanguageAnnotation = `using wiki-specified custom default language`; } else if (languages[internalDefaultLanguage.code]) { const customDefaultLanguage = languages[internalDefaultLanguage.code]; - customDefaultLanguage.inheritedStrings = internalDefaultLanguage.strings; finalDefaultLanguage = customDefaultLanguage; finalDefaultLanguageWatcher = customLanguageWatchers.find(({language}) => language === customDefaultLanguage); @@ -1284,6 +1277,12 @@ async function main() { finalDefaultLanguageAnnotation = `no custom default language specified`; } + const inheritStringsFromInternalLanguage = () => { + if (finalDefaultLanguage === internalDefaultLanguage) return; + const {strings: inheritedStrings} = internalDefaultLanguage; + Object.assign(finalDefaultLanguage, {inheritedStrings}); + }; + const inheritStringsFromDefaultLanguage = () => { const {strings: inheritedStrings} = finalDefaultLanguage; for (const language of Object.values(languages)) { @@ -1292,8 +1291,19 @@ async function main() { } }; - inheritStringsFromDefaultLanguage(); + // The custom default language, if set, will be the new one providing fallback + // strings for other languages. But on its own, it still might not be a complete + // list of strings - so it falls back to the internal default language, which + // won't otherwise be presented in the build. + if (finalDefaultLanguage !== internalDefaultLanguage) { + inheritStringsFromInternalLanguage(); + internalDefaultLanguageWatcher.on('update', () => { + inheritStringsFromInternalLanguage(); + inheritStringsFromDefaultLanguage(); + }); + } + inheritStringsFromDefaultLanguage(); finalDefaultLanguageWatcher.on('update', () => { inheritStringsFromDefaultLanguage(); }); -- cgit 1.3.0-6-gf8a5 From 8901b8bb4c9966945519de9a0b7115fb9c5a9564 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 7 Nov 2023 08:19:09 -0400 Subject: upd8: quick eslint fixes --- src/upd8.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/upd8.js b/src/upd8.js index 91f9a090..ea4629ee 100755 --- a/src/upd8.js +++ b/src/upd8.js @@ -39,7 +39,7 @@ import {fileURLToPath} from 'node:url'; import wrap from 'word-wrap'; import {displayCompositeCacheAnalysis} from '#composite'; -import {processLanguageFile, watchLanguageFile} from '#language'; +import {watchLanguageFile} from '#language'; import {isMain, traverse} from '#node-utils'; import bootRepl from '#repl'; import {empty, showAggregate, withEntries} from '#sugar'; @@ -56,7 +56,6 @@ import { logError, parseOptions, progressCallAll, - progressPromiseAll, } from '#cli'; import genThumbs, { -- cgit 1.3.0-6-gf8a5 From 505a2bf05216de928d667655ee2670ad6c3ff46d Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 7 Nov 2023 08:27:19 -0400 Subject: upd8: stub --no-input option --- src/upd8.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/upd8.js b/src/upd8.js index ea4629ee..40683744 100755 --- a/src/upd8.js +++ b/src/upd8.js @@ -290,6 +290,11 @@ async function main() { type: 'flag', }, + 'no-input': { + help: `Don't wait on input from stdin - assume the device is headless`, + type: 'flag', + }, + // Want sweet, sweet trace8ack info in aggreg8te error messages? This // will print all the juicy details (or at least the first relevant // line) right to your output, 8ut also pro8a8ly give you a headache @@ -456,6 +461,7 @@ async function main() { const thumbsOnly = cliOptions['thumbs-only'] ?? false; const skipReferenceValidation = cliOptions['skip-reference-validation'] ?? false; const noBuild = cliOptions['no-build'] ?? false; + const noInput = cliOptions['no-input'] ?? false; showStepStatusSummary = cliOptions['show-step-summary'] ?? false; -- cgit 1.3.0-6-gf8a5 From 7fa4f92c8a41754e198ade96a7d5d0dd5b0aa59e Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 7 Nov 2023 09:12:47 -0400 Subject: upd8: add --no-language-reloading option, default for static-build --- src/data/language.js | 2 +- src/upd8.js | 318 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 204 insertions(+), 116 deletions(-) (limited to 'src') diff --git a/src/data/language.js b/src/data/language.js index 99eaa58f..15c11933 100644 --- a/src/data/language.js +++ b/src/data/language.js @@ -17,7 +17,7 @@ import { const {Language} = T; -export function processLanguageSpec(spec, {existingCode = null}) { +export function processLanguageSpec(spec, {existingCode = null} = {}) { const { 'meta.languageCode': code, 'meta.languageName': name, diff --git a/src/upd8.js b/src/upd8.js index 40683744..764ee0c3 100755 --- a/src/upd8.js +++ b/src/upd8.js @@ -39,7 +39,7 @@ import {fileURLToPath} from 'node:url'; import wrap from 'word-wrap'; import {displayCompositeCacheAnalysis} from '#composite'; -import {watchLanguageFile} from '#language'; +import {processLanguageFile, watchLanguageFile} from '#language'; import {isMain, traverse} from '#node-utils'; import bootRepl from '#repl'; import {empty, showAggregate, withEntries} from '#sugar'; @@ -295,6 +295,13 @@ async function main() { type: 'flag', }, + 'no-language-reloading': { + help: `Don't reload language files while the build is running\n\nApplied by default for --static-build`, + type: 'flag', + }, + + 'no-language-reload': {alias: 'no-language-reloading'}, + // Want sweet, sweet trace8ack info in aggreg8te error messages? This // will print all the juicy details (or at least the first relevant // line) right to your output, 8ut also pro8a8ly give you a headache @@ -462,6 +469,7 @@ async function main() { const skipReferenceValidation = cliOptions['skip-reference-validation'] ?? false; const noBuild = cliOptions['no-build'] ?? false; const noInput = cliOptions['no-input'] ?? false; + let noLanguageReloading = cliOptions['no-language-reloading'] ?? null; // Will get default later. showStepStatusSummary = cliOptions['show-step-summary'] ?? false; @@ -572,12 +580,24 @@ async function main() { } if (noBuild) { + logInfo`Won't generate any site or page files this run (--no-build passed).`; + Object.assign(stepStatusSummary.performBuild, { status: STATUS_NOT_APPLICABLE, annotation: `--no-build provided`, }); + } else if (usingDefaultBuildMode) { + logInfo`No build mode specified, will use default: ${selectedBuildModeFlag}`; + } else { + logInfo`Will use specified build mode: ${selectedBuildModeFlag}`; } + noLanguageReloading ??= + ({ + 'static-build': true, + 'live-dev-server': false, + })[selectedBuildModeFlag]; + if (skipThumbs && thumbsOnly) { logInfo`Well, you've put yourself rather between a roc and a hard place, hmmmm?`; return false; @@ -771,14 +791,6 @@ async function main() { thumbsCache = result.cache; } - if (noBuild) { - logInfo`Not generating any site or page files this run (--no-build passed).`; - } else if (usingDefaultBuildMode) { - logInfo`No build mode specified, using default: ${selectedBuildModeFlag}`; - } else { - logInfo`Using specified build mode: ${selectedBuildModeFlag}`; - } - if (showInvalidPropertyAccesses) { CacheableObject.DEBUG_SLOW_TRACK_INVALID_PROPERTIES = true; } @@ -1090,35 +1102,54 @@ async function main() { }); let internalDefaultLanguage; + let internalDefaultLanguageWatcher; - const internalDefaultLanguageWatcher = - watchLanguageFile(path.join(__dirname, DEFAULT_STRINGS_FILE)); + const internalDefaultStringsFile = path.join(__dirname, DEFAULT_STRINGS_FILE); - try { - await new Promise((resolve, reject) => { - const watcher = internalDefaultLanguageWatcher; - - const onReady = () => { - watcher.removeListener('ready', onReady); - watcher.removeListener('error', onError); - resolve(); - }; - - const onError = error => { - watcher.removeListener('ready', onReady); - watcher.removeListener('error', onError); - watcher.close(); - reject(error); - }; - - watcher.on('ready', onReady); - watcher.on('error', onError); - }); + let errorLoadingInternalDefaultLanguage = false; - internalDefaultLanguage = internalDefaultLanguageWatcher.language; - } catch (_error) { - // No need to display the error here - it's already printed by - // watchLanguageFile. + if (noLanguageReloading) { + internalDefaultLanguageWatcher = null; + + try { + internalDefaultLanguage = await processLanguageFile(internalDefaultStringsFile); + } catch (error) { + niceShowAggregate(error); + errorLoadingInternalDefaultLanguage = true; + } + } else { + internalDefaultLanguageWatcher = watchLanguageFile(internalDefaultStringsFile); + + try { + await new Promise((resolve, reject) => { + const watcher = internalDefaultLanguageWatcher; + + const onReady = () => { + watcher.removeListener('ready', onReady); + watcher.removeListener('error', onError); + resolve(); + }; + + const onError = error => { + watcher.removeListener('ready', onReady); + watcher.removeListener('error', onError); + watcher.close(); + reject(error); + }; + + watcher.on('ready', onReady); + watcher.on('error', onError); + }); + + internalDefaultLanguage = internalDefaultLanguageWatcher.language; + } catch (_error) { + // No need to display the error here - it's already printed by + // watchLanguageFile. + errorLoadingInternalDefaultLanguage = true; + } + } + + if (errorLoadingInternalDefaultLanguage) { logError`There was an error reading the internal language file.`; fileIssue(); @@ -1131,8 +1162,10 @@ async function main() { return false; } - // Bypass node.js special-case handling for uncaught error events - internalDefaultLanguageWatcher.on('error', () => {}); + if (!noLanguageReloading) { + // Bypass node.js special-case handling for uncaught error events + internalDefaultLanguageWatcher.on('error', () => {}); + } Object.assign(stepStatusSummary.loadInternalDefaultLanguage, { status: STATUS_DONE_CLEAN, @@ -1153,81 +1186,118 @@ async function main() { pathStyle: 'device', }); - customLanguageWatchers = - languageDataFiles.map(file => { - const watcher = watchLanguageFile(file); + let errorLoadingCustomLanguages = false; - // Bypass node.js special-case handling for uncaught error events - watcher.on('error', () => {}); + if (noLanguageReloading) { + languages = {}; - return watcher; - }); + const results = + await Promise.allSettled( + languageDataFiles + .map(file => processLanguageFile(file))); - const waitingOnWatchers = new Set(customLanguageWatchers); - - const initialResults = - await Promise.allSettled( - customLanguageWatchers.map(watcher => - new Promise((resolve, reject) => { - const onReady = () => { - watcher.removeListener('ready', onReady); - watcher.removeListener('error', onError); - waitingOnWatchers.delete(watcher); - resolve(); - }; - - const onError = error => { - watcher.removeListener('ready', onReady); - watcher.removeListener('error', onError); - reject(error); - }; - - watcher.on('ready', onReady); - watcher.on('error', onError); - }))); - - if (initialResults.some(({status}) => status === 'rejected')) { - logWarn`There were errors loading custom languages from the language path`; - logWarn`provided: ${langPath}`; - - if (noInput) { - logError`Failed to load language files. Please investigate these, or don't provide`; - logError`--lang-path (or HSMUSIC_LANG) and build again.`; - - Object.assign(stepStatusSummary.loadLanguageFiles, { - status: STATUS_FATAL_ERROR, - annotation: `see log for details`, - timeEnd: Date.now(), + for (const {status, value: language, reason: error} of results) { + if (status === 'rejected') { + errorLoadingCustomLanguages = true; + niceShowAggregate(error); + } else { + languages[language.code] = language; + } + } + } else watchCustomLanguages: { + customLanguageWatchers = + languageDataFiles.map(file => { + const watcher = watchLanguageFile(file); + + // Bypass node.js special-case handling for uncaught error events + watcher.on('error', () => {}); + + return watcher; }); - return false; - } + const waitingOnWatchers = new Set(customLanguageWatchers); + + const initialResults = + await Promise.allSettled( + customLanguageWatchers + .map(watcher => new Promise((resolve, reject) => { + const onReady = () => { + watcher.removeListener('ready', onReady); + watcher.removeListener('error', onError); + waitingOnWatchers.delete(watcher); + resolve(); + }; + + const onError = error => { + watcher.removeListener('ready', onReady); + watcher.removeListener('error', onError); + reject(error); + }; + + watcher.on('ready', onReady); + watcher.on('error', onError); + }))); + + if (initialResults.some(({status}) => status === 'rejected')) { + logWarn`There were errors loading custom languages from the language path`; + logWarn`provided: ${langPath}`; + + if (noInput) { + internalDefaultLanguageWatcher.close(); + + for (const watcher of Object.values(customLanguageWatchers)) { + watcher.close(); + } - logWarn`The build should start automatically if you investigate these.`; - logWarn`Or, exit by pressing ^C here (control+C) and run again without`; - logWarn`providing ${'--lang-path'} (or ${'HSMUSIC_LANG'}) to build without custom`; - logWarn`languages.`; - - await new Promise(resolve => { - for (const watcher of waitingOnWatchers) { - watcher.once('ready', () => { - waitingOnWatchers.remove(watcher); - if (empty(waitingOnWatchers)) { - resolve(); - } - }); + errorLoadingCustomLanguages = true; + break watchCustomLanguages; } - }); + + logWarn`The build should start automatically if you investigate these.`; + logWarn`Or, exit by pressing ^C here (control+C) and run again without`; + logWarn`providing ${'--lang-path'} (or ${'HSMUSIC_LANG'}) to build without custom`; + logWarn`languages.`; + + await new Promise(resolve => { + for (const watcher of waitingOnWatchers) { + watcher.once('ready', () => { + waitingOnWatchers.remove(watcher); + if (empty(waitingOnWatchers)) { + resolve(); + } + }); + } + }); + } + + languages = + Object.fromEntries( + customLanguageWatchers + .map(({language}) => [language.code, language])); } - languages = - Object.fromEntries( - customLanguageWatchers - .map(watcher => [watcher.language.code, watcher.language])); + if (errorLoadingCustomLanguages) { + logError`Failed to load language files. Please investigate these, or don't provide`; + logError`--lang-path (or HSMUSIC_LANG) and build again.`; + + Object.assign(stepStatusSummary.loadLanguageFiles, { + status: STATUS_FATAL_ERROR, + annotation: `see log for details`, + timeEnd: Date.now(), + }); + + return false; + } Object.assign(stepStatusSummary.loadLanguageFiles, { status: STATUS_DONE_CLEAN, timeEnd: Date.now(), + annotation: + (noLanguageReloading + ? (selectedBuildModeFlag === 'static-build' + ? `loaded statically, default for --static-build` + : `loaded statically, --no-language-reloading provided`) + : `watching for changes`), }); } else { languages = {}; @@ -1265,24 +1335,40 @@ async function main() { logInfo`Applying new default strings from custom ${customDefaultLanguage.code} language file.`; finalDefaultLanguage = customDefaultLanguage; - finalDefaultLanguageWatcher = - customLanguageWatchers.find(({language}) => language === customDefaultLanguage); finalDefaultLanguageAnnotation = `using wiki-specified custom default language`; + + if (!noLanguageReloading) { + finalDefaultLanguageWatcher = + customLanguageWatchers + .find(({language}) => language === customDefaultLanguage); + } } else if (languages[internalDefaultLanguage.code]) { const customDefaultLanguage = languages[internalDefaultLanguage.code]; + finalDefaultLanguage = customDefaultLanguage; - finalDefaultLanguageWatcher = - customLanguageWatchers.find(({language}) => language === customDefaultLanguage); finalDefaultLanguageAnnotation = `using inferred custom default language`; + + if (!noLanguageReloading) { + finalDefaultLanguageWatcher = + customLanguageWatchers + .find(({language}) => language === customDefaultLanguage); + } } else { languages[internalDefaultLanguage.code] = internalDefaultLanguage; finalDefaultLanguage = internalDefaultLanguage; - finalDefaultLanguageWatcher = internalDefaultLanguageWatcher; finalDefaultLanguageAnnotation = `no custom default language specified`; + + if (!noLanguageReloading) { + finalDefaultLanguageWatcher = internalDefaultLanguageWatcher; + } } const inheritStringsFromInternalLanguage = () => { + // The custom default language, if set, will be the new one providing fallback + // strings for other languages. But on its own, it still might not be a complete + // list of strings - so it falls back to the internal default language, which + // won't otherwise be presented in the build. if (finalDefaultLanguage === internalDefaultLanguage) return; const {strings: inheritedStrings} = internalDefaultLanguage; Object.assign(finalDefaultLanguage, {inheritedStrings}); @@ -1296,22 +1382,24 @@ async function main() { } }; - // The custom default language, if set, will be the new one providing fallback - // strings for other languages. But on its own, it still might not be a complete - // list of strings - so it falls back to the internal default language, which - // won't otherwise be presented in the build. if (finalDefaultLanguage !== internalDefaultLanguage) { inheritStringsFromInternalLanguage(); - internalDefaultLanguageWatcher.on('update', () => { - inheritStringsFromInternalLanguage(); - inheritStringsFromDefaultLanguage(); - }); } inheritStringsFromDefaultLanguage(); - finalDefaultLanguageWatcher.on('update', () => { - inheritStringsFromDefaultLanguage(); - }); + + if (!noLanguageReloading) { + if (finalDefaultLanguage !== internalDefaultLanguage) { + internalDefaultLanguageWatcher.on('update', () => { + inheritStringsFromInternalLanguage(); + inheritStringsFromDefaultLanguage(); + }); + } + + finalDefaultLanguageWatcher.on('update', () => { + inheritStringsFromDefaultLanguage(); + }); + } logInfo`Loaded language strings: ${Object.keys(languages).join(', ')}`; -- cgit 1.3.0-6-gf8a5