ripple 0.2.74 → 0.2.76
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/package.json +8 -1
- package/src/compiler/index.js +29 -12
- package/src/compiler/phases/3-transform/{index.js → client/index.js} +17 -19
- package/src/compiler/phases/3-transform/server/index.js +95 -0
- package/src/runtime/internal/client/for.js +3 -4
- package/src/runtime/internal/server/index.js +40 -0
- package/src/server/index.js +1 -0
- package/tests/{array.test.ripple → client/array.test.ripple} +1 -1
- package/types/server.d.ts +0 -0
- /package/tests/{__snapshots__ → client/__snapshots__}/basic.test.ripple.snap +0 -0
- /package/tests/{__snapshots__ → client/__snapshots__}/composite.test.ripple.snap +0 -0
- /package/tests/{__snapshots__ → client/__snapshots__}/for.test.ripple.snap +0 -0
- /package/tests/{accessors-props.test.ripple → client/accessors-props.test.ripple} +0 -0
- /package/tests/{basic.test.ripple → client/basic.test.ripple} +0 -0
- /package/tests/{boundaries.test.ripple → client/boundaries.test.ripple} +0 -0
- /package/tests/{compiler.test.ripple → client/compiler.test.ripple} +0 -0
- /package/tests/{composite.test.ripple → client/composite.test.ripple} +0 -0
- /package/tests/{context.test.ripple → client/context.test.ripple} +0 -0
- /package/tests/{for.test.ripple → client/for.test.ripple} +0 -0
- /package/tests/{map.test.ripple → client/map.test.ripple} +0 -0
- /package/tests/{ref.test.ripple → client/ref.test.ripple} +0 -0
- /package/tests/{set.test.ripple → client/set.test.ripple} +0 -0
- /package/tests/{svg.test.ripple → client/svg.test.ripple} +0 -0
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.2.
|
|
6
|
+
"version": "0.2.76",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index.js",
|
|
9
9
|
"main": "src/runtime/index.js",
|
|
@@ -29,6 +29,10 @@
|
|
|
29
29
|
"default": "./src/runtime/index.js"
|
|
30
30
|
},
|
|
31
31
|
"./package.json": "./package.json",
|
|
32
|
+
"./server": {
|
|
33
|
+
"types": "./types/server.d.ts",
|
|
34
|
+
"default": "./src/server/index.js"
|
|
35
|
+
},
|
|
32
36
|
"./compiler": {
|
|
33
37
|
"types": "./types/index.d.ts",
|
|
34
38
|
"require": "./compiler/index.js",
|
|
@@ -42,6 +46,9 @@
|
|
|
42
46
|
"./internal/client": {
|
|
43
47
|
"default": "./src/runtime/internal/client/index.js"
|
|
44
48
|
},
|
|
49
|
+
"./internal/server": {
|
|
50
|
+
"default": "./src/runtime/internal/server/index.js"
|
|
51
|
+
},
|
|
45
52
|
"./jsx-runtime": {
|
|
46
53
|
"types": "./src/jsx-runtime.d.ts",
|
|
47
54
|
"import": "./src/jsx-runtime.js",
|
package/src/compiler/index.js
CHANGED
|
@@ -1,25 +1,42 @@
|
|
|
1
|
+
/** @import { RawSourceMap } from 'source-map' */
|
|
2
|
+
/** @import { Program } from 'estree' */
|
|
3
|
+
/** @import { ParseError } from './phases/1-parse/index.js' */
|
|
4
|
+
|
|
1
5
|
import { parse as parse_module } from './phases/1-parse/index.js';
|
|
2
6
|
import { analyze } from './phases/2-analyze/index.js';
|
|
3
|
-
import {
|
|
7
|
+
import { transform_client } from './phases/3-transform/client/index.js';
|
|
8
|
+
import { transform_server } from './phases/3-transform/server/index.js';
|
|
4
9
|
import { convert_source_map_to_mappings } from './phases/3-transform/segments.js';
|
|
5
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} source
|
|
13
|
+
* @returns {{ ast: Program, errors: ParseError[] }}
|
|
14
|
+
*/
|
|
6
15
|
export function parse(source) {
|
|
7
|
-
|
|
16
|
+
return parse_module(source);
|
|
8
17
|
}
|
|
9
18
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} source
|
|
21
|
+
* @param {string} filename
|
|
22
|
+
* @param {{ environment?: 'client' | 'server' }} options
|
|
23
|
+
* @returns {{ js: { code: string, map: RawSourceMap }, css: { code: string, map: RawSourceMap } | null }}
|
|
24
|
+
*/
|
|
25
|
+
export function compile(source, filename, options = {}) {
|
|
26
|
+
const ast = parse_module(source);
|
|
27
|
+
const analysis = analyze(ast, filename);
|
|
28
|
+
const result = options.environment === 'server'
|
|
29
|
+
? transform_server(filename, source, analysis)
|
|
30
|
+
: transform_client(filename, source, analysis, false);
|
|
14
31
|
|
|
15
|
-
|
|
32
|
+
return result;
|
|
16
33
|
}
|
|
17
34
|
|
|
18
35
|
export function compile_to_volar_mappings(source, filename) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
36
|
+
// Parse and transform to get the esrap sourcemap
|
|
37
|
+
const ast = parse_module(source);
|
|
38
|
+
const analysis = analyze(ast, filename);
|
|
39
|
+
const transformed = transform_client(filename, source, analysis, true);
|
|
23
40
|
|
|
24
|
-
|
|
41
|
+
return convert_source_map_to_mappings(transformed.js.map, source, transformed.js.code);
|
|
25
42
|
}
|
|
@@ -2,15 +2,15 @@ import { walk } from 'zimmerframe';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { print } from 'esrap';
|
|
4
4
|
import tsx from 'esrap/languages/tsx';
|
|
5
|
-
import * as b from '
|
|
5
|
+
import * as b from '../../../../utils/builders.js';
|
|
6
6
|
import {
|
|
7
7
|
IS_CONTROLLED,
|
|
8
8
|
IS_INDEXED,
|
|
9
9
|
TEMPLATE_FRAGMENT,
|
|
10
10
|
TEMPLATE_SVG_NAMESPACE,
|
|
11
11
|
TEMPLATE_MATHML_NAMESPACE,
|
|
12
|
-
} from '
|
|
13
|
-
import { sanitize_template_string } from '
|
|
12
|
+
} from '../../../../constants.js';
|
|
13
|
+
import { sanitize_template_string } from '../../../../utils/sanitize_template_string.js';
|
|
14
14
|
import {
|
|
15
15
|
build_hoisted_params,
|
|
16
16
|
is_inside_component,
|
|
@@ -27,11 +27,11 @@ import {
|
|
|
27
27
|
is_element_dom_element,
|
|
28
28
|
is_top_level_await,
|
|
29
29
|
is_ripple_track_call,
|
|
30
|
-
} from '
|
|
30
|
+
} from '../../../utils.js';
|
|
31
31
|
import is_reference from 'is-reference';
|
|
32
|
-
import { object } from '
|
|
33
|
-
import { render_stylesheets } from '
|
|
34
|
-
import { is_event_attribute, is_passive_event } from '
|
|
32
|
+
import { object } from '../../../../utils/ast.js';
|
|
33
|
+
import { render_stylesheets } from '../stylesheet.js';
|
|
34
|
+
import { is_event_attribute, is_passive_event } from '../../../../utils/events.js';
|
|
35
35
|
|
|
36
36
|
function add_ripple_internal_import(context) {
|
|
37
37
|
if (!context.state.to_ts) {
|
|
@@ -65,7 +65,11 @@ function visit_function(node, context) {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
let body = context.visit(node.body,
|
|
68
|
+
let body = context.visit(node.body, {
|
|
69
|
+
...state,
|
|
70
|
+
// we are new context so tracking no longer applies
|
|
71
|
+
metadata: { ...state.metadata, tracked: false },
|
|
72
|
+
});
|
|
69
73
|
|
|
70
74
|
if (metadata?.tracked === true) {
|
|
71
75
|
const new_body = [];
|
|
@@ -1663,7 +1667,7 @@ function transform_body(body, { visit, state }) {
|
|
|
1663
1667
|
return [...body_state.setup, ...body_state.init, ...body_state.final];
|
|
1664
1668
|
}
|
|
1665
1669
|
|
|
1666
|
-
export function
|
|
1670
|
+
export function transform_client(filename, source, analysis, to_ts) {
|
|
1667
1671
|
const state = {
|
|
1668
1672
|
imports: new Set(),
|
|
1669
1673
|
events: new Set(),
|
|
@@ -1700,16 +1704,10 @@ export function transform(filename, source, analysis, to_ts) {
|
|
|
1700
1704
|
);
|
|
1701
1705
|
}
|
|
1702
1706
|
|
|
1703
|
-
const js = print(
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
}),
|
|
1708
|
-
{
|
|
1709
|
-
sourceMapContent: source,
|
|
1710
|
-
sourceMapSource: path.basename(filename),
|
|
1711
|
-
},
|
|
1712
|
-
);
|
|
1707
|
+
const js = print(program, tsx(), {
|
|
1708
|
+
sourceMapContent: source,
|
|
1709
|
+
sourceMapSource: path.basename(filename),
|
|
1710
|
+
});
|
|
1713
1711
|
|
|
1714
1712
|
const css = render_stylesheets(state.stylesheets);
|
|
1715
1713
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as b from '../../../../utils/builders.js';
|
|
2
|
+
import { walk } from 'zimmerframe';
|
|
3
|
+
import ts from 'esrap/languages/ts';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { print } from 'esrap';
|
|
6
|
+
|
|
7
|
+
function add_ripple_internal_import(context) {
|
|
8
|
+
if (!context.state.to_ts) {
|
|
9
|
+
if (!context.state.imports.has(`import * as _$_ from 'ripple/internal/server'`)) {
|
|
10
|
+
context.state.imports.add(`import * as _$_ from 'ripple/internal/server'`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function transform_body(body, { visit, state }) {
|
|
16
|
+
const body_state = {
|
|
17
|
+
...state,
|
|
18
|
+
init: [],
|
|
19
|
+
metadata: state.metadata,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return body_state.init;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const visitors = {
|
|
26
|
+
_: function set_scope(node, { next, state }) {
|
|
27
|
+
const scope = state.scopes.get(node);
|
|
28
|
+
|
|
29
|
+
if (scope && scope !== state.scope) {
|
|
30
|
+
return next({ ...state, scope });
|
|
31
|
+
} else {
|
|
32
|
+
return next();
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
Component(node, context) {
|
|
37
|
+
add_ripple_internal_import(context);
|
|
38
|
+
|
|
39
|
+
const metadata = { await: false };
|
|
40
|
+
const body_statements = [
|
|
41
|
+
b.stmt(b.call('_$_.push_component')),
|
|
42
|
+
...transform_body(node.body, {
|
|
43
|
+
...context,
|
|
44
|
+
state: { ...context.state, component: node, metadata },
|
|
45
|
+
}),
|
|
46
|
+
b.stmt(b.call('_$_.pop_component')),
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
if (node.css !== null && node.css) {
|
|
50
|
+
context.state.stylesheets.push(node.css);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return b.function(
|
|
54
|
+
node.id,
|
|
55
|
+
node.params.length > 0 ? [b.id('__output'), node.params[0]] : [b.id('__output')],
|
|
56
|
+
b.block([
|
|
57
|
+
...(metadata.await
|
|
58
|
+
? [b.stmt(b.call('_$_.async', b.thunk(b.block(body_statements), true)))]
|
|
59
|
+
: body_statements),
|
|
60
|
+
]),
|
|
61
|
+
);
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export function transform_server(filename, source, analysis) {
|
|
66
|
+
const state = {
|
|
67
|
+
imports: new Set(),
|
|
68
|
+
init: null,
|
|
69
|
+
scope: analysis.scope,
|
|
70
|
+
scopes: analysis.scopes,
|
|
71
|
+
stylesheets: [],
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const program = /** @type {ESTree.Program} */ (
|
|
75
|
+
walk(analysis.ast, { ...state, namespace: 'html' }, visitors)
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
for (const import_node of state.imports) {
|
|
79
|
+
program.body.unshift(b.stmt(b.id(import_node)));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const js = print(program, ts(), {
|
|
83
|
+
sourceMapContent: source,
|
|
84
|
+
sourceMapSource: path.basename(filename),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// TODO: extract css
|
|
88
|
+
const css = '';
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
ast: program,
|
|
92
|
+
js,
|
|
93
|
+
css,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -210,10 +210,9 @@ function reconcile(anchor, block, b, render_fn, is_controlled, is_indexed) {
|
|
|
210
210
|
sources[j - b_start] = i + 1;
|
|
211
211
|
if (fast_path_removal) {
|
|
212
212
|
fast_path_removal = false;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// }
|
|
213
|
+
while (a_start < i) {
|
|
214
|
+
destroy_block(a_blocks[a_start++]);
|
|
215
|
+
}
|
|
217
216
|
}
|
|
218
217
|
if (pos > j) {
|
|
219
218
|
moved = true;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
class Output {
|
|
3
|
+
head = '';
|
|
4
|
+
body = '';
|
|
5
|
+
#parent = null;
|
|
6
|
+
|
|
7
|
+
constructor(parent) {
|
|
8
|
+
this.#parent = parent;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
push(str) {
|
|
12
|
+
this.body += str;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function renderToString(component) {
|
|
17
|
+
const output = new Output(null);
|
|
18
|
+
|
|
19
|
+
if (component.async) {
|
|
20
|
+
await component(output, {});
|
|
21
|
+
} else {
|
|
22
|
+
component(output, {});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { head, body } = output;
|
|
26
|
+
|
|
27
|
+
return { head, body };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function push_component() {
|
|
31
|
+
debugger;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function pop_component() {
|
|
35
|
+
debugger;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function async(fn) {
|
|
39
|
+
// TODO
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { renderToString } from '../runtime/internal/server/index.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
2
|
import { mount, flushSync, effect, untrack, TrackedArray, track } from 'ripple';
|
|
3
|
-
import { MAX_ARRAY_LENGTH } from '
|
|
3
|
+
import { MAX_ARRAY_LENGTH } from '../../src/runtime/internal/client/constants.js';
|
|
4
4
|
|
|
5
5
|
describe('TrackedArray', () => {
|
|
6
6
|
let container;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|