@loadbare/app 0.5.6 → 0.6.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/README.md +3 -4
- package/dist/build/assemble.d.ts +1 -1
- package/dist/build/assemble.d.ts.map +1 -1
- package/dist/build/assemble.js +80 -7
- package/dist/build/cli.d.ts +2 -2
- package/dist/build/cli.js +2 -2
- package/dist/build/expand.d.ts.map +1 -1
- package/dist/build/expand.js +19 -32
- package/dist/build/locations.d.ts +3 -3
- package/dist/build/locations.d.ts.map +1 -1
- package/dist/build/locations.js +15 -3
- package/dist/build/origins.d.ts +0 -13
- package/dist/build/origins.d.ts.map +1 -1
- package/dist/build/origins.js +32 -8
- package/dist/build/pages.d.ts +3 -3
- package/dist/build/pages.d.ts.map +1 -1
- package/dist/build/pages.js +9 -7
- package/dist/core/lb-constants.d.ts +15 -13
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +103 -53
- package/dist/core/lb-types.d.ts +103 -62
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js +11 -3
- package/dist/hub/lb-apply.d.ts +18 -4
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +184 -34
- package/dist/hub/lb-hub.browser.d.ts +1 -1
- package/dist/hub/lb-hub.browser.d.ts.map +1 -1
- package/dist/hub/lb-hub.browser.js +131 -84
- package/dist/server/lb-express.d.ts +7 -4
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +45 -33
- package/dist/server/lb-server.d.ts +67 -45
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +55 -18
- package/dist/tests/assemble.test.js +154 -2
- package/dist/tests/expand.test.js +6 -3
- package/dist/tests/helpers/hub.d.ts +73 -0
- package/dist/tests/helpers/hub.d.ts.map +1 -0
- package/dist/tests/helpers/hub.js +151 -0
- package/dist/tests/lb-apply.test.js +86 -62
- package/dist/tests/lb-express.test.d.ts +1 -1
- package/dist/tests/lb-express.test.js +43 -38
- package/dist/tests/lb-hub.test.d.ts +14 -0
- package/dist/tests/lb-hub.test.d.ts.map +1 -0
- package/dist/tests/lb-hub.test.js +319 -0
- package/dist/tests/{lb-rows.test.d.ts → lb-list.test.d.ts} +1 -1
- package/dist/tests/lb-list.test.d.ts.map +1 -0
- package/dist/tests/{lb-rows.test.js → lb-list.test.js} +109 -106
- package/dist/tests/lb-server.test.js +151 -100
- package/dist/tests/origins.test.js +19 -1
- package/dist/tests/pages.test.d.ts +1 -1
- package/dist/tests/pages.test.js +64 -14
- package/docs/TECHREF-1.0.md +1000 -0
- package/docs/reference/builder.md +4 -4
- package/docs/reference/chrome.md +10 -9
- package/docs/reference/custom-elements.md +51 -36
- package/docs/reference/data-binding.md +141 -88
- package/docs/reference/overview.md +1 -1
- package/docs/reference/page-files.md +64 -49
- package/docs/reference/server.md +7 -6
- package/docs/reference/widgets.md +22 -30
- package/docs/roadmap.md +68 -22
- package/docs/testing.md +47 -17
- package/docs/theory.md +2 -2
- package/docs/tutorials/010-pages-and-navigation.md +8 -8
- package/docs/tutorials/040-displaying-data.md +9 -9
- package/docs/tutorials/050-actions.md +5 -5
- package/docs/tutorials/060-custom-element-code.md +1 -1
- package/docs/tutorials/065-conditional-rendering.md +4 -4
- package/docs/tutorials/070-displaying-a-list.md +24 -47
- package/docs/tutorials/072-inserting-into-a-list.md +17 -17
- package/docs/tutorials/074-deleting-from-a-list.md +15 -17
- package/docs/tutorials/076-updating-a-list-item.md +20 -22
- package/docs/tutorials/080-widget-requests.md +27 -23
- package/docs/tutorials/090-using-widget-libraries.md +1 -1
- package/package.json +1 -2
- package/dist/hub/lb-rows.d.ts +0 -18
- package/dist/hub/lb-rows.d.ts.map +0 -1
- package/dist/hub/lb-rows.js +0 -106
- package/dist/tests/lb-rows.test.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -4,17 +4,18 @@ The fundamentals of @loadbare/app are fixed, we are now working
|
|
|
4
4
|
on completeness.
|
|
5
5
|
|
|
6
6
|
> This package is being prepped for 1.0, current work is:
|
|
7
|
+
>
|
|
7
8
|
> 1. docs (nearly done)
|
|
8
9
|
> 2. demos (must be normalized and checked against docs)
|
|
9
10
|
> 3. test a release/use cycle, make sure all instructions work
|
|
10
11
|
|
|
11
|
-
|
|
12
12
|
## Purpose
|
|
13
13
|
|
|
14
14
|
Loadbare App is a web app framework built specifically to deliver high performance
|
|
15
|
-
to the user for server-bound applications.
|
|
15
|
+
to the user for server-bound applications.
|
|
16
16
|
|
|
17
17
|
Loadbare App has two twin primary goals
|
|
18
|
+
|
|
18
19
|
- To follow the loadbare philosophy of reducing accidental complexity
|
|
19
20
|
to near zero, so the app developer is spending maximum time on the app
|
|
20
21
|
instead of the tooling.
|
|
@@ -62,5 +63,3 @@ each lesson.
|
|
|
62
63
|
## Roadmap Items for 1.0 and 1.1
|
|
63
64
|
|
|
64
65
|
[Roadmap](./docs/roadmap.md)
|
|
65
|
-
|
|
66
|
-
|
package/dist/build/assemble.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* built-in widgets and whatever definitions were found in the caller's own
|
|
7
7
|
* source tree. `expand()` only ever sees a fragment, so the chrome's own is
|
|
8
8
|
* the text between its `<body>` tags; a page's is the whole file. A page's
|
|
9
|
-
* expanded host is wrapped in `<template
|
|
9
|
+
* expanded host is wrapped in `<template lb-page="<name>">` and, together
|
|
10
10
|
* with the chrome's own expanded body content, spliced back into the
|
|
11
11
|
* chrome's `<body>`. The result is the one document a server has to serve
|
|
12
12
|
* for every route — see docs/tutorials/000-getting-started.md and
|
|
@@ -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;AAoBH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAwH/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,CA2CtC"}
|
package/dist/build/assemble.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* built-in widgets and whatever definitions were found in the caller's own
|
|
7
7
|
* source tree. `expand()` only ever sees a fragment, so the chrome's own is
|
|
8
8
|
* the text between its `<body>` tags; a page's is the whole file. A page's
|
|
9
|
-
* expanded host is wrapped in `<template
|
|
9
|
+
* expanded host is wrapped in `<template lb-page="<name>">` and, together
|
|
10
10
|
* with the chrome's own expanded body content, spliced back into the
|
|
11
11
|
* chrome's `<body>`. The result is the one document a server has to serve
|
|
12
12
|
* for every route — see docs/tutorials/000-getting-started.md and
|
|
@@ -20,12 +20,17 @@ import { readFile } from "node:fs/promises";
|
|
|
20
20
|
import { JSDOM } from "jsdom";
|
|
21
21
|
import { addDefinitions, customElementTags, expand, } from "./expand.js";
|
|
22
22
|
import { formatHtml } from "./format.js";
|
|
23
|
-
import { ATTR_UNKNOWN_PAGE,
|
|
23
|
+
import { ATTR_CELL, ATTR_KEY, ATTR_LIST, ATTR_PAGE, ATTR_ROW, ATTR_UNKNOWN_PAGE, HUB_TAG_NAME, } from "../core/lb-constants.js";
|
|
24
24
|
/**
|
|
25
|
-
* The hub calls showModal() on whatever carries lb-unknown-page
|
|
26
|
-
* so a chrome that puts the attribute on anything
|
|
27
|
-
* runtime, on whichever page happens to 404 first, rather
|
|
28
|
-
* time. The attribute is optional;
|
|
25
|
+
* The hub calls showModal() on whatever carries lb-unknown-page
|
|
26
|
+
* (hub/lb-hub.browser.ts), so a chrome that puts the attribute on anything
|
|
27
|
+
* else would fail at runtime, on whichever page happens to 404 first, rather
|
|
28
|
+
* than at build time. The attribute is optional; a wrong element on it, or a
|
|
29
|
+
* right one out of the hub's reach, is an error.
|
|
30
|
+
*
|
|
31
|
+
* Out of reach because the hub looks for the dialog inside itself, as it
|
|
32
|
+
* does for everything else it acts on. A dialog elsewhere in the body would
|
|
33
|
+
* never open and would say nothing about why.
|
|
29
34
|
*/
|
|
30
35
|
function checkUnknownPageDialog(chromeFile, expandedBody) {
|
|
31
36
|
const fragment = JSDOM.fragment(expandedBody);
|
|
@@ -36,6 +41,72 @@ function checkUnknownPageDialog(chromeFile, expandedBody) {
|
|
|
36
41
|
throw new Error(`assemble: '${chromeFile}' declares ${ATTR_UNKNOWN_PAGE} on ` +
|
|
37
42
|
`<${el.tagName.toLowerCase()}>, must be a <dialog>`);
|
|
38
43
|
}
|
|
44
|
+
if (!el.closest(HUB_TAG_NAME)) {
|
|
45
|
+
throw new Error(`assemble: '${chromeFile}' declares ${ATTR_UNKNOWN_PAGE} outside ` +
|
|
46
|
+
`<${HUB_TAG_NAME}>, where the hub cannot reach it`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The binding vocabulary, checked once against the finished document rather
|
|
51
|
+
* than discovered one console error at a time in a browser.
|
|
52
|
+
*
|
|
53
|
+
* Everything here is a fact the markup states about itself, so none of it
|
|
54
|
+
* needs the server: a key is named on a row template, a row template belongs
|
|
55
|
+
* to a list, and a cell belongs to a scope. What the markup and the server
|
|
56
|
+
* say about cardinality cannot be compared here, because they are separate
|
|
57
|
+
* artifacts — createHub holds that check. See docs/reference/data-binding.md.
|
|
58
|
+
*
|
|
59
|
+
* A list scope with no row template is not an error. It is bound to the list
|
|
60
|
+
* without displaying it, which is what an insert form naming the list it adds
|
|
61
|
+
* to already is.
|
|
62
|
+
*
|
|
63
|
+
* A `<template>`'s children are walked in the scope that encloses the
|
|
64
|
+
* template, because a row template's clones land in the list around it.
|
|
65
|
+
*/
|
|
66
|
+
function walkBinding(node, scope, problems) {
|
|
67
|
+
for (const el of node.children) {
|
|
68
|
+
const listName = el.getAttribute(ATTR_LIST);
|
|
69
|
+
const rowName = el.getAttribute(ATTR_ROW);
|
|
70
|
+
const tag = el.localName;
|
|
71
|
+
let here = scope;
|
|
72
|
+
if (listName !== null && rowName !== null) {
|
|
73
|
+
problems.push(`<${tag}> carries both ${ATTR_LIST} and ${ATTR_ROW}; a scope is ` +
|
|
74
|
+
`one or the other, and a name answers with one shape`);
|
|
75
|
+
}
|
|
76
|
+
if (listName !== null)
|
|
77
|
+
here = { kind: "list", name: listName };
|
|
78
|
+
else if (rowName !== null)
|
|
79
|
+
here = { kind: "row", name: rowName };
|
|
80
|
+
if (el.hasAttribute(ATTR_CELL) && here === null) {
|
|
81
|
+
problems.push(`<${tag}> carries ${ATTR_CELL}="${el.getAttribute(ATTR_CELL)}" with ` +
|
|
82
|
+
`no ${ATTR_LIST} or ${ATTR_ROW} scope around it`);
|
|
83
|
+
}
|
|
84
|
+
if (el.hasAttribute(ATTR_KEY)) {
|
|
85
|
+
if (tag !== "template") {
|
|
86
|
+
problems.push(`<${tag}> carries ${ATTR_KEY}; it names the column that identifies ` +
|
|
87
|
+
`a row and belongs on the row <template>`);
|
|
88
|
+
}
|
|
89
|
+
else if (here === null || here.kind !== "list") {
|
|
90
|
+
problems.push(`a <template> carries ${ATTR_KEY} outside any ${ATTR_LIST} scope; ` +
|
|
91
|
+
`only a list has rows to identify`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
walkBinding(el, here, problems);
|
|
95
|
+
// By tag name rather than by instanceof: JSDOM.fragment() parses into a
|
|
96
|
+
// document with no window, so the constructor is not reachable from the
|
|
97
|
+
// node.
|
|
98
|
+
if (tag === "template") {
|
|
99
|
+
walkBinding(el.content, here, problems);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Check one expanded fragment, and name the file if anything is wrong. */
|
|
104
|
+
function checkBinding(file, html) {
|
|
105
|
+
const problems = [];
|
|
106
|
+
walkBinding(JSDOM.fragment(html), null, problems);
|
|
107
|
+
if (problems.length > 0) {
|
|
108
|
+
throw new Error(`assemble: '${file}' binding:\n ` + problems.join(`\n `));
|
|
109
|
+
}
|
|
39
110
|
}
|
|
40
111
|
export async function assemble({ chromeFile, pages, scans, }) {
|
|
41
112
|
// One layer per origin, in order, so a later origin's definition overrides
|
|
@@ -49,7 +120,8 @@ export async function assemble({ chromeFile, pages, scans, }) {
|
|
|
49
120
|
for (const { name, file } of pages) {
|
|
50
121
|
const authored = await readFile(file, "utf-8");
|
|
51
122
|
const host = expand(authored, defs);
|
|
52
|
-
|
|
123
|
+
checkBinding(file, host);
|
|
124
|
+
templates.push(`<template ${ATTR_PAGE}="${name}">${host}</template>`);
|
|
53
125
|
}
|
|
54
126
|
let chromeSource;
|
|
55
127
|
try {
|
|
@@ -65,6 +137,7 @@ export async function assemble({ chromeFile, pages, scans, }) {
|
|
|
65
137
|
const [whole, bodyAttrs, bodyContent] = body;
|
|
66
138
|
const expandedBody = expand(bodyContent, defs);
|
|
67
139
|
checkUnknownPageDialog(chromeFile, expandedBody);
|
|
140
|
+
checkBinding(chromeFile, expandedBody);
|
|
68
141
|
const withPages = chromeSource.replace(whole, () => `<body${bodyAttrs}>${expandedBody}\n${templates.join("\n")}\n</body>`);
|
|
69
142
|
return {
|
|
70
143
|
html: await formatHtml(withPages),
|
package/dist/build/cli.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* loadbare-app-build [--src src] [--out dist] [--watch] [--minify]
|
|
8
8
|
*
|
|
9
9
|
* `--src` names the application's own tree: the one `chrome.html` file,
|
|
10
|
-
* every `*.page.html` page, its `*.
|
|
10
|
+
* every `*.page.html` page, its `*.requests.ts`/`*.queries.ts` pairs, and
|
|
11
11
|
* `imports.ts` if there is one — see build/locations.ts. It is also the last
|
|
12
12
|
* origin in the cascade that supplies widget definitions, widget scripts and
|
|
13
13
|
* stylesheets; this package's own widgets come first and each package named
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* The assembled document is written to `<out>/app.html`; the client bundle
|
|
18
18
|
* to `<out>/client.js`, by way of a generated `<out>/client-entry.ts` — see
|
|
19
19
|
* build/elements.ts for how a tag is resolved to the script that registers
|
|
20
|
-
* it. When any page has a
|
|
20
|
+
* it. When any page has a requests or queries file, the hub registry that used
|
|
21
21
|
* to be hand-maintained is written to `<out>/pages.ts` — see build/pages.ts.
|
|
22
22
|
* Every origin's stylesheets are concatenated in that same cascade order and
|
|
23
23
|
* written to `<out>/app.css` — see build/styles.ts.
|
package/dist/build/cli.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* loadbare-app-build [--src src] [--out dist] [--watch] [--minify]
|
|
8
8
|
*
|
|
9
9
|
* `--src` names the application's own tree: the one `chrome.html` file,
|
|
10
|
-
* every `*.page.html` page, its `*.
|
|
10
|
+
* every `*.page.html` page, its `*.requests.ts`/`*.queries.ts` pairs, and
|
|
11
11
|
* `imports.ts` if there is one — see build/locations.ts. It is also the last
|
|
12
12
|
* origin in the cascade that supplies widget definitions, widget scripts and
|
|
13
13
|
* stylesheets; this package's own widgets come first and each package named
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* The assembled document is written to `<out>/app.html`; the client bundle
|
|
18
18
|
* to `<out>/client.js`, by way of a generated `<out>/client-entry.ts` — see
|
|
19
19
|
* build/elements.ts for how a tag is resolved to the script that registers
|
|
20
|
-
* it. When any page has a
|
|
20
|
+
* it. When any page has a requests or queries file, the hub registry that used
|
|
21
21
|
* to be hand-maintained is written to `<out>/pages.ts` — see build/pages.ts.
|
|
22
22
|
* Every origin's stylesheets are concatenated in that same cascade order and
|
|
23
23
|
* written to `<out>/app.css` — see build/styles.ts.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expand.d.ts","sourceRoot":"","sources":["../../build/expand.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"expand.d.ts","sourceRoot":"","sources":["../../build/expand.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAkCH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AA8BjD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAmB1E;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACzB,OAAO,CAAC,WAAW,CAAC,CAStB;AA4CD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAS3D;AA8OD;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,CAIhE"}
|
package/dist/build/expand.js
CHANGED
|
@@ -11,23 +11,9 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { readdir, readFile } from "node:fs/promises";
|
|
13
13
|
import { JSDOM } from "jsdom";
|
|
14
|
-
import { ATTR_SLOT, ATTR_TEMPLATE
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
* definition — a typo here is caught immediately rather than shipped as an
|
|
18
|
-
* inert tag. A tag outside this namespace still expands when a definition
|
|
19
|
-
* exists for it (an application is free to name its own widgets anything),
|
|
20
|
-
* but is not required to have one: with no definition, it is assumed to be
|
|
21
|
-
* a plain custom element, registered by script alone.
|
|
22
|
-
*/
|
|
23
|
-
const WIDGET_TAG = /^LB-/;
|
|
24
|
-
/**
|
|
25
|
-
* The one LB-* tag that is not a widget: the hub itself, always present in
|
|
26
|
-
* the chrome, registered by script rather than by definition. Expanding the
|
|
27
|
-
* chrome (see build/assemble.ts) would otherwise demand a definition for it
|
|
28
|
-
* that could never exist.
|
|
29
|
-
*/
|
|
30
|
-
const HUB_TAG = HUB_TAG_NAME.toUpperCase();
|
|
14
|
+
import { ATTR_SLOT, ATTR_TEMPLATE } from "../core/lb-constants.js";
|
|
15
|
+
/** Lowercase, hyphenated — the one shape a custom element tag has. */
|
|
16
|
+
const CUSTOM_ELEMENT = /-/;
|
|
31
17
|
/** A placeholder is an entire attribute value or an entire text node. */
|
|
32
18
|
/**
|
|
33
19
|
* `{{name}}` or `{{name|default}}`. The default is a literal that stands in
|
|
@@ -40,8 +26,11 @@ const HUB_TAG = HUB_TAG_NAME.toUpperCase();
|
|
|
40
26
|
const PLACEHOLDER = /^\{\{\s*([A-Za-z][\w-]*)\s*(?:\|\s*([^}]*?)\s*)?\}\}$/;
|
|
41
27
|
/**
|
|
42
28
|
* Marks an attribute as input to expansion. Three namespaces share the tag:
|
|
43
|
-
* `lb-`
|
|
44
|
-
* HTML's and means what HTML says it
|
|
29
|
+
* `lb-` holds the names Loadbare defines, `exp-` the names a widget author
|
|
30
|
+
* defines, and everything unprefixed is HTML's and means what HTML says it
|
|
31
|
+
* means. The split is by owner rather than by phase — `lb-slot` and
|
|
32
|
+
* `lb-template` are expansion's own and never reach the browser, while
|
|
33
|
+
* `lb-list` and `lb-cell` are read at both times. So an author is free to write
|
|
45
34
|
* `class`, `title` or `hidden` on any widget, whatever its parameters happen
|
|
46
35
|
* to be named. The prefix marks the slot on the tag, where the ambiguity was;
|
|
47
36
|
* inside a definition `{{ }}` already says the same thing, so `exp-label`
|
|
@@ -179,13 +168,13 @@ export function customElementTags(html) {
|
|
|
179
168
|
}
|
|
180
169
|
return tags;
|
|
181
170
|
}
|
|
182
|
-
/** Which
|
|
183
|
-
function referencesOf(source) {
|
|
171
|
+
/** Which definitions a definition uses. A tag with no definition expands to nothing and cannot cycle. */
|
|
172
|
+
function referencesOf(source, defs) {
|
|
184
173
|
const refs = new Set();
|
|
185
174
|
for (const scope of scopes(parse(source))) {
|
|
186
175
|
for (const el of scope.querySelectorAll("*")) {
|
|
187
176
|
const tag = el.tagName.toUpperCase();
|
|
188
|
-
if (
|
|
177
|
+
if (CUSTOM_ELEMENT.test(tag) && tag in defs)
|
|
189
178
|
refs.add(tag);
|
|
190
179
|
}
|
|
191
180
|
}
|
|
@@ -198,7 +187,7 @@ function referencesOf(source) {
|
|
|
198
187
|
function checkAcyclic(defs) {
|
|
199
188
|
const refs = new Map();
|
|
200
189
|
for (const [tag, source] of Object.entries(defs)) {
|
|
201
|
-
refs.set(tag, referencesOf(source));
|
|
190
|
+
refs.set(tag, referencesOf(source, defs));
|
|
202
191
|
}
|
|
203
192
|
const done = new Set();
|
|
204
193
|
const path = [];
|
|
@@ -335,12 +324,8 @@ function fillSlot(tag, root, content) {
|
|
|
335
324
|
slot.append(...content);
|
|
336
325
|
slot.removeAttribute(ATTR_SLOT);
|
|
337
326
|
}
|
|
338
|
-
function expandElement(el, defs) {
|
|
327
|
+
function expandElement(el, defs, source) {
|
|
339
328
|
const tag = el.tagName.toUpperCase();
|
|
340
|
-
const source = defs[tag];
|
|
341
|
-
if (source === undefined) {
|
|
342
|
-
throw new Error(`expand: <${tag.toLowerCase()}> has no definition. Every hub tag must resolve.`);
|
|
343
|
-
}
|
|
344
329
|
// The tag survives expansion carrying every attribute the author wrote,
|
|
345
330
|
// `exp-` ones included. They cost nothing where they are, and what ships
|
|
346
331
|
// shows what was asked for beside what it produced.
|
|
@@ -369,10 +354,12 @@ function expandElement(el, defs) {
|
|
|
369
354
|
}
|
|
370
355
|
function walk(root, defs) {
|
|
371
356
|
for (const child of [...root.children]) {
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
357
|
+
const source = defs[child.tagName.toUpperCase()];
|
|
358
|
+
// A tag with no definition is left alone. It is a custom element a
|
|
359
|
+
// script registers, and build/elements.ts is where a tag that has
|
|
360
|
+
// neither a definition nor a script is refused — one rule, one place.
|
|
361
|
+
if (source !== undefined)
|
|
362
|
+
expandElement(child, defs, source);
|
|
376
363
|
// Definitions may use other widgets, so descend after expanding. The
|
|
377
364
|
// acyclicity check is what makes this terminate.
|
|
378
365
|
walk(child, defs);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* filename suffix does instead: `chrome.html` is the one chrome file, and
|
|
9
9
|
* `*.page.html` is a page.
|
|
10
10
|
*
|
|
11
|
-
* A page's server half is named the same way: `*.
|
|
11
|
+
* A page's server half is named the same way: `*.requests.ts` and
|
|
12
12
|
* `*.queries.ts` pair with a `*.page.html` by sharing its basename, and are
|
|
13
13
|
* free to sit anywhere too. Either may be absent — a page with no data needs
|
|
14
14
|
* neither — but one with no matching `*.page.html` is a naming mistake and
|
|
@@ -32,8 +32,8 @@ export interface PageFile {
|
|
|
32
32
|
file: string;
|
|
33
33
|
}
|
|
34
34
|
export interface PageSource {
|
|
35
|
-
/** Absolute path, without extension, to the `.
|
|
36
|
-
|
|
35
|
+
/** Absolute path, without extension, to the `.requests.ts` module, if this page has one. */
|
|
36
|
+
requests?: string;
|
|
37
37
|
/** Absolute path, without extension, to the `.queries.ts` module, if this page has one. */
|
|
38
38
|
queries?: string;
|
|
39
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locations.d.ts","sourceRoot":"","sources":["../../build/locations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAQlD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,
|
|
1
|
+
{"version":3,"file":"locations.d.ts","sourceRoot":"","sources":["../../build/locations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAQlD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2FAA2F;IAC3F,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,UAAU;IAClB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACrC,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,gHAAgH;AAChH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA2ClE;AAED,MAAM,MAAM,WAAW,GAAG,WAAW,CAAC;AAEtC,wBAAsB,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,CAmBxD;AAED,MAAM,WAAW,YAAY;IAC3B,8FAA8F;IAC9F,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,SAAU,SAAQ,WAAW;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CA2D7E"}
|
package/dist/build/locations.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* filename suffix does instead: `chrome.html` is the one chrome file, and
|
|
9
9
|
* `*.page.html` is a page.
|
|
10
10
|
*
|
|
11
|
-
* A page's server half is named the same way: `*.
|
|
11
|
+
* A page's server half is named the same way: `*.requests.ts` and
|
|
12
12
|
* `*.queries.ts` pair with a `*.page.html` by sharing its basename, and are
|
|
13
13
|
* free to sit anywhere too. Either may be absent — a page with no data needs
|
|
14
14
|
* neither — but one with no matching `*.page.html` is a naming mistake and
|
|
@@ -32,7 +32,7 @@ import { findPackageRoot } from "./package-root.js";
|
|
|
32
32
|
export { CUSTOM_ELEMENT_TAG } from "./origins.js";
|
|
33
33
|
const CHROME_FILENAME = "chrome.html";
|
|
34
34
|
const PAGE_SUFFIX = ".page.html";
|
|
35
|
-
const HOOKS_SUFFIX = ".
|
|
35
|
+
const HOOKS_SUFFIX = ".requests.ts";
|
|
36
36
|
const QUERIES_SUFFIX = ".queries.ts";
|
|
37
37
|
const IMPORTS_FILENAME = "imports.ts";
|
|
38
38
|
/** The raw walk, with no uniqueness checks — usable on its own by anything that does not need a chrome file. */
|
|
@@ -70,7 +70,8 @@ export async function discoverSrc(src) {
|
|
|
70
70
|
pages.push({ name: entry.name.slice(0, -PAGE_SUFFIX.length), file });
|
|
71
71
|
}
|
|
72
72
|
else if (entry.name.endsWith(HOOKS_SUFFIX)) {
|
|
73
|
-
pageSource(entry.name.slice(0, -HOOKS_SUFFIX.length)).
|
|
73
|
+
pageSource(entry.name.slice(0, -HOOKS_SUFFIX.length)).requests =
|
|
74
|
+
file.slice(0, -".ts".length);
|
|
74
75
|
}
|
|
75
76
|
else if (entry.name.endsWith(QUERIES_SUFFIX)) {
|
|
76
77
|
pageSource(entry.name.slice(0, -QUERIES_SUFFIX.length)).queries =
|
|
@@ -116,6 +117,17 @@ export async function resolveLocations(args) {
|
|
|
116
117
|
throw new Error(`locations: more than one ${IMPORTS_FILENAME} found under '${args.src}': ` +
|
|
117
118
|
importsCandidates.join(", "));
|
|
118
119
|
}
|
|
120
|
+
// Sorted by name above, so duplicates are adjacent. A stub is the page's
|
|
121
|
+
// whole identity — its route, its template and its server half all key on
|
|
122
|
+
// it — so two files claiming one stub is a naming mistake, not a merge.
|
|
123
|
+
for (let i = 1; i < pages.length; i++) {
|
|
124
|
+
const [prev, here] = [pages[i - 1], pages[i]];
|
|
125
|
+
if (prev.name === here.name) {
|
|
126
|
+
throw new Error(`locations: more than one '${here.name}${PAGE_SUFFIX}' found under ` +
|
|
127
|
+
`'${args.src}': ${prev.file}, ${here.file}; the page namespace is ` +
|
|
128
|
+
`flat, so a stub names one page`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
119
131
|
const pageNames = new Set(pages.map((p) => p.name));
|
|
120
132
|
for (const name of pageSources.keys()) {
|
|
121
133
|
if (!pageNames.has(name)) {
|
package/dist/build/origins.d.ts
CHANGED
|
@@ -71,19 +71,6 @@ export interface OriginScan {
|
|
|
71
71
|
/** Every `.css` file here, sorted by filename with the full path breaking a tie. */
|
|
72
72
|
css: string[];
|
|
73
73
|
}
|
|
74
|
-
/**
|
|
75
|
-
* One origin's contribution, classified by filename alone.
|
|
76
|
-
*
|
|
77
|
-
* A `.html` file is a widget's only when its basename is a tag, and a module
|
|
78
|
-
* only when it is `<tag>.browser.ts` — which is what excludes `chrome.html`,
|
|
79
|
-
* `about.page.html`, `about.hooks.ts` and `imports.ts` here without naming
|
|
80
|
-
* any of them. Those are the application's own files, and
|
|
81
|
-
* build/locations.ts picks them out of `src` separately.
|
|
82
|
-
*
|
|
83
|
-
* A module named after a tag without the `.browser` goes in `unmarked`, so
|
|
84
|
-
* an author who forgot the word gets told which file to rename rather than
|
|
85
|
-
* being told their tag does not exist.
|
|
86
|
-
*/
|
|
87
74
|
export declare function scanOrigin(origin: Origin): Promise<OriginScan>;
|
|
88
75
|
/** The shape of an `imports.ts` module's default export: the packages an application pulls widgets from. */
|
|
89
76
|
export type ElementManifest = string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"origins.d.ts","sourceRoot":"","sources":["../../build/origins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAOH,gHAAgH;AAChH,eAAO,MAAM,kBAAkB,QAAkC,CAAC;AASlE,MAAM,WAAW,MAAM;IACrB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,qCAAqC;IACrC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,oEAAoE;IACpE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,oFAAoF;IACpF,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;
|
|
1
|
+
{"version":3,"file":"origins.d.ts","sourceRoot":"","sources":["../../build/origins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAOH,gHAAgH;AAChH,eAAO,MAAM,kBAAkB,QAAkC,CAAC;AASlE,MAAM,WAAW,MAAM;IACrB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,qCAAqC;IACrC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,oEAAoE;IACpE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,oFAAoF;IACpF,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AA2DD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA4EpE;AAED,4GAA4G;AAC5G,MAAM,MAAM,eAAe,GAAG,MAAM,EAAE,CAAC;AAEvC;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,eAAe,CAAC,CA4B1B;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAwED,MAAM,WAAW,WAAW;IAC1B,+FAA+F;IAC/F,aAAa,EAAE,MAAM,CAAC;IACtB,kGAAkG;IAClG,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,eAAe,EACzB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,EAAE,CAAC,CAkBnB;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,MAAM,EACX,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,UAAU,EAAE,CAAC,CAIvB;AAED,iEAAiE;AACjE,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,CAErD"}
|
package/dist/build/origins.js
CHANGED
|
@@ -76,7 +76,7 @@ async function filesUnder(dir) {
|
|
|
76
76
|
*
|
|
77
77
|
* A `.html` file is a widget's only when its basename is a tag, and a module
|
|
78
78
|
* only when it is `<tag>.browser.ts` — which is what excludes `chrome.html`,
|
|
79
|
-
* `about.page.html`, `about.
|
|
79
|
+
* `about.page.html`, `about.requests.ts` and `imports.ts` here without naming
|
|
80
80
|
* any of them. Those are the application's own files, and
|
|
81
81
|
* build/locations.ts picks them out of `src` separately.
|
|
82
82
|
*
|
|
@@ -84,6 +84,29 @@ async function filesUnder(dir) {
|
|
|
84
84
|
* an author who forgot the word gets told which file to rename rather than
|
|
85
85
|
* being told their tag does not exist.
|
|
86
86
|
*/
|
|
87
|
+
/**
|
|
88
|
+
* The tag a filename claims, or null when it claims none.
|
|
89
|
+
*
|
|
90
|
+
* A filename is the tag verbatim, never folded. HTML matches an element name
|
|
91
|
+
* case-insensitively, so folding would let `My-Widget.html` and
|
|
92
|
+
* `my-widget.html` be two files for one tag — a collision on a
|
|
93
|
+
* case-sensitive filesystem and one file on a case-insensitive one, which is
|
|
94
|
+
* a difference between machines rather than a rule anyone can read.
|
|
95
|
+
*
|
|
96
|
+
* A name that is a tag only once folded is refused rather than ignored: the
|
|
97
|
+
* author meant a widget, and silence would leave them with a tag that never
|
|
98
|
+
* expands.
|
|
99
|
+
*/
|
|
100
|
+
function tagIn(stem, file) {
|
|
101
|
+
if (CUSTOM_ELEMENT_TAG.test(stem))
|
|
102
|
+
return stem;
|
|
103
|
+
const folded = stem.toLowerCase();
|
|
104
|
+
if (!CUSTOM_ELEMENT_TAG.test(folded))
|
|
105
|
+
return null;
|
|
106
|
+
const suffix = path.basename(file).slice(stem.length);
|
|
107
|
+
throw new Error(`origins: '${file}' carries capitals; a tag is lowercase, so this ` +
|
|
108
|
+
`file must be named '${folded}${suffix}'`);
|
|
109
|
+
}
|
|
87
110
|
export async function scanOrigin(origin) {
|
|
88
111
|
const definitions = new Map();
|
|
89
112
|
const scripts = new Map();
|
|
@@ -104,20 +127,19 @@ export async function scanOrigin(origin) {
|
|
|
104
127
|
css.push(file);
|
|
105
128
|
}
|
|
106
129
|
else if (name.endsWith(HTML_SUFFIX)) {
|
|
107
|
-
const tag = name.slice(0, -HTML_SUFFIX.length)
|
|
108
|
-
if (
|
|
130
|
+
const tag = tagIn(name.slice(0, -HTML_SUFFIX.length), file);
|
|
131
|
+
if (tag)
|
|
109
132
|
claim(definitions, "definition", tag, file);
|
|
110
|
-
}
|
|
111
133
|
}
|
|
112
134
|
else {
|
|
113
135
|
const browser = BROWSER_SUFFIXES.find((s) => name.endsWith(s));
|
|
114
136
|
if (browser) {
|
|
115
|
-
const tag = name.slice(0, -browser.length)
|
|
137
|
+
const tag = tagIn(name.slice(0, -browser.length), file);
|
|
116
138
|
// Only the trailing ".ts" comes off, never the ".browser": what is
|
|
117
139
|
// left becomes an import specifier, and esbuild resolves
|
|
118
140
|
// "lb-thing.browser" to "lb-thing.browser.ts" the same way as to
|
|
119
141
|
// ".js".
|
|
120
|
-
if (
|
|
142
|
+
if (tag) {
|
|
121
143
|
const ext = MODULE_SUFFIXES.find((e) => name.endsWith(e));
|
|
122
144
|
claim(scripts, "script", tag, file.slice(0, -ext.length));
|
|
123
145
|
}
|
|
@@ -130,8 +152,10 @@ export async function scanOrigin(origin) {
|
|
|
130
152
|
// code. It contributes nothing. Remembering it costs a map entry and
|
|
131
153
|
// buys an error message that names the file instead of describing an
|
|
132
154
|
// absence. A `.d.ts` never reaches here — stripping ".ts" leaves a
|
|
133
|
-
// dot, which is not a tag.
|
|
134
|
-
|
|
155
|
+
// dot, which is not a tag. Tested rather than tagIn()'d: an unmarked
|
|
156
|
+
// module was never claimed to be a widget, so a capital in its name
|
|
157
|
+
// is not a mistake anyone here can see.
|
|
158
|
+
const tag = name.slice(0, -ext.length);
|
|
135
159
|
if (CUSTOM_ELEMENT_TAG.test(tag) && !unmarked.has(tag)) {
|
|
136
160
|
unmarked.set(tag, file);
|
|
137
161
|
}
|
package/dist/build/pages.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Generating the hub's page registry — the server-side counterpart to
|
|
3
3
|
* build/elements.ts's client entry point.
|
|
4
4
|
*
|
|
5
|
-
* `*.
|
|
5
|
+
* `*.requests.ts` and `*.queries.ts` are ordinary TypeScript, found by
|
|
6
6
|
* build/locations.ts and handed here already paired by page name. What this
|
|
7
7
|
* module writes is the file an application used to hand-maintain: an import
|
|
8
8
|
* of each pair, a `Pages` object naming them by page, and the one
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
* code, so it never needs a bundler step the way the browser-bound client
|
|
12
12
|
* entry does.
|
|
13
13
|
*
|
|
14
|
-
* Nothing here is emitted for a page with neither a
|
|
14
|
+
* Nothing here is emitted for a page with neither a requests nor a queries
|
|
15
15
|
* file — a purely static page needs no hub entry, and createHub is only
|
|
16
16
|
* called at all when there is at least one.
|
|
17
17
|
*/
|
|
18
18
|
import type { PageFile, PageSource } from "./locations.js";
|
|
19
19
|
/**
|
|
20
|
-
* `undefined` when no page has a
|
|
20
|
+
* `undefined` when no page has a requests or queries file — the caller writes
|
|
21
21
|
* nothing in that case, the same way an app with no custom elements gets no
|
|
22
22
|
* client entry beyond the built-ins.
|
|
23
23
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../build/pages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAY3D;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,QAAQ,EAAE,EACjB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../build/pages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAY3D;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,QAAQ,EAAE,EACjB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,SAAS,CAsCpB"}
|
package/dist/build/pages.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Generating the hub's page registry — the server-side counterpart to
|
|
3
3
|
* build/elements.ts's client entry point.
|
|
4
4
|
*
|
|
5
|
-
* `*.
|
|
5
|
+
* `*.requests.ts` and `*.queries.ts` are ordinary TypeScript, found by
|
|
6
6
|
* build/locations.ts and handed here already paired by page name. What this
|
|
7
7
|
* module writes is the file an application used to hand-maintain: an import
|
|
8
8
|
* of each pair, a `Pages` object naming them by page, and the one
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* code, so it never needs a bundler step the way the browser-bound client
|
|
12
12
|
* entry does.
|
|
13
13
|
*
|
|
14
|
-
* Nothing here is emitted for a page with neither a
|
|
14
|
+
* Nothing here is emitted for a page with neither a requests nor a queries
|
|
15
15
|
* file — a purely static page needs no hub entry, and createHub is only
|
|
16
16
|
* called at all when there is at least one.
|
|
17
17
|
*/
|
|
@@ -25,7 +25,7 @@ function relativeImport(outDir, file) {
|
|
|
25
25
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
* `undefined` when no page has a
|
|
28
|
+
* `undefined` when no page has a requests or queries file — the caller writes
|
|
29
29
|
* nothing in that case, the same way an app with no custom elements gets no
|
|
30
30
|
* client entry beyond the built-ins.
|
|
31
31
|
*/
|
|
@@ -40,15 +40,17 @@ export function pagesSource(pages, pageSources, outDir, packageName) {
|
|
|
40
40
|
const source = pageSources.get(name);
|
|
41
41
|
if (!source)
|
|
42
42
|
continue;
|
|
43
|
-
const
|
|
43
|
+
const requestsId = source.requests
|
|
44
|
+
? identifier(name, "Requests")
|
|
45
|
+
: undefined;
|
|
44
46
|
const queriesId = source.queries ? identifier(name, "Queries") : undefined;
|
|
45
|
-
if (source.
|
|
46
|
-
imports.push(`import {
|
|
47
|
+
if (source.requests) {
|
|
48
|
+
imports.push(`import { requests as ${requestsId} } from ${JSON.stringify(relativeImport(outDir, source.requests))};`);
|
|
47
49
|
}
|
|
48
50
|
if (source.queries) {
|
|
49
51
|
imports.push(`import { queries as ${queriesId} } from ${JSON.stringify(relativeImport(outDir, source.queries))};`);
|
|
50
52
|
}
|
|
51
|
-
entries.push(` ${JSON.stringify(name)}: {
|
|
53
|
+
entries.push(` ${JSON.stringify(name)}: { requests: ${requestsId ?? "{}"}, queries: ${queriesId ?? "{}"} },`);
|
|
52
54
|
}
|
|
53
55
|
return ([...imports, "", "export const hub = createHub({", ...entries, "});"].join("\n") + "\n");
|
|
54
56
|
}
|
|
@@ -1,27 +1,29 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const ATTR_LIST = "lb-list";
|
|
2
|
+
export declare const ATTR_ROW = "lb-row";
|
|
2
3
|
export declare const ATTR_KEY = "lb-key";
|
|
4
|
+
export declare const ATTR_KEY_VALUE = "lb-key-value";
|
|
3
5
|
export declare const ATTR_CELL = "lb-cell";
|
|
4
6
|
export declare const ATTR_VALUE = "lb-value";
|
|
5
|
-
export declare const
|
|
6
|
-
export declare const ATTR_SORT = "lb-sort";
|
|
7
|
-
export declare const ATTR_ROW_COUNT = "data-rows";
|
|
7
|
+
export declare const ATTR_ROW_COUNT = "lb-row-count";
|
|
8
8
|
export declare const LB_EVENT_NAME = "lb-request";
|
|
9
9
|
export declare const ATTR_ACTION = "lb-action";
|
|
10
|
-
export declare const
|
|
11
|
-
export declare const
|
|
12
|
-
export declare const
|
|
10
|
+
export declare const LB_RESERVED_PREFIX = "lb-";
|
|
11
|
+
export declare const ACTION_ROW_INSERT = "lb-row-insert";
|
|
12
|
+
export declare const ACTION_ROW_DELETE = "lb-row-delete";
|
|
13
|
+
export declare const ACTION_ROW_UPDATE = "lb-row-update";
|
|
14
|
+
export declare const ACTION_CELL_CHANGE = "lb-cell-change";
|
|
15
|
+
export declare const LB_ACTIONS: readonly ["lb-row-insert", "lb-row-delete", "lb-row-update", "lb-cell-change"];
|
|
13
16
|
export declare const ATTR_SLOT = "lb-slot";
|
|
14
17
|
export declare const ATTR_TEMPLATE = "lb-template";
|
|
15
18
|
export declare const ATTR_NAV_LINK = "lb-nav-link";
|
|
16
|
-
export declare const
|
|
17
|
-
export declare const
|
|
19
|
+
export declare const ATTR_PAGE = "lb-page";
|
|
20
|
+
export declare const NAV_ROW = "lb-navigation";
|
|
18
21
|
export declare const NAV_CELL_LABEL = "page-label";
|
|
19
22
|
export declare const NAV_CELL_URI = "page-uri";
|
|
20
23
|
export declare const ATTR_UNKNOWN_PAGE = "lb-unknown-page";
|
|
21
24
|
export declare const HUB_TAG_NAME = "lb-hub";
|
|
22
|
-
export declare const ATTR_PENDING = "
|
|
23
|
-
export declare const ATTR_ERROR = "
|
|
24
|
-
export declare const
|
|
25
|
-
export declare const LB_REQUEST_ENDPOINT = "/lb";
|
|
25
|
+
export declare const ATTR_PENDING = "lb-pending";
|
|
26
|
+
export declare const ATTR_ERROR = "lb-error";
|
|
27
|
+
export declare const LB_ENDPOINT = "/lb";
|
|
26
28
|
export declare const LB_REQUEST_TIMEOUT_MS = 10000;
|
|
27
29
|
//# sourceMappingURL=lb-constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-constants.d.ts","sourceRoot":"","sources":["../../core/lb-constants.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lb-constants.d.ts","sourceRoot":"","sources":["../../core/lb-constants.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,SAAS,YAAY,CAAC;AAQnC,eAAO,MAAM,QAAQ,WAAW,CAAC;AAMjC,eAAO,MAAM,QAAQ,WAAW,CAAC;AAMjC,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAQ7C,eAAO,MAAM,SAAS,YAAY,CAAC;AAEnC,eAAO,MAAM,UAAU,aAAa,CAAC;AAOrC,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAK7C,eAAO,MAAM,aAAa,eAAe,CAAC;AAS1C,eAAO,MAAM,WAAW,cAAc,CAAC;AAYvC,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAMxC,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAKjD,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAOjD,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAMjD,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAInD,eAAO,MAAM,UAAU,gFAKb,CAAC;AAMX,eAAO,MAAM,SAAS,YAAY,CAAC;AAYnC,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAK3C,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAM3C,eAAO,MAAM,SAAS,YAAY,CAAC;AAQnC,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAKvC,eAAO,MAAM,cAAc,eAAe,CAAC;AAC3C,eAAO,MAAM,YAAY,aAAa,CAAC;AAUvC,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAQnD,eAAO,MAAM,YAAY,WAAW,CAAC;AAQrC,eAAO,MAAM,YAAY,eAAe,CAAC;AAOzC,eAAO,MAAM,UAAU,aAAa,CAAC;AAMrC,eAAO,MAAM,WAAW,QAAQ,CAAC;AAIjC,eAAO,MAAM,qBAAqB,QAAS,CAAC"}
|