@loadbare/app 0.13.0 → 0.15.0
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/dist/build/assemble.d.ts.map +1 -1
- package/dist/build/assemble.js +31 -1
- package/dist/build/assemble.js.map +1 -1
- package/dist/build/elements.d.ts +12 -2
- package/dist/build/elements.d.ts.map +1 -1
- package/dist/build/elements.js +44 -10
- package/dist/build/elements.js.map +1 -1
- package/dist/core/lb-constants.d.ts +13 -2
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +50 -3
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +52 -8
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +22 -3
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +82 -37
- package/dist/hub/lb-apply.js.map +1 -1
- package/dist/hub/lb-hub.browser.d.ts.map +1 -1
- package/dist/hub/lb-hub.browser.js +382 -26
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/hub/lb-lifecycle.d.ts +40 -0
- package/dist/hub/lb-lifecycle.d.ts.map +1 -0
- package/dist/hub/lb-lifecycle.js +140 -0
- package/dist/hub/lb-lifecycle.js.map +1 -0
- package/dist/server/lb-express.d.ts +13 -3
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +30 -12
- package/dist/server/lb-express.js.map +1 -1
- package/dist/server/lb-server.d.ts +31 -1
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +112 -2
- package/dist/server/lb-server.js.map +1 -1
- package/docs/TECHREF-1.0.md +343 -68
- package/docs/comparison.md +13 -9
- package/docs/possible-ideas.md +152 -26
- package/docs/reference/custom-elements.md +203 -88
- package/docs/reference/data-binding.md +310 -11
- package/docs/reference/page-files.md +76 -3
- package/docs/reference/server.md +20 -0
- package/docs/reference/widgets.md +35 -12
- package/docs/roadmap.md +9 -2
- package/docs/testing.md +2 -2
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +70 -23
- package/skills/loadbare-app/references/TECHREF-1.0.md +343 -68
- package/skills/loadbare-app/references/custom-elements.md +203 -88
- package/skills/loadbare-app/references/data-binding.md +310 -11
- package/skills/loadbare-app/references/page-files.md +76 -3
- package/skills/loadbare-app/references/server.md +20 -0
- package/skills/loadbare-app/references/widgets.md +35 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assemble.d.ts","sourceRoot":"","sources":["../../build/assemble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;
|
|
1
|
+
{"version":3,"file":"assemble.d.ts","sourceRoot":"","sources":["../../build/assemble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAgCH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAgU/C,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,8EAA8E;IAC9E,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACvB;AAED,wBAAsB,QAAQ,CAAC,EAC7B,UAAU,EACV,KAAK,EACL,KAAK,GACN,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAwDtC"}
|
package/dist/build/assemble.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
import { readFile } from "node:fs/promises";
|
|
20
20
|
import { addDefinitions, customElementTags, expandTree, } from "./expand.js";
|
|
21
21
|
import { formatHtml } from "./format.js";
|
|
22
|
-
import { AGGREGATES, ATTR_COUNT, ATTR_GROUP, ATTR_PAGE, ATTR_PAGE_TITLE, ATTR_QUERY, ATTR_REQUEST, ATTR_SHOW, ATTR_URL_LINK, ATTR_URL_PUSH, ATTR_URL_UNKNOWN, DEVELOPER_ATTRIBUTES, HUB_TAG_NAME, LB_RESERVED_PREFIX, SHOW_NOT, } from "../core/lb-constants.js";
|
|
22
|
+
import { AGGREGATES, ATTR_COLUMN, ATTR_COUNT, ATTR_GROUP, ATTR_PAGE, ATTR_PAGE_TITLE, ATTR_QUERY, ATTR_REQUEST, ATTR_SELECT, ATTR_SHOW, ATTR_URL_LINK, ATTR_URL_PUSH, ATTR_URL_UNKNOWN, DEVELOPER_ATTRIBUTES, HUB_TAG_NAME, LB_COMMAND_PREFIX, LB_COMMANDS, LB_RESERVED_PREFIX, SHOW_NOT, } from "../core/lb-constants.js";
|
|
23
23
|
import { isRowRequest } from "../core/lb-types.js";
|
|
24
24
|
/**
|
|
25
25
|
* The hub is one element, and it swaps each page into the one `<main>`
|
|
@@ -107,6 +107,36 @@ function walkMarkup(node, scope, problems) {
|
|
|
107
107
|
problems.push(`<${tag}> carries ${ATTR_URL_PUSH} and no ${ATTR_REQUEST}; it goes ` +
|
|
108
108
|
`on an element with ${ATTR_REQUEST}`);
|
|
109
109
|
}
|
|
110
|
+
// A selector is a checkbox in a live row, and selects that row. It is no
|
|
111
|
+
// column, and commits nothing of its own.
|
|
112
|
+
if (el.hasAttribute(ATTR_SELECT)) {
|
|
113
|
+
if (tag !== "input" || el.getAttribute("type") !== "checkbox") {
|
|
114
|
+
problems.push(`<${tag}> carries ${ATTR_SELECT}; it goes on an ` +
|
|
115
|
+
`<input type="checkbox">`);
|
|
116
|
+
}
|
|
117
|
+
else if (scope?.row !== true) {
|
|
118
|
+
problems.push(`<input> carries ${ATTR_SELECT} outside a row template; it ` +
|
|
119
|
+
`selects the row it sits in`);
|
|
120
|
+
}
|
|
121
|
+
for (const name of [ATTR_COLUMN, ATTR_REQUEST]) {
|
|
122
|
+
if (el.hasAttribute(name)) {
|
|
123
|
+
problems.push(`<${tag}> carries ${ATTR_SELECT} and ${name}; a selector is no ` +
|
|
124
|
+
`column and sends nothing`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// HTML's own command attribute, whose `--lb-` values are Loadbare's.
|
|
129
|
+
const command = el.getAttribute("command");
|
|
130
|
+
if (command !== null && command.startsWith(LB_COMMAND_PREFIX)) {
|
|
131
|
+
if (!LB_COMMANDS.includes(command)) {
|
|
132
|
+
problems.push(`<${tag}> carries command="${command}", which begins with ` +
|
|
133
|
+
`'${LB_COMMAND_PREFIX}' but names no command Loadbare provides`);
|
|
134
|
+
}
|
|
135
|
+
else if (!el.hasAttribute("commandfor")) {
|
|
136
|
+
problems.push(`<${tag}> carries command="${command}" and no commandfor; it ` +
|
|
137
|
+
`names the form the command is for`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
110
140
|
if (el.hasAttribute(ATTR_URL_UNKNOWN) && tag !== "dialog") {
|
|
111
141
|
problems.push(`<${tag}> carries ${ATTR_URL_UNKNOWN}; it goes on a <dialog>`);
|
|
112
142
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assemble.js","sourceRoot":"","sources":["../../build/assemble.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Assembling one document out of a chrome file and a set of pages.\n *\n * Every `.html` file in play — the chrome and each page — goes through the\n * same `expand()` (see build/expand.ts) against the same definitions: the\n * built-in widgets and whatever definitions were found in the caller's own\n * source tree. `expand()` only ever sees a fragment, so the chrome's own is\n * the text between its `<body>` tags; a page's is the whole file. A page's\n * expanded host is wrapped in `<template lb-page=\"<name>\">` and, together\n * with the chrome's own expanded body content, spliced back into the\n * chrome's `<body>`. The result is the one document a server has to serve\n * for every route — see docs/tutorials/000-getting-started.md and\n * docs/reference/builder.md.\n *\n * Every path here is a parameter, resolved once by build/locations.ts — this\n * module never reconstructs one of its own, and never reads a directory\n * looking for pages or widgets; it is handed exactly which files those are.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport {\n addDefinitions,\n customElementTags,\n expandTree,\n type Definitions,\n} from \"./expand.js\";\nimport { formatHtml } from \"./format.js\";\nimport {\n AGGREGATES,\n ATTR_COUNT,\n ATTR_GROUP,\n ATTR_PAGE,\n ATTR_PAGE_TITLE,\n ATTR_QUERY,\n ATTR_REQUEST,\n ATTR_SHOW,\n ATTR_URL_LINK,\n ATTR_URL_PUSH,\n ATTR_URL_UNKNOWN,\n DEVELOPER_ATTRIBUTES,\n HUB_TAG_NAME,\n LB_RESERVED_PREFIX,\n SHOW_NOT,\n} from \"../core/lb-constants.js\";\nimport { isRowRequest } from \"../core/lb-types.js\";\nimport type { PageFile } from \"./locations.js\";\nimport type { OriginScan } from \"./origins.js\";\n\n/**\n * The hub is one element, and it swaps each page into the one `<main>`\n * inside it (hub/lb-hub.browser.ts), so the chrome holds exactly one of each,\n * the `<main>` inside the hub and empty, since whatever it held would be\n * replaced by the first page. A page is swapped into that `<main>`, so it\n * carries neither.\n */\nfunction checkChrome(chromeFile: string, body: ParentNode): void {\n const where = `assemble: '${chromeFile}'`;\n const hubs = body.querySelectorAll(HUB_TAG_NAME).length;\n if (hubs !== 1) {\n throw new Error(\n `${where} has ${hubs} <${HUB_TAG_NAME}>; it needs exactly one`,\n );\n }\n const mains = body.querySelectorAll(\"main\");\n if (mains.length !== 1) {\n throw new Error(\n `${where} has ${mains.length} <main>; it needs exactly one`,\n );\n }\n const main = mains[0]!;\n if (!main.closest(HUB_TAG_NAME)) {\n throw new Error(\n `${where} has its <main> outside <${HUB_TAG_NAME}>, where the hub cannot reach it`,\n );\n }\n if (main.children.length > 0 || main.textContent!.trim() !== \"\") {\n throw new Error(\n `${where} has content in its <main>, which the first page replaces; it goes empty`,\n );\n }\n}\n\n/** A page lands inside the chrome's `<main>`, so it brings no second one and no hub. */\nfunction checkPage(file: string, root: ParentNode): void {\n for (const tag of [HUB_TAG_NAME, \"main\"]) {\n if (root.querySelector(tag)) {\n throw new Error(\n `assemble: '${file}' carries a <${tag}>, which belongs to the chrome alone`,\n );\n }\n }\n}\n\n/**\n * The hub calls showModal() on the `<dialog>` carrying lb-url-unknown\n * (hub/lb-hub.browser.ts), and looks for it inside itself, as it does for\n * everything else it acts on. A dialog elsewhere in the body would never open\n * and would say nothing about why.\n */\nfunction checkUnknownPageDialog(chromeFile: string, body: ParentNode): void {\n const el = body.querySelector(`[${ATTR_URL_UNKNOWN}]`);\n if (!el) return;\n if (!el.closest(HUB_TAG_NAME)) {\n throw new Error(\n `assemble: '${chromeFile}' declares ${ATTR_URL_UNKNOWN} outside ` +\n `<${HUB_TAG_NAME}>, where the hub cannot reach it`,\n );\n }\n}\n\n/**\n * Where the markup stands while the check walks it: inside some `lb-query`,\n * and whether there is a row there to take a value from. Inside a row\n * template there always is. Inside an `lb-query` outside one, there is when\n * the query is of kind `row`, which only the server knows.\n */\ninterface Scope {\n row: boolean | \"unknown\";\n}\n\n/**\n * The markup, checked once against the finished document rather than\n * discovered one console error at a time in a browser.\n *\n * Every rule here is a fact the markup states about itself. The developer\n * writes `lb-*` attributes in markup, and script never assigns them, which is\n * what makes checking the markup sound. See docs/reference/data-binding.md.\n *\n * A `<template>`'s children are walked in the scope that encloses the\n * template, because a row template's clones land in the element around it.\n */\nfunction walkMarkup(\n node: ParentNode,\n scope: Scope | null,\n problems: string[],\n): void {\n for (const el of node.children) {\n const tag = el.localName;\n let here = scope;\n if (el.hasAttribute(ATTR_QUERY)) here = { row: \"unknown\" };\n\n for (const { name } of el.attributes) {\n if (\n name.startsWith(LB_RESERVED_PREFIX) &&\n !(DEVELOPER_ATTRIBUTES as readonly string[]).includes(name)\n ) {\n problems.push(\n `<${tag}> carries ${name}, which is not an attribute a developer ` +\n `writes`,\n );\n }\n }\n\n const request = el.getAttribute(ATTR_REQUEST);\n if (\n request !== null &&\n request.startsWith(LB_RESERVED_PREFIX) &&\n !isRowRequest(request)\n ) {\n problems.push(\n `<${tag}> carries ${ATTR_REQUEST}=\"${request}\", which begins with ` +\n `'${LB_RESERVED_PREFIX}' but names no request Loadbare provides`,\n );\n }\n if (el.hasAttribute(ATTR_URL_LINK) && tag !== \"a\") {\n problems.push(`<${tag}> carries ${ATTR_URL_LINK}; it goes on an <a>`);\n }\n if (el.hasAttribute(ATTR_URL_PUSH) && request === null) {\n problems.push(\n `<${tag}> carries ${ATTR_URL_PUSH} and no ${ATTR_REQUEST}; it goes ` +\n `on an element with ${ATTR_REQUEST}`,\n );\n }\n if (el.hasAttribute(ATTR_URL_UNKNOWN) && tag !== \"dialog\") {\n problems.push(\n `<${tag}> carries ${ATTR_URL_UNKNOWN}; it goes on a <dialog>`,\n );\n }\n\n // A group is a template holding a heading and the template its\n // contents go in; an aggregate is set on an element, from the column it\n // names.\n if (el.hasAttribute(ATTR_GROUP)) {\n if (tag !== \"template\") {\n problems.push(\n `<${tag}> carries ${ATTR_GROUP}; it goes on a <template>`,\n );\n } else if (\n !(el as HTMLTemplateElement).content.querySelector(\n `template:not([${ATTR_SHOW}])`,\n )\n ) {\n problems.push(\n `a <template ${ATTR_GROUP}> holds no <template> for its contents`,\n );\n }\n }\n for (const name of AGGREGATES) {\n if (!el.hasAttribute(name)) continue;\n if (tag === \"template\") {\n problems.push(`a <template> carries ${name}; it goes on an element`);\n } else if (name !== ATTR_COUNT && !el.getAttribute(name)) {\n problems.push(`<${tag}> carries ${name} naming no column`);\n }\n }\n\n // Judged by the scope around the element, not one the element carries:\n // its condition is a column of the row around it. With no lb-query\n // around it at all, nothing ever lands on it, and the element never\n // shows.\n const show = el.getAttribute(ATTR_SHOW);\n if (show !== null) {\n if (tag === \"template\") {\n problems.push(\n `a <template> carries ${ATTR_SHOW}=\"${show}\"; write it on the ` +\n `element it shows, and Loadbare supplies the template`,\n );\n } else if (scope === null || scope.row === false) {\n problems.push(\n `<${tag}> carries ${ATTR_SHOW}=\"${show}\" with no row around it ` +\n `to take the value from`,\n );\n } else if (show === SHOW_NOT || show.startsWith(SHOW_NOT + SHOW_NOT)) {\n problems.push(\n `<${tag}> carries ${ATTR_SHOW}=\"${show}\"; write one ` +\n `${SHOW_NOT} and then the column it reverses`,\n );\n }\n }\n\n walkMarkup(el, here, problems);\n // By tag name rather than by instanceof: template content belongs to a\n // document with no window, so the constructor is not reachable from the\n // node.\n if (tag === \"template\") {\n const content = (el as HTMLTemplateElement).content;\n const isRowTemplate =\n scope !== null && !!el.parentElement?.closest(`[${ATTR_QUERY}]`);\n if (isRowTemplate) {\n for (const root of content.children) {\n if (root.hasAttribute(ATTR_SHOW)) {\n problems.push(\n `<${root.localName}> is a row template's root and carries ` +\n `${ATTR_SHOW}; a row that should not show is left out by ` +\n `the query`,\n );\n }\n }\n }\n walkMarkup(content, isRowTemplate ? { row: true } : here, problems);\n }\n }\n}\n\n/**\n * Ship every `lb-show` element already inside the template the hub keeps an\n * absent branch in, so nothing conditional shows until its value says so.\n * A page is in the document before its data arrives, and a value that has not\n * arrived is no value.\n *\n * Elements are collected before any is moved, and a wrapped element is still\n * reached once its outer one has gone into a template, because the references\n * are held.\n */\nfunction wrapShown(holder: HTMLTemplateElement): void {\n const doc = holder.ownerDocument;\n const shown: Element[] = [];\n const collect = (root: ParentNode): void => {\n shown.push(...root.querySelectorAll(`[${ATTR_SHOW}]`));\n for (const t of root.querySelectorAll(\"template\")) {\n collect((t as HTMLTemplateElement).content);\n }\n };\n collect(holder.content);\n for (const el of shown) {\n const parked = doc.createElement(\"template\");\n parked.setAttribute(ATTR_SHOW, el.getAttribute(ATTR_SHOW)!);\n el.replaceWith(parked);\n parked.content.append(el);\n }\n}\n\n/**\n * Expand one file's markup, naming the file if expansion refuses it.\n *\n * What comes back is the tree the browser will build, so every pass after\n * this reads and changes it in place, and it is serialized once, when it\n * ships.\n */\nfunction expandFile(\n file: string,\n source: string,\n defs: Definitions,\n): HTMLTemplateElement {\n try {\n return expandTree(source, defs);\n } catch (e) {\n throw new Error(`assemble: '${file}': ${(e as Error).message}`);\n }\n}\n\n/** Check one expanded fragment, and name the file if anything is wrong. */\nfunction checkMarkup(file: string, root: ParentNode): void {\n const problems: string[] = [];\n walkMarkup(root, null, problems);\n if (problems.length > 0) {\n throw new Error(`assemble: '${file}' markup:\\n ` + problems.join(`\\n `));\n }\n}\n\n/**\n * A page file's `<title>` names the page. It is lifted out, since a page is\n * a fragment inside `<main>` and a `<title>` belongs in a document's head,\n * and its text content is stamped on the page as ATTR_PAGE_TITLE.\n */\nfunction liftTitle(holder: HTMLTemplateElement): string | null {\n const title = holder.content.querySelector(\"title\");\n if (!title) return null;\n const text = title.textContent?.trim() ?? \"\";\n title.remove();\n return text;\n}\n\n/** An attribute value, escaped for a double-quoted attribute. */\nfunction attributeValue(text: string): string {\n return text.replace(/&/g, \"&\").replace(/\"/g, \""\");\n}\n\nexport interface AssembleOptions {\n chromeFile: string;\n pages: PageFile[];\n /** Every origin, already scanned, in cascade order — see build/origins.ts. */\n scans: OriginScan[];\n}\n\nexport interface Assembled {\n html: string;\n /** Every custom element tag left in the document once expansion is done. */\n usedTags: Set<string>;\n}\n\nexport async function assemble({\n chromeFile,\n pages,\n scans,\n}: AssembleOptions): Promise<Assembled> {\n // One layer per origin, in order, so a later origin's definition overrides\n // an earlier one's for the same tag. Each layer is checked for cycles as it\n // lands, against everything merged so far.\n let defs: Definitions = {};\n for (const scan of scans) {\n defs = await addDefinitions(defs, scan.definitions);\n }\n\n // Tags are collected from each tree as it goes by. What ships is these\n // trees and the chrome around its body, which is collected on its own.\n const usedTags = new Set<string>();\n const templates: string[] = [];\n for (const { name, file } of pages) {\n const authored = await readFile(file, \"utf-8\");\n const host = expandFile(file, authored, defs);\n const title = liftTitle(host);\n checkPage(file, host.content);\n checkMarkup(file, host.content);\n wrapShown(host);\n customElementTags(host.content, usedTags);\n const titled =\n title === null ? \"\" : ` ${ATTR_PAGE_TITLE}=\"${attributeValue(title)}\"`;\n templates.push(\n `<template ${ATTR_PAGE}=\"${name}\"${titled}>${host.innerHTML}</template>`,\n );\n }\n\n let chromeSource: string;\n try {\n chromeSource = await readFile(chromeFile, \"utf-8\");\n } catch {\n throw new Error(`assemble: no chrome file at '${chromeFile}'`);\n }\n\n const body = /<body([^>]*)>([\\s\\S]*)<\\/body>/i.exec(chromeSource);\n if (!body) {\n throw new Error(\n `assemble: '${chromeFile}' has no <body>...</body> to expand`,\n );\n }\n const [whole, bodyAttrs, bodyContent] = body;\n const chromeBody = expandFile(chromeFile, bodyContent!, defs);\n checkChrome(chromeFile, chromeBody.content);\n checkUnknownPageDialog(chromeFile, chromeBody.content);\n checkMarkup(chromeFile, chromeBody.content);\n wrapShown(chromeBody);\n customElementTags(chromeBody.content, usedTags);\n customElementTags(chromeSource.replace(whole!, \"\"), usedTags);\n const withPages = chromeSource.replace(\n whole!,\n () =>\n `<body${bodyAttrs}>${chromeBody.innerHTML}\\n${templates.join(\"\\n\")}\\n</body>`,\n );\n\n return { html: await formatHtml(withPages), usedTags };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"assemble.js","sourceRoot":"","sources":["../../build/assemble.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Assembling one document out of a chrome file and a set of pages.\n *\n * Every `.html` file in play — the chrome and each page — goes through the\n * same `expand()` (see build/expand.ts) against the same definitions: the\n * built-in widgets and whatever definitions were found in the caller's own\n * source tree. `expand()` only ever sees a fragment, so the chrome's own is\n * the text between its `<body>` tags; a page's is the whole file. A page's\n * expanded host is wrapped in `<template lb-page=\"<name>\">` and, together\n * with the chrome's own expanded body content, spliced back into the\n * chrome's `<body>`. The result is the one document a server has to serve\n * for every route — see docs/tutorials/000-getting-started.md and\n * docs/reference/builder.md.\n *\n * Every path here is a parameter, resolved once by build/locations.ts — this\n * module never reconstructs one of its own, and never reads a directory\n * looking for pages or widgets; it is handed exactly which files those are.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport {\n addDefinitions,\n customElementTags,\n expandTree,\n type Definitions,\n} from \"./expand.js\";\nimport { formatHtml } from \"./format.js\";\nimport {\n AGGREGATES,\n ATTR_COLUMN,\n ATTR_COUNT,\n ATTR_GROUP,\n ATTR_PAGE,\n ATTR_PAGE_TITLE,\n ATTR_QUERY,\n ATTR_REQUEST,\n ATTR_SELECT,\n ATTR_SHOW,\n ATTR_URL_LINK,\n ATTR_URL_PUSH,\n ATTR_URL_UNKNOWN,\n DEVELOPER_ATTRIBUTES,\n HUB_TAG_NAME,\n LB_COMMAND_PREFIX,\n LB_COMMANDS,\n LB_RESERVED_PREFIX,\n SHOW_NOT,\n} from \"../core/lb-constants.js\";\nimport { isRowRequest } from \"../core/lb-types.js\";\nimport type { PageFile } from \"./locations.js\";\nimport type { OriginScan } from \"./origins.js\";\n\n/**\n * The hub is one element, and it swaps each page into the one `<main>`\n * inside it (hub/lb-hub.browser.ts), so the chrome holds exactly one of each,\n * the `<main>` inside the hub and empty, since whatever it held would be\n * replaced by the first page. A page is swapped into that `<main>`, so it\n * carries neither.\n */\nfunction checkChrome(chromeFile: string, body: ParentNode): void {\n const where = `assemble: '${chromeFile}'`;\n const hubs = body.querySelectorAll(HUB_TAG_NAME).length;\n if (hubs !== 1) {\n throw new Error(\n `${where} has ${hubs} <${HUB_TAG_NAME}>; it needs exactly one`,\n );\n }\n const mains = body.querySelectorAll(\"main\");\n if (mains.length !== 1) {\n throw new Error(\n `${where} has ${mains.length} <main>; it needs exactly one`,\n );\n }\n const main = mains[0]!;\n if (!main.closest(HUB_TAG_NAME)) {\n throw new Error(\n `${where} has its <main> outside <${HUB_TAG_NAME}>, where the hub cannot reach it`,\n );\n }\n if (main.children.length > 0 || main.textContent!.trim() !== \"\") {\n throw new Error(\n `${where} has content in its <main>, which the first page replaces; it goes empty`,\n );\n }\n}\n\n/** A page lands inside the chrome's `<main>`, so it brings no second one and no hub. */\nfunction checkPage(file: string, root: ParentNode): void {\n for (const tag of [HUB_TAG_NAME, \"main\"]) {\n if (root.querySelector(tag)) {\n throw new Error(\n `assemble: '${file}' carries a <${tag}>, which belongs to the chrome alone`,\n );\n }\n }\n}\n\n/**\n * The hub calls showModal() on the `<dialog>` carrying lb-url-unknown\n * (hub/lb-hub.browser.ts), and looks for it inside itself, as it does for\n * everything else it acts on. A dialog elsewhere in the body would never open\n * and would say nothing about why.\n */\nfunction checkUnknownPageDialog(chromeFile: string, body: ParentNode): void {\n const el = body.querySelector(`[${ATTR_URL_UNKNOWN}]`);\n if (!el) return;\n if (!el.closest(HUB_TAG_NAME)) {\n throw new Error(\n `assemble: '${chromeFile}' declares ${ATTR_URL_UNKNOWN} outside ` +\n `<${HUB_TAG_NAME}>, where the hub cannot reach it`,\n );\n }\n}\n\n/**\n * Where the markup stands while the check walks it: inside some `lb-query`,\n * and whether there is a row there to take a value from. Inside a row\n * template there always is. Inside an `lb-query` outside one, there is when\n * the query is of kind `row`, which only the server knows.\n */\ninterface Scope {\n row: boolean | \"unknown\";\n}\n\n/**\n * The markup, checked once against the finished document rather than\n * discovered one console error at a time in a browser.\n *\n * Every rule here is a fact the markup states about itself. The developer\n * writes `lb-*` attributes in markup, and script never assigns them, which is\n * what makes checking the markup sound. See docs/reference/data-binding.md.\n *\n * A `<template>`'s children are walked in the scope that encloses the\n * template, because a row template's clones land in the element around it.\n */\nfunction walkMarkup(\n node: ParentNode,\n scope: Scope | null,\n problems: string[],\n): void {\n for (const el of node.children) {\n const tag = el.localName;\n let here = scope;\n if (el.hasAttribute(ATTR_QUERY)) here = { row: \"unknown\" };\n\n for (const { name } of el.attributes) {\n if (\n name.startsWith(LB_RESERVED_PREFIX) &&\n !(DEVELOPER_ATTRIBUTES as readonly string[]).includes(name)\n ) {\n problems.push(\n `<${tag}> carries ${name}, which is not an attribute a developer ` +\n `writes`,\n );\n }\n }\n\n const request = el.getAttribute(ATTR_REQUEST);\n if (\n request !== null &&\n request.startsWith(LB_RESERVED_PREFIX) &&\n !isRowRequest(request)\n ) {\n problems.push(\n `<${tag}> carries ${ATTR_REQUEST}=\"${request}\", which begins with ` +\n `'${LB_RESERVED_PREFIX}' but names no request Loadbare provides`,\n );\n }\n if (el.hasAttribute(ATTR_URL_LINK) && tag !== \"a\") {\n problems.push(`<${tag}> carries ${ATTR_URL_LINK}; it goes on an <a>`);\n }\n if (el.hasAttribute(ATTR_URL_PUSH) && request === null) {\n problems.push(\n `<${tag}> carries ${ATTR_URL_PUSH} and no ${ATTR_REQUEST}; it goes ` +\n `on an element with ${ATTR_REQUEST}`,\n );\n }\n // A selector is a checkbox in a live row, and selects that row. It is no\n // column, and commits nothing of its own.\n if (el.hasAttribute(ATTR_SELECT)) {\n if (tag !== \"input\" || el.getAttribute(\"type\") !== \"checkbox\") {\n problems.push(\n `<${tag}> carries ${ATTR_SELECT}; it goes on an ` +\n `<input type=\"checkbox\">`,\n );\n } else if (scope?.row !== true) {\n problems.push(\n `<input> carries ${ATTR_SELECT} outside a row template; it ` +\n `selects the row it sits in`,\n );\n }\n for (const name of [ATTR_COLUMN, ATTR_REQUEST]) {\n if (el.hasAttribute(name)) {\n problems.push(\n `<${tag}> carries ${ATTR_SELECT} and ${name}; a selector is no ` +\n `column and sends nothing`,\n );\n }\n }\n }\n // HTML's own command attribute, whose `--lb-` values are Loadbare's.\n const command = el.getAttribute(\"command\");\n if (command !== null && command.startsWith(LB_COMMAND_PREFIX)) {\n if (!(LB_COMMANDS as readonly string[]).includes(command)) {\n problems.push(\n `<${tag}> carries command=\"${command}\", which begins with ` +\n `'${LB_COMMAND_PREFIX}' but names no command Loadbare provides`,\n );\n } else if (!el.hasAttribute(\"commandfor\")) {\n problems.push(\n `<${tag}> carries command=\"${command}\" and no commandfor; it ` +\n `names the form the command is for`,\n );\n }\n }\n if (el.hasAttribute(ATTR_URL_UNKNOWN) && tag !== \"dialog\") {\n problems.push(\n `<${tag}> carries ${ATTR_URL_UNKNOWN}; it goes on a <dialog>`,\n );\n }\n\n // A group is a template holding a heading and the template its\n // contents go in; an aggregate is set on an element, from the column it\n // names.\n if (el.hasAttribute(ATTR_GROUP)) {\n if (tag !== \"template\") {\n problems.push(\n `<${tag}> carries ${ATTR_GROUP}; it goes on a <template>`,\n );\n } else if (\n !(el as HTMLTemplateElement).content.querySelector(\n `template:not([${ATTR_SHOW}])`,\n )\n ) {\n problems.push(\n `a <template ${ATTR_GROUP}> holds no <template> for its contents`,\n );\n }\n }\n for (const name of AGGREGATES) {\n if (!el.hasAttribute(name)) continue;\n if (tag === \"template\") {\n problems.push(`a <template> carries ${name}; it goes on an element`);\n } else if (name !== ATTR_COUNT && !el.getAttribute(name)) {\n problems.push(`<${tag}> carries ${name} naming no column`);\n }\n }\n\n // Judged by the scope around the element, not one the element carries:\n // its condition is a column of the row around it. With no lb-query\n // around it at all, nothing ever lands on it, and the element never\n // shows.\n const show = el.getAttribute(ATTR_SHOW);\n if (show !== null) {\n if (tag === \"template\") {\n problems.push(\n `a <template> carries ${ATTR_SHOW}=\"${show}\"; write it on the ` +\n `element it shows, and Loadbare supplies the template`,\n );\n } else if (scope === null || scope.row === false) {\n problems.push(\n `<${tag}> carries ${ATTR_SHOW}=\"${show}\" with no row around it ` +\n `to take the value from`,\n );\n } else if (show === SHOW_NOT || show.startsWith(SHOW_NOT + SHOW_NOT)) {\n problems.push(\n `<${tag}> carries ${ATTR_SHOW}=\"${show}\"; write one ` +\n `${SHOW_NOT} and then the column it reverses`,\n );\n }\n }\n\n walkMarkup(el, here, problems);\n // By tag name rather than by instanceof: template content belongs to a\n // document with no window, so the constructor is not reachable from the\n // node.\n if (tag === \"template\") {\n const content = (el as HTMLTemplateElement).content;\n const isRowTemplate =\n scope !== null && !!el.parentElement?.closest(`[${ATTR_QUERY}]`);\n if (isRowTemplate) {\n for (const root of content.children) {\n if (root.hasAttribute(ATTR_SHOW)) {\n problems.push(\n `<${root.localName}> is a row template's root and carries ` +\n `${ATTR_SHOW}; a row that should not show is left out by ` +\n `the query`,\n );\n }\n }\n }\n walkMarkup(content, isRowTemplate ? { row: true } : here, problems);\n }\n }\n}\n\n/**\n * Ship every `lb-show` element already inside the template the hub keeps an\n * absent branch in, so nothing conditional shows until its value says so.\n * A page is in the document before its data arrives, and a value that has not\n * arrived is no value.\n *\n * Elements are collected before any is moved, and a wrapped element is still\n * reached once its outer one has gone into a template, because the references\n * are held.\n */\nfunction wrapShown(holder: HTMLTemplateElement): void {\n const doc = holder.ownerDocument;\n const shown: Element[] = [];\n const collect = (root: ParentNode): void => {\n shown.push(...root.querySelectorAll(`[${ATTR_SHOW}]`));\n for (const t of root.querySelectorAll(\"template\")) {\n collect((t as HTMLTemplateElement).content);\n }\n };\n collect(holder.content);\n for (const el of shown) {\n const parked = doc.createElement(\"template\");\n parked.setAttribute(ATTR_SHOW, el.getAttribute(ATTR_SHOW)!);\n el.replaceWith(parked);\n parked.content.append(el);\n }\n}\n\n/**\n * Expand one file's markup, naming the file if expansion refuses it.\n *\n * What comes back is the tree the browser will build, so every pass after\n * this reads and changes it in place, and it is serialized once, when it\n * ships.\n */\nfunction expandFile(\n file: string,\n source: string,\n defs: Definitions,\n): HTMLTemplateElement {\n try {\n return expandTree(source, defs);\n } catch (e) {\n throw new Error(`assemble: '${file}': ${(e as Error).message}`);\n }\n}\n\n/** Check one expanded fragment, and name the file if anything is wrong. */\nfunction checkMarkup(file: string, root: ParentNode): void {\n const problems: string[] = [];\n walkMarkup(root, null, problems);\n if (problems.length > 0) {\n throw new Error(`assemble: '${file}' markup:\\n ` + problems.join(`\\n `));\n }\n}\n\n/**\n * A page file's `<title>` names the page. It is lifted out, since a page is\n * a fragment inside `<main>` and a `<title>` belongs in a document's head,\n * and its text content is stamped on the page as ATTR_PAGE_TITLE.\n */\nfunction liftTitle(holder: HTMLTemplateElement): string | null {\n const title = holder.content.querySelector(\"title\");\n if (!title) return null;\n const text = title.textContent?.trim() ?? \"\";\n title.remove();\n return text;\n}\n\n/** An attribute value, escaped for a double-quoted attribute. */\nfunction attributeValue(text: string): string {\n return text.replace(/&/g, \"&\").replace(/\"/g, \""\");\n}\n\nexport interface AssembleOptions {\n chromeFile: string;\n pages: PageFile[];\n /** Every origin, already scanned, in cascade order — see build/origins.ts. */\n scans: OriginScan[];\n}\n\nexport interface Assembled {\n html: string;\n /** Every custom element tag left in the document once expansion is done. */\n usedTags: Set<string>;\n}\n\nexport async function assemble({\n chromeFile,\n pages,\n scans,\n}: AssembleOptions): Promise<Assembled> {\n // One layer per origin, in order, so a later origin's definition overrides\n // an earlier one's for the same tag. Each layer is checked for cycles as it\n // lands, against everything merged so far.\n let defs: Definitions = {};\n for (const scan of scans) {\n defs = await addDefinitions(defs, scan.definitions);\n }\n\n // Tags are collected from each tree as it goes by. What ships is these\n // trees and the chrome around its body, which is collected on its own.\n const usedTags = new Set<string>();\n const templates: string[] = [];\n for (const { name, file } of pages) {\n const authored = await readFile(file, \"utf-8\");\n const host = expandFile(file, authored, defs);\n const title = liftTitle(host);\n checkPage(file, host.content);\n checkMarkup(file, host.content);\n wrapShown(host);\n customElementTags(host.content, usedTags);\n const titled =\n title === null ? \"\" : ` ${ATTR_PAGE_TITLE}=\"${attributeValue(title)}\"`;\n templates.push(\n `<template ${ATTR_PAGE}=\"${name}\"${titled}>${host.innerHTML}</template>`,\n );\n }\n\n let chromeSource: string;\n try {\n chromeSource = await readFile(chromeFile, \"utf-8\");\n } catch {\n throw new Error(`assemble: no chrome file at '${chromeFile}'`);\n }\n\n const body = /<body([^>]*)>([\\s\\S]*)<\\/body>/i.exec(chromeSource);\n if (!body) {\n throw new Error(\n `assemble: '${chromeFile}' has no <body>...</body> to expand`,\n );\n }\n const [whole, bodyAttrs, bodyContent] = body;\n const chromeBody = expandFile(chromeFile, bodyContent!, defs);\n checkChrome(chromeFile, chromeBody.content);\n checkUnknownPageDialog(chromeFile, chromeBody.content);\n checkMarkup(chromeFile, chromeBody.content);\n wrapShown(chromeBody);\n customElementTags(chromeBody.content, usedTags);\n customElementTags(chromeSource.replace(whole!, \"\"), usedTags);\n const withPages = chromeSource.replace(\n whole!,\n () =>\n `<body${bodyAttrs}>${chromeBody.innerHTML}\\n${templates.join(\"\\n\")}\\n</body>`,\n );\n\n return { html: await formatHtml(withPages), usedTags };\n}\n"]}
|
package/dist/build/elements.d.ts
CHANGED
|
@@ -44,8 +44,14 @@ export declare function resolveElements({ used, scans, }: ResolveOptions): Resol
|
|
|
44
44
|
* Loadbare owns every `lb` method name on a custom element. A script that
|
|
45
45
|
* declares one Loadbare does not call is either a misspelling of one it does,
|
|
46
46
|
* which the hub would then silently never call, or a name Loadbare may define
|
|
47
|
-
* tomorrow with a meaning of its own.
|
|
48
|
-
*
|
|
47
|
+
* tomorrow with a meaning of its own.
|
|
48
|
+
*
|
|
49
|
+
* A custom element hears the hub's lifecycle in place of the browser's, so a
|
|
50
|
+
* script that declares `connectedCallback` or its kin is refused too: the
|
|
51
|
+
* browser calls them on every move and every `lb-show` toggle, and the hub's
|
|
52
|
+
* `lbAttached` and `lbDetached` are what it means.
|
|
53
|
+
*
|
|
54
|
+
* Both are refused here, in every script the build ships but Loadbare's own.
|
|
49
55
|
*/
|
|
50
56
|
export declare function checkReservedMethods(resolved: Map<string, Resolved>): Promise<void>;
|
|
51
57
|
/**
|
|
@@ -53,6 +59,10 @@ export declare function checkReservedMethods(resolved: Map<string, Resolved>): P
|
|
|
53
59
|
* document actually uses, and nothing else. Written to `outDir` so a
|
|
54
60
|
* relative import to a local widget resolves the ordinary way; a specifier
|
|
55
61
|
* (built-in or third-party) is written as the bare string it is.
|
|
62
|
+
*
|
|
63
|
+
* The hub comes last. It starts as soon as it is defined, and every other
|
|
64
|
+
* element must be defined by then, so that everything the hub places has
|
|
65
|
+
* upgraded before it is filled.
|
|
56
66
|
*/
|
|
57
67
|
export declare function clientEntrySource(resolved: Map<string, Resolved>, outDir: string): string;
|
|
58
68
|
//# sourceMappingURL=elements.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elements.d.ts","sourceRoot":"","sources":["../../build/elements.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;
|
|
1
|
+
{"version":3,"file":"elements.d.ts","sourceRoot":"","sources":["../../build/elements.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AASH,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAE,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAEzE,8FAA8F;AAC9F,MAAM,MAAM,QAAQ,GAClB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClB,8EAA8E;IAC9E,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACjC;AAED,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,KAAK,GACN,EAAE,cAAc,GAAG,aAAa,CA+ChC;AAqBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC,CAiCf;AAeD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC/B,MAAM,EAAE,MAAM,GACb,MAAM,CAmBR"}
|
package/dist/build/elements.js
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import { access, readFile } from "node:fs/promises";
|
|
25
25
|
import path from "node:path";
|
|
26
|
-
import { LB_METHODS } from "../core/lb-constants.js";
|
|
26
|
+
import { BROWSER_LIFECYCLE, HUB_TAG_NAME, LB_METHODS, } from "../core/lb-constants.js";
|
|
27
27
|
import { MODULE_SUFFIXES } from "./origins.js";
|
|
28
28
|
export { loadElementManifest } from "./origins.js";
|
|
29
29
|
export function resolveElements({ used, scans, }) {
|
|
@@ -75,17 +75,30 @@ export function resolveElements({ used, scans, }) {
|
|
|
75
75
|
* before it. A call through `this.` or `el.` never starts a line with the
|
|
76
76
|
* name, so it is not taken for one.
|
|
77
77
|
*/
|
|
78
|
-
const LB_DECLARATION =
|
|
78
|
+
const LB_DECLARATION = declaration("lb[A-Z]\\w*");
|
|
79
|
+
/** One of the browser's lifecycle callbacks, declared the same way. */
|
|
80
|
+
const BROWSER_DECLARATION = declaration(BROWSER_LIFECYCLE.join("|"));
|
|
81
|
+
function declaration(names) {
|
|
82
|
+
return new RegExp(`^[ \\t]*(?:(?:static|async|override|public|private|protected|readonly|get|set)[ \\t]+)*` +
|
|
83
|
+
`(${names})[ \\t]*(?:[(<=:!]|\\?[ \\t]*[(<:])`, "gm");
|
|
84
|
+
}
|
|
79
85
|
/**
|
|
80
86
|
* Loadbare owns every `lb` method name on a custom element. A script that
|
|
81
87
|
* declares one Loadbare does not call is either a misspelling of one it does,
|
|
82
88
|
* which the hub would then silently never call, or a name Loadbare may define
|
|
83
|
-
* tomorrow with a meaning of its own.
|
|
84
|
-
*
|
|
89
|
+
* tomorrow with a meaning of its own.
|
|
90
|
+
*
|
|
91
|
+
* A custom element hears the hub's lifecycle in place of the browser's, so a
|
|
92
|
+
* script that declares `connectedCallback` or its kin is refused too: the
|
|
93
|
+
* browser calls them on every move and every `lb-show` toggle, and the hub's
|
|
94
|
+
* `lbAttached` and `lbDetached` are what it means.
|
|
95
|
+
*
|
|
96
|
+
* Both are refused here, in every script the build ships but Loadbare's own.
|
|
85
97
|
*/
|
|
86
98
|
export async function checkReservedMethods(resolved) {
|
|
87
99
|
const known = LB_METHODS;
|
|
88
|
-
const
|
|
100
|
+
const reserved = [];
|
|
101
|
+
const browser = [];
|
|
89
102
|
for (const [tag, entry] of resolved) {
|
|
90
103
|
if (entry.kind !== "file")
|
|
91
104
|
continue;
|
|
@@ -94,14 +107,26 @@ export async function checkReservedMethods(resolved) {
|
|
|
94
107
|
for (const [, name] of source.matchAll(LB_DECLARATION)) {
|
|
95
108
|
if (known.includes(name))
|
|
96
109
|
continue;
|
|
97
|
-
|
|
110
|
+
reserved.push(`<${tag}> in '${file}' declares ${name}`);
|
|
111
|
+
}
|
|
112
|
+
for (const [, name] of source.matchAll(BROWSER_DECLARATION)) {
|
|
113
|
+
browser.push(`<${tag}> in '${file}' declares ${name}`);
|
|
98
114
|
}
|
|
99
115
|
}
|
|
100
|
-
|
|
101
|
-
|
|
116
|
+
const problems = [];
|
|
117
|
+
if (reserved.length > 0) {
|
|
118
|
+
problems.push(`build: a method name beginning with lb belongs to Loadbare, which ` +
|
|
102
119
|
`defines only ${known.join(", ")}:\n ` +
|
|
103
|
-
|
|
120
|
+
reserved.join("\n "));
|
|
121
|
+
}
|
|
122
|
+
if (browser.length > 0) {
|
|
123
|
+
problems.push(`build: a custom element hears the hub's lifecycle, not the ` +
|
|
124
|
+
`browser's; write lbAttached and lbDetached in place of ` +
|
|
125
|
+
`${BROWSER_LIFECYCLE.join(", ")}:\n ` +
|
|
126
|
+
browser.join("\n "));
|
|
104
127
|
}
|
|
128
|
+
if (problems.length > 0)
|
|
129
|
+
throw new Error(problems.join("\n"));
|
|
105
130
|
}
|
|
106
131
|
/** The file behind an import path that has had its extension taken off. */
|
|
107
132
|
async function moduleFile(stripped) {
|
|
@@ -121,10 +146,19 @@ async function moduleFile(stripped) {
|
|
|
121
146
|
* document actually uses, and nothing else. Written to `outDir` so a
|
|
122
147
|
* relative import to a local widget resolves the ordinary way; a specifier
|
|
123
148
|
* (built-in or third-party) is written as the bare string it is.
|
|
149
|
+
*
|
|
150
|
+
* The hub comes last. It starts as soon as it is defined, and every other
|
|
151
|
+
* element must be defined by then, so that everything the hub places has
|
|
152
|
+
* upgraded before it is filled.
|
|
124
153
|
*/
|
|
125
154
|
export function clientEntrySource(resolved, outDir) {
|
|
126
155
|
const lines = [];
|
|
127
|
-
|
|
156
|
+
const tags = [...resolved.keys()].sort();
|
|
157
|
+
if (tags.includes(HUB_TAG_NAME)) {
|
|
158
|
+
tags.splice(tags.indexOf(HUB_TAG_NAME), 1);
|
|
159
|
+
tags.push(HUB_TAG_NAME);
|
|
160
|
+
}
|
|
161
|
+
for (const tag of tags) {
|
|
128
162
|
const entry = resolved.get(tag);
|
|
129
163
|
if (entry.kind === "specifier") {
|
|
130
164
|
lines.push(`import ${JSON.stringify(entry.value)};`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elements.js","sourceRoot":"","sources":["../../build/elements.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validating that a custom element a build actually uses can do something —\n * and finding the script to import for it when it can.\n *\n * A used tag is valid if it has a script, a definition, or both:\n * - a script registers the class that upgrades it.\n * - a definition (an `.html` file) expands the tag's content at build\n * time. A widget with only a definition and no script is markup only:\n * expansion already gave it everything it will ever have, and the tag\n * survives as an inert wrapper (see expand.ts).\n *\n * A tag with neither — no script anywhere and no definition — would do\n * nothing were it ever to reach the browser, so that is an error. When a\n * module named after the tag exists but never said `.browser`, the error\n * names that file: forgetting the word is the ordinary way to arrive here,\n * and it is the one an author can fix in a rename.\n *\n * Both halves are looked for in the same ordered origins, and the later\n * origin wins: an application's own script overrides one from a package it\n * imported, which overrides a built-in. Two files claiming one tag *within*\n * one origin is the error case, and build/origins.ts raises it while\n * scanning. Nothing is scanned here.\n */\n\nimport { access, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { LB_METHODS } from \"../core/lb-constants.js\";\nimport { MODULE_SUFFIXES, type OriginScan } from \"./origins.js\";\n\nexport { loadElementManifest, type ElementManifest } from \"./origins.js\";\n\n/** A resolved tag: a bare specifier to import, or a local file to import by relative path. */\nexport type Resolved =\n { kind: \"specifier\"; value: string } | { kind: \"file\"; value: string };\n\nexport interface ResolveOptions {\n used: Set<string>;\n /** Every origin, already scanned, in cascade order — see build/origins.ts. */\n scans: OriginScan[];\n}\n\nexport interface ResolveResult {\n resolved: Map<string, Resolved>;\n}\n\nexport function resolveElements({\n used,\n scans,\n}: ResolveOptions): ResolveResult {\n const resolved = new Map<string, Resolved>();\n\n for (const tag of used) {\n let script: Resolved | undefined;\n let hasDefinition = false;\n\n // In order, so the last origin holding a script is the one that wins.\n for (const scan of scans) {\n if (scan.definitions.has(tag)) hasDefinition = true;\n const found = scan.scripts.get(tag);\n if (found === undefined) continue;\n script = scan.specifier\n ? { kind: \"specifier\", value: scan.specifier(tag) }\n : { kind: \"file\", value: found };\n }\n\n if (script) {\n resolved.set(tag, script);\n continue;\n }\n // No script anywhere. Valid only if a definition gave the tag its\n // content — otherwise nothing, ever, would upgrade or fill it, and the\n // tag would do nothing were it to reach the browser.\n if (!hasDefinition) {\n // The likeliest reason, checked first: a module named after the tag is\n // sitting right there without the word that would ship it. Say which\n // file, because \"there is no script\" reads as a lie to someone looking\n // straight at one.\n for (const scan of scans) {\n const near = scan.unmarked.get(tag);\n if (near === undefined) continue;\n throw new Error(\n `build: <${tag}> has no script, but '${near}' is named after it. ` +\n `A script reaches the browser only when its name says so — ` +\n `rename it '${path.basename(near, path.extname(near))}.browser` +\n `${path.extname(near)}' if that is what it is.`,\n );\n }\n throw new Error(\n `build: <${tag}> has neither a script nor a definition, so it would ` +\n `do nothing (checked ${scans.map((s) => `'${s.name}'`).join(\", \")})`,\n );\n }\n }\n\n return { resolved };\n}\n\n/**\n * A declaration at the start of a line whose name begins with `lb` and a\n * capital: a method, an accessor, or a field, with whatever modifiers come\n * before it. A call through `this.` or `el.` never starts a line with the\n * name, so it is not taken for one.\n */\nconst LB_DECLARATION =\n /^[ \\t]*(?:(?:static|async|override|public|private|protected|readonly|get|set)[ \\t]+)*(lb[A-Z]\\w*)[ \\t]*(?:[(<=:!]|\\?[ \\t]*[(<:])/gm;\n\n/**\n * Loadbare owns every `lb` method name on a custom element. A script that\n * declares one Loadbare does not call is either a misspelling of one it does,\n * which the hub would then silently never call, or a name Loadbare may define\n * tomorrow with a meaning of its own. Both are refused here, in every script\n * the build ships but Loadbare's own.\n */\nexport async function checkReservedMethods(\n resolved: Map<string, Resolved>,\n): Promise<void> {\n const known: readonly string[] = LB_METHODS;\n const problems: string[] = [];\n for (const [tag, entry] of resolved) {\n if (entry.kind !== \"file\") continue;\n const file = await moduleFile(entry.value);\n const source = await readFile(file, \"utf-8\");\n for (const [, name] of source.matchAll(LB_DECLARATION)) {\n if (known.includes(name!)) continue;\n problems.push(`<${tag}> in '${file}' declares ${name}`);\n }\n }\n if (problems.length > 0) {\n throw new Error(\n `build: a method name beginning with lb belongs to Loadbare, which ` +\n `defines only ${known.join(\", \")}:\\n ` +\n problems.join(\"\\n \"),\n );\n }\n}\n\n/** The file behind an import path that has had its extension taken off. */\nasync function moduleFile(stripped: string): Promise<string> {\n for (const ext of MODULE_SUFFIXES) {\n try {\n await access(stripped + ext);\n return stripped + ext;\n } catch {\n // Try the next extension.\n }\n }\n throw new Error(`build: no script at '${stripped}'`);\n}\n\n/**\n * The generated client entry point — every custom element the assembled\n * document actually uses, and nothing else. Written to `outDir` so a\n * relative import to a local widget resolves the ordinary way; a specifier\n * (built-in or third-party) is written as the bare string it is.\n */\nexport function clientEntrySource(\n resolved: Map<string, Resolved>,\n outDir: string,\n): string {\n const lines: string[] = [];\n for (const tag of [...resolved.keys()].sort()) {\n const entry = resolved.get(tag)!;\n if (entry.kind === \"specifier\") {\n lines.push(`import ${JSON.stringify(entry.value)};`);\n } else {\n const rel = path.relative(outDir, entry.value).split(path.sep).join(\"/\");\n lines.push(\n `import ${JSON.stringify(rel.startsWith(\".\") ? rel : `./${rel}`)};`,\n );\n }\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n"]}
|
|
1
|
+
{"version":3,"file":"elements.js","sourceRoot":"","sources":["../../build/elements.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validating that a custom element a build actually uses can do something —\n * and finding the script to import for it when it can.\n *\n * A used tag is valid if it has a script, a definition, or both:\n * - a script registers the class that upgrades it.\n * - a definition (an `.html` file) expands the tag's content at build\n * time. A widget with only a definition and no script is markup only:\n * expansion already gave it everything it will ever have, and the tag\n * survives as an inert wrapper (see expand.ts).\n *\n * A tag with neither — no script anywhere and no definition — would do\n * nothing were it ever to reach the browser, so that is an error. When a\n * module named after the tag exists but never said `.browser`, the error\n * names that file: forgetting the word is the ordinary way to arrive here,\n * and it is the one an author can fix in a rename.\n *\n * Both halves are looked for in the same ordered origins, and the later\n * origin wins: an application's own script overrides one from a package it\n * imported, which overrides a built-in. Two files claiming one tag *within*\n * one origin is the error case, and build/origins.ts raises it while\n * scanning. Nothing is scanned here.\n */\n\nimport { access, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n BROWSER_LIFECYCLE,\n HUB_TAG_NAME,\n LB_METHODS,\n} from \"../core/lb-constants.js\";\nimport { MODULE_SUFFIXES, type OriginScan } from \"./origins.js\";\n\nexport { loadElementManifest, type ElementManifest } from \"./origins.js\";\n\n/** A resolved tag: a bare specifier to import, or a local file to import by relative path. */\nexport type Resolved =\n { kind: \"specifier\"; value: string } | { kind: \"file\"; value: string };\n\nexport interface ResolveOptions {\n used: Set<string>;\n /** Every origin, already scanned, in cascade order — see build/origins.ts. */\n scans: OriginScan[];\n}\n\nexport interface ResolveResult {\n resolved: Map<string, Resolved>;\n}\n\nexport function resolveElements({\n used,\n scans,\n}: ResolveOptions): ResolveResult {\n const resolved = new Map<string, Resolved>();\n\n for (const tag of used) {\n let script: Resolved | undefined;\n let hasDefinition = false;\n\n // In order, so the last origin holding a script is the one that wins.\n for (const scan of scans) {\n if (scan.definitions.has(tag)) hasDefinition = true;\n const found = scan.scripts.get(tag);\n if (found === undefined) continue;\n script = scan.specifier\n ? { kind: \"specifier\", value: scan.specifier(tag) }\n : { kind: \"file\", value: found };\n }\n\n if (script) {\n resolved.set(tag, script);\n continue;\n }\n // No script anywhere. Valid only if a definition gave the tag its\n // content — otherwise nothing, ever, would upgrade or fill it, and the\n // tag would do nothing were it to reach the browser.\n if (!hasDefinition) {\n // The likeliest reason, checked first: a module named after the tag is\n // sitting right there without the word that would ship it. Say which\n // file, because \"there is no script\" reads as a lie to someone looking\n // straight at one.\n for (const scan of scans) {\n const near = scan.unmarked.get(tag);\n if (near === undefined) continue;\n throw new Error(\n `build: <${tag}> has no script, but '${near}' is named after it. ` +\n `A script reaches the browser only when its name says so — ` +\n `rename it '${path.basename(near, path.extname(near))}.browser` +\n `${path.extname(near)}' if that is what it is.`,\n );\n }\n throw new Error(\n `build: <${tag}> has neither a script nor a definition, so it would ` +\n `do nothing (checked ${scans.map((s) => `'${s.name}'`).join(\", \")})`,\n );\n }\n }\n\n return { resolved };\n}\n\n/**\n * A declaration at the start of a line whose name begins with `lb` and a\n * capital: a method, an accessor, or a field, with whatever modifiers come\n * before it. A call through `this.` or `el.` never starts a line with the\n * name, so it is not taken for one.\n */\nconst LB_DECLARATION = declaration(\"lb[A-Z]\\\\w*\");\n\n/** One of the browser's lifecycle callbacks, declared the same way. */\nconst BROWSER_DECLARATION = declaration(BROWSER_LIFECYCLE.join(\"|\"));\n\nfunction declaration(names: string): RegExp {\n return new RegExp(\n `^[ \\\\t]*(?:(?:static|async|override|public|private|protected|readonly|get|set)[ \\\\t]+)*` +\n `(${names})[ \\\\t]*(?:[(<=:!]|\\\\?[ \\\\t]*[(<:])`,\n \"gm\",\n );\n}\n\n/**\n * Loadbare owns every `lb` method name on a custom element. A script that\n * declares one Loadbare does not call is either a misspelling of one it does,\n * which the hub would then silently never call, or a name Loadbare may define\n * tomorrow with a meaning of its own.\n *\n * A custom element hears the hub's lifecycle in place of the browser's, so a\n * script that declares `connectedCallback` or its kin is refused too: the\n * browser calls them on every move and every `lb-show` toggle, and the hub's\n * `lbAttached` and `lbDetached` are what it means.\n *\n * Both are refused here, in every script the build ships but Loadbare's own.\n */\nexport async function checkReservedMethods(\n resolved: Map<string, Resolved>,\n): Promise<void> {\n const known: readonly string[] = LB_METHODS;\n const reserved: string[] = [];\n const browser: string[] = [];\n for (const [tag, entry] of resolved) {\n if (entry.kind !== \"file\") continue;\n const file = await moduleFile(entry.value);\n const source = await readFile(file, \"utf-8\");\n for (const [, name] of source.matchAll(LB_DECLARATION)) {\n if (known.includes(name!)) continue;\n reserved.push(`<${tag}> in '${file}' declares ${name}`);\n }\n for (const [, name] of source.matchAll(BROWSER_DECLARATION)) {\n browser.push(`<${tag}> in '${file}' declares ${name}`);\n }\n }\n const problems: string[] = [];\n if (reserved.length > 0) {\n problems.push(\n `build: a method name beginning with lb belongs to Loadbare, which ` +\n `defines only ${known.join(\", \")}:\\n ` +\n reserved.join(\"\\n \"),\n );\n }\n if (browser.length > 0) {\n problems.push(\n `build: a custom element hears the hub's lifecycle, not the ` +\n `browser's; write lbAttached and lbDetached in place of ` +\n `${BROWSER_LIFECYCLE.join(\", \")}:\\n ` +\n browser.join(\"\\n \"),\n );\n }\n if (problems.length > 0) throw new Error(problems.join(\"\\n\"));\n}\n\n/** The file behind an import path that has had its extension taken off. */\nasync function moduleFile(stripped: string): Promise<string> {\n for (const ext of MODULE_SUFFIXES) {\n try {\n await access(stripped + ext);\n return stripped + ext;\n } catch {\n // Try the next extension.\n }\n }\n throw new Error(`build: no script at '${stripped}'`);\n}\n\n/**\n * The generated client entry point — every custom element the assembled\n * document actually uses, and nothing else. Written to `outDir` so a\n * relative import to a local widget resolves the ordinary way; a specifier\n * (built-in or third-party) is written as the bare string it is.\n *\n * The hub comes last. It starts as soon as it is defined, and every other\n * element must be defined by then, so that everything the hub places has\n * upgraded before it is filled.\n */\nexport function clientEntrySource(\n resolved: Map<string, Resolved>,\n outDir: string,\n): string {\n const lines: string[] = [];\n const tags = [...resolved.keys()].sort();\n if (tags.includes(HUB_TAG_NAME)) {\n tags.splice(tags.indexOf(HUB_TAG_NAME), 1);\n tags.push(HUB_TAG_NAME);\n }\n for (const tag of tags) {\n const entry = resolved.get(tag)!;\n if (entry.kind === \"specifier\") {\n lines.push(`import ${JSON.stringify(entry.value)};`);\n } else {\n const rel = path.relative(outDir, entry.value).split(path.sep).join(\"/\");\n lines.push(\n `import ${JSON.stringify(rel.startsWith(\".\") ? rel : `./${rel}`)};`,\n );\n }\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n"]}
|
|
@@ -33,13 +33,24 @@ export declare const ATTR_REQUEST = "lb-request";
|
|
|
33
33
|
export declare const LB_EVENT_NAME = "lb-request";
|
|
34
34
|
export declare const LB_DONE_EVENT_NAME = "lb-request-done";
|
|
35
35
|
export declare const ATTR_REQUEST_PENDING = "lb-request-pending";
|
|
36
|
+
export declare const ATTR_REQUEST_REFUSED = "lb-request-refused";
|
|
37
|
+
export declare const LB_REFUSAL_STATUS = 422;
|
|
36
38
|
export declare const ATTR_REQUEST_ERROR = "lb-request-error";
|
|
39
|
+
export declare const COMMAND_EDIT = "--lb-edit";
|
|
40
|
+
export declare const COMMAND_NEW = "--lb-new";
|
|
41
|
+
export declare const COMMAND_RELEASE = "--lb-release";
|
|
42
|
+
export declare const LB_COMMANDS: readonly ["--lb-edit", "--lb-new", "--lb-release"];
|
|
43
|
+
export declare const LB_COMMAND_PREFIX = "--lb-";
|
|
44
|
+
export declare const ATTR_ROW_EDITING = "lb-row-editing";
|
|
45
|
+
export declare const ATTR_SELECT = "lb-select";
|
|
46
|
+
export declare const ATTR_ROW_SELECTED = "lb-row-selected";
|
|
37
47
|
export declare const LB_RESERVED_PREFIX = "lb-";
|
|
38
48
|
export declare const REQUEST_ROW_INSERT = "lb-row-insert";
|
|
39
49
|
export declare const REQUEST_ROW_UPDATE = "lb-row-update";
|
|
40
50
|
export declare const REQUEST_ROW_DELETE = "lb-row-delete";
|
|
41
51
|
export declare const LB_ROW_REQUESTS: readonly ["lb-row-insert", "lb-row-update", "lb-row-delete"];
|
|
42
|
-
export declare const LB_METHODS: readonly ["lbRowsLanded"];
|
|
52
|
+
export declare const LB_METHODS: readonly ["lbAttached", "lbRowsLanded", "lbRequestDone", "lbDetached"];
|
|
53
|
+
export declare const BROWSER_LIFECYCLE: readonly ["connectedCallback", "disconnectedCallback", "adoptedCallback", "connectedMoveCallback"];
|
|
43
54
|
export declare const KIND_ROW = "row";
|
|
44
55
|
export declare const KIND_ROWS = "rows";
|
|
45
56
|
export declare const URL_QUERY = "lb-url";
|
|
@@ -53,7 +64,7 @@ export declare const ATTR_EXP_SLOT = "lb-exp-slot";
|
|
|
53
64
|
export declare const ATTR_EXP_TEMPLATE = "lb-exp-template";
|
|
54
65
|
export declare const ATTR_PAGE = "lb-page";
|
|
55
66
|
export declare const ATTR_PAGE_TITLE = "lb-page-title";
|
|
56
|
-
export declare const DEVELOPER_ATTRIBUTES: readonly ["lb-query", "lb-column", "lb-show", "lb-group", "lb-count", "lb-sum", "lb-avg", "lb-min", "lb-max", "lb-request", "lb-url-link", "lb-url-push", "lb-url-unknown"];
|
|
67
|
+
export declare const DEVELOPER_ATTRIBUTES: readonly ["lb-query", "lb-column", "lb-show", "lb-group", "lb-count", "lb-sum", "lb-avg", "lb-min", "lb-max", "lb-request", "lb-select", "lb-url-link", "lb-url-push", "lb-url-unknown"];
|
|
57
68
|
export declare const HUB_TAG_NAME = "lb-hub";
|
|
58
69
|
export declare const LB_ENDPOINT = "/lb";
|
|
59
70
|
export declare const LB_REQUEST_TIMEOUT_MS = 10000;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-constants.d.ts","sourceRoot":"","sources":["../../core/lb-constants.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,UAAU,aAAa,CAAC;AAKrC,eAAO,MAAM,WAAW,cAAc,CAAC;AAavC,eAAO,MAAM,SAAS,YAAY,CAAC;AAInC,eAAO,MAAM,QAAQ,MAAM,CAAC;AAK5B,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAKnD,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAM7C,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAI3C,eAAO,MAAM,QAAQ,kBAAuB,CAAC;AAK7C,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;AAYzD,eAAO,MAAM,UAAU,aAAa,CAAC;AAIrC,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAI/C,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AACnD,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAGjD,eAAO,MAAM,UAAU,oBAAyB,CAAC;AAMjD,eAAO,MAAM,UAAU,aAAa,CAAC;AACrC,eAAO,MAAM,QAAQ,WAAW,CAAC;AACjC,eAAO,MAAM,QAAQ,WAAW,CAAC;AACjC,eAAO,MAAM,QAAQ,WAAW,CAAC;AACjC,eAAO,MAAM,QAAQ,WAAW,CAAC;AAEjC,eAAO,MAAM,UAAU,+DAMb,CAAC;AAKX,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAG7C,eAAO,MAAM,gBAAgB,MAAM,CAAC;AASpC,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAGjD,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAIjD,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAK7C,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AACrD,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAC3C,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAC3C,eAAO,MAAM,eAAe,UAAU,CAAC;AAKvC,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AACjD,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AAKrD,eAAO,MAAM,YAAY,eAAe,CAAC;AAIzC,eAAO,MAAM,aAAa,eAAe,CAAC;AAM1C,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AAIpD,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"lb-constants.d.ts","sourceRoot":"","sources":["../../core/lb-constants.ts"],"names":[],"mappings":"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"}
|
|
@@ -128,10 +128,43 @@ export const LB_DONE_EVENT_NAME = "lb-request-done";
|
|
|
128
128
|
// Stamped on the element that issued a request while its round trip is in
|
|
129
129
|
// flight, alongside aria-busy. A commit on an element carrying it is ignored.
|
|
130
130
|
export const ATTR_REQUEST_PENDING = "lb-request-pending";
|
|
131
|
+
// Stamped on the element that issued a request when its handler refused it:
|
|
132
|
+
// the refusal's message for the request as a whole, empty when it has none.
|
|
133
|
+
// Cleared at the start of that element's next request. A refusal is not a
|
|
134
|
+
// failure, and does not stamp ATTR_REQUEST_ERROR.
|
|
135
|
+
export const ATTR_REQUEST_REFUSED = "lb-request-refused";
|
|
136
|
+
// The status a refusal travels with. Every other failure is a 500 with no
|
|
137
|
+
// body, so nothing but a refusal's own words reaches the browser.
|
|
138
|
+
export const LB_REFUSAL_STATUS = 422;
|
|
131
139
|
// Stamped on the element that issued a request when its round trip failed —
|
|
132
140
|
// a non-2xx response, a thrown application error, or a timeout, all alike.
|
|
133
141
|
// Cleared at the start of that element's next request.
|
|
134
142
|
export const ATTR_REQUEST_ERROR = "lb-request-error";
|
|
143
|
+
// --- A form pointed at a row (docs/reference/data-binding.md) -----------
|
|
144
|
+
// One form edits any row of its query, or enters a new one. A button points
|
|
145
|
+
// it with HTML's own `commandfor="<form id>"` and one of these commands,
|
|
146
|
+
// which HTML requires to begin with `--`. The hub hears the `command` event
|
|
147
|
+
// on the form.
|
|
148
|
+
// From a button in a live row of the form's query: fill the form from that
|
|
149
|
+
// row, as the hub holds it, and key it by that row.
|
|
150
|
+
export const COMMAND_EDIT = "--lb-edit";
|
|
151
|
+
// From any button: start the form empty, for an insert.
|
|
152
|
+
export const COMMAND_NEW = "--lb-new";
|
|
153
|
+
// From any button: let the form go without saving.
|
|
154
|
+
export const COMMAND_RELEASE = "--lb-release";
|
|
155
|
+
export const LB_COMMANDS = [COMMAND_EDIT, COMMAND_NEW, COMMAND_RELEASE];
|
|
156
|
+
// Loadbare owns every command beginning with this prefix.
|
|
157
|
+
export const LB_COMMAND_PREFIX = "--lb-";
|
|
158
|
+
// Stamped by the hub on the live row a form is pointed at, until the form
|
|
159
|
+
// lets go of it.
|
|
160
|
+
export const ATTR_ROW_EDITING = "lb-row-editing";
|
|
161
|
+
// --- Selecting rows (docs/reference/data-binding.md) ---------------------
|
|
162
|
+
// On a checkbox in a row template: ticking it selects the live row it sits
|
|
163
|
+
// in. It is not a column and is not gathered as one. A request for the
|
|
164
|
+
// row's query that names no one row carries the keys of every row selected.
|
|
165
|
+
export const ATTR_SELECT = "lb-select";
|
|
166
|
+
// Stamped by the hub on a live row while its `lb-select` checkbox is ticked.
|
|
167
|
+
export const ATTR_ROW_SELECTED = "lb-row-selected";
|
|
135
168
|
// --- Reserved names ----------------------------------------------------
|
|
136
169
|
// Loadbare owns every name beginning with this prefix: attribute names, the
|
|
137
170
|
// values of its attributes, query names, request names, the column names of
|
|
@@ -149,9 +182,22 @@ export const LB_ROW_REQUESTS = [
|
|
|
149
182
|
REQUEST_ROW_DELETE,
|
|
150
183
|
];
|
|
151
184
|
// Loadbare also owns every method name on a custom element that begins with
|
|
152
|
-
// `lb` and a capital. These are the ones it calls (the
|
|
153
|
-
// core/lb-types.ts); the builder refuses a script that declares any other.
|
|
154
|
-
export const LB_METHODS = [
|
|
185
|
+
// `lb` and a capital. These are the ones it calls (the HubLifecycle interface
|
|
186
|
+
// in core/lb-types.ts); the builder refuses a script that declares any other.
|
|
187
|
+
export const LB_METHODS = [
|
|
188
|
+
"lbAttached",
|
|
189
|
+
"lbRowsLanded",
|
|
190
|
+
"lbRequestDone",
|
|
191
|
+
"lbDetached",
|
|
192
|
+
];
|
|
193
|
+
// The browser's lifecycle callbacks, which the hub's methods replace. The
|
|
194
|
+
// builder refuses a script that declares any of them.
|
|
195
|
+
export const BROWSER_LIFECYCLE = [
|
|
196
|
+
"connectedCallback",
|
|
197
|
+
"disconnectedCallback",
|
|
198
|
+
"adoptedCallback",
|
|
199
|
+
"connectedMoveCallback",
|
|
200
|
+
];
|
|
155
201
|
// --- Kinds --------------------------------------------------------------
|
|
156
202
|
export const KIND_ROW = "row";
|
|
157
203
|
export const KIND_ROWS = "rows";
|
|
@@ -193,6 +239,7 @@ export const DEVELOPER_ATTRIBUTES = [
|
|
|
193
239
|
ATTR_GROUP,
|
|
194
240
|
...AGGREGATES,
|
|
195
241
|
ATTR_REQUEST,
|
|
242
|
+
ATTR_SELECT,
|
|
196
243
|
ATTR_URL_LINK,
|
|
197
244
|
ATTR_URL_PUSH,
|
|
198
245
|
ATTR_URL_UNKNOWN,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-constants.js","sourceRoot":"","sources":["../../core/lb-constants.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,2DAA2D;AAC3D,kCAAkC;AAElC,4EAA4E;AAC5E,wEAAwE;AACxE,uEAAuE;AACvE,2EAA2E;AAC3E,2BAA2B;AAE3B,wEAAwE;AACxE,yDAAyD;AACzD,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;AAErC,wEAAwE;AACxE,2EAA2E;AAC3E,mCAAmC;AACnC,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AAEvC,4EAA4E;AAC5E,2EAA2E;AAC3E,4BAA4B;AAC5B,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,yEAAyE;AACzE,2EAA2E;AAC3E,6EAA6E;AAC7E,8EAA8E;AAC9E,kEAAkE;AAClE,MAAM,CAAC,MAAM,SAAS,GAAG,SAAS,CAAC;AAEnC,qEAAqE;AACrE,kEAAkE;AAClE,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAC;AAE5B,0EAA0E;AAC1E,2EAA2E;AAC3E,yBAAyB;AACzB,MAAM,CAAC,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAEnD,0EAA0E;AAC1E,wEAAwE;AACxE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAAC;AAE7C,2EAA2E;AAC3E,sEAAsE;AACtE,4EAA4E;AAC5E,qEAAqE;AACrE,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;AAE3C,4EAA4E;AAC5E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,aAAa,GAAG,CAAC;AAE7C,2EAA2E;AAC3E,mEAAmE;AACnE,+BAA+B;AAC/B,MAAM,CAAC,MAAM,oBAAoB,GAAG,oBAAoB,CAAC;AAEzD,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAE7E,4EAA4E;AAC5E,yEAAyE;AACzE,0EAA0E;AAC1E,0EAA0E;AAC1E,0EAA0E;AAC1E,kDAAkD;AAClD,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;AAErC,2EAA2E;AAC3E,mDAAmD;AACnD,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC;AAE/C,0EAA0E;AAC1E,eAAe;AACf,MAAM,CAAC,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AACnD,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAEjD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,eAAe,GAAG,CAAC;AAEjD,2EAA2E;AAC3E,0EAA0E;AAC1E,4EAA4E;AAC5E,uDAAuD;AACvD,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;AACrC,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC;AACjC,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC;AACjC,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC;AACjC,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAEjC,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;CACA,CAAC;AAEX,2EAA2E;AAC3E,0EAA0E;AAC1E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAE7C,wEAAwE;AACxE,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAEpC,2EAA2E;AAC3E,0EAA0E;AAC1E,4EAA4E;AAC5E,2EAA2E;AAC3E,2DAA2D;AAE3D,oDAAoD;AACpD,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAEjD,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAEjD,uEAAuE;AACvE,6DAA6D;AAC7D,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAAC;AAE7C,wEAAwE;AACxE,6EAA6E;AAC7E,oDAAoD;AACpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAAkB,CAAC;AACrD,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAC3C,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAC3C,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAEvC,6EAA6E;AAC7E,2EAA2E;AAC3E,kBAAkB;AAClB,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AACjD,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAAkB,CAAC;AAErD,2EAA2E;AAC3E,2EAA2E;AAC3E,6CAA6C;AAC7C,MAAM,CAAC,MAAM,YAAY,GAAG,YAAY,CAAC;AAEzC,2EAA2E;AAC3E,kCAAkC;AAClC,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAC;AAE1C,0EAA0E;AAC1E,sEAAsE;AACtE,2EAA2E;AAC3E,6BAA6B;AAC7B,MAAM,CAAC,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAEpD,0EAA0E;AAC1E,8EAA8E;AAC9E,MAAM,CAAC,MAAM,oBAAoB,GAAG,oBAAoB,CAAC;AAEzD,4EAA4E;AAC5E,2EAA2E;AAC3E,uDAAuD;AACvD,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAAkB,CAAC;AAErD,0EAA0E;AAC1E,4EAA4E;AAC5E,4EAA4E;AAC5E,4EAA4E;AAC5E,sDAAsD;AACtD,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAExC,4EAA4E;AAC5E,uBAAuB;AACvB,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAClD,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAClD,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAElD,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,kBAAkB;IAClB,kBAAkB;IAClB,kBAAkB;CACV,CAAC;AAEX,4EAA4E;AAC5E,6EAA6E;AAC7E,2EAA2E;AAC3E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,cAAc,CAAU,CAAC;AAEpD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAC9B,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC;AAEhC,2EAA2E;AAC3E,4EAA4E;AAC5E,uBAAuB;AACvB,MAAM,CAAC,MAAM,SAAS,GAAG,QAAQ,CAAC;AAClC,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAC;AACzC,MAAM,CAAC,MAAM,qBAAqB,GAAG,eAAe,CAAC;AACrD,MAAM,CAAC,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AAEzD,qEAAqE;AACrE,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;AAE3C,2EAA2E;AAC3E,kCAAkC;AAClC,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;AAE3C,6EAA6E;AAC7E,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAEjD,2EAA2E;AAC3E,0EAA0E;AAC1E,4EAA4E;AAC5E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;AAE3C,6EAA6E;AAC7E,wEAAwE;AACxE,kEAAkE;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAEnD,+CAA+C;AAC/C,MAAM,CAAC,MAAM,SAAS,GAAG,SAAS,CAAC;AAEnC,wEAAwE;AACxE,+CAA+C;AAC/C,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC;AAE/C,yEAAyE;AACzE,sEAAsE;AACtE,0CAA0C;AAC1C,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,UAAU;IACV,WAAW;IACX,SAAS;IACT,UAAU;IACV,GAAG,UAAU;IACb,YAAY;IACZ,aAAa;IACb,aAAa;IACb,gBAAgB;CACR,CAAC;AAEX,qEAAqE;AACrE,iFAAiF;AACjF,uEAAuE;AACvE,4EAA4E;AAC5E,qEAAqE;AACrE,qCAAqC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AAErC,0EAA0E;AAC1E,wEAAwE;AACxE,wEAAwE;AACxE,4EAA4E;AAC5E,0EAA0E;AAC1E,0EAA0E;AAC1E,iEAAiE;AACjE,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AAEjC,4EAA4E;AAC5E,kEAAkE;AAClE,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC","sourcesContent":["// Every Loadbare attribute name lives here. Nothing writes one as a string\n// literal — not a widget, not a page host, not a test. See\n// docs/reference/data-binding.md.\n\n// --- Landing (docs/reference/data-binding.md) ----------------------------\n// Everything is a query. The server answers every request with response\n// items, one per query, and each carries the query's kind and key. The\n// markup names a query and the columns it shows; it never repeats what the\n// server already declared.\n\n// Names the query whose rows land in an element's content. A nested one\n// begins a new query: what is inside it is that query's.\nexport const ATTR_QUERY = \"lb-query\";\n\n// The column an element shows, read from the nearest ancestor row. On a\n// control the hub sets its value, and gathers it back under this name when\n// the control's request is issued.\nexport const ATTR_COLUMN = \"lb-column\";\n\n// The column that decides whether an element is present: `null` and `false`\n// are off, and every other value is on. It reads from the nearest ancestor\n// row, as ATTR_COLUMN does.\n//\n// An element that is off is moved into a `<template>` carrying this attribute\n// and the same column, standing where the element stood, and moved back out\n// when the column turns on. The builder ships every such element already\n// inside its template. A developer writes this attribute on an element and\n// never on a template: the template form is Loadbare's, and holds the absent\n// branch in the document so the hub holds nothing. Landing reaches inside it,\n// so a branch that returns is already current; nothing else does.\nexport const ATTR_SHOW = \"lb-show\";\n\n// Written before the column in ATTR_SHOW, it reverses the condition:\n// `lb-show=\"!chosen\"` is present while `chosen` is null or false.\nexport const SHOW_NOT = \"!\";\n\n// Stamped by the hub on every element it sets from a column: the value it\n// set, so a stylesheet can select on it and a custom element that is not a\n// control can render it.\nexport const ATTR_COLUMN_VALUE = \"lb-column-value\";\n\n// Stamped by the hub on each live row, and on an element a `row` lands on\n// itself: the row's key. The key column is the query's, declared by the\n// server and carried by every response item.\nexport const ATTR_KEY_VALUE = \"lb-key-value\";\n\n// Stamped by the hub on each live row, and on nothing else: the element it\n// cloned from a row template. A key alone does not say so, because an\n// element a `row` lands on carries one too, and a live row may name a query\n// of its own, so neither the key nor `lb-query` tells the two apart.\nexport const ATTR_ROW_LIVE = \"lb-row-live\";\n\n// Selects a live row. Anything that walks rows — reconciliation, gathering,\n// a custom element's own placement — finds them with this and nothing else.\nexport const LIVE_ROW = `[${ATTR_ROW_LIVE}]`;\n\n// Stamped by the hub on an element with a row template: how many live rows\n// it holds, so \"no members yet\" is a stylesheet rule rather than a\n// conditional in every widget.\nexport const ATTR_QUERY_ROW_COUNT = \"lb-query-row-count\";\n\n// --- Order and groups (docs/reference/data-binding.md) -------------------\n// A `rows` query's order is a rule over its columns, and the hub places every\n// live row by it. A group is a run of rows sharing the order's leading term.\n\n// On a `<template>` inside an element naming a query: a group template. Its\n// content holds the group's heading and exactly one nested `<template>`,\n// which is where the group's contents go: the next group template, or, at\n// the innermost level, the row template. The nth group template breaks on\n// the order's nth term. The markup's nesting decides whether the contents\n// land inside the heading's element or beside it.\nexport const ATTR_GROUP = \"lb-group\";\n\n// Stamped by the hub on each top-level element of a group it built, and on\n// nothing else, as ATTR_ROW_LIVE is on a live row.\nexport const ATTR_GROUP_LIVE = \"lb-group-live\";\n\n// Stamped beside ATTR_GROUP_LIVE: the column the group breaks on, and its\n// value there.\nexport const ATTR_GROUP_COLUMN = \"lb-group-column\";\nexport const ATTR_GROUP_VALUE = \"lb-group-value\";\n\n// Selects a group's element, as LIVE_ROW selects a live row.\nexport const LIVE_GROUP = `[${ATTR_GROUP_LIVE}]`;\n\n// Aggregates, written on any element in a group template or in the element\n// naming the query: the hub sets the element from the rows of the nearest\n// group around it, or of the whole list outside any group. `lb-count` takes\n// no value; the others name the column they aggregate.\nexport const ATTR_COUNT = \"lb-count\";\nexport const ATTR_SUM = \"lb-sum\";\nexport const ATTR_AVG = \"lb-avg\";\nexport const ATTR_MIN = \"lb-min\";\nexport const ATTR_MAX = \"lb-max\";\n\nexport const AGGREGATES = [\n ATTR_COUNT,\n ATTR_SUM,\n ATTR_AVG,\n ATTR_MIN,\n ATTR_MAX,\n] as const;\n\n// The query parm that carries the user's order for one query: this prefix,\n// then the query's name. It replaces the order the server declared. It is\n// the one parm Loadbare gives a meaning, and it still reaches `contextFor`.\nexport const ORDER_PARM_PREFIX = \"lb-order-\";\n\n// Written before a column in an order, it sorts that column descending.\nexport const ORDER_DESCENDING = \"-\";\n\n// --- What happened to a row (docs/reference/data-binding.md) ------------\n// Every change the hub makes to a list is one a stylesheet can see, so an\n// application animates with CSS alone. The first three are cleared when the\n// hub next touches the row, and a stamp applied again is removed and added\n// as two changes, so an animation keyed to it plays again.\n\n// The row was created when the hub last touched it.\nexport const ATTR_ROW_CREATED = \"lb-row-created\";\n\n// The row's values changed when the hub last touched it.\nexport const ATTR_ROW_CHANGED = \"lb-row-changed\";\n\n// The row moved when the hub last touched it, because the order put it\n// somewhere else. A copy stays behind where it was, leaving.\nexport const ATTR_ROW_MOVED = \"lb-row-moved\";\n\n// What a request from this page did to the row: one of the three values\n// below. Cleared at every landing of the row's query, so a script reading it\n// after a landing reads only what that landing did.\nexport const ATTR_ROW_REQUESTED = \"lb-row-requested\";\nexport const REQUESTED_CREATED = \"created\";\nexport const REQUESTED_CHANGED = \"changed\";\nexport const REQUESTED_MOVED = \"moved\";\n\n// A row or a group on its way out. It is no longer live, takes no input, and\n// is removed once the animations running on it have finished, at once when\n// there are none.\nexport const ATTR_ROW_LEAVING = \"lb-row-leaving\";\nexport const ATTR_GROUP_LEAVING = \"lb-group-leaving\";\n\n// --- Requests (docs/reference/data-binding.md) --------------------------\n// Names the request an element issues when it commits: a form on submit, a\n// control on change, anything else on click.\nexport const ATTR_REQUEST = \"lb-request\";\n\n// Every request travels as one bubbling event of this name, whoever issued\n// it, so an ancestor may stop it.\nexport const LB_EVENT_NAME = \"lb-request\";\n\n// The counterpart of LB_EVENT_NAME: raised on the element that committed,\n// once what the request brought back has landed or the round trip has\n// failed. It bubbles, so the element that cares about the outcome need not\n// be the one that committed.\nexport const LB_DONE_EVENT_NAME = \"lb-request-done\";\n\n// Stamped on the element that issued a request while its round trip is in\n// flight, alongside aria-busy. A commit on an element carrying it is ignored.\nexport const ATTR_REQUEST_PENDING = \"lb-request-pending\";\n\n// Stamped on the element that issued a request when its round trip failed —\n// a non-2xx response, a thrown application error, or a timeout, all alike.\n// Cleared at the start of that element's next request.\nexport const ATTR_REQUEST_ERROR = \"lb-request-error\";\n\n// --- Reserved names ----------------------------------------------------\n// Loadbare owns every name beginning with this prefix: attribute names, the\n// values of its attributes, query names, request names, the column names of\n// its own queries, custom element names and event names. The server refuses\n// a page that declares a query or a request so named.\nexport const LB_RESERVED_PREFIX = \"lb-\";\n\n// The requests Loadbare provides. Each runs the page's crud declaration for\n// the request's query.\nexport const REQUEST_ROW_INSERT = \"lb-row-insert\";\nexport const REQUEST_ROW_UPDATE = \"lb-row-update\";\nexport const REQUEST_ROW_DELETE = \"lb-row-delete\";\n\nexport const LB_ROW_REQUESTS = [\n REQUEST_ROW_INSERT,\n REQUEST_ROW_UPDATE,\n REQUEST_ROW_DELETE,\n] as const;\n\n// Loadbare also owns every method name on a custom element that begins with\n// `lb` and a capital. These are the ones it calls (the RowsHost interface in\n// core/lb-types.ts); the builder refuses a script that declares any other.\nexport const LB_METHODS = [\"lbRowsLanded\"] as const;\n\n// --- Kinds --------------------------------------------------------------\nexport const KIND_ROW = \"row\";\nexport const KIND_ROWS = \"rows\";\n\n// --- The URL (docs/reference/chrome.md) ---------------------------------\n// The query the hub serves: one row, keyed by the path, whose other columns\n// are the query parms.\nexport const URL_QUERY = \"lb-url\";\nexport const URL_COLUMN_PATH = \"lb-path\";\nexport const URL_COLUMN_PAGE_LABEL = \"lb-page-label\";\nexport const URL_COLUMN_PAGE_UNKNOWN = \"lb-page-unknown\";\n\n// On an `<a>`: a plain primary click sets `lb-path` from the `href`.\nexport const ATTR_URL_LINK = \"lb-url-link\";\n\n// On an element with `lb-request`: its update of `lb-url` pushes a history\n// entry instead of replacing one.\nexport const ATTR_URL_PUSH = \"lb-url-push\";\n\n// On a `<dialog>`: the hub calls showModal() when `lb-page-unknown` is true.\nexport const ATTR_URL_UNKNOWN = \"lb-url-unknown\";\n\n// --- Build time (docs/reference/custom-elements.md) ---------------------\n// Marks the element in an element file whose children receive the rest of\n// the custom element's content. An attribute rather than an element because\n// HTML content models discard foreign elements inside <select> and <table>.\nexport const ATTR_EXP_SLOT = \"lb-exp-slot\";\n\n// One name in two positions. In an element file it marks a destination; on a\n// `<template>` in the custom element's content it names the destination\n// that template is for, and the template's content moves into it.\nexport const ATTR_EXP_TEMPLATE = \"lb-exp-template\";\n\n// A page ships as <template lb-page=\"<stub>\">.\nexport const ATTR_PAGE = \"lb-page\";\n\n// Stamped by the builder beside ATTR_PAGE: the text content of the page\n// file's `<title>`, which the builder removes.\nexport const ATTR_PAGE_TITLE = \"lb-page-title\";\n\n// The attributes a developer writes. The builder refuses any other `lb-`\n// attribute in markup: the rest are stamps, written by the hub or the\n// builder and never by hand or by script.\nexport const DEVELOPER_ATTRIBUTES = [\n ATTR_QUERY,\n ATTR_COLUMN,\n ATTR_SHOW,\n ATTR_GROUP,\n ...AGGREGATES,\n ATTR_REQUEST,\n ATTR_URL_LINK,\n ATTR_URL_PUSH,\n ATTR_URL_UNKNOWN,\n] as const;\n\n// The hub's own tag. It is exempt from the rule every other LB-* tag\n// follows: expansion does not require it to have a definition (build/expand.ts),\n// and the client build does not require it to have a script of its own\n// (build/elements.ts) — it is the framework's live element, always present,\n// registered once by the package's main entry point, not a widget an\n// application discovers or declares.\nexport const HUB_TAG_NAME = \"lb-hub\";\n\n// --- Wire --------------------------------------------------------------\n// One path, one method: everything the hub asks of the server is a POST\n// below this path. The page's stub follows it, and the query string the\n// browser is showing rides after that verbatim, so `/accounts?acct=23` asks\n// as `POST /lb/accounts?acct=23` and the server always knows what URL the\n// browser is showing. Navigation is therefore the only GET an application\n// serves, which is what leaves the page name space unrestricted.\nexport const LB_ENDPOINT = \"/lb\";\n\n// A client-side deadline for one round trip. fetch() has no deadline of its\n// own; past this the request is aborted and treated as a failure.\nexport const LB_REQUEST_TIMEOUT_MS = 10_000;\n"]}
|
|
1
|
+
{"version":3,"file":"lb-constants.js","sourceRoot":"","sources":["../../core/lb-constants.ts"],"names":[],"mappings":"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","sourcesContent":["// Every Loadbare attribute name lives here. Nothing writes one as a string\n// literal — not a widget, not a page host, not a test. See\n// docs/reference/data-binding.md.\n\n// --- Landing (docs/reference/data-binding.md) ----------------------------\n// Everything is a query. The server answers every request with response\n// items, one per query, and each carries the query's kind and key. The\n// markup names a query and the columns it shows; it never repeats what the\n// server already declared.\n\n// Names the query whose rows land in an element's content. A nested one\n// begins a new query: what is inside it is that query's.\nexport const ATTR_QUERY = \"lb-query\";\n\n// The column an element shows, read from the nearest ancestor row. On a\n// control the hub sets its value, and gathers it back under this name when\n// the control's request is issued.\nexport const ATTR_COLUMN = \"lb-column\";\n\n// The column that decides whether an element is present: `null` and `false`\n// are off, and every other value is on. It reads from the nearest ancestor\n// row, as ATTR_COLUMN does.\n//\n// An element that is off is moved into a `<template>` carrying this attribute\n// and the same column, standing where the element stood, and moved back out\n// when the column turns on. The builder ships every such element already\n// inside its template. A developer writes this attribute on an element and\n// never on a template: the template form is Loadbare's, and holds the absent\n// branch in the document so the hub holds nothing. Landing reaches inside it,\n// so a branch that returns is already current; nothing else does.\nexport const ATTR_SHOW = \"lb-show\";\n\n// Written before the column in ATTR_SHOW, it reverses the condition:\n// `lb-show=\"!chosen\"` is present while `chosen` is null or false.\nexport const SHOW_NOT = \"!\";\n\n// Stamped by the hub on every element it sets from a column: the value it\n// set, so a stylesheet can select on it and a custom element that is not a\n// control can render it.\nexport const ATTR_COLUMN_VALUE = \"lb-column-value\";\n\n// Stamped by the hub on each live row, and on an element a `row` lands on\n// itself: the row's key. The key column is the query's, declared by the\n// server and carried by every response item.\nexport const ATTR_KEY_VALUE = \"lb-key-value\";\n\n// Stamped by the hub on each live row, and on nothing else: the element it\n// cloned from a row template. A key alone does not say so, because an\n// element a `row` lands on carries one too, and a live row may name a query\n// of its own, so neither the key nor `lb-query` tells the two apart.\nexport const ATTR_ROW_LIVE = \"lb-row-live\";\n\n// Selects a live row. Anything that walks rows — reconciliation, gathering,\n// a custom element's own placement — finds them with this and nothing else.\nexport const LIVE_ROW = `[${ATTR_ROW_LIVE}]`;\n\n// Stamped by the hub on an element with a row template: how many live rows\n// it holds, so \"no members yet\" is a stylesheet rule rather than a\n// conditional in every widget.\nexport const ATTR_QUERY_ROW_COUNT = \"lb-query-row-count\";\n\n// --- Order and groups (docs/reference/data-binding.md) -------------------\n// A `rows` query's order is a rule over its columns, and the hub places every\n// live row by it. A group is a run of rows sharing the order's leading term.\n\n// On a `<template>` inside an element naming a query: a group template. Its\n// content holds the group's heading and exactly one nested `<template>`,\n// which is where the group's contents go: the next group template, or, at\n// the innermost level, the row template. The nth group template breaks on\n// the order's nth term. The markup's nesting decides whether the contents\n// land inside the heading's element or beside it.\nexport const ATTR_GROUP = \"lb-group\";\n\n// Stamped by the hub on each top-level element of a group it built, and on\n// nothing else, as ATTR_ROW_LIVE is on a live row.\nexport const ATTR_GROUP_LIVE = \"lb-group-live\";\n\n// Stamped beside ATTR_GROUP_LIVE: the column the group breaks on, and its\n// value there.\nexport const ATTR_GROUP_COLUMN = \"lb-group-column\";\nexport const ATTR_GROUP_VALUE = \"lb-group-value\";\n\n// Selects a group's element, as LIVE_ROW selects a live row.\nexport const LIVE_GROUP = `[${ATTR_GROUP_LIVE}]`;\n\n// Aggregates, written on any element in a group template or in the element\n// naming the query: the hub sets the element from the rows of the nearest\n// group around it, or of the whole list outside any group. `lb-count` takes\n// no value; the others name the column they aggregate.\nexport const ATTR_COUNT = \"lb-count\";\nexport const ATTR_SUM = \"lb-sum\";\nexport const ATTR_AVG = \"lb-avg\";\nexport const ATTR_MIN = \"lb-min\";\nexport const ATTR_MAX = \"lb-max\";\n\nexport const AGGREGATES = [\n ATTR_COUNT,\n ATTR_SUM,\n ATTR_AVG,\n ATTR_MIN,\n ATTR_MAX,\n] as const;\n\n// The query parm that carries the user's order for one query: this prefix,\n// then the query's name. It replaces the order the server declared. It is\n// the one parm Loadbare gives a meaning, and it still reaches `contextFor`.\nexport const ORDER_PARM_PREFIX = \"lb-order-\";\n\n// Written before a column in an order, it sorts that column descending.\nexport const ORDER_DESCENDING = \"-\";\n\n// --- What happened to a row (docs/reference/data-binding.md) ------------\n// Every change the hub makes to a list is one a stylesheet can see, so an\n// application animates with CSS alone. The first three are cleared when the\n// hub next touches the row, and a stamp applied again is removed and added\n// as two changes, so an animation keyed to it plays again.\n\n// The row was created when the hub last touched it.\nexport const ATTR_ROW_CREATED = \"lb-row-created\";\n\n// The row's values changed when the hub last touched it.\nexport const ATTR_ROW_CHANGED = \"lb-row-changed\";\n\n// The row moved when the hub last touched it, because the order put it\n// somewhere else. A copy stays behind where it was, leaving.\nexport const ATTR_ROW_MOVED = \"lb-row-moved\";\n\n// What a request from this page did to the row: one of the three values\n// below. Cleared at every landing of the row's query, so a script reading it\n// after a landing reads only what that landing did.\nexport const ATTR_ROW_REQUESTED = \"lb-row-requested\";\nexport const REQUESTED_CREATED = \"created\";\nexport const REQUESTED_CHANGED = \"changed\";\nexport const REQUESTED_MOVED = \"moved\";\n\n// A row or a group on its way out. It is no longer live, takes no input, and\n// is removed once the animations running on it have finished, at once when\n// there are none.\nexport const ATTR_ROW_LEAVING = \"lb-row-leaving\";\nexport const ATTR_GROUP_LEAVING = \"lb-group-leaving\";\n\n// --- Requests (docs/reference/data-binding.md) --------------------------\n// Names the request an element issues when it commits: a form on submit, a\n// control on change, anything else on click.\nexport const ATTR_REQUEST = \"lb-request\";\n\n// Every request travels as one bubbling event of this name, whoever issued\n// it, so an ancestor may stop it.\nexport const LB_EVENT_NAME = \"lb-request\";\n\n// The counterpart of LB_EVENT_NAME: raised on the element that committed,\n// once what the request brought back has landed or the round trip has\n// failed. It bubbles, so the element that cares about the outcome need not\n// be the one that committed.\nexport const LB_DONE_EVENT_NAME = \"lb-request-done\";\n\n// Stamped on the element that issued a request while its round trip is in\n// flight, alongside aria-busy. A commit on an element carrying it is ignored.\nexport const ATTR_REQUEST_PENDING = \"lb-request-pending\";\n\n// Stamped on the element that issued a request when its handler refused it:\n// the refusal's message for the request as a whole, empty when it has none.\n// Cleared at the start of that element's next request. A refusal is not a\n// failure, and does not stamp ATTR_REQUEST_ERROR.\nexport const ATTR_REQUEST_REFUSED = \"lb-request-refused\";\n\n// The status a refusal travels with. Every other failure is a 500 with no\n// body, so nothing but a refusal's own words reaches the browser.\nexport const LB_REFUSAL_STATUS = 422;\n\n// Stamped on the element that issued a request when its round trip failed —\n// a non-2xx response, a thrown application error, or a timeout, all alike.\n// Cleared at the start of that element's next request.\nexport const ATTR_REQUEST_ERROR = \"lb-request-error\";\n\n// --- A form pointed at a row (docs/reference/data-binding.md) -----------\n// One form edits any row of its query, or enters a new one. A button points\n// it with HTML's own `commandfor=\"<form id>\"` and one of these commands,\n// which HTML requires to begin with `--`. The hub hears the `command` event\n// on the form.\n\n// From a button in a live row of the form's query: fill the form from that\n// row, as the hub holds it, and key it by that row.\nexport const COMMAND_EDIT = \"--lb-edit\";\n\n// From any button: start the form empty, for an insert.\nexport const COMMAND_NEW = \"--lb-new\";\n\n// From any button: let the form go without saving.\nexport const COMMAND_RELEASE = \"--lb-release\";\n\nexport const LB_COMMANDS = [COMMAND_EDIT, COMMAND_NEW, COMMAND_RELEASE] as const;\n\n// Loadbare owns every command beginning with this prefix.\nexport const LB_COMMAND_PREFIX = \"--lb-\";\n\n// Stamped by the hub on the live row a form is pointed at, until the form\n// lets go of it.\nexport const ATTR_ROW_EDITING = \"lb-row-editing\";\n\n// --- Selecting rows (docs/reference/data-binding.md) ---------------------\n// On a checkbox in a row template: ticking it selects the live row it sits\n// in. It is not a column and is not gathered as one. A request for the\n// row's query that names no one row carries the keys of every row selected.\nexport const ATTR_SELECT = \"lb-select\";\n\n// Stamped by the hub on a live row while its `lb-select` checkbox is ticked.\nexport const ATTR_ROW_SELECTED = \"lb-row-selected\";\n\n// --- Reserved names ----------------------------------------------------\n// Loadbare owns every name beginning with this prefix: attribute names, the\n// values of its attributes, query names, request names, the column names of\n// its own queries, custom element names and event names. The server refuses\n// a page that declares a query or a request so named.\nexport const LB_RESERVED_PREFIX = \"lb-\";\n\n// The requests Loadbare provides. Each runs the page's crud declaration for\n// the request's query.\nexport const REQUEST_ROW_INSERT = \"lb-row-insert\";\nexport const REQUEST_ROW_UPDATE = \"lb-row-update\";\nexport const REQUEST_ROW_DELETE = \"lb-row-delete\";\n\nexport const LB_ROW_REQUESTS = [\n REQUEST_ROW_INSERT,\n REQUEST_ROW_UPDATE,\n REQUEST_ROW_DELETE,\n] as const;\n\n// Loadbare also owns every method name on a custom element that begins with\n// `lb` and a capital. These are the ones it calls (the HubLifecycle interface\n// in core/lb-types.ts); the builder refuses a script that declares any other.\nexport const LB_METHODS = [\n \"lbAttached\",\n \"lbRowsLanded\",\n \"lbRequestDone\",\n \"lbDetached\",\n] as const;\n\n// The browser's lifecycle callbacks, which the hub's methods replace. The\n// builder refuses a script that declares any of them.\nexport const BROWSER_LIFECYCLE = [\n \"connectedCallback\",\n \"disconnectedCallback\",\n \"adoptedCallback\",\n \"connectedMoveCallback\",\n] as const;\n\n// --- Kinds --------------------------------------------------------------\nexport const KIND_ROW = \"row\";\nexport const KIND_ROWS = \"rows\";\n\n// --- The URL (docs/reference/chrome.md) ---------------------------------\n// The query the hub serves: one row, keyed by the path, whose other columns\n// are the query parms.\nexport const URL_QUERY = \"lb-url\";\nexport const URL_COLUMN_PATH = \"lb-path\";\nexport const URL_COLUMN_PAGE_LABEL = \"lb-page-label\";\nexport const URL_COLUMN_PAGE_UNKNOWN = \"lb-page-unknown\";\n\n// On an `<a>`: a plain primary click sets `lb-path` from the `href`.\nexport const ATTR_URL_LINK = \"lb-url-link\";\n\n// On an element with `lb-request`: its update of `lb-url` pushes a history\n// entry instead of replacing one.\nexport const ATTR_URL_PUSH = \"lb-url-push\";\n\n// On a `<dialog>`: the hub calls showModal() when `lb-page-unknown` is true.\nexport const ATTR_URL_UNKNOWN = \"lb-url-unknown\";\n\n// --- Build time (docs/reference/custom-elements.md) ---------------------\n// Marks the element in an element file whose children receive the rest of\n// the custom element's content. An attribute rather than an element because\n// HTML content models discard foreign elements inside <select> and <table>.\nexport const ATTR_EXP_SLOT = \"lb-exp-slot\";\n\n// One name in two positions. In an element file it marks a destination; on a\n// `<template>` in the custom element's content it names the destination\n// that template is for, and the template's content moves into it.\nexport const ATTR_EXP_TEMPLATE = \"lb-exp-template\";\n\n// A page ships as <template lb-page=\"<stub>\">.\nexport const ATTR_PAGE = \"lb-page\";\n\n// Stamped by the builder beside ATTR_PAGE: the text content of the page\n// file's `<title>`, which the builder removes.\nexport const ATTR_PAGE_TITLE = \"lb-page-title\";\n\n// The attributes a developer writes. The builder refuses any other `lb-`\n// attribute in markup: the rest are stamps, written by the hub or the\n// builder and never by hand or by script.\nexport const DEVELOPER_ATTRIBUTES = [\n ATTR_QUERY,\n ATTR_COLUMN,\n ATTR_SHOW,\n ATTR_GROUP,\n ...AGGREGATES,\n ATTR_REQUEST,\n ATTR_SELECT,\n ATTR_URL_LINK,\n ATTR_URL_PUSH,\n ATTR_URL_UNKNOWN,\n] as const;\n\n// The hub's own tag. It is exempt from the rule every other LB-* tag\n// follows: expansion does not require it to have a definition (build/expand.ts),\n// and the client build does not require it to have a script of its own\n// (build/elements.ts) — it is the framework's live element, always present,\n// registered once by the package's main entry point, not a widget an\n// application discovers or declares.\nexport const HUB_TAG_NAME = \"lb-hub\";\n\n// --- Wire --------------------------------------------------------------\n// One path, one method: everything the hub asks of the server is a POST\n// below this path. The page's stub follows it, and the query string the\n// browser is showing rides after that verbatim, so `/accounts?acct=23` asks\n// as `POST /lb/accounts?acct=23` and the server always knows what URL the\n// browser is showing. Navigation is therefore the only GET an application\n// serves, which is what leaves the page name space unrestricted.\nexport const LB_ENDPOINT = \"/lb\";\n\n// A client-side deadline for one round trip. fetch() has no deadline of its\n// own; past this the request is aborted and treated as a failure.\nexport const LB_REQUEST_TIMEOUT_MS = 10_000;\n"]}
|