tutuca 0.9.30 → 0.9.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/tutuca-cli.js +157 -29
- package/dist/tutuca-dev.js +36 -18
- package/dist/tutuca-dev.min.js +3 -3
- package/dist/tutuca-extra.js +31 -16
- package/dist/tutuca-extra.min.js +3 -3
- package/dist/tutuca.js +28 -13
- package/dist/tutuca.min.js +3 -3
- package/package.json +9 -4
- package/skill/SKILL.md +36 -0
- package/skill/advanced.md +170 -0
- package/skill/cli.md +110 -0
- package/skill/core.md +677 -0
package/README.md
CHANGED
|
@@ -95,6 +95,7 @@ tutuca help [command]
|
|
|
95
95
|
| `lint [name]` | Run lint checks — all, or one by name (exit 2 on errors) |
|
|
96
96
|
| `render [name] [--title t] [--view v]` | Render examples to HTML |
|
|
97
97
|
| `doctor` | Lint + render smoke test over the whole module |
|
|
98
|
+
| `install-skill [--user] [--force]` | Install the tutuca Claude Code skill (no module path needed) |
|
|
98
99
|
|
|
99
100
|
Global flags: `-f, --format <cli\|md\|json\|html>`, `-o, --output <file>`, `--pretty`, `-h, --help`.
|
|
100
101
|
|
|
@@ -138,6 +139,27 @@ The invocation stays short even without wrapping, but common patterns:
|
|
|
138
139
|
- **`justfile` / `Makefile`** — one recipe per subcommand, passing through positionals
|
|
139
140
|
- **Programmatic** — `import "tutuca/cli"` (the bundled entry) for custom build integration
|
|
140
141
|
|
|
142
|
+
## Use with Claude Code
|
|
143
|
+
|
|
144
|
+
Tutuca ships an LLM-facing reference (`SKILL.md` + `core.md` / `cli.md` /
|
|
145
|
+
`advanced.md`) packaged as a [Claude Code skill](https://docs.claude.com/en/docs/claude-code/skills).
|
|
146
|
+
Once installed, Claude auto-loads it whenever a session touches tutuca
|
|
147
|
+
components, views, macros, or the CLI.
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
# project-scoped: writes ./.claude/skills/tutuca/ (commit it for the team)
|
|
151
|
+
npx tutuca install-skill
|
|
152
|
+
|
|
153
|
+
# or user-scoped: writes ~/.claude/skills/tutuca/
|
|
154
|
+
npx tutuca install-skill --user
|
|
155
|
+
|
|
156
|
+
# overwrite an existing install
|
|
157
|
+
npx tutuca install-skill --force
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The skill content is generated from `docs/llm/`, so the same reference
|
|
161
|
+
runs locally (`tutuca <module> doctor`) and inside Claude.
|
|
162
|
+
|
|
141
163
|
## License
|
|
142
164
|
|
|
143
165
|
MIT
|
package/dist/tutuca-cli.js
CHANGED
|
@@ -1394,7 +1394,7 @@ class ParseContext {
|
|
|
1394
1394
|
parseHTML(html) {
|
|
1395
1395
|
const t = this.document.createElement("template");
|
|
1396
1396
|
t.innerHTML = html;
|
|
1397
|
-
return
|
|
1397
|
+
return t.content.childNodes;
|
|
1398
1398
|
}
|
|
1399
1399
|
addNodeIf(Class, val, extra) {
|
|
1400
1400
|
if (val !== null) {
|
|
@@ -1614,7 +1614,20 @@ var init_anode = __esm(() => {
|
|
|
1614
1614
|
return this.val.toPathItem();
|
|
1615
1615
|
}
|
|
1616
1616
|
static parse(html, px) {
|
|
1617
|
-
|
|
1617
|
+
const nodes = px.parseHTML(html);
|
|
1618
|
+
if (nodes.length === 0)
|
|
1619
|
+
return new TextNode("");
|
|
1620
|
+
if (nodes.length === 1)
|
|
1621
|
+
return ANode.fromDOM(nodes[0], px);
|
|
1622
|
+
const childs = new Array(nodes.length);
|
|
1623
|
+
for (let i = 0;i < nodes.length; i++)
|
|
1624
|
+
childs[i] = ANode.fromDOM(nodes[i], px);
|
|
1625
|
+
const trimmed = condenseChildsWhites(childs);
|
|
1626
|
+
if (trimmed.length === 0)
|
|
1627
|
+
return new TextNode("");
|
|
1628
|
+
if (trimmed.length === 1)
|
|
1629
|
+
return trimmed[0];
|
|
1630
|
+
return new FragmentNode(trimmed);
|
|
1618
1631
|
}
|
|
1619
1632
|
static fromDOM(node, px) {
|
|
1620
1633
|
if (node instanceof px.Text)
|
|
@@ -1634,10 +1647,8 @@ var init_anode = __esm(() => {
|
|
|
1634
1647
|
switch (name) {
|
|
1635
1648
|
case "slot":
|
|
1636
1649
|
return new SlotNode(null, vp.const(value), maybeFragment(childs));
|
|
1637
|
-
case "text":
|
|
1638
|
-
|
|
1639
|
-
return v !== null ? new RenderTextNode(null, v) : null;
|
|
1640
|
-
}
|
|
1650
|
+
case "text":
|
|
1651
|
+
return px.addNodeIf(RenderTextNode, vp.parseText(value, px));
|
|
1641
1652
|
case "render":
|
|
1642
1653
|
return px.addNodeIf(RenderNode, vp.parseRender(value, px), as);
|
|
1643
1654
|
case "render-it":
|
|
@@ -2025,7 +2036,11 @@ class ComponentStack {
|
|
|
2025
2036
|
}
|
|
2026
2037
|
}
|
|
2027
2038
|
registerMacros(macros) {
|
|
2028
|
-
|
|
2039
|
+
for (const key in macros) {
|
|
2040
|
+
const lower = key.toLowerCase();
|
|
2041
|
+
console.assert(this.macros[lower] === undefined, "macro key collision", lower);
|
|
2042
|
+
this.macros[lower] = macros[key];
|
|
2043
|
+
}
|
|
2029
2044
|
}
|
|
2030
2045
|
getCompFor(v) {
|
|
2031
2046
|
return this.comps.getCompFor(v);
|
|
@@ -2083,7 +2098,10 @@ function checkMacroCallArgs(lx, view, Comp) {
|
|
|
2083
2098
|
const { defaults } = macro;
|
|
2084
2099
|
for (const argName in macroNode.attrs) {
|
|
2085
2100
|
if (!(argName in defaults)) {
|
|
2086
|
-
lx.error(UNKNOWN_MACRO_ARG, {
|
|
2101
|
+
lx.error(UNKNOWN_MACRO_ARG, {
|
|
2102
|
+
name: argName,
|
|
2103
|
+
macroName: macroNode.name
|
|
2104
|
+
});
|
|
2087
2105
|
}
|
|
2088
2106
|
}
|
|
2089
2107
|
}
|
|
@@ -2244,7 +2262,7 @@ function checkConsistentAttrVal(lx, val, fields, proto, computed, scope, alter,
|
|
|
2244
2262
|
if (alter[val.name] === undefined) {
|
|
2245
2263
|
lx.error(ALT_HANDLER_NOT_DEFINED, { name: val.name });
|
|
2246
2264
|
}
|
|
2247
|
-
} else if (valName !== "ConstVal" && valName !== "BindVal") {
|
|
2265
|
+
} else if (valName !== "ConstVal" && valName !== "BindVal" && valName !== "DynVal") {
|
|
2248
2266
|
console.log(val);
|
|
2249
2267
|
}
|
|
2250
2268
|
}
|
|
@@ -7719,7 +7737,7 @@ class Renderer {
|
|
|
7719
7737
|
this.cache = new WeakMapDomCache;
|
|
7720
7738
|
}
|
|
7721
7739
|
getSeqInfo(seq) {
|
|
7722
|
-
return isIndexed(seq) ? imIndexedIter : isKeyed(seq) ? imKeyedIter :
|
|
7740
|
+
return isIndexed(seq) ? imIndexedIter : isKeyed(seq) ? imKeyedIter : seq?.[SEQ_INFO] ?? unkIter;
|
|
7723
7741
|
}
|
|
7724
7742
|
renderTag(tag, attrs, childs) {
|
|
7725
7743
|
return h(tag, attrs, childs);
|
|
@@ -7835,12 +7853,12 @@ var DATASET_ATTRS, imIndexedIter = (seq, visit) => {
|
|
|
7835
7853
|
}, imKeyedIter = (seq, visit) => {
|
|
7836
7854
|
for (const [k, v] of seq.toSeq().entries())
|
|
7837
7855
|
visit(k, v, "sk");
|
|
7838
|
-
}, unkIter = () => {},
|
|
7856
|
+
}, unkIter = () => {}, SEQ_INFO;
|
|
7839
7857
|
var init_renderer = __esm(() => {
|
|
7840
7858
|
init_immutable();
|
|
7841
7859
|
init_vdom();
|
|
7842
7860
|
DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
7843
|
-
|
|
7861
|
+
SEQ_INFO = Symbol.for("tutuca.seqInfo");
|
|
7844
7862
|
});
|
|
7845
7863
|
|
|
7846
7864
|
// src/util/render.js
|
|
@@ -8040,11 +8058,105 @@ var init__registry = __esm(() => {
|
|
|
8040
8058
|
};
|
|
8041
8059
|
});
|
|
8042
8060
|
|
|
8061
|
+
// tools/cli/commands/install-skill.js
|
|
8062
|
+
var exports_install_skill = {};
|
|
8063
|
+
__export(exports_install_skill, {
|
|
8064
|
+
run: () => run,
|
|
8065
|
+
describe: () => describe
|
|
8066
|
+
});
|
|
8067
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
8068
|
+
import { homedir } from "node:os";
|
|
8069
|
+
import { dirname, resolve } from "node:path";
|
|
8070
|
+
import { parseArgs } from "node:util";
|
|
8071
|
+
import { fileURLToPath } from "node:url";
|
|
8072
|
+
function findSkillDir() {
|
|
8073
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
8074
|
+
const candidates = [resolve(here, "..", "..", "..", "skill"), resolve(here, "..", "skill")];
|
|
8075
|
+
for (const c of candidates) {
|
|
8076
|
+
if (existsSync(resolve(c, "SKILL.md")))
|
|
8077
|
+
return c;
|
|
8078
|
+
}
|
|
8079
|
+
return null;
|
|
8080
|
+
}
|
|
8081
|
+
function targetDir(scope) {
|
|
8082
|
+
if (scope === "user")
|
|
8083
|
+
return resolve(homedir(), ".claude/skills/tutuca");
|
|
8084
|
+
return resolve(process.cwd(), ".claude/skills/tutuca");
|
|
8085
|
+
}
|
|
8086
|
+
async function run(argv) {
|
|
8087
|
+
const parsed = parseArgs({
|
|
8088
|
+
args: argv,
|
|
8089
|
+
options: {
|
|
8090
|
+
user: { type: "boolean", default: false },
|
|
8091
|
+
project: { type: "boolean", default: false },
|
|
8092
|
+
force: { type: "boolean", short: "f", default: false },
|
|
8093
|
+
help: { type: "boolean", short: "h", default: false }
|
|
8094
|
+
},
|
|
8095
|
+
allowPositionals: false
|
|
8096
|
+
});
|
|
8097
|
+
if (parsed.values.help) {
|
|
8098
|
+
process.stdout.write(`tutuca install-skill [--user | --project] [--force]
|
|
8099
|
+
` + `
|
|
8100
|
+
` + ` Copies SKILL.md + core.md + cli.md + advanced.md into
|
|
8101
|
+
` + ` .claude/skills/tutuca/. Defaults to --project (cwd).
|
|
8102
|
+
` + ` --user installs at ~/.claude/skills/tutuca/.
|
|
8103
|
+
` + ` --force overwrites existing files.
|
|
8104
|
+
`);
|
|
8105
|
+
return;
|
|
8106
|
+
}
|
|
8107
|
+
if (parsed.values.user && parsed.values.project) {
|
|
8108
|
+
process.stderr.write(`tutuca: --user and --project are mutually exclusive
|
|
8109
|
+
`);
|
|
8110
|
+
process.exit(1);
|
|
8111
|
+
}
|
|
8112
|
+
const scope = parsed.values.user ? "user" : "project";
|
|
8113
|
+
const target = targetDir(scope);
|
|
8114
|
+
const src = findSkillDir();
|
|
8115
|
+
if (!src) {
|
|
8116
|
+
process.stderr.write(`tutuca: skill assets not found alongside this CLI.
|
|
8117
|
+
` + "If you're running from a checkout, run `bun scripts/build-skill.js` first.\n");
|
|
8118
|
+
process.exit(1);
|
|
8119
|
+
}
|
|
8120
|
+
if (existsSync(target) && !parsed.values.force) {
|
|
8121
|
+
const existing = readdirSync(target).filter((n) => SKILL_FILES.includes(n));
|
|
8122
|
+
if (existing.length > 0) {
|
|
8123
|
+
process.stderr.write(`tutuca: ${target} already contains skill files. Re-run with --force to overwrite.
|
|
8124
|
+
`);
|
|
8125
|
+
process.exit(1);
|
|
8126
|
+
}
|
|
8127
|
+
}
|
|
8128
|
+
mkdirSync(target, { recursive: true });
|
|
8129
|
+
for (const name of SKILL_FILES) {
|
|
8130
|
+
const from = resolve(src, name);
|
|
8131
|
+
if (!existsSync(from)) {
|
|
8132
|
+
process.stderr.write(`tutuca: missing skill asset: ${from}
|
|
8133
|
+
`);
|
|
8134
|
+
process.exit(1);
|
|
8135
|
+
}
|
|
8136
|
+
const buf = readFileSync(from);
|
|
8137
|
+
writeFileSync(resolve(target, name), buf);
|
|
8138
|
+
}
|
|
8139
|
+
const rel = scope === "project" ? ".claude/skills/tutuca" : target;
|
|
8140
|
+
process.stdout.write(`installed tutuca skill → ${rel}
|
|
8141
|
+
`);
|
|
8142
|
+
process.stdout.write(`Open a Claude Code session in this directory to use it.
|
|
8143
|
+
`);
|
|
8144
|
+
}
|
|
8145
|
+
var describe = "Install the tutuca Claude Code skill into .claude/skills/tutuca/.", SKILL_FILES;
|
|
8146
|
+
var init_install_skill = __esm(() => {
|
|
8147
|
+
SKILL_FILES = ["SKILL.md", "core.md", "cli.md", "advanced.md"];
|
|
8148
|
+
});
|
|
8149
|
+
|
|
8043
8150
|
// tools/tutuca.js
|
|
8044
8151
|
init__registry();
|
|
8045
8152
|
|
|
8046
8153
|
// tools/cli/commands/help.js
|
|
8047
|
-
var
|
|
8154
|
+
var exports_help = {};
|
|
8155
|
+
__export(exports_help, {
|
|
8156
|
+
run: () => run2,
|
|
8157
|
+
describe: () => describe2
|
|
8158
|
+
});
|
|
8159
|
+
var describe2 = "Show usage. `help <command>` for per-command detail.";
|
|
8048
8160
|
var OVERVIEW = `tutuca — CLI for inspecting, documenting, linting and rendering tutuca
|
|
8049
8161
|
components defined in an ES module.
|
|
8050
8162
|
|
|
@@ -8122,6 +8234,11 @@ COMMANDS (no module required)
|
|
|
8122
8234
|
Without [command]: prints this full reference.
|
|
8123
8235
|
With [command]: prints that command's one-line description.
|
|
8124
8236
|
|
|
8237
|
+
install-skill [--user | --project] [--force]
|
|
8238
|
+
Copy the bundled Claude Code skill (SKILL.md + core/cli/advanced.md)
|
|
8239
|
+
into .claude/skills/tutuca/. Default scope is --project (cwd);
|
|
8240
|
+
--user installs at ~/.claude/skills/tutuca/. --force overwrites.
|
|
8241
|
+
|
|
8125
8242
|
GLOBAL FLAGS
|
|
8126
8243
|
-f, --format <cli|md|json|html>
|
|
8127
8244
|
Output format. Defaults per command:
|
|
@@ -8163,19 +8280,22 @@ EXAMPLES
|
|
|
8163
8280
|
# CI smoke test
|
|
8164
8281
|
tutuca ./src/components.js doctor
|
|
8165
8282
|
`;
|
|
8166
|
-
async function
|
|
8283
|
+
async function run2(argv) {
|
|
8167
8284
|
const target = argv?.[0];
|
|
8168
8285
|
if (!target) {
|
|
8169
8286
|
process.stdout.write(OVERVIEW);
|
|
8170
8287
|
return;
|
|
8171
8288
|
}
|
|
8172
8289
|
if (target === "help") {
|
|
8173
|
-
process.stdout.write(`help: ${
|
|
8290
|
+
process.stdout.write(`help: ${describe2}
|
|
8174
8291
|
`);
|
|
8175
8292
|
return;
|
|
8176
8293
|
}
|
|
8177
8294
|
const { COMMANDS: COMMANDS2 } = await Promise.resolve().then(() => (init__registry(), exports__registry));
|
|
8178
|
-
const
|
|
8295
|
+
const noModule = {
|
|
8296
|
+
"install-skill": await Promise.resolve().then(() => (init_install_skill(), exports_install_skill))
|
|
8297
|
+
};
|
|
8298
|
+
const cmd = COMMANDS2[target] ?? noModule[target];
|
|
8179
8299
|
if (!cmd) {
|
|
8180
8300
|
process.stderr.write(`tutuca: unknown command: ${target}
|
|
8181
8301
|
`);
|
|
@@ -8187,8 +8307,11 @@ async function run(argv) {
|
|
|
8187
8307
|
process.stdout.write("Run `tutuca help` for the full reference including signatures and flags.\n");
|
|
8188
8308
|
}
|
|
8189
8309
|
|
|
8310
|
+
// tools/tutuca.js
|
|
8311
|
+
init_install_skill();
|
|
8312
|
+
|
|
8190
8313
|
// tools/cli/with-module.js
|
|
8191
|
-
import { parseArgs } from "node:util";
|
|
8314
|
+
import { parseArgs as parseArgs2 } from "node:util";
|
|
8192
8315
|
|
|
8193
8316
|
// tools/cli/env.js
|
|
8194
8317
|
init_anode();
|
|
@@ -8218,16 +8341,16 @@ async function createNodeEnv() {
|
|
|
8218
8341
|
}
|
|
8219
8342
|
|
|
8220
8343
|
// tools/cli/load.js
|
|
8221
|
-
import { resolve } from "node:path";
|
|
8344
|
+
import { resolve as resolve2 } from "node:path";
|
|
8222
8345
|
async function loadAndNormalize(modulePath) {
|
|
8223
|
-
const abs =
|
|
8346
|
+
const abs = resolve2(modulePath);
|
|
8224
8347
|
const mod = await import(abs);
|
|
8225
8348
|
const { normalized } = normalizeModule(mod, { path: abs });
|
|
8226
8349
|
return normalized;
|
|
8227
8350
|
}
|
|
8228
8351
|
|
|
8229
8352
|
// tools/cli/output.js
|
|
8230
|
-
import { writeFileSync } from "node:fs";
|
|
8353
|
+
import { writeFileSync as writeFileSync2 } from "node:fs";
|
|
8231
8354
|
|
|
8232
8355
|
// tools/format/cli.js
|
|
8233
8356
|
var exports_cli = {};
|
|
@@ -8619,7 +8742,7 @@ async function formatResult(formatName, result, options = {}) {
|
|
|
8619
8742
|
async function emit(result, { format: format5, pretty, output }) {
|
|
8620
8743
|
const text = await formatResult(format5, result, { pretty });
|
|
8621
8744
|
if (output) {
|
|
8622
|
-
|
|
8745
|
+
writeFileSync2(output, text);
|
|
8623
8746
|
} else {
|
|
8624
8747
|
process.stdout.write(text);
|
|
8625
8748
|
if (!text.endsWith(`
|
|
@@ -8631,7 +8754,7 @@ async function emit(result, { format: format5, pretty, output }) {
|
|
|
8631
8754
|
|
|
8632
8755
|
// tools/cli/with-module.js
|
|
8633
8756
|
async function runCommand(cmd, argv, globalOpts) {
|
|
8634
|
-
const parsed =
|
|
8757
|
+
const parsed = parseArgs2({
|
|
8635
8758
|
args: argv,
|
|
8636
8759
|
options: cmd.parseOptions ?? {},
|
|
8637
8760
|
allowPositionals: true
|
|
@@ -8652,6 +8775,10 @@ async function runCommand(cmd, argv, globalOpts) {
|
|
|
8652
8775
|
}
|
|
8653
8776
|
|
|
8654
8777
|
// tools/tutuca.js
|
|
8778
|
+
var NO_MODULE_COMMANDS = {
|
|
8779
|
+
help: exports_help,
|
|
8780
|
+
"install-skill": exports_install_skill
|
|
8781
|
+
};
|
|
8655
8782
|
function usageError(msg) {
|
|
8656
8783
|
process.stderr.write(`tutuca: ${msg}
|
|
8657
8784
|
Run \`tutuca help\` for usage.
|
|
@@ -8688,13 +8815,13 @@ function extractGlobals(argv) {
|
|
|
8688
8815
|
async function main() {
|
|
8689
8816
|
const { opts, rest } = extractGlobals(process.argv.slice(2));
|
|
8690
8817
|
if (rest.length === 0 || opts.help && rest.length === 0) {
|
|
8691
|
-
await
|
|
8818
|
+
await run2([], opts);
|
|
8692
8819
|
return;
|
|
8693
8820
|
}
|
|
8694
8821
|
let command;
|
|
8695
8822
|
let commandArgs;
|
|
8696
|
-
if (rest[0]
|
|
8697
|
-
command =
|
|
8823
|
+
if (NO_MODULE_COMMANDS[rest[0]]) {
|
|
8824
|
+
command = rest[0];
|
|
8698
8825
|
commandArgs = rest.slice(1);
|
|
8699
8826
|
} else if (opts.module) {
|
|
8700
8827
|
command = rest[0];
|
|
@@ -8706,12 +8833,13 @@ async function main() {
|
|
|
8706
8833
|
command = rest[1];
|
|
8707
8834
|
commandArgs = rest.slice(2);
|
|
8708
8835
|
}
|
|
8709
|
-
if (
|
|
8710
|
-
|
|
8836
|
+
if (NO_MODULE_COMMANDS[command]) {
|
|
8837
|
+
const args = opts.help ? [...commandArgs, "--help"] : commandArgs;
|
|
8838
|
+
await NO_MODULE_COMMANDS[command].run(args, opts);
|
|
8711
8839
|
return;
|
|
8712
8840
|
}
|
|
8713
|
-
if (
|
|
8714
|
-
await
|
|
8841
|
+
if (opts.help) {
|
|
8842
|
+
await run2([command], opts);
|
|
8715
8843
|
return;
|
|
8716
8844
|
}
|
|
8717
8845
|
const cmd = COMMANDS[command];
|
package/dist/tutuca-dev.js
CHANGED
|
@@ -1005,7 +1005,20 @@ class ANode extends BaseNode {
|
|
|
1005
1005
|
return this.val.toPathItem();
|
|
1006
1006
|
}
|
|
1007
1007
|
static parse(html, px) {
|
|
1008
|
-
|
|
1008
|
+
const nodes = px.parseHTML(html);
|
|
1009
|
+
if (nodes.length === 0)
|
|
1010
|
+
return new TextNode("");
|
|
1011
|
+
if (nodes.length === 1)
|
|
1012
|
+
return ANode.fromDOM(nodes[0], px);
|
|
1013
|
+
const childs = new Array(nodes.length);
|
|
1014
|
+
for (let i = 0;i < nodes.length; i++)
|
|
1015
|
+
childs[i] = ANode.fromDOM(nodes[i], px);
|
|
1016
|
+
const trimmed = condenseChildsWhites(childs);
|
|
1017
|
+
if (trimmed.length === 0)
|
|
1018
|
+
return new TextNode("");
|
|
1019
|
+
if (trimmed.length === 1)
|
|
1020
|
+
return trimmed[0];
|
|
1021
|
+
return new FragmentNode(trimmed);
|
|
1009
1022
|
}
|
|
1010
1023
|
static fromDOM(node, px) {
|
|
1011
1024
|
if (node instanceof px.Text)
|
|
@@ -1025,10 +1038,8 @@ class ANode extends BaseNode {
|
|
|
1025
1038
|
switch (name) {
|
|
1026
1039
|
case "slot":
|
|
1027
1040
|
return new SlotNode(null, vp.const(value), maybeFragment(childs));
|
|
1028
|
-
case "text":
|
|
1029
|
-
|
|
1030
|
-
return v !== null ? new RenderTextNode(null, v) : null;
|
|
1031
|
-
}
|
|
1041
|
+
case "text":
|
|
1042
|
+
return px.addNodeIf(RenderTextNode, vp.parseText(value, px));
|
|
1032
1043
|
case "render":
|
|
1033
1044
|
return px.addNodeIf(RenderNode, vp.parseRender(value, px), as);
|
|
1034
1045
|
case "render-it":
|
|
@@ -1320,7 +1331,7 @@ class ParseContext {
|
|
|
1320
1331
|
parseHTML(html) {
|
|
1321
1332
|
const t = this.document.createElement("template");
|
|
1322
1333
|
t.innerHTML = html;
|
|
1323
|
-
return
|
|
1334
|
+
return t.content.childNodes;
|
|
1324
1335
|
}
|
|
1325
1336
|
addNodeIf(Class, val, extra) {
|
|
1326
1337
|
if (val !== null) {
|
|
@@ -1597,7 +1608,10 @@ function checkMacroCallArgs(lx, view, Comp) {
|
|
|
1597
1608
|
const { defaults } = macro;
|
|
1598
1609
|
for (const argName in macroNode.attrs) {
|
|
1599
1610
|
if (!(argName in defaults)) {
|
|
1600
|
-
lx.error(UNKNOWN_MACRO_ARG, {
|
|
1611
|
+
lx.error(UNKNOWN_MACRO_ARG, {
|
|
1612
|
+
name: argName,
|
|
1613
|
+
macroName: macroNode.name
|
|
1614
|
+
});
|
|
1601
1615
|
}
|
|
1602
1616
|
}
|
|
1603
1617
|
}
|
|
@@ -1779,7 +1793,7 @@ function checkConsistentAttrVal(lx, val, fields, proto, computed, scope, alter,
|
|
|
1779
1793
|
if (alter[val.name] === undefined) {
|
|
1780
1794
|
lx.error(ALT_HANDLER_NOT_DEFINED, { name: val.name });
|
|
1781
1795
|
}
|
|
1782
|
-
} else if (valName !== "ConstVal" && valName !== "BindVal") {
|
|
1796
|
+
} else if (valName !== "ConstVal" && valName !== "BindVal" && valName !== "DynVal") {
|
|
1783
1797
|
console.log(val);
|
|
1784
1798
|
}
|
|
1785
1799
|
}
|
|
@@ -2117,7 +2131,11 @@ class ComponentStack {
|
|
|
2117
2131
|
}
|
|
2118
2132
|
}
|
|
2119
2133
|
registerMacros(macros) {
|
|
2120
|
-
|
|
2134
|
+
for (const key in macros) {
|
|
2135
|
+
const lower = key.toLowerCase();
|
|
2136
|
+
console.assert(this.macros[lower] === undefined, "macro key collision", lower);
|
|
2137
|
+
this.macros[lower] = macros[key];
|
|
2138
|
+
}
|
|
2121
2139
|
}
|
|
2122
2140
|
getCompFor(v) {
|
|
2123
2141
|
return this.comps.getCompFor(v);
|
|
@@ -8068,7 +8086,7 @@ class ClassBuilder {
|
|
|
8068
8086
|
return field;
|
|
8069
8087
|
}
|
|
8070
8088
|
}
|
|
8071
|
-
var
|
|
8089
|
+
var FIELD_CLASS = Symbol.for("tutuca.fieldClass");
|
|
8072
8090
|
var fieldsByTypeName = {
|
|
8073
8091
|
text: FieldString,
|
|
8074
8092
|
int: FieldInt,
|
|
@@ -8105,7 +8123,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
|
|
|
8105
8123
|
else if (Map2.isMap(value) || value?.constructor === Object)
|
|
8106
8124
|
b.addField(field, Map2(value), FieldMap);
|
|
8107
8125
|
else {
|
|
8108
|
-
const Field2 =
|
|
8126
|
+
const Field2 = value?.[FIELD_CLASS] ?? FieldAny;
|
|
8109
8127
|
b.addField(field, value, Field2);
|
|
8110
8128
|
}
|
|
8111
8129
|
}
|
|
@@ -8126,7 +8144,7 @@ class Renderer {
|
|
|
8126
8144
|
this.cache = new WeakMapDomCache;
|
|
8127
8145
|
}
|
|
8128
8146
|
getSeqInfo(seq) {
|
|
8129
|
-
return isIndexed(seq) ? imIndexedIter : isKeyed(seq) ? imKeyedIter :
|
|
8147
|
+
return isIndexed(seq) ? imIndexedIter : isKeyed(seq) ? imKeyedIter : seq?.[SEQ_INFO] ?? unkIter;
|
|
8130
8148
|
}
|
|
8131
8149
|
renderTag(tag, attrs, childs) {
|
|
8132
8150
|
return h(tag, attrs, childs);
|
|
@@ -8245,7 +8263,7 @@ var imKeyedIter = (seq, visit) => {
|
|
|
8245
8263
|
visit(k, v, "sk");
|
|
8246
8264
|
};
|
|
8247
8265
|
var unkIter = () => {};
|
|
8248
|
-
var
|
|
8266
|
+
var SEQ_INFO = Symbol.for("tutuca.seqInfo");
|
|
8249
8267
|
|
|
8250
8268
|
// extra/klist.js
|
|
8251
8269
|
class KList {
|
|
@@ -8337,11 +8355,11 @@ class FieldKList extends Field {
|
|
|
8337
8355
|
};
|
|
8338
8356
|
}
|
|
8339
8357
|
}
|
|
8340
|
-
|
|
8341
|
-
|
|
8358
|
+
KList.prototype[FIELD_CLASS] = FieldKList;
|
|
8359
|
+
KList.prototype[SEQ_INFO] = (seq, visit) => {
|
|
8342
8360
|
for (const k of seq.order)
|
|
8343
8361
|
visit(k, seq.items.get(k), "data-sk");
|
|
8344
|
-
}
|
|
8362
|
+
};
|
|
8345
8363
|
// index.js
|
|
8346
8364
|
var css = String.raw;
|
|
8347
8365
|
var html = String.raw;
|
|
@@ -8627,7 +8645,6 @@ export {
|
|
|
8627
8645
|
tutuca,
|
|
8628
8646
|
setIn$1 as setIn,
|
|
8629
8647
|
set,
|
|
8630
|
-
seqInfoByClass,
|
|
8631
8648
|
removeIn,
|
|
8632
8649
|
remove,
|
|
8633
8650
|
mergeWith$1 as mergeWith,
|
|
@@ -8664,7 +8681,6 @@ export {
|
|
|
8664
8681
|
getComponentsDocs,
|
|
8665
8682
|
get,
|
|
8666
8683
|
fromJS,
|
|
8667
|
-
fieldsByClass,
|
|
8668
8684
|
docComponents,
|
|
8669
8685
|
css,
|
|
8670
8686
|
component,
|
|
@@ -8680,6 +8696,7 @@ export {
|
|
|
8680
8696
|
Stack2 as Stack,
|
|
8681
8697
|
Set2 as Set,
|
|
8682
8698
|
Seq,
|
|
8699
|
+
SEQ_INFO,
|
|
8683
8700
|
Repeat,
|
|
8684
8701
|
Record,
|
|
8685
8702
|
Range,
|
|
@@ -8703,6 +8720,7 @@ export {
|
|
|
8703
8720
|
INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD,
|
|
8704
8721
|
Map2 as IMap,
|
|
8705
8722
|
FIELD_VAL_NOT_DEFINED,
|
|
8723
|
+
FIELD_CLASS,
|
|
8706
8724
|
DUPLICATE_ATTR_DEFINITION,
|
|
8707
8725
|
Collection,
|
|
8708
8726
|
COMPUTED_VAL_NOT_DEFINED,
|