@cilix/lightjs 0.0.5 → 0.0.7

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.
Files changed (3) hide show
  1. package/core.js +115 -36
  2. package/index.js +13 -3
  3. 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
- const fs = require('fs');
23
- const path = require("path");
24
-
25
- module.exports = (config) => {
22
+ module.exports = (config, fs, path) => {
26
23
  const _files = {};
24
+ let includeRuntime;
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--;
1123
+ }
1124
+
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;
1115
1176
  }
1116
1177
 
1117
- const parse_tag_list = () => {
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, head: false, body: 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
  }
@@ -1497,11 +1564,13 @@ module.exports = (config) => {
1497
1564
  } else {
1498
1565
  node.children.forEach(walk);
1499
1566
  if (node.data.name === 'head') {
1500
- emit('<script>');
1501
- emit(`document.addEventListener('DOMContentLoaded', function () {\n`);
1502
- emit(`(function (data){${js}})(${JSON.stringify(initial_state)})`);
1503
- emit('});');
1504
- emit('<' + '/script>');
1567
+ if (js) {
1568
+ emit('<script type="module">');
1569
+ emit(`document.addEventListener('DOMContentLoaded', function () {\n`);
1570
+ emit(`(function (data){${js}})(${JSON.stringify(initial_state)})`);
1571
+ emit('});');
1572
+ emit('<' + '/script>');
1573
+ }
1505
1574
  }
1506
1575
  emit('</');
1507
1576
  emit(node.data.name);
@@ -2189,7 +2258,7 @@ module.exports = (config) => {
2189
2258
  out[out.length - 1].code += txt;
2190
2259
  if (fileIdx > -1) {
2191
2260
  const n = fileList[fileIdx].name;
2192
- out[out.length - 1].parent_dir = getPathInfo(n).parent;
2261
+ out[out.length - 1].parent_dir = path ? getPathInfo(n).parent : '/';
2193
2262
  }
2194
2263
  };
2195
2264
 
@@ -2688,28 +2757,30 @@ module.exports = (config) => {
2688
2757
  return out;
2689
2758
  };
2690
2759
 
2691
- const renderToAst = async (file, actions) => {
2692
- const fileText = openFile(file);
2760
+ const renderToAst = async (file, actions, _fileText) => {
2761
+ includeRuntime = false;
2762
+ const fileText = file === 'default' ? _fileText : openFile(file);
2693
2763
  const tokens = tokenize(fileText, file);
2694
2764
  const ast = parse(tokens);
2695
- const runtime = generateRuntime(ast, actions);
2696
2765
  let js;
2766
+ if (includeRuntime) {
2767
+ const runtime = generateRuntime(ast, actions);
2697
2768
 
2698
- if (config.jsTransform) {
2699
- js = (await Promise.all(runtime.map(async (chunk) => {
2700
- if (chunk.transform) {
2701
- return await config.jsTransform(chunk);
2702
- }
2703
- return chunk.code;
2704
- }))).join('\n');
2705
- } else {
2706
- js = runtime.map((chunk) => chunk.code).join('\n');
2707
- }
2769
+ if (config.jsTransform) {
2770
+ js = (await Promise.all(runtime.map(async (chunk) => {
2771
+ if (chunk.transform) {
2772
+ return await config.jsTransform(chunk);
2773
+ }
2774
+ return chunk.code;
2775
+ }))).join('\n');
2776
+ } else {
2777
+ js = runtime.map((chunk) => chunk.code).join('\n');
2778
+ }
2708
2779
 
2709
- if (config.jsPostProcess) {
2710
- js = await config.jsPostProcess(js);
2780
+ if (config.jsPostProcess) {
2781
+ js = await config.jsPostProcess(js);
2782
+ }
2711
2783
  }
2712
-
2713
2784
  return { ast, js };
2714
2785
  };
2715
2786
 
@@ -2728,11 +2799,19 @@ module.exports = (config) => {
2728
2799
  return html;
2729
2800
  };
2730
2801
 
2802
+ const renderString = async (fileText, data) => {
2803
+ _files.default = fileText;
2804
+ const result = await renderToAst('default', [], fileText);
2805
+ const html = renderToHTML(result, data);
2806
+
2807
+ return html;
2808
+ };
2809
+
2731
2810
  const renderToCache = async (file, actions) => {
2732
2811
  const result = await renderToAst(file, actions);
2733
2812
  return JSON.stringify(result);
2734
2813
  };
2735
2814
 
2736
- return { render, renderToCache, renderToHTML, printError };
2815
+ return { render, renderString, renderToCache, renderToHTML, printError };
2737
2816
  };
2738
2817
 
package/index.js CHANGED
@@ -53,6 +53,14 @@ const addParentPaths = (code, p) => {
53
53
  return out;
54
54
  };
55
55
 
56
+ const hideDynamicImports = (code) => {
57
+ return code.split('import(').join('__IMPORT_PLACEHOLDER__(');
58
+ };
59
+
60
+ const restoreDynamicImports = (code) => {
61
+ return code.split('__IMPORT_PLACEHOLDER__(').join('import(');
62
+ };
63
+
56
64
  const esbuild_to_light_error = (e, chunk) => {
57
65
  let row = e.location.line - 1;
58
66
  let col = e.location.column;
@@ -88,7 +96,8 @@ Light.compile = async (name, opts) => {
88
96
  jsTransform: async (chunk) => {
89
97
  try {
90
98
  const opts = { format: 'cjs', loader: 'ts' };
91
- const result = await esbuild.transform(chunk.code, opts);
99
+ const codeChunk = hideDynamicImports(chunk.code);
100
+ const result = await esbuild.transform(codeChunk, opts);
92
101
  return addParentPaths(result.code, chunk.parent_dir);
93
102
  } catch (e) {
94
103
  e.origin = 'esbuild';
@@ -106,9 +115,10 @@ Light.compile = async (name, opts) => {
106
115
  minify: opts.minify,
107
116
  write: false
108
117
  });
109
- return result.outputFiles[0].text;
118
+ const output = restoreDynamicImports(result.outputFiles[0].text);
119
+ return output;
110
120
  }
111
- });
121
+ }, fs, path);
112
122
  try {
113
123
  let html;
114
124
  if (opts.cache) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cilix/lightjs",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "A new kind of JavaScript framework",
5
5
  "main": "index.js",
6
6
  "scripts": {