rip-lang 3.13.133 → 3.13.135
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 +0 -1
- package/README.md +4 -7
- package/bin/rip +16 -4
- package/docs/RIP-LANG.md +0 -42
- package/docs/RIP-TYPES.md +47 -52
- package/docs/demo.html +2 -2
- package/docs/dist/rip.js +2294 -1544
- package/docs/dist/rip.min.js +202 -192
- package/docs/dist/rip.min.js.br +0 -0
- package/package.json +1 -1
- package/rip-loader.js +2 -2
- package/src/AGENTS.md +76 -11
- package/src/browser.js +5 -5
- package/src/compiler.js +961 -639
- package/src/components.js +274 -109
- package/src/error.js +250 -0
- package/src/grammar/grammar.rip +2 -12
- package/src/lexer.js +15 -11
- package/src/parser.js +220 -223
- package/src/repl.js +3 -2
- package/src/sourcemap-utils.js +39 -6
- package/src/typecheck.js +312 -80
- package/src/types.js +229 -54
- package/src/ui.rip +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -115,7 +115,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
115
115
|
| `@rip-lang/x12` | 0.2.7 |
|
|
116
116
|
| `@rip-lang/schema` | 0.3.7 |
|
|
117
117
|
| `@rip-lang/swarm` | 1.2.17 |
|
|
118
|
-
| `@rip-lang/all` | 3.13.26 |
|
|
119
118
|
|
|
120
119
|
## [3.10.12] - 2026-02-20
|
|
121
120
|
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.13.
|
|
12
|
+
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.13.135-blue.svg" alt="Version"></a>
|
|
13
13
|
<a href="#zero-dependencies"><img src="https://img.shields.io/badge/dependencies-ZERO-brightgreen.svg" alt="Dependencies"></a>
|
|
14
14
|
<a href="#"><img src="https://img.shields.io/badge/tests-1%2C436%2F1%2C436-brightgreen.svg" alt="Tests"></a>
|
|
15
15
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
|
|
@@ -38,7 +38,7 @@ get '/users/:id' -> # RESTful API endpoint, comma-less
|
|
|
38
38
|
|
|
39
39
|
**What makes Rip different:**
|
|
40
40
|
- **Modern output** — ES2022 with native classes, `?.`, `??`, modules
|
|
41
|
-
- **New operators** — `!`,
|
|
41
|
+
- **New operators** — `!`, `//`, `%%`, `=~`, `|>`, `.new()`, and more
|
|
42
42
|
- **Reactive operators** — `:=`, `~=`, `~>` as language syntax
|
|
43
43
|
- **Optional types** — `::` annotations, `type` aliases, `.d.ts` emission
|
|
44
44
|
- **Zero dependencies** — everything included, even the parser generator
|
|
@@ -213,8 +213,6 @@ All use `globalThis` with `??=` — override any by redeclaring locally.
|
|
|
213
213
|
|----------|---------|--------------|
|
|
214
214
|
| `!` (dammit) | `fetchData!` | Calls AND awaits |
|
|
215
215
|
| `!` (void) | `def process!` | Suppresses implicit return |
|
|
216
|
-
| `!?` (otherwise) | `val !? 5` | Default only if `undefined` (infix) |
|
|
217
|
-
| `!?` (defined) | `val!?` | True if not `undefined` (postfix) |
|
|
218
216
|
| `?!` (presence) | `@checked?!` | True if truthy, else `undefined` (Houdini operator) |
|
|
219
217
|
| `?` (existence) | `x?` | True if `x != null` |
|
|
220
218
|
| `?:` (ternary) | `x > 0 ? 'yes' : 'no'` | JS-style ternary expression |
|
|
@@ -485,7 +483,7 @@ bun run build # Build browser bundle
|
|
|
485
483
|
## Release
|
|
486
484
|
|
|
487
485
|
```bash
|
|
488
|
-
# rip-lang + changed @rip-lang/* packages
|
|
486
|
+
# rip-lang + changed @rip-lang/* packages
|
|
489
487
|
bun run bump
|
|
490
488
|
|
|
491
489
|
# Explicit version level
|
|
@@ -495,8 +493,7 @@ bun run bump major
|
|
|
495
493
|
```
|
|
496
494
|
|
|
497
495
|
- `bun run bump` is the standard release flow for the npm ecosystem in this repo.
|
|
498
|
-
- It bumps `rip-lang`, bumps any changed publishable `@rip-lang/*` packages,
|
|
499
|
-
- `@rip-lang/all` is released automatically as part of that flow; there is no separate manual release step for it.
|
|
496
|
+
- It bumps `rip-lang`, bumps any changed publishable `@rip-lang/*` packages, runs the build and test steps, then commits, pushes, and publishes.
|
|
500
497
|
- `packages/vscode` is intentionally excluded and must be versioned and published separately.
|
|
501
498
|
|
|
502
499
|
---
|
package/bin/rip
CHANGED
|
@@ -4,7 +4,7 @@ import { readFileSync, readdirSync, writeFileSync, existsSync, statSync, unlinkS
|
|
|
4
4
|
import { execSync, spawnSync, spawn } from 'child_process';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import { dirname, basename, join } from 'path';
|
|
7
|
-
import { Compiler } from '../src/compiler.js';
|
|
7
|
+
import { Compiler, formatError } from '../src/compiler.js';
|
|
8
8
|
import packageJson from '../package.json' with { type: 'json' };
|
|
9
9
|
|
|
10
10
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -55,8 +55,13 @@ Options:
|
|
|
55
55
|
|
|
56
56
|
Subcommands:
|
|
57
57
|
rip check [dir] Type-check all .rip files in directory
|
|
58
|
+
rip check --strict [dir] Require type annotations in all .rip files
|
|
58
59
|
rip <name> [args] Run rip-<name> (repo bin/, node_modules, or PATH)
|
|
59
60
|
|
|
61
|
+
Configure via rip.json or package.json:
|
|
62
|
+
{ "strict": true, "exclude": ["scripts/**"] } # rip.json
|
|
63
|
+
{ "rip": { "strict": true, "exclude": ["scripts/**"] } } # package.json
|
|
64
|
+
|
|
60
65
|
Packages:
|
|
61
66
|
rip server [flags] [app] Start server (run 'rip server -h' for details)
|
|
62
67
|
rip db DuckDB server
|
|
@@ -135,6 +140,7 @@ async function main() {
|
|
|
135
140
|
const dir = checkArgs.find(a => !a.startsWith('-')) || '.';
|
|
136
141
|
const exitCode = await runCheck(dir, {
|
|
137
142
|
quiet: checkArgs.includes('-q') || checkArgs.includes('--quiet'),
|
|
143
|
+
strict: checkArgs.includes('--strict'),
|
|
138
144
|
});
|
|
139
145
|
process.exit(exitCode);
|
|
140
146
|
}
|
|
@@ -269,7 +275,13 @@ async function main() {
|
|
|
269
275
|
|
|
270
276
|
// Non-.rip files (e.g. shebang scripts): compile to temp file, execute, clean up
|
|
271
277
|
const source = readFileSync(inputFile, 'utf-8');
|
|
272
|
-
|
|
278
|
+
let result;
|
|
279
|
+
try {
|
|
280
|
+
result = new Compiler({ filename: inputFile }).compile(source);
|
|
281
|
+
} catch (error) {
|
|
282
|
+
console.error(formatError(error, { source, file: inputFile }));
|
|
283
|
+
process.exit(1);
|
|
284
|
+
}
|
|
273
285
|
const tmp = join(dirname(inputFile), `.${basename(inputFile)}.__rip__.mjs`);
|
|
274
286
|
let exitCode = 0;
|
|
275
287
|
try {
|
|
@@ -295,6 +307,7 @@ async function main() {
|
|
|
295
307
|
|
|
296
308
|
try {
|
|
297
309
|
const compiler = new Compiler({ showTokens, showSExpr, quiet,
|
|
310
|
+
filename: inputFile || '<stdin>',
|
|
298
311
|
types: generateDts ? 'emit' : undefined,
|
|
299
312
|
sourceMap: generateMap ? 'inline' : undefined,
|
|
300
313
|
});
|
|
@@ -320,8 +333,7 @@ async function main() {
|
|
|
320
333
|
console.log(entry.tsContent);
|
|
321
334
|
}
|
|
322
335
|
} catch (error) {
|
|
323
|
-
console.error(
|
|
324
|
-
if (error.stack) console.error(error.stack);
|
|
336
|
+
console.error(formatError(error, { source, file: inputFile }));
|
|
325
337
|
process.exit(1);
|
|
326
338
|
}
|
|
327
339
|
}
|
package/docs/RIP-LANG.md
CHANGED
|
@@ -305,7 +305,6 @@ Multiple lines
|
|
|
305
305
|
| `in` | `x in arr` | Array membership |
|
|
306
306
|
| `of` | `k of obj` | Object key existence |
|
|
307
307
|
| `?` (postfix) | `a?` | Existence check (`a != null`) |
|
|
308
|
-
| `!?` (postfix) | `a!?` | Defined check (`a !== undefined`) |
|
|
309
308
|
| `?!` (postfix) | `a?!` | Presence check — true if truthy, else undefined |
|
|
310
309
|
| `?` (ternary) | `a ? b : c` | Ternary conditional |
|
|
311
310
|
| `if...else` (postfix) | `b if a else c` | Python-style ternary |
|
|
@@ -325,8 +324,6 @@ Multiple lines
|
|
|
325
324
|
| `%%` | True modulo | `-1 %% 3` | Always positive result (not remainder) |
|
|
326
325
|
| `!` | Dammit | `fetchData!` | `await fetchData()` — calls AND awaits |
|
|
327
326
|
| `!` | Void | `def process!` | Suppresses implicit return |
|
|
328
|
-
| `!?` | Otherwise | `val !? 5` | Default if undefined (infix) |
|
|
329
|
-
| `!?` | Defined | `val!?` | True if not undefined (postfix) |
|
|
330
327
|
| `?!` | Presence | `@checked?!` | `(this.checked ? true : undefined)` — Houdini operator |
|
|
331
328
|
| `=~` | Match | `str =~ /pat/` | Ruby-style regex match, captures in `_` |
|
|
332
329
|
| `::` | Prototype | `String::trim` | `String.prototype.trim` |
|
|
@@ -438,37 +435,6 @@ level = score > 90 ? 'A' : score > 80 ? 'B' : score > 70 ? 'C' : 'F'
|
|
|
438
435
|
item = found ? (arr[0]) : default
|
|
439
436
|
```
|
|
440
437
|
|
|
441
|
-
## Otherwise Operator (`!?`) and Defined Check (`!?`)
|
|
442
|
-
|
|
443
|
-
The `!?` token serves two roles, distinguished by spacing:
|
|
444
|
-
|
|
445
|
-
**Infix (spaced) — otherwise:** Provides a fallback when a value is `undefined`:
|
|
446
|
-
|
|
447
|
-
```coffee
|
|
448
|
-
result = getValue() !? "default"
|
|
449
|
-
# If getValue() returns undefined, result = "default"
|
|
450
|
-
# null, 0, false, "" all pass through unchanged
|
|
451
|
-
```
|
|
452
|
-
|
|
453
|
-
**Postfix (unspaced) — defined check:** Returns `true` if a value is not `undefined`:
|
|
454
|
-
|
|
455
|
-
```coffee
|
|
456
|
-
value!? # (value !== undefined)
|
|
457
|
-
|
|
458
|
-
# Useful in comprehensions for filtering defined keys
|
|
459
|
-
keys = (k for k, v of obj when v!?)
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
The postfix form mirrors `?` (existence check) but with tighter semantics:
|
|
463
|
-
|
|
464
|
-
| Operator | Checks | `null` | `undefined` | `0` | `false` | `""` |
|
|
465
|
-
|----------|--------|--------|-------------|-----|---------|------|
|
|
466
|
-
| `v?` | not nullish | false | false | true | true | true |
|
|
467
|
-
| `v!?` | not undefined | true | false | true | true | true |
|
|
468
|
-
| `v?!` | truthy presence | `undefined` | `undefined` | `undefined` | `undefined` | `undefined` |
|
|
469
|
-
|
|
470
|
-
Note: `v?!` returns `true` for truthy values, `undefined` for falsy values.
|
|
471
|
-
|
|
472
438
|
## Presence Operator (`?!`) — The Houdini
|
|
473
439
|
|
|
474
440
|
The `?!` operator (postfix, unspaced) returns `true` if the value is truthy,
|
|
@@ -1955,12 +1921,6 @@ catch error
|
|
|
1955
1921
|
finally
|
|
1956
1922
|
cleanup()
|
|
1957
1923
|
|
|
1958
|
-
# Otherwise operator for defaults
|
|
1959
|
-
value = riskyOperation() !? "default"
|
|
1960
|
-
|
|
1961
|
-
# Defined check for filtering
|
|
1962
|
-
keys = (k for k, v of data when v!?)
|
|
1963
|
-
|
|
1964
1924
|
# Optional chaining for safety
|
|
1965
1925
|
name = user?.profile?.name ?? "Anonymous"
|
|
1966
1926
|
```
|
|
@@ -2068,8 +2028,6 @@ X.new(a: 1)
|
|
|
2068
2028
|
|
|
2069
2029
|
# Operators
|
|
2070
2030
|
a! # await a()
|
|
2071
|
-
a !? b # a if defined, else b (infix otherwise)
|
|
2072
|
-
a!? # true if a is defined (postfix defined check)
|
|
2073
2031
|
a?! # true if truthy, else undefined (Houdini)
|
|
2074
2032
|
a // b # floor divide
|
|
2075
2033
|
a %% b # true modulo
|
package/docs/RIP-TYPES.md
CHANGED
|
@@ -643,39 +643,40 @@ count = 0 # Inferred as number
|
|
|
643
643
|
|
|
644
644
|
## Adoption Model
|
|
645
645
|
|
|
646
|
-
Types are optional
|
|
646
|
+
Types are optional and gradual:
|
|
647
647
|
|
|
648
648
|
### Project Level
|
|
649
649
|
|
|
650
|
+
Configure via `rip.json` or the `"rip"` key in `package.json`:
|
|
651
|
+
|
|
650
652
|
```json
|
|
651
653
|
{
|
|
652
|
-
"
|
|
653
|
-
|
|
654
|
-
}
|
|
654
|
+
"strict": true,
|
|
655
|
+
"exclude": ["vendor/**", "legacy/**"]
|
|
655
656
|
}
|
|
656
657
|
```
|
|
657
658
|
|
|
658
|
-
|
|
|
659
|
-
|
|
660
|
-
| `
|
|
661
|
-
| `
|
|
662
|
-
| `"check"` | `.d.ts` generated + `tsc --noEmit` validates types |
|
|
659
|
+
| Key | Purpose |
|
|
660
|
+
|-----|--------|
|
|
661
|
+
| `strict` | Enable strict mode for `rip check` (default: `false`) |
|
|
662
|
+
| `exclude` | Glob patterns for files to skip during `rip check` |
|
|
663
663
|
|
|
664
664
|
### File Level
|
|
665
665
|
|
|
666
|
-
|
|
666
|
+
Opt out of type-checking for a single file:
|
|
667
667
|
|
|
668
668
|
```coffee
|
|
669
|
-
# @
|
|
670
|
-
# @types emit — Parse and emit .d.ts
|
|
671
|
-
# @types check — Full TypeScript checking
|
|
669
|
+
# @nocheck
|
|
672
670
|
```
|
|
673
671
|
|
|
672
|
+
Untyped files (no `::` annotations) automatically get `// @ts-nocheck` —
|
|
673
|
+
no directive needed.
|
|
674
|
+
|
|
674
675
|
### Gradual Path
|
|
675
676
|
|
|
676
|
-
1. **Start
|
|
677
|
-
2. **
|
|
678
|
-
3. **
|
|
677
|
+
1. **Start untyped** — Write normal Rip code
|
|
678
|
+
2. **Add annotations** — Use `::` where helpful; `.d.ts` emitted automatically for editor IntelliSense
|
|
679
|
+
3. **Enable strict** — Set `strict: true` to enforce type safety via `rip check`
|
|
679
680
|
|
|
680
681
|
---
|
|
681
682
|
|
|
@@ -752,7 +753,7 @@ Rip Types is primarily **editor-driven**. The intended loop:
|
|
|
752
753
|
1. Define shapes and contracts
|
|
753
754
|
2. Annotate public boundaries
|
|
754
755
|
3. Let the editor guide implementation
|
|
755
|
-
4. Optionally validate via `
|
|
756
|
+
4. Optionally validate via `rip check`
|
|
756
757
|
|
|
757
758
|
High-quality `.d.ts` output is a first-class goal.
|
|
758
759
|
|
|
@@ -768,8 +769,8 @@ Rip does not:
|
|
|
768
769
|
- Introduce runtime type checks
|
|
769
770
|
- Evaluate type expressions or prove soundness
|
|
770
771
|
|
|
771
|
-
These responsibilities belong to editors, linters, and TypeScript tooling
|
|
772
|
-
|
|
772
|
+
These responsibilities belong to editors, linters, and TypeScript tooling.
|
|
773
|
+
When types are added, `rip check` delegates to TypeScript, which provides all of these capabilities.
|
|
773
774
|
|
|
774
775
|
Rip only needs to:
|
|
775
776
|
|
|
@@ -821,13 +822,13 @@ Components added `src/components.js` alongside the compiler — types add
|
|
|
821
822
|
|------|------|-------|
|
|
822
823
|
| `src/lexer.js` | Detect `::` and `type` keyword, import `installTypeSupport` from `types.js` | Small inline changes |
|
|
823
824
|
| `src/types.js` | Lexer sidecar: `installTypeSupport(Lexer)`, `emitTypes(tokens)`, `generateEnum()` | New file, bulk of logic |
|
|
824
|
-
| `src/compiler.js` | Call `emitTypes()`
|
|
825
|
+
| `src/compiler.js` | Call `emitTypes()` after codegen, wire `generateEnum()` | ~8 lines |
|
|
825
826
|
| `src/grammar/grammar.rip` | Add `Enum` rule to `Expression` | 1 rule + 1 export |
|
|
826
827
|
|
|
827
828
|
The boundary is the token stream. Types are fully resolved before parsing —
|
|
828
|
-
`rewriteTypes()` strips annotations
|
|
829
|
-
|
|
830
|
-
|
|
829
|
+
`rewriteTypes()` strips annotations and type-only constructs are removed
|
|
830
|
+
before the parser runs. After codegen, `emitTypes()` produces `.d.ts` from
|
|
831
|
+
the annotated tokens and the parsed s-expression tree. Only `enum` crosses into the parser/compiler because it generates
|
|
831
832
|
runtime JavaScript.
|
|
832
833
|
|
|
833
834
|
**The `components.js` pattern to follow:**
|
|
@@ -1415,8 +1416,9 @@ if (tag === 'IDENTIFIER' && token[1] === 'type') {
|
|
|
1415
1416
|
}
|
|
1416
1417
|
```
|
|
1417
1418
|
|
|
1418
|
-
The `TYPE_DECL` marker is
|
|
1419
|
-
|
|
1419
|
+
The `TYPE_DECL` marker is **removed from the token stream** before parsing
|
|
1420
|
+
(a copy is saved for `emitTypes()`, which runs after codegen). No grammar
|
|
1421
|
+
rule is needed.
|
|
1420
1422
|
|
|
1421
1423
|
.d.ts: `type ID = number;`
|
|
1422
1424
|
|
|
@@ -1567,9 +1569,9 @@ enum HttpCode {
|
|
|
1567
1569
|
}
|
|
1568
1570
|
```
|
|
1569
1571
|
|
|
1570
|
-
Note: `emitTypes()` reads enum info from the token stream
|
|
1571
|
-
The enum tokens remain in the stream for the parser (unlike type
|
|
1572
|
-
and interfaces, which are removed).
|
|
1572
|
+
Note: `emitTypes()` reads enum info from the saved token stream after
|
|
1573
|
+
codegen. The enum tokens remain in the stream for the parser (unlike type
|
|
1574
|
+
aliases and interfaces, which are removed).
|
|
1573
1575
|
|
|
1574
1576
|
#### 2.5 Grammar Changes Summary
|
|
1575
1577
|
|
|
@@ -1669,9 +1671,10 @@ type Container<T> = { value: T; };
|
|
|
1669
1671
|
|
|
1670
1672
|
### Phase 3: Dual Emission (.js and .d.ts)
|
|
1671
1673
|
|
|
1672
|
-
All type-related logic lives in `src/types.js`. The `.
|
|
1673
|
-
the
|
|
1674
|
-
|
|
1674
|
+
All type-related logic lives in `src/types.js`. The `.js` is generated by
|
|
1675
|
+
the existing CodeGenerator (after parsing), with only `generateEnum()`
|
|
1676
|
+
added. The `.d.ts` is emitted last by `emitTypes()`, which receives both
|
|
1677
|
+
the annotated token stream and the parsed s-expression tree.
|
|
1675
1678
|
|
|
1676
1679
|
#### 3.1 `generateEnum()` — The One Compiler Addition
|
|
1677
1680
|
|
|
@@ -1725,13 +1728,9 @@ compile(source) {
|
|
|
1725
1728
|
let lexer = new Lexer();
|
|
1726
1729
|
let tokens = lexer.tokenize(source);
|
|
1727
1730
|
|
|
1728
|
-
// Step 2:
|
|
1729
|
-
let
|
|
1730
|
-
|
|
1731
|
-
dts = emitTypes(tokens);
|
|
1732
|
-
// Remove TYPE_DECL markers so the parser doesn't see them
|
|
1733
|
-
tokens = tokens.filter(t => t[0] !== 'TYPE_DECL');
|
|
1734
|
-
}
|
|
1731
|
+
// Step 2: Save annotated tokens, remove TYPE_DECL markers
|
|
1732
|
+
let typeTokens = hasTypes ? [...tokens] : null;
|
|
1733
|
+
tokens = tokens.filter(t => t[0] !== 'TYPE_DECL');
|
|
1735
1734
|
|
|
1736
1735
|
// Step 3: Parse (grammar only sees Enum as a new construct)
|
|
1737
1736
|
// ... existing parser setup ...
|
|
@@ -1741,15 +1740,18 @@ compile(source) {
|
|
|
1741
1740
|
let generator = new CodeGenerator({ ... });
|
|
1742
1741
|
let code = generator.compile(sexpr);
|
|
1743
1742
|
|
|
1743
|
+
// Step 5: Emit .d.ts from annotated tokens + parsed s-expression
|
|
1744
|
+
let dts = typeTokens ? emitTypes(typeTokens, sexpr, source) : null;
|
|
1745
|
+
|
|
1744
1746
|
return { tokens, sexpr, code, dts, data: dataSection, reactiveVars: generator.reactiveVars };
|
|
1745
1747
|
}
|
|
1746
1748
|
```
|
|
1747
1749
|
|
|
1748
|
-
The key insight:
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1750
|
+
The key insight: `TYPE_DECL` markers are removed **before parsing**, so the
|
|
1751
|
+
parser receives a clean, type-free token stream — identical to what it
|
|
1752
|
+
would see from untyped Rip code, plus `ENUM` tokens. The `.d.ts` is emitted
|
|
1753
|
+
**after codegen**, giving `emitTypes()` access to both the annotated tokens
|
|
1754
|
+
and the s-expression tree (used for export detection, etc.).
|
|
1753
1755
|
|
|
1754
1756
|
#### 3.4 `const` Emission Rule
|
|
1755
1757
|
|
|
@@ -1791,15 +1793,8 @@ See §1.6 for the full Rip-to-TypeScript conversion table (including `::` → `:
|
|
|
1791
1793
|
|
|
1792
1794
|
#### File-Level Type Directives
|
|
1793
1795
|
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
# @types emit — emit .d.ts
|
|
1797
|
-
# @types check — emit .d.ts + enable tsc validation
|
|
1798
|
-
```
|
|
1799
|
-
|
|
1800
|
-
These are comments. The lexer's `commentToken()` method can detect this
|
|
1801
|
-
pattern and set a flag. Alternatively, the `Compiler` can scan for the
|
|
1802
|
-
directive before tokenizing.
|
|
1796
|
+
A `# @nocheck` comment near the top of a file opts it out of type-checking.
|
|
1797
|
+
Untyped files (no `::` annotations) are automatically skipped.
|
|
1803
1798
|
|
|
1804
1799
|
#### Export of Type-Only Declarations
|
|
1805
1800
|
|
package/docs/demo.html
CHANGED
|
@@ -959,10 +959,10 @@ export Dashboard = component
|
|
|
959
959
|
|
|
960
960
|
p class: 'section', "Core Charts"
|
|
961
961
|
.grid
|
|
962
|
-
ChartCard title: 'Monthly Revenue',
|
|
962
|
+
ChartCard title: 'Monthly Revenue', subtitle: 'Total recurring revenue by month', chartId: 'line'
|
|
963
963
|
ChartCard title: 'Revenue by Product', subtitle: 'Stacked area breakdown across product lines', chartId: 'area'
|
|
964
964
|
ChartCard title: 'Quarterly Revenue', subtitle: 'Quarter-over-quarter comparison', chartId: 'bar'
|
|
965
|
-
ChartCard title: 'Revenue by Product × Quarter',
|
|
965
|
+
ChartCard title: 'Revenue by Product × Quarter', subtitle: 'Stacked bar with product breakdown', chartId: 'stackedBar'
|
|
966
966
|
ChartCard title: 'Revenue & Margin', subtitle: 'Revenue bars with gross margin % line overlay', chartId: 'combo'
|
|
967
967
|
ChartCard title: 'Revenue & Growth Rate', subtitle: 'Dual-axis: revenue (left) and YoY growth (right)', chartId: 'multiAxis'
|
|
968
968
|
ChartCard title: 'Customers by Segment', subtitle: 'Distribution across customer tiers', chartId: 'pie'
|