ripple 0.3.3 → 0.3.4
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 +72 -0
- package/package.json +2 -2
- package/src/compiler/identifier-utils.js +1 -8
- package/src/compiler/phases/1-parse/index.js +101 -195
- package/src/compiler/phases/2-analyze/index.js +82 -174
- package/src/compiler/phases/2-analyze/prune.js +2 -2
- package/src/compiler/phases/3-transform/client/index.js +169 -261
- package/src/compiler/phases/3-transform/server/index.js +185 -42
- package/src/compiler/types/index.d.ts +14 -33
- package/src/compiler/utils.js +32 -20
- package/src/runtime/index-client.js +0 -17
- package/src/runtime/internal/client/bindings.js +118 -7
- package/src/runtime/internal/client/render.js +5 -1
- package/src/runtime/internal/client/runtime.js +1 -1
- package/src/runtime/internal/client/types.d.ts +4 -0
- package/tests/client/array/array.copy-within.test.ripple +7 -7
- package/tests/client/array/array.derived.test.ripple +24 -24
- package/tests/client/array/array.iteration.test.ripple +7 -7
- package/tests/client/array/array.mutations.test.ripple +17 -17
- package/tests/client/array/array.to-methods.test.ripple +4 -4
- package/tests/client/async-suspend.test.ripple +3 -3
- package/tests/client/basic/basic.attributes.test.ripple +31 -31
- package/tests/client/basic/basic.collections.test.ripple +6 -6
- package/tests/client/basic/basic.components.test.ripple +8 -8
- package/tests/client/basic/basic.errors.test.ripple +31 -34
- package/tests/client/basic/basic.events.test.ripple +11 -11
- package/tests/client/basic/basic.get-set.test.ripple +18 -18
- package/tests/client/basic/basic.reactivity.test.ripple +36 -36
- package/tests/client/basic/basic.rendering.test.ripple +7 -7
- package/tests/client/basic/basic.utilities.test.ripple +4 -4
- package/tests/client/boundaries.test.ripple +7 -7
- package/tests/client/compiler/__snapshots__/compiler.typescript.test.ripple.snap +24 -0
- package/tests/client/compiler/compiler.assignments.test.ripple +12 -10
- package/tests/client/compiler/compiler.basic.test.ripple +57 -58
- package/tests/client/compiler/compiler.tracked-access.test.ripple +14 -8
- package/tests/client/compiler/compiler.typescript.test.ripple +31 -0
- package/tests/client/composite/composite.dynamic-components.test.ripple +6 -6
- package/tests/client/composite/composite.props.test.ripple +9 -9
- package/tests/client/composite/composite.reactivity.test.ripple +23 -23
- package/tests/client/composite/composite.render.test.ripple +52 -4
- package/tests/client/computed-properties.test.ripple +3 -3
- package/tests/client/context.test.ripple +3 -3
- package/tests/client/css/global-additional-cases.test.ripple +5 -2
- package/tests/client/css/style-identifier.test.ripple +40 -49
- package/tests/client/date.test.ripple +39 -39
- package/tests/client/dynamic-elements.test.ripple +37 -37
- package/tests/client/events.test.ripple +25 -25
- package/tests/client/for.test.ripple +8 -8
- package/tests/client/head.test.ripple +7 -7
- package/tests/client/html.test.ripple +2 -2
- package/tests/client/input-value.test.ripple +376 -177
- package/tests/client/lazy-destructuring.test.ripple +185 -0
- package/tests/client/map.test.ripple +20 -20
- package/tests/client/media-query.test.ripple +4 -4
- package/tests/client/object.test.ripple +5 -5
- package/tests/client/portal.test.ripple +4 -4
- package/tests/client/ref.test.ripple +3 -3
- package/tests/client/return.test.ripple +17 -17
- package/tests/client/set.test.ripple +10 -10
- package/tests/client/svg.test.ripple +6 -5
- package/tests/client/switch.test.ripple +10 -10
- package/tests/client/tracked-expression.test.ripple +3 -1
- package/tests/client/try.test.ripple +4 -4
- package/tests/client/url/url.derived.test.ripple +6 -7
- package/tests/client/url/url.parsing.test.ripple +9 -9
- package/tests/client/url/url.partial-removal.test.ripple +9 -9
- package/tests/client/url/url.reactivity.test.ripple +16 -16
- package/tests/client/url/url.serialization.test.ripple +3 -3
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +7 -8
- package/tests/client/url-search-params/url-search-params.initialization.test.ripple +6 -4
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +12 -12
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +18 -18
- package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +16 -16
- package/tests/client/url-search-params/url-search-params.serialization.test.ripple +4 -4
- package/tests/client/url-search-params/url-search-params.tracked-url.test.ripple +3 -3
- package/tests/hydration/build-components.js +4 -10
- package/tests/hydration/compiled/client/basic.js +4 -4
- package/tests/hydration/compiled/client/events.js +2 -0
- package/tests/hydration/compiled/client/for.js +2 -0
- package/tests/hydration/compiled/client/head.js +13 -11
- package/tests/hydration/compiled/client/hmr.js +4 -2
- package/tests/hydration/compiled/client/html.js +82 -95
- package/tests/hydration/compiled/client/if-children.js +8 -9
- package/tests/hydration/compiled/client/if.js +2 -0
- package/tests/hydration/compiled/client/mixed-control-flow.js +4 -2
- package/tests/hydration/compiled/client/portal.js +1 -1
- package/tests/hydration/compiled/client/reactivity.js +2 -0
- package/tests/hydration/compiled/client/return.js +2 -0
- package/tests/hydration/compiled/client/switch.js +2 -0
- package/tests/hydration/compiled/server/composite.js +2 -2
- package/tests/hydration/compiled/server/events.js +2 -0
- package/tests/hydration/compiled/server/for.js +2 -0
- package/tests/hydration/compiled/server/head.js +13 -11
- package/tests/hydration/compiled/server/hmr.js +2 -0
- package/tests/hydration/compiled/server/html.js +2 -0
- package/tests/hydration/compiled/server/if-children.js +2 -0
- package/tests/hydration/compiled/server/if.js +2 -0
- package/tests/hydration/compiled/server/mixed-control-flow.js +2 -0
- package/tests/hydration/compiled/server/portal.js +1 -1
- package/tests/hydration/compiled/server/reactivity.js +2 -0
- package/tests/hydration/compiled/server/return.js +2 -0
- package/tests/hydration/compiled/server/switch.js +2 -0
- package/tests/hydration/components/composite.ripple +1 -1
- package/tests/hydration/components/events.ripple +10 -8
- package/tests/hydration/components/for.ripple +22 -20
- package/tests/hydration/components/head.ripple +8 -6
- package/tests/hydration/components/hmr.ripple +3 -1
- package/tests/hydration/components/html.ripple +3 -1
- package/tests/hydration/components/if-children.ripple +9 -7
- package/tests/hydration/components/if.ripple +7 -5
- package/tests/hydration/components/mixed-control-flow.ripple +5 -3
- package/tests/hydration/components/portal.ripple +2 -2
- package/tests/hydration/components/reactivity.ripple +11 -9
- package/tests/hydration/components/return.ripple +13 -11
- package/tests/hydration/components/switch.ripple +6 -4
- package/tests/server/__snapshots__/compiler.test.ripple.snap +22 -0
- package/tests/server/await.test.ripple +2 -2
- package/tests/server/basic.attributes.test.ripple +21 -19
- package/tests/server/basic.components.test.ripple +5 -4
- package/tests/server/basic.test.ripple +21 -20
- package/tests/server/compiler.test.ripple +36 -5
- package/tests/server/composite.props.test.ripple +7 -6
- package/tests/server/context.test.ripple +3 -1
- package/tests/server/dynamic-elements.test.ripple +24 -24
- package/tests/server/head.test.ripple +7 -5
- package/tests/server/style-identifier.test.ripple +95 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,77 @@
|
|
|
1
1
|
# ripple
|
|
2
2
|
|
|
3
|
+
## 0.3.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`92982cd`](https://github.com/Ripple-TS/ripple/commit/92982cd7b918d0afee9334c74765573b30c8a645)
|
|
8
|
+
Thanks [@trueadm](https://github.com/trueadm)! - feat(compiler): add lazy
|
|
9
|
+
destructuring syntax (`&{...}` and `&[...]`)
|
|
10
|
+
|
|
11
|
+
Lazy destructuring defers property/index access until the binding is read,
|
|
12
|
+
preserving reactivity for destructured props. Works with default values,
|
|
13
|
+
compound assignment operators, and update expressions.
|
|
14
|
+
|
|
15
|
+
- [#814](https://github.com/Ripple-TS/ripple/pull/814)
|
|
16
|
+
[`747ae1f`](https://github.com/Ripple-TS/ripple/commit/747ae1fc7948e994eeb521f3ed78711c9dd3e802)
|
|
17
|
+
Thanks [@RazinShafayet2007](https://github.com/RazinShafayet2007)! -
|
|
18
|
+
fix(compiler): strip TypeScript class syntax from JS output
|
|
19
|
+
|
|
20
|
+
This fixes compiler output for `.ripple` classes by stripping TypeScript-only
|
|
21
|
+
`implements` clauses and `extends` type arguments from emitted JavaScript.
|
|
22
|
+
|
|
23
|
+
- [#820](https://github.com/Ripple-TS/ripple/pull/820)
|
|
24
|
+
[`abe1caa`](https://github.com/Ripple-TS/ripple/commit/abe1caa6ab636722099a6ecd4cafbf117d208ec2)
|
|
25
|
+
Thanks [@RazinShafayet2007](https://github.com/RazinShafayet2007)! - fix: sync
|
|
26
|
+
`<select>` `bindValue` with typed and dynamic options
|
|
27
|
+
|
|
28
|
+
- [#817](https://github.com/Ripple-TS/ripple/pull/817)
|
|
29
|
+
[`046d0ba`](https://github.com/Ripple-TS/ripple/commit/046d0baf190d161c3b851799080d11eb4f95e094)
|
|
30
|
+
Thanks [@RazinShafayet2007](https://github.com/RazinShafayet2007)! -
|
|
31
|
+
fix(compiler): preserve class `extends` generics in volar output
|
|
32
|
+
|
|
33
|
+
- [`79a920e`](https://github.com/Ripple-TS/ripple/commit/79a920e30f0f35f2ec07ff8d52dc709f8bb74c77)
|
|
34
|
+
Thanks [@trueadm](https://github.com/trueadm)! - Remove `#ripple` namespace
|
|
35
|
+
syntax in favor of direct imports from `'ripple'`
|
|
36
|
+
|
|
37
|
+
The `#ripple` namespace (`#ripple.track()`, `#ripple.effect()`,
|
|
38
|
+
`#ripple.array()`, etc.) has been removed. All reactive APIs are now accessed
|
|
39
|
+
via standard imports:
|
|
40
|
+
|
|
41
|
+
```ripple
|
|
42
|
+
import {
|
|
43
|
+
track,
|
|
44
|
+
effect,
|
|
45
|
+
untrack,
|
|
46
|
+
Context,
|
|
47
|
+
RippleArray,
|
|
48
|
+
RippleObject,
|
|
49
|
+
} from 'ripple';
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- `#ripple.track(value)` → `track(value)`
|
|
53
|
+
- `#ripple.effect(fn)` → `effect(fn)`
|
|
54
|
+
- `#ripple.untrack(fn)` → `untrack(fn)`
|
|
55
|
+
- `#ripple.context(value)` → `new Context(value)`
|
|
56
|
+
- `#ripple[1, 2, 3]` → `new RippleArray(1, 2, 3)`
|
|
57
|
+
- `#ripple{ key: value }` → `new RippleObject({ key: value })`
|
|
58
|
+
- `#ripple.style` → `#style`
|
|
59
|
+
- `#ripple.server` → `#server`
|
|
60
|
+
|
|
61
|
+
- [#824](https://github.com/Ripple-TS/ripple/pull/824)
|
|
62
|
+
[`83807a4`](https://github.com/Ripple-TS/ripple/commit/83807a412603ff49c398f9365b011fd4b4a5f8bf)
|
|
63
|
+
Thanks [@RazinShafayet2007](https://github.com/RazinShafayet2007)! -
|
|
64
|
+
fix(parser): avoid hanging on unclosed tsx compat tags
|
|
65
|
+
|
|
66
|
+
- Updated dependencies
|
|
67
|
+
[[`92982cd`](https://github.com/Ripple-TS/ripple/commit/92982cd7b918d0afee9334c74765573b30c8a645),
|
|
68
|
+
[`747ae1f`](https://github.com/Ripple-TS/ripple/commit/747ae1fc7948e994eeb521f3ed78711c9dd3e802),
|
|
69
|
+
[`abe1caa`](https://github.com/Ripple-TS/ripple/commit/abe1caa6ab636722099a6ecd4cafbf117d208ec2),
|
|
70
|
+
[`046d0ba`](https://github.com/Ripple-TS/ripple/commit/046d0baf190d161c3b851799080d11eb4f95e094),
|
|
71
|
+
[`79a920e`](https://github.com/Ripple-TS/ripple/commit/79a920e30f0f35f2ec07ff8d52dc709f8bb74c77),
|
|
72
|
+
[`83807a4`](https://github.com/Ripple-TS/ripple/commit/83807a412603ff49c398f9365b011fd4b4a5f8bf)]:
|
|
73
|
+
- ripple@0.3.4
|
|
74
|
+
|
|
3
75
|
## 0.3.3
|
|
4
76
|
|
|
5
77
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Ripple is an elegant TypeScript UI framework",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.3.
|
|
6
|
+
"version": "0.3.4",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index-client.js",
|
|
9
9
|
"main": "src/runtime/index-client.js",
|
|
@@ -105,6 +105,6 @@
|
|
|
105
105
|
"vscode-languageserver-types": "^3.17.5"
|
|
106
106
|
},
|
|
107
107
|
"peerDependencies": {
|
|
108
|
-
"ripple": "0.3.
|
|
108
|
+
"ripple": "0.3.4"
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
export const IDENTIFIER_OBFUSCATION_PREFIX = '_$_';
|
|
2
|
-
export const RIPPLE_NAMESPACE_IDENTIFIER =
|
|
3
|
-
IDENTIFIER_OBFUSCATION_PREFIX + encode_utf16_char('#') + 'ripple';
|
|
4
2
|
export const STYLE_IDENTIFIER = IDENTIFIER_OBFUSCATION_PREFIX + encode_utf16_char('#') + 'style';
|
|
5
|
-
export const SERVER_IDENTIFIER =
|
|
6
|
-
IDENTIFIER_OBFUSCATION_PREFIX +
|
|
7
|
-
encode_utf16_char('#') +
|
|
8
|
-
'ripple' +
|
|
9
|
-
encode_utf16_char('.') +
|
|
10
|
-
'server';
|
|
3
|
+
export const SERVER_IDENTIFIER = IDENTIFIER_OBFUSCATION_PREFIX + encode_utf16_char('#') + 'server';
|
|
11
4
|
export const CSS_HASH_IDENTIFIER = IDENTIFIER_OBFUSCATION_PREFIX + 'hash';
|
|
12
5
|
|
|
13
6
|
const DECODE_UTF16_REGEX = /_u([0-9a-fA-F]{4})_/g;
|
|
@@ -665,46 +665,14 @@ function RipplePlugin(config) {
|
|
|
665
665
|
ch === 13 || // carriage return
|
|
666
666
|
ch === -1; // EOF
|
|
667
667
|
|
|
668
|
-
if (startsWith('#
|
|
669
|
-
this.pos +=
|
|
670
|
-
return this.finishToken(tt.
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
if (startsWith('#ripple{')) {
|
|
674
|
-
this.pos += 8;
|
|
675
|
-
return this.finishToken(tt.braceL, '#ripple{');
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
const ripple_keywords = [
|
|
679
|
-
'#ripple.map',
|
|
680
|
-
'#ripple.set',
|
|
681
|
-
'#ripple.array',
|
|
682
|
-
'#ripple.object',
|
|
683
|
-
'#ripple.track',
|
|
684
|
-
'#ripple.trackSplit',
|
|
685
|
-
'#ripple.untrack',
|
|
686
|
-
'#ripple.effect',
|
|
687
|
-
'#ripple.context',
|
|
688
|
-
'#ripple.date',
|
|
689
|
-
'#ripple.url',
|
|
690
|
-
'#ripple.urlSearchParams',
|
|
691
|
-
'#ripple.mediaQuery',
|
|
692
|
-
'#ripple.server',
|
|
693
|
-
'#ripple.style',
|
|
694
|
-
'#ripple.validate',
|
|
695
|
-
];
|
|
696
|
-
|
|
697
|
-
for (let i = 0; i < ripple_keywords.length; i++) {
|
|
698
|
-
const keyword = ripple_keywords[i];
|
|
699
|
-
if (startsWith(keyword) && is_ripple_delimiter(char_after(keyword.length))) {
|
|
700
|
-
this.pos += keyword.length;
|
|
701
|
-
return this.finishToken(tt.name, keyword);
|
|
702
|
-
}
|
|
668
|
+
if (startsWith('#server') && is_ripple_delimiter(char_after(7))) {
|
|
669
|
+
this.pos += 7;
|
|
670
|
+
return this.finishToken(tt.name, '#server');
|
|
703
671
|
}
|
|
704
672
|
|
|
705
|
-
if (
|
|
706
|
-
this.pos +=
|
|
707
|
-
return this.finishToken(tt.name, '#
|
|
673
|
+
if (startsWith('#style') && is_ripple_delimiter(char_after(6))) {
|
|
674
|
+
this.pos += 6;
|
|
675
|
+
return this.finishToken(tt.name, '#style');
|
|
708
676
|
}
|
|
709
677
|
}
|
|
710
678
|
}
|
|
@@ -904,6 +872,49 @@ function RipplePlugin(config) {
|
|
|
904
872
|
);
|
|
905
873
|
}
|
|
906
874
|
|
|
875
|
+
/**
|
|
876
|
+
* Override isLet to recognize `let &{` and `let &[` as variable declarations.
|
|
877
|
+
* Acorn's isLet checks the char after `let` and only recognizes `{`, `[`, or identifiers.
|
|
878
|
+
* The `&` char (38) is not in that set, so `let &{...}` would not be parsed as a declaration.
|
|
879
|
+
* @param {string} context
|
|
880
|
+
* @returns {boolean}
|
|
881
|
+
*/
|
|
882
|
+
isLet(context) {
|
|
883
|
+
if (!this.isContextual('let')) return false;
|
|
884
|
+
const skip = /\s*/y;
|
|
885
|
+
skip.lastIndex = this.pos;
|
|
886
|
+
const match = skip.exec(this.input);
|
|
887
|
+
if (!match) return super.isLet(context);
|
|
888
|
+
const next = this.pos + match[0].length;
|
|
889
|
+
const nextCh = this.input.charCodeAt(next);
|
|
890
|
+
// If next char is &, check if char after & is { or [
|
|
891
|
+
if (nextCh === 38) {
|
|
892
|
+
const afterAmp = this.input.charCodeAt(next + 1);
|
|
893
|
+
if (afterAmp === 123 || afterAmp === 91) return true;
|
|
894
|
+
}
|
|
895
|
+
return super.isLet(context);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* Parse binding atom - handles lazy destructuring patterns (&{...} and &[...])
|
|
900
|
+
* When & is directly followed by { or [, parse as a lazy destructuring pattern.
|
|
901
|
+
* The resulting ObjectPattern/ArrayPattern node gets a `lazy: true` flag.
|
|
902
|
+
*/
|
|
903
|
+
parseBindingAtom() {
|
|
904
|
+
if (this.type === tt.bitwiseAND) {
|
|
905
|
+
// Check that the char immediately after & is { or [ (no whitespace)
|
|
906
|
+
const charAfterAmp = this.input.charCodeAt(this.end);
|
|
907
|
+
if (charAfterAmp === 123 || charAfterAmp === 91) {
|
|
908
|
+
// & directly followed by { or [ — lazy destructuring
|
|
909
|
+
this.next(); // consume &, now current token is { or [
|
|
910
|
+
const pattern = super.parseBindingAtom();
|
|
911
|
+
pattern.lazy = true;
|
|
912
|
+
return pattern;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
return super.parseBindingAtom();
|
|
916
|
+
}
|
|
917
|
+
|
|
907
918
|
/**
|
|
908
919
|
* Parse expression atom - handles RippleArray and RippleObject literals
|
|
909
920
|
* @type {Parse.Parser['parseExprAtom']}
|
|
@@ -917,69 +928,19 @@ function RipplePlugin(config) {
|
|
|
917
928
|
return this.parseTrackedExpression();
|
|
918
929
|
}
|
|
919
930
|
|
|
920
|
-
// Check if this is #
|
|
921
|
-
if (this.type === tt.name && this.value === '#
|
|
931
|
+
// Check if this is #server identifier for server function calls
|
|
932
|
+
if (this.type === tt.name && this.value === '#server') {
|
|
922
933
|
const node = this.startNode();
|
|
923
934
|
this.next();
|
|
924
935
|
return /** @type {AST.ServerIdentifier} */ (this.finishNode(node, 'ServerIdentifier'));
|
|
925
936
|
}
|
|
926
937
|
|
|
927
|
-
if (this.type === tt.name && this.value === '#
|
|
938
|
+
if (this.type === tt.name && this.value === '#style') {
|
|
928
939
|
const node = this.startNode();
|
|
929
940
|
this.next();
|
|
930
941
|
return /** @type {AST.StyleIdentifier} */ (this.finishNode(node, 'StyleIdentifier'));
|
|
931
942
|
}
|
|
932
943
|
|
|
933
|
-
if (this.type === tt.name && typeof this.value === 'string') {
|
|
934
|
-
const ripple_identifier_map = {
|
|
935
|
-
'#ripple.array': 'RippleArray',
|
|
936
|
-
'#ripple.object': 'RippleObject',
|
|
937
|
-
'#ripple.track': 'track',
|
|
938
|
-
'#ripple.trackSplit': 'trackSplit',
|
|
939
|
-
'#ripple.untrack': 'untrack',
|
|
940
|
-
'#ripple.effect': 'effect',
|
|
941
|
-
'#ripple.context': 'Context',
|
|
942
|
-
'#ripple.date': 'RippleDate',
|
|
943
|
-
'#ripple.map': 'RippleMap',
|
|
944
|
-
'#ripple.set': 'RippleSet',
|
|
945
|
-
'#ripple.url': 'RippleURL',
|
|
946
|
-
'#ripple.urlSearchParams': 'RippleURLSearchParams',
|
|
947
|
-
'#ripple.mediaQuery': 'MediaQuery',
|
|
948
|
-
};
|
|
949
|
-
|
|
950
|
-
const identifier_name =
|
|
951
|
-
ripple_identifier_map[/** @type {keyof typeof ripple_identifier_map} */ (this.value)];
|
|
952
|
-
if (identifier_name !== undefined) {
|
|
953
|
-
const node = /** @type {AST.Identifier} */ (this.startNode());
|
|
954
|
-
node.name = identifier_name;
|
|
955
|
-
node.metadata ??= { path: [] };
|
|
956
|
-
node.metadata.source_name = this.value;
|
|
957
|
-
this.next();
|
|
958
|
-
return this.finishNode(node, 'Identifier');
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
// In loose mode, handle incomplete #ripple prefixes for autocomplete
|
|
963
|
-
if (
|
|
964
|
-
this.#loose &&
|
|
965
|
-
this.type === tt.name &&
|
|
966
|
-
typeof this.value === 'string' &&
|
|
967
|
-
this.value === '#ripple'
|
|
968
|
-
) {
|
|
969
|
-
// Return an Identifier node for incomplete tracked syntax
|
|
970
|
-
const node = /** @type {AST.Identifier} */ (this.startNode());
|
|
971
|
-
node.name = this.value;
|
|
972
|
-
this.next();
|
|
973
|
-
return this.finishNode(node, 'Identifier');
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
// Check if this is a tuple literal starting with #ripple[
|
|
977
|
-
if (this.type === tt.bracketL && this.value === '#ripple[') {
|
|
978
|
-
return this.parseRippleArrayExpression();
|
|
979
|
-
} else if (this.type === tt.braceL && this.value === '#ripple{') {
|
|
980
|
-
return this.parseRippleObjectExpression();
|
|
981
|
-
}
|
|
982
|
-
|
|
983
944
|
// Check if this is a component expression (e.g., in object literal values)
|
|
984
945
|
if (this.type === tt.name && this.value === 'component') {
|
|
985
946
|
return this.parseComponent();
|
|
@@ -1080,79 +1041,6 @@ function RipplePlugin(config) {
|
|
|
1080
1041
|
return this.finishNode(node, 'ServerBlock');
|
|
1081
1042
|
}
|
|
1082
1043
|
|
|
1083
|
-
/**
|
|
1084
|
-
* @type {Parse.Parser['parseRippleArrayExpression']}
|
|
1085
|
-
*/
|
|
1086
|
-
parseRippleArrayExpression() {
|
|
1087
|
-
const node = /** @type {AST.RippleArrayExpression} */ (this.startNode());
|
|
1088
|
-
this.next(); // consume the '#ripple['
|
|
1089
|
-
|
|
1090
|
-
node.elements = [];
|
|
1091
|
-
|
|
1092
|
-
// Parse array elements similar to regular array parsing
|
|
1093
|
-
let first = true;
|
|
1094
|
-
while (!this.eat(tt.bracketR)) {
|
|
1095
|
-
if (!first) {
|
|
1096
|
-
this.expect(tt.comma);
|
|
1097
|
-
if (this.afterTrailingComma(tt.bracketR)) break;
|
|
1098
|
-
} else {
|
|
1099
|
-
first = false;
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
if (this.type === tt.comma) {
|
|
1103
|
-
// Hole in array
|
|
1104
|
-
node.elements.push(null);
|
|
1105
|
-
} else if (this.type === tt.ellipsis) {
|
|
1106
|
-
// Spread element
|
|
1107
|
-
const element = this.parseSpread();
|
|
1108
|
-
node.elements.push(element);
|
|
1109
|
-
if (this.type === tt.comma && this.input.charCodeAt(this.pos) === 93) {
|
|
1110
|
-
this.raise(this.pos, 'Trailing comma is not permitted after the rest element');
|
|
1111
|
-
}
|
|
1112
|
-
} else {
|
|
1113
|
-
// Regular element
|
|
1114
|
-
node.elements.push(this.parseMaybeAssign(false));
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
return this.finishNode(node, 'RippleArrayExpression');
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
/**
|
|
1122
|
-
* @type {Parse.Parser['parseRippleObjectExpression']}
|
|
1123
|
-
*/
|
|
1124
|
-
parseRippleObjectExpression() {
|
|
1125
|
-
const node = /** @type {AST.RippleObjectExpression} */ (this.startNode());
|
|
1126
|
-
this.next(); // consume the '#ripple{'
|
|
1127
|
-
|
|
1128
|
-
node.properties = [];
|
|
1129
|
-
|
|
1130
|
-
// Parse object properties similar to regular object parsing
|
|
1131
|
-
let first = true;
|
|
1132
|
-
while (!this.eat(tt.braceR)) {
|
|
1133
|
-
if (!first) {
|
|
1134
|
-
this.expect(tt.comma);
|
|
1135
|
-
if (this.afterTrailingComma(tt.braceR)) break;
|
|
1136
|
-
} else {
|
|
1137
|
-
first = false;
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
if (this.type === tt.ellipsis) {
|
|
1141
|
-
// Spread property
|
|
1142
|
-
const prop = this.parseSpread();
|
|
1143
|
-
node.properties.push(prop);
|
|
1144
|
-
if (this.type === tt.comma && this.input.charCodeAt(this.pos) === 125) {
|
|
1145
|
-
this.raise(this.pos, 'Trailing comma is not permitted after the rest element');
|
|
1146
|
-
}
|
|
1147
|
-
} else {
|
|
1148
|
-
// Regular property
|
|
1149
|
-
node.properties.push(this.parseProperty(false, new DestructuringErrors()));
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
return this.finishNode(node, 'RippleObjectExpression');
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
1044
|
/**
|
|
1157
1045
|
* Parse a component - common implementation used by statements, expressions, and export defaults
|
|
1158
1046
|
* @type {Parse.Parser['parseComponent']}
|
|
@@ -2146,32 +2034,34 @@ function RipplePlugin(config) {
|
|
|
2146
2034
|
if (element.type === 'TsxCompat') {
|
|
2147
2035
|
this.#path.pop();
|
|
2148
2036
|
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2037
|
+
if (!element.unclosed) {
|
|
2038
|
+
const raise_error = () => {
|
|
2039
|
+
this.raise(this.start, `Expected closing tag '</tsx:${element.kind}>'`);
|
|
2040
|
+
};
|
|
2152
2041
|
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2042
|
+
this.next();
|
|
2043
|
+
// we should expect to see </tsx:kind>
|
|
2044
|
+
if (this.value !== '/') {
|
|
2045
|
+
raise_error();
|
|
2046
|
+
}
|
|
2047
|
+
this.next();
|
|
2048
|
+
if (this.value !== 'tsx') {
|
|
2049
|
+
raise_error();
|
|
2050
|
+
}
|
|
2051
|
+
this.next();
|
|
2052
|
+
if (this.type.label !== ':') {
|
|
2053
|
+
raise_error();
|
|
2054
|
+
}
|
|
2055
|
+
this.next();
|
|
2056
|
+
if (this.value !== element.kind) {
|
|
2057
|
+
raise_error();
|
|
2058
|
+
}
|
|
2059
|
+
this.next();
|
|
2060
|
+
if (this.type !== tstt.jsxTagEnd) {
|
|
2061
|
+
raise_error();
|
|
2062
|
+
}
|
|
2063
|
+
this.next();
|
|
2173
2064
|
}
|
|
2174
|
-
this.next();
|
|
2175
2065
|
} else if (this.#path[this.#path.length - 1] === element) {
|
|
2176
2066
|
// Check if this element was properly closed
|
|
2177
2067
|
if (!this.#loose) {
|
|
@@ -2235,6 +2125,22 @@ function RipplePlugin(config) {
|
|
|
2235
2125
|
this.exprAllowed = true;
|
|
2236
2126
|
|
|
2237
2127
|
while (true) {
|
|
2128
|
+
if (this.type === tt.eof || this.pos >= this.input.length || this.type === tt.braceR) {
|
|
2129
|
+
if (!this.#loose) {
|
|
2130
|
+
this.raise(
|
|
2131
|
+
this.start,
|
|
2132
|
+
`Unclosed tag '<tsx:${inside_tsx_compat.kind}>'. Expected '</tsx:${inside_tsx_compat.kind}>' before end of component.`,
|
|
2133
|
+
);
|
|
2134
|
+
} else {
|
|
2135
|
+
inside_tsx_compat.unclosed = true;
|
|
2136
|
+
/** @type {AST.NodeWithLocation} */ (inside_tsx_compat).loc.end = {
|
|
2137
|
+
.../** @type {AST.SourceLocation} */ (inside_tsx_compat.openingElement.loc).end,
|
|
2138
|
+
};
|
|
2139
|
+
inside_tsx_compat.end = inside_tsx_compat.openingElement.end;
|
|
2140
|
+
}
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2238
2144
|
if (this.input.slice(this.pos, this.pos + 5) === '/tsx:') {
|
|
2239
2145
|
return;
|
|
2240
2146
|
}
|
|
@@ -2254,9 +2160,9 @@ function RipplePlugin(config) {
|
|
|
2254
2160
|
while (this.pos < this.input.length) {
|
|
2255
2161
|
const ch = this.input.charCodeAt(this.pos);
|
|
2256
2162
|
|
|
2257
|
-
// Stop at opening tag,
|
|
2258
|
-
if (ch === 60 || ch === 123) {
|
|
2259
|
-
// < or {
|
|
2163
|
+
// Stop at opening tag, expression, or the component-closing brace
|
|
2164
|
+
if (ch === 60 || ch === 123 || ch === 125) {
|
|
2165
|
+
// < or { or }
|
|
2260
2166
|
break;
|
|
2261
2167
|
}
|
|
2262
2168
|
|
|
@@ -2433,16 +2339,16 @@ function RipplePlugin(config) {
|
|
|
2433
2339
|
);
|
|
2434
2340
|
}
|
|
2435
2341
|
|
|
2436
|
-
if (this.value === '#
|
|
2437
|
-
// Peek ahead to see if this is a server block (#
|
|
2438
|
-
// a server identifier expression (#
|
|
2342
|
+
if (this.value === '#server') {
|
|
2343
|
+
// Peek ahead to see if this is a server block (#server { ... }) vs
|
|
2344
|
+
// a server identifier expression (#server.fn(), #server.fn().then())
|
|
2439
2345
|
let peek_pos = this.end;
|
|
2440
2346
|
while (peek_pos < this.input.length && /\s/.test(this.input[peek_pos])) peek_pos++;
|
|
2441
2347
|
if (peek_pos < this.input.length && this.input.charCodeAt(peek_pos) === 123) {
|
|
2442
2348
|
// Next non-whitespace character is '{' — parse as server block
|
|
2443
2349
|
return this.parseServerBlock();
|
|
2444
2350
|
}
|
|
2445
|
-
// Otherwise fall through to parse as expression statement (e.g., #
|
|
2351
|
+
// Otherwise fall through to parse as expression statement (e.g., #server.fn().then(...))
|
|
2446
2352
|
}
|
|
2447
2353
|
|
|
2448
2354
|
if (this.value === 'component') {
|