@symbo.ls/brender 3.14.678 → 3.14.680

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/index.js CHANGED
@@ -16,6 +16,9 @@ import { trimSpriteToPage, classRulesForPage, markupClasses, trimVariablesToPage
16
16
  // page's faces name (`smbls build` maps file: URLs into its output) marks the
17
17
  // sheet again.
18
18
  import { markFacesSheet, facesSheetMarks } from './faces.js'
19
+ // The faces a page's elements draw (XMA r12 results, item 2): `smbls build`
20
+ // inlines and awaits only those.
21
+ import { drawnFaces } from './drawnFaces.js'
19
22
 
20
23
  export {
21
24
  createEnv,
@@ -48,7 +51,8 @@ export {
48
51
  trimVariablesToPage,
49
52
  stylesheetRules,
50
53
  markFacesSheet,
51
- facesSheetMarks
54
+ facesSheetMarks,
55
+ drawnFaces
52
56
  }
53
57
 
54
58
  export default {
@@ -82,5 +86,6 @@ export default {
82
86
  trimVariablesToPage,
83
87
  stylesheetRules,
84
88
  markFacesSheet,
85
- facesSheetMarks
89
+ facesSheetMarks,
90
+ drawnFaces
86
91
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbo.ls/brender",
3
- "version": "3.14.678",
3
+ "version": "3.14.680",
4
4
  "license": "CC-BY-NC-4.0",
5
5
  "type": "module",
6
6
  "module": "./dist/esm/index.js",
@@ -30,6 +30,11 @@
30
30
  "development": "./faces.js",
31
31
  "import": "./dist/esm/faces.js",
32
32
  "default": "./dist/esm/faces.js"
33
+ },
34
+ "./drawnFaces": {
35
+ "development": "./drawnFaces.js",
36
+ "import": "./dist/esm/drawnFaces.js",
37
+ "default": "./dist/esm/drawnFaces.js"
33
38
  }
34
39
  },
35
40
  "source": "index.js",
@@ -52,17 +57,17 @@
52
57
  },
53
58
  "dependencies": {
54
59
  "@symbo.ls/css": "^3.14.782",
55
- "@symbo.ls/default-config": "^3.14.789",
56
- "@symbo.ls/element": "^3.14.818",
57
- "@symbo.ls/fetch": "^3.14.674",
58
- "@symbo.ls/helmet": "^3.14.673",
59
- "@symbo.ls/scratch": "^3.14.796",
60
- "@symbo.ls/utils": "^3.14.854",
60
+ "@symbo.ls/default-config": "^3.14.794",
61
+ "@symbo.ls/element": "^3.14.823",
62
+ "@symbo.ls/fetch": "^3.14.678",
63
+ "@symbo.ls/helmet": "^3.14.674",
64
+ "@symbo.ls/scratch": "^3.14.799",
65
+ "@symbo.ls/utils": "^3.14.859",
61
66
  "esbuild": "^0.28.1",
62
67
  "linkedom": "^0.16.8"
63
68
  },
64
69
  "peerDependencies": {
65
- "smbls": "^3.14.860"
70
+ "smbls": "^3.14.869"
66
71
  },
67
72
  "optionalDependencies": {
68
73
  "@symbo.ls/funcql": "^3.14.0"
package/render.js CHANGED
@@ -1063,6 +1063,19 @@ const renderTimeoutOf = (value) => {
1063
1063
  return Math.min(value, TIMER_MAX)
1064
1064
  }
1065
1065
 
1066
+ // `options.search`: the query of the address the page is rendered at (S1,
1067
+ // final-landing 2026-10-28: the landing's agent view, `?view=agent`, read by
1068
+ // its app at init). '?a=b', or 'a=b'; undefined, null, '' or '?' for none —
1069
+ // then the location is as it was before the option, byte for byte. A hash
1070
+ // is no part of it.
1071
+ const renderSearchOf = (value) => {
1072
+ if (value === undefined || value === null || value === '' || value === '?') return ''
1073
+ if (typeof value !== 'string' || value.includes('#')) {
1074
+ throw new TypeError(`brender: options.search is a query string ('?view=agent'), without a hash — not ${JSON.stringify(value)}`)
1075
+ }
1076
+ return value.charAt(0) === '?' ? value : '?' + value
1077
+ }
1078
+
1066
1079
  const renderTimeoutError = (options, timeout) => {
1067
1080
  const route = options.route || '/'
1068
1081
  const pathname = options.pathname || route
@@ -1105,6 +1118,8 @@ const once = (fn) => {
1105
1118
  * @param {object} [options]
1106
1119
  * @param {string} [options.route='/'] - The route/page to render
1107
1120
  * @param {string} [options.pathname] - The address the page is rendered at (default: the route)
1121
+ * @param {string} [options.search] - That address's query ('?view=agent'): the
1122
+ * render's location.search (and href); none by default
1108
1123
  * @param {object} [options.state] - State overrides
1109
1124
  * @param {object} [options.context] - Additional context overrides
1110
1125
  * @param {boolean} [options.prefetch=false] - Fetch table/RPC labels first and wait for the page's requests
@@ -1116,6 +1131,7 @@ export const render = (data, options = {}) => {
1116
1131
  let timeout
1117
1132
  try {
1118
1133
  timeout = renderTimeoutOf(options.timeout)
1134
+ renderSearchOf(options.search)
1119
1135
  } catch (err) {
1120
1136
  return Promise.reject(err)
1121
1137
  }
@@ -1148,18 +1164,20 @@ const renderOnce = async (data, options, turn) => {
1148
1164
  const { route = '/', pathname, state: stateOverrides, context: contextOverrides, prefetch = false, lazyGroups } = options
1149
1165
  // pathname is the actual URL path (e.g. /podcast/abc-123), route is the page pattern (e.g. /podcast/:id)
1150
1166
  const locationPath = pathname || route
1167
+ // its query ('' for none; checked in render())
1168
+ const locationSearch = renderSearchOf(options.search)
1151
1169
 
1152
1170
  // This render's diagnostics (see `DIAG`), open before its first request.
1153
1171
  trackFetches()
1154
1172
  const diag = openRenderRecord(DIAG, () => ({ failures: [], labelKeys: new Set(), tainted: false }))
1155
1173
  try {
1156
- return await renderWithDiagnostics(withRevivedDefaultLang(data), { route, locationPath, stateOverrides, contextOverrides, prefetch, lazyGroups }, diag.record, turn)
1174
+ return await renderWithDiagnostics(withRevivedDefaultLang(data), { route, locationPath, locationSearch, stateOverrides, contextOverrides, prefetch, lazyGroups }, diag.record, turn)
1157
1175
  } finally {
1158
1176
  diag.close()
1159
1177
  }
1160
1178
  }
1161
1179
 
1162
- const renderWithDiagnostics = async (data, { route, locationPath, stateOverrides, contextOverrides, prefetch, lazyGroups }, diag, turn) => {
1180
+ const renderWithDiagnostics = async (data, { route, locationPath, locationSearch, stateOverrides, contextOverrides, prefetch, lazyGroups }, diag, turn) => {
1163
1181
  // After every wait: a render abandoned at its timeout stops here (see
1164
1182
  // "One render at a time").
1165
1183
  const live = () => {
@@ -1199,6 +1217,13 @@ const renderWithDiagnostics = async (data, { route, locationPath, stateOverrides
1199
1217
 
1200
1218
  // Set route on location so the router picks it up
1201
1219
  window.location.pathname = locationPath
1220
+ // The address's query (`options.search`): page code reads it as in a
1221
+ // browser at that address — location.search, and href with it. None: the
1222
+ // location as before (href stays the origin's).
1223
+ if (locationSearch) {
1224
+ window.location.search = locationSearch
1225
+ window.location.href = window.location.origin + locationPath + locationSearch
1226
+ }
1202
1227
 
1203
1228
  // globalThis.document/location for the bundled smbls code (which uses
1204
1229
  // `window = globalThis`) during SSR, and the render's own storage behind
@@ -1894,6 +1919,7 @@ export const replaceEmotionCSS = (html, newCSS) => {
1894
1919
  * @param {object} data - Full project data
1895
1920
  * @param {object} [options]
1896
1921
  * @param {string} [options.route='/'] - Route to render
1922
+ * @param {string} [options.search] - The query of the address (see render())
1897
1923
  * @param {number|false} [options.timeout] - render()'s time limit (30 s by default)
1898
1924
  * @returns {Promise<{ html: string, css: string, resetCss: string, fontLinks: string, metadata: object, brKeyCount: number }>}
1899
1925
  */
@@ -1901,11 +1927,11 @@ export const renderRoute = async (data, options = {}) => {
1901
1927
  // `prefetch: false` fetches no table/RPC labels first and does not wait for
1902
1928
  // the page's requests — the publish-time pre-render (smbls publish →
1903
1929
  // ssrCache) renders data-free.
1904
- const { route = '/', pathname, prefetch = true, timeout } = options
1930
+ const { route = '/', pathname, search, prefetch = true, timeout } = options
1905
1931
 
1906
1932
  // Use the full render pipeline which handles polyglot, prefetch, emotion, etc.
1907
1933
  // Pass pathname so the virtual DOM location reflects the actual URL (for dynamic routes)
1908
- const result = await render(data, { route, pathname, prefetch, timeout })
1934
+ const result = await render(data, { route, pathname, search, prefetch, timeout })
1909
1935
  if (!result) return null
1910
1936
 
1911
1937
  const ds = data.designSystem || {}
@@ -2011,6 +2037,8 @@ const collectFetchedState = (element) => {
2011
2037
  * The result then carries `shell: true`.
2012
2038
  * @param {number|false} [options.timeout] - render()'s time limit (30 s by
2013
2039
  * default; 0 or false: none) — see render()
2040
+ * @param {string} [options.search] - The query of the address the page is
2041
+ * rendered at ('?view=agent'; see render()); none by default
2014
2042
  * @param {string|number} [options.stamp] - The build's data stamp, written into
2015
2043
  * the page (see buildStamp); default: the render time as an ISO string
2016
2044
  * @param {number} [options.time] - The build time in ms (see buildStamp);
@@ -2039,7 +2067,7 @@ const collectFetchedState = (element) => {
2039
2067
  * @returns {Promise<{ html: string, route: string, brKeyCount: number, shell?: true }>}
2040
2068
  */
2041
2069
  export const renderPage = async (data, route = '/', options = {}) => {
2042
- const { lang, themeColor, isr, hydrate = true, prefetch = true, shell, adoptDom = false, pathname, eagerImages = EAGER_IMAGES_DEFAULT, preloadScripts = true, nonce, timeout, stamp, time, spriteIcons = 'all', cssClasses = 'all', cssVariables = 'all', registryFormat = 'paths', lazyGroups, paint } = options
2070
+ const { lang, themeColor, isr, hydrate = true, prefetch = true, shell, adoptDom = false, pathname, search, eagerImages = EAGER_IMAGES_DEFAULT, preloadScripts = true, nonce, timeout, stamp, time, spriteIcons = 'all', cssClasses = 'all', cssVariables = 'all', registryFormat = 'paths', lazyGroups, paint } = options
2043
2071
  const whole = paintsWhole(paint)
2044
2072
  const nonceAttr = nonceAttribute(nonce)
2045
2073
 
@@ -2054,7 +2082,7 @@ export const renderPage = async (data, route = '/', options = {}) => {
2054
2082
  // canonical/og:url built from it read it. Without it a route was rendered
2055
2083
  // at its own pattern: the `/*` page wrote a `/*` canonical into 404.html
2056
2084
  // (xma.info report, brender build item 7).
2057
- const result = await render(data, { route, pathname, prefetch, timeout, lazyGroups })
2085
+ const result = await render(data, { route, pathname, search, prefetch, timeout, lazyGroups })
2058
2086
  if (!result) return null
2059
2087
 
2060
2088
  const metadata = { ...result.metadata }