@symbo.ls/utils 3.14.787 → 3.14.788

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @symbo.ls/utils
2
2
 
3
+ ## 3.14.788
4
+
5
+ ### Patch Changes
6
+
7
+ - Server renders run one at a time per process, and a page at /<lang>/… starts in that language.
8
+
9
+ - brender: `render()` (and `renderRoute` / `renderPage`) run one at a time per process; a per-render `timeout` (default 30 s, `0`/`false` turns it off) rejects with `BRENDER_RENDER_TIMEOUT`, puts the render's globals back and lets the next render start.
10
+ - brender + mermaid: before the app starts, the render stores the address's language (the first path segment, when it is one of the project's languages) under polyglot's key, so the fetch seed is recorded in the language the browser asks in; the served page's start-up script stores the page's language. One helper in utils (`polyglotAddressLang`, `polyglotStartupScript`).
11
+ - cli: the publish pre-render passes its route limit to brender's `timeout`; `symbols.json` `brender.timeout` sets each page's render limit for `smbls build` and `smbls brender`.
12
+
3
13
  ## 3.14.787
4
14
 
5
15
  ### Patch Changes
@@ -1 +1 @@
1
- "use strict";var o=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var l=(t,a)=>{for(var n in a)o(t,n,{get:a[n],enumerable:!0})},_=(t,a,n,s)=>{if(a&&typeof a=="object"||typeof a=="function")for(let e of r(a))!c.call(t,e)&&e!==n&&o(t,e,{get:()=>a[e],enumerable:!(s=L(a,e))||s.enumerable});return t};var p=t=>_(o({},"__esModule",{value:!0}),t);var K={};l(K,{POLYGLOT_LANG_STORAGE_KEY:()=>g,polyglotFallbackLang:()=>G,polyglotLangStorageKey:()=>x});module.exports=p(K);const g="smbls_lang",x=t=>t&&t.storageLangKey||g,G=(t,a)=>t||a&&a.defaultLang||"en";
1
+ "use strict";var f=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var l=(t,e)=>{for(var r in e)f(t,r,{get:e[r],enumerable:!0})},x=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of O(e))!p.call(t,n)&&n!==r&&f(t,n,{get:()=>e[n],enumerable:!(s=y(e,n))||s.enumerable});return t};var N=t=>x(f({},"__esModule",{value:!0}),t);var m={};l(m,{POLYGLOT_LANG_STORAGE_KEY:()=>u,polyglotAddressLang:()=>L,polyglotFallbackLang:()=>S,polyglotLangStorageKey:()=>$,polyglotStartupScript:()=>d});module.exports=N(m);const u="smbls_lang",$=t=>t&&t.storageLangKey||u,S=(t,e)=>t||e&&e.defaultLang||"en",L=(t,e)=>{if(!e)return null;const r=Array.isArray(e.languages)&&e.languages.length?e.languages:Object.keys(e.translations||{}),s=/^\/([^/?#]+)/.exec(String(t||""));if(!s)return null;const n=s[1].toLowerCase();for(const a of r)if(typeof a=="string"&&a.toLowerCase()===n)return a;return null},d=({polyglot:t,translations:e,lang:r,pathname:s,attrs:n=""}={})=>{if(!e||typeof e!="object")return"";const a=t&&t.storagePrefix||"",c=t&&t.storageLangKey||"",g=[];for(const i in e){const o=e[i];o&&typeof o=="object"&&g.push(`localStorage.setItem(${JSON.stringify(a+i)},${JSON.stringify(JSON.stringify(o))})`)}if(c){const i=r||L(s,t)||S(void 0,t);g.push(`if(!localStorage.getItem(${JSON.stringify(c)}))localStorage.setItem(${JSON.stringify(c)},${JSON.stringify(i)})`)}return g.length?`<script${n}>try{${g.join(";")}}catch(e){}<\/script>`:""};
@@ -1 +1 @@
1
- const e="smbls_lang",n=t=>t&&t.storageLangKey||e,o=(t,a)=>t||a&&a.defaultLang||"en";export{e as POLYGLOT_LANG_STORAGE_KEY,o as polyglotFallbackLang,n as polyglotLangStorageKey};
1
+ const f="smbls_lang",L=e=>e&&e.storageLangKey||f,u=(e,t)=>e||t&&t.defaultLang||"en",S=(e,t)=>{if(!t)return null;const g=Array.isArray(t.languages)&&t.languages.length?t.languages:Object.keys(t.translations||{}),r=/^\/([^/?#]+)/.exec(String(e||""));if(!r)return null;const i=r[1].toLowerCase();for(const n of g)if(typeof n=="string"&&n.toLowerCase()===i)return n;return null},y=({polyglot:e,translations:t,lang:g,pathname:r,attrs:i=""}={})=>{if(!t||typeof t!="object")return"";const n=e&&e.storagePrefix||"",c=e&&e.storageLangKey||"",s=[];for(const a in t){const o=t[a];o&&typeof o=="object"&&s.push(`localStorage.setItem(${JSON.stringify(n+a)},${JSON.stringify(JSON.stringify(o))})`)}if(c){const a=g||S(r,e)||u(void 0,e);s.push(`if(!localStorage.getItem(${JSON.stringify(c)}))localStorage.setItem(${JSON.stringify(c)},${JSON.stringify(a)})`)}return s.length?`<script${i}>try{${s.join(";")}}catch(e){}<\/script>`:""};export{f as POLYGLOT_LANG_STORAGE_KEY,S as polyglotAddressLang,u as polyglotFallbackLang,L as polyglotLangStorageKey,y as polyglotStartupScript};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbo.ls/utils",
3
- "version": "3.14.787",
3
+ "version": "3.14.788",
4
4
  "license": "CC-BY-NC-4.0",
5
5
  "type": "module",
6
6
  "module": "./dist/esm/index.js",
package/polyglotLang.js CHANGED
@@ -20,3 +20,65 @@ export const polyglotLangStorageKey = (polyglot) =>
20
20
  */
21
21
  export const polyglotFallbackLang = (stateLang, polyglot) =>
22
22
  stateLang || (polyglot && polyglot.defaultLang) || 'en'
23
+
24
+ /**
25
+ * The language an address names: its first path segment, when that is one of
26
+ * the project's languages (`polyglot.languages`, else the keys of
27
+ * `polyglot.translations`) — `/en/about` with `['ka', 'en']` gives 'en'.
28
+ * Matched without regard to case, returned as configured; null for any other
29
+ * address. A server render (@symbo.ls/brender) starts in it, the way a page's
30
+ * pre-boot script starts the browser in it: stored under
31
+ * polyglotLangStorageKey before the app starts.
32
+ */
33
+ export const polyglotAddressLang = (pathname, polyglot) => {
34
+ if (!polyglot) return null
35
+ const languages = Array.isArray(polyglot.languages) && polyglot.languages.length
36
+ ? polyglot.languages
37
+ : Object.keys(polyglot.translations || {})
38
+ const first = /^\/([^/?#]+)/.exec(String(pathname || ''))
39
+ if (!first) return null
40
+ const segment = first[1].toLowerCase()
41
+ for (const lang of languages) {
42
+ if (typeof lang === 'string' && lang.toLowerCase() === segment) return lang
43
+ }
44
+ return null
45
+ }
46
+
47
+ /**
48
+ * A pre-rendered page's polyglot start-up script, run before the app: the
49
+ * labels the server rendered with, each under `storagePrefix` + its language,
50
+ * and — for a visitor with no language stored yet (`storageLangKey`) — the
51
+ * language the page was rendered in (`lang`), else the language its address
52
+ * names (`pathname`), else the default (polyglotFallbackLang). So the client
53
+ * starts where the server did: on its markup, and on the requests the page's
54
+ * fetch seed recorded. '' without labels.
55
+ *
56
+ * Shared by every server that writes one — @symbo.ls/brender renderPage (an
57
+ * ISR page) and @symbo.ls/mermaid (a publish-time cache entry, a live render)
58
+ * — which each kept a copy that stored the default language.
59
+ *
60
+ * @param {object} options
61
+ * @param {object} [options.polyglot] - the project's polyglot config
62
+ * @param {object} [options.translations] - labels by language
63
+ * @param {string} [options.lang] - the language the page was rendered in
64
+ * @param {string} [options.pathname] - the page's address
65
+ * @param {string} [options.attrs] - attributes for the tag (` nonce="…"`)
66
+ * @returns {string}
67
+ */
68
+ export const polyglotStartupScript = ({ polyglot, translations, lang, pathname, attrs = '' } = {}) => {
69
+ if (!translations || typeof translations !== 'object') return ''
70
+ const storagePrefix = (polyglot && polyglot.storagePrefix) || ''
71
+ const storageLangKey = (polyglot && polyglot.storageLangKey) || ''
72
+ const entries = []
73
+ for (const code in translations) {
74
+ const map = translations[code]
75
+ if (map && typeof map === 'object') {
76
+ entries.push(`localStorage.setItem(${JSON.stringify(storagePrefix + code)},${JSON.stringify(JSON.stringify(map))})`)
77
+ }
78
+ }
79
+ if (storageLangKey) {
80
+ const pageLang = lang || polyglotAddressLang(pathname, polyglot) || polyglotFallbackLang(undefined, polyglot)
81
+ entries.push(`if(!localStorage.getItem(${JSON.stringify(storageLangKey)}))localStorage.setItem(${JSON.stringify(storageLangKey)},${JSON.stringify(pageLang)})`)
82
+ }
83
+ return entries.length ? `<script${attrs}>try{${entries.join(';')}}catch(e){}</script>` : ''
84
+ }