tutuca 0.9.66 → 0.9.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tutuca-cli.js +76 -44
- package/dist/tutuca-dev.ext.js +81 -46
- package/dist/tutuca-dev.js +69 -42
- package/dist/tutuca-dev.min.js +2 -2
- package/dist/tutuca-extra.ext.js +48 -42
- package/dist/tutuca-extra.js +46 -42
- package/dist/tutuca-extra.min.js +2 -2
- package/dist/tutuca.ext.js +46 -42
- package/dist/tutuca.js +46 -42
- package/dist/tutuca.min.js +2 -2
- package/package.json +1 -1
- package/skill/tutuca/core.md +10 -2
- package/skill/tutuca/testing.md +3 -2
- package/skill/tutuca-source/SKILL.md +33 -0
- package/skill/tutuca-source/tutuca.ext.js +3828 -0
- package/skill/SKILL.md +0 -46
- package/skill/advanced.md +0 -146
- package/skill/cli.md +0 -117
- package/skill/core.md +0 -793
package/skill/SKILL.md
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: tutuca
|
|
3
|
-
description: Authoring or reviewing tutuca components, html`` views, macros, or running the `tutuca` CLI. Covers field types, @-directives, bubble/receive/response handlers, and the post-edit `tutuca <module> lint` + `tutuca <module> render --title …` verification recipe.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Tutuca
|
|
7
|
-
|
|
8
|
-
Tutuca is an immutable-state SPA framework: components have typed
|
|
9
|
-
`fields`, auto-generated mutators (`setX`, `pushInX`, …), HTML-template
|
|
10
|
-
`view`s with `@`-prefixed directives, and `bubble` / `receive` /
|
|
11
|
-
`response` handlers for orchestration.
|
|
12
|
-
|
|
13
|
-
## Verifying changes
|
|
14
|
-
|
|
15
|
-
After editing a tutuca module, run two checks before declaring the edit
|
|
16
|
-
done:
|
|
17
|
-
|
|
18
|
-
1. **Lint** — catches undefined fields/handlers/macros/events. Exits
|
|
19
|
-
`2` on any error-level finding.
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
tutuca <module-path> lint
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
2. **Render the example that exercises the feature you changed** —
|
|
26
|
-
confirms the component mounts in a headless DOM with the new
|
|
27
|
-
behavior. Exits `3` on render crash.
|
|
28
|
-
|
|
29
|
-
```sh
|
|
30
|
-
tutuca <module-path> render --title "<example title>"
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
If no example covers the feature, add one to `getExamples()` first —
|
|
34
|
-
that's how the feature becomes verifiable.
|
|
35
|
-
|
|
36
|
-
## Routing
|
|
37
|
-
|
|
38
|
-
| Task | File |
|
|
39
|
-
| ---------------------------------------------------------------------------------------------- | ------------------------------- |
|
|
40
|
-
| Authoring `component({...})`, `html\`...\`` views, macros, fields, events, lists, styles | [core.md](./core.md) |
|
|
41
|
-
| CLI commands, flags, exit codes, full linter rule list | [cli.md](./cli.md) |
|
|
42
|
-
| Drag & drop, dynamic bindings (`*x`), pseudo-`x`, custom seq types, Tailwind/MargaUI | [advanced.md](./advanced.md) |
|
|
43
|
-
|
|
44
|
-
Read `core.md` first. Reach for `cli.md` or `advanced.md` only when the
|
|
45
|
-
task touches them — both files are referenced inline from `core.md` so
|
|
46
|
-
you'll be pointed there when relevant.
|
package/skill/advanced.md
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# Tutuca — Advanced Topics
|
|
2
|
-
|
|
3
|
-
Reach this file only when the task touches drag & drop, context-style
|
|
4
|
-
"dynamic bindings", pseudo-`x` (the `<x>`-stripping workaround inside
|
|
5
|
-
`<select>`/`<table>`/`<tr>`), registering a custom seq type, or
|
|
6
|
-
compiling Tailwind / MargaUI classes. For everything else, `core.md`
|
|
7
|
-
is the right place.
|
|
8
|
-
|
|
9
|
-
## Drag and Drop
|
|
10
|
-
|
|
11
|
-
```html
|
|
12
|
-
<div
|
|
13
|
-
@each=".items"
|
|
14
|
-
draggable="true"
|
|
15
|
-
data-dragtype="my-item"
|
|
16
|
-
data-droptarget="my-item"
|
|
17
|
-
@on.drop="onDrop @key dragInfo event"
|
|
18
|
-
></div>
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
```js
|
|
22
|
-
input: {
|
|
23
|
-
onDrop(targetKey, dragInfo, e) {
|
|
24
|
-
const sourceKey = dragInfo.lookupBind("key"); // any bind from source render
|
|
25
|
-
return this.setItems(this.items.moveKeyBeforeKey(sourceKey, targetKey));
|
|
26
|
-
},
|
|
27
|
-
}
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Tutuca auto-manages two attrs during a drag — style them with CSS:
|
|
31
|
-
|
|
32
|
-
```css
|
|
33
|
-
[data-dragging="1"] {
|
|
34
|
-
opacity: 0.5;
|
|
35
|
-
}
|
|
36
|
-
[data-draggingover="my-item"] {
|
|
37
|
-
outline: 1px dashed;
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Touch is wired up too (drag fires after a small move threshold).
|
|
42
|
-
|
|
43
|
-
## Dynamic Bindings
|
|
44
|
-
|
|
45
|
-
For passing values "context-style" through nested components without prop
|
|
46
|
-
drilling. Define on the producer; alias on consumers; resolve as `*name`.
|
|
47
|
-
|
|
48
|
-
```js
|
|
49
|
-
const Theme = component({
|
|
50
|
-
name: "Theme",
|
|
51
|
-
fields: { color: "blue" },
|
|
52
|
-
dynamic: { color: ".color" },
|
|
53
|
-
on: {
|
|
54
|
-
stackEnter() {
|
|
55
|
-
return ["color"];
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
const Child = component({
|
|
60
|
-
dynamic: { color: { for: "Theme.color", default: "'gray'" } },
|
|
61
|
-
view: html`<p :style="color: {*color}"></p>`,
|
|
62
|
-
});
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
`on.stackEnter()` is required only on the **producer** (the component
|
|
66
|
-
declaring `dynamic: { name: ".field" }` to expose a value). It returns
|
|
67
|
-
the list of dynamic-binding names this component pushes onto the stack
|
|
68
|
-
when entering its render. Consumers (which only alias via
|
|
69
|
-
`{ for: "Producer.name", default: ... }`) don't need it.
|
|
70
|
-
|
|
71
|
-
## Pseudo-`x` (`@x`)
|
|
72
|
-
|
|
73
|
-
Tutuca's special operations (`render`, `render-it`, `render-each`, `text`,
|
|
74
|
-
`show`, `hide`, `slot`) live on the `<x>` tag. That works almost
|
|
75
|
-
everywhere, but the browser's HTML parser refuses to keep `<x>` (or any
|
|
76
|
-
unknown tag) as a child of certain elements: `<select>` only allows
|
|
77
|
-
`<option>` / `<optgroup>`, `<table>` only allows `<thead>` / `<tbody>` /
|
|
78
|
-
`<tr>`, `<tr>` only allows `<th>` / `<td>`, etc. Drop `<x render-each>`
|
|
79
|
-
inside one of those and the parser silently strips it.
|
|
80
|
-
|
|
81
|
-
The escape hatch: prefix the **first** attribute on a *legal* tag with
|
|
82
|
-
`@x`. Tutuca treats that tag as if it were `<x>` and reads the next
|
|
83
|
-
attribute as the special op.
|
|
84
|
-
|
|
85
|
-
```html
|
|
86
|
-
<!-- ❌ <x> stripped by the HTML parser inside <select> -->
|
|
87
|
-
<select>
|
|
88
|
-
<x render-each=".items" as="option"></x>
|
|
89
|
-
</select>
|
|
90
|
-
|
|
91
|
-
<!-- ✅ pseudo-x: <option @x render-each=".items" as="option"> -->
|
|
92
|
-
<select>
|
|
93
|
-
<option @x render-each=".items" as="option"></option>
|
|
94
|
-
</select>
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Notes:
|
|
98
|
-
|
|
99
|
-
- `@x` must be the **first** attribute; the special op (`render-each`,
|
|
100
|
-
`render`, `text`, `show`, ...) is the second.
|
|
101
|
-
- The host tag (here `<option>`) is otherwise ignored — only the special
|
|
102
|
-
op runs. Tutuca produces the rendered children directly.
|
|
103
|
-
- Same trick works inside `<tr>`, `<table>`, `<colgroup>`, `<dl>`,
|
|
104
|
-
`<details>`, or anywhere else the parser would discard `<x>`.
|
|
105
|
-
|
|
106
|
-
## Registering a custom seq type
|
|
107
|
-
|
|
108
|
-
To make `@each` recognize your own collection class, install a
|
|
109
|
-
`SEQ_INFO` walker on its prototype:
|
|
110
|
-
|
|
111
|
-
```js
|
|
112
|
-
import { SEQ_INFO } from "tutuca";
|
|
113
|
-
|
|
114
|
-
class MyClass {
|
|
115
|
-
// ...
|
|
116
|
-
}
|
|
117
|
-
MyClass.prototype[SEQ_INFO] = (seq, visit) => {
|
|
118
|
-
for (const [k, v] of seq.entries()) visit(k, v, "data-sk");
|
|
119
|
-
};
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
`SEQ_INFO` is `Symbol.for("tutuca.seqInfo")`, so the same identity
|
|
123
|
-
is shared across module graphs (source vs. bundled tutuca). The
|
|
124
|
-
renderer reads `seq[SEQ_INFO]` directly (no `.constructor` lookup),
|
|
125
|
-
which is why the walker goes on the prototype, not as a static.
|
|
126
|
-
|
|
127
|
-
The third arg to `visit` is the data attribute used for stable-key
|
|
128
|
-
diffing (typically `"data-sk"` for "sequence key").
|
|
129
|
-
|
|
130
|
-
## Tailwind / MargaUI Class Compilation (extra build)
|
|
131
|
-
|
|
132
|
-
```js
|
|
133
|
-
import { compileClassesToStyleText, injectCss, tutuca } from "tutuca/extra";
|
|
134
|
-
import { compile } from "https://esm.sh/margaui";
|
|
135
|
-
|
|
136
|
-
const app = tutuca("#app");
|
|
137
|
-
app.registerComponents([Comp]);
|
|
138
|
-
const css = await compileClassesToStyleText(app, compile);
|
|
139
|
-
injectCss("myapp", css);
|
|
140
|
-
app.start();
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
`compileClassesToStyleText` walks every registered component's templates,
|
|
144
|
-
collects the `class=` and `:class=` literals, hands them to a `compile`
|
|
145
|
-
function (any margaui-compatible signature), and returns CSS text. Pair
|
|
146
|
-
with `injectCss(scopeName, css)` to install the result before `start()`.
|
package/skill/cli.md
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# Tutuca CLI Reference
|
|
2
|
-
|
|
3
|
-
The `tutuca` CLI inspects, documents, lints, and renders any module that
|
|
4
|
-
follows the *Conventional Module Exports* shape (see `core.md`). Reach
|
|
5
|
-
this file when you need command/flag/exit-code details, or when reading
|
|
6
|
-
a lint code out of `lint` output. Otherwise the post-edit recipe in
|
|
7
|
-
`core.md` (run `lint`, then `render --title "<your example>"`) is
|
|
8
|
-
enough.
|
|
9
|
-
|
|
10
|
-
## Install / invoke
|
|
11
|
-
|
|
12
|
-
```sh
|
|
13
|
-
# project local
|
|
14
|
-
npm i --save-dev tutuca
|
|
15
|
-
npx tutuca <module-path> <command> [name] [flags]
|
|
16
|
-
|
|
17
|
-
# global
|
|
18
|
-
npm i -g tutuca
|
|
19
|
-
tutuca <module-path> <command> [name] [flags]
|
|
20
|
-
|
|
21
|
-
# from a checkout of this repo
|
|
22
|
-
bun tools/tutuca.js <module-path> <command> [name] [flags]
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
The module path comes **first**, the command second, an optional component
|
|
26
|
-
name third. `tutuca help` prints the full reference; `tutuca help <command>`
|
|
27
|
-
prints a one-liner. `tutuca` ↔ `tutuca -h` prints overview.
|
|
28
|
-
|
|
29
|
-
## Commands
|
|
30
|
-
|
|
31
|
-
| Command | Purpose |
|
|
32
|
-
| --------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
33
|
-
| `info` | Summarize which `getX()` exports are present and counts |
|
|
34
|
-
| `list` | List components with their views and fields (name + type) |
|
|
35
|
-
| `examples` | Print `getExamples()` content (title, items, per section) |
|
|
36
|
-
| `docs [name]` | Generate API docs (methods, input handlers, fields with auto-generated accessors) — all or one |
|
|
37
|
-
| `lint [name]` | Run the linter; exits **2** on any error-level finding |
|
|
38
|
-
| `render [name]` | Render examples to HTML in a headless DOM. Filter by component name or `--title`/`--view`. Exits **3** on render crash |
|
|
39
|
-
| `help [cmd]` | Show usage; the only command that does **not** need a module path |
|
|
40
|
-
|
|
41
|
-
## Global flags
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
-
-f, --format <cli|md|json|html> output format
|
|
45
|
-
defaults: info/list/examples/lint → cli
|
|
46
|
-
docs/render → md
|
|
47
|
-
html only valid for render
|
|
48
|
-
json works for every command
|
|
49
|
-
-o, --output <file> write to file instead of stdout
|
|
50
|
-
--pretty pretty-print HTML (md/html) via prettier;
|
|
51
|
-
JSON formatter uses indent 2
|
|
52
|
-
--module <path> alternative to first-positional module path
|
|
53
|
-
-h, --help show help (overview, or for one command)
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Exit codes
|
|
57
|
-
|
|
58
|
-
| Code | Meaning |
|
|
59
|
-
| ---- | -------------------------------------------------------- |
|
|
60
|
-
| `0` | success |
|
|
61
|
-
| `1` | usage error (bad args, missing module, bad module shape) |
|
|
62
|
-
| `2` | lint findings at error level |
|
|
63
|
-
| `3` | render crash |
|
|
64
|
-
|
|
65
|
-
## Examples
|
|
66
|
-
|
|
67
|
-
```sh
|
|
68
|
-
tutuca ./src/components.js info # quick overview
|
|
69
|
-
tutuca ./src/components.js list # components, views, fields
|
|
70
|
-
tutuca ./src/components.js docs Button -f json # one component, JSON
|
|
71
|
-
tutuca ./src/components.js render -f html --pretty -o out/examples.html
|
|
72
|
-
tutuca ./src/components.js render Button --title "Disabled state"
|
|
73
|
-
|
|
74
|
-
# Post-edit verification: lint, then render the example for the feature
|
|
75
|
-
# you just changed (add the example first if none covers it). Add
|
|
76
|
-
# --pretty when you need to read the HTML to verify structure.
|
|
77
|
-
tutuca ./src/components.js lint
|
|
78
|
-
tutuca ./src/components.js render --title "Disabled state"
|
|
79
|
-
tutuca ./src/components.js render --title "Disabled state" --pretty
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Linter Rules
|
|
83
|
-
|
|
84
|
-
Codes emitted by `lint`. Source: `tools/core/lint-check.js`.
|
|
85
|
-
|
|
86
|
-
### Field references
|
|
87
|
-
|
|
88
|
-
- `FIELD_VAL_NOT_DEFINED` — `.field` not declared in `fields`.
|
|
89
|
-
|
|
90
|
-
### Input-handler / method confusion
|
|
91
|
-
|
|
92
|
-
- `INPUT_HANDLER_NOT_IMPLEMENTED` — bare handler name not in `input`.
|
|
93
|
-
- `INPUT_HANDLER_NOT_REFERENCED` — `input` entry never used.
|
|
94
|
-
- `INPUT_HANDLER_METHOD_NOT_IMPLEMENTED` — `.handler` not in `methods`.
|
|
95
|
-
- `INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD` — bare name resolves to `methods` (use `.name`).
|
|
96
|
-
- `INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER` — `.name` resolves to `input` (drop the dot).
|
|
97
|
-
|
|
98
|
-
### Iteration helpers (`alter`)
|
|
99
|
-
|
|
100
|
-
- `ALT_HANDLER_NOT_DEFINED` — `@when` / `@enrich-with` / `@loop-with` name not in `alter`.
|
|
101
|
-
- `ALT_HANDLER_NOT_REFERENCED` — `alter` entry never used.
|
|
102
|
-
|
|
103
|
-
### Templates / events
|
|
104
|
-
|
|
105
|
-
- `RENDER_IT_OUTSIDE_OF_LOOP` — `<x render-it>` outside `@each` / `render-each`.
|
|
106
|
-
- `UNKNOWN_EVENT_MODIFIER` — `+mod` not in the recognized modifier set.
|
|
107
|
-
- `UNKNOWN_HANDLER_ARG_NAME` — handler arg name not a built-in / declared component.
|
|
108
|
-
- `DUPLICATE_ATTR_DEFINITION` — same attr set by literal + `:attr` + `@if.attr` on one element.
|
|
109
|
-
- `UNKNOWN_DIRECTIVE` — `@name` directive not recognized (typo or unsupported).
|
|
110
|
-
- `UNKNOWN_X_OP` — first attribute on `<x>` (or pseudo-`@x`) is not a known op.
|
|
111
|
-
- `UNKNOWN_X_ATTR` — extra attribute on `<x op>` not consumed by the op and not a known wrapper (`show`/`hide`).
|
|
112
|
-
|
|
113
|
-
### Names registered with the app
|
|
114
|
-
|
|
115
|
-
- `UNKNOWN_REQUEST_NAME` — `!name` not registered.
|
|
116
|
-
- `UNKNOWN_COMPONENT_NAME` — component type not registered.
|
|
117
|
-
- `UNKNOWN_MACRO_ARG` — macro attr not declared in defaults.
|