@plitzi/cli 0.38.9 → 0.38.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +261 -0
- package/README.md +22 -7
- package/dist/index.js +1344 -816
- package/package.json +3 -3
- package/skills/plitzi-cli/reference/functions.md +7 -2
- package/skills/plitzi-cli/reference/projects.md +1 -1
package/dist/index.js
CHANGED
|
@@ -14,8 +14,8 @@ import readline from "node:readline/promises";
|
|
|
14
14
|
import { EXPLAIN_KINDS, PAGE_SPEC_FIELDS, PAGE_TEXT_LIMIT, actionSpecFromEntry, actionToSource, authorSpace, blankTemplateFiles, catalogTemplateFiles, closest, comparePictures, compareTexts, darkScheme, dataIssues, elementTriggers, elementTypeNames, emptyTemplateFiles, explain, explainKindOf, explainList, explanationText, failedFlowText, importProbe, importedFiles, inspectDocument, inspectPage, isSuggestionCode, loadImages, locateClasses, locateElements, openPage, pageRegions, pageTexts, planFixes, readDevTools, refusalOf, unrollPage } from "@plitzi/sdk-authoring";
|
|
15
15
|
import { existsSync, readFileSync, readdirSync, realpathSync, statSync, watch } from "node:fs";
|
|
16
16
|
import { parseEnv, promisify } from "node:util";
|
|
17
|
-
import { lookup } from "node:dns/promises";
|
|
18
17
|
import esbuild, { build } from "esbuild";
|
|
18
|
+
import { lookup } from "node:dns/promises";
|
|
19
19
|
import { unzipSync, zipSync } from "fflate";
|
|
20
20
|
import { gzipSync } from "node:zlib";
|
|
21
21
|
import { emitKeypressEvents } from "node:readline";
|
|
@@ -24,6 +24,9 @@ var t$5 = `[data-plitzi-devtools] { display: none !important; }`;
|
|
|
24
24
|
//#region ../../packages/sdk-shared/dist/helpers/isRecord.mjs
|
|
25
25
|
var e$3 = (e) => typeof e == "object" && !!e && !Array.isArray(e);
|
|
26
26
|
//#endregion
|
|
27
|
+
//#region ../../packages/sdk-shared/dist/realtime/topics.mjs
|
|
28
|
+
var m$2 = "plitzi-observer";
|
|
29
|
+
//#endregion
|
|
27
30
|
//#region ../../packages/sdk-shared/dist/theme/themeCookie.mjs
|
|
28
31
|
var t$3 = "theme";
|
|
29
32
|
//#endregion
|
|
@@ -148,11 +151,15 @@ var openProjectPage = async (browser, origin, view) => {
|
|
|
148
151
|
colorScheme: view.scheme ?? "light",
|
|
149
152
|
reducedMotion: view.reducedMotion ? "reduce" : "no-preference"
|
|
150
153
|
});
|
|
151
|
-
|
|
154
|
+
await page.context().addCookies([...view.scheme ? [{
|
|
152
155
|
name: t$3,
|
|
153
156
|
value: view.scheme,
|
|
154
157
|
url: origin
|
|
155
|
-
}]
|
|
158
|
+
}] : [], ...view.presence ? [] : [{
|
|
159
|
+
name: m$2,
|
|
160
|
+
value: "1",
|
|
161
|
+
url: origin
|
|
162
|
+
}]]);
|
|
156
163
|
return page;
|
|
157
164
|
};
|
|
158
165
|
/**
|
|
@@ -1354,7 +1361,7 @@ var n$3 = [
|
|
|
1354
1361
|
".otf"
|
|
1355
1362
|
];
|
|
1356
1363
|
var r$5 = () => Object.fromEntries(n$3.map((e) => [e, "dataurl"]));
|
|
1357
|
-
var i$
|
|
1364
|
+
var i$4 = /\?(raw|inline)$/;
|
|
1358
1365
|
var a$5 = {
|
|
1359
1366
|
".wasm": "application/wasm",
|
|
1360
1367
|
".js": "text/javascript",
|
|
@@ -1371,8 +1378,8 @@ var a$5 = {
|
|
|
1371
1378
|
var o$4 = () => ({
|
|
1372
1379
|
name: "plitzi-import-queries",
|
|
1373
1380
|
setup: (n) => {
|
|
1374
|
-
n.onResolve({ filter: i$
|
|
1375
|
-
let t = i$
|
|
1381
|
+
n.onResolve({ filter: i$4 }, async (e) => {
|
|
1382
|
+
let t = i$4.exec(e.path)?.[1] ?? "raw", r = await n.resolve(e.path.replace(i$4, ""), {
|
|
1376
1383
|
kind: e.kind,
|
|
1377
1384
|
importer: e.importer,
|
|
1378
1385
|
resolveDir: e.resolveDir
|
|
@@ -1405,7 +1412,7 @@ var o$4 = () => ({
|
|
|
1405
1412
|
//#region src/scaffold/pluginPackage/names.ts
|
|
1406
1413
|
var PREFIX = "plitzi-plugin-";
|
|
1407
1414
|
/** npm's own rule for a package name, scope included. */
|
|
1408
|
-
var PACKAGE_NAME = /^(@[a-z0-9][a-z0-9-._~]*\/)?[a-z0-9][a-z0-9-._~]*$/;
|
|
1415
|
+
var PACKAGE_NAME$1 = /^(@[a-z0-9][a-z0-9-._~]*\/)?[a-z0-9][a-z0-9-._~]*$/;
|
|
1409
1416
|
/** What the name has to leave once the scope and prefix are off: words of letters and digits, starting with a letter. */
|
|
1410
1417
|
var BASE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
1411
1418
|
var baseOf = (packageName) => {
|
|
@@ -1414,7 +1421,7 @@ var baseOf = (packageName) => {
|
|
|
1414
1421
|
};
|
|
1415
1422
|
/** What is wrong with a name as a plugin's, in words that say how to fix it — or `undefined` when nothing is. */
|
|
1416
1423
|
var pluginNameProblem = (packageName) => {
|
|
1417
|
-
if (!PACKAGE_NAME.test(packageName)) return `"${packageName}" is not a package name npm accepts: lowercase letters, digits and dashes, optionally under a @scope/.`;
|
|
1424
|
+
if (!PACKAGE_NAME$1.test(packageName)) return `"${packageName}" is not a package name npm accepts: lowercase letters, digits and dashes, optionally under a @scope/.`;
|
|
1418
1425
|
if (!BASE.test(baseOf(packageName))) return `"${packageName}" has to name the plugin in words — lowercase letters and digits between single dashes, starting with a letter (seat-picker, chart2) — since the component and the type a space uses are made from it.`;
|
|
1419
1426
|
const { type } = pluginNames(packageName);
|
|
1420
1427
|
if (elementTypeNames.includes(type)) return `"${packageName}" would make the type "${type}", which is a built-in element: a space could not tell the two apart. Name it after what it does (seat-picker, sales-chart).`;
|
|
@@ -2512,7 +2519,7 @@ var YARN_IGNORES$1 = "\n.yarn/*\n!.yarn/patches\n!.yarn/plugins\n!.yarn/releases
|
|
|
2512
2519
|
* the CLI records about it, and is committed — a clone without it could not pull, push or upgrade.
|
|
2513
2520
|
*/
|
|
2514
2521
|
var gitignore$1 = ({ mode, packageManager }) => `node_modules\n${v$3}\n.env\ntmp\n${mode === "server" ? `${y$2}\n` : ""}${packageManager === "yarn" ? YARN_IGNORES$1 : ""}`;
|
|
2515
|
-
var startLine = ({ mode, packageManager, source }) => mode === "server" ? `\`${runCommand(packageManager, "start")}\` serves pages on http://127.0.0.1:8080 — or, when something else holds 8080, the next free port, which it prints and writes to \`${x$3}\` (set \`PORT\` to choose one). \`${runCommand(packageManager, "start:dev")}\` restarts on a save to the server's code; a save to a plugin swaps it in the open page${source === "local" ? ", and a save to the space reloads it" : ""}. In production, \`${runCommand(packageManager, "build")}\` once and run \`${runCommand(packageManager, "start:prod")}\`, which sets \`NODE_ENV=production\` itself: the compiled server, with no TypeScript in the process.` : `\`${runCommand(packageManager, "start")}\` runs Vite on http://127.0.0.1:5173, with hot module replacement.`;
|
|
2522
|
+
var startLine = ({ mode, packageManager, source }) => mode === "server" ? `\`${runCommand(packageManager, "start")}\` serves pages on http://127.0.0.1:8080 — or, when something else holds 8080, the next free port, which it prints and writes to \`${x$3}\` (set \`PORT\` to choose one; \`HOST=0.0.0.0\` opens it to your network — a tablet on the same Wi-Fi — and prints the address to open there). \`${runCommand(packageManager, "start:dev")}\` restarts on a save to the server's code; a save to a plugin swaps it in the open page${source === "local" ? ", and a save to the space reloads it" : ""}. In production, \`${runCommand(packageManager, "build")}\` once and run \`${runCommand(packageManager, "start:prod")}\`, which sets \`NODE_ENV=production\` itself: the compiled server, with no TypeScript in the process.` : `\`${runCommand(packageManager, "start")}\` runs Vite on http://127.0.0.1:5173, with hot module replacement.`;
|
|
2516
2523
|
var spaceSection = (answers) => {
|
|
2517
2524
|
if (answers.source === "cloud") return `## Where the space comes from
|
|
2518
2525
|
|
|
@@ -2656,7 +2663,7 @@ ${code(".claude/skills/plitzi-cli/SKILL.md")} first: ${code("plitzi plugin add")
|
|
|
2656
2663
|
|
|
2657
2664
|
What you leave behind is the next reader's problem — the user's, or the next agent's. Before calling a change done:
|
|
2658
2665
|
|
|
2659
|
-
- **Nothing unused.** Delete what you made and no longer use — a file, a page, a component, a class, a token, a data file, an import, a plugin folder. No commented-out code, no ${code("console.log")} left from debugging, no copy of a file kept "just in case": git keeps the history.
|
|
2666
|
+
- **Nothing unused.** Delete what you made and no longer use — a file, a page, a component, a class, a token, a data file, an import, a plugin folder. A folder's ${code(".gitkeep")} keeps it in git while it is empty; once the folder holds files it does nothing, and ${code("doctor")} and ${code("upgrade")} ask for it no more. No commented-out code, no ${code("console.log")} left from debugging, no copy of a file kept "just in case": git keeps the history.
|
|
2660
2667
|
- **Scratch goes in ${code(`tmp/`)}, or nowhere.** A one-off script, a dump, a picture to look at — never at the root or beside the source, where it reads as part of the project.
|
|
2661
2668
|
- **One of everything.** A look used twice is a class; a value used twice is a token; a block used twice is a component, and rows of data are one list. Change it where it is defined, and rename everywhere when you rename.
|
|
2662
2669
|
- **Files a reader can find.** One part per file, named after what it is, in the folder of its kind — the shape ${code("src/space/")} already has. Do not start a parallel layout of your own.
|
|
@@ -2724,6 +2731,12 @@ PLITZI_SIGNING_SECRET=
|
|
|
2724
2731
|
|
|
2725
2732
|
# Left out: 8080, or the next free port while developing.
|
|
2726
2733
|
# PORT=8080
|
|
2734
|
+
|
|
2735
|
+
# Left out: this machine only. 0.0.0.0 opens it to the network — a tablet on the same Wi-Fi, and anyone else on it.
|
|
2736
|
+
# HOST=0.0.0.0
|
|
2737
|
+
|
|
2738
|
+
# The secrets the space's actions and functions name — ctx.fetch's credential, a connector's: credential id → its keys.
|
|
2739
|
+
# PLITZI_CREDENTIALS={"google":{"clientId":"…","clientSecret":"…"}}
|
|
2727
2740
|
`;
|
|
2728
2741
|
/** A `.env` with the signing key `plitzi create` made for the project in its place. */
|
|
2729
2742
|
var withSigningSecret = (env, secret) => env.replace(/^PLITZI_SIGNING_SECRET=$/m, `PLITZI_SIGNING_SECRET=${secret}`);
|
|
@@ -2908,6 +2921,8 @@ var serverOptionsModule = (local) => `import type { ProjectServerOptions } from
|
|
|
2908
2921
|
*
|
|
2909
2922
|
* - \`images: { domains: ['images.example.com'] }\` — pictures from those hosts resized here, with \`sharp\` installed.
|
|
2910
2923
|
${local ? ACTION_OPTIONS_DOC : ""} * - \`rsc: { elementTimeoutMs }\` — how long a section resolved on the server is waited for: 5 s by default.
|
|
2924
|
+
* - \`devMode\` — the development build, the dev tools, a public action's trace: on unless \`NODE_ENV\` is \`production\`.
|
|
2925
|
+
* \`devMode: false\` keeps them off wherever the server is started, \`NODE_ENV\` or not. \`devReload\` follows it.
|
|
2911
2926
|
*/
|
|
2912
2927
|
export const serverOptions: ProjectServerOptions = {};
|
|
2913
2928
|
`;
|
|
@@ -4425,15 +4440,15 @@ var __exportAll = (all, no_symbols) => {
|
|
|
4425
4440
|
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
4426
4441
|
return target;
|
|
4427
4442
|
};
|
|
4428
|
-
var e$
|
|
4429
|
-
var t$63 = `(?:${e$
|
|
4430
|
-
var n$47 = `\\[\\s*(?:\\d+|'[^']*'|"[^"]*"|${e$
|
|
4431
|
-
var r$36 = `${`${e$
|
|
4432
|
-
var i$
|
|
4433
|
-
var a$24 = `(?:${`\\{\\{\\{\\s*${r$36}\\s*\\}\\}\\}`}|${i$
|
|
4443
|
+
var e$43 = "[a-zA-Z_][a-zA-Z0-9_]*(?:-[a-zA-Z0-9_]+)*";
|
|
4444
|
+
var t$63 = `(?:${e$43}|\\d+)`;
|
|
4445
|
+
var n$47 = `\\[\\s*(?:\\d+|'[^']*'|"[^"]*"|${e$43}(?:\\.${t$63})*)\\s*\\]`;
|
|
4446
|
+
var r$36 = `${`${e$43}(?:${n$47})*(?:\\??\\.${t$63}(?:${n$47})*)*`}(?:\\s*\\?\\?\\s*[^|{}]+?)?(?:\\s*\\|\\s*[a-zA-Z_]+(?:\\([^)]*\\))?)*`;
|
|
4447
|
+
var i$29 = `\\{\\{\\s*${r$36}\\s*\\}\\}`;
|
|
4448
|
+
var a$24 = `(?:${`\\{\\{\\{\\s*${r$36}\\s*\\}\\}\\}`}|${i$29})`;
|
|
4434
4449
|
new RegExp(a$24, "g");
|
|
4435
4450
|
RegExp(`^${a$24}$`);
|
|
4436
|
-
var e$
|
|
4451
|
+
var e$42 = ["smooth", "auto"];
|
|
4437
4452
|
var t$61 = [
|
|
4438
4453
|
"start",
|
|
4439
4454
|
"center",
|
|
@@ -4445,7 +4460,7 @@ var r$34 = {
|
|
|
4445
4460
|
type: "select",
|
|
4446
4461
|
description: "How it moves: \"smooth\" glides there, \"auto\" jumps.",
|
|
4447
4462
|
default: "smooth",
|
|
4448
|
-
options: [...e$
|
|
4463
|
+
options: [...e$42]
|
|
4449
4464
|
};
|
|
4450
4465
|
var a$22 = {
|
|
4451
4466
|
setState: {
|
|
@@ -4561,7 +4576,7 @@ var a$22 = {
|
|
|
4561
4576
|
}
|
|
4562
4577
|
}
|
|
4563
4578
|
};
|
|
4564
|
-
var e$
|
|
4579
|
+
var e$41 = {
|
|
4565
4580
|
onLoad: {
|
|
4566
4581
|
action: "onLoad",
|
|
4567
4582
|
title: "On Load",
|
|
@@ -4731,7 +4746,7 @@ var e$40 = {
|
|
|
4731
4746
|
params: {}
|
|
4732
4747
|
}
|
|
4733
4748
|
};
|
|
4734
|
-
var e$
|
|
4749
|
+
var e$40 = () => (e) => e;
|
|
4735
4750
|
var t$60 = () => (e) => e;
|
|
4736
4751
|
var t$59 = t$60()({
|
|
4737
4752
|
type: "blockHtml",
|
|
@@ -4964,13 +4979,13 @@ var n$44 = {
|
|
|
4964
4979
|
var r$33 = t$60()({
|
|
4965
4980
|
type: "button",
|
|
4966
4981
|
attributeValues: {
|
|
4967
|
-
subType: e$
|
|
4982
|
+
subType: e$40()([
|
|
4968
4983
|
"button",
|
|
4969
4984
|
"submit",
|
|
4970
4985
|
"reset"
|
|
4971
4986
|
]),
|
|
4972
|
-
contentPlacement: e$
|
|
4973
|
-
iconPlacement: e$
|
|
4987
|
+
contentPlacement: e$40()(["before", "after"]),
|
|
4988
|
+
iconPlacement: e$40()(["before", "after"])
|
|
4974
4989
|
},
|
|
4975
4990
|
content: {
|
|
4976
4991
|
attributes: {
|
|
@@ -5038,7 +5053,7 @@ var r$33 = t$60()({
|
|
|
5038
5053
|
});
|
|
5039
5054
|
var n$43 = t$60()({
|
|
5040
5055
|
type: "dropdown",
|
|
5041
|
-
attributeValues: { popupPlacement: e$
|
|
5056
|
+
attributeValues: { popupPlacement: e$40()([
|
|
5042
5057
|
"left",
|
|
5043
5058
|
"right",
|
|
5044
5059
|
"top",
|
|
@@ -5169,7 +5184,7 @@ var t$54 = t$60()({
|
|
|
5169
5184
|
});
|
|
5170
5185
|
var n$42 = t$60()({
|
|
5171
5186
|
type: "heading",
|
|
5172
|
-
attributeValues: { subType: e$
|
|
5187
|
+
attributeValues: { subType: e$40()([
|
|
5173
5188
|
"h1",
|
|
5174
5189
|
"h2",
|
|
5175
5190
|
"h3",
|
|
@@ -5291,20 +5306,20 @@ var n$42 = t$60()({
|
|
|
5291
5306
|
var n$41 = t$60()({
|
|
5292
5307
|
type: "link",
|
|
5293
5308
|
attributeValues: {
|
|
5294
|
-
mode: e$
|
|
5309
|
+
mode: e$40()([
|
|
5295
5310
|
"page",
|
|
5296
5311
|
"internal",
|
|
5297
5312
|
"external"
|
|
5298
5313
|
]),
|
|
5299
|
-
target: e$
|
|
5314
|
+
target: e$40()([
|
|
5300
5315
|
"self",
|
|
5301
5316
|
"blank",
|
|
5302
5317
|
"parent",
|
|
5303
5318
|
"top"
|
|
5304
5319
|
]),
|
|
5305
|
-
contentPlacement: e$
|
|
5306
|
-
iconPlacement: e$
|
|
5307
|
-
current: e$
|
|
5320
|
+
contentPlacement: e$40()(["before", "after"]),
|
|
5321
|
+
iconPlacement: e$40()(["before", "after"]),
|
|
5322
|
+
current: e$40()(["page", "section"])
|
|
5308
5323
|
},
|
|
5309
5324
|
content: {
|
|
5310
5325
|
attributes: {
|
|
@@ -5476,7 +5491,7 @@ var t$52 = t$60()({
|
|
|
5476
5491
|
});
|
|
5477
5492
|
var n$40 = t$60()({
|
|
5478
5493
|
type: "richText",
|
|
5479
|
-
attributeValues: { format: e$
|
|
5494
|
+
attributeValues: { format: e$40()([
|
|
5480
5495
|
"html",
|
|
5481
5496
|
"markdown",
|
|
5482
5497
|
"text"
|
|
@@ -5613,7 +5628,7 @@ var n$39 = {
|
|
|
5613
5628
|
};
|
|
5614
5629
|
var r$32 = t$60()({
|
|
5615
5630
|
type: "themeToggle",
|
|
5616
|
-
attributeValues: { subType: e$
|
|
5631
|
+
attributeValues: { subType: e$40()(["switch", "segmented"]) },
|
|
5617
5632
|
triggers: { onThemeChange: {
|
|
5618
5633
|
action: "onThemeChange",
|
|
5619
5634
|
title: "On Theme Change",
|
|
@@ -5679,7 +5694,7 @@ var r$32 = t$60()({
|
|
|
5679
5694
|
});
|
|
5680
5695
|
var n$38 = t$60()({
|
|
5681
5696
|
type: "form",
|
|
5682
|
-
attributeValues: { method: e$
|
|
5697
|
+
attributeValues: { method: e$40()(["get", "post"]) },
|
|
5683
5698
|
sourceType: "apiContainer",
|
|
5684
5699
|
triggers: { onSubmit: {
|
|
5685
5700
|
action: "onSubmit",
|
|
@@ -5813,7 +5828,7 @@ var r$31 = {
|
|
|
5813
5828
|
...n$37,
|
|
5814
5829
|
"line-height": "20px"
|
|
5815
5830
|
};
|
|
5816
|
-
var i$
|
|
5831
|
+
var i$26 = {
|
|
5817
5832
|
display: "flex",
|
|
5818
5833
|
cursor: "pointer",
|
|
5819
5834
|
"font-weight": "600",
|
|
@@ -5823,7 +5838,7 @@ var i$25 = {
|
|
|
5823
5838
|
"user-select": "none"
|
|
5824
5839
|
};
|
|
5825
5840
|
var a$21 = {
|
|
5826
|
-
...i$
|
|
5841
|
+
...i$26,
|
|
5827
5842
|
"margin-bottom": "4px"
|
|
5828
5843
|
};
|
|
5829
5844
|
var o$23 = {
|
|
@@ -5857,7 +5872,7 @@ var l$13 = {
|
|
|
5857
5872
|
"font-size": "inherit",
|
|
5858
5873
|
"box-shadow": "none"
|
|
5859
5874
|
};
|
|
5860
|
-
var u$
|
|
5875
|
+
var u$14 = {
|
|
5861
5876
|
height: "100%",
|
|
5862
5877
|
width: "100%",
|
|
5863
5878
|
display: "block",
|
|
@@ -5941,7 +5956,7 @@ var m$7 = (e, t, { field: n, icon: r } = {}) => ({
|
|
|
5941
5956
|
var h$4 = { field: l$13 };
|
|
5942
5957
|
var g$4 = t$60()({
|
|
5943
5958
|
type: "formControl",
|
|
5944
|
-
attributeValues: { subType: e$
|
|
5959
|
+
attributeValues: { subType: e$40()([
|
|
5945
5960
|
"text",
|
|
5946
5961
|
"number",
|
|
5947
5962
|
"email",
|
|
@@ -5996,7 +6011,7 @@ var g$4 = t$60()({
|
|
|
5996
6011
|
definition: {
|
|
5997
6012
|
label: "Form Control",
|
|
5998
6013
|
type: "formControl",
|
|
5999
|
-
description: "A single labelled input (text/select/checkbox/… per its subType) inside a form; captures one field of user input. A select offers its `options`: `[{ label, value }, …]` — the text shown, and what the field takes. A `switch` is a checkbox announced and drawn as an on/off switch (`role=\"switch\"`), for a setting that applies at once; both hold `true`/`false`, and a `defaultValue` of `\"true\"` starts them on. Its slots: `label`, `requiredMark` (the `*` that ends the label of a required field), `input` (the box a typed field or a select is drawn in — a textarea, checkbox or switch is its own box), `field` (the `<input>` or `<select>` inside that box), `icon` (the show/hide button of a password) and `error`. The thumb of a switch is no element a class reaches: the class on its `input` slot sets `--plitzi-switch-thumb` (off), `--plitzi-switch-thumb-checked` (on, white by default) and `--plitzi-switch-thumb-shadow`.",
|
|
6014
|
+
description: "A single labelled input (text/select/checkbox/… per its subType) inside a form; captures one field of user input. Optional unless `required: true`, as an HTML field is: a `requiredMessage` alone requires nothing. A select offers its `options`: `[{ label, value }, …]` — the text shown, and what the field takes. A `switch` is a checkbox announced and drawn as an on/off switch (`role=\"switch\"`), for a setting that applies at once; both hold `true`/`false`, and a `defaultValue` of `\"true\"` starts them on. Its slots: `label`, `requiredMark` (the `*` that ends the label of a required field), `input` (the box a typed field or a select is drawn in — a textarea, checkbox or switch is its own box), `field` (the `<input>` or `<select>` inside that box), `icon` (the show/hide button of a password) and `error`. The box is ringed (`2px solid currentColor`) while the field inside has keyboard focus: restyle it with a `focus-within` state on the `input` slot — the box never takes `focus` itself. The thumb of a switch is no element a class reaches: the class on its `input` slot sets `--plitzi-switch-thumb` (off), `--plitzi-switch-thumb-checked` (on, white by default) and `--plitzi-switch-thumb-shadow`.",
|
|
6000
6015
|
bindings: {},
|
|
6001
6016
|
styleSelectors: {
|
|
6002
6017
|
base: "",
|
|
@@ -6051,7 +6066,7 @@ var g$4 = t$60()({
|
|
|
6051
6066
|
color: "inherit",
|
|
6052
6067
|
resize: "vertical"
|
|
6053
6068
|
}),
|
|
6054
|
-
select: m$7("Form Control Select", f$10, { field: u$
|
|
6069
|
+
select: m$7("Form Control Select", f$10, { field: u$14 }),
|
|
6055
6070
|
checkbox: {
|
|
6056
6071
|
name: "Form Control Checkbox",
|
|
6057
6072
|
displayMode: "desktop",
|
|
@@ -6063,7 +6078,7 @@ var g$4 = t$60()({
|
|
|
6063
6078
|
"margin-left": "0px",
|
|
6064
6079
|
"margin-right": "4px"
|
|
6065
6080
|
} },
|
|
6066
|
-
label: { default: i$
|
|
6081
|
+
label: { default: i$26 },
|
|
6067
6082
|
requiredMark: { default: s$20 },
|
|
6068
6083
|
error: { default: o$23 }
|
|
6069
6084
|
}
|
|
@@ -6075,7 +6090,7 @@ var g$4 = t$60()({
|
|
|
6075
6090
|
base: { default: {} },
|
|
6076
6091
|
input: { default: p$11 },
|
|
6077
6092
|
label: { default: {
|
|
6078
|
-
...i$
|
|
6093
|
+
...i$26,
|
|
6079
6094
|
"align-items": "center"
|
|
6080
6095
|
} },
|
|
6081
6096
|
requiredMark: { default: s$20 },
|
|
@@ -6089,7 +6104,7 @@ var g$4 = t$60()({
|
|
|
6089
6104
|
});
|
|
6090
6105
|
var n$36 = t$60()({
|
|
6091
6106
|
type: "layoutContainer",
|
|
6092
|
-
attributeValues: { subType: e$
|
|
6107
|
+
attributeValues: { subType: e$40()([
|
|
6093
6108
|
"div",
|
|
6094
6109
|
"header",
|
|
6095
6110
|
"footer",
|
|
@@ -6221,6 +6236,11 @@ var t$49 = t$60()({
|
|
|
6221
6236
|
});
|
|
6222
6237
|
var t$48 = t$60()({
|
|
6223
6238
|
type: "page",
|
|
6239
|
+
serverTemplates: [
|
|
6240
|
+
"seoPageTitle",
|
|
6241
|
+
"seoPageDescription",
|
|
6242
|
+
"notFound"
|
|
6243
|
+
],
|
|
6224
6244
|
triggers: { onPageLoad: {
|
|
6225
6245
|
action: "onPageLoad",
|
|
6226
6246
|
title: "On Page Load",
|
|
@@ -6388,12 +6408,12 @@ var t$46 = t$60()({
|
|
|
6388
6408
|
var n$35 = t$60()({
|
|
6389
6409
|
type: "image",
|
|
6390
6410
|
attributeValues: {
|
|
6391
|
-
fetchPriority: e$
|
|
6411
|
+
fetchPriority: e$40()([
|
|
6392
6412
|
"high",
|
|
6393
6413
|
"low",
|
|
6394
6414
|
"auto"
|
|
6395
6415
|
]),
|
|
6396
|
-
loadMode: e$
|
|
6416
|
+
loadMode: e$40()([
|
|
6397
6417
|
"auto",
|
|
6398
6418
|
"eager",
|
|
6399
6419
|
"lazy"
|
|
@@ -6542,7 +6562,7 @@ var t$44 = t$60()({
|
|
|
6542
6562
|
var n$34 = t$60()({
|
|
6543
6563
|
type: "apiContainer",
|
|
6544
6564
|
attributeValues: {
|
|
6545
|
-
subType: e$
|
|
6565
|
+
subType: e$40()([
|
|
6546
6566
|
"",
|
|
6547
6567
|
"div",
|
|
6548
6568
|
"header",
|
|
@@ -6555,25 +6575,26 @@ var n$34 = t$60()({
|
|
|
6555
6575
|
"address",
|
|
6556
6576
|
"figure"
|
|
6557
6577
|
]),
|
|
6558
|
-
method: e$
|
|
6578
|
+
method: e$40()([
|
|
6559
6579
|
"get",
|
|
6560
6580
|
"post",
|
|
6561
6581
|
"put",
|
|
6562
6582
|
"delete",
|
|
6563
6583
|
"patch"
|
|
6564
6584
|
]),
|
|
6565
|
-
credentials: e$
|
|
6585
|
+
credentials: e$40()([
|
|
6566
6586
|
"include",
|
|
6567
6587
|
"omit",
|
|
6568
6588
|
"same-origin"
|
|
6569
6589
|
]),
|
|
6570
|
-
pagination: e$
|
|
6590
|
+
pagination: e$40()([
|
|
6571
6591
|
"none",
|
|
6572
6592
|
"url",
|
|
6573
6593
|
"append"
|
|
6574
6594
|
])
|
|
6575
6595
|
},
|
|
6576
6596
|
sourceType: "apiContainer",
|
|
6597
|
+
serverTemplates: ["notFound"],
|
|
6577
6598
|
triggers: {
|
|
6578
6599
|
onApiError: {
|
|
6579
6600
|
action: "onApiError",
|
|
@@ -6715,7 +6736,7 @@ var n$34 = t$60()({
|
|
|
6715
6736
|
});
|
|
6716
6737
|
var n$33 = t$60()({
|
|
6717
6738
|
type: "channel",
|
|
6718
|
-
attributeValues: { subType: e$
|
|
6739
|
+
attributeValues: { subType: e$40()([
|
|
6719
6740
|
"",
|
|
6720
6741
|
"div",
|
|
6721
6742
|
"section",
|
|
@@ -6734,7 +6755,8 @@ var n$33 = t$60()({
|
|
|
6734
6755
|
data: "",
|
|
6735
6756
|
from: "",
|
|
6736
6757
|
user: "",
|
|
6737
|
-
at: ""
|
|
6758
|
+
at: "",
|
|
6759
|
+
echo: !1
|
|
6738
6760
|
}
|
|
6739
6761
|
},
|
|
6740
6762
|
onJoin: {
|
|
@@ -6776,6 +6798,11 @@ var n$33 = t$60()({
|
|
|
6776
6798
|
label: "Data (JSON or a template)",
|
|
6777
6799
|
defaultValue: "",
|
|
6778
6800
|
type: "text"
|
|
6801
|
+
},
|
|
6802
|
+
echo: {
|
|
6803
|
+
label: "Heard on this page too",
|
|
6804
|
+
defaultValue: !1,
|
|
6805
|
+
type: "boolean"
|
|
6779
6806
|
}
|
|
6780
6807
|
}
|
|
6781
6808
|
},
|
|
@@ -6801,7 +6828,7 @@ var n$33 = t$60()({
|
|
|
6801
6828
|
definition: {
|
|
6802
6829
|
label: "Channel",
|
|
6803
6830
|
type: "channel",
|
|
6804
|
-
description: "A realtime channel: every page on the same `topic` hears what
|
|
6831
|
+
description: "A realtime channel: every OTHER page on the same `topic` hears what one publishes, within milliseconds — the page that sent it too with `echo` (its `from` is then the channel's `me`). The topic must match a channel the space declares in its settings (`channels`), e.g. `board:{{ id }}` under `board:{id}`. A topic of a private channel (`grant: true`) opens only with `grant`, bound to the grant the action that let this visitor in returned (its `realtime.grant` step). ITS DESCENDANTS bind to its source `channel_<id>`: `connected`, `members` (with the state each announced), `messages` (the last `keep`) and `last`. It fires `onMessage`; `onJoin` when somebody who came after this page has announced who they are, and `onLeave` when somebody goes — each with `from`, `user` and the `state` they announced; and answers `publish({ type, data, echo })` and `setPresence({ data })`; `presence` is the state this page announces (a name, a colour). Closed in the builder and anywhere without a server.",
|
|
6805
6832
|
items: [],
|
|
6806
6833
|
bindings: {},
|
|
6807
6834
|
styleSelectors: { base: "" },
|
|
@@ -6835,6 +6862,49 @@ var n$33 = t$60()({
|
|
|
6835
6862
|
}
|
|
6836
6863
|
});
|
|
6837
6864
|
var t$43 = t$60()({
|
|
6865
|
+
type: "carouselTrack",
|
|
6866
|
+
ancestorType: "carousel",
|
|
6867
|
+
content: {
|
|
6868
|
+
attributes: {},
|
|
6869
|
+
definition: {
|
|
6870
|
+
label: "Carousel Track",
|
|
6871
|
+
type: "carouselTrack",
|
|
6872
|
+
description: "Where a carousel shows its slides: what is inside is one slide, rendered once per item.",
|
|
6873
|
+
items: [],
|
|
6874
|
+
bindings: {},
|
|
6875
|
+
styleSelectors: { base: "" },
|
|
6876
|
+
initialState: { visibility: !0 }
|
|
6877
|
+
},
|
|
6878
|
+
builder: {
|
|
6879
|
+
canDelete: !0,
|
|
6880
|
+
canSelect: !0,
|
|
6881
|
+
canDragDrop: !0,
|
|
6882
|
+
canMove: !0,
|
|
6883
|
+
canSnippet: !1,
|
|
6884
|
+
itemsAllowed: [],
|
|
6885
|
+
itemsNotAllowed: []
|
|
6886
|
+
},
|
|
6887
|
+
market: {
|
|
6888
|
+
category: "structure",
|
|
6889
|
+
owner: "Plitzi",
|
|
6890
|
+
verified: !0,
|
|
6891
|
+
license: "MIT",
|
|
6892
|
+
website: "https://plitzi.com",
|
|
6893
|
+
backgroundColor: "#4422ee",
|
|
6894
|
+
icon: "fa-solid fa-film"
|
|
6895
|
+
},
|
|
6896
|
+
defaultStyle: {
|
|
6897
|
+
name: "Carousel Track",
|
|
6898
|
+
displayMode: "desktop",
|
|
6899
|
+
style: { base: { default: {
|
|
6900
|
+
position: "relative",
|
|
6901
|
+
overflow: "hidden"
|
|
6902
|
+
} } }
|
|
6903
|
+
},
|
|
6904
|
+
settings: {}
|
|
6905
|
+
}
|
|
6906
|
+
});
|
|
6907
|
+
var t$42 = t$60()({
|
|
6838
6908
|
type: "carousel",
|
|
6839
6909
|
sourceType: "carousel",
|
|
6840
6910
|
triggers: { onChange: {
|
|
@@ -6936,53 +7006,10 @@ var t$43 = t$60()({
|
|
|
6936
7006
|
},
|
|
6937
7007
|
initialItems: ["carouselTrack"]
|
|
6938
7008
|
});
|
|
6939
|
-
var t$42 = t$60()({
|
|
6940
|
-
type: "carouselTrack",
|
|
6941
|
-
ancestorType: "carousel",
|
|
6942
|
-
content: {
|
|
6943
|
-
attributes: {},
|
|
6944
|
-
definition: {
|
|
6945
|
-
label: "Carousel Track",
|
|
6946
|
-
type: "carouselTrack",
|
|
6947
|
-
description: "Where a carousel shows its slides: what is inside is one slide, rendered once per item.",
|
|
6948
|
-
items: [],
|
|
6949
|
-
bindings: {},
|
|
6950
|
-
styleSelectors: { base: "" },
|
|
6951
|
-
initialState: { visibility: !0 }
|
|
6952
|
-
},
|
|
6953
|
-
builder: {
|
|
6954
|
-
canDelete: !0,
|
|
6955
|
-
canSelect: !0,
|
|
6956
|
-
canDragDrop: !0,
|
|
6957
|
-
canMove: !0,
|
|
6958
|
-
canSnippet: !1,
|
|
6959
|
-
itemsAllowed: [],
|
|
6960
|
-
itemsNotAllowed: []
|
|
6961
|
-
},
|
|
6962
|
-
market: {
|
|
6963
|
-
category: "structure",
|
|
6964
|
-
owner: "Plitzi",
|
|
6965
|
-
verified: !0,
|
|
6966
|
-
license: "MIT",
|
|
6967
|
-
website: "https://plitzi.com",
|
|
6968
|
-
backgroundColor: "#4422ee",
|
|
6969
|
-
icon: "fa-solid fa-film"
|
|
6970
|
-
},
|
|
6971
|
-
defaultStyle: {
|
|
6972
|
-
name: "Carousel Track",
|
|
6973
|
-
displayMode: "desktop",
|
|
6974
|
-
style: { base: { default: {
|
|
6975
|
-
position: "relative",
|
|
6976
|
-
overflow: "hidden"
|
|
6977
|
-
} } }
|
|
6978
|
-
},
|
|
6979
|
-
settings: {}
|
|
6980
|
-
}
|
|
6981
|
-
});
|
|
6982
7009
|
var r$30 = t$60()({
|
|
6983
7010
|
type: "container",
|
|
6984
7011
|
attributeValues: {
|
|
6985
|
-
subType: e$
|
|
7012
|
+
subType: e$40()([
|
|
6986
7013
|
"div",
|
|
6987
7014
|
"header",
|
|
6988
7015
|
"footer",
|
|
@@ -7006,7 +7033,7 @@ var r$30 = t$60()({
|
|
|
7006
7033
|
"p",
|
|
7007
7034
|
"span"
|
|
7008
7035
|
]),
|
|
7009
|
-
live: e$
|
|
7036
|
+
live: e$40()([
|
|
7010
7037
|
"",
|
|
7011
7038
|
"polite",
|
|
7012
7039
|
"assertive"
|
|
@@ -7097,8 +7124,8 @@ var B$2 = {
|
|
|
7097
7124
|
BlockHtml: t$59,
|
|
7098
7125
|
BlockJsx: t$58,
|
|
7099
7126
|
Button: r$33,
|
|
7100
|
-
Carousel: t$
|
|
7101
|
-
CarouselTrack: t$
|
|
7127
|
+
Carousel: t$42,
|
|
7128
|
+
CarouselTrack: t$43,
|
|
7102
7129
|
Channel: n$33,
|
|
7103
7130
|
Container: r$30,
|
|
7104
7131
|
Custom: t$57,
|
|
@@ -7231,8 +7258,7 @@ var B$2 = {
|
|
|
7231
7258
|
top: "0",
|
|
7232
7259
|
position: "absolute",
|
|
7233
7260
|
"z-index": "210",
|
|
7234
|
-
"background-color": "
|
|
7235
|
-
opacity: "0.5"
|
|
7261
|
+
"background-color": "rgb(0 0 0 / 50%)"
|
|
7236
7262
|
} },
|
|
7237
7263
|
rootContainer: { default: {
|
|
7238
7264
|
display: "flex",
|
|
@@ -7303,8 +7329,8 @@ var B$2 = {
|
|
|
7303
7329
|
List: t$60()({
|
|
7304
7330
|
type: "list",
|
|
7305
7331
|
attributeValues: {
|
|
7306
|
-
subType: e$
|
|
7307
|
-
source: e$
|
|
7332
|
+
subType: e$40()(["ul", "ol"]),
|
|
7333
|
+
source: e$40()(["none", "controlled"])
|
|
7308
7334
|
},
|
|
7309
7335
|
sourceType: "list",
|
|
7310
7336
|
content: {
|
|
@@ -7467,7 +7493,7 @@ var B$2 = {
|
|
|
7467
7493
|
definition: {
|
|
7468
7494
|
label: "Modal Container",
|
|
7469
7495
|
type: "modalContainer",
|
|
7470
|
-
description: "A modal overlay container opened and closed through interactions; use for dialogs over the page.",
|
|
7496
|
+
description: "A modal overlay container opened and closed through interactions; use for dialogs over the page. The element itself is fixed over the whole viewport, and holds two layers side by side — neither inside the other: `backgroundContainer`, the dim layer, `rgb(0 0 0 / 50%)` (its `background-color` is the whole dim), and `rootContainer`, the dialog, centred by `top: 50%`, `left: 50%` and `transform: translate3d(-50%, -50%, 0)` — to sit it near the top, set `top` and `transform: translateX(-50%)`; flex alignment on the dim layer moves nothing. Inside the dialog, top to bottom: `headerContainer` (with `headerTitle` and `headerCloseButton`) and `bodyContainer`.",
|
|
7471
7497
|
items: [],
|
|
7472
7498
|
bindings: {},
|
|
7473
7499
|
loadStrategy: "lazy",
|
|
@@ -7519,8 +7545,7 @@ var B$2 = {
|
|
|
7519
7545
|
top: "0",
|
|
7520
7546
|
position: "absolute",
|
|
7521
7547
|
"z-index": "210",
|
|
7522
|
-
"background-color": "
|
|
7523
|
-
opacity: "0.5"
|
|
7548
|
+
"background-color": "rgb(0 0 0 / 50%)"
|
|
7524
7549
|
} },
|
|
7525
7550
|
rootContainer: { default: {
|
|
7526
7551
|
display: "flex",
|
|
@@ -7604,8 +7629,8 @@ var B$2 = {
|
|
|
7604
7629
|
Pagination: t$60()({
|
|
7605
7630
|
type: "pagination",
|
|
7606
7631
|
attributeValues: {
|
|
7607
|
-
mode: e$
|
|
7608
|
-
target: e$
|
|
7632
|
+
mode: e$40()(["pages", "loadMore"]),
|
|
7633
|
+
target: e$40()(["url", "interaction"])
|
|
7609
7634
|
},
|
|
7610
7635
|
triggers: { onPageChange: {
|
|
7611
7636
|
action: "onPageChange",
|
|
@@ -7857,6 +7882,7 @@ var B$2 = {
|
|
|
7857
7882
|
ThemeToggle: r$32,
|
|
7858
7883
|
Video: t$44
|
|
7859
7884
|
};
|
|
7885
|
+
Object.fromEntries(Object.values(B$2).flatMap((e) => "serverTemplates" in e ? [[e.type, e.serverTemplates]] : []));
|
|
7860
7886
|
/** Every declaration, read through the part of its shape this catalog uses. */
|
|
7861
7887
|
var declarations$1 = B$2;
|
|
7862
7888
|
/** Keyed by the schema `type`, which is what a document and every catalog address a type by. */
|
|
@@ -7867,7 +7893,7 @@ var elementCatalog = Object.fromEntries(Object.values(declarations$1).map((decla
|
|
|
7867
7893
|
}]));
|
|
7868
7894
|
Object.keys(elementCatalog);
|
|
7869
7895
|
Object.fromEntries(Object.values(declarations$1).filter((declaration) => declaration.sourceType).map((declaration) => [declaration.type, declaration.sourceType]));
|
|
7870
|
-
Object.fromEntries(Object.values(declarations$1).map((declaration) => [declaration.type, [...Object.keys(e$
|
|
7896
|
+
Object.fromEntries(Object.values(declarations$1).map((declaration) => [declaration.type, [...Object.keys(e$41), ...Object.keys(declaration.triggers ?? {})]]));
|
|
7871
7897
|
/** The triggers only some types fire, by action name — for a step builder that wants the title the builder shows. */
|
|
7872
7898
|
var typeTriggerDefinitions = Object.fromEntries(Object.values(declarations$1).flatMap((declaration) => Object.entries(declaration.triggers ?? {})));
|
|
7873
7899
|
Object.fromEntries(Object.values(declarations$1).flatMap((declaration) => Object.entries(declaration.callbacks ?? {})));
|
|
@@ -7968,10 +7994,20 @@ var AUTHORING_CODES = {
|
|
|
7968
7994
|
means: "a page that sends visitors it is not for to a page the space does not have",
|
|
7969
7995
|
fix: "a page's id or slug (`''` is the home page), or a full URL"
|
|
7970
7996
|
},
|
|
7997
|
+
"page-template": {
|
|
7998
|
+
kind: "refused",
|
|
7999
|
+
means: "a template in a page's `seoTitle`, `seoDescription` or `notFound` that reads what is not there when the server answers — anything but the page's `runtime: 'server'` providers and `navigation` — or cannot be read",
|
|
8000
|
+
fix: "read the record from a provider with `runtime: 'server'` on the page or its layout — `'{{ apiContainer_post.title }} — Blog'` — or words of its own"
|
|
8001
|
+
},
|
|
8002
|
+
"declared-callback-target": {
|
|
8003
|
+
kind: "refused",
|
|
8004
|
+
means: "a `declaredCallback` target with a key beside `on` and `params` — read nowhere, so the step runs without it",
|
|
8005
|
+
fix: "the value in `params`: `{ on: 'calendar', params: { date } }`"
|
|
8006
|
+
},
|
|
7971
8007
|
"folder-undeclared": {
|
|
7972
8008
|
kind: "refused",
|
|
7973
8009
|
means: "a page, a layout or a folder filed in a folder the space does not declare",
|
|
7974
|
-
fix: "declare the
|
|
8010
|
+
fix: "declare it on the space — `pageFolders: [{ id: 'docs', name: 'Docs' }]`, its slug starting its pages' addresses — or use the name it suggests"
|
|
7975
8011
|
},
|
|
7976
8012
|
"folder-cycle": {
|
|
7977
8013
|
kind: "refused",
|
|
@@ -8068,6 +8104,11 @@ var AUTHORING_CODES = {
|
|
|
8068
8104
|
means: "a `slots` key the element type does not have — its class would dress nothing",
|
|
8069
8105
|
fix: "one of the slots `plitzi explain <type>` lists; the element itself takes `class`"
|
|
8070
8106
|
},
|
|
8107
|
+
"slot-not-class": {
|
|
8108
|
+
kind: "refused",
|
|
8109
|
+
means: "a `slots` entry that is not a class — rules written in place, or nothing — which a slot cannot wear",
|
|
8110
|
+
fix: "the rules as a `styles()` declaration, handed to the slot beside its other classes"
|
|
8111
|
+
},
|
|
8071
8112
|
"class-conflict": {
|
|
8072
8113
|
kind: "refused",
|
|
8073
8114
|
means: "two different declarations for one class name",
|
|
@@ -8081,7 +8122,7 @@ var AUTHORING_CODES = {
|
|
|
8081
8122
|
"class-and-css": {
|
|
8082
8123
|
kind: "refused",
|
|
8083
8124
|
means: "an element wearing a shared class AND `css` or `states` of its own — it has one base selector",
|
|
8084
|
-
fix: "the rules on top of the class: `class: [card, { opacity: '0.5' }]`
|
|
8125
|
+
fix: "the rules on top of the class: `class: [card, { opacity: '0.5' }]` — or into the class"
|
|
8085
8126
|
},
|
|
8086
8127
|
"class-and-selector": {
|
|
8087
8128
|
kind: "refused",
|
|
@@ -8093,11 +8134,6 @@ var AUTHORING_CODES = {
|
|
|
8093
8134
|
means: "more than one set of rules in a class list",
|
|
8094
8135
|
fix: "one set, after the classes: `class: [card, { opacity: '0.5', 'margin-top': '8px' }]`"
|
|
8095
8136
|
},
|
|
8096
|
-
"modifier-without-id": {
|
|
8097
|
-
kind: "refused",
|
|
8098
|
-
means: "rules on top of a class on an element with no `id` — the id names the class they become",
|
|
8099
|
-
fix: "`id: 'hero-bg'`"
|
|
8100
|
-
},
|
|
8101
8137
|
"selector-invalid": {
|
|
8102
8138
|
kind: "refused",
|
|
8103
8139
|
means: "a `selector` that is not a CSS class name",
|
|
@@ -8143,6 +8179,11 @@ var AUTHORING_CODES = {
|
|
|
8143
8179
|
means: "an ancestor condition keyed by something that is neither a class name nor `'>'` (the parent)",
|
|
8144
8180
|
fix: "`[card.name]` for a `styles()` declaration, or `'>'` for the parent whatever it wears"
|
|
8145
8181
|
},
|
|
8182
|
+
"focus-on-field-box": {
|
|
8183
|
+
kind: "warned",
|
|
8184
|
+
means: "a `focus` or `focus-visible` state on a text field's or a select's `input` slot — the box the field is drawn in, which never takes focus, so no ring is ever shown",
|
|
8185
|
+
fix: "`'focus-within'` on the same class, or the state on the `field` slot"
|
|
8186
|
+
},
|
|
8146
8187
|
"heading-level-overridden": {
|
|
8147
8188
|
kind: "warned",
|
|
8148
8189
|
means: "a markdown's or richText's `heading` slot and a level's (`heading3`) both setting one property, the general class written later in the stylesheet — the level's value is lost",
|
|
@@ -8373,6 +8414,11 @@ var AUTHORING_CODES = {
|
|
|
8373
8414
|
means: "a `runtime: 'server'` element inside a component: the page server resolves a page's and its layouts', never a component's",
|
|
8374
8415
|
fix: "put the provider on the page, around the instance, and hand the component its rows as a prop"
|
|
8375
8416
|
},
|
|
8417
|
+
"template-in-value": {
|
|
8418
|
+
kind: "refused",
|
|
8419
|
+
means: "a `{{ }}` inside an attribute that is an object or a list — a provider's `input`, a list's `items`, a plugin's settings: only an attribute that is text is evaluated",
|
|
8420
|
+
fix: "a binding on the attribute (`bindTemplate(name, source, template, { returns: 'value' })`); for a provider's `input`, nothing for a route or query param — the action is already handed them as `input.<name>`"
|
|
8421
|
+
},
|
|
8376
8422
|
"not-found-in-browser": {
|
|
8377
8423
|
kind: "refused",
|
|
8378
8424
|
means: "`notFound` on a provider asked from the browser — its answer arrives after the page was sent with its status",
|
|
@@ -8380,7 +8426,7 @@ var AUTHORING_CODES = {
|
|
|
8380
8426
|
},
|
|
8381
8427
|
"not-found-not-a-template": {
|
|
8382
8428
|
kind: "refused",
|
|
8383
|
-
means: "`notFound
|
|
8429
|
+
means: "`notFound`, a provider's or a page's, that is not one `{{ expression }}` — never `true`, so never a 404",
|
|
8384
8430
|
fix: "`notFound: '{{ source.found == false }}'`"
|
|
8385
8431
|
},
|
|
8386
8432
|
"server-data-in-browser": {
|
|
@@ -8403,6 +8449,11 @@ var AUTHORING_CODES = {
|
|
|
8403
8449
|
means: "a control in a form with no `name` — its value never reaches `values`",
|
|
8404
8450
|
fix: "`formControl({ name: 'email', … })`"
|
|
8405
8451
|
},
|
|
8452
|
+
"required-message-unused": {
|
|
8453
|
+
kind: "warned",
|
|
8454
|
+
means: "a `requiredMessage` on a field nothing requires — fields are optional unless `required: true`, so it is never shown and an empty answer is sent",
|
|
8455
|
+
fix: "`required: true` on the field, or no message"
|
|
8456
|
+
},
|
|
8406
8457
|
"form-control-name-taken": {
|
|
8407
8458
|
kind: "warned",
|
|
8408
8459
|
means: "two controls in one form with one name — one overwrites the other",
|
|
@@ -8980,10 +9031,14 @@ var sourceRow = (listSource, items) => {
|
|
|
8980
9031
|
const shape = Reflect.get(items, SHAPE);
|
|
8981
9032
|
return {
|
|
8982
9033
|
item: pathTo(`${listSource}.item`, Array.isArray(shape) ? itemShape(shape) : UNKNOWN),
|
|
8983
|
-
index: pathTo(`${listSource}.index`, 0)
|
|
9034
|
+
index: pathTo(`${listSource}.index`, 0),
|
|
9035
|
+
inTemplate: {
|
|
9036
|
+
item: `${listSource}.item`,
|
|
9037
|
+
index: `${listSource}.index`
|
|
9038
|
+
}
|
|
8984
9039
|
};
|
|
8985
9040
|
};
|
|
8986
|
-
var e$
|
|
9041
|
+
var e$39 = [
|
|
8987
9042
|
"variables",
|
|
8988
9043
|
"navigation",
|
|
8989
9044
|
"auth",
|
|
@@ -8993,7 +9048,7 @@ var e$38 = [
|
|
|
8993
9048
|
"flags",
|
|
8994
9049
|
"computed"
|
|
8995
9050
|
];
|
|
8996
|
-
e$
|
|
9051
|
+
e$39.filter((e) => e !== "state" && e !== "computed");
|
|
8997
9052
|
var t$30 = {
|
|
8998
9053
|
DISPLAY: "display",
|
|
8999
9054
|
FLEX_WRAP: "flex-wrap",
|
|
@@ -9199,7 +9254,7 @@ Object.values(t$30).map((e) => ({
|
|
|
9199
9254
|
label: e
|
|
9200
9255
|
}));
|
|
9201
9256
|
t$30.DISPLAY, t$30.FLEX_WRAP, t$30.FLEX_DIRECTION, t$30.ALIGN_ITEMS, t$30.JUSTIFY_ITEMS, t$30.JUSTIFY_CONTENT, t$30.ALIGN_CONTENT, t$30.ROW_GAP, t$30.COLUMN_GAP, t$30.GRID_ROW_GAP, t$30.GRID_COLUMN_GAP, t$30.GRID_TEMPLATE_AREAS, t$30.GRID_TEMPLATE_COLUMNS, t$30.GRID_TEMPLATE_ROWS, t$30.GRID_AUTO_FLOW, t$30.GRID_AUTO_ROWS, t$30.GRID_AUTO_COLUMNS, t$30.GRID_ROW_START, t$30.GRID_COLUMN_START, t$30.GRID_ROW_END, t$30.GRID_COLUMN_END, t$30.ALIGN_SELF, t$30.JUSTIFY_SELF, t$30.ORDER, t$30.FLEX_GROW, t$30.FLEX_SHRINK, t$30.FLEX_BASIS, t$30.LIST_STYLE, t$30.LIST_STYLE_TYPE, t$30.LIST_STYLE_POSITION, t$30.LIST_STYLE_IMAGE, t$30.BACKGROUND_COLOR, t$30.BACKGROUND_IMAGE, t$30.BACKGROUND_POSITION, t$30.BACKGROUND_SIZE, t$30.BACKGROUND_CLIP, t$30.BACKGROUND_ORIGIN, t$30.BACKGROUND_REPEAT, t$30.BACKGROUND_ATTACHMENT, t$30.BACKGROUND_BLEND_MODE, t$30.MASK_IMAGE, t$30.MASK_SIZE, t$30.MASK_POSITION, t$30.MASK_REPEAT, t$30.MASK_COMPOSITE, t$30.WEBKIT_MASK_IMAGE, t$30.BORDER_TOP_STYLE, t$30.BORDER_TOP_WIDTH, t$30.BORDER_TOP_COLOR, t$30.BORDER_BOTTOM_STYLE, t$30.BORDER_BOTTOM_WIDTH, t$30.BORDER_BOTTOM_COLOR, t$30.BORDER_LEFT_STYLE, t$30.BORDER_LEFT_WIDTH, t$30.BORDER_LEFT_COLOR, t$30.BORDER_RIGHT_STYLE, t$30.BORDER_RIGHT_WIDTH, t$30.BORDER_RIGHT_COLOR, t$30.BORDER_TOP_LEFT_RADIUS, t$30.BORDER_TOP_RIGHT_RADIUS, t$30.BORDER_BOTTOM_LEFT_RADIUS, t$30.BORDER_BOTTOM_RIGHT_RADIUS, t$30.BORDER_COLLAPSE, t$30.BORDER_SPACING, t$30.TABLE_LAYOUT, t$30.OPACITY, t$30.VISIBILITY, t$30.CURSOR, t$30.TRANSITION, t$30.TRANSITION_PROPERTY, t$30.TRANSITION_DURATION, t$30.TRANSITION_TIMING_FUNCTION, t$30.TRANSITION_DELAY, t$30.TRANSITION_BEHAVIOR, t$30.ANIMATION, t$30.ANIMATION_NAME, t$30.ANIMATION_DURATION, t$30.ANIMATION_TIMING_FUNCTION, t$30.ANIMATION_DELAY, t$30.ANIMATION_ITERATION_COUNT, t$30.ANIMATION_DIRECTION, t$30.ANIMATION_FILL_MODE, t$30.ANIMATION_PLAY_STATE, t$30.ANIMATION_TIMELINE, t$30.ANIMATION_RANGE, t$30.BOX_SHADOW, t$30.FILTER, t$30.BACKDROP_FILTER, t$30.MIX_BLEND_MODE, t$30.ISOLATION, t$30.CLIP_PATH, t$30.TRANSFORM, t$30.TRANSFORM_ORIGIN, t$30.TRANSLATE, t$30.ROTATE, t$30.SCALE, t$30.TRANSFORM_STYLE, t$30.PERSPECTIVE, t$30.PERSPECTIVE_ORIGIN, t$30.BACKFACE_VISIBILITY, t$30.WILL_CHANGE, t$30.OUTLINE_WIDTH, t$30.OUTLINE_STYLE, t$30.OUTLINE_COLOR, t$30.OUTLINE_OFFSET, t$30.POINTER_EVENTS, t$30.USER_SELECT, t$30.TOUCH_ACTION, t$30.RESIZE, t$30.APPEARANCE, t$30.SCROLL_BEHAVIOR, t$30.OVERSCROLL_BEHAVIOR, t$30.SCROLL_SNAP_TYPE, t$30.SCROLL_SNAP_ALIGN, t$30.SCROLL_SNAP_STOP, t$30.SCROLL_PADDING_TOP, t$30.SCROLL_MARGIN_TOP, t$30.ACCENT_COLOR, t$30.CARET_COLOR, t$30.COLOR_SCHEME, t$30.POSITION, t$30.FLOAT, t$30.CLEAR, t$30.Z_INDEX, t$30.TOP, t$30.BOTTOM, t$30.LEFT, t$30.RIGHT, t$30.BOX_SIZING, t$30.ASPECT_RATIO, t$30.WIDTH, t$30.HEIGHT, t$30.MIN_WIDTH, t$30.MIN_HEIGHT, t$30.MAX_WIDTH, t$30.MAX_HEIGHT, t$30.OVERFLOW, t$30.OVERFLOW_X, t$30.OVERFLOW_Y, t$30.SCROLLBAR_WIDTH, t$30.SCROLLBAR_COLOR, t$30.CONTAINER_TYPE, t$30.CONTENT, t$30.CONTAINER_NAME, t$30.OBJECT_FIT, t$30.OBJECT_POSITION, t$30.COLUMN_WIDTH, t$30.COLUMN_COUNT, t$30.MARGIN_TOP, t$30.MARGIN_BOTTOM, t$30.MARGIN_LEFT, t$30.MARGIN_RIGHT, t$30.PADDING_TOP, t$30.PADDING_BOTTOM, t$30.PADDING_LEFT, t$30.PADDING_RIGHT, t$30.FONT_FAMILY, t$30.FONT_WEIGHT, t$30.FONT_SIZE, t$30.LINE_HEIGHT, t$30.COLOR, t$30.TEXT_ALIGN, t$30.FONT_STYLE, t$30.FONT_VARIANT, t$30.FONT_VARIANT_NUMERIC, t$30.FONT_FEATURE_SETTINGS, t$30.TEXT_DECORATION, t$30.TEXT_DECORATION_LINE, t$30.TEXT_DECORATION_COLOR, t$30.TEXT_DECORATION_STYLE, t$30.TEXT_DECORATION_THICKNESS, t$30.TEXT_UNDERLINE_OFFSET, t$30.LETTER_SPACING, t$30.WORD_SPACING, t$30.TEXT_INDENT, t$30.TEXT_TRANSFORM, t$30.DIRECTION, t$30.WRITING_MODE, t$30.TEXT_ORIENTATION, t$30.WHITE_SPACE, t$30.TEXT_WRAP, t$30.WORD_BREAK, t$30.OVERFLOW_WRAP, t$30.HYPHENS, t$30.VERTICAL_ALIGN, t$30.TEXT_OVERFLOW, t$30.TEXT_SHADOW, t$30.LINE_CLAMP, t$30.WEBKIT_LINE_CLAMP, t$30.WEBKIT_BOX_ORIENT, t$30.WEBKIT_TEXT_FILL_COLOR, t$30.WEBKIT_BACKGROUND_CLIP, t$30.BOX_DECORATION_BREAK, t$30.WEBKIT_BOX_DECORATION_BREAK, t$30.FILL, t$30.STROKE, t$30.STROKE_WIDTH;
|
|
9202
|
-
[...e$
|
|
9257
|
+
[...e$39];
|
|
9203
9258
|
/** Both binding forms as one list. The map form targets attributes, which is what nearly every binding does. */
|
|
9204
9259
|
var toBindingSpecs = (bind) => Array.isArray(bind) ? bind : Object.entries(bind).map(([to, source]) => ({
|
|
9205
9260
|
to,
|
|
@@ -9511,20 +9566,20 @@ var tabContainerItem = defineElement(B$2.TabContainerItem);
|
|
|
9511
9566
|
var text$1 = defineElement(B$2.Text);
|
|
9512
9567
|
var themeToggle = defineElement(B$2.ThemeToggle);
|
|
9513
9568
|
var video = defineElement(B$2.Video);
|
|
9514
|
-
var e$
|
|
9569
|
+
var e$33 = (e) => typeof e == "object" && !!e && !Array.isArray(e);
|
|
9515
9570
|
var STEP_TYPES = [
|
|
9516
9571
|
"trigger",
|
|
9517
9572
|
"globalCallback",
|
|
9518
9573
|
"callback",
|
|
9519
9574
|
"utility"
|
|
9520
9575
|
];
|
|
9521
|
-
var e$
|
|
9576
|
+
var e$31 = {
|
|
9522
9577
|
desktop: 1024,
|
|
9523
9578
|
tablet: 768,
|
|
9524
9579
|
mobile: 0
|
|
9525
9580
|
};
|
|
9526
|
-
var t$26 = (t) => e$
|
|
9527
|
-
var e$
|
|
9581
|
+
var t$26 = (t) => e$31[t] === 0 ? "0" : `${String(e$31[t] / 16)}rem`;
|
|
9582
|
+
var e$30 = [
|
|
9528
9583
|
"desktop",
|
|
9529
9584
|
"tablet",
|
|
9530
9585
|
"mobile"
|
|
@@ -9532,14 +9587,14 @@ var e$29 = [
|
|
|
9532
9587
|
Object.values(/* @__PURE__ */ function(e) {
|
|
9533
9588
|
return e.COLOR = "color", e.SPACING = "spacing", e.SHADOW = "shadow", e.CUSTOM = "custom", e;
|
|
9534
9589
|
}({}));
|
|
9535
|
-
var e$
|
|
9590
|
+
var e$28 = {
|
|
9536
9591
|
"motion-reduce": "@media (prefers-reduced-motion: reduce)",
|
|
9537
9592
|
"motion-safe": "@media (prefers-reduced-motion: no-preference)"
|
|
9538
9593
|
};
|
|
9539
|
-
var t$23 = Object.keys(e$
|
|
9540
|
-
var r$18 = (t) => Object.hasOwn(e$
|
|
9541
|
-
var i$
|
|
9542
|
-
var a$15 = String.raw`\((?:min|max)-width:\s*${i$
|
|
9594
|
+
var t$23 = Object.keys(e$28);
|
|
9595
|
+
var r$18 = (t) => Object.hasOwn(e$28, t);
|
|
9596
|
+
var i$18 = String.raw`\d+(?:\.\d+)?(?:px|rem|em|ch)`;
|
|
9597
|
+
var a$15 = String.raw`\((?:min|max)-width:\s*${i$18}\)`;
|
|
9543
9598
|
var o$17 = new RegExp(String.raw`^container(?:\s+(?<name>-?[_a-zA-Z][\w-]*))?\s+(?<query>${a$15}(?:\s+and\s+${a$15})?)$`);
|
|
9544
9599
|
var s$15 = (e) => {
|
|
9545
9600
|
let t = o$17.exec(e.trim());
|
|
@@ -9553,7 +9608,7 @@ var c$12 = (e) => {
|
|
|
9553
9608
|
let t = s$15(e);
|
|
9554
9609
|
if (t) return t.name ? `container ${t.name} ${t.query}` : `container ${t.query}`;
|
|
9555
9610
|
};
|
|
9556
|
-
var e$
|
|
9611
|
+
var e$27 = [
|
|
9557
9612
|
"before",
|
|
9558
9613
|
"after",
|
|
9559
9614
|
"marker",
|
|
@@ -9572,7 +9627,7 @@ var t$22 = {
|
|
|
9572
9627
|
selection: "::selection"
|
|
9573
9628
|
};
|
|
9574
9629
|
var n$19 = (e) => Object.hasOwn(t$22, e);
|
|
9575
|
-
var i$
|
|
9630
|
+
var i$17 = [
|
|
9576
9631
|
"before",
|
|
9577
9632
|
"after",
|
|
9578
9633
|
"marker"
|
|
@@ -9633,7 +9688,7 @@ var l$8 = {
|
|
|
9633
9688
|
...c$11
|
|
9634
9689
|
]
|
|
9635
9690
|
};
|
|
9636
|
-
var u$
|
|
9691
|
+
var u$8 = (e, t) => {
|
|
9637
9692
|
let n = l$8[e];
|
|
9638
9693
|
return !n || t.startsWith("--") || n.includes(t);
|
|
9639
9694
|
};
|
|
@@ -9672,7 +9727,7 @@ var m$4 = (e) => {
|
|
|
9672
9727
|
let t = p$8(e.trim());
|
|
9673
9728
|
return t?.length ? t.every((e) => /^(["']).*\1$/s.test(e) || d$7.has(e.toLowerCase()) || f$5.test(e) && e.endsWith(")")) : !1;
|
|
9674
9729
|
};
|
|
9675
|
-
var e$
|
|
9730
|
+
var e$26 = [
|
|
9676
9731
|
"hover",
|
|
9677
9732
|
"focus",
|
|
9678
9733
|
"focus-visible",
|
|
@@ -9707,7 +9762,7 @@ var r$16 = {
|
|
|
9707
9762
|
disabled: 13,
|
|
9708
9763
|
hidden: 14
|
|
9709
9764
|
};
|
|
9710
|
-
var i$
|
|
9765
|
+
var i$16 = (e) => Object.hasOwn(r$16, e);
|
|
9711
9766
|
var l$7 = {
|
|
9712
9767
|
current: ":is([aria-current]:not([aria-current=\"false\"]),[aria-pressed=\"true\"],[aria-selected=\"true\"],[role=\"tabpanel\"]:not([hidden]))",
|
|
9713
9768
|
expanded: "[aria-expanded=\"true\"]",
|
|
@@ -9717,7 +9772,7 @@ var l$7 = {
|
|
|
9717
9772
|
odd: ":nth-child(odd)",
|
|
9718
9773
|
even: ":nth-child(even)"
|
|
9719
9774
|
};
|
|
9720
|
-
var u$
|
|
9775
|
+
var u$7 = (e) => (i$16(e) ? l$7[e] : void 0) ?? `:${e}`;
|
|
9721
9776
|
var p$7 = (e) => e === ">";
|
|
9722
9777
|
var n$16 = (e) => {
|
|
9723
9778
|
let t = typeof e == "string" && e.trim() !== "" ? Number(e) : e;
|
|
@@ -9753,7 +9808,7 @@ var r$13 = {
|
|
|
9753
9808
|
del: "delete",
|
|
9754
9809
|
return: "enter"
|
|
9755
9810
|
};
|
|
9756
|
-
var i$
|
|
9811
|
+
var i$13 = /* @__PURE__ */ new Set([
|
|
9757
9812
|
"escape",
|
|
9758
9813
|
"enter",
|
|
9759
9814
|
"tab",
|
|
@@ -9786,7 +9841,7 @@ var o$11 = (e, t) => {
|
|
|
9786
9841
|
}
|
|
9787
9842
|
if (u.length !== 1) return { problem: `"${e.trim()}" names ${u.length ? `${u.length} keys (${u.join(", ")})` : "no key, only modifiers"}: a shortcut is modifiers and ONE key, like "shift+f"` };
|
|
9788
9843
|
let [d] = u;
|
|
9789
|
-
return d.length !== 1 && !i$
|
|
9844
|
+
return d.length !== 1 && !i$13.has(d) ? { problem: `"${d}" in "${e.trim()}" is not a key: use one character ("f", "?", "+") or a key's name (${[...i$13].slice(0, 15).join(", ")}, f1…f12)` } : { combo: a$10(l, d) };
|
|
9790
9845
|
};
|
|
9791
9846
|
var s$9 = (e, t = !1) => {
|
|
9792
9847
|
let n = e.split(",").map((e) => o$11(e, t));
|
|
@@ -9839,7 +9894,7 @@ var steps_exports$1 = /* @__PURE__ */ __exportAll({
|
|
|
9839
9894
|
* the builders useless for exactly the flows that matter most.
|
|
9840
9895
|
*/
|
|
9841
9896
|
var builtinTrigger = (trigger) => {
|
|
9842
|
-
if (Object.hasOwn(e$
|
|
9897
|
+
if (Object.hasOwn(e$41, trigger)) return e$41[trigger];
|
|
9843
9898
|
return Object.hasOwn(typeTriggerDefinitions, trigger) ? typeTriggerDefinitions[trigger] : void 0;
|
|
9844
9899
|
};
|
|
9845
9900
|
var on = (trigger, params = {}) => {
|
|
@@ -10004,19 +10059,22 @@ var openModal = (target, metadata) => ({
|
|
|
10004
10059
|
params: metadata === void 0 ? {} : { metadata }
|
|
10005
10060
|
});
|
|
10006
10061
|
/**
|
|
10007
|
-
* Says something on a `channel`, by id: every page on its topic hears it — `onMessage`, and the channel's source.
|
|
10062
|
+
* Says something on a `channel`, by id: every OTHER page on its topic hears it — `onMessage`, and the channel's source.
|
|
10063
|
+
* The page that said it hears it too with `{ echo: true }` — a reaction, a chat line: what the sender shows the moment
|
|
10064
|
+
* it sends — once the server took it, its `from` the channel's `me`.
|
|
10008
10065
|
*
|
|
10009
10066
|
* `data` is what they receive: a template (`'{{ state.draft }}'`) or JSON text. `type` is yours to name — `chat`,
|
|
10010
10067
|
* `wave`, `move` — and a flow on `onMessage` tells them apart with `when({ field: '<step>.type', … })`.
|
|
10011
10068
|
*/
|
|
10012
|
-
var publishOn = (target, type, data = null) => ({
|
|
10069
|
+
var publishOn = (target, type, data = null, { echo = false } = {}) => ({
|
|
10013
10070
|
type: "callback",
|
|
10014
10071
|
action: "publish",
|
|
10015
10072
|
title: "Publish",
|
|
10016
10073
|
on: target,
|
|
10017
10074
|
params: {
|
|
10018
10075
|
type,
|
|
10019
|
-
data: typeof data === "string" ? data : JSON.stringify(data)
|
|
10076
|
+
data: typeof data === "string" ? data : JSON.stringify(data),
|
|
10077
|
+
...echo ? { echo } : {}
|
|
10020
10078
|
}
|
|
10021
10079
|
});
|
|
10022
10080
|
/** Announces this page on a `channel` with presence — a name, a colour: what the other members see of it. */
|
|
@@ -10123,6 +10181,12 @@ var declaredTrigger = (declaration, trigger) => {
|
|
|
10123
10181
|
*/
|
|
10124
10182
|
var declaredCallback = (declaration, callback, target) => {
|
|
10125
10183
|
const declared = declaration.callbacks?.[callback];
|
|
10184
|
+
const stray = Object.keys(target).filter((key) => key !== "on" && key !== "params");
|
|
10185
|
+
if (stray.length > 0) {
|
|
10186
|
+
const named = Object.keys(declared?.params ?? {});
|
|
10187
|
+
const moved = stray.map((key) => `${key}: ${JSON.stringify(Reflect.get(target, key))}`).join(", ");
|
|
10188
|
+
throw new AuthoringError("declared-callback-target", `declaredCallback(…, '${callback}') is given ${stray.map((key) => `"${key}"`).join(", ")} beside \`on\`, where nothing reads it${stray.every((key) => named.includes(key)) ? ` — ${stray.length === 1 ? "it is a param" : "they are params"} of "${callback}"` : ""}: a callback's values go in \`params\` — \`{ on: '${target.on}', params: { ${moved} } }\`.`);
|
|
10189
|
+
}
|
|
10126
10190
|
return {
|
|
10127
10191
|
type: "callback",
|
|
10128
10192
|
action: declared?.action ?? callback,
|
|
@@ -10150,7 +10214,7 @@ var carouselGoTo = (target, index) => carouselStep(target, "goTo", "Go To Slide"
|
|
|
10150
10214
|
var carouselPlay = (target) => carouselStep(target, "play", "Play");
|
|
10151
10215
|
/** The carousel `target` stops moving by itself until it is told to play. */
|
|
10152
10216
|
var carouselPause = (target) => carouselStep(target, "pause", "Pause");
|
|
10153
|
-
var e$
|
|
10217
|
+
var e$22 = {
|
|
10154
10218
|
origin: "Requests to the same site",
|
|
10155
10219
|
all: "All cached requests",
|
|
10156
10220
|
elements: "Only these containers",
|
|
@@ -10162,7 +10226,7 @@ var t$16 = (t, n = () => !0) => ({
|
|
|
10162
10226
|
description: "What to refresh once the write succeeded, so the page shows the new data: the requests to the same site, every provider on the page, only the api containers named in `invalidateElements`, or none for a step that only reads. Server-driven containers are refreshed too, asking the server past its cache. Containers on screen ask again at once; the rest when they are shown.",
|
|
10163
10227
|
default: t[0],
|
|
10164
10228
|
options: [...t],
|
|
10165
|
-
optionLabels: Object.fromEntries(t.map((t) => [t, e$
|
|
10229
|
+
optionLabels: Object.fromEntries(t.map((t) => [t, e$22[t]])),
|
|
10166
10230
|
label: "Refresh cached requests",
|
|
10167
10231
|
canBind: !1,
|
|
10168
10232
|
when: n
|
|
@@ -10242,7 +10306,7 @@ var t$15 = {
|
|
|
10242
10306
|
preview: { cancelled: "" }
|
|
10243
10307
|
}
|
|
10244
10308
|
};
|
|
10245
|
-
var e$
|
|
10309
|
+
var e$21 = {
|
|
10246
10310
|
login: {
|
|
10247
10311
|
source: "auth",
|
|
10248
10312
|
title: "Auth Login",
|
|
@@ -10328,7 +10392,7 @@ var e$20 = {
|
|
|
10328
10392
|
params: {}
|
|
10329
10393
|
}
|
|
10330
10394
|
};
|
|
10331
|
-
var e$
|
|
10395
|
+
var e$20 = { hostAction: {
|
|
10332
10396
|
source: "host",
|
|
10333
10397
|
title: "Host Action",
|
|
10334
10398
|
strictParams: !0,
|
|
@@ -10345,7 +10409,7 @@ var e$19 = { hostAction: {
|
|
|
10345
10409
|
}
|
|
10346
10410
|
}
|
|
10347
10411
|
} };
|
|
10348
|
-
var e$
|
|
10412
|
+
var e$19 = { navigate: {
|
|
10349
10413
|
source: "navigation",
|
|
10350
10414
|
title: "Navigate",
|
|
10351
10415
|
strictParams: !0,
|
|
@@ -10372,7 +10436,7 @@ var e$18 = { navigate: {
|
|
|
10372
10436
|
}
|
|
10373
10437
|
}
|
|
10374
10438
|
} };
|
|
10375
|
-
var e$
|
|
10439
|
+
var e$18 = { invalidateQueries: {
|
|
10376
10440
|
source: "queries",
|
|
10377
10441
|
title: "Invalidate Queries",
|
|
10378
10442
|
strictParams: !0,
|
|
@@ -10605,11 +10669,11 @@ var BUILTIN_GLOBAL_CALLBACKS = {
|
|
|
10605
10669
|
default: ""
|
|
10606
10670
|
} }
|
|
10607
10671
|
},
|
|
10608
|
-
...e$19,
|
|
10609
|
-
...e$18,
|
|
10610
10672
|
...e$20,
|
|
10673
|
+
...e$19,
|
|
10674
|
+
...e$21,
|
|
10611
10675
|
...t$15,
|
|
10612
|
-
...e$
|
|
10676
|
+
...e$18
|
|
10613
10677
|
};
|
|
10614
10678
|
var steps_exports = /* @__PURE__ */ __exportAll({
|
|
10615
10679
|
SET_STATE_TYPES: () => SET_STATE_TYPES,
|
|
@@ -10848,549 +10912,98 @@ var t$14 = (e) => {
|
|
|
10848
10912
|
var t$13 = "[A-Za-z_][A-Za-z0-9_]*";
|
|
10849
10913
|
RegExp(`^${t$13}$`);
|
|
10850
10914
|
RegExp(`^!?${t$13}$`);
|
|
10851
|
-
var e$
|
|
10852
|
-
var e$
|
|
10853
|
-
var i$
|
|
10854
|
-
i$
|
|
10855
|
-
/**
|
|
10856
|
-
|
|
10857
|
-
new Set(
|
|
10858
|
-
|
|
10859
|
-
var
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
|
|
10863
|
-
|
|
10864
|
-
|
|
10865
|
-
|
|
10866
|
-
|
|
10915
|
+
var e$9 = "/data/";
|
|
10916
|
+
var e$7 = (e) => typeof e == "string" && /\{\{[\s\S]*?\}\}|\{%[\s\S]*?%\}/.test(e);
|
|
10917
|
+
var i$5 = (e) => `value|round(0, '${e}')`;
|
|
10918
|
+
i$5("floor"), i$5("ceil");
|
|
10919
|
+
/** Every kebab-case CSS property Plitzi's style engine understands. Values written to a definition must use these
|
|
10920
|
+
* exact keys — camelCase or unknown keys are rejected. */
|
|
10921
|
+
var cssProperties = Array.from(new Set(Object.values(t$30))).sort();
|
|
10922
|
+
var cssPropertySet = new Set(cssProperties);
|
|
10923
|
+
var isCssProperty = (key) => cssPropertySet.has(key);
|
|
10924
|
+
var toKebab = (key) => key.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
10925
|
+
/**
|
|
10926
|
+
* A property as an author may write it, in the spelling the document keeps: kebab-case already, or camelCase the way a
|
|
10927
|
+
* React style object writes it — `paddingTop` is `padding-top`, `WebkitLineClamp` is `-webkit-line-clamp`. A custom
|
|
10928
|
+
* property (`--brand`) is the author's own spelling and is kept.
|
|
10929
|
+
*/
|
|
10930
|
+
var cssPropertyName = (key) => {
|
|
10931
|
+
if (isCustomProperty(key) || !/[A-Z]/.test(key)) return key;
|
|
10932
|
+
return /^(Webkit|Moz|Ms|O)(?=[A-Z])/.exec(key) ? `-${toKebab(key)}` : toKebab(key);
|
|
10867
10933
|
};
|
|
10868
|
-
|
|
10869
|
-
|
|
10870
|
-
|
|
10871
|
-
|
|
10872
|
-
|
|
10873
|
-
"
|
|
10874
|
-
"
|
|
10934
|
+
/**
|
|
10935
|
+
* The properties a bare number is a whole value of — a weight, an opacity, a count, a ratio. Anywhere else a number is
|
|
10936
|
+
* a length, and a length without a unit is no value at all: `gap: 16` is `16px`.
|
|
10937
|
+
*/
|
|
10938
|
+
var UNITLESS = /* @__PURE__ */ new Set([
|
|
10939
|
+
"opacity",
|
|
10940
|
+
"z-index",
|
|
10941
|
+
"font-weight",
|
|
10942
|
+
"line-height",
|
|
10943
|
+
"flex",
|
|
10944
|
+
"flex-grow",
|
|
10945
|
+
"flex-shrink",
|
|
10946
|
+
"order",
|
|
10947
|
+
"column-count",
|
|
10948
|
+
"aspect-ratio",
|
|
10949
|
+
"orphans",
|
|
10950
|
+
"widows",
|
|
10951
|
+
"zoom",
|
|
10875
10952
|
"scale",
|
|
10876
|
-
"
|
|
10877
|
-
"
|
|
10878
|
-
"
|
|
10879
|
-
"
|
|
10880
|
-
"
|
|
10881
|
-
"
|
|
10882
|
-
|
|
10883
|
-
|
|
10884
|
-
"
|
|
10885
|
-
"
|
|
10886
|
-
|
|
10887
|
-
|
|
10888
|
-
var
|
|
10889
|
-
|
|
10890
|
-
|
|
10891
|
-
|
|
10892
|
-
|
|
10893
|
-
"bounce",
|
|
10894
|
-
"wobble",
|
|
10895
|
-
"orbit",
|
|
10896
|
-
"heartbeat",
|
|
10897
|
-
"drift"
|
|
10898
|
-
];
|
|
10899
|
-
var o$6 = {
|
|
10900
|
-
fade: [{
|
|
10901
|
-
at: 0,
|
|
10902
|
-
opacity: 0
|
|
10903
|
-
}],
|
|
10904
|
-
"fade-up": [{
|
|
10905
|
-
at: 0,
|
|
10906
|
-
opacity: 0,
|
|
10907
|
-
translate: "0 24px"
|
|
10908
|
-
}],
|
|
10909
|
-
"fade-down": [{
|
|
10910
|
-
at: 0,
|
|
10911
|
-
opacity: 0,
|
|
10912
|
-
translate: "0 -24px"
|
|
10913
|
-
}],
|
|
10914
|
-
"slide-left": [{
|
|
10915
|
-
at: 0,
|
|
10916
|
-
opacity: 0,
|
|
10917
|
-
translate: "32px 0"
|
|
10918
|
-
}],
|
|
10919
|
-
"slide-right": [{
|
|
10920
|
-
at: 0,
|
|
10921
|
-
opacity: 0,
|
|
10922
|
-
translate: "-32px 0"
|
|
10923
|
-
}],
|
|
10924
|
-
"slide-up": [{
|
|
10925
|
-
at: 0,
|
|
10926
|
-
opacity: 0,
|
|
10927
|
-
translate: "0 72px"
|
|
10928
|
-
}],
|
|
10929
|
-
scale: [{
|
|
10930
|
-
at: 0,
|
|
10931
|
-
opacity: 0,
|
|
10932
|
-
scale: "0.94"
|
|
10933
|
-
}],
|
|
10934
|
-
"zoom-in": [{
|
|
10935
|
-
at: 0,
|
|
10936
|
-
opacity: 0,
|
|
10937
|
-
scale: "0.6"
|
|
10938
|
-
}],
|
|
10939
|
-
"zoom-out": [{
|
|
10940
|
-
at: 0,
|
|
10941
|
-
opacity: 0,
|
|
10942
|
-
scale: "1.25"
|
|
10943
|
-
}],
|
|
10944
|
-
pop: [
|
|
10945
|
-
{
|
|
10946
|
-
at: 0,
|
|
10947
|
-
opacity: 0,
|
|
10948
|
-
scale: "0.5"
|
|
10949
|
-
},
|
|
10950
|
-
{
|
|
10951
|
-
at: 55,
|
|
10952
|
-
opacity: 1,
|
|
10953
|
-
scale: "1.08"
|
|
10954
|
-
},
|
|
10955
|
-
{
|
|
10956
|
-
at: 78,
|
|
10957
|
-
scale: "0.97"
|
|
10958
|
-
}
|
|
10959
|
-
],
|
|
10960
|
-
"bounce-in": [
|
|
10961
|
-
{
|
|
10962
|
-
at: 0,
|
|
10963
|
-
opacity: 0,
|
|
10964
|
-
translate: "0 -64px"
|
|
10965
|
-
},
|
|
10966
|
-
{
|
|
10967
|
-
at: 55,
|
|
10968
|
-
opacity: 1,
|
|
10969
|
-
translate: "0 10px"
|
|
10970
|
-
},
|
|
10971
|
-
{
|
|
10972
|
-
at: 75,
|
|
10973
|
-
translate: "0 -5px"
|
|
10974
|
-
},
|
|
10975
|
-
{
|
|
10976
|
-
at: 90,
|
|
10977
|
-
translate: "0 2px"
|
|
10978
|
-
}
|
|
10979
|
-
],
|
|
10980
|
-
tilt: [{
|
|
10981
|
-
at: 0,
|
|
10982
|
-
opacity: 0,
|
|
10983
|
-
translate: "0 32px",
|
|
10984
|
-
rotate: "-6deg"
|
|
10985
|
-
}],
|
|
10986
|
-
"spin-in": [{
|
|
10987
|
-
at: 0,
|
|
10988
|
-
opacity: 0,
|
|
10989
|
-
scale: "0.4",
|
|
10990
|
-
rotate: "-180deg"
|
|
10991
|
-
}]
|
|
10992
|
-
};
|
|
10993
|
-
Object.fromEntries(t$6.map((e) => {
|
|
10994
|
-
let [{ at: t, ...n }] = o$6[e];
|
|
10995
|
-
return [e, n];
|
|
10996
|
-
}));
|
|
10997
|
-
var c$4 = (e, t) => {
|
|
10998
|
-
let n = t * 2 * Math.PI, r = Math.round(Math.sin(n) * e * 10) / 10, i = Math.round(-Math.cos(n) * e * 10) / 10;
|
|
10999
|
-
return `translate(${String(r)}px, ${String(i)}px)`;
|
|
10953
|
+
"tab-size",
|
|
10954
|
+
"animation-iteration-count",
|
|
10955
|
+
"grid-row-start",
|
|
10956
|
+
"grid-row-end",
|
|
10957
|
+
"grid-column-start",
|
|
10958
|
+
"grid-column-end",
|
|
10959
|
+
"fill-opacity",
|
|
10960
|
+
"stroke-opacity",
|
|
10961
|
+
"stroke-width",
|
|
10962
|
+
"-webkit-line-clamp"
|
|
10963
|
+
]);
|
|
10964
|
+
/** A number written as a value, as CSS reads it: itself where a bare number is a whole value, pixels otherwise. */
|
|
10965
|
+
var cssNumberValue = (property, value) => UNITLESS.has(property) || isCustomProperty(property) || value === 0 ? value : `${String(value)}px`;
|
|
10966
|
+
/** If a camelCase key maps to a known kebab-case property, return it — used to name the correct key in an error. */
|
|
10967
|
+
var suggestCssProperty = (key) => {
|
|
10968
|
+
const kebab = toKebab(key);
|
|
10969
|
+
return cssPropertySet.has(kebab) ? kebab : void 0;
|
|
11000
10970
|
};
|
|
11001
|
-
Array.from({ length: 9 }, (e, t) => ({
|
|
11002
|
-
at: t * 100 / 8,
|
|
11003
|
-
transform: c$4(6, t / 8)
|
|
11004
|
-
}));
|
|
11005
|
-
[
|
|
11006
|
-
"[data-motion-loop] { animation-play-state: running, running !important; }",
|
|
11007
|
-
"[data-motion-on=\"view\"][data-motion-enter], [data-motion-on=\"view\"][data-motion-stagger] > * { animation-play-state: running, running !important; }",
|
|
11008
|
-
"[data-motion-on=\"scroll\"][data-motion-enter], [data-motion-on=\"scroll\"][data-motion-stagger] > * { animation-timeline: auto, auto !important; }"
|
|
11009
|
-
].join("\n");
|
|
11010
|
-
Object.entries(AUTHORING_CODES).filter(([, entry]) => entry.kind === "suggested").map(([code]) => code);
|
|
11011
|
-
var URL_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
|
|
11012
|
-
/** A page target that is really a URL: the one reading of `mailto:`/`https:` a page-mode link can never mean. */
|
|
11013
|
-
var isUrlTarget = (target) => typeof target === "string" && !e$6(target) && URL_SCHEME.test(target);
|
|
11014
|
-
var isRoot = (element) => !element.definition.parentId;
|
|
11015
|
-
var stepsOf$1 = (element) => Object.values(element.definition.interactions ?? {});
|
|
11016
10971
|
/**
|
|
11017
|
-
* A
|
|
11018
|
-
*
|
|
10972
|
+
* A CSS custom property — `--brand`, `--space-4`.
|
|
10973
|
+
*
|
|
10974
|
+
* Not in the vocabulary and deliberately allowed anyway: a custom property is a declaration the browser resolves,
|
|
10975
|
+
* not one the style editor has to offer a control for, and a space that defines its palette in one place and reads
|
|
10976
|
+
* it back with `var(--brand)` is doing the right thing.
|
|
11019
10977
|
*/
|
|
11020
|
-
var
|
|
11021
|
-
|
|
11022
|
-
|
|
11023
|
-
|
|
11024
|
-
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
Reflect.deleteProperty(record, key);
|
|
11029
|
-
report(`Moved ${inners.join(", ")} out of the ${what} "${key}", up to where ${inners.length === 1 ? "it is" : "they are"} read.`, {
|
|
11030
|
-
on,
|
|
11031
|
-
op: "unwrap",
|
|
11032
|
-
key
|
|
11033
|
-
});
|
|
11034
|
-
}
|
|
10978
|
+
var isCustomProperty = (key) => key.startsWith("--");
|
|
10979
|
+
var walkTopLevel = (value, onChar) => {
|
|
10980
|
+
let depth = 0;
|
|
10981
|
+
let quote = "";
|
|
10982
|
+
for (const ch of value) {
|
|
10983
|
+
if (quote) {
|
|
10984
|
+
onChar(ch, false);
|
|
10985
|
+
if (ch === quote) quote = "";
|
|
11035
10986
|
continue;
|
|
11036
10987
|
}
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
11043
|
-
|
|
11044
|
-
|
|
11045
|
-
});
|
|
11046
|
-
} else report(`Removed the ${what} "${key}", which nothing reads.`, {
|
|
11047
|
-
on,
|
|
11048
|
-
op: "remove",
|
|
11049
|
-
key
|
|
11050
|
-
});
|
|
11051
|
-
Reflect.deleteProperty(record, key);
|
|
10988
|
+
if (/["']/.test(ch)) {
|
|
10989
|
+
quote = ch;
|
|
10990
|
+
onChar(ch, false);
|
|
10991
|
+
continue;
|
|
10992
|
+
}
|
|
10993
|
+
if (ch === "(") depth += 1;
|
|
10994
|
+
else if (ch === ")") depth = Math.max(0, depth - 1);
|
|
10995
|
+
onChar(ch, depth === 0);
|
|
11052
10996
|
}
|
|
11053
10997
|
};
|
|
11054
|
-
/**
|
|
11055
|
-
var
|
|
11056
|
-
|
|
11057
|
-
|
|
11058
|
-
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
const { href, mode } = element.attributes;
|
|
11064
|
-
if (element.definition.type === "link" && (mode ?? "page") === "page" && isUrlTarget(href)) {
|
|
11065
|
-
element.attributes.mode = "external";
|
|
11066
|
-
report(`The link to "${href}" now opens it as an external URL.`, {
|
|
11067
|
-
on: "attribute",
|
|
11068
|
-
op: "set",
|
|
11069
|
-
key: "mode",
|
|
11070
|
-
value: "external"
|
|
11071
|
-
});
|
|
11072
|
-
}
|
|
11073
|
-
for (const step of stepsOf$1(element)) if (step.action === "navigate" && step.params.urlType === "page" && isUrlTarget(step.params.url)) {
|
|
11074
|
-
step.params.urlType = "external";
|
|
11075
|
-
report(`Step "${step.id}" now navigates to "${step.params.url}" as an external URL.`, {
|
|
11076
|
-
on: { step: step.id },
|
|
11077
|
-
op: "set",
|
|
11078
|
-
key: "urlType",
|
|
11079
|
-
value: "external"
|
|
11080
|
-
});
|
|
11081
|
-
}
|
|
11082
|
-
},
|
|
11083
|
-
"unknown-attribute": (element, ctx, report) => {
|
|
11084
|
-
const names = ctx.attributeNamesFor(element);
|
|
11085
|
-
if (!isRoot(element) && names) settleUnknownKeys(element.attributes, names, "attribute", "attribute", report, ctx.defaultsFor(element));
|
|
11086
|
-
},
|
|
11087
|
-
"attribute-kind": (element, ctx, report) => {
|
|
11088
|
-
const defaults = ctx.catalogs.defaultAttributes?.[element.definition.type] ?? {};
|
|
11089
|
-
for (const [name, value] of Object.entries(element.attributes)) {
|
|
11090
|
-
const flag = asFlag(value);
|
|
11091
|
-
if (typeof defaults[name] === "boolean" && flag !== void 0) {
|
|
11092
|
-
element.attributes[name] = flag;
|
|
11093
|
-
report(`\`${name}\` is now the boolean ${String(flag)}, not the text "${String(value)}".`, {
|
|
11094
|
-
on: "attribute",
|
|
11095
|
-
op: "set",
|
|
11096
|
-
key: name,
|
|
11097
|
-
value: flag
|
|
11098
|
-
});
|
|
11099
|
-
}
|
|
11100
|
-
}
|
|
11101
|
-
},
|
|
11102
|
-
"step-params": (element, ctx, report) => {
|
|
11103
|
-
for (const step of stepsOf$1(element)) {
|
|
11104
|
-
const spec = stepSpec(ctx.catalogs, step);
|
|
11105
|
-
if (!spec?.params) continue;
|
|
11106
|
-
const params = spec.params;
|
|
11107
|
-
if (spec.strictParams) settleUnknownKeys(step.params, Object.keys(params), `param of step "${step.id}"`, { step: step.id }, report);
|
|
11108
|
-
for (const [key, value] of Object.entries(step.params)) {
|
|
11109
|
-
const flag = asFlag(value);
|
|
11110
|
-
if (Object.hasOwn(params, key) && params[key].type === "boolean" && flag !== void 0) {
|
|
11111
|
-
step.params[key] = flag;
|
|
11112
|
-
report(`Step "${step.id}": \`${key}\` is now the boolean ${String(flag)}.`, {
|
|
11113
|
-
on: { step: step.id },
|
|
11114
|
-
op: "set",
|
|
11115
|
-
key,
|
|
11116
|
-
value: flag
|
|
11117
|
-
});
|
|
11118
|
-
}
|
|
11119
|
-
}
|
|
11120
|
-
}
|
|
11121
|
-
},
|
|
11122
|
-
"global-callback-module": (element, ctx, report) => {
|
|
11123
|
-
for (const step of stepsOf$1(element)) {
|
|
11124
|
-
const declared = step.type === "globalCallback" && ctx.catalogs.vocabulary ? ctx.catalogs.vocabulary.globalCallbacks[step.action] : void 0;
|
|
11125
|
-
if (declared && step.elementId !== declared.source) {
|
|
11126
|
-
step.elementId = declared.source;
|
|
11127
|
-
report(`Step "${step.id}" now runs "${step.action}" on "${declared.source}", the module that registers it.`, {
|
|
11128
|
-
on: { step: step.id },
|
|
11129
|
-
op: "set",
|
|
11130
|
-
key: "on",
|
|
11131
|
-
value: declared.source
|
|
11132
|
-
});
|
|
11133
|
-
}
|
|
11134
|
-
}
|
|
11135
|
-
},
|
|
11136
|
-
"utility-module": (element, ctx, report) => {
|
|
11137
|
-
for (const step of stepsOf$1(element)) {
|
|
11138
|
-
const known = ctx.catalogs.vocabulary ? Object.hasOwn(ctx.catalogs.vocabulary.utilities, step.action) : false;
|
|
11139
|
-
if (step.type === "utility" && known && step.elementId !== null) {
|
|
11140
|
-
step.elementId = null;
|
|
11141
|
-
report(`Step "${step.id}" runs the utility "${step.action}" on no element: a utility takes none.`, {
|
|
11142
|
-
on: { step: step.id },
|
|
11143
|
-
op: "remove",
|
|
11144
|
-
key: "on"
|
|
11145
|
-
});
|
|
11146
|
-
}
|
|
11147
|
-
}
|
|
11148
|
-
},
|
|
11149
|
-
"visibility-as-attribute": (element, _ctx, report) => {
|
|
11150
|
-
const bindings = element.definition.bindings;
|
|
11151
|
-
const moved = bindings?.attributes?.filter((binding) => binding.to === "visibility") ?? [];
|
|
11152
|
-
if (!bindings || moved.length === 0) return;
|
|
11153
|
-
bindings.attributes = bindings.attributes?.filter((binding) => binding.to !== "visibility");
|
|
11154
|
-
bindings.initialState = [...bindings.initialState ?? [], ...moved];
|
|
11155
|
-
report("The visibility binding now sets the visibility, rather than an attribute nothing reads.");
|
|
11156
|
-
},
|
|
11157
|
-
"binding-target-unknown": (element, ctx, report) => {
|
|
11158
|
-
const names = ctx.attributeNamesFor(element);
|
|
11159
|
-
const bindings = element.definition.bindings;
|
|
11160
|
-
if (!names || !bindings?.attributes) return;
|
|
11161
|
-
const reads = (binding) => binding.to === "visibility" || binding.to === "className" || names.includes(binding.to);
|
|
11162
|
-
for (const binding of bindings.attributes.filter((candidate) => !reads(candidate))) report(`Removed the binding onto "${binding.to}", which a "${element.definition.type}" never reads.`, {
|
|
11163
|
-
on: "binding",
|
|
11164
|
-
op: "remove",
|
|
11165
|
-
key: binding.to
|
|
11166
|
-
});
|
|
11167
|
-
bindings.attributes = bindings.attributes.filter(reads);
|
|
11168
|
-
},
|
|
11169
|
-
"unknown-transformer": (element, ctx, report) => {
|
|
11170
|
-
const catalog = ctx.catalogs.transformers;
|
|
11171
|
-
if (!catalog) return;
|
|
11172
|
-
for (const binding of Object.values(element.definition.bindings ?? {}).flat()) for (const transformer of binding.transformers ?? []) {
|
|
11173
|
-
const meant = Object.hasOwn(catalog, transformer.action) ? void 0 : closest$1(transformer.action, Object.keys(catalog));
|
|
11174
|
-
if (meant !== void 0) {
|
|
11175
|
-
report(`The binding of "${binding.to}" now runs "${meant}" (was "${transformer.action}").`, {
|
|
11176
|
-
on: "binding",
|
|
11177
|
-
op: "replace",
|
|
11178
|
-
key: transformer.action,
|
|
11179
|
-
to: meant
|
|
11180
|
-
});
|
|
11181
|
-
transformer.action = meant;
|
|
11182
|
-
}
|
|
11183
|
-
}
|
|
11184
|
-
},
|
|
11185
|
-
"list-items-ignored": (element, _ctx, report) => {
|
|
11186
|
-
const { attributes } = element;
|
|
11187
|
-
const bound = Object.values(element.definition.bindings ?? {}).flat().some((binding) => binding.to === "items");
|
|
11188
|
-
const written = Array.isArray(attributes.items) && attributes.items.length > 0;
|
|
11189
|
-
if (element.definition.type === "list" && attributes.source !== "controlled" && (bound || written)) {
|
|
11190
|
-
attributes.source = "controlled";
|
|
11191
|
-
report("The list now reads its items (`source: controlled`), one row per item.", {
|
|
11192
|
-
on: "attribute",
|
|
11193
|
-
op: "set",
|
|
11194
|
-
key: "source",
|
|
11195
|
-
value: "controlled"
|
|
11196
|
-
});
|
|
11197
|
-
}
|
|
11198
|
-
},
|
|
11199
|
-
"list-row-not-li": (element, ctx, report) => {
|
|
11200
|
-
const { parentId } = element.definition;
|
|
11201
|
-
const list = parentId ? ctx.element(parentId) : void 0;
|
|
11202
|
-
if (list?.definition.type === "list" && list.attributes.source === "controlled" && isPlainContainer(element)) {
|
|
11203
|
-
element.attributes.subType = "li";
|
|
11204
|
-
report("The row is now an `<li>` (`subType: li`), an item of the list it renders in.", {
|
|
11205
|
-
on: "attribute",
|
|
11206
|
-
op: "set",
|
|
11207
|
-
key: "subType",
|
|
11208
|
-
value: "li"
|
|
11209
|
-
});
|
|
11210
|
-
}
|
|
11211
|
-
},
|
|
11212
|
-
"overlay-starts-open": (element, _ctx, report) => {
|
|
11213
|
-
const { type, bindings } = element.definition;
|
|
11214
|
-
const visibilityBound = (bindings?.initialState ?? []).some((binding) => binding.to === "visibility");
|
|
11215
|
-
if ((type === "modalContainer" || type === "dialogContainer") && element.definition.initialState?.visibility !== false && !visibilityBound) {
|
|
11216
|
-
element.definition.initialState = {
|
|
11217
|
-
...element.definition.initialState,
|
|
11218
|
-
visibility: false
|
|
11219
|
-
};
|
|
11220
|
-
report(`The ${type} now starts closed, to be opened from a flow.`, {
|
|
11221
|
-
on: "field",
|
|
11222
|
-
op: "set",
|
|
11223
|
-
key: "visible",
|
|
11224
|
-
value: false
|
|
11225
|
-
});
|
|
11226
|
-
}
|
|
11227
|
-
},
|
|
11228
|
-
"state-key-has-runtime-prefix": (element, _ctx, report) => {
|
|
11229
|
-
for (const step of stepsOf$1(element)) {
|
|
11230
|
-
if (step.type !== "globalCallback" || step.elementId !== "state") continue;
|
|
11231
|
-
for (const param of STATE_PATH_PARAMS[step.action] ?? []) {
|
|
11232
|
-
const value = step.params[param];
|
|
11233
|
-
if (typeof value === "string" && /^(?:runtime\.)?state\./.test(value)) {
|
|
11234
|
-
const next = value.replace(/^(?:runtime\.)?state\./, "");
|
|
11235
|
-
step.params[param] = next;
|
|
11236
|
-
report(`Step "${step.id}": \`${param}\` is now "${next}" (was "${value}").`, {
|
|
11237
|
-
on: { step: step.id },
|
|
11238
|
-
op: "set",
|
|
11239
|
-
key: param,
|
|
11240
|
-
value: next
|
|
11241
|
-
});
|
|
11242
|
-
}
|
|
11243
|
-
}
|
|
11244
|
-
}
|
|
11245
|
-
}
|
|
11246
|
-
}));
|
|
11247
|
-
var e$4 = ".Toastify__toast-container.plitzi-sdk-toasts";
|
|
11248
|
-
var t$4 = [
|
|
11249
|
-
{
|
|
11250
|
-
selector: e$4,
|
|
11251
|
-
fields: {
|
|
11252
|
-
background: ["--toastify-color-light", "--toastify-color-dark"],
|
|
11253
|
-
text: ["--toastify-text-color-light", "--toastify-text-color-dark"],
|
|
11254
|
-
success: ["--toastify-color-success"],
|
|
11255
|
-
danger: ["--toastify-color-error"],
|
|
11256
|
-
warning: ["--toastify-color-warning"],
|
|
11257
|
-
info: ["--toastify-color-info"],
|
|
11258
|
-
radius: ["--toastify-toast-bd-radius"],
|
|
11259
|
-
font: ["--toastify-font-family"],
|
|
11260
|
-
shadow: ["--toastify-toast-shadow"],
|
|
11261
|
-
padding: ["--toastify-toast-padding"],
|
|
11262
|
-
minHeight: ["--toastify-toast-min-height"]
|
|
11263
|
-
}
|
|
11264
|
-
},
|
|
11265
|
-
{
|
|
11266
|
-
selector: `:where(${e$4} .Toastify__toast)`,
|
|
11267
|
-
fields: {
|
|
11268
|
-
fontSize: ["font-size"],
|
|
11269
|
-
fontWeight: ["font-weight"],
|
|
11270
|
-
lineHeight: ["line-height"],
|
|
11271
|
-
border: ["border"]
|
|
11272
|
-
}
|
|
11273
|
-
},
|
|
11274
|
-
{
|
|
11275
|
-
selector: `${e$4} .Toastify__toast-icon`,
|
|
11276
|
-
fields: {
|
|
11277
|
-
iconSize: ["width"],
|
|
11278
|
-
iconGap: ["margin-inline-end"]
|
|
11279
|
-
}
|
|
11280
|
-
},
|
|
11281
|
-
{
|
|
11282
|
-
selector: `${e$4} .Toastify__close-button`,
|
|
11283
|
-
fields: { closeColor: ["color"] }
|
|
11284
|
-
},
|
|
11285
|
-
{
|
|
11286
|
-
selector: `${e$4} .Toastify__close-button:not(:hover, :focus)`,
|
|
11287
|
-
fields: { closeOpacity: ["opacity"] }
|
|
11288
|
-
},
|
|
11289
|
-
{
|
|
11290
|
-
selector: `${e$4} .Toastify__progress-bar--wrp`,
|
|
11291
|
-
fields: { progressHeight: ["height"] }
|
|
11292
|
-
}
|
|
11293
|
-
];
|
|
11294
|
-
var n$4 = t$4.flatMap((e) => Object.keys(e.fields));
|
|
11295
|
-
var r$2$1 = (e) => n$4.includes(e);
|
|
11296
|
-
n$4.filter(r$2$1);
|
|
11297
|
-
var c$2$1 = (e) => e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11298
|
-
t$4.map((e) => {
|
|
11299
|
-
let t = new Map(Object.entries(e.fields).flatMap(([e, t]) => r$2$1(e) ? t.map((t) => [t, e]) : []));
|
|
11300
|
-
return {
|
|
11301
|
-
pattern: RegExp(`(?:^|\\n)${c$2$1(e.selector)}\\s*\\{([^}]*)\\}`, "g"),
|
|
11302
|
-
fieldOf: (e) => t.get(e)
|
|
11303
|
-
};
|
|
11304
|
-
});
|
|
11305
|
-
Object.fromEntries(e$29.map((e) => [e, t$26(e)]));
|
|
11306
|
-
/** Every kebab-case CSS property Plitzi's style engine understands. Values written to a definition must use these
|
|
11307
|
-
* exact keys — camelCase or unknown keys are rejected. */
|
|
11308
|
-
var cssProperties = Array.from(new Set(Object.values(t$30))).sort();
|
|
11309
|
-
var cssPropertySet = new Set(cssProperties);
|
|
11310
|
-
var isCssProperty = (key) => cssPropertySet.has(key);
|
|
11311
|
-
var toKebab = (key) => key.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
11312
|
-
/**
|
|
11313
|
-
* A property as an author may write it, in the spelling the document keeps: kebab-case already, or camelCase the way a
|
|
11314
|
-
* React style object writes it — `paddingTop` is `padding-top`, `WebkitLineClamp` is `-webkit-line-clamp`. A custom
|
|
11315
|
-
* property (`--brand`) is the author's own spelling and is kept.
|
|
11316
|
-
*/
|
|
11317
|
-
var cssPropertyName = (key) => {
|
|
11318
|
-
if (isCustomProperty(key) || !/[A-Z]/.test(key)) return key;
|
|
11319
|
-
return /^(Webkit|Moz|Ms|O)(?=[A-Z])/.exec(key) ? `-${toKebab(key)}` : toKebab(key);
|
|
11320
|
-
};
|
|
11321
|
-
/**
|
|
11322
|
-
* The properties a bare number is a whole value of — a weight, an opacity, a count, a ratio. Anywhere else a number is
|
|
11323
|
-
* a length, and a length without a unit is no value at all: `gap: 16` is `16px`.
|
|
11324
|
-
*/
|
|
11325
|
-
var UNITLESS = /* @__PURE__ */ new Set([
|
|
11326
|
-
"opacity",
|
|
11327
|
-
"z-index",
|
|
11328
|
-
"font-weight",
|
|
11329
|
-
"line-height",
|
|
11330
|
-
"flex",
|
|
11331
|
-
"flex-grow",
|
|
11332
|
-
"flex-shrink",
|
|
11333
|
-
"order",
|
|
11334
|
-
"column-count",
|
|
11335
|
-
"aspect-ratio",
|
|
11336
|
-
"orphans",
|
|
11337
|
-
"widows",
|
|
11338
|
-
"zoom",
|
|
11339
|
-
"scale",
|
|
11340
|
-
"tab-size",
|
|
11341
|
-
"animation-iteration-count",
|
|
11342
|
-
"grid-row-start",
|
|
11343
|
-
"grid-row-end",
|
|
11344
|
-
"grid-column-start",
|
|
11345
|
-
"grid-column-end",
|
|
11346
|
-
"fill-opacity",
|
|
11347
|
-
"stroke-opacity",
|
|
11348
|
-
"stroke-width",
|
|
11349
|
-
"-webkit-line-clamp"
|
|
11350
|
-
]);
|
|
11351
|
-
/** A number written as a value, as CSS reads it: itself where a bare number is a whole value, pixels otherwise. */
|
|
11352
|
-
var cssNumberValue = (property, value) => UNITLESS.has(property) || isCustomProperty(property) || value === 0 ? value : `${String(value)}px`;
|
|
11353
|
-
/** If a camelCase key maps to a known kebab-case property, return it — used to name the correct key in an error. */
|
|
11354
|
-
var suggestCssProperty = (key) => {
|
|
11355
|
-
const kebab = toKebab(key);
|
|
11356
|
-
return cssPropertySet.has(kebab) ? kebab : void 0;
|
|
11357
|
-
};
|
|
11358
|
-
/**
|
|
11359
|
-
* A CSS custom property — `--brand`, `--space-4`.
|
|
11360
|
-
*
|
|
11361
|
-
* Not in the vocabulary and deliberately allowed anyway: a custom property is a declaration the browser resolves,
|
|
11362
|
-
* not one the style editor has to offer a control for, and a space that defines its palette in one place and reads
|
|
11363
|
-
* it back with `var(--brand)` is doing the right thing.
|
|
11364
|
-
*/
|
|
11365
|
-
var isCustomProperty = (key) => key.startsWith("--");
|
|
11366
|
-
var walkTopLevel = (value, onChar) => {
|
|
11367
|
-
let depth = 0;
|
|
11368
|
-
let quote = "";
|
|
11369
|
-
for (const ch of value) {
|
|
11370
|
-
if (quote) {
|
|
11371
|
-
onChar(ch, false);
|
|
11372
|
-
if (ch === quote) quote = "";
|
|
11373
|
-
continue;
|
|
11374
|
-
}
|
|
11375
|
-
if (/["']/.test(ch)) {
|
|
11376
|
-
quote = ch;
|
|
11377
|
-
onChar(ch, false);
|
|
11378
|
-
continue;
|
|
11379
|
-
}
|
|
11380
|
-
if (ch === "(") depth += 1;
|
|
11381
|
-
else if (ch === ")") depth = Math.max(0, depth - 1);
|
|
11382
|
-
onChar(ch, depth === 0);
|
|
11383
|
-
}
|
|
11384
|
-
};
|
|
11385
|
-
/** Split a shorthand value into whitespace-separated tokens, keeping parenthesized and quoted runs whole. */
|
|
11386
|
-
var splitTokens = (value) => {
|
|
11387
|
-
const tokens = [];
|
|
11388
|
-
let current = "";
|
|
11389
|
-
walkTopLevel(value.trim(), (ch, topLevel) => {
|
|
11390
|
-
if (topLevel && /\s/.test(ch)) {
|
|
11391
|
-
if (current) {
|
|
11392
|
-
tokens.push(current);
|
|
11393
|
-
current = "";
|
|
10998
|
+
/** Split a shorthand value into whitespace-separated tokens, keeping parenthesized and quoted runs whole. */
|
|
10999
|
+
var splitTokens = (value) => {
|
|
11000
|
+
const tokens = [];
|
|
11001
|
+
let current = "";
|
|
11002
|
+
walkTopLevel(value.trim(), (ch, topLevel) => {
|
|
11003
|
+
if (topLevel && /\s/.test(ch)) {
|
|
11004
|
+
if (current) {
|
|
11005
|
+
tokens.push(current);
|
|
11006
|
+
current = "";
|
|
11394
11007
|
}
|
|
11395
11008
|
} else current += ch;
|
|
11396
11009
|
});
|
|
@@ -12087,7 +11700,7 @@ var byProperty = (rules) => {
|
|
|
12087
11700
|
return responsive;
|
|
12088
11701
|
};
|
|
12089
11702
|
/** The states a selector can react to — the closed list the style editor offers, read from where it is declared. */
|
|
12090
|
-
var STYLE_STATES = e$
|
|
11703
|
+
var STYLE_STATES = e$26;
|
|
12091
11704
|
var STYLE_STATE_SET = new Set(STYLE_STATES);
|
|
12092
11705
|
var RULE_SET_KEYS = /* @__PURE__ */ new Set([
|
|
12093
11706
|
"css",
|
|
@@ -12151,11 +11764,11 @@ var assertPseudo = (pseudo, part) => {
|
|
|
12151
11764
|
const ruleSets = partRuleSets(part);
|
|
12152
11765
|
for (const rules of ruleSets) for (const [property, value] of Object.entries(rules)) {
|
|
12153
11766
|
if (property === "content") {
|
|
12154
|
-
if (!i$
|
|
11767
|
+
if (!i$17.includes(pseudo)) throw new AuthoringError("style-pseudo-content", `\`content\` on \`::${pseudo}\` draws nothing: only ${i$17.map((name) => `\`::${name}\``).join(", ")} take one.`);
|
|
12155
11768
|
if (!m$4(String(value))) throw new AuthoringError("style-pseudo-content", `\`content: ${String(value)}\` on \`::${pseudo}\` is not text CSS can read, so nothing is drawn. Text goes in quotes inside the string — \`content: '"${String(value).replace(/"/g, "\\\"")}"'\` — and an empty box is \`'""'\`; \`counter()\`, \`attr()\` and \`url()\` are written as they are.`);
|
|
12156
11769
|
continue;
|
|
12157
11770
|
}
|
|
12158
|
-
if (!u$
|
|
11771
|
+
if (!u$8(pseudo, property)) throw new AuthoringError("style-pseudo-property", `\`${property}\` on \`::${pseudo}\` is dropped by every browser — \`::${pseudo}\` honours ${(l$8[pseudo] ?? []).map((name) => `\`${name}\``).join(", ")}. Style the element itself for the rest.`);
|
|
12159
11772
|
}
|
|
12160
11773
|
if (a$14.includes(pseudo) && !ruleSets.some((rules) => Object.hasOwn(rules, "content"))) throw new AuthoringError("style-pseudo-content", `\`::${pseudo}\` has no \`content\`, so the browser draws nothing for it. Give it one — \`content: '""'\` for an empty box — in its rules or in a state's.`);
|
|
12161
11774
|
};
|
|
@@ -12163,7 +11776,7 @@ var toPseudos = (pseudos) => {
|
|
|
12163
11776
|
const parts = /* @__PURE__ */ new Map();
|
|
12164
11777
|
for (const [name, spec] of Object.entries(pseudos ?? {})) {
|
|
12165
11778
|
const bare = name.replace(/^:+/, "");
|
|
12166
|
-
if (!n$19(name)) throw new AuthoringError("style-pseudo-unknown", `Unknown pseudo-element "${name}"${n$19(bare) ? ` — write it without the colons, "${bare}"` : didYouMean(bare, e$
|
|
11779
|
+
if (!n$19(name)) throw new AuthoringError("style-pseudo-unknown", `Unknown pseudo-element "${name}"${n$19(bare) ? ` — write it without the colons, "${bare}"` : didYouMean(bare, e$27)}. A class dresses ${e$27.join(", ")}.`);
|
|
12167
11780
|
const part = partOf(spec);
|
|
12168
11781
|
const rules = {
|
|
12169
11782
|
base: toResponsive(part.css),
|
|
@@ -13759,37 +13372,489 @@ var createTw = ({ colors = {} } = {}) => (classes) => {
|
|
|
13759
13372
|
});
|
|
13760
13373
|
}
|
|
13761
13374
|
}
|
|
13762
|
-
const own = buckets.get("|")?.bucket ?? {};
|
|
13763
|
-
const ownRanges = byRange(own);
|
|
13764
|
-
const rules = { css: responsive(rangesOf(own)) };
|
|
13765
|
-
for (const [key, { target, bucket }] of buckets) {
|
|
13766
|
-
if (key === "|") continue;
|
|
13767
|
-
const css = responsive(rangesOf(bucket, ownRanges));
|
|
13768
|
-
if (target.state) rules.states = {
|
|
13769
|
-
...rules.states,
|
|
13770
|
-
[target.state]: css
|
|
13771
|
-
};
|
|
13772
|
-
else if (target.ancestor) {
|
|
13773
|
-
const ancestors = { ...rules.ancestors };
|
|
13774
|
-
const { name, state } = target.ancestor;
|
|
13775
|
-
const ancestor = ancestors[name] ?? {};
|
|
13776
|
-
ancestors[name] = state ? {
|
|
13777
|
-
...ancestor,
|
|
13778
|
-
states: {
|
|
13779
|
-
...ancestor.states,
|
|
13780
|
-
[state]: css
|
|
13781
|
-
}
|
|
13782
|
-
} : {
|
|
13783
|
-
...ancestor,
|
|
13784
|
-
css
|
|
13785
|
-
};
|
|
13786
|
-
rules.ancestors = ancestors;
|
|
13375
|
+
const own = buckets.get("|")?.bucket ?? {};
|
|
13376
|
+
const ownRanges = byRange(own);
|
|
13377
|
+
const rules = { css: responsive(rangesOf(own)) };
|
|
13378
|
+
for (const [key, { target, bucket }] of buckets) {
|
|
13379
|
+
if (key === "|") continue;
|
|
13380
|
+
const css = responsive(rangesOf(bucket, ownRanges));
|
|
13381
|
+
if (target.state) rules.states = {
|
|
13382
|
+
...rules.states,
|
|
13383
|
+
[target.state]: css
|
|
13384
|
+
};
|
|
13385
|
+
else if (target.ancestor) {
|
|
13386
|
+
const ancestors = { ...rules.ancestors };
|
|
13387
|
+
const { name, state } = target.ancestor;
|
|
13388
|
+
const ancestor = ancestors[name] ?? {};
|
|
13389
|
+
ancestors[name] = state ? {
|
|
13390
|
+
...ancestor,
|
|
13391
|
+
states: {
|
|
13392
|
+
...ancestor.states,
|
|
13393
|
+
[state]: css
|
|
13394
|
+
}
|
|
13395
|
+
} : {
|
|
13396
|
+
...ancestor,
|
|
13397
|
+
css
|
|
13398
|
+
};
|
|
13399
|
+
rules.ancestors = ancestors;
|
|
13400
|
+
}
|
|
13401
|
+
}
|
|
13402
|
+
return rules;
|
|
13403
|
+
};
|
|
13404
|
+
createTw();
|
|
13405
|
+
new Set(Object.entries(g$4.content.defaultStyle.subTypes).filter(([, variant]) => "field" in variant.style).map(([subType]) => subType));
|
|
13406
|
+
/** A container with no tag of its own named: the row `list-row-not-li` makes an `<li>` without asking. */
|
|
13407
|
+
var isPlainContainer = (element) => element.definition.type === "container" && (element.attributes.subType === void 0 || element.attributes.subType === "div");
|
|
13408
|
+
new Set(STEP_TYPES);
|
|
13409
|
+
/** A step's params that name a path under `runtime.state`, by action. */
|
|
13410
|
+
var STATE_PATH_PARAMS = {
|
|
13411
|
+
setState: ["key"],
|
|
13412
|
+
toggleState: ["key"],
|
|
13413
|
+
appendState: ["key"],
|
|
13414
|
+
removeState: ["key"],
|
|
13415
|
+
toggleInState: ["key"],
|
|
13416
|
+
clearState: ["key"],
|
|
13417
|
+
moveState: ["from", "to"]
|
|
13418
|
+
};
|
|
13419
|
+
var t$6 = [
|
|
13420
|
+
"fade",
|
|
13421
|
+
"fade-up",
|
|
13422
|
+
"fade-down",
|
|
13423
|
+
"slide-left",
|
|
13424
|
+
"slide-right",
|
|
13425
|
+
"slide-up",
|
|
13426
|
+
"scale",
|
|
13427
|
+
"zoom-in",
|
|
13428
|
+
"zoom-out",
|
|
13429
|
+
"pop",
|
|
13430
|
+
"bounce-in",
|
|
13431
|
+
"tilt",
|
|
13432
|
+
"spin-in"
|
|
13433
|
+
];
|
|
13434
|
+
var n$6 = [
|
|
13435
|
+
"load",
|
|
13436
|
+
"view",
|
|
13437
|
+
"scroll"
|
|
13438
|
+
];
|
|
13439
|
+
var r$4 = [
|
|
13440
|
+
"float",
|
|
13441
|
+
"pulse",
|
|
13442
|
+
"spin",
|
|
13443
|
+
"sway",
|
|
13444
|
+
"bounce",
|
|
13445
|
+
"wobble",
|
|
13446
|
+
"orbit",
|
|
13447
|
+
"heartbeat",
|
|
13448
|
+
"drift"
|
|
13449
|
+
];
|
|
13450
|
+
var o$6 = {
|
|
13451
|
+
fade: [{
|
|
13452
|
+
at: 0,
|
|
13453
|
+
opacity: 0
|
|
13454
|
+
}],
|
|
13455
|
+
"fade-up": [{
|
|
13456
|
+
at: 0,
|
|
13457
|
+
opacity: 0,
|
|
13458
|
+
translate: "0 24px"
|
|
13459
|
+
}],
|
|
13460
|
+
"fade-down": [{
|
|
13461
|
+
at: 0,
|
|
13462
|
+
opacity: 0,
|
|
13463
|
+
translate: "0 -24px"
|
|
13464
|
+
}],
|
|
13465
|
+
"slide-left": [{
|
|
13466
|
+
at: 0,
|
|
13467
|
+
opacity: 0,
|
|
13468
|
+
translate: "32px 0"
|
|
13469
|
+
}],
|
|
13470
|
+
"slide-right": [{
|
|
13471
|
+
at: 0,
|
|
13472
|
+
opacity: 0,
|
|
13473
|
+
translate: "-32px 0"
|
|
13474
|
+
}],
|
|
13475
|
+
"slide-up": [{
|
|
13476
|
+
at: 0,
|
|
13477
|
+
opacity: 0,
|
|
13478
|
+
translate: "0 72px"
|
|
13479
|
+
}],
|
|
13480
|
+
scale: [{
|
|
13481
|
+
at: 0,
|
|
13482
|
+
opacity: 0,
|
|
13483
|
+
scale: "0.94"
|
|
13484
|
+
}],
|
|
13485
|
+
"zoom-in": [{
|
|
13486
|
+
at: 0,
|
|
13487
|
+
opacity: 0,
|
|
13488
|
+
scale: "0.6"
|
|
13489
|
+
}],
|
|
13490
|
+
"zoom-out": [{
|
|
13491
|
+
at: 0,
|
|
13492
|
+
opacity: 0,
|
|
13493
|
+
scale: "1.25"
|
|
13494
|
+
}],
|
|
13495
|
+
pop: [
|
|
13496
|
+
{
|
|
13497
|
+
at: 0,
|
|
13498
|
+
opacity: 0,
|
|
13499
|
+
scale: "0.5"
|
|
13500
|
+
},
|
|
13501
|
+
{
|
|
13502
|
+
at: 55,
|
|
13503
|
+
opacity: 1,
|
|
13504
|
+
scale: "1.08"
|
|
13505
|
+
},
|
|
13506
|
+
{
|
|
13507
|
+
at: 78,
|
|
13508
|
+
scale: "0.97"
|
|
13509
|
+
}
|
|
13510
|
+
],
|
|
13511
|
+
"bounce-in": [
|
|
13512
|
+
{
|
|
13513
|
+
at: 0,
|
|
13514
|
+
opacity: 0,
|
|
13515
|
+
translate: "0 -64px"
|
|
13516
|
+
},
|
|
13517
|
+
{
|
|
13518
|
+
at: 55,
|
|
13519
|
+
opacity: 1,
|
|
13520
|
+
translate: "0 10px"
|
|
13521
|
+
},
|
|
13522
|
+
{
|
|
13523
|
+
at: 75,
|
|
13524
|
+
translate: "0 -5px"
|
|
13525
|
+
},
|
|
13526
|
+
{
|
|
13527
|
+
at: 90,
|
|
13528
|
+
translate: "0 2px"
|
|
13529
|
+
}
|
|
13530
|
+
],
|
|
13531
|
+
tilt: [{
|
|
13532
|
+
at: 0,
|
|
13533
|
+
opacity: 0,
|
|
13534
|
+
translate: "0 32px",
|
|
13535
|
+
rotate: "-6deg"
|
|
13536
|
+
}],
|
|
13537
|
+
"spin-in": [{
|
|
13538
|
+
at: 0,
|
|
13539
|
+
opacity: 0,
|
|
13540
|
+
scale: "0.4",
|
|
13541
|
+
rotate: "-180deg"
|
|
13542
|
+
}]
|
|
13543
|
+
};
|
|
13544
|
+
Object.fromEntries(t$6.map((e) => {
|
|
13545
|
+
let [{ at: t, ...n }] = o$6[e];
|
|
13546
|
+
return [e, n];
|
|
13547
|
+
}));
|
|
13548
|
+
var c$4 = (e, t) => {
|
|
13549
|
+
let n = t * 2 * Math.PI, r = Math.round(Math.sin(n) * e * 10) / 10, i = Math.round(-Math.cos(n) * e * 10) / 10;
|
|
13550
|
+
return `translate(${String(r)}px, ${String(i)}px)`;
|
|
13551
|
+
};
|
|
13552
|
+
Array.from({ length: 9 }, (e, t) => ({
|
|
13553
|
+
at: t * 100 / 8,
|
|
13554
|
+
transform: c$4(6, t / 8)
|
|
13555
|
+
}));
|
|
13556
|
+
[
|
|
13557
|
+
"[data-motion-loop] { animation-play-state: running, running !important; }",
|
|
13558
|
+
"[data-motion-on=\"view\"][data-motion-enter], [data-motion-on=\"view\"][data-motion-stagger] > * { animation-play-state: running, running !important; }",
|
|
13559
|
+
"[data-motion-on=\"scroll\"][data-motion-enter], [data-motion-on=\"scroll\"][data-motion-stagger] > * { animation-timeline: auto, auto !important; }"
|
|
13560
|
+
].join("\n");
|
|
13561
|
+
Object.entries(AUTHORING_CODES).filter(([, entry]) => entry.kind === "suggested").map(([code]) => code);
|
|
13562
|
+
var URL_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
|
|
13563
|
+
/** A page target that is really a URL: the one reading of `mailto:`/`https:` a page-mode link can never mean. */
|
|
13564
|
+
var isUrlTarget = (target) => typeof target === "string" && !e$7(target) && URL_SCHEME.test(target);
|
|
13565
|
+
var isRoot = (element) => !element.definition.parentId;
|
|
13566
|
+
var stepsOf$1 = (element) => Object.values(element.definition.interactions ?? {});
|
|
13567
|
+
/**
|
|
13568
|
+
* A key the element or step does not take, renamed to the one it was a typo of — when that one is free — or dropped:
|
|
13569
|
+
* it was never read, so dropping it changes nothing on screen.
|
|
13570
|
+
*/
|
|
13571
|
+
var settleUnknownKeys = (record, known, what, on, report, defaults = {}) => {
|
|
13572
|
+
for (const key of Object.keys(record)) {
|
|
13573
|
+
if (known.includes(key)) continue;
|
|
13574
|
+
const wrapped = record[key];
|
|
13575
|
+
if (e$33(wrapped) && Object.keys(wrapped).length > 0 && Object.keys(wrapped).every((inner) => known.includes(inner))) {
|
|
13576
|
+
const inners = Object.keys(wrapped);
|
|
13577
|
+
if (inners.every((inner) => record[inner] === void 0 || record[inner] === defaults[inner])) {
|
|
13578
|
+
Object.assign(record, wrapped);
|
|
13579
|
+
Reflect.deleteProperty(record, key);
|
|
13580
|
+
report(`Moved ${inners.join(", ")} out of the ${what} "${key}", up to where ${inners.length === 1 ? "it is" : "they are"} read.`, {
|
|
13581
|
+
on,
|
|
13582
|
+
op: "unwrap",
|
|
13583
|
+
key
|
|
13584
|
+
});
|
|
13585
|
+
}
|
|
13586
|
+
continue;
|
|
13587
|
+
}
|
|
13588
|
+
const meant = closest$1(key, known);
|
|
13589
|
+
if (meant !== void 0 && record[meant] === void 0) {
|
|
13590
|
+
record[meant] = record[key];
|
|
13591
|
+
report(`Renamed the ${what} "${key}" to "${meant}".`, {
|
|
13592
|
+
on,
|
|
13593
|
+
op: "rename",
|
|
13594
|
+
key,
|
|
13595
|
+
to: meant
|
|
13596
|
+
});
|
|
13597
|
+
} else report(`Removed the ${what} "${key}", which nothing reads.`, {
|
|
13598
|
+
on,
|
|
13599
|
+
op: "remove",
|
|
13600
|
+
key
|
|
13601
|
+
});
|
|
13602
|
+
Reflect.deleteProperty(record, key);
|
|
13603
|
+
}
|
|
13604
|
+
};
|
|
13605
|
+
/** A flag written as the words `'true'`/`'false'`, stored as the boolean it is read as. */
|
|
13606
|
+
var asFlag = (value) => value === "true" ? true : value === "false" ? false : void 0;
|
|
13607
|
+
var stepSpec = (catalogs, step) => {
|
|
13608
|
+
const vocabulary = catalogs.vocabulary;
|
|
13609
|
+
const table = step.type === "globalCallback" ? vocabulary?.globalCallbacks : step.type === "utility" ? vocabulary?.utilities : step.type === "callback" ? vocabulary?.sharedCallbacks : void 0;
|
|
13610
|
+
return table && Object.hasOwn(table, step.action) ? table[step.action] : void 0;
|
|
13611
|
+
};
|
|
13612
|
+
new Set(Object.keys({
|
|
13613
|
+
"page-target-url": (element, _ctx, report) => {
|
|
13614
|
+
const { href, mode } = element.attributes;
|
|
13615
|
+
if (element.definition.type === "link" && (mode ?? "page") === "page" && isUrlTarget(href)) {
|
|
13616
|
+
element.attributes.mode = "external";
|
|
13617
|
+
report(`The link to "${href}" now opens it as an external URL.`, {
|
|
13618
|
+
on: "attribute",
|
|
13619
|
+
op: "set",
|
|
13620
|
+
key: "mode",
|
|
13621
|
+
value: "external"
|
|
13622
|
+
});
|
|
13623
|
+
}
|
|
13624
|
+
for (const step of stepsOf$1(element)) if (step.action === "navigate" && step.params.urlType === "page" && isUrlTarget(step.params.url)) {
|
|
13625
|
+
step.params.urlType = "external";
|
|
13626
|
+
report(`Step "${step.id}" now navigates to "${step.params.url}" as an external URL.`, {
|
|
13627
|
+
on: { step: step.id },
|
|
13628
|
+
op: "set",
|
|
13629
|
+
key: "urlType",
|
|
13630
|
+
value: "external"
|
|
13631
|
+
});
|
|
13632
|
+
}
|
|
13633
|
+
},
|
|
13634
|
+
"unknown-attribute": (element, ctx, report) => {
|
|
13635
|
+
const names = ctx.attributeNamesFor(element);
|
|
13636
|
+
if (!isRoot(element) && names) settleUnknownKeys(element.attributes, names, "attribute", "attribute", report, ctx.defaultsFor(element));
|
|
13637
|
+
},
|
|
13638
|
+
"attribute-kind": (element, ctx, report) => {
|
|
13639
|
+
const defaults = ctx.catalogs.defaultAttributes?.[element.definition.type] ?? {};
|
|
13640
|
+
for (const [name, value] of Object.entries(element.attributes)) {
|
|
13641
|
+
const flag = asFlag(value);
|
|
13642
|
+
if (typeof defaults[name] === "boolean" && flag !== void 0) {
|
|
13643
|
+
element.attributes[name] = flag;
|
|
13644
|
+
report(`\`${name}\` is now the boolean ${String(flag)}, not the text "${String(value)}".`, {
|
|
13645
|
+
on: "attribute",
|
|
13646
|
+
op: "set",
|
|
13647
|
+
key: name,
|
|
13648
|
+
value: flag
|
|
13649
|
+
});
|
|
13650
|
+
}
|
|
13651
|
+
}
|
|
13652
|
+
},
|
|
13653
|
+
"step-params": (element, ctx, report) => {
|
|
13654
|
+
for (const step of stepsOf$1(element)) {
|
|
13655
|
+
const spec = stepSpec(ctx.catalogs, step);
|
|
13656
|
+
if (!spec?.params) continue;
|
|
13657
|
+
const params = spec.params;
|
|
13658
|
+
if (spec.strictParams) settleUnknownKeys(step.params, Object.keys(params), `param of step "${step.id}"`, { step: step.id }, report);
|
|
13659
|
+
for (const [key, value] of Object.entries(step.params)) {
|
|
13660
|
+
const flag = asFlag(value);
|
|
13661
|
+
if (Object.hasOwn(params, key) && params[key].type === "boolean" && flag !== void 0) {
|
|
13662
|
+
step.params[key] = flag;
|
|
13663
|
+
report(`Step "${step.id}": \`${key}\` is now the boolean ${String(flag)}.`, {
|
|
13664
|
+
on: { step: step.id },
|
|
13665
|
+
op: "set",
|
|
13666
|
+
key,
|
|
13667
|
+
value: flag
|
|
13668
|
+
});
|
|
13669
|
+
}
|
|
13670
|
+
}
|
|
13671
|
+
}
|
|
13672
|
+
},
|
|
13673
|
+
"global-callback-module": (element, ctx, report) => {
|
|
13674
|
+
for (const step of stepsOf$1(element)) {
|
|
13675
|
+
const declared = step.type === "globalCallback" && ctx.catalogs.vocabulary ? ctx.catalogs.vocabulary.globalCallbacks[step.action] : void 0;
|
|
13676
|
+
if (declared && step.elementId !== declared.source) {
|
|
13677
|
+
step.elementId = declared.source;
|
|
13678
|
+
report(`Step "${step.id}" now runs "${step.action}" on "${declared.source}", the module that registers it.`, {
|
|
13679
|
+
on: { step: step.id },
|
|
13680
|
+
op: "set",
|
|
13681
|
+
key: "on",
|
|
13682
|
+
value: declared.source
|
|
13683
|
+
});
|
|
13684
|
+
}
|
|
13685
|
+
}
|
|
13686
|
+
},
|
|
13687
|
+
"utility-module": (element, ctx, report) => {
|
|
13688
|
+
for (const step of stepsOf$1(element)) {
|
|
13689
|
+
const known = ctx.catalogs.vocabulary ? Object.hasOwn(ctx.catalogs.vocabulary.utilities, step.action) : false;
|
|
13690
|
+
if (step.type === "utility" && known && step.elementId !== null) {
|
|
13691
|
+
step.elementId = null;
|
|
13692
|
+
report(`Step "${step.id}" runs the utility "${step.action}" on no element: a utility takes none.`, {
|
|
13693
|
+
on: { step: step.id },
|
|
13694
|
+
op: "remove",
|
|
13695
|
+
key: "on"
|
|
13696
|
+
});
|
|
13697
|
+
}
|
|
13698
|
+
}
|
|
13699
|
+
},
|
|
13700
|
+
"visibility-as-attribute": (element, _ctx, report) => {
|
|
13701
|
+
const bindings = element.definition.bindings;
|
|
13702
|
+
const moved = bindings?.attributes?.filter((binding) => binding.to === "visibility") ?? [];
|
|
13703
|
+
if (!bindings || moved.length === 0) return;
|
|
13704
|
+
bindings.attributes = bindings.attributes?.filter((binding) => binding.to !== "visibility");
|
|
13705
|
+
bindings.initialState = [...bindings.initialState ?? [], ...moved];
|
|
13706
|
+
report("The visibility binding now sets the visibility, rather than an attribute nothing reads.");
|
|
13707
|
+
},
|
|
13708
|
+
"binding-target-unknown": (element, ctx, report) => {
|
|
13709
|
+
const names = ctx.attributeNamesFor(element);
|
|
13710
|
+
const bindings = element.definition.bindings;
|
|
13711
|
+
if (!names || !bindings?.attributes) return;
|
|
13712
|
+
const reads = (binding) => binding.to === "visibility" || binding.to === "className" || names.includes(binding.to);
|
|
13713
|
+
for (const binding of bindings.attributes.filter((candidate) => !reads(candidate))) report(`Removed the binding onto "${binding.to}", which a "${element.definition.type}" never reads.`, {
|
|
13714
|
+
on: "binding",
|
|
13715
|
+
op: "remove",
|
|
13716
|
+
key: binding.to
|
|
13717
|
+
});
|
|
13718
|
+
bindings.attributes = bindings.attributes.filter(reads);
|
|
13719
|
+
},
|
|
13720
|
+
"unknown-transformer": (element, ctx, report) => {
|
|
13721
|
+
const catalog = ctx.catalogs.transformers;
|
|
13722
|
+
if (!catalog) return;
|
|
13723
|
+
for (const binding of Object.values(element.definition.bindings ?? {}).flat()) for (const transformer of binding.transformers ?? []) {
|
|
13724
|
+
const meant = Object.hasOwn(catalog, transformer.action) ? void 0 : closest$1(transformer.action, Object.keys(catalog));
|
|
13725
|
+
if (meant !== void 0) {
|
|
13726
|
+
report(`The binding of "${binding.to}" now runs "${meant}" (was "${transformer.action}").`, {
|
|
13727
|
+
on: "binding",
|
|
13728
|
+
op: "replace",
|
|
13729
|
+
key: transformer.action,
|
|
13730
|
+
to: meant
|
|
13731
|
+
});
|
|
13732
|
+
transformer.action = meant;
|
|
13733
|
+
}
|
|
13734
|
+
}
|
|
13735
|
+
},
|
|
13736
|
+
"list-items-ignored": (element, _ctx, report) => {
|
|
13737
|
+
const { attributes } = element;
|
|
13738
|
+
const bound = Object.values(element.definition.bindings ?? {}).flat().some((binding) => binding.to === "items");
|
|
13739
|
+
const written = Array.isArray(attributes.items) && attributes.items.length > 0;
|
|
13740
|
+
if (element.definition.type === "list" && attributes.source !== "controlled" && (bound || written)) {
|
|
13741
|
+
attributes.source = "controlled";
|
|
13742
|
+
report("The list now reads its items (`source: controlled`), one row per item.", {
|
|
13743
|
+
on: "attribute",
|
|
13744
|
+
op: "set",
|
|
13745
|
+
key: "source",
|
|
13746
|
+
value: "controlled"
|
|
13747
|
+
});
|
|
13748
|
+
}
|
|
13749
|
+
},
|
|
13750
|
+
"list-row-not-li": (element, ctx, report) => {
|
|
13751
|
+
const { parentId } = element.definition;
|
|
13752
|
+
const list = parentId ? ctx.element(parentId) : void 0;
|
|
13753
|
+
if (list?.definition.type === "list" && list.attributes.source === "controlled" && isPlainContainer(element)) {
|
|
13754
|
+
element.attributes.subType = "li";
|
|
13755
|
+
report("The row is now an `<li>` (`subType: li`), an item of the list it renders in.", {
|
|
13756
|
+
on: "attribute",
|
|
13757
|
+
op: "set",
|
|
13758
|
+
key: "subType",
|
|
13759
|
+
value: "li"
|
|
13760
|
+
});
|
|
13761
|
+
}
|
|
13762
|
+
},
|
|
13763
|
+
"overlay-starts-open": (element, _ctx, report) => {
|
|
13764
|
+
const { type, bindings } = element.definition;
|
|
13765
|
+
const visibilityBound = (bindings?.initialState ?? []).some((binding) => binding.to === "visibility");
|
|
13766
|
+
if ((type === "modalContainer" || type === "dialogContainer") && element.definition.initialState?.visibility !== false && !visibilityBound) {
|
|
13767
|
+
element.definition.initialState = {
|
|
13768
|
+
...element.definition.initialState,
|
|
13769
|
+
visibility: false
|
|
13770
|
+
};
|
|
13771
|
+
report(`The ${type} now starts closed, to be opened from a flow.`, {
|
|
13772
|
+
on: "field",
|
|
13773
|
+
op: "set",
|
|
13774
|
+
key: "visible",
|
|
13775
|
+
value: false
|
|
13776
|
+
});
|
|
13777
|
+
}
|
|
13778
|
+
},
|
|
13779
|
+
"state-key-has-runtime-prefix": (element, _ctx, report) => {
|
|
13780
|
+
for (const step of stepsOf$1(element)) {
|
|
13781
|
+
if (step.type !== "globalCallback" || step.elementId !== "state") continue;
|
|
13782
|
+
for (const param of STATE_PATH_PARAMS[step.action] ?? []) {
|
|
13783
|
+
const value = step.params[param];
|
|
13784
|
+
if (typeof value === "string" && /^(?:runtime\.)?state\./.test(value)) {
|
|
13785
|
+
const next = value.replace(/^(?:runtime\.)?state\./, "");
|
|
13786
|
+
step.params[param] = next;
|
|
13787
|
+
report(`Step "${step.id}": \`${param}\` is now "${next}" (was "${value}").`, {
|
|
13788
|
+
on: { step: step.id },
|
|
13789
|
+
op: "set",
|
|
13790
|
+
key: param,
|
|
13791
|
+
value: next
|
|
13792
|
+
});
|
|
13793
|
+
}
|
|
13794
|
+
}
|
|
13795
|
+
}
|
|
13796
|
+
}
|
|
13797
|
+
}));
|
|
13798
|
+
var e$4 = ".Toastify__toast-container.plitzi-sdk-toasts";
|
|
13799
|
+
var t$4 = [
|
|
13800
|
+
{
|
|
13801
|
+
selector: e$4,
|
|
13802
|
+
fields: {
|
|
13803
|
+
background: ["--toastify-color-light", "--toastify-color-dark"],
|
|
13804
|
+
text: ["--toastify-text-color-light", "--toastify-text-color-dark"],
|
|
13805
|
+
success: ["--toastify-color-success"],
|
|
13806
|
+
danger: ["--toastify-color-error"],
|
|
13807
|
+
warning: ["--toastify-color-warning"],
|
|
13808
|
+
info: ["--toastify-color-info"],
|
|
13809
|
+
radius: ["--toastify-toast-bd-radius"],
|
|
13810
|
+
font: ["--toastify-font-family"],
|
|
13811
|
+
shadow: ["--toastify-toast-shadow"],
|
|
13812
|
+
padding: ["--toastify-toast-padding"],
|
|
13813
|
+
minHeight: ["--toastify-toast-min-height"]
|
|
13814
|
+
}
|
|
13815
|
+
},
|
|
13816
|
+
{
|
|
13817
|
+
selector: `:where(${e$4} .Toastify__toast)`,
|
|
13818
|
+
fields: {
|
|
13819
|
+
fontSize: ["font-size"],
|
|
13820
|
+
fontWeight: ["font-weight"],
|
|
13821
|
+
lineHeight: ["line-height"],
|
|
13822
|
+
border: ["border"]
|
|
13823
|
+
}
|
|
13824
|
+
},
|
|
13825
|
+
{
|
|
13826
|
+
selector: `${e$4} .Toastify__toast-icon`,
|
|
13827
|
+
fields: {
|
|
13828
|
+
iconSize: ["width"],
|
|
13829
|
+
iconGap: ["margin-inline-end"]
|
|
13787
13830
|
}
|
|
13831
|
+
},
|
|
13832
|
+
{
|
|
13833
|
+
selector: `${e$4} .Toastify__close-button`,
|
|
13834
|
+
fields: { closeColor: ["color"] }
|
|
13835
|
+
},
|
|
13836
|
+
{
|
|
13837
|
+
selector: `${e$4} .Toastify__close-button:not(:hover, :focus)`,
|
|
13838
|
+
fields: { closeOpacity: ["opacity"] }
|
|
13839
|
+
},
|
|
13840
|
+
{
|
|
13841
|
+
selector: `${e$4} .Toastify__progress-bar--wrp`,
|
|
13842
|
+
fields: { progressHeight: ["height"] }
|
|
13788
13843
|
}
|
|
13789
|
-
|
|
13790
|
-
|
|
13791
|
-
|
|
13792
|
-
|
|
13844
|
+
];
|
|
13845
|
+
var n$4 = t$4.flatMap((e) => Object.keys(e.fields));
|
|
13846
|
+
var r$2$1 = (e) => n$4.includes(e);
|
|
13847
|
+
n$4.filter(r$2$1);
|
|
13848
|
+
var c$2$1 = (e) => e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13849
|
+
t$4.map((e) => {
|
|
13850
|
+
let t = new Map(Object.entries(e.fields).flatMap(([e, t]) => r$2$1(e) ? t.map((t) => [t, e]) : []));
|
|
13851
|
+
return {
|
|
13852
|
+
pattern: RegExp(`(?:^|\\n)${c$2$1(e.selector)}\\s*\\{([^}]*)\\}`, "g"),
|
|
13853
|
+
fieldOf: (e) => t.get(e)
|
|
13854
|
+
};
|
|
13855
|
+
});
|
|
13856
|
+
Object.fromEntries(e$30.map((e) => [e, t$26(e)]));
|
|
13857
|
+
[...new Set(STYLE_STATES.filter((state) => state !== "hidden"))].filter((state) => u$7(state) !== `:${state}`);
|
|
13793
13858
|
new Set("break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield let static implements interface package private protected public await element styles".split(" "));
|
|
13794
13859
|
new Set(STYLE_STATES);
|
|
13795
13860
|
new Set([
|
|
@@ -14972,7 +15037,7 @@ var V$1 = (e) => {
|
|
|
14972
15037
|
for (let n of e.filter((e) => x$2.test(e))) t.set(M$1(n), [...t.get(M$1(n)) ?? [], n]);
|
|
14973
15038
|
return [...t].flatMap(([e, t]) => t.slice(1).map((n) => y$1("plugin-type-taken", `${o$1$1}/${n}/`, `${o$1$1}/${t[0]}/ and ${o$1$1}/${n}/ are both the plugin ${e}: the server registers a folder by its name with a small first letter, and keeps one.`, `Put them in one folder, or rename one: git mv ${o$1$1}/${n} ${o$1$1}/<AnotherName>`)));
|
|
14974
15039
|
};
|
|
14975
|
-
var H$1 = (t) => e$
|
|
15040
|
+
var H$1 = (t) => e$33(t.assets) ? Object.values(t.assets).flatMap((t) => e$33(t) && typeof t.src == "string" && typeof t.type == "string" ? [{
|
|
14976
15041
|
src: t.src,
|
|
14977
15042
|
type: t.type,
|
|
14978
15043
|
isMain: t.isMain === !0
|
|
@@ -14986,7 +15051,7 @@ var U$1 = (t, n) => {
|
|
|
14986
15051
|
} catch (e) {
|
|
14987
15052
|
return { problem: y$1("vendor-manifest-invalid", i, `${i} is not JSON (${e instanceof Error ? e.message : String(e)}), so ${n} does not run.`, a) };
|
|
14988
15053
|
}
|
|
14989
|
-
if (!e$
|
|
15054
|
+
if (!e$33(o)) return { problem: y$1("vendor-manifest-invalid", i, `${i} is not a manifest, so ${n} does not run.`, a) };
|
|
14990
15055
|
let s = H$1(o), l = s.find((e) => e.type === "script" && e.isMain) ?? s.find((e) => e.type === "script");
|
|
14991
15056
|
if (!l) return { problem: y$1("vendor-script-missing", i, `${i} names no script to run, so ${n} does not run.`, a) };
|
|
14992
15057
|
if (!C$1(t, path.posix.join(r, l.src), "file")) return { problem: y$1("vendor-script-missing", i, `${i} names ${l.src} as the script to run, and ${r}/${l.src} is not there, so ${n} does not run.`, a) };
|
|
@@ -15110,7 +15175,7 @@ var ce$1 = (e, t) => {
|
|
|
15110
15175
|
var Z$1 = (t) => {
|
|
15111
15176
|
try {
|
|
15112
15177
|
let n = JSON.parse(readFileSync(path.join(t, "package.json"), "utf-8"));
|
|
15113
|
-
return e$
|
|
15178
|
+
return e$33(n) && [n.dependencies, n.devDependencies].some((t) => e$33(t) && "@plitzi/sdk-server" in t);
|
|
15114
15179
|
} catch {
|
|
15115
15180
|
return !1;
|
|
15116
15181
|
}
|
|
@@ -15233,7 +15298,7 @@ var publicData = (folder) => fileReader(folder, "/");
|
|
|
15233
15298
|
* never serves (`dataDir`) — for `authorSpace`'s `serverData`: bindings are held to the file, and a provider reading
|
|
15234
15299
|
* one from the browser is refused.
|
|
15235
15300
|
*/
|
|
15236
|
-
var projectData = (folder) => fileReader(folder, e$
|
|
15301
|
+
var projectData = (folder) => fileReader(folder, e$9);
|
|
15237
15302
|
/**
|
|
15238
15303
|
* The declaration of every plugin under `folder` — `src/plugins/<Name>/declaration.ts`, its default export — for
|
|
15239
15304
|
* `authorSpace`'s `plugins`: what each fires, answers and reads. Found by folder, as the server finds the plugins
|
|
@@ -15252,10 +15317,10 @@ var pluginDeclarations = async (folder) => {
|
|
|
15252
15317
|
}));
|
|
15253
15318
|
};
|
|
15254
15319
|
/** The manifest of a plugin run as it was built, read; nothing when it cannot be — the layout check says why first. */
|
|
15255
|
-
var manifestOf$
|
|
15320
|
+
var manifestOf$2 = (file) => {
|
|
15256
15321
|
try {
|
|
15257
15322
|
const manifest = JSON.parse(readFileSync(file, "utf-8"));
|
|
15258
|
-
return e$
|
|
15323
|
+
return e$33(manifest) ? manifest : {};
|
|
15259
15324
|
} catch {
|
|
15260
15325
|
return {};
|
|
15261
15326
|
}
|
|
@@ -15265,8 +15330,8 @@ var manifestOf$1 = (file) => {
|
|
|
15265
15330
|
* space): each folder's type and every element its manifest provides (`pluginSchema`). None in most projects.
|
|
15266
15331
|
*/
|
|
15267
15332
|
var builtPluginTypes = (folder) => existsSync(folder) ? readdirSync(folder, { withFileTypes: true }).filter((entry) => entry.isDirectory()).sort((a, b) => a.name.localeCompare(b.name)).flatMap((entry) => {
|
|
15268
|
-
const { pluginSchema } = manifestOf$
|
|
15269
|
-
return [entry.name, ...e$
|
|
15333
|
+
const { pluginSchema } = manifestOf$2(path.join(folder, entry.name, d$1));
|
|
15334
|
+
return [entry.name, ...e$33(pluginSchema) ? Object.keys(pluginSchema) : []];
|
|
15270
15335
|
}) : [];
|
|
15271
15336
|
/**
|
|
15272
15337
|
* The stylesheets of the plugins under `folder` — every `.css` in a plugin's folder, at any depth — as their text, for
|
|
@@ -15335,7 +15400,7 @@ var importProjectModule = async (file, root) => {
|
|
|
15335
15400
|
* What the module exports as `space`, taken as a declaration when it has the shape of one. `authorSpace` checks the
|
|
15336
15401
|
* rest of it, field by field, and says what is wrong — so this only has to tell a space from anything else.
|
|
15337
15402
|
*/
|
|
15338
|
-
var isSpaceSpec = (value) => e$
|
|
15403
|
+
var isSpaceSpec = (value) => e$33(value) && typeof value.name === "string" && typeof value.permanentUrl === "string" && Array.isArray(value.pages);
|
|
15339
15404
|
/**
|
|
15340
15405
|
* `projectSpace` of the project at `root`, held to the same checks: for a tool that works on a project from another
|
|
15341
15406
|
* folder — the CLI, run anywhere inside one. A project's own code calls `projectSpace()` or `authorProjectSpace()`.
|
|
@@ -15343,7 +15408,7 @@ var isSpaceSpec = (value) => e$32(value) && typeof value.name === "string" && ty
|
|
|
15343
15408
|
var projectSpaceAt = async (root) => {
|
|
15344
15409
|
const authoring = await projectAuthoringAt(root);
|
|
15345
15410
|
const module = await importProjectModule(l$2(root, a$1, process.argv[1]), root);
|
|
15346
|
-
const space = e$
|
|
15411
|
+
const space = e$33(module) ? module.space : void 0;
|
|
15347
15412
|
if (!isSpaceSpec(space)) throw new ProjectSpaceError(a$1);
|
|
15348
15413
|
return {
|
|
15349
15414
|
space,
|
|
@@ -16294,7 +16359,8 @@ var unifiedDiff = (file, before, after, context = 2) => {
|
|
|
16294
16359
|
* is left to the author, said with the command that would take the registry's.
|
|
16295
16360
|
* - `skills`: `.claude/skills/plitzi-*` from the packages installed, each replaced whole.
|
|
16296
16361
|
* - `renames`: a name a version renamed, still written in the source (`canTemplate`), at its file and line — and with
|
|
16297
|
-
* `--write`, renamed.
|
|
16362
|
+
* `--write`, renamed. With it, what a version changed that the source may count on — a `formControl` written
|
|
16363
|
+
* before fields became optional — at its file and line, for a project last upgraded before: said, never written.
|
|
16298
16364
|
*
|
|
16299
16365
|
* Shown by default; `--write` makes it. What the space is — its pages, plugins, data — is the project's, never named.
|
|
16300
16366
|
*
|
|
@@ -16355,6 +16421,42 @@ var renamesIn = (file, text) => RENAMES.filter((rename) => !rename.from || impor
|
|
|
16355
16421
|
since: rename.since,
|
|
16356
16422
|
what: rename.what
|
|
16357
16423
|
}] : []));
|
|
16424
|
+
/** Before this version a `formControl` was required unless it said `required: false`; from it, optional unless `true`. */
|
|
16425
|
+
var OPTIONAL_FIELDS_SINCE = "0.38.9";
|
|
16426
|
+
/** The text of the call whose `(` is at `open`, up to its `)` — strings skipped, so a `)` inside one closes nothing. */
|
|
16427
|
+
var callArguments = (text, open) => {
|
|
16428
|
+
let depth = 0;
|
|
16429
|
+
let quote;
|
|
16430
|
+
for (let at = open; at < text.length; at++) {
|
|
16431
|
+
const char = text[at];
|
|
16432
|
+
if (quote && char === "\\") {
|
|
16433
|
+
at++;
|
|
16434
|
+
continue;
|
|
16435
|
+
}
|
|
16436
|
+
if (quote) {
|
|
16437
|
+
quote = char === quote ? void 0 : quote;
|
|
16438
|
+
continue;
|
|
16439
|
+
}
|
|
16440
|
+
if (/['"`]/.test(char)) quote = char;
|
|
16441
|
+
else if (char === "(") depth++;
|
|
16442
|
+
else if (char === ")" && --depth === 0) return text.slice(open + 1, at);
|
|
16443
|
+
}
|
|
16444
|
+
return text.slice(open + 1);
|
|
16445
|
+
};
|
|
16446
|
+
/**
|
|
16447
|
+
* A `formControl(…)` that writes no `required`: one that, written before fields became optional, was required, and now
|
|
16448
|
+
* takes an empty answer. Said, never written — whether a field must be answered is the space's to say. Found as written
|
|
16449
|
+
* in the call: one built by a helper of the project's own is the helper's to look at.
|
|
16450
|
+
*/
|
|
16451
|
+
var optionalFieldsIn = (file, text) => [...text.matchAll(/\bformControl\(/g)].flatMap((match) => {
|
|
16452
|
+
const open = match.index + match[0].length - 1;
|
|
16453
|
+
return /\brequired\s*:/.test(callArguments(text, open)) ? [] : [{
|
|
16454
|
+
file,
|
|
16455
|
+
line: text.slice(0, match.index).split("\n").length,
|
|
16456
|
+
since: OPTIONAL_FIELDS_SINCE,
|
|
16457
|
+
what: "a formControl with no `required` is optional now — write `required: true` if it must be answered"
|
|
16458
|
+
}];
|
|
16459
|
+
});
|
|
16358
16460
|
/** The lowest version a range allows, as numbers: `^0.38.2` → [0, 38, 2]. */
|
|
16359
16461
|
var floorOf$1 = (range) => {
|
|
16360
16462
|
const match = /(\d+)\.(\d+)\.(\d+)/.exec(range);
|
|
@@ -16451,8 +16553,20 @@ var readText$1 = async (file) => {
|
|
|
16451
16553
|
return;
|
|
16452
16554
|
}
|
|
16453
16555
|
};
|
|
16556
|
+
var holdsFiles = async (folder) => {
|
|
16557
|
+
try {
|
|
16558
|
+
return (await fs.readdir(folder)).length > 0;
|
|
16559
|
+
} catch {
|
|
16560
|
+
return false;
|
|
16561
|
+
}
|
|
16562
|
+
};
|
|
16454
16563
|
var planFiles = async (root, files, recorded, take) => Promise.all(Object.entries(files).map(async ([file, ours]) => {
|
|
16455
16564
|
const yours = await readText$1(path.join(root, file));
|
|
16565
|
+
if (yours === void 0 && path.basename(file) === ".gitkeep" && await holdsFiles(path.join(root, file, ".."))) return {
|
|
16566
|
+
file,
|
|
16567
|
+
status: "current",
|
|
16568
|
+
ours
|
|
16569
|
+
};
|
|
16456
16570
|
if (yours === void 0) return {
|
|
16457
16571
|
file,
|
|
16458
16572
|
status: "added",
|
|
@@ -16611,6 +16725,10 @@ var reportText$3 = (report, install) => {
|
|
|
16611
16725
|
lines.push(report.renames.length === 0 ? chalk.green("renames: none written") : "renames:");
|
|
16612
16726
|
lines.push(...report.renames.map((found) => chalk.yellow(` ${report.write ? "~" : "!"} ${found.file}:${String(found.line)} ${found.name} → ${found.to} (${found.since}: ${found.what})`)));
|
|
16613
16727
|
}
|
|
16728
|
+
if (report.changes && report.changes.length > 0) {
|
|
16729
|
+
lines.push("changes the source may count on (look, then decide — never written):");
|
|
16730
|
+
lines.push(...report.changes.map((found) => chalk.yellow(` ! ${found.file}:${String(found.line)} (${found.since}) ${found.what}`)));
|
|
16731
|
+
}
|
|
16614
16732
|
return lines.join("\n");
|
|
16615
16733
|
};
|
|
16616
16734
|
var upgrade = async (parts, options) => {
|
|
@@ -16707,8 +16825,11 @@ var upgrade = async (parts, options) => {
|
|
|
16707
16825
|
}
|
|
16708
16826
|
if (wanted.has("renames")) {
|
|
16709
16827
|
const found = [];
|
|
16828
|
+
const changes = [];
|
|
16829
|
+
const before = record === void 0 || isBelow(record.cli, OPTIONAL_FIELDS_SINCE);
|
|
16710
16830
|
for (const file of await sourceFiles(root)) {
|
|
16711
16831
|
const text = await readText$1(path.join(root, file));
|
|
16832
|
+
if (before && text !== void 0) changes.push(...optionalFieldsIn(file, text));
|
|
16712
16833
|
const inFile = text === void 0 ? [] : renamesIn(file, text);
|
|
16713
16834
|
if (write && text !== void 0 && inFile.length > 0) {
|
|
16714
16835
|
const renamed = [...new Set(inFile.map((entry) => entry.name))].reduce((result, name) => result.replace(wordOf(name), RENAMES.find((rename) => rename.name === name)?.to ?? name), text);
|
|
@@ -16717,6 +16838,7 @@ var upgrade = async (parts, options) => {
|
|
|
16717
16838
|
found.push(...inFile);
|
|
16718
16839
|
}
|
|
16719
16840
|
report.renames = found;
|
|
16841
|
+
report.changes = changes;
|
|
16720
16842
|
}
|
|
16721
16843
|
console.log(options.json ? JSON.stringify(report) : reportText$3(report, installCommand(manager)));
|
|
16722
16844
|
if (report.packages?.install === "failed") {
|
|
@@ -18389,15 +18511,32 @@ var checkAccount = async (root, username) => {
|
|
|
18389
18511
|
password
|
|
18390
18512
|
};
|
|
18391
18513
|
};
|
|
18514
|
+
/** Signs the page's browser in as the account, through the server's `/auth` routes: what went wrong, or nothing. */
|
|
18515
|
+
var signInAs = async (page, origin, account) => {
|
|
18516
|
+
const answer = await page.request.post(`${origin}${SIGN_IN_PATH}`, { data: {
|
|
18517
|
+
username: account.username,
|
|
18518
|
+
password: account.password
|
|
18519
|
+
} });
|
|
18520
|
+
if (answer.ok()) return;
|
|
18521
|
+
return answer.status() === 404 ? `nothing answers at ${SIGN_IN_PATH}: --as signs in through the routes createServer({ auth }) mounts there` : `${account.username} was not signed in (${String(answer.status())}): ${(await answer.text()).slice(0, 200)} — check ${CHECK_PASSWORD_ENV} in .env`;
|
|
18522
|
+
};
|
|
18523
|
+
var withoutTrailingSlash = (path) => path.length > 1 ? path.replace(/\/+$/, "") : path;
|
|
18524
|
+
/** Where the page landed, when that is not the path it was opened at — sent to the sign-in, most often. */
|
|
18525
|
+
var sentElsewhere = (page, pathname) => {
|
|
18526
|
+
const landed = new URL(page.url()).pathname;
|
|
18527
|
+
const asked = new URL(pathname, page.url()).pathname;
|
|
18528
|
+
return withoutTrailingSlash(landed) === withoutTrailingSlash(asked) ? void 0 : landed;
|
|
18529
|
+
};
|
|
18392
18530
|
/** The space the project declares, authored. Only for one written here. */
|
|
18393
18531
|
var projectSpace = async (root) => {
|
|
18394
18532
|
const project = await loadProjectSpace(root);
|
|
18395
18533
|
if ("problem" in project) return { problem: `${project.problem} There is nothing to check the page against.` };
|
|
18396
18534
|
try {
|
|
18397
|
-
const { handles, schema } = authorSpace(project.space, project.authoring);
|
|
18535
|
+
const { handles, schema, style } = authorSpace(project.space, project.authoring);
|
|
18398
18536
|
return {
|
|
18399
18537
|
handles,
|
|
18400
|
-
schema
|
|
18538
|
+
schema,
|
|
18539
|
+
schemes: SCHEMES.filter((scheme) => style.theme.schemes.includes(scheme))
|
|
18401
18540
|
};
|
|
18402
18541
|
} catch (error) {
|
|
18403
18542
|
return { problem: `The space does not author — npm run author says why: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}` };
|
|
@@ -18628,7 +18767,7 @@ var momentChanges = (before, after, state) => {
|
|
|
18628
18767
|
...stateChanges
|
|
18629
18768
|
];
|
|
18630
18769
|
};
|
|
18631
|
-
var selectorOf
|
|
18770
|
+
var selectorOf = (authored, id) => authored && Object.hasOwn(authored.handles.elements, id) ? authored.handles.elements[id].selector : `[data-plitzi-el="${id}"]`;
|
|
18632
18771
|
var FIELDS = "input, textarea, select";
|
|
18633
18772
|
/** The elements of the space the fields inside a node belong to: the nearest element around each. */
|
|
18634
18773
|
var fieldOwnersInPage = (node, selector) => Array.from(node.querySelectorAll(selector), (field) => field.closest("[data-plitzi-el]")?.getAttribute("data-plitzi-el")).map((owner) => owner ?? "?");
|
|
@@ -18638,7 +18777,7 @@ var fieldOwnersInPage = (node, selector) => Array.from(node.querySelectorAll(sel
|
|
|
18638
18777
|
* it is another's; or what could not be filled, and why.
|
|
18639
18778
|
*/
|
|
18640
18779
|
var fillField = async (page, authored, { element, value }) => {
|
|
18641
|
-
const node = page.locator(selectorOf
|
|
18780
|
+
const node = page.locator(selectorOf(authored, element)).first();
|
|
18642
18781
|
if (await node.count() === 0) return { problem: `no element ${element} is on this page to fill` };
|
|
18643
18782
|
const own = await node.evaluate((each, selector) => each.matches(selector), FIELDS);
|
|
18644
18783
|
const owners = own ? [element] : await node.evaluate(fieldOwnersInPage, FIELDS);
|
|
@@ -18663,7 +18802,7 @@ var fillField = async (page, authored, { element, value }) => {
|
|
|
18663
18802
|
* nothing is said as such: a button whose flow does nothing looks the same as one that works until somebody clicks.
|
|
18664
18803
|
*/
|
|
18665
18804
|
var clickEffects = async (page, authored, { element: id, fill }) => {
|
|
18666
|
-
const target = page.locator(selectorOf
|
|
18805
|
+
const target = page.locator(selectorOf(authored, id)).first();
|
|
18667
18806
|
if (await target.count() === 0) return {
|
|
18668
18807
|
element: id,
|
|
18669
18808
|
problem: `no element ${id} is on this page`,
|
|
@@ -18792,12 +18931,12 @@ var lateElements = (schema, served, hydrated, width) => {
|
|
|
18792
18931
|
browserOnly
|
|
18793
18932
|
};
|
|
18794
18933
|
};
|
|
18795
|
-
var checkAt = async (browser, origin, pathname, width,
|
|
18934
|
+
var checkAt = async (browser, origin, pathname, width, view, authored, asked, ssr, account, click) => {
|
|
18796
18935
|
const handles = authored?.handles;
|
|
18797
18936
|
const page = await openProjectPage(browser, origin, {
|
|
18798
18937
|
width,
|
|
18799
18938
|
height: 900,
|
|
18800
|
-
...
|
|
18939
|
+
...view
|
|
18801
18940
|
});
|
|
18802
18941
|
/** A report of a page that could not be looked at — nothing answered, no sign-in, sent elsewhere. */
|
|
18803
18942
|
const unchecked = (issue) => ({
|
|
@@ -18813,17 +18952,12 @@ var checkAt = async (browser, origin, pathname, width, scheme, authored, asked,
|
|
|
18813
18952
|
devTools: false,
|
|
18814
18953
|
lists: {}
|
|
18815
18954
|
});
|
|
18816
|
-
|
|
18817
|
-
|
|
18818
|
-
|
|
18819
|
-
|
|
18820
|
-
|
|
18821
|
-
|
|
18822
|
-
code: "not-signed-in",
|
|
18823
|
-
message: signedIn.status() === 404 ? `nothing answers at ${SIGN_IN_PATH}: --as signs in through the routes createServer({ auth }) mounts there` : `${account.username} was not signed in (${String(signedIn.status())}): ${(await signedIn.text()).slice(0, 200)} — check ${CHECK_PASSWORD_ENV} in .env`,
|
|
18824
|
-
width
|
|
18825
|
-
});
|
|
18826
|
-
}
|
|
18955
|
+
const notSignedIn = account && await signInAs(page, origin, account);
|
|
18956
|
+
if (notSignedIn) return unchecked({
|
|
18957
|
+
code: "not-signed-in",
|
|
18958
|
+
message: notSignedIn,
|
|
18959
|
+
width
|
|
18960
|
+
});
|
|
18827
18961
|
const consoleErrors = [];
|
|
18828
18962
|
const failedRequests = [];
|
|
18829
18963
|
page.on("pageerror", (error) => consoleErrors.push(error.message));
|
|
@@ -18857,8 +18991,8 @@ var checkAt = async (browser, origin, pathname, width, scheme, authored, asked,
|
|
|
18857
18991
|
consoleErrors,
|
|
18858
18992
|
failedRequests
|
|
18859
18993
|
};
|
|
18860
|
-
const landed =
|
|
18861
|
-
if (
|
|
18994
|
+
const landed = sentElsewhere(page, pathname);
|
|
18995
|
+
if (landed) return {
|
|
18862
18996
|
...unchecked({
|
|
18863
18997
|
code: "redirected",
|
|
18864
18998
|
message: account ? `${pathname} sent the browser to ${landed}, signed in as ${account.username}: that account may not see it` : `${pathname} sent the browser to ${landed} — what a page for signed-in visitors does: \`plitzi page check ${pathname} --as <username>\` signs in first, the password in ${CHECK_PASSWORD_ENV} in .env`,
|
|
@@ -18986,7 +19120,7 @@ var clickedText = (clicked) => {
|
|
|
18986
19120
|
];
|
|
18987
19121
|
};
|
|
18988
19122
|
var reportText$2 = (report, asked) => {
|
|
18989
|
-
const head = `${report.path} at ${String(report.width)} px`;
|
|
19123
|
+
const head = `${report.path} at ${String(report.width)} px${report.scheme ? `, ${report.scheme}` : ""}`;
|
|
18990
19124
|
const held = [
|
|
18991
19125
|
...report.notFound ? [" · sent with status 404: the page for an address that shows nothing"] : [],
|
|
18992
19126
|
...listsText(report.lists),
|
|
@@ -19008,7 +19142,6 @@ var reportText$2 = (report, asked) => {
|
|
|
19008
19142
|
...held
|
|
19009
19143
|
].join("\n");
|
|
19010
19144
|
};
|
|
19011
|
-
var withoutTrailingSlash = (path) => path.length > 1 ? path.replace(/\/+$/, "") : path;
|
|
19012
19145
|
var check = async (routes, options) => {
|
|
19013
19146
|
const project = await projectHere("whose page to check");
|
|
19014
19147
|
if (!project) return;
|
|
@@ -19034,6 +19167,7 @@ var check = async (routes, options) => {
|
|
|
19034
19167
|
asked,
|
|
19035
19168
|
ssr: Boolean(options.ssr),
|
|
19036
19169
|
...options.scheme ? { scheme: options.scheme } : {},
|
|
19170
|
+
presence: options.presence === true,
|
|
19037
19171
|
...account ? { account } : {},
|
|
19038
19172
|
...options.click ? { click: {
|
|
19039
19173
|
element: options.click,
|
|
@@ -19062,17 +19196,29 @@ var checkRoutes = async (project, routes, options) => {
|
|
|
19062
19196
|
if ("problem" in browser) return browser;
|
|
19063
19197
|
try {
|
|
19064
19198
|
const reports = [];
|
|
19065
|
-
for (const route of routes) for (const width of options.widths)
|
|
19199
|
+
for (const route of routes) for (const width of options.widths) {
|
|
19200
|
+
const report = await checkAt(browser, where.origin, route, width, {
|
|
19201
|
+
...options.scheme ? { scheme: options.scheme } : {},
|
|
19202
|
+
presence: options.presence === true
|
|
19203
|
+
}, authored, options.asked, options.ssr, options.account, options.click);
|
|
19204
|
+
reports.push({
|
|
19205
|
+
...report,
|
|
19206
|
+
...options.scheme ? { scheme: options.scheme } : {}
|
|
19207
|
+
});
|
|
19208
|
+
}
|
|
19066
19209
|
return reports;
|
|
19067
19210
|
} finally {
|
|
19068
19211
|
await browser.close();
|
|
19069
19212
|
}
|
|
19070
19213
|
};
|
|
19071
|
-
/**
|
|
19214
|
+
/** What a whole-project check opens: every page with no parameter in its path, in every theme the space can show. */
|
|
19072
19215
|
var staticPaths = async (root) => {
|
|
19073
19216
|
const authored = await projectSpace(root);
|
|
19074
19217
|
if ("problem" in authored) return authored;
|
|
19075
|
-
return
|
|
19218
|
+
return {
|
|
19219
|
+
paths: Object.values(authored.handles.pages).map((page) => isNotFoundPage(page) ? `${page.path.slice(0, -1)}${NOT_FOUND_PROBE}` : page.path).filter((pathname) => pathname.split("/").every((segment) => !segment.startsWith(":") && !/\{\{.*\}\}/.test(segment))),
|
|
19220
|
+
schemes: authored.schemes
|
|
19221
|
+
};
|
|
19076
19222
|
};
|
|
19077
19223
|
//#endregion
|
|
19078
19224
|
//#region src/commands/functions.ts
|
|
@@ -19297,16 +19443,6 @@ var projectRunner = async (root) => {
|
|
|
19297
19443
|
} catch {}
|
|
19298
19444
|
fail("plitzi functions dev runs them with this project’s own @plitzi/sdk-server, and the isolates it needs:\n npm install --save-dev @plitzi/sdk-server isolated-vm core-js");
|
|
19299
19445
|
};
|
|
19300
|
-
/** `PLITZI_FUNCTIONS_CREDENTIALS`, a JSON object of credential id → its keys: what `ctx.fetch` may name locally. */
|
|
19301
|
-
var localCredentials = () => {
|
|
19302
|
-
const raw = process.env.PLITZI_FUNCTIONS_CREDENTIALS;
|
|
19303
|
-
try {
|
|
19304
|
-
const value = raw ? JSON.parse(raw) : {};
|
|
19305
|
-
return e$3(value) ? Object.fromEntries(Object.entries(value).flatMap(([id, keys]) => e$3(keys) ? [[id, Object.fromEntries(Object.entries(keys).filter((pair) => typeof pair[1] === "string"))]] : [])) : {};
|
|
19306
|
-
} catch {
|
|
19307
|
-
return {};
|
|
19308
|
-
}
|
|
19309
|
-
};
|
|
19310
19446
|
var NO_NODE_SNAPSHOT = "--no-node-snapshot";
|
|
19311
19447
|
/**
|
|
19312
19448
|
* The isolates `dev` runs need Node's startup snapshot off, and a process cannot turn it off once started: `dev` runs
|
|
@@ -19336,10 +19472,7 @@ var devFunction = async (task, options) => {
|
|
|
19336
19472
|
const root = params && await rootOf();
|
|
19337
19473
|
const runner = root ? await projectRunner(root) : void 0;
|
|
19338
19474
|
if (!root || !runner) return;
|
|
19339
|
-
const local = runner.createLocalFunctions({
|
|
19340
|
-
credentials: localCredentials(),
|
|
19341
|
-
dataDir: path.join(root, m)
|
|
19342
|
-
});
|
|
19475
|
+
const local = runner.createLocalFunctions({ dataDir: path.join(root, m) });
|
|
19343
19476
|
const run = async () => {
|
|
19344
19477
|
const loaded = await local.load(await readFunctionsFiles(root));
|
|
19345
19478
|
if (!loaded.ok) {
|
|
@@ -21104,6 +21237,125 @@ var fix = async (options) => {
|
|
|
21104
21237
|
].join("\n"));
|
|
21105
21238
|
};
|
|
21106
21239
|
//#endregion
|
|
21240
|
+
//#region src/commands/functionsAdd.ts
|
|
21241
|
+
/** Where a package added to the functions is kept: their own code from then on, copied in. */
|
|
21242
|
+
var VENDOR_DIR = "vendor";
|
|
21243
|
+
/** What a space's functions may weigh built, whole — a package added is part of it (`@plitzi/sdk-server`'s cap). */
|
|
21244
|
+
var MAX_FUNCTIONS_BYTES = 1e6;
|
|
21245
|
+
/** A package's name, as npm writes one: `ical.js`, `@scope/name`. */
|
|
21246
|
+
var PACKAGE_NAME = /^(@[a-z0-9][\w.-]*\/)?[a-z0-9][\w.-]*$/i;
|
|
21247
|
+
/** Globals of Node a package may read and a runner does not have: said, since a bundle cannot tell if they run. */
|
|
21248
|
+
var NODE_GLOBALS = /\b(process\.(env|nextTick|platform|versions?)|Buffer\.(from|alloc|isBuffer)|__dirname|__filename)\b/;
|
|
21249
|
+
/** The file a package is kept in, under `src/functions/vendor/`: its name, with its scope folded in. */
|
|
21250
|
+
var vendorFileOf = (name) => `${name.replace(/^@/, "").replace("/", "__")}.js`;
|
|
21251
|
+
/** The package's own `package.json`, found from where it resolves: its version and its licence for the header. */
|
|
21252
|
+
var manifestOf$1 = async (entry, name) => {
|
|
21253
|
+
for (let dir = path.dirname(entry); dir !== path.dirname(dir); dir = path.dirname(dir)) try {
|
|
21254
|
+
const parsed = JSON.parse(await fs.readFile(path.join(dir, "package.json"), "utf8"));
|
|
21255
|
+
if (e$3(parsed) && parsed.name === name) return {
|
|
21256
|
+
version: typeof parsed.version === "string" ? parsed.version : "?",
|
|
21257
|
+
license: typeof parsed.license === "string" ? parsed.license : "no licence stated"
|
|
21258
|
+
};
|
|
21259
|
+
} catch {}
|
|
21260
|
+
return {
|
|
21261
|
+
version: "?",
|
|
21262
|
+
license: "no licence stated"
|
|
21263
|
+
};
|
|
21264
|
+
};
|
|
21265
|
+
/**
|
|
21266
|
+
* One package bundled for the functions: web APIs only, as they run — what reaches Node (`fs`, `node:crypto`) does
|
|
21267
|
+
* not resolve on a neutral platform, and is the reason it is refused. With what it exports, for its types.
|
|
21268
|
+
*/
|
|
21269
|
+
var bundle = async (root, name, withDefault) => {
|
|
21270
|
+
try {
|
|
21271
|
+
const result = await build({
|
|
21272
|
+
stdin: {
|
|
21273
|
+
contents: `export * from '${name}';${withDefault ? `\nexport { default } from '${name}';` : ""}`,
|
|
21274
|
+
resolveDir: root,
|
|
21275
|
+
loader: "js"
|
|
21276
|
+
},
|
|
21277
|
+
bundle: true,
|
|
21278
|
+
write: false,
|
|
21279
|
+
metafile: true,
|
|
21280
|
+
format: "esm",
|
|
21281
|
+
platform: "neutral",
|
|
21282
|
+
mainFields: ["module", "main"],
|
|
21283
|
+
target: "es2022",
|
|
21284
|
+
minify: true,
|
|
21285
|
+
legalComments: "inline",
|
|
21286
|
+
logLevel: "silent"
|
|
21287
|
+
});
|
|
21288
|
+
const exports = Object.values(result.metafile.outputs).flatMap((output) => output.exports);
|
|
21289
|
+
return {
|
|
21290
|
+
code: result.outputFiles.map((output) => output.text).join(""),
|
|
21291
|
+
exports
|
|
21292
|
+
};
|
|
21293
|
+
} catch (error) {
|
|
21294
|
+
return { errors: e$3(error) && Array.isArray(error.errors) ? error.errors.flatMap((entry) => e$3(entry) && typeof entry.text === "string" ? [{ text: entry.text }] : []) : [{ text: error instanceof Error ? error.message : String(error) }] };
|
|
21295
|
+
}
|
|
21296
|
+
};
|
|
21297
|
+
/** Why esbuild could not bundle it, in the words that say what to do: a Node module is a package that cannot run here. */
|
|
21298
|
+
var refusalOf$1 = (name, errors) => {
|
|
21299
|
+
const node = errors.map((entry) => /Could not resolve "([^"]+)"/.exec(entry.text)?.[1]).find((module) => module !== void 0 && !module.startsWith("."));
|
|
21300
|
+
return node ? `${name} reaches "${node}", which the functions do not have: they run with web APIs only — fetch, crypto.subtle, URL — on any runner, so a package that needs Node cannot run there. Look for one written for the browser or the edge.` : `${name} could not be bundled: ${errors.map((entry) => entry.text).join("; ")}`;
|
|
21301
|
+
};
|
|
21302
|
+
/**
|
|
21303
|
+
* `plitzi functions add <package>`: a package the functions use, as a function carries its dependencies — bundled into
|
|
21304
|
+
* `src/functions/vendor/`, and from then on their own code: pushed and built with the rest, read by the builder, run by
|
|
21305
|
+
* the runner. Nothing is resolved anywhere else, so a space's functions stay its own files. Installed first, with the
|
|
21306
|
+
* project's package manager, so its version is the project's choice and its types reach the editor.
|
|
21307
|
+
*/
|
|
21308
|
+
var addFunctionsPackage = async (name, options) => {
|
|
21309
|
+
if (!PACKAGE_NAME.test(name)) {
|
|
21310
|
+
fail(`"${name}" is not a package's name — ical.js, @scope/name.`);
|
|
21311
|
+
return;
|
|
21312
|
+
}
|
|
21313
|
+
const root = (await projectHere("whose functions these are"))?.root;
|
|
21314
|
+
if (!root) return;
|
|
21315
|
+
let entry;
|
|
21316
|
+
try {
|
|
21317
|
+
entry = createRequire(path.join(root, "package.json")).resolve(name);
|
|
21318
|
+
} catch {
|
|
21319
|
+
try {
|
|
21320
|
+
entry = createRequire(path.join(root, "package.json")).resolve(`${name}/package.json`);
|
|
21321
|
+
} catch {
|
|
21322
|
+
fail(`${name} is not installed in this project: install it first (npm install --save-dev ${name}), then add it.`);
|
|
21323
|
+
return;
|
|
21324
|
+
}
|
|
21325
|
+
}
|
|
21326
|
+
let built = await bundle(root, name, true);
|
|
21327
|
+
if ("errors" in built && built.errors.some((entry) => /No matching export .*"default"/.test(entry.text))) built = await bundle(root, name, false);
|
|
21328
|
+
if ("errors" in built) {
|
|
21329
|
+
fail(refusalOf$1(name, built.errors));
|
|
21330
|
+
return;
|
|
21331
|
+
}
|
|
21332
|
+
const bytes = Buffer.byteLength(built.code);
|
|
21333
|
+
if (bytes > MAX_FUNCTIONS_BYTES) {
|
|
21334
|
+
fail(`${name} is ${String(Math.round(bytes / 1024))} KB bundled, and a space's functions are at most ${String(MAX_FUNCTIONS_BYTES / 1e3)} KB built, all of it: look for a smaller one, or import less of it.`);
|
|
21335
|
+
return;
|
|
21336
|
+
}
|
|
21337
|
+
const { version, license } = await manifestOf$1(entry, name);
|
|
21338
|
+
const file = vendorFileOf(name);
|
|
21339
|
+
const relative = `./${VENDOR_DIR}/${file}`;
|
|
21340
|
+
const header = `// ${name}@${version} — ${license}. Added by \`plitzi functions add ${name}\`: the package bundled for the functions\n// (web APIs only), imported as '${relative}'. Not to be edited: run it again to update it.\n`;
|
|
21341
|
+
const types = `// The types of ${name}@${version}, for '${relative}' — the installed package's own.\n${built.exports.filter((exported) => exported !== "default").length > 0 ? `export * from '${name}';\n` : ""}${built.exports.includes("default") ? `export { default } from '${name}';\n` : ""}`;
|
|
21342
|
+
const written = {
|
|
21343
|
+
[path.join(VENDOR_DIR, file)]: `${header}${built.code}`,
|
|
21344
|
+
[path.join(VENDOR_DIR, file.replace(/\.js$/, ".d.ts"))]: types
|
|
21345
|
+
};
|
|
21346
|
+
const base = path.join(root, h$1);
|
|
21347
|
+
if (options.dryRun) {
|
|
21348
|
+
sayDryRun(`plitzi functions add ${name}`, [...(await filesWouldWrite(base, Object.keys(written))).map((line) => line.replace(/^(.) /, `$1 ${h$1}/`))]);
|
|
21349
|
+
return;
|
|
21350
|
+
}
|
|
21351
|
+
for (const [target, text] of Object.entries(written)) {
|
|
21352
|
+
await fs.mkdir(path.dirname(path.join(base, target)), { recursive: true });
|
|
21353
|
+
await fs.writeFile(path.join(base, target), text);
|
|
21354
|
+
}
|
|
21355
|
+
console.log(`Added ${name}@${version} (${String(Math.round(bytes / 1024))} KB) as ${h$1}/${VENDOR_DIR}/${file}: import it from a file of ${h$1}/ with '${relative}' — \`functions push\` saves it with the rest.`);
|
|
21356
|
+
if (NODE_GLOBALS.test(built.code)) console.warn(`${name} reads globals of Node (process, Buffer, __dirname) somewhere: the functions have none, so whatever reads them fails when it runs. Try what you use with \`plitzi functions dev\`.`);
|
|
21357
|
+
};
|
|
21358
|
+
//#endregion
|
|
21107
21359
|
//#region src/commands/siteOwnership.ts
|
|
21108
21360
|
var NOT_ASKED = (host) => `${host} is not served from this machine, so importing it takes proof that it is yours: its domain verified on one of your Plitzi spaces. That is asked of your Plitzi account, signing in — run it again with --account to ask. A site that is not yours is not imported.`;
|
|
21109
21361
|
var LOOPBACK = /^(127\.|::1$|::ffff:127\.)/;
|
|
@@ -21186,12 +21438,12 @@ var measure = async (browser, url, width, scheme, read = []) => {
|
|
|
21186
21438
|
screen: await page.screenshot({ fullPage: true })
|
|
21187
21439
|
};
|
|
21188
21440
|
};
|
|
21189
|
-
var count$
|
|
21441
|
+
var count$3 = (amount, one, many = `${one}s`) => `${String(amount)} ${amount === 1 ? one : many}`;
|
|
21190
21442
|
var summaryText = (summary, out, stale) => [
|
|
21191
21443
|
chalk.green(`Imported ${summary.url} into ${out}`),
|
|
21192
|
-
` tokens ${count$
|
|
21193
|
-
` outline ${count$
|
|
21194
|
-
...summary.lists.length > 0 ? [` lists ${summary.lists.map((list) => `${list.file} (${count$
|
|
21444
|
+
` tokens ${count$3(summary.colours, "colour")} (${summary.dark ? "light and dark" : "no dark scheme: dark repeats light"}), ${count$3(summary.shadows, "shadow")}, ${count$3(summary.radii, "radius", "radii")}${summary.fonts.length > 0 ? `, fonts ${summary.fonts.join(", ")}` : ""}`,
|
|
21445
|
+
` outline ${count$3(summary.blocks, "block")} at ${summary.widths.join(", ")} px`,
|
|
21446
|
+
...summary.lists.length > 0 ? [` lists ${summary.lists.map((list) => `${list.file} (${count$3(list.rows, "row")})`).join(", ")}`] : [],
|
|
21195
21447
|
` pictures ${String(summary.pictures)} in assets.json`,
|
|
21196
21448
|
...stale.length > 0 ? [chalk.yellow(` earlier ${stale.join(", ")} ${stale.length === 1 ? "was" : "were"} there before and not written this time: delete what is stale`)] : [],
|
|
21197
21449
|
` next ${path.join(out, "IMPORT.md")} says what was not carried over`
|
|
@@ -22409,7 +22661,7 @@ var projectConnectors = async (root) => {
|
|
|
22409
22661
|
manifest: value.manifest
|
|
22410
22662
|
}] : []);
|
|
22411
22663
|
};
|
|
22412
|
-
var count$
|
|
22664
|
+
var count$2 = (entries, noun) => entries ? `${String(entries.length)} ${noun}${entries.length === 1 ? "" : "s"}` : `the space’s ${noun}s as they are`;
|
|
22413
22665
|
/**
|
|
22414
22666
|
* What of the space would not reach Plitzi with it, said before it is sent — never left to be found on a page that
|
|
22415
22667
|
* renders empty there:
|
|
@@ -22494,7 +22746,7 @@ var pushSpaceOf = async (root, connection, space, { base, force, downloads }) =>
|
|
|
22494
22746
|
outcome: "unchanged",
|
|
22495
22747
|
draft: data.draft
|
|
22496
22748
|
};
|
|
22497
|
-
console.log(chalk.green(`The space is ${space.name}’s draft now — its pages and styles, ${count$
|
|
22749
|
+
console.log(chalk.green(`The space is ${space.name}’s draft now — its pages and styles, ${count$2(sent.actions, "action")}, ${count$2(sent.connectors, "connector")}.`) + chalk.dim(" Any builder open on it shows it now."));
|
|
22498
22750
|
return {
|
|
22499
22751
|
outcome: "pushed",
|
|
22500
22752
|
draft: data.draft
|
|
@@ -23522,7 +23774,108 @@ var _ = `[data-motion-enter], [data-motion-stagger] > *, [data-motion-loop] { an
|
|
|
23522
23774
|
"[data-motion-on=\"scroll\"][data-motion-enter], [data-motion-on=\"scroll\"][data-motion-stagger] > * { animation-timeline: auto, auto !important; }"
|
|
23523
23775
|
].join("\n");
|
|
23524
23776
|
//#endregion
|
|
23777
|
+
//#region src/commands/shotSteps.ts
|
|
23778
|
+
var STEP_NAMES = [
|
|
23779
|
+
"click",
|
|
23780
|
+
"type",
|
|
23781
|
+
"press",
|
|
23782
|
+
"wait",
|
|
23783
|
+
"wait-for",
|
|
23784
|
+
"shot",
|
|
23785
|
+
"frames"
|
|
23786
|
+
];
|
|
23787
|
+
/** The longest a script may wait in one step: a page that needs more is waiting for something else. */
|
|
23788
|
+
var MAX_WAIT_MS = 3e4;
|
|
23789
|
+
var unquoted = (text) => text.replace(/^(["'])(.*)\1$/s, "$2");
|
|
23790
|
+
var count$1 = (value, at, max) => {
|
|
23791
|
+
const parsed = Number(value);
|
|
23792
|
+
return Number.isInteger(parsed) && parsed > 0 && parsed <= max ? parsed : { problem: `${at}: "${value ?? ""}" is not a whole number from 1 to ${String(max)}` };
|
|
23793
|
+
};
|
|
23794
|
+
/** A script, read into its steps — or what is wrong with it, said by its step. */
|
|
23795
|
+
var parseSteps = (script, every) => {
|
|
23796
|
+
const lines = script.split(/[;\n]/).map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#"));
|
|
23797
|
+
if (lines.length === 0) return { problem: "--steps has no step: click, type, press, wait, wait-for, shot or frames, separated by \";\"" };
|
|
23798
|
+
const steps = [];
|
|
23799
|
+
for (const [index, line] of lines.entries()) {
|
|
23800
|
+
const at = `step ${String(index + 1)} ("${line}")`;
|
|
23801
|
+
const [name, ...rest] = line.split(/\s+/);
|
|
23802
|
+
const argument = unquoted(rest.join(" "));
|
|
23803
|
+
switch (name) {
|
|
23804
|
+
case "click":
|
|
23805
|
+
case "wait-for":
|
|
23806
|
+
if (!argument) return { problem: `${at}: ${name} needs an element — its name or a CSS selector` };
|
|
23807
|
+
steps.push({
|
|
23808
|
+
kind: name,
|
|
23809
|
+
target: argument
|
|
23810
|
+
});
|
|
23811
|
+
break;
|
|
23812
|
+
case "type": {
|
|
23813
|
+
const quoted = /^(["'])(.+?)\1\s+(.+)$/s.exec(rest.join(" "));
|
|
23814
|
+
const [target, text] = quoted ? [quoted[2], quoted[3]] : [rest[0], rest.slice(1).join(" ")];
|
|
23815
|
+
if (!target || text === "") return { problem: `${at}: type needs an element and the text — type <element> <text>, type ".panel textarea" hi` };
|
|
23816
|
+
steps.push({
|
|
23817
|
+
kind: "type",
|
|
23818
|
+
target,
|
|
23819
|
+
text: unquoted(text)
|
|
23820
|
+
});
|
|
23821
|
+
break;
|
|
23822
|
+
}
|
|
23823
|
+
case "press":
|
|
23824
|
+
if (!argument) return { problem: `${at}: press needs a key — Enter, Escape, ArrowDown…` };
|
|
23825
|
+
steps.push({
|
|
23826
|
+
kind: "press",
|
|
23827
|
+
key: argument
|
|
23828
|
+
});
|
|
23829
|
+
break;
|
|
23830
|
+
case "wait": {
|
|
23831
|
+
const ms = count$1(rest[0], at, MAX_WAIT_MS);
|
|
23832
|
+
if (typeof ms !== "number") return ms;
|
|
23833
|
+
steps.push({
|
|
23834
|
+
kind: "wait",
|
|
23835
|
+
ms
|
|
23836
|
+
});
|
|
23837
|
+
break;
|
|
23838
|
+
}
|
|
23839
|
+
case "shot":
|
|
23840
|
+
steps.push({
|
|
23841
|
+
kind: "shot",
|
|
23842
|
+
...argument ? { label: argument } : {}
|
|
23843
|
+
});
|
|
23844
|
+
break;
|
|
23845
|
+
case "frames": {
|
|
23846
|
+
const frames = count$1(rest[0], at, 60);
|
|
23847
|
+
if (typeof frames !== "number") return frames;
|
|
23848
|
+
const apart = rest.length < 2 ? every : count$1(rest[1], at, MAX_WAIT_MS);
|
|
23849
|
+
if (typeof apart !== "number") return apart;
|
|
23850
|
+
steps.push({
|
|
23851
|
+
kind: "frames",
|
|
23852
|
+
count: frames,
|
|
23853
|
+
every: apart
|
|
23854
|
+
});
|
|
23855
|
+
break;
|
|
23856
|
+
}
|
|
23857
|
+
default: return { problem: `${at}: "${name}" is not a step — the steps are ${STEP_NAMES.join(", ")}` };
|
|
23858
|
+
}
|
|
23859
|
+
}
|
|
23860
|
+
return steps;
|
|
23861
|
+
};
|
|
23862
|
+
//#endregion
|
|
23525
23863
|
//#region src/commands/shot.ts
|
|
23864
|
+
/**
|
|
23865
|
+
* `plitzi page shot`: a picture of one page of the project — and, asked, the numbers that say what a picture would.
|
|
23866
|
+
*
|
|
23867
|
+
* plitzi page shot /about --width 390 --scheme dark
|
|
23868
|
+
* plitzi page shot / --compare https://example.com --width 1440 # beside another site: what differs, and how
|
|
23869
|
+
* plitzi page shot / --frames 4 --every 500 # what moves: a marquee, an autoplay
|
|
23870
|
+
* plitzi page shot / --clip pricing-table # one element, scrolled to wherever it is
|
|
23871
|
+
* plitzi page shot / --scroll-to faq --viewport --frames 6 # the screen at that section, as it animates
|
|
23872
|
+
*
|
|
23873
|
+
* The project's server has to be running (`npm start`). `--json` answers in one object, for a tool or an agent. The
|
|
23874
|
+
* dev tools' badge is never in the picture; a picture of the whole page has every lazy image loaded and shows every
|
|
23875
|
+
* arrival that waits for the scroll as it ends — taken without scrolling, they would be holes where the sections are.
|
|
23876
|
+
*/
|
|
23877
|
+
/** When a run's first picture is taken: once the page settles, or as soon as its HTML is in. */
|
|
23878
|
+
var SHOT_MOMENTS = ["settled", "load"];
|
|
23526
23879
|
/** A region moves when more than this share of it changed between two frames: below is anti-aliasing and carets. */
|
|
23527
23880
|
var MOVING_PERCENT = .5;
|
|
23528
23881
|
/** How long a whole page waits for its pictures before it is taken anyway. */
|
|
@@ -23533,12 +23886,42 @@ var TEXTS_SHOWN = 12;
|
|
|
23533
23886
|
var DRIFT_PX = 2;
|
|
23534
23887
|
/** An arrival that waits for the scroll and has not had it: one waiting to be seen, or one tied to the scroll. */
|
|
23535
23888
|
var WAITING_FOR_SCROLL = "[data-motion-on=\"view\"]:not([data-motion-seen]), [data-motion-on=\"scroll\"]";
|
|
23536
|
-
|
|
23537
|
-
|
|
23538
|
-
var
|
|
23539
|
-
|
|
23889
|
+
var BARE = /^[\w-]+$/;
|
|
23890
|
+
/** A bare word: an element's name — letters, digits, `-` and `_`, as an id is written — or else a tag (`textarea`). */
|
|
23891
|
+
var namedBy = (target) => `[data-plitzi-el="${target}"]`;
|
|
23892
|
+
/** What a wait waits for: an element by name or, a bare word naming none, a tag — whichever shows first. */
|
|
23893
|
+
var awaited = (target) => BARE.test(target) ? `${namedBy(target)}, ${target}` : target;
|
|
23894
|
+
/**
|
|
23895
|
+
* A target found on the page: an element's name, a tag no element is named by (`textarea`), or a selector — CSS or
|
|
23896
|
+
* Playwright's own (`button:has-text("Orbit")`, `text=Saved`, `role=button[name="Publish"]`). With how many it finds
|
|
23897
|
+
* (none is one not on the page), or why it is no selector at all: Playwright throws on one it cannot read, and an
|
|
23898
|
+
* uncaught throw ended the command with a stack trace.
|
|
23899
|
+
*/
|
|
23900
|
+
var targetOn = async (page, target) => {
|
|
23901
|
+
try {
|
|
23902
|
+
if (!BARE.test(target)) return {
|
|
23903
|
+
selector: target,
|
|
23904
|
+
found: await page.locator(target).first().count() > 0
|
|
23905
|
+
};
|
|
23906
|
+
if (await page.locator(namedBy(target)).first().count() > 0) return {
|
|
23907
|
+
selector: namedBy(target),
|
|
23908
|
+
found: true
|
|
23909
|
+
};
|
|
23910
|
+
return await page.locator(target).first().count() > 0 ? {
|
|
23911
|
+
selector: target,
|
|
23912
|
+
found: true
|
|
23913
|
+
} : {
|
|
23914
|
+
selector: namedBy(target),
|
|
23915
|
+
found: false
|
|
23916
|
+
};
|
|
23917
|
+
} catch (error) {
|
|
23918
|
+
return { problem: `${target} is neither an element's name nor a selector the page can read: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}` };
|
|
23919
|
+
}
|
|
23920
|
+
};
|
|
23921
|
+
var framing = (view, clip) => {
|
|
23922
|
+
if (clip) return {
|
|
23540
23923
|
kind: "element",
|
|
23541
|
-
selector:
|
|
23924
|
+
selector: clip
|
|
23542
23925
|
};
|
|
23543
23926
|
return view.viewport || view.scrollTo ? { kind: "viewport" } : { kind: "page" };
|
|
23544
23927
|
};
|
|
@@ -23559,24 +23942,45 @@ var pictureOf = async (browser, url, view, origin) => {
|
|
|
23559
23942
|
colorScheme: view.scheme ?? "light",
|
|
23560
23943
|
reducedMotion: view.reducedMotion ? "reduce" : "no-preference"
|
|
23561
23944
|
});
|
|
23562
|
-
|
|
23563
|
-
if (
|
|
23564
|
-
|
|
23945
|
+
const notSignedIn = origin && view.account && await signInAs(page, origin, view.account);
|
|
23946
|
+
if (notSignedIn) return { problem: `--as ${notSignedIn}.` };
|
|
23947
|
+
if (!(view.fromLoad ? await page.goto(url, { waitUntil: "domcontentloaded" }).catch(() => null) : await openPage(page, url))) return { problem: `Nothing answers at ${url}.${origin ? " Start the project first: npm start" : ""}` };
|
|
23948
|
+
const sentTo = origin ? sentElsewhere(page, new URL(url).pathname) : void 0;
|
|
23949
|
+
for (const target of [
|
|
23950
|
+
view.waitFor,
|
|
23951
|
+
view.scrollTo,
|
|
23952
|
+
view.clip
|
|
23953
|
+
]) {
|
|
23954
|
+
const read = target === void 0 ? void 0 : await targetOn(page, target);
|
|
23955
|
+
if (read && "problem" in read) return read;
|
|
23565
23956
|
}
|
|
23566
|
-
|
|
23567
|
-
|
|
23957
|
+
if (view.waitFor) {
|
|
23958
|
+
if (!await page.waitForSelector(awaited(view.waitFor), { timeout: 1e4 }).catch(() => null)) return { problem: `${view.waitFor} did not appear on ${url} within 10 s.` };
|
|
23959
|
+
}
|
|
23960
|
+
/** The element a target names, once it is there: what it is scrolled to, or pictured alone. */
|
|
23961
|
+
const shown = {};
|
|
23962
|
+
for (const target of [view.scrollTo, view.clip]) {
|
|
23963
|
+
if (target === void 0) continue;
|
|
23964
|
+
const read = await page.waitForSelector(awaited(target), { timeout: 1e4 }).catch(() => null) ? await targetOn(page, target) : void 0;
|
|
23965
|
+
if (!read || "problem" in read || !read.found) return { problem: `${target} is not on ${url}.` };
|
|
23966
|
+
shown[target] = read.selector;
|
|
23967
|
+
}
|
|
23968
|
+
if (view.scrollTo) await page.locator(shown[view.scrollTo]).first().scrollIntoViewIfNeeded();
|
|
23969
|
+
const how = framing(view, view.clip === void 0 ? void 0 : shown[view.clip]);
|
|
23568
23970
|
await withoutDevTools(page);
|
|
23569
23971
|
const settled = view.still ? await page.evaluate((selector) => document.querySelectorAll(selector).length, WAITING_FOR_SCROLL) : 0;
|
|
23570
|
-
const whole =
|
|
23972
|
+
const whole = how.kind === "page";
|
|
23571
23973
|
const pictures = whole ? await page.evaluate(loadImages, IMAGES_BUDGET_MS) : void 0;
|
|
23572
23974
|
if (whole) await page.evaluate(unrollPage, void 0);
|
|
23573
23975
|
if (view.still) await page.addStyleTag({ content: _ });
|
|
23574
23976
|
return {
|
|
23575
23977
|
page,
|
|
23576
|
-
|
|
23978
|
+
how,
|
|
23979
|
+
png: await capture(page, how),
|
|
23577
23980
|
scheme: await paintedScheme(page, view.scheme ?? "light"),
|
|
23578
23981
|
settled,
|
|
23579
|
-
unloaded: pictures?.missing ?? 0
|
|
23982
|
+
unloaded: pictures?.missing ?? 0,
|
|
23983
|
+
...sentTo ? { sentTo } : {}
|
|
23580
23984
|
};
|
|
23581
23985
|
};
|
|
23582
23986
|
var shiftText = (shift) => shift !== void 0 && Math.abs(shift) > DRIFT_PX ? ` (${shift > 0 ? "+" : ""}${String(shift)}px there)` : "";
|
|
@@ -23690,8 +24094,10 @@ var clickThrough = async (taken, how, clicks, { frames, every }) => {
|
|
|
23690
24094
|
}];
|
|
23691
24095
|
const clicked = [];
|
|
23692
24096
|
for (const target of clicks) {
|
|
23693
|
-
const
|
|
23694
|
-
if (
|
|
24097
|
+
const read = await targetOn(taken.page, target);
|
|
24098
|
+
if ("problem" in read) return read;
|
|
24099
|
+
if (!read.found) return { problem: `${target} is not on the page: --click takes an element's name, a tag or a selector.` };
|
|
24100
|
+
const element = taken.page.locator(read.selector).first();
|
|
23695
24101
|
const before = moments[moments.length - 1].png;
|
|
23696
24102
|
try {
|
|
23697
24103
|
await element.click({ timeout: 3e3 });
|
|
@@ -23716,6 +24122,71 @@ var clickThrough = async (taken, how, clicks, { frames, every }) => {
|
|
|
23716
24122
|
clicked
|
|
23717
24123
|
};
|
|
23718
24124
|
};
|
|
24125
|
+
/** What a step is, as its label says it. */
|
|
24126
|
+
var stepText = (step) => {
|
|
24127
|
+
switch (step.kind) {
|
|
24128
|
+
case "click":
|
|
24129
|
+
case "wait-for": return `${step.kind} ${step.target}`;
|
|
24130
|
+
case "type": return `type ${step.target}`;
|
|
24131
|
+
case "press": return `press ${step.key}`;
|
|
24132
|
+
case "wait": return `wait ${String(step.ms)} ms`;
|
|
24133
|
+
case "shot": return step.label ?? "shot";
|
|
24134
|
+
case "frames": return `frames ${String(step.count)}`;
|
|
24135
|
+
}
|
|
24136
|
+
};
|
|
24137
|
+
/**
|
|
24138
|
+
* A `--steps` script played on the page: what each step does, and every picture the script asks for — each labelled with
|
|
24139
|
+
* its step and the time since the first, and measured against the one before it, so "nothing changed" is said.
|
|
24140
|
+
*/
|
|
24141
|
+
var playSteps = async (taken, how, steps) => {
|
|
24142
|
+
const { page } = taken;
|
|
24143
|
+
const started = Date.now();
|
|
24144
|
+
const moments = [{
|
|
24145
|
+
label: "before",
|
|
24146
|
+
png: taken.png
|
|
24147
|
+
}];
|
|
24148
|
+
const changes = [];
|
|
24149
|
+
const picture = async (label) => {
|
|
24150
|
+
const before = moments[moments.length - 1].png;
|
|
24151
|
+
const png = await capture(page, how);
|
|
24152
|
+
const at = `${label} · +${String(Date.now() - started)} ms`;
|
|
24153
|
+
moments.push({
|
|
24154
|
+
label: at,
|
|
24155
|
+
png
|
|
24156
|
+
});
|
|
24157
|
+
changes.push({
|
|
24158
|
+
label: at,
|
|
24159
|
+
changed: (await comparePictures(page, dataUrl(before), dataUrl(png))).changed
|
|
24160
|
+
});
|
|
24161
|
+
};
|
|
24162
|
+
for (const [index, step] of steps.entries()) try {
|
|
24163
|
+
if (step.kind === "click" || step.kind === "type") {
|
|
24164
|
+
const read = await targetOn(page, step.target);
|
|
24165
|
+
if ("problem" in read || !read.found) return { problem: `Step ${String(index + 1)}: ${"problem" in read ? read.problem : `${step.target} is not on the page — its name, a tag or a selector; one with spaces in quotes: type ".panel textarea" hola`}.` };
|
|
24166
|
+
await page.locator(read.selector).first().click({ timeout: 3e3 });
|
|
24167
|
+
if (step.kind === "type") {
|
|
24168
|
+
if (!await page.evaluate(() => {
|
|
24169
|
+
const focused = document.activeElement;
|
|
24170
|
+
return focused instanceof HTMLElement && (focused.isContentEditable || focused.matches("input, textarea, select"));
|
|
24171
|
+
}, void 0)) return { problem: `Step ${String(index + 1)}: clicking ${step.target} leaves no field focused, so the text would go to the page itself — name the field: type ".panel textarea" hola` };
|
|
24172
|
+
await page.keyboard.type(step.text);
|
|
24173
|
+
}
|
|
24174
|
+
} else if (step.kind === "press") await page.keyboard.press(step.key);
|
|
24175
|
+
else if (step.kind === "wait") await page.waitForTimeout(step.ms);
|
|
24176
|
+
else if (step.kind === "wait-for") await page.waitForSelector(awaited(step.target), { timeout: 1e4 });
|
|
24177
|
+
else if (step.kind === "shot") await picture(step.label ?? `step ${String(index + 1)}`);
|
|
24178
|
+
else for (let frame = 1; frame <= step.count; frame += 1) {
|
|
24179
|
+
if (frame > 1) await page.waitForTimeout(step.every);
|
|
24180
|
+
await picture(`frame ${String(frame)}/${String(step.count)}`);
|
|
24181
|
+
}
|
|
24182
|
+
} catch (error) {
|
|
24183
|
+
return { problem: `Step ${String(index + 1)} (${stepText(step)}) did not happen: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}` };
|
|
24184
|
+
}
|
|
24185
|
+
return {
|
|
24186
|
+
moments,
|
|
24187
|
+
changes
|
|
24188
|
+
};
|
|
24189
|
+
};
|
|
23719
24190
|
var shot = async (route, options) => {
|
|
23720
24191
|
const project = await projectHere("whose page to picture");
|
|
23721
24192
|
if (!project) return;
|
|
@@ -23724,20 +24195,53 @@ var shot = async (route, options) => {
|
|
|
23724
24195
|
fail(where.problem);
|
|
23725
24196
|
return;
|
|
23726
24197
|
}
|
|
24198
|
+
const account = options.as === void 0 ? void 0 : await checkAccount(project.root, options.as);
|
|
24199
|
+
if (account && "problem" in account) {
|
|
24200
|
+
fail(`--as ${account.problem}.`);
|
|
24201
|
+
return;
|
|
24202
|
+
}
|
|
23727
24203
|
const browser = await launchBrowser(project.root);
|
|
23728
24204
|
if ("problem" in browser) {
|
|
23729
24205
|
fail(browser.problem);
|
|
23730
24206
|
return;
|
|
23731
24207
|
}
|
|
23732
24208
|
const clicks = options.click ?? [];
|
|
24209
|
+
const script = options.steps?.startsWith("@") ? await readFile(path.resolve(options.steps.slice(1)), "utf-8").catch(() => void 0) : options.steps;
|
|
24210
|
+
if (options.steps !== void 0 && script === void 0) {
|
|
24211
|
+
await browser.close();
|
|
24212
|
+
fail(`${options.steps.slice(1)} cannot be read: --steps @<file> names a file of steps.`);
|
|
24213
|
+
return;
|
|
24214
|
+
}
|
|
24215
|
+
const steps = script === void 0 ? void 0 : parseSteps(script, options.every ?? 500);
|
|
24216
|
+
if (steps && "problem" in steps) {
|
|
24217
|
+
await browser.close();
|
|
24218
|
+
fail(`--steps: ${steps.problem}.`);
|
|
24219
|
+
return;
|
|
24220
|
+
}
|
|
24221
|
+
if (steps && (clicks.length > 0 || options.compare || (options.frames ?? 0) > 1)) {
|
|
24222
|
+
await browser.close();
|
|
24223
|
+
fail("`--steps` is the whole interaction — its own clicks and frames: leave out --click, --frames and --compare.");
|
|
24224
|
+
return;
|
|
24225
|
+
}
|
|
23733
24226
|
if (options.compare && clicks.length > 0) {
|
|
23734
24227
|
await browser.close();
|
|
23735
24228
|
fail("`--compare` sets the page beside another site as it loads: leave out --click, or picture the click on its own.");
|
|
23736
24229
|
return;
|
|
23737
24230
|
}
|
|
23738
|
-
if (options.sheet && clicks.length === 0 && (options.frames ?? 0) <= 1) {
|
|
24231
|
+
if (options.sheet && clicks.length === 0 && (options.frames ?? 0) <= 1 && options.steps === void 0) {
|
|
24232
|
+
await browser.close();
|
|
24233
|
+
fail("`--sheet` lays out the pictures a --click, --frames or --steps takes: with none of them, there is one picture and no sheet.");
|
|
24234
|
+
return;
|
|
24235
|
+
}
|
|
24236
|
+
const fromLoad = options.from === "load";
|
|
24237
|
+
if (fromLoad && ((options.frames ?? 0) <= 1 || clicks.length > 0 || options.compare)) {
|
|
23739
24238
|
await browser.close();
|
|
23740
|
-
fail("`--
|
|
24239
|
+
fail("`--from load` starts --frames as the HTML arrives, for what plays while the page loads: give it --frames, and leave out --click and --compare.");
|
|
24240
|
+
return;
|
|
24241
|
+
}
|
|
24242
|
+
if (fromLoad && !options.clip && !options.scrollTo && !options.viewport) {
|
|
24243
|
+
await browser.close();
|
|
24244
|
+
fail("`--from load` pictures the screen as the page arrives, never the whole page — unrolling it waits for it to settle: add --viewport or --clip.");
|
|
23741
24245
|
return;
|
|
23742
24246
|
}
|
|
23743
24247
|
if (options.compare && (options.clip || options.scrollTo || options.viewport)) {
|
|
@@ -23756,14 +24260,17 @@ var shot = async (route, options) => {
|
|
|
23756
24260
|
...options.clip ? { clip: options.clip } : {},
|
|
23757
24261
|
...options.scrollTo ? { scrollTo: options.scrollTo } : {},
|
|
23758
24262
|
...options.viewport ? { viewport: true } : {},
|
|
24263
|
+
...options.presence ? { presence: true } : {},
|
|
24264
|
+
...account ? { account } : {},
|
|
24265
|
+
...fromLoad ? { fromLoad } : {},
|
|
23759
24266
|
still: !options.clip && !options.scrollTo && !options.viewport && (options.frames ?? 0) <= 1 && clicks.length === 0
|
|
23760
24267
|
};
|
|
23761
|
-
const how = framing(view);
|
|
23762
24268
|
const taken = await pictureOf(browser, `${where.origin}${pathname}`, view, where.origin);
|
|
23763
24269
|
if ("problem" in taken) {
|
|
23764
|
-
fail(
|
|
24270
|
+
fail(taken.problem);
|
|
23765
24271
|
return;
|
|
23766
24272
|
}
|
|
24273
|
+
const { how } = taken;
|
|
23767
24274
|
const name = pathname === "/" ? "home" : pathname.replace(/[^a-z0-9]+/gi, "-").replace(/^-|-$/g, "");
|
|
23768
24275
|
const out = path.resolve(project.root, options.out ?? `tmp/shots/${name}-${String(view.width)}-${taken.scheme}.png`);
|
|
23769
24276
|
const base = out.replace(/\.png$/, "");
|
|
@@ -23776,7 +24283,8 @@ var shot = async (route, options) => {
|
|
|
23776
24283
|
scheme: taken.scheme,
|
|
23777
24284
|
out,
|
|
23778
24285
|
...taken.settled > 0 ? { settled: taken.settled } : {},
|
|
23779
|
-
...taken.unloaded > 0 ? { unloaded: taken.unloaded } : {}
|
|
24286
|
+
...taken.unloaded > 0 ? { unloaded: taken.unloaded } : {},
|
|
24287
|
+
...taken.sentTo ? { sentTo: taken.sentTo } : {}
|
|
23780
24288
|
};
|
|
23781
24289
|
if (options.compare) {
|
|
23782
24290
|
const other = new URL(options.compare);
|
|
@@ -23790,7 +24298,15 @@ var shot = async (route, options) => {
|
|
|
23790
24298
|
const frames = options.frames ?? 0;
|
|
23791
24299
|
const every = options.every ?? 500;
|
|
23792
24300
|
let moments = [];
|
|
23793
|
-
if (
|
|
24301
|
+
if (steps) {
|
|
24302
|
+
const played = await playSteps(taken, how, steps);
|
|
24303
|
+
if ("problem" in played) {
|
|
24304
|
+
fail(played.problem);
|
|
24305
|
+
return;
|
|
24306
|
+
}
|
|
24307
|
+
moments = played.moments;
|
|
24308
|
+
report.steps = played.changes;
|
|
24309
|
+
} else if (clicks.length > 0) {
|
|
23794
24310
|
const played = await clickThrough(taken, how, clicks, {
|
|
23795
24311
|
frames,
|
|
23796
24312
|
every
|
|
@@ -23808,7 +24324,7 @@ var shot = async (route, options) => {
|
|
|
23808
24324
|
pictures.push(await capture(taken.page, how));
|
|
23809
24325
|
}
|
|
23810
24326
|
moments = pictures.map((png, frame) => ({
|
|
23811
|
-
label: frame === 0 ? "before" : `+${String(frame * every)} ms`,
|
|
24327
|
+
label: frame === 0 ? fromLoad ? "HTML in" : "before" : `+${String(frame * every)} ms`,
|
|
23812
24328
|
png
|
|
23813
24329
|
}));
|
|
23814
24330
|
const diffs = [];
|
|
@@ -23832,7 +24348,7 @@ var shot = async (route, options) => {
|
|
|
23832
24348
|
})));
|
|
23833
24349
|
report.sheet = `${base}-sheet.png`;
|
|
23834
24350
|
await writeFile(report.sheet, Buffer.from(sheet.replace(/^data:image\/png;base64,/, ""), "base64"));
|
|
23835
|
-
} else if (moments.length > 1 && clicks.length > 0) {
|
|
24351
|
+
} else if (moments.length > 1 && (clicks.length > 0 || steps)) {
|
|
23836
24352
|
report.pictures = [];
|
|
23837
24353
|
for (const [index, moment] of moments.slice(1).entries()) {
|
|
23838
24354
|
const file = `${base}-${String(index + 1)}.png`;
|
|
@@ -23848,9 +24364,11 @@ var shot = async (route, options) => {
|
|
|
23848
24364
|
return;
|
|
23849
24365
|
}
|
|
23850
24366
|
console.log(out);
|
|
24367
|
+
if (report.sentTo) console.log(chalk.yellow(account ? `${pathname} sent the browser to ${report.sentTo}, signed in as ${account.username}: the picture is of ${report.sentTo} — that account may not see ${pathname}` : `${pathname} sent the browser to ${report.sentTo}: the picture is of ${report.sentTo}. A page for signed-in visitors? \`--as <username>\` signs in first, the password in ${CHECK_PASSWORD_ENV} in .env`));
|
|
23851
24368
|
if (report.settled) console.log(chalk.dim(`${String(report.settled)} arrival${report.settled === 1 ? "" : "s"} waiting for the scroll shown as they end — --scroll-to <id> --viewport --frames 4 shows one arriving`));
|
|
23852
24369
|
if (report.unloaded) console.log(chalk.yellow(`${String(report.unloaded)} picture(s) had not loaded when the page was taken`));
|
|
23853
24370
|
if (report.compare) console.log(compareText(report.compare).join("\n"));
|
|
24371
|
+
for (const { label, changed } of report.steps ?? []) console.log(changed > 0 ? `${label}: ${String(changed)}% of the picture changed` : chalk.yellow(`${label}: nothing changed since the picture before`));
|
|
23854
24372
|
for (const { target, changed } of report.clicked ?? []) console.log(changed > 0 ? `clicked ${target}: ${String(changed)}% of the picture changed` : chalk.yellow(`clicked ${target}: nothing changed — the click did nothing to see`));
|
|
23855
24373
|
if (report.sheet) console.log(`sheet: ${report.sheet}`);
|
|
23856
24374
|
for (const picture of report.pictures ?? []) console.log(`${picture.label}: ${picture.out}`);
|
|
@@ -23961,30 +24479,39 @@ var verify = async (options) => {
|
|
|
23961
24479
|
};
|
|
23962
24480
|
var NOT_STARTED = "start it (npm start) and verify again, or --no-pages to leave them";
|
|
23963
24481
|
var pagesChecked = async (project) => {
|
|
23964
|
-
const
|
|
23965
|
-
if ("problem" in
|
|
23966
|
-
const
|
|
23967
|
-
|
|
23968
|
-
|
|
23969
|
-
|
|
24482
|
+
const found = await staticPaths(project.root);
|
|
24483
|
+
if ("problem" in found) return found;
|
|
24484
|
+
const { paths, schemes } = found;
|
|
24485
|
+
const inEveryTheme = async (routes, account) => {
|
|
24486
|
+
const all = [];
|
|
24487
|
+
for (const scheme of schemes) {
|
|
24488
|
+
const reports = await checkRoutes(project, routes, {
|
|
24489
|
+
widths: WIDTHS,
|
|
24490
|
+
asked: { state: false },
|
|
24491
|
+
ssr: false,
|
|
24492
|
+
scheme,
|
|
24493
|
+
...account ? { account } : {}
|
|
24494
|
+
});
|
|
24495
|
+
if ("problem" in reports) return { problem: `${reports.problem} — ${NOT_STARTED}` };
|
|
24496
|
+
all.push(...reports);
|
|
24497
|
+
}
|
|
24498
|
+
return all;
|
|
23970
24499
|
};
|
|
23971
|
-
const reports = await
|
|
23972
|
-
if ("problem" in reports) return
|
|
24500
|
+
const reports = await inEveryTheme(paths);
|
|
24501
|
+
if ("problem" in reports) return reports;
|
|
23973
24502
|
const sentAway = [...new Set(reports.filter(redirected).map((report) => report.path))];
|
|
23974
|
-
if (sentAway.length === 0) return summary(reports);
|
|
24503
|
+
if (sentAway.length === 0) return summary(schemes, reports);
|
|
23975
24504
|
const account = await checkAccount(project.root);
|
|
23976
|
-
if (!account || "problem" in account) return summary(reports, account ?? { none: true });
|
|
23977
|
-
const signedIn = await
|
|
23978
|
-
|
|
23979
|
-
|
|
23980
|
-
});
|
|
23981
|
-
if ("problem" in signedIn) return { problem: `${signedIn.problem} — ${NOT_STARTED}` };
|
|
23982
|
-
return summary([...reports.filter((report) => !sentAway.includes(report.path)), ...signedIn], {
|
|
24505
|
+
if (!account || "problem" in account) return summary(schemes, reports, account ?? { none: true });
|
|
24506
|
+
const signedIn = await inEveryTheme(sentAway, account);
|
|
24507
|
+
if ("problem" in signedIn) return signedIn;
|
|
24508
|
+
return summary(schemes, [...reports.filter((report) => !sentAway.includes(report.path)), ...signedIn], {
|
|
23983
24509
|
as: account.username,
|
|
23984
24510
|
checks: signedIn.filter((report) => !unchecked(report)).length
|
|
23985
24511
|
});
|
|
23986
24512
|
};
|
|
23987
|
-
var summary = (reports, signedIn) => ({
|
|
24513
|
+
var summary = (schemes, reports, signedIn) => ({
|
|
24514
|
+
schemes,
|
|
23988
24515
|
passing: reports.filter((report) => report.ok).length,
|
|
23989
24516
|
failing: reports.filter((report) => !report.ok && !unchecked(report)),
|
|
23990
24517
|
unchecked: [...new Set(reports.filter(unchecked).map((report) => report.path))],
|
|
@@ -24003,7 +24530,7 @@ var verifyText = (results, pages) => [...results.flatMap((result) => result.ok ?
|
|
|
24003
24530
|
...(result.said ?? []).map((line) => ` ${line}`),
|
|
24004
24531
|
...result.fix ? [` → ${result.fix}`] : []
|
|
24005
24532
|
]), ...pages === void 0 ? [chalk.yellow("- pages not checked: --no-pages")] : "waiting" in pages ? [chalk.yellow(`- not run until ${pages.after} passes: ${pages.waiting.join(", ")} (--keep-going runs them anyway)`)] : "problem" in pages ? [chalk.red(`✗ pages — ${pages.problem}`)] : [
|
|
24006
|
-
pages.failing.length === 0 ? chalk.green(`✓ pages — ${String(pages.passing)} checks at ${WIDTHS.join(" and ")} px${pages.signedIn && "as" in pages.signedIn ? `, ${String(pages.signedIn.checks)} of them signed in as ${pages.signedIn.as}` : ""}`) : chalk.red(`✗ pages — ${String(pages.failing.length)} of ${String(pages.passing + pages.failing.length)} checks`),
|
|
24533
|
+
pages.failing.length === 0 ? chalk.green(`✓ pages — ${String(pages.passing)} checks at ${WIDTHS.join(" and ")} px, ${pages.schemes.join(" and ")}${pages.signedIn && "as" in pages.signedIn ? `, ${String(pages.signedIn.checks)} of them signed in as ${pages.signedIn.as}` : ""}`) : chalk.red(`✗ pages — ${String(pages.failing.length)} of ${String(pages.passing + pages.failing.length)} checks`),
|
|
24007
24534
|
...pages.failing.map((report) => reportText$2(report, { state: false })),
|
|
24008
24535
|
...pages.unchecked.length > 0 ? [chalk.yellow(uncheckedText(pages))] : []
|
|
24009
24536
|
]].join("\n");
|
|
@@ -27185,14 +27712,14 @@ program.command("login").description("Sign in, in your browser. The session is k
|
|
|
27185
27712
|
program.command("logout").description("Sign out: the session is revoked on the platform and forgotten here").action(() => logout());
|
|
27186
27713
|
program.command("whoami").description("Who the CLI is signed in as, and the space it works in").option("--json", "One object: { api, user, space }, for a tool or an agent").option(...API_OPTION).action((options) => whoami(options));
|
|
27187
27714
|
spaceGroup.command("use").description("Choose the space to work in, in your browser. One at a time: it replaces the one chosen before").option(...API_OPTION).action((options) => space$2(options));
|
|
27188
|
-
pageGroup.command("check").argument("[paths...]", "The pages: /about /writers, in one browser. The home page when left out").description("Whether a page of the running project is whole, in text: every element on screen, no broken image, no console error, no failed flow").addOption(widthsOption("The widths to check it at, separated by commas", [1440, 390])).addOption(schemeOption()).option("--state", "Also what the page holds: its state, and every source by name").option("--element <id>", "Also one element: what it reads, its own state, whether it is on screen").option("--ssr", "Also the HTML the server sent against the hydrated page: what a server provider sent late").option("--click <id>", "Click one element once the page settles, and say what it changed — or that nothing did").addOption(new Option("--fill <id=value>", "Fill a field before the click, as a visitor types in it — once per field; a box takes true or false").argParser(fill)).option("--as <username>", "Sign in first as this account, through the server’s /auth routes — the password from PLITZI_CHECK_PASSWORD, in .env").option("--json", "One object per page and width, for a tool or an agent").action((paths, options) => check(paths, options));
|
|
27715
|
+
pageGroup.command("check").argument("[paths...]", "The pages: /about /writers, in one browser. The home page when left out").description("Whether a page of the running project is whole, in text: every element on screen, no broken image, no console error, no failed flow").addOption(widthsOption("The widths to check it at, separated by commas", [1440, 390])).addOption(schemeOption()).option("--state", "Also what the page holds: its state, and every source by name").option("--element <id>", "Also one element: what it reads, its own state, whether it is on screen").option("--ssr", "Also the HTML the server sent against the hydrated page: what a server provider sent late").option("--click <id>", "Click one element once the page settles, and say what it changed — or that nothing did").addOption(new Option("--fill <id=value>", "Fill a field before the click, as a visitor types in it — once per field; a box takes true or false").argParser(fill)).option("--as <username>", "Sign in first as this account, through the server’s /auth routes — the password from PLITZI_CHECK_PASSWORD, in .env").option("--presence", "Take part in the page’s realtime channels as a visitor does — arrive, announce, send. Otherwise it only watches them").option("--json", "One object per page and width, for a tool or an agent").action((paths, options) => check(paths, options));
|
|
27189
27716
|
spaceGroup.command("fix").description("What authoring would fix in the space, as edits to your source: shown as a diff; with --write written, formatted and checked").option("--write", "Write the edits — kept only when the space authors with each fix gone and no problem added").option("--json", "The plan as one object, for a tool or an agent").action((options) => fix(options));
|
|
27190
27717
|
pageGroup.command("import").argument("<url>", "The page to start from: https://example.com/pricing").description("A page of a site you verified, as a place to start writing from: its tokens, the outline of its blocks per breakpoint, its lists as JSON — never its words").option("-o, --out <dir>", "Where it is written, inside the project", "src/imported").addOption(widthsOption("The widths it is measured at: the widest is desktop, then tablet and mobile", [
|
|
27191
27718
|
1440,
|
|
27192
27719
|
768,
|
|
27193
27720
|
390
|
|
27194
27721
|
])).option("-f, --force", "Write over what --out already holds").option("--account", "A site not served from this machine: ask your Plitzi account whether one of your spaces verified its domain (signs in)").option("--json", "One object, for a tool or an agent").option(...API_OPTION).option(...DRY_RUN_OPTION).action((url, options) => importPage(url, options));
|
|
27195
|
-
pageGroup.command("shot").argument("[path]", "The page: /about. The home page when left out").description("A picture of one page of the running project — and, asked, how it differs from another or what moves").addOption(new Option("--width <px>", "The viewport width").argParser(width).default(1280)).addOption(new Option("--height <px>", "The viewport height (the picture is the whole page unless --viewport, --scroll-to or --clip)").argParser(positiveInteger).default(800)).addOption(schemeOption()).option("-o, --out <file>", "Where the picture goes. tmp/shots/<page>-<width>-<scheme>.png by default").option("--compare <url>", "Another site: the same page there, side by side, and how much differs by section").addOption(new Option("--frames <n>", "Pictures taken one after another: which sections move (a marquee, an autoplay)").argParser(positiveInteger)).addOption(new Option("--every <ms>", "How far apart --frames are taken").argParser(positiveInteger).default(500)).option("--wait-for <element>", "An element to wait for first: its name (data-plitzi-el) or a CSS selector").option("--clip <element>", "Only this element — its name or a CSS selector — scrolled to wherever it is").option("--scroll-to <element>", "The page scrolled until this element is in view; the picture is the screen there").option("--viewport", "Only what fits the viewport, not the whole page").option("--click <element...>", "Click these in order once the page settles — each its name or a CSS selector, inside a plugin too — picturing what each changed (--frames pictures --every ms apart after each)").option("--sheet", "Every picture taken — before, after each click, each frame — on one contact sheet").option("--reduced-motion", "As a visitor who asked for less motion").option("--json", "One object, for a tool or an agent").action((path, options) => shot(path, options));
|
|
27722
|
+
pageGroup.command("shot").argument("[path]", "The page: /about. The home page when left out").description("A picture of one page of the running project — and, asked, how it differs from another or what moves").addOption(new Option("--width <px>", "The viewport width").argParser(width).default(1280)).addOption(new Option("--height <px>", "The viewport height (the picture is the whole page unless --viewport, --scroll-to or --clip)").argParser(positiveInteger).default(800)).addOption(schemeOption()).option("-o, --out <file>", "Where the picture goes. tmp/shots/<page>-<width>-<scheme>.png by default").option("--compare <url>", "Another site: the same page there, side by side, and how much differs by section").addOption(new Option("--frames <n>", "Pictures taken one after another: which sections move (a marquee, an autoplay)").argParser(positiveInteger)).addOption(new Option("--every <ms>", "How far apart --frames are taken").argParser(positiveInteger).default(500)).addOption(new Option("--from <moment>", "When --frames start: once the page settles, or as soon as its HTML is in (load) — what plays as it arrives").choices([...SHOT_MOMENTS]).default("settled")).option("--wait-for <element>", "An element to wait for first: its name (data-plitzi-el) or a CSS selector").option("--clip <element>", "Only this element — its name or a CSS selector — scrolled to wherever it is").option("--scroll-to <element>", "The page scrolled until this element is in view; the picture is the screen there").option("--viewport", "Only what fits the viewport, not the whole page").option("--click <element...>", "Click these in order once the page settles — each its name or a CSS selector, inside a plugin too — picturing what each changed (--frames pictures --every ms apart after each)").option("--sheet", "Every picture taken — before, after each click, each frame — on one contact sheet").option("--steps <script>", "An interaction, step by step: \"click <el>; type <el> <text>; press <key>; wait <ms>; wait-for <el>; shot [label]; frames <n> [ms]\" — or @file with one per line").option("--reduced-motion", "As a visitor who asked for less motion").option("--as <username>", "Sign in first as this account, through the server’s /auth routes — the password from PLITZI_CHECK_PASSWORD, in .env").option("--presence", "Take part in the page’s realtime channels as a visitor does — arrive, announce, send. Otherwise it only watches them").option("--json", "One object, for a tool or an agent").action((path, options) => shot(path, options));
|
|
27196
27723
|
program.command("verify").description("Whether the project is left passing: author, lints, types, format and every page, only the problems said").option("--no-pages", "Leave the pages out — said as such").option("--keep-going", "Run every check even after one fails — by default the first failure ends the run").option("--json", "One object, for a tool or an agent").action((options) => verify(options));
|
|
27197
27724
|
elementGroup.command("where").argument("<query>", "An element’s id, a class it wears, or words it shows: hero-cta, navLink, \"Get started\"").description("Where the project’s code writes an element: the file, the line and the call itself").addOption(new Option("--by <reading>", "Read the query one way only, not the first of id, class and words that matches").choices(WHERE_READINGS)).option("--json", "One object, for a tool or an agent").action((query, options) => where(query, options));
|
|
27198
27725
|
elementGroup.command("edit").argument("<id>", "The element, by its id: hero-cta").description("Change an element’s attributes in the call that writes it, then check the space still authors").option("--set <key=value...>", "An attribute to write: content=\"Start free\", required=true").option("--remove <key...>", "An attribute to take out").option("--every", "The call writes other elements too, and the change is for every one").option("--json", "One object, for a tool or an agent").action((id, options) => edit(id, options));
|
|
@@ -27210,6 +27737,7 @@ pluginGroup.command("upload").argument("[zip]", "The zip plitzi plugin pack buil
|
|
|
27210
27737
|
var functions = program.command("functions").description(`The space’s own server code: ${h$1}/ in this project is a working copy of it`);
|
|
27211
27738
|
functions.command("pull").description(`Write the space’s functions into ${h$1}/ — refused when that would overwrite what is not pushed`).option("-f, --force", "Overwrite what is not pushed, or a copy of another space").option(...API_OPTION).option(...DRY_RUN_OPTION).action((options) => pullFunctions(options));
|
|
27212
27739
|
functions.command("push").description(`Save ${h$1}/ as the space’s draft: built and checked on the platform, refused if it moved on since`).option(...API_OPTION).option(...DRY_RUN_OPTION).action((options) => pushFunctions(options));
|
|
27740
|
+
functions.command("add").argument("<package>", "An npm package the project installed — ical.js, @scope/name").description(`Bundle a package into ${h$1}/vendor/ for the functions to import, as a function carries its dependencies — web APIs only`).option(...DRY_RUN_OPTION).action((name, options) => addFunctionsPackage(name, options));
|
|
27213
27741
|
functions.command("try").argument("<task>", "The task, <namespace>.<action>").description("Run one task of the draft in the sandbox: its value, what it logged, and why it failed").option("--params <json>", "Its params, as a JSON object").option(...API_OPTION).action((task, options) => tryFunction(task, options));
|
|
27214
27742
|
functions.command("dev").argument("<task>", "The task, <namespace>.<action>").description(`Run one task from ${h$1}/ on this machine, as the platform runs it — nothing reaches the space`).option("--params <json>", "Its params, as a JSON object").option("-w, --watch", `Run it again every time a file of ${h$1}/ is saved`).action((task, options) => devFunction(task, options));
|
|
27215
27743
|
runtime.command("push").description("Pack this project’s runtime module and keep it as the space’s draft runtime").option("--entry <path>", "The module whose default export is defineRuntime(…)", "src/runtime/index.ts").option(...API_OPTION).option(...DRY_RUN_OPTION).action((options) => pushRuntime(options));
|