malinajs 0.6.53 → 0.6.56

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 CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
  ## 0.6.x
3
3
 
4
+ * destruncting for "each" for array and object
4
5
  * style's attribute "global"
5
6
  * compound classes (handle mix of class and class directives)
6
7
  * new passing class
package/compile.js CHANGED
@@ -19,7 +19,7 @@ function assert(x, info) {
19
19
 
20
20
  function toCamelCase(name) {
21
21
  assert(name[name.length - 1] !== '-', 'Wrong name');
22
- return name.replace(/(\-\w)/g, function(part) {
22
+ return name.replace(/(?<!-)(\-\w)/g, function(part) {
23
23
  return part[1].toUpperCase();
24
24
  });
25
25
  }
@@ -55,19 +55,10 @@ function detectExpressionType(name) {
55
55
  let ast = acorn.parse(name, {allowReturnOutsideFunction: true});
56
56
 
57
57
  function checkIdentificator(body) {
58
- if(body.length != 1) return;
59
- if(body[0].type != 'ExpressionStatement') return;
60
- if(body[0].expression.type != 'Identifier') return;
61
- return true;
62
- }
63
-
64
- function checkMemberIdentificator(body) {
65
58
  if(body.length != 1) return;
66
59
  if(body[0].type != 'ExpressionStatement') return;
67
60
  let obj = body[0].expression;
68
- if(obj.type != 'MemberExpression') return;
69
- if(obj.property.type != 'Identifier') return;
70
- return true;
61
+ return obj.type == 'Identifier' || obj.type == 'MemberExpression';
71
62
  }
72
63
 
73
64
  function checkFunction(body) {
@@ -79,7 +70,6 @@ function detectExpressionType(name) {
79
70
  }
80
71
 
81
72
  if(checkIdentificator(ast.body)) return 'identifier';
82
- if(checkMemberIdentificator(ast.body)) return 'identifier';
83
73
  if(checkFunction(ast.body)) return 'function';
84
74
 
85
75
  return;
@@ -301,7 +291,7 @@ const extractKeywords = (exp) => {
301
291
 
302
292
  const replaceElementKeyword = (exp, fn) => {
303
293
  let changed = false;
304
- let r = parseJS(exp, (n, pk) => {
294
+ let r = parseJS(exp).transform((n, pk) => {
305
295
  if(n.type != 'Identifier') return;
306
296
  if(pk == 'property' || pk == 'params') return;
307
297
  if(n.name != '$element') return;
@@ -312,38 +302,42 @@ const replaceElementKeyword = (exp, fn) => {
312
302
  };
313
303
 
314
304
 
315
- const parseJS = (exp, fn) => {
316
- let result = {};
317
- let ast = result.ast = acorn.parse(exp, {sourceType: 'module', ecmaVersion: 12});
305
+ const parseJS = (exp) => {
306
+ let self = {};
307
+ self.ast = acorn.parse(exp, {sourceType: 'module', ecmaVersion: 12});
318
308
 
319
- const rec = (n, pk) => {
320
- let self;
321
- if(n.type) {
322
- self = n;
323
- fn?.(n, pk);
324
- }
325
-
326
- for(let k in n) {
327
- if(k == '_parent') continue;
328
- let v = n[k];
329
- if(v == null || typeof(v) != 'object') continue;
330
- if(Array.isArray(v)) {
331
- v.forEach(i => {
332
- i._parent = self || n._parent;
333
- rec(i, k);
334
- });
335
- } else {
336
- v._parent = self || n._parent;
337
- rec(v, k);
309
+ self.transform = function(fn) {
310
+ const rec = (n, pk) => {
311
+ let self;
312
+ if(n.type) {
313
+ self = n;
314
+ fn?.(n, pk);
338
315
  }
339
- }
316
+
317
+ for(let k in n) {
318
+ if(k == '_parent') continue;
319
+ let v = n[k];
320
+ if(v == null || typeof(v) != 'object') continue;
321
+ if(Array.isArray(v)) {
322
+ v.forEach(i => {
323
+ i._parent = self || n._parent;
324
+ rec(i, k);
325
+ });
326
+ } else {
327
+ v._parent = self || n._parent;
328
+ rec(v, k);
329
+ }
330
+ }
331
+ };
332
+ rec(self.ast, null);
333
+
334
+ return self;
340
335
  };
341
- rec(ast, null);
342
336
 
343
- result.build = (data) => {
344
- return astring.generate(data || ast);
337
+ self.build = function(data) {
338
+ return astring.generate(data || self.ast);
345
339
  };
346
- return result;
340
+ return self;
347
341
  };
348
342
 
349
343
 
@@ -5012,7 +5006,7 @@ function makeEachBlock(data, option) {
5012
5006
  assert(rx, `Wrong #each expression '${data.value}'`);
5013
5007
  let arrayName = rx[1];
5014
5008
  let right = rx[2];
5015
- let keyName;
5009
+ let keyName, keyFunction = null;
5016
5010
 
5017
5011
  // get keyName
5018
5012
  rx = right.match(/^(.*)\s*\(\s*([^\(\)]+)\s*\)\s*$/s);
@@ -5022,61 +5016,86 @@ function makeEachBlock(data, option) {
5022
5016
  }
5023
5017
  right = right.trim();
5024
5018
 
5025
- let itemName, indexName, bind0 = null;
5026
- if(right[0] == '{') {
5027
- rx = right.match(/^(\{[^}]+\})(.*)$/s);
5028
- assert(rx, `Wrong #each expression '${data.value}'`);
5029
- let exp = rx[1], keywords;
5019
+ const makeKeyFunction = (keyLink) => {
5020
+ const e = parseJS(keyName).transform((n, pk) => {
5021
+ if(n.type != 'Identifier') return;
5022
+ if(pk == 'property') return;
5023
+ let r = keyLink[n.name];
5024
+ if(r) n.name = r;
5025
+ });
5026
+ let exp = e.build(e.ast.body[0].expression);
5027
+ keyFunction = xNode('key-function', {
5028
+ exp
5029
+ }, (ctx, n) => {
5030
+ ctx.write(`($$item, $index) => ${n.exp}`);
5031
+ });
5032
+ };
5030
5033
 
5034
+ let itemName, indexName, bind0 = null;
5035
+ if(right[0] == '{' || right[0] == '[') {
5036
+ let keywords, unwrap;
5031
5037
  try {
5032
- keywords = acorn.parse(`(${exp} = $$item)`, {sourceType: 'module', ecmaVersion: 12}).body[0].expression.left.properties.map(p => p.key.name);
5038
+ let exp = `[${right}]`;
5039
+ let e = parseJS(exp);
5040
+ assert(e.ast.body.length == 1);
5041
+
5042
+ itemName = '$$item';
5043
+ let n = e.ast.body[0];
5044
+ let a = n.expression.elements[0];
5045
+ unwrap = exp.substring(a.start, a.end);
5046
+ if(n.expression.elements.length == 1) {
5047
+ indexName = '$index';
5048
+ } else {
5049
+ assert(n.expression.elements.length == 2);
5050
+ let b = n.expression.elements[1];
5051
+ assert(b.type == 'Identifier');
5052
+ indexName = exp.substring(b.start, b.end);
5053
+ }
5054
+
5055
+ e = parseJS(`(${unwrap} = $$item)`);
5056
+ let l = e.ast.body[0].expression.left;
5057
+ if(l.type == 'ArrayPattern') {
5058
+ keywords = l.elements.map(p => p.name);
5059
+
5060
+ if(keyName) {
5061
+ let keyLink = {};
5062
+ for(let i in keywords) keyLink[keywords[i]] = `$$item[${i}]`;
5063
+ makeKeyFunction(keyLink);
5064
+ }
5065
+ } else {
5066
+ assert(l.type == 'ObjectPattern');
5067
+ keywords = l.properties.map(p => p.key.name);
5068
+
5069
+ if(keyName) {
5070
+ let keyLink = {};
5071
+ for(let k of keywords) keyLink[k] = `$$item.${k}`;
5072
+ makeKeyFunction(keyLink);
5073
+ }
5074
+ }
5033
5075
  } catch (e) {
5034
5076
  throw new Error('Wrong destructuring in each: ' + data.value);
5035
5077
  }
5036
5078
 
5037
- itemName = '$$item';
5038
- indexName = rx[2].trim();
5039
- if(indexName[0] == ',') indexName = indexName.substring(1).trim();
5040
- indexName = indexName || '$index';
5041
-
5042
5079
  bind0 = xNode('each:unwrap', {
5043
- exp,
5080
+ unwrap,
5044
5081
  keywords
5045
5082
  }, (ctx, n) => {
5046
5083
  ctx.writeLine(`let ${n.keywords.join(', ')};`);
5047
- ctx.writeLine(`$runtime.prefixPush($ctx.cd, () => (${n.exp} = $$item));`);
5084
+ ctx.writeLine(`$runtime.prefixPush($ctx.cd, () => (${n.unwrap} = $$item));`);
5048
5085
  });
5049
5086
  } else {
5050
5087
  rx = right.trim().split(/\s*\,\s*/);
5051
5088
  assert(rx.length <= 2, `Wrong #each expression '${data.value}'`);
5052
5089
  itemName = rx[0];
5053
5090
  indexName = rx[1] || '$index';
5091
+ if(keyName) {
5092
+ if(keyName == itemName) keyFunction = 'noop';
5093
+ else makeKeyFunction({[itemName]: '$$item', [indexName]: '$index'});
5094
+ }
5054
5095
  }
5055
5096
  assert(isSimpleName(itemName), `Wrong name '${itemName}'`);
5056
5097
  assert(isSimpleName(indexName), `Wrong name '${indexName}'`);
5057
5098
 
5058
- let keyFunction = null;
5059
- if(keyName == itemName) {
5060
- keyName = null;
5061
- keyFunction = 'noop';
5062
- }
5063
- if(keyName) assert(detectExpressionType(keyName) == 'identifier', `Wrong key '${keyName}'`);
5064
-
5065
- if(keyName) {
5066
- this.detectDependency(keyName);
5067
- keyFunction = xNode('function', {
5068
- inline: true,
5069
- arrow: true,
5070
- args: [itemName, 'i'],
5071
- body: [xNode('block', {
5072
- index: indexName,
5073
- key: keyName
5074
- }, (ctx, data) => {
5075
- if(data.key == data.index) ctx.writeLine('return i;');
5076
- else ctx.writeLine(`return ${data.key};`);
5077
- })]
5078
- });
5079
- }
5080
5099
  let bind;
5081
5100
  if(itemData.source) {
5082
5101
  bind = xNode('function', {
@@ -5318,7 +5337,7 @@ function attachSlot(slotName, label, node) {
5318
5337
  ctx.build(n.placeholder);
5319
5338
  });
5320
5339
  ctx.write(true, '}');
5321
- } else if(hasDynProps && !this.config.immutable) ctx.write(`, 0`);
5340
+ } else if(hasDynProps && !this.config.immutable) ctx.write(`, null`);
5322
5341
  if(hasDynProps && !this.config.immutable) ctx.write(`, $runtime.$$compareDeep`);
5323
5342
  ctx.write(');\n');
5324
5343
  });
package/malina.js CHANGED
@@ -20,7 +20,7 @@
20
20
 
21
21
  function toCamelCase(name) {
22
22
  assert(name[name.length - 1] !== '-', 'Wrong name');
23
- return name.replace(/(\-\w)/g, function(part) {
23
+ return name.replace(/(?<!-)(\-\w)/g, function(part) {
24
24
  return part[1].toUpperCase();
25
25
  });
26
26
  }
@@ -56,19 +56,10 @@
56
56
  let ast = acorn.parse(name, {allowReturnOutsideFunction: true});
57
57
 
58
58
  function checkIdentificator(body) {
59
- if(body.length != 1) return;
60
- if(body[0].type != 'ExpressionStatement') return;
61
- if(body[0].expression.type != 'Identifier') return;
62
- return true;
63
- }
64
-
65
- function checkMemberIdentificator(body) {
66
59
  if(body.length != 1) return;
67
60
  if(body[0].type != 'ExpressionStatement') return;
68
61
  let obj = body[0].expression;
69
- if(obj.type != 'MemberExpression') return;
70
- if(obj.property.type != 'Identifier') return;
71
- return true;
62
+ return obj.type == 'Identifier' || obj.type == 'MemberExpression';
72
63
  }
73
64
 
74
65
  function checkFunction(body) {
@@ -80,7 +71,6 @@
80
71
  }
81
72
 
82
73
  if(checkIdentificator(ast.body)) return 'identifier';
83
- if(checkMemberIdentificator(ast.body)) return 'identifier';
84
74
  if(checkFunction(ast.body)) return 'function';
85
75
 
86
76
  return;
@@ -302,7 +292,7 @@
302
292
 
303
293
  const replaceElementKeyword = (exp, fn) => {
304
294
  let changed = false;
305
- let r = parseJS(exp, (n, pk) => {
295
+ let r = parseJS(exp).transform((n, pk) => {
306
296
  if(n.type != 'Identifier') return;
307
297
  if(pk == 'property' || pk == 'params') return;
308
298
  if(n.name != '$element') return;
@@ -313,38 +303,42 @@
313
303
  };
314
304
 
315
305
 
316
- const parseJS = (exp, fn) => {
317
- let result = {};
318
- let ast = result.ast = acorn.parse(exp, {sourceType: 'module', ecmaVersion: 12});
306
+ const parseJS = (exp) => {
307
+ let self = {};
308
+ self.ast = acorn.parse(exp, {sourceType: 'module', ecmaVersion: 12});
319
309
 
320
- const rec = (n, pk) => {
321
- let self;
322
- if(n.type) {
323
- self = n;
324
- fn?.(n, pk);
325
- }
326
-
327
- for(let k in n) {
328
- if(k == '_parent') continue;
329
- let v = n[k];
330
- if(v == null || typeof(v) != 'object') continue;
331
- if(Array.isArray(v)) {
332
- v.forEach(i => {
333
- i._parent = self || n._parent;
334
- rec(i, k);
335
- });
336
- } else {
337
- v._parent = self || n._parent;
338
- rec(v, k);
310
+ self.transform = function(fn) {
311
+ const rec = (n, pk) => {
312
+ let self;
313
+ if(n.type) {
314
+ self = n;
315
+ fn?.(n, pk);
339
316
  }
340
- }
317
+
318
+ for(let k in n) {
319
+ if(k == '_parent') continue;
320
+ let v = n[k];
321
+ if(v == null || typeof(v) != 'object') continue;
322
+ if(Array.isArray(v)) {
323
+ v.forEach(i => {
324
+ i._parent = self || n._parent;
325
+ rec(i, k);
326
+ });
327
+ } else {
328
+ v._parent = self || n._parent;
329
+ rec(v, k);
330
+ }
331
+ }
332
+ };
333
+ rec(self.ast, null);
334
+
335
+ return self;
341
336
  };
342
- rec(ast, null);
343
337
 
344
- result.build = (data) => {
345
- return astring.generate(data || ast);
338
+ self.build = function(data) {
339
+ return astring.generate(data || self.ast);
346
340
  };
347
- return result;
341
+ return self;
348
342
  };
349
343
 
350
344
 
@@ -5013,7 +5007,7 @@
5013
5007
  assert(rx, `Wrong #each expression '${data.value}'`);
5014
5008
  let arrayName = rx[1];
5015
5009
  let right = rx[2];
5016
- let keyName;
5010
+ let keyName, keyFunction = null;
5017
5011
 
5018
5012
  // get keyName
5019
5013
  rx = right.match(/^(.*)\s*\(\s*([^\(\)]+)\s*\)\s*$/s);
@@ -5023,61 +5017,86 @@
5023
5017
  }
5024
5018
  right = right.trim();
5025
5019
 
5026
- let itemName, indexName, bind0 = null;
5027
- if(right[0] == '{') {
5028
- rx = right.match(/^(\{[^}]+\})(.*)$/s);
5029
- assert(rx, `Wrong #each expression '${data.value}'`);
5030
- let exp = rx[1], keywords;
5020
+ const makeKeyFunction = (keyLink) => {
5021
+ const e = parseJS(keyName).transform((n, pk) => {
5022
+ if(n.type != 'Identifier') return;
5023
+ if(pk == 'property') return;
5024
+ let r = keyLink[n.name];
5025
+ if(r) n.name = r;
5026
+ });
5027
+ let exp = e.build(e.ast.body[0].expression);
5028
+ keyFunction = xNode('key-function', {
5029
+ exp
5030
+ }, (ctx, n) => {
5031
+ ctx.write(`($$item, $index) => ${n.exp}`);
5032
+ });
5033
+ };
5031
5034
 
5035
+ let itemName, indexName, bind0 = null;
5036
+ if(right[0] == '{' || right[0] == '[') {
5037
+ let keywords, unwrap;
5032
5038
  try {
5033
- keywords = acorn.parse(`(${exp} = $$item)`, {sourceType: 'module', ecmaVersion: 12}).body[0].expression.left.properties.map(p => p.key.name);
5039
+ let exp = `[${right}]`;
5040
+ let e = parseJS(exp);
5041
+ assert(e.ast.body.length == 1);
5042
+
5043
+ itemName = '$$item';
5044
+ let n = e.ast.body[0];
5045
+ let a = n.expression.elements[0];
5046
+ unwrap = exp.substring(a.start, a.end);
5047
+ if(n.expression.elements.length == 1) {
5048
+ indexName = '$index';
5049
+ } else {
5050
+ assert(n.expression.elements.length == 2);
5051
+ let b = n.expression.elements[1];
5052
+ assert(b.type == 'Identifier');
5053
+ indexName = exp.substring(b.start, b.end);
5054
+ }
5055
+
5056
+ e = parseJS(`(${unwrap} = $$item)`);
5057
+ let l = e.ast.body[0].expression.left;
5058
+ if(l.type == 'ArrayPattern') {
5059
+ keywords = l.elements.map(p => p.name);
5060
+
5061
+ if(keyName) {
5062
+ let keyLink = {};
5063
+ for(let i in keywords) keyLink[keywords[i]] = `$$item[${i}]`;
5064
+ makeKeyFunction(keyLink);
5065
+ }
5066
+ } else {
5067
+ assert(l.type == 'ObjectPattern');
5068
+ keywords = l.properties.map(p => p.key.name);
5069
+
5070
+ if(keyName) {
5071
+ let keyLink = {};
5072
+ for(let k of keywords) keyLink[k] = `$$item.${k}`;
5073
+ makeKeyFunction(keyLink);
5074
+ }
5075
+ }
5034
5076
  } catch (e) {
5035
5077
  throw new Error('Wrong destructuring in each: ' + data.value);
5036
5078
  }
5037
5079
 
5038
- itemName = '$$item';
5039
- indexName = rx[2].trim();
5040
- if(indexName[0] == ',') indexName = indexName.substring(1).trim();
5041
- indexName = indexName || '$index';
5042
-
5043
5080
  bind0 = xNode('each:unwrap', {
5044
- exp,
5081
+ unwrap,
5045
5082
  keywords
5046
5083
  }, (ctx, n) => {
5047
5084
  ctx.writeLine(`let ${n.keywords.join(', ')};`);
5048
- ctx.writeLine(`$runtime.prefixPush($ctx.cd, () => (${n.exp} = $$item));`);
5085
+ ctx.writeLine(`$runtime.prefixPush($ctx.cd, () => (${n.unwrap} = $$item));`);
5049
5086
  });
5050
5087
  } else {
5051
5088
  rx = right.trim().split(/\s*\,\s*/);
5052
5089
  assert(rx.length <= 2, `Wrong #each expression '${data.value}'`);
5053
5090
  itemName = rx[0];
5054
5091
  indexName = rx[1] || '$index';
5092
+ if(keyName) {
5093
+ if(keyName == itemName) keyFunction = 'noop';
5094
+ else makeKeyFunction({[itemName]: '$$item', [indexName]: '$index'});
5095
+ }
5055
5096
  }
5056
5097
  assert(isSimpleName(itemName), `Wrong name '${itemName}'`);
5057
5098
  assert(isSimpleName(indexName), `Wrong name '${indexName}'`);
5058
5099
 
5059
- let keyFunction = null;
5060
- if(keyName == itemName) {
5061
- keyName = null;
5062
- keyFunction = 'noop';
5063
- }
5064
- if(keyName) assert(detectExpressionType(keyName) == 'identifier', `Wrong key '${keyName}'`);
5065
-
5066
- if(keyName) {
5067
- this.detectDependency(keyName);
5068
- keyFunction = xNode('function', {
5069
- inline: true,
5070
- arrow: true,
5071
- args: [itemName, 'i'],
5072
- body: [xNode('block', {
5073
- index: indexName,
5074
- key: keyName
5075
- }, (ctx, data) => {
5076
- if(data.key == data.index) ctx.writeLine('return i;');
5077
- else ctx.writeLine(`return ${data.key};`);
5078
- })]
5079
- });
5080
- }
5081
5100
  let bind;
5082
5101
  if(itemData.source) {
5083
5102
  bind = xNode('function', {
@@ -5319,7 +5338,7 @@
5319
5338
  ctx.build(n.placeholder);
5320
5339
  });
5321
5340
  ctx.write(true, '}');
5322
- } else if(hasDynProps && !this.config.immutable) ctx.write(`, 0`);
5341
+ } else if(hasDynProps && !this.config.immutable) ctx.write(`, null`);
5323
5342
  if(hasDynProps && !this.config.immutable) ctx.write(`, $runtime.$$compareDeep`);
5324
5343
  ctx.write(');\n');
5325
5344
  });
@@ -5898,7 +5917,7 @@
5898
5917
  return {event, fn};
5899
5918
  }
5900
5919
 
5901
- const version = '0.6.53';
5920
+ const version = '0.6.56';
5902
5921
 
5903
5922
 
5904
5923
  async function compile(source, config = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "malinajs",
3
- "version": "0.6.53",
3
+ "version": "0.6.56",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "prepare": "npm run build",
package/runtime.js CHANGED
@@ -510,7 +510,7 @@ const bindText = (cd, element, fn) => {
510
510
 
511
511
  const bindStyle = (cd, element, name, fn) => {
512
512
  $watchReadOnly(cd, fn, (value) => {
513
- element.style[name] = value;
513
+ element.style.setProperty(name, value);
514
514
  });
515
515
  };
516
516