kopular 1.1.1 → 1.1.3
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/GUIDE.md +43 -6
- package/package.json +1 -1
package/GUIDE.md
CHANGED
|
@@ -27,8 +27,12 @@ both scripts). `ks check src/app.ks` type-checks without building, if you just w
|
|
|
27
27
|
- No implicit `this` — every member reference is `this.Field`/`this.Method()`, always,
|
|
28
28
|
including inside a lambda.
|
|
29
29
|
- `if`/`else`/`while`/`for`/`foreach (Type x in xs)` — all statements, no ternary. Use
|
|
30
|
-
`match` for a conditional value: `match x {
|
|
31
|
-
|
|
30
|
+
`match` for a conditional value: `match x { "a" => "one", _ => "other" }`. **The subject
|
|
31
|
+
must be `string` or an `enum` — never `bool`/`number`/anything else, and every pattern
|
|
32
|
+
must be a string literal (or, for an enum subject, an `Enum.Member` name) — not a number,
|
|
33
|
+
not `true`/`false`.** The `_` arm is required unless every case is covered (only possible
|
|
34
|
+
for an enum subject, by naming every member). For a `bool`, use `if`/`else` instead —
|
|
35
|
+
there's no equivalent shorthand.
|
|
32
36
|
- Lambdas need explicit parameter types: `(number x) => x * 2`.
|
|
33
37
|
- Nullable: `string? name` — a nullable field forces `if (x != null) { ... }` before use;
|
|
34
38
|
narrowing is scoped to that `if` block, not reachability-based (an early
|
|
@@ -43,6 +47,18 @@ both scripts). `ks check src/app.ks` type-checks without building, if you just w
|
|
|
43
47
|
`.Slice(a, b)/.Concat(ys)/.Join(sep)/.Reduce(fn, initial)`.
|
|
44
48
|
- `x == null` / `x != null` also match `undefined` — a missed `Array.Find`, an absent
|
|
45
49
|
optional field, etc. all read as `null`.
|
|
50
|
+
- **No `.Match()`/`.Test()`/`.Exec()` on `string` — there is no direct regex-execute method
|
|
51
|
+
at all.** A regex literal (`r"^[a-z]+$"`) only means something as a `match` *pattern*.
|
|
52
|
+
The idiomatic way to classify or extract by character class is `.Split("")` (splits into
|
|
53
|
+
a `string[]` of single characters) plus `match` per character:
|
|
54
|
+
```ks
|
|
55
|
+
bool isLetter = match c { r"^[a-z]$" => true, _ => false };
|
|
56
|
+
```
|
|
57
|
+
Build up runs (words, tokens, ...) by iterating those characters and appending to an
|
|
58
|
+
accumulator string, flushing it whenever a non-matching character (or the end) is
|
|
59
|
+
reached — this covers tokenizing/extracting by character class without ever needing a
|
|
60
|
+
hand-written JS shim. Reach for a real shim (below) only for something a `match` pattern
|
|
61
|
+
genuinely can't express, like capturing a submatch.
|
|
46
62
|
- No object-literal syntax anywhere (`{ key: value }` doesn't exist as a value). A JS API
|
|
47
63
|
that needs one (rare — `fetch`'s options, `addEventListener`'s options object) needs a
|
|
48
64
|
small hand-written `.js` shim; Kopular's own `Http`/`FormField` cover the common cases so
|
|
@@ -68,10 +84,31 @@ need one: `this.SomeService.Count.Subscribe((v) => this.Update());` in the const
|
|
|
68
84
|
|
|
69
85
|
**Template bindings**: `{{ expr }}` text, `[prop]="expr"` (real fields for
|
|
70
86
|
`id`/`className`/`value`/`disabled`/`checked`; anything else is a plain attribute),
|
|
71
|
-
`(click)`/`(input)`/`(blur)`/`(change)` events,
|
|
72
|
-
(
|
|
73
|
-
|
|
74
|
-
|
|
87
|
+
`(click)`/`(input)`/`(blur)`/`(change)` events, `*if="expr"`, `*for="Type v of expr"`
|
|
88
|
+
(element type required, no inference), `*mount="expr"` (embeds a live child component,
|
|
89
|
+
composes with `*for`).
|
|
90
|
+
|
|
91
|
+
**Two-way binding, `[(value)]="Field"`** — `Field` can be a bare name, `this.Field`, or a
|
|
92
|
+
member path; it's assigned back directly (`Field = e.target.value`), so it must resolve
|
|
93
|
+
to something assignable, never a method call. **A `state<T>` field needs `.Value` on the
|
|
94
|
+
end** — `[(value)]="Qty.Value"`, not `[(value)]="Qty"` (a bare `state<T>` isn't itself a
|
|
95
|
+
`string`, so binding it directly is a type error):
|
|
96
|
+
```ks
|
|
97
|
+
public state<string> Qty;
|
|
98
|
+
constructor() : base() { this.Qty = state("1"); }
|
|
99
|
+
```
|
|
100
|
+
```html
|
|
101
|
+
<input [(value)]="Qty.Value" />
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Exactly one top-level element per template — no auto-wrapping, a hard compile error
|
|
105
|
+
otherwise.** Wrap multiple top-level pieces in one real container element:
|
|
106
|
+
```html
|
|
107
|
+
<div>
|
|
108
|
+
<input id="text" [(value)]="Draft" />
|
|
109
|
+
<button (click)="Submit()">Go</button>
|
|
110
|
+
</div>
|
|
111
|
+
```
|
|
75
112
|
|
|
76
113
|
**Hand-written `Render()`** (needed when logic is too dynamic for a template, or a template
|
|
77
114
|
would obscure more than it clarifies):
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kopular",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Kopular: a small component framework for KopScript — components, reactive state, constructor-injected services, routing, real compiled templates, and HTTP, with no DI container",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|