rip-lang 3.10.14 → 3.12.0
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 +1 -1
- package/README.md +2 -2
- package/docs/RIP-INTERNALS.md +1 -1
- package/docs/RIP-LANG.md +1 -1
- package/docs/RIP-TYPES.md +1 -1
- package/docs/WEB-FRAMEWORKS.md +486 -0
- package/docs/WEB-ROADMAP.md +126 -0
- package/docs/WEB-STYLING.md +701 -0
- package/docs/charts.html +921 -0
- package/docs/dist/{rip-ui.min.js → rip.min.js} +124 -122
- package/docs/dist/rip.min.js.br +0 -0
- package/docs/evidence.html +1228 -0
- package/docs/example/index.html +1 -3
- package/docs/index.html +6 -2
- package/docs/results/index.html +1 -1
- package/docs/sierpinski.html +1 -1
- package/package.json +5 -4
- package/src/app.rip +1002 -0
- package/src/browser.js +9 -12
- package/src/compiler.js +12 -4
- package/src/components.js +70 -29
- package/src/types.js +2 -2
- package/docs/dist/rip-ui.min.js.br +0 -0
- package/docs/dist/rip.browser.min.js +0 -521
- package/docs/dist/rip.browser.min.js.br +0 -0
- package/src/tags.js +0 -62
- /package/docs/{rip-1280w.png → assets/rip-1280w.png} +0 -0
- /package/docs/{rip-512b.png → assets/rip-512b.png} +0 -0
- /package/docs/{rip-fav.svg → assets/rip-fav.svg} +0 -0
- /package/docs/{rip.png → assets/rip.png} +0 -0
- /package/docs/{rip.svg → assets/rip.svg} +0 -0
package/src/browser.js
CHANGED
|
@@ -13,7 +13,7 @@ export const BUILD_DATE = "0000-00-00@00:00:00GMT";
|
|
|
13
13
|
import { compile, compileToJS, formatSExpr, getReactiveRuntime, getComponentRuntime } from './compiler.js';
|
|
14
14
|
|
|
15
15
|
// Eagerly register Rip's reactive primitives on globalThis so that
|
|
16
|
-
// framework code (
|
|
16
|
+
// framework code (app.rip) can use them directly without the compiler
|
|
17
17
|
// needing to detect reactive operators in the source
|
|
18
18
|
if (typeof globalThis !== 'undefined' && !globalThis.__rip) {
|
|
19
19
|
new Function(getReactiveRuntime())();
|
|
@@ -71,10 +71,10 @@ export { processRipScripts };
|
|
|
71
71
|
/**
|
|
72
72
|
* Import a .rip file as an ES module
|
|
73
73
|
* Fetches the URL, compiles Rip→JS, dynamically imports via Blob URL
|
|
74
|
-
* Usage: const { launch } = await importRip('/
|
|
74
|
+
* Usage: const { launch } = await importRip('/app.rip')
|
|
75
75
|
*
|
|
76
76
|
* Pre-compiled modules can be registered on importRip.modules to skip fetching.
|
|
77
|
-
* The
|
|
77
|
+
* The browser bundle uses this to embed app.rip without a server round-trip.
|
|
78
78
|
*/
|
|
79
79
|
export async function importRip(url) {
|
|
80
80
|
for (const [key, mod] of Object.entries(importRip.modules)) {
|
|
@@ -85,13 +85,10 @@ export async function importRip(url) {
|
|
|
85
85
|
return r.text();
|
|
86
86
|
});
|
|
87
87
|
const js = compileToJS(source);
|
|
88
|
-
const
|
|
88
|
+
const header = `// ${url}\n`;
|
|
89
|
+
const blob = new Blob([header + js], { type: 'application/javascript' });
|
|
89
90
|
const blobUrl = URL.createObjectURL(blob);
|
|
90
|
-
|
|
91
|
-
return await import(blobUrl);
|
|
92
|
-
} finally {
|
|
93
|
-
URL.revokeObjectURL(blobUrl);
|
|
94
|
-
}
|
|
91
|
+
return await import(blobUrl);
|
|
95
92
|
}
|
|
96
93
|
importRip.modules = {};
|
|
97
94
|
|
|
@@ -136,12 +133,12 @@ if (typeof globalThis !== 'undefined') {
|
|
|
136
133
|
globalThis.__ripExports = { compile, compileToJS, formatSExpr, VERSION, BUILD_DATE, getReactiveRuntime, getComponentRuntime };
|
|
137
134
|
}
|
|
138
135
|
|
|
139
|
-
// Auto-launch: if rip
|
|
136
|
+
// Auto-launch: if app.rip is bundled and the page has component scripts or a data-url,
|
|
140
137
|
// call launch() automatically with config from the script tag's data attributes.
|
|
141
138
|
// Hash routing defaults to true (opt out with data-hash="false").
|
|
142
139
|
async function autoLaunch() {
|
|
143
140
|
if (globalThis.__ripLaunched) return;
|
|
144
|
-
const ui = importRip.modules?.['
|
|
141
|
+
const ui = importRip.modules?.['app.rip'];
|
|
145
142
|
if (!ui?.launch) return;
|
|
146
143
|
const cfg = document.querySelector('script[data-hash], script[data-url]');
|
|
147
144
|
const url = cfg?.getAttribute('data-url') || '';
|
|
@@ -153,7 +150,7 @@ async function autoLaunch() {
|
|
|
153
150
|
}
|
|
154
151
|
|
|
155
152
|
// Auto-process <script type="text/rip"> blocks, then auto-launch if applicable.
|
|
156
|
-
// Deferred via queueMicrotask so bundled entry code (e.g. rip
|
|
153
|
+
// Deferred via queueMicrotask so bundled entry code (e.g. rip.min.js registering
|
|
157
154
|
// importRip.modules) runs before script processing begins.
|
|
158
155
|
if (typeof document !== 'undefined') {
|
|
159
156
|
globalThis.__ripScriptsReady = new Promise(resolve => {
|
package/src/compiler.js
CHANGED
|
@@ -871,9 +871,7 @@ export class CodeGenerator {
|
|
|
871
871
|
} else if (typeof target === 'string' && this.reactiveVars?.has(target)) {
|
|
872
872
|
targetCode = `${target}.value`;
|
|
873
873
|
} else {
|
|
874
|
-
this.suppressReactiveUnwrap = true;
|
|
875
874
|
targetCode = this.generate(target, 'value');
|
|
876
|
-
this.suppressReactiveUnwrap = false;
|
|
877
875
|
}
|
|
878
876
|
|
|
879
877
|
let valueCode = this.generate(value, 'value');
|
|
@@ -1012,11 +1010,15 @@ export class CodeGenerator {
|
|
|
1012
1010
|
if (this.is(body, 'block') && body.length === 2) {
|
|
1013
1011
|
let expr = body[1];
|
|
1014
1012
|
if (!Array.isArray(expr) || expr[0] !== 'return') {
|
|
1015
|
-
|
|
1013
|
+
let code = this.generate(expr, 'value');
|
|
1014
|
+
if (code[0] === '{') code = `(${code})`;
|
|
1015
|
+
return `${prefix}${paramSyntax} => ${code}`;
|
|
1016
1016
|
}
|
|
1017
1017
|
}
|
|
1018
1018
|
if (!Array.isArray(body) || body[0] !== 'block') {
|
|
1019
|
-
|
|
1019
|
+
let code = this.generate(body, 'value');
|
|
1020
|
+
if (code[0] === '{') code = `(${code})`;
|
|
1021
|
+
return `${prefix}${paramSyntax} => ${code}`;
|
|
1020
1022
|
}
|
|
1021
1023
|
}
|
|
1022
1024
|
|
|
@@ -1279,6 +1281,12 @@ export class CodeGenerator {
|
|
|
1279
1281
|
|
|
1280
1282
|
generateForOf(head, rest, context, sexpr) {
|
|
1281
1283
|
let [vars, obj, own, guard, body] = rest;
|
|
1284
|
+
|
|
1285
|
+
if (context === 'value' && this.comprehensionDepth === 0) {
|
|
1286
|
+
let iterator = ['for-of', vars, obj, own];
|
|
1287
|
+
return this.generate(['comprehension', body, [iterator], guard ? [guard] : []], context);
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1282
1290
|
let [keyVar, valueVar] = Array.isArray(vars) ? vars : [vars];
|
|
1283
1291
|
let objCode = this.generate(obj, 'value');
|
|
1284
1292
|
let code = `for (const ${keyVar} in ${objCode}) `;
|
package/src/components.js
CHANGED
|
@@ -7,7 +7,46 @@
|
|
|
7
7
|
//
|
|
8
8
|
// Naming: All render-tree generators use generate* (consistent with compiler).
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// HTML/SVG Tag Definitions
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
const HTML_TAGS = new Set([
|
|
15
|
+
'html', 'head', 'title', 'base', 'link', 'meta', 'style',
|
|
16
|
+
'body', 'address', 'article', 'aside', 'footer', 'header',
|
|
17
|
+
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'main', 'nav', 'section',
|
|
18
|
+
'blockquote', 'dd', 'div', 'dl', 'dt', 'figcaption', 'figure',
|
|
19
|
+
'hr', 'li', 'ol', 'p', 'pre', 'ul',
|
|
20
|
+
'a', 'abbr', 'b', 'bdi', 'bdo', 'br', 'cite', 'code', 'data',
|
|
21
|
+
'dfn', 'em', 'i', 'kbd', 'mark', 'q', 'rp', 'rt', 'ruby', 's',
|
|
22
|
+
'samp', 'small', 'span', 'strong', 'sub', 'sup', 'time', 'u', 'var', 'wbr',
|
|
23
|
+
'area', 'audio', 'img', 'map', 'track', 'video',
|
|
24
|
+
'embed', 'iframe', 'object', 'param', 'picture', 'portal', 'source',
|
|
25
|
+
'svg', 'math', 'canvas',
|
|
26
|
+
'noscript', 'script',
|
|
27
|
+
'del', 'ins',
|
|
28
|
+
'caption', 'col', 'colgroup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr',
|
|
29
|
+
'button', 'datalist', 'fieldset', 'form', 'input', 'label', 'legend',
|
|
30
|
+
'meter', 'optgroup', 'option', 'output', 'progress', 'select', 'textarea',
|
|
31
|
+
'details', 'dialog', 'menu', 'summary',
|
|
32
|
+
'slot', 'template'
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
const SVG_TAGS = new Set([
|
|
36
|
+
'svg', 'g', 'defs', 'symbol', 'use', 'marker', 'clipPath', 'mask', 'pattern',
|
|
37
|
+
'circle', 'ellipse', 'line', 'path', 'polygon', 'polyline', 'rect',
|
|
38
|
+
'text', 'textPath', 'tspan',
|
|
39
|
+
'linearGradient', 'radialGradient', 'stop',
|
|
40
|
+
'filter', 'feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite',
|
|
41
|
+
'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight',
|
|
42
|
+
'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR',
|
|
43
|
+
'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology',
|
|
44
|
+
'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence',
|
|
45
|
+
'animate', 'animateMotion', 'animateTransform', 'set', 'mpath',
|
|
46
|
+
'desc', 'foreignObject', 'image', 'metadata', 'switch', 'title', 'view'
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
const TEMPLATE_TAGS = new Set([...HTML_TAGS, ...SVG_TAGS]);
|
|
11
50
|
|
|
12
51
|
// ============================================================================
|
|
13
52
|
// Constants
|
|
@@ -135,6 +174,18 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
135
174
|
return isHtmlTag(name) || isComponent(name);
|
|
136
175
|
};
|
|
137
176
|
|
|
177
|
+
let skipBalancedPair = (tokens, from, closer, opener) => {
|
|
178
|
+
let depth = 1;
|
|
179
|
+
let k = from;
|
|
180
|
+
while (k >= 0 && depth > 0) {
|
|
181
|
+
let kt = tokens[k][0];
|
|
182
|
+
if (kt === closer) depth++;
|
|
183
|
+
else if (kt === opener) depth--;
|
|
184
|
+
if (depth > 0) k--;
|
|
185
|
+
}
|
|
186
|
+
return k;
|
|
187
|
+
};
|
|
188
|
+
|
|
138
189
|
let startsWithTag = (tokens, i) => {
|
|
139
190
|
let j = i;
|
|
140
191
|
while (j > 0) {
|
|
@@ -145,31 +196,21 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
145
196
|
if (pt === 'INDENT' || pt === 'OUTDENT') {
|
|
146
197
|
let jt = tokens[j][0];
|
|
147
198
|
if (jt === 'CALL_END' || jt === ')') {
|
|
148
|
-
|
|
149
|
-
let depth = 1;
|
|
150
|
-
let k = j - 1;
|
|
151
|
-
while (k >= 0 && depth > 0) {
|
|
152
|
-
let kt = tokens[k][0];
|
|
153
|
-
if (kt === jt) depth++;
|
|
154
|
-
else if (kt === open) depth--;
|
|
155
|
-
if (depth > 0) k--;
|
|
156
|
-
}
|
|
157
|
-
j = k;
|
|
199
|
+
j = skipBalancedPair(tokens, j - 1, jt, jt === 'CALL_END' ? 'CALL_START' : '(');
|
|
158
200
|
continue;
|
|
159
201
|
}
|
|
160
202
|
break;
|
|
161
203
|
}
|
|
162
204
|
if (pt === 'CALL_END' || pt === ')') {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
j = k;
|
|
205
|
+
j = skipBalancedPair(tokens, j - 2, pt, pt === 'CALL_END' ? 'CALL_START' : '(');
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (pt === 'INTERPOLATION_END') {
|
|
209
|
+
j = skipBalancedPair(tokens, j - 2, 'INTERPOLATION_END', 'INTERPOLATION_START');
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
if (pt === 'STRING_END') {
|
|
213
|
+
j = skipBalancedPair(tokens, j - 2, 'STRING_END', 'STRING_START');
|
|
173
214
|
continue;
|
|
174
215
|
}
|
|
175
216
|
j--;
|
|
@@ -1309,14 +1350,14 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1309
1350
|
setupLines.push(` if (want === 'then') {`);
|
|
1310
1351
|
setupLines.push(` currentBlock = ${thenBlockName}(this${extraArgs});`);
|
|
1311
1352
|
setupLines.push(` currentBlock.c();`);
|
|
1312
|
-
setupLines.push(` currentBlock.m(anchor.parentNode, anchor.nextSibling);`);
|
|
1353
|
+
setupLines.push(` if (anchor.parentNode) currentBlock.m(anchor.parentNode, anchor.nextSibling);`);
|
|
1313
1354
|
setupLines.push(` currentBlock.p(this${extraArgs});`);
|
|
1314
1355
|
setupLines.push(` }`);
|
|
1315
1356
|
if (elseBlock) {
|
|
1316
1357
|
setupLines.push(` if (want === 'else') {`);
|
|
1317
1358
|
setupLines.push(` currentBlock = ${elseBlockName}(this${extraArgs});`);
|
|
1318
1359
|
setupLines.push(` currentBlock.c();`);
|
|
1319
|
-
setupLines.push(` currentBlock.m(anchor.parentNode, anchor.nextSibling);`);
|
|
1360
|
+
setupLines.push(` if (anchor.parentNode) currentBlock.m(anchor.parentNode, anchor.nextSibling);`);
|
|
1320
1361
|
setupLines.push(` currentBlock.p(this${extraArgs});`);
|
|
1321
1362
|
setupLines.push(` }`);
|
|
1322
1363
|
}
|
|
@@ -1411,10 +1452,10 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1411
1452
|
const condFragChildren = getFragChildren(rootVar, createLines, localizeVar);
|
|
1412
1453
|
if (condFragChildren) {
|
|
1413
1454
|
for (const child of condFragChildren) {
|
|
1414
|
-
factoryLines.push(` if (detaching) ${child}.remove();`);
|
|
1455
|
+
factoryLines.push(` if (detaching && ${child}) ${child}.remove();`);
|
|
1415
1456
|
}
|
|
1416
1457
|
} else {
|
|
1417
|
-
factoryLines.push(` if (detaching) ${localizeVar(rootVar)}.remove();`);
|
|
1458
|
+
factoryLines.push(` if (detaching && ${localizeVar(rootVar)}) ${localizeVar(rootVar)}.remove();`);
|
|
1418
1459
|
}
|
|
1419
1460
|
factoryLines.push(` }`);
|
|
1420
1461
|
|
|
@@ -1512,10 +1553,10 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1512
1553
|
factoryLines.push(` m(target, anchor) {`);
|
|
1513
1554
|
if (loopFragChildren) {
|
|
1514
1555
|
for (const child of loopFragChildren) {
|
|
1515
|
-
factoryLines.push(` target.insertBefore(${child}, anchor);`);
|
|
1556
|
+
factoryLines.push(` if (target) target.insertBefore(${child}, anchor);`);
|
|
1516
1557
|
}
|
|
1517
1558
|
} else {
|
|
1518
|
-
factoryLines.push(` target.insertBefore(${localizeVar(itemNode)}, anchor);`);
|
|
1559
|
+
factoryLines.push(` if (target) target.insertBefore(${localizeVar(itemNode)}, anchor);`);
|
|
1519
1560
|
}
|
|
1520
1561
|
factoryLines.push(` },`);
|
|
1521
1562
|
|
|
@@ -1545,10 +1586,10 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
1545
1586
|
}
|
|
1546
1587
|
if (loopFragChildren) {
|
|
1547
1588
|
for (const child of loopFragChildren) {
|
|
1548
|
-
factoryLines.push(` if (detaching) ${child}.remove();`);
|
|
1589
|
+
factoryLines.push(` if (detaching && ${child}) ${child}.remove();`);
|
|
1549
1590
|
}
|
|
1550
1591
|
} else {
|
|
1551
|
-
factoryLines.push(` if (detaching) ${localizeVar(itemNode)}.remove();`);
|
|
1592
|
+
factoryLines.push(` if (detaching && ${localizeVar(itemNode)}) ${localizeVar(itemNode)}.remove();`);
|
|
1552
1593
|
}
|
|
1553
1594
|
factoryLines.push(` }`);
|
|
1554
1595
|
|
package/src/types.js
CHANGED
|
@@ -1017,13 +1017,13 @@ function emitComponentTypes(sexpr, lines, indent, indentLevel, componentVars) {
|
|
|
1017
1017
|
propName = isProp ? (target[2]?.valueOf?.() ?? target[2]) : (target?.valueOf?.() ?? target);
|
|
1018
1018
|
type = isProp ? target[2]?.type : target?.type;
|
|
1019
1019
|
hasDefault = true;
|
|
1020
|
-
componentVars.add(propName);
|
|
1020
|
+
if (!isProp) componentVars.add(propName);
|
|
1021
1021
|
} else if (mHead === '.') {
|
|
1022
1022
|
isProp = (member[1]?.valueOf?.() ?? member[1]) === 'this';
|
|
1023
1023
|
propName = isProp ? (member[2]?.valueOf?.() ?? member[2]) : null;
|
|
1024
1024
|
type = isProp ? member[2]?.type : null;
|
|
1025
1025
|
hasDefault = false;
|
|
1026
|
-
if (propName) componentVars.add(propName);
|
|
1026
|
+
if (!isProp && propName) componentVars.add(propName);
|
|
1027
1027
|
} else {
|
|
1028
1028
|
continue;
|
|
1029
1029
|
}
|
|
Binary file
|