@cilix/lightjs 0.0.4 → 0.0.6
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/core.js +139 -53
- package/index.js +1 -1
- package/package.json +1 -1
package/core.js
CHANGED
|
@@ -19,11 +19,9 @@
|
|
|
19
19
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
const path = require("path");
|
|
24
|
-
|
|
25
|
-
module.exports = (config) => {
|
|
22
|
+
module.exports = (config, fs, path) => {
|
|
26
23
|
const _files = {};
|
|
24
|
+
let includeRuntime = false;
|
|
27
25
|
|
|
28
26
|
function throw_error (err) {
|
|
29
27
|
err.origin = 'light';
|
|
@@ -351,7 +349,9 @@ module.exports = (config) => {
|
|
|
351
349
|
"let",
|
|
352
350
|
"nosync",
|
|
353
351
|
"as",
|
|
354
|
-
"global"
|
|
352
|
+
"global",
|
|
353
|
+
"when",
|
|
354
|
+
"catch"
|
|
355
355
|
];
|
|
356
356
|
|
|
357
357
|
let symbols = [
|
|
@@ -661,10 +661,15 @@ module.exports = (config) => {
|
|
|
661
661
|
const parse = (tokens) => {
|
|
662
662
|
let tok = tokens[0];
|
|
663
663
|
let cursor = 0;
|
|
664
|
-
let in_tag = false;
|
|
665
664
|
let ast = { type: 'file', data: { file: tok.file }, children: [] };
|
|
666
665
|
let parent = ast;
|
|
667
666
|
|
|
667
|
+
const parse_state = {
|
|
668
|
+
in_tag: false,
|
|
669
|
+
if_depth: 0,
|
|
670
|
+
each_depth: 0
|
|
671
|
+
};
|
|
672
|
+
|
|
668
673
|
function ast_node(type, data) {
|
|
669
674
|
let node = { type, data, children: [] };
|
|
670
675
|
parent.children.push(node);
|
|
@@ -1014,6 +1019,7 @@ module.exports = (config) => {
|
|
|
1014
1019
|
attr[key] = { type: "bool", data: true };
|
|
1015
1020
|
}
|
|
1016
1021
|
} else if (accept("on")) {
|
|
1022
|
+
includeRuntime = true;
|
|
1017
1023
|
expect(":");
|
|
1018
1024
|
let handler;
|
|
1019
1025
|
let evt = tok.data;
|
|
@@ -1030,9 +1036,9 @@ module.exports = (config) => {
|
|
|
1030
1036
|
}
|
|
1031
1037
|
|
|
1032
1038
|
function parse_custom_tag_body () {
|
|
1033
|
-
in_tag = true;
|
|
1039
|
+
parse_state.in_tag = true;
|
|
1034
1040
|
parse_tag_list();
|
|
1035
|
-
in_tag = false;
|
|
1041
|
+
parse_state.in_tag = false;
|
|
1036
1042
|
}
|
|
1037
1043
|
|
|
1038
1044
|
function parse_tag() {
|
|
@@ -1084,6 +1090,7 @@ module.exports = (config) => {
|
|
|
1084
1090
|
}
|
|
1085
1091
|
|
|
1086
1092
|
function parse_if_statement() {
|
|
1093
|
+
parse_state.if_depth++;
|
|
1087
1094
|
expect("(");
|
|
1088
1095
|
let condition = parse_expr();
|
|
1089
1096
|
expect(")");
|
|
@@ -1112,13 +1119,68 @@ module.exports = (config) => {
|
|
|
1112
1119
|
}
|
|
1113
1120
|
}
|
|
1114
1121
|
parent = current;
|
|
1122
|
+
parse_state.if_depth--;
|
|
1115
1123
|
}
|
|
1116
1124
|
|
|
1117
|
-
|
|
1125
|
+
function parse_when_statement() {
|
|
1126
|
+
if (parse_state.each_depth > 0) {
|
|
1127
|
+
throw_error({
|
|
1128
|
+
msg: 'when cannot be nested in each',
|
|
1129
|
+
pos: tok.pos,
|
|
1130
|
+
file: tok.file
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
if (parse_state.if_depth > 0) {
|
|
1134
|
+
throw_error({
|
|
1135
|
+
msg: 'when cannot be nested in if',
|
|
1136
|
+
pos: tok.pos,
|
|
1137
|
+
file: tok.file
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
expect("(");
|
|
1141
|
+
let condition = parse_expr();
|
|
1142
|
+
expect(")");
|
|
1143
|
+
let current = parent;
|
|
1144
|
+
let node = ast_node('when', condition);
|
|
1145
|
+
parent = node;
|
|
1146
|
+
let pass = ast_node('block');
|
|
1147
|
+
parent = pass;
|
|
1148
|
+
if (accept("[")) {
|
|
1149
|
+
parse_tag_list();
|
|
1150
|
+
expect("]");
|
|
1151
|
+
} else {
|
|
1152
|
+
parse_tag();
|
|
1153
|
+
}
|
|
1154
|
+
expect("else");
|
|
1155
|
+
parent = node;
|
|
1156
|
+
let fail = ast_node('block');
|
|
1157
|
+
parent = fail;
|
|
1158
|
+
if (accept("[")) {
|
|
1159
|
+
parse_tag_list();
|
|
1160
|
+
expect("]");
|
|
1161
|
+
} else {
|
|
1162
|
+
parse_tag();
|
|
1163
|
+
}
|
|
1164
|
+
parent = current;
|
|
1165
|
+
expect("catch");
|
|
1166
|
+
parent = node;
|
|
1167
|
+
let catchBlock = ast_node('block');
|
|
1168
|
+
parent = catchBlock;
|
|
1169
|
+
if (accept("[")) {
|
|
1170
|
+
parse_tag_list();
|
|
1171
|
+
expect("]");
|
|
1172
|
+
} else {
|
|
1173
|
+
parse_tag();
|
|
1174
|
+
}
|
|
1175
|
+
parent = current;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
function parse_tag_list() {
|
|
1118
1179
|
if (accept("if")) {
|
|
1119
1180
|
parse_if_statement();
|
|
1120
1181
|
parse_tag_list();
|
|
1121
1182
|
} else if (accept("each")) {
|
|
1183
|
+
parse_state.each_depth++;
|
|
1122
1184
|
expect("(");
|
|
1123
1185
|
let it1, it0 = tok.data;
|
|
1124
1186
|
expect("ident");
|
|
@@ -1142,6 +1204,10 @@ module.exports = (config) => {
|
|
|
1142
1204
|
parse_tag();
|
|
1143
1205
|
}
|
|
1144
1206
|
parent = current;
|
|
1207
|
+
parse_state.each_depth--;
|
|
1208
|
+
parse_tag_list();
|
|
1209
|
+
} else if (accept("when")) {
|
|
1210
|
+
parse_when_statement();
|
|
1145
1211
|
parse_tag_list();
|
|
1146
1212
|
} else if (peek("ident")) {
|
|
1147
1213
|
parse_tag();
|
|
@@ -1154,10 +1220,11 @@ module.exports = (config) => {
|
|
|
1154
1220
|
ast_node('yield', { pos: tok.pos, file: tok.file });
|
|
1155
1221
|
next();
|
|
1156
1222
|
parse_tag_list();
|
|
1157
|
-
} else if (in_tag && (peek('global') || peek('const') || peek('let'))) {
|
|
1223
|
+
} else if (parse_state.in_tag && (peek('global') || peek('const') || peek('let'))) {
|
|
1158
1224
|
parse_assignment();
|
|
1159
1225
|
parse_tag_list();
|
|
1160
|
-
} else if (in_tag && peek('js_context')) {
|
|
1226
|
+
} else if (parse_state.in_tag && peek('js_context')) {
|
|
1227
|
+
includeRuntime = true;
|
|
1161
1228
|
parent.js = tok.data;
|
|
1162
1229
|
ast_node('js', { js: tok.data, pos: tok.pos, file: tok.file });
|
|
1163
1230
|
next();
|
|
@@ -1296,6 +1363,7 @@ module.exports = (config) => {
|
|
|
1296
1363
|
} else if (peek('const') || peek('let') || peek('global')) {
|
|
1297
1364
|
parse_assignment();
|
|
1298
1365
|
} else if (peek('js_context')) {
|
|
1366
|
+
includeRuntime = true;
|
|
1299
1367
|
ast_node('js', { js: tok.data, pos: tok.pos, file: tok.file });
|
|
1300
1368
|
js_found = true;
|
|
1301
1369
|
next();
|
|
@@ -1320,7 +1388,7 @@ module.exports = (config) => {
|
|
|
1320
1388
|
let inScript = false;
|
|
1321
1389
|
let inStyle = false;
|
|
1322
1390
|
|
|
1323
|
-
const found = { head: false,
|
|
1391
|
+
const found = { head: false, html: false, body: false };
|
|
1324
1392
|
|
|
1325
1393
|
const emit = flush ? (txt) => {
|
|
1326
1394
|
if (html.length > 100) {
|
|
@@ -1432,7 +1500,6 @@ module.exports = (config) => {
|
|
|
1432
1500
|
ctx.pop();
|
|
1433
1501
|
break;
|
|
1434
1502
|
}
|
|
1435
|
-
// todo: html -> head, body enforcement
|
|
1436
1503
|
if (valid_tags.indexOf(node.data.name) === -1) {
|
|
1437
1504
|
err(`Invalid tag: ${node.data.name}`, node.data);
|
|
1438
1505
|
}
|
|
@@ -1447,9 +1514,11 @@ module.exports = (config) => {
|
|
|
1447
1514
|
}
|
|
1448
1515
|
emit('<');
|
|
1449
1516
|
emit(node.data.name);
|
|
1517
|
+
let innerText = null;
|
|
1450
1518
|
for (let a in attr) {
|
|
1451
1519
|
let val = evaluate(attr[a]);
|
|
1452
1520
|
const t = getType(val);
|
|
1521
|
+
if (a === 'innerHTML') innerText = val;
|
|
1453
1522
|
if (val !== false || a === 'innerHTML') {
|
|
1454
1523
|
emit(' ');
|
|
1455
1524
|
emit(a.replace('bind:', ''));
|
|
@@ -1473,11 +1542,13 @@ module.exports = (config) => {
|
|
|
1473
1542
|
emit('>');
|
|
1474
1543
|
if (void_tags.indexOf(node.data.name) === -1) {
|
|
1475
1544
|
if (node.data.name === 'html') {
|
|
1545
|
+
if (innerText) err('cannot set innerHTML of html tag');
|
|
1476
1546
|
if (found.html) err('html tag may only be used once', node.data);
|
|
1477
1547
|
found.html = true;
|
|
1478
1548
|
} else if (!found.html) {
|
|
1479
1549
|
err('html tag must be the first tag printed', node.data);
|
|
1480
1550
|
} else if (node.data.name === 'head') {
|
|
1551
|
+
if (innerText) err('cannot set innerHTML of head tag');
|
|
1481
1552
|
if (found.head) err('head tag may only be used once', node.data);
|
|
1482
1553
|
found.head = true;
|
|
1483
1554
|
} else if (node.data.name === 'body') {
|
|
@@ -1485,23 +1556,27 @@ module.exports = (config) => {
|
|
|
1485
1556
|
if (found.body) err('body tag may only be used once', node.data);
|
|
1486
1557
|
found.body = true;
|
|
1487
1558
|
}
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1559
|
+
if (innerText) {
|
|
1560
|
+
emit(innerText);
|
|
1561
|
+
emit('</');
|
|
1562
|
+
emit(node.data.name);
|
|
1563
|
+
emit('>');
|
|
1564
|
+
} else {
|
|
1565
|
+
node.children.forEach(walk);
|
|
1566
|
+
if (node.data.name === 'head') {
|
|
1567
|
+
if (includeRuntime) {
|
|
1568
|
+
emit('<script>');
|
|
1569
|
+
emit(`document.addEventListener('DOMContentLoaded', function () {\n`);
|
|
1570
|
+
emit(`(function (data){${js}})(${JSON.stringify(initial_state)})`);
|
|
1571
|
+
emit('});');
|
|
1572
|
+
emit('<' + '/script>');
|
|
1573
|
+
}
|
|
1499
1574
|
}
|
|
1575
|
+
emit('</');
|
|
1576
|
+
emit(node.data.name);
|
|
1577
|
+
emit('>');
|
|
1578
|
+
inScript = false;
|
|
1500
1579
|
}
|
|
1501
|
-
emit('</');
|
|
1502
|
-
emit(node.data.name);
|
|
1503
|
-
emit('>');
|
|
1504
|
-
inScript = false;
|
|
1505
1580
|
}
|
|
1506
1581
|
} break;
|
|
1507
1582
|
case 'if': {
|
|
@@ -1520,14 +1595,14 @@ module.exports = (config) => {
|
|
|
1520
1595
|
if (t === 'array' || t === 'string') {
|
|
1521
1596
|
for (let i = 0; i < val.length; i++) {
|
|
1522
1597
|
s[it[0]] = val[i];
|
|
1523
|
-
s[it[1]] = i;
|
|
1598
|
+
if (it[1]) s[it[1]] = i;
|
|
1524
1599
|
node.children.forEach(walk);
|
|
1525
1600
|
}
|
|
1526
1601
|
} else if (t === 'object') {
|
|
1527
1602
|
const keys = Object.keys(val);
|
|
1528
1603
|
for (let i = 0; i < keys.length; i++) {
|
|
1529
1604
|
s[it[0]] = keys[i];
|
|
1530
|
-
s[it[1]] = val[keys[i]];
|
|
1605
|
+
if (it[1]) s[it[1]] = val[keys[i]];
|
|
1531
1606
|
node.children.forEach(walk);
|
|
1532
1607
|
}
|
|
1533
1608
|
} else {
|
|
@@ -1804,7 +1879,7 @@ module.exports = (config) => {
|
|
|
1804
1879
|
if (t === 'object' || t === 'null' || t === 'array') {
|
|
1805
1880
|
stack.push(JSON.stringify(val));
|
|
1806
1881
|
} else {
|
|
1807
|
-
stack.push(
|
|
1882
|
+
stack.push(val.toString());
|
|
1808
1883
|
}
|
|
1809
1884
|
} break;
|
|
1810
1885
|
case 'join': {
|
|
@@ -2183,7 +2258,7 @@ module.exports = (config) => {
|
|
|
2183
2258
|
out[out.length - 1].code += txt;
|
|
2184
2259
|
if (fileIdx > -1) {
|
|
2185
2260
|
const n = fileList[fileIdx].name;
|
|
2186
|
-
out[out.length - 1].parent_dir = getPathInfo(n).parent;
|
|
2261
|
+
out[out.length - 1].parent_dir = path ? getPathInfo(n).parent : '/';
|
|
2187
2262
|
}
|
|
2188
2263
|
};
|
|
2189
2264
|
|
|
@@ -2631,7 +2706,8 @@ module.exports = (config) => {
|
|
|
2631
2706
|
|
|
2632
2707
|
createFileList(ast);
|
|
2633
2708
|
|
|
2634
|
-
emit(`document.addEventListener('DOMContentLoaded', function () {\n`);
|
|
2709
|
+
// emit(`document.addEventListener('DOMContentLoaded', function () {\n`);
|
|
2710
|
+
emit('(function () {')
|
|
2635
2711
|
emit(`${light_runtime}`);
|
|
2636
2712
|
emit('var $sync = function () {};\n');
|
|
2637
2713
|
for (let g in globals) {
|
|
@@ -2675,33 +2751,35 @@ module.exports = (config) => {
|
|
|
2675
2751
|
});
|
|
2676
2752
|
|
|
2677
2753
|
emit('$sync();\n');
|
|
2678
|
-
emit('});\n');
|
|
2754
|
+
// emit('});\n');
|
|
2755
|
+
emit('})();\n');
|
|
2679
2756
|
|
|
2680
2757
|
return out;
|
|
2681
2758
|
};
|
|
2682
2759
|
|
|
2683
|
-
const renderToAst = async (file, actions) => {
|
|
2684
|
-
const fileText = openFile(file);
|
|
2760
|
+
const renderToAst = async (file, actions, _fileText) => {
|
|
2761
|
+
const fileText = file === 'default' ? _fileText : openFile(file);
|
|
2685
2762
|
const tokens = tokenize(fileText, file);
|
|
2686
2763
|
const ast = parse(tokens);
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2764
|
+
let js = '';
|
|
2765
|
+
if (includeRuntime) {
|
|
2766
|
+
const runtime = generateRuntime(ast, actions);
|
|
2767
|
+
|
|
2768
|
+
if (config.jsTransform) {
|
|
2769
|
+
js = (await Promise.all(runtime.map(async (chunk) => {
|
|
2770
|
+
if (chunk.transform) {
|
|
2771
|
+
return await config.jsTransform(chunk);
|
|
2772
|
+
}
|
|
2773
|
+
return chunk.code;
|
|
2774
|
+
}))).join('\n');
|
|
2775
|
+
} else {
|
|
2776
|
+
js = runtime.map((chunk) => chunk.code).join('\n');
|
|
2777
|
+
}
|
|
2700
2778
|
|
|
2701
|
-
|
|
2702
|
-
|
|
2779
|
+
if (config.jsPostProcess) {
|
|
2780
|
+
js = await config.jsPostProcess(js);
|
|
2781
|
+
}
|
|
2703
2782
|
}
|
|
2704
|
-
|
|
2705
2783
|
return { ast, js };
|
|
2706
2784
|
};
|
|
2707
2785
|
|
|
@@ -2720,11 +2798,19 @@ module.exports = (config) => {
|
|
|
2720
2798
|
return html;
|
|
2721
2799
|
};
|
|
2722
2800
|
|
|
2801
|
+
const renderString = async (fileText, data) => {
|
|
2802
|
+
_files.default = fileText;
|
|
2803
|
+
const result = await renderToAst('default', [], fileText);
|
|
2804
|
+
const html = renderToHTML(result, data);
|
|
2805
|
+
|
|
2806
|
+
return html;
|
|
2807
|
+
};
|
|
2808
|
+
|
|
2723
2809
|
const renderToCache = async (file, actions) => {
|
|
2724
2810
|
const result = await renderToAst(file, actions);
|
|
2725
2811
|
return JSON.stringify(result);
|
|
2726
2812
|
};
|
|
2727
2813
|
|
|
2728
|
-
return { render, renderToCache, renderToHTML, printError };
|
|
2814
|
+
return { render, renderString, renderToCache, renderToHTML, printError };
|
|
2729
2815
|
};
|
|
2730
2816
|
|
package/index.js
CHANGED