check:facet-cascade: read the facet rail by brace depth, so getter titles stop blinding it
The gate reads facetRail out of dashboard.config.js with /\{[^{}]*\}/, which
matches only objects with no braces inside. 53e2c662 translated the rail titles
as getters (get title() { return tStatic(...) || 'People' }), so the four drill
sections stopped parsing. The bus was then built with no hierarchy, and the gate
reported 21 'orphaned child' failures in a dashboard that cascades correctly
(the real one reads the live config object, never this parser). Red on main
since 53e2c662 (bisected by swapping the gate's only two inputs: 7f700935 OK,
53e2c662 FAIL).
The parser now splits the array into top-level objects by brace depth, skipping
quoted strings, and throws if a section has neither a drill nor a facet. So a
parse miss is an error, never a false pass or a false fail.
Headless: it passes on main's real files. With a poisoned bus (configureHierarchy
installs no hierarchy) it FAILS; restored, it passes.
This commit is contained in:
parent
9888c4bcc9
commit
1228cd1f1a
1 changed files with 18 additions and 5 deletions
|
|
@ -114,11 +114,20 @@ function readFacetRail(src) {
|
|||
if (end < 0) throw new Error('facetRail array is unterminated')
|
||||
const body = src.slice(open, end + 1)
|
||||
const sections = []
|
||||
// one entry per `{ … }` object at the top level of that array
|
||||
const objRe = /\{[^{}]*\}/g
|
||||
let m
|
||||
while ((m = objRe.exec(body))) {
|
||||
const obj = m[0]
|
||||
// One entry per object at the TOP level of that array, found by brace depth. A `{[^{}]*}` regex
|
||||
// matched only objects with no braces inside, and 53e2c662 gave every section a getter title
|
||||
// (`get title() { return tStatic(…) || 'People' }`): the four drill sections stopped parsing, the
|
||||
// bus was built with no hierarchy, and this gate reported 21 "orphans" in a dashboard that cascades
|
||||
// correctly. Braces inside quoted strings are skipped, for the same reason.
|
||||
const objs = []
|
||||
for (let i = 1, d = 0, st = -1, q = null; i < body.length - 1; i++) {
|
||||
const c = body[i]
|
||||
if (q) { if (c === '\\') i++; else if (c === q) q = null; continue }
|
||||
if (c === "'" || c === '"' || c === '`') { q = c; continue }
|
||||
if (c === '{') { if (d === 0) st = i; d++ }
|
||||
else if (c === '}') { d--; if (d === 0 && st >= 0) { objs.push(body.slice(st, i + 1)); st = -1 } }
|
||||
}
|
||||
for (const obj of objs) {
|
||||
const id = /id:\s*'([^']+)'/.exec(obj)?.[1]
|
||||
const drillRaw = /drill:\s*\[([^\]]*)\]/.exec(obj)?.[1]
|
||||
const drill = drillRaw ? [...drillRaw.matchAll(/'([^']+)'/g)].map((x) => x[1]) : undefined
|
||||
|
|
@ -126,6 +135,10 @@ function readFacetRail(src) {
|
|||
sections.push({ id, drill, facet })
|
||||
}
|
||||
if (!sections.length) throw new Error('no facetRail sections parsed')
|
||||
// A section with neither a drill nor a facet is one this parser could not read: fail loudly
|
||||
// rather than test a hierarchy that is not the dashboard's.
|
||||
const unread = sections.filter((x) => !x.id || (!x.drill && !x.facet))
|
||||
if (unread.length) throw new Error(`facetRail: ${unread.length} section(s) could not be read (${unread.map((x) => x.id || '?').join(', ')})`)
|
||||
return sections
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue