malinajs 0.6.55 → 0.6.58

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
@@ -291,7 +291,7 @@ const extractKeywords = (exp) => {
291
291
 
292
292
  const replaceElementKeyword = (exp, fn) => {
293
293
  let changed = false;
294
- let r = parseJS(exp, (n, pk) => {
294
+ let r = parseJS(exp).transform((n, pk) => {
295
295
  if(n.type != 'Identifier') return;
296
296
  if(pk == 'property' || pk == 'params') return;
297
297
  if(n.name != '$element') return;
@@ -302,38 +302,42 @@ const replaceElementKeyword = (exp, fn) => {
302
302
  };
303
303
 
304
304
 
305
- const parseJS = (exp, fn) => {
306
- let result = {};
307
- 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});
308
308
 
309
- const rec = (n, pk) => {
310
- let self;
311
- if(n.type) {
312
- self = n;
313
- fn?.(n, pk);
314
- }
315
-
316
- for(let k in n) {
317
- if(k == '_parent') continue;
318
- let v = n[k];
319
- if(v == null || typeof(v) != 'object') continue;
320
- if(Array.isArray(v)) {
321
- v.forEach(i => {
322
- i._parent = self || n._parent;
323
- rec(i, k);
324
- });
325
- } else {
326
- v._parent = self || n._parent;
327
- 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);
328
315
  }
329
- }
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;
330
335
  };
331
- rec(ast, null);
332
336
 
333
- result.build = (data) => {
334
- return astring.generate(data || ast);
337
+ self.build = function(data) {
338
+ return astring.generate(data || self.ast);
335
339
  };
336
- return result;
340
+ return self;
337
341
  };
338
342
 
339
343
 
@@ -1243,7 +1247,7 @@ function transform() {
1243
1247
  function walk(node, parent, fn) {
1244
1248
  if(typeof node !== 'object') return;
1245
1249
 
1246
- if(node._apply) return;
1250
+ if(node._apply && node.type == 'ExpressionStatement') return;
1247
1251
  node._parent = parent;
1248
1252
  let forParent = parent;
1249
1253
  if(node.type) {
@@ -4021,7 +4025,10 @@ function makeDom(data) {
4021
4025
  let n = new Node(e.name, {__node: e});
4022
4026
  e.attributes.forEach(a => {
4023
4027
  if(a.name == 'class') {
4024
- if(a.value != null) n.className += ' ' + a.value;
4028
+ if(a.value != null) {
4029
+ if(a.value.includes('{')) n.dynClass = true;
4030
+ else n.className += ' ' + a.value;
4031
+ }
4025
4032
  n.attributes[a.name] = a.value;
4026
4033
  } else if(a.name == 'id') n.attributes.id = n.id = a.value;
4027
4034
  else if(a.name.startsWith('class:')) {
@@ -4098,12 +4105,16 @@ Node.prototype.getElementsByClassName = function(names) {
4098
4105
  if(names.length != 1) throw 'Not supported';
4099
4106
  let cls = names[0];
4100
4107
 
4108
+ let rx = RegExp('(^|\\s)' + cls + '(\\s|$)', 'i');
4101
4109
  let result = [];
4102
- this.childNodes.forEach(n => {
4103
- let rx = RegExp('(^|\\s)' + cls + '(\\s|$)', 'i');
4104
- if(rx.test(n.className)) result.push(n);
4105
- result.push.apply(result, n.getElementsByClassName(cls));
4106
- });
4110
+ const walk = (node) => {
4111
+ node.childNodes.forEach(n => {
4112
+ if(n.dynClass) result.push(n);
4113
+ else if(rx.test(n.className)) result.push(n);
4114
+ walk(n);
4115
+ });
4116
+ };
4117
+ walk(this);
4107
4118
  return result;
4108
4119
  };
4109
4120
 
@@ -5002,7 +5013,7 @@ function makeEachBlock(data, option) {
5002
5013
  assert(rx, `Wrong #each expression '${data.value}'`);
5003
5014
  let arrayName = rx[1];
5004
5015
  let right = rx[2];
5005
- let keyName;
5016
+ let keyName, keyFunction = null;
5006
5017
 
5007
5018
  // get keyName
5008
5019
  rx = right.match(/^(.*)\s*\(\s*([^\(\)]+)\s*\)\s*$/s);
@@ -5012,61 +5023,86 @@ function makeEachBlock(data, option) {
5012
5023
  }
5013
5024
  right = right.trim();
5014
5025
 
5015
- let itemName, indexName, bind0 = null;
5016
- if(right[0] == '{') {
5017
- rx = right.match(/^(\{[^}]+\})(.*)$/s);
5018
- assert(rx, `Wrong #each expression '${data.value}'`);
5019
- let exp = rx[1], keywords;
5026
+ const makeKeyFunction = (keyLink) => {
5027
+ const e = parseJS(keyName).transform((n, pk) => {
5028
+ if(n.type != 'Identifier') return;
5029
+ if(pk == 'property') return;
5030
+ let r = keyLink[n.name];
5031
+ if(r) n.name = r;
5032
+ });
5033
+ let exp = e.build(e.ast.body[0].expression);
5034
+ keyFunction = xNode('key-function', {
5035
+ exp
5036
+ }, (ctx, n) => {
5037
+ ctx.write(`($$item, $index) => ${n.exp}`);
5038
+ });
5039
+ };
5020
5040
 
5041
+ let itemName, indexName, bind0 = null;
5042
+ if(right[0] == '{' || right[0] == '[') {
5043
+ let keywords, unwrap;
5021
5044
  try {
5022
- keywords = acorn.parse(`(${exp} = $$item)`, {sourceType: 'module', ecmaVersion: 12}).body[0].expression.left.properties.map(p => p.key.name);
5045
+ let exp = `[${right}]`;
5046
+ let e = parseJS(exp);
5047
+ assert(e.ast.body.length == 1);
5048
+
5049
+ itemName = '$$item';
5050
+ let n = e.ast.body[0];
5051
+ let a = n.expression.elements[0];
5052
+ unwrap = exp.substring(a.start, a.end);
5053
+ if(n.expression.elements.length == 1) {
5054
+ indexName = '$index';
5055
+ } else {
5056
+ assert(n.expression.elements.length == 2);
5057
+ let b = n.expression.elements[1];
5058
+ assert(b.type == 'Identifier');
5059
+ indexName = exp.substring(b.start, b.end);
5060
+ }
5061
+
5062
+ e = parseJS(`(${unwrap} = $$item)`);
5063
+ let l = e.ast.body[0].expression.left;
5064
+ if(l.type == 'ArrayPattern') {
5065
+ keywords = l.elements.map(p => p.name);
5066
+
5067
+ if(keyName) {
5068
+ let keyLink = {};
5069
+ for(let i in keywords) keyLink[keywords[i]] = `$$item[${i}]`;
5070
+ makeKeyFunction(keyLink);
5071
+ }
5072
+ } else {
5073
+ assert(l.type == 'ObjectPattern');
5074
+ keywords = l.properties.map(p => p.key.name);
5075
+
5076
+ if(keyName) {
5077
+ let keyLink = {};
5078
+ for(let k of keywords) keyLink[k] = `$$item.${k}`;
5079
+ makeKeyFunction(keyLink);
5080
+ }
5081
+ }
5023
5082
  } catch (e) {
5024
5083
  throw new Error('Wrong destructuring in each: ' + data.value);
5025
5084
  }
5026
5085
 
5027
- itemName = '$$item';
5028
- indexName = rx[2].trim();
5029
- if(indexName[0] == ',') indexName = indexName.substring(1).trim();
5030
- indexName = indexName || '$index';
5031
-
5032
5086
  bind0 = xNode('each:unwrap', {
5033
- exp,
5087
+ unwrap,
5034
5088
  keywords
5035
5089
  }, (ctx, n) => {
5036
5090
  ctx.writeLine(`let ${n.keywords.join(', ')};`);
5037
- ctx.writeLine(`$runtime.prefixPush($ctx.cd, () => (${n.exp} = $$item));`);
5091
+ ctx.writeLine(`$runtime.prefixPush($ctx.cd, () => (${n.unwrap} = $$item));`);
5038
5092
  });
5039
5093
  } else {
5040
5094
  rx = right.trim().split(/\s*\,\s*/);
5041
5095
  assert(rx.length <= 2, `Wrong #each expression '${data.value}'`);
5042
5096
  itemName = rx[0];
5043
5097
  indexName = rx[1] || '$index';
5098
+ if(keyName) {
5099
+ if(keyName == itemName) keyFunction = 'noop';
5100
+ else makeKeyFunction({[itemName]: '$$item', [indexName]: '$index'});
5101
+ }
5044
5102
  }
5045
5103
  assert(isSimpleName(itemName), `Wrong name '${itemName}'`);
5046
5104
  assert(isSimpleName(indexName), `Wrong name '${indexName}'`);
5047
5105
 
5048
- let keyFunction = null;
5049
- if(keyName == itemName) {
5050
- keyName = null;
5051
- keyFunction = 'noop';
5052
- }
5053
- if(keyName) assert(detectExpressionType(keyName) == 'identifier', `Wrong key '${keyName}'`);
5054
-
5055
- if(keyName) {
5056
- this.detectDependency(keyName);
5057
- keyFunction = xNode('function', {
5058
- inline: true,
5059
- arrow: true,
5060
- args: [itemName, 'i'],
5061
- body: [xNode('block', {
5062
- index: indexName,
5063
- key: keyName
5064
- }, (ctx, data) => {
5065
- if(data.key == data.index) ctx.writeLine('return i;');
5066
- else ctx.writeLine(`return ${data.key};`);
5067
- })]
5068
- });
5069
- }
5070
5106
  let bind;
5071
5107
  if(itemData.source) {
5072
5108
  bind = xNode('function', {
package/malina.js CHANGED
@@ -292,7 +292,7 @@
292
292
 
293
293
  const replaceElementKeyword = (exp, fn) => {
294
294
  let changed = false;
295
- let r = parseJS(exp, (n, pk) => {
295
+ let r = parseJS(exp).transform((n, pk) => {
296
296
  if(n.type != 'Identifier') return;
297
297
  if(pk == 'property' || pk == 'params') return;
298
298
  if(n.name != '$element') return;
@@ -303,38 +303,42 @@
303
303
  };
304
304
 
305
305
 
306
- const parseJS = (exp, fn) => {
307
- let result = {};
308
- 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});
309
309
 
310
- const rec = (n, pk) => {
311
- let self;
312
- if(n.type) {
313
- self = n;
314
- fn?.(n, pk);
315
- }
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);
310
+ self.transform = function(fn) {
311
+ const rec = (n, pk) => {
312
+ let self;
313
+ if(n.type) {
314
+ self = n;
315
+ fn?.(n, pk);
329
316
  }
330
- }
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;
331
336
  };
332
- rec(ast, null);
333
337
 
334
- result.build = (data) => {
335
- return astring.generate(data || ast);
338
+ self.build = function(data) {
339
+ return astring.generate(data || self.ast);
336
340
  };
337
- return result;
341
+ return self;
338
342
  };
339
343
 
340
344
 
@@ -1244,7 +1248,7 @@
1244
1248
  function walk(node, parent, fn) {
1245
1249
  if(typeof node !== 'object') return;
1246
1250
 
1247
- if(node._apply) return;
1251
+ if(node._apply && node.type == 'ExpressionStatement') return;
1248
1252
  node._parent = parent;
1249
1253
  let forParent = parent;
1250
1254
  if(node.type) {
@@ -4022,7 +4026,10 @@
4022
4026
  let n = new Node(e.name, {__node: e});
4023
4027
  e.attributes.forEach(a => {
4024
4028
  if(a.name == 'class') {
4025
- if(a.value != null) n.className += ' ' + a.value;
4029
+ if(a.value != null) {
4030
+ if(a.value.includes('{')) n.dynClass = true;
4031
+ else n.className += ' ' + a.value;
4032
+ }
4026
4033
  n.attributes[a.name] = a.value;
4027
4034
  } else if(a.name == 'id') n.attributes.id = n.id = a.value;
4028
4035
  else if(a.name.startsWith('class:')) {
@@ -4099,12 +4106,16 @@
4099
4106
  if(names.length != 1) throw 'Not supported';
4100
4107
  let cls = names[0];
4101
4108
 
4109
+ let rx = RegExp('(^|\\s)' + cls + '(\\s|$)', 'i');
4102
4110
  let result = [];
4103
- this.childNodes.forEach(n => {
4104
- let rx = RegExp('(^|\\s)' + cls + '(\\s|$)', 'i');
4105
- if(rx.test(n.className)) result.push(n);
4106
- result.push.apply(result, n.getElementsByClassName(cls));
4107
- });
4111
+ const walk = (node) => {
4112
+ node.childNodes.forEach(n => {
4113
+ if(n.dynClass) result.push(n);
4114
+ else if(rx.test(n.className)) result.push(n);
4115
+ walk(n);
4116
+ });
4117
+ };
4118
+ walk(this);
4108
4119
  return result;
4109
4120
  };
4110
4121
 
@@ -5003,7 +5014,7 @@
5003
5014
  assert(rx, `Wrong #each expression '${data.value}'`);
5004
5015
  let arrayName = rx[1];
5005
5016
  let right = rx[2];
5006
- let keyName;
5017
+ let keyName, keyFunction = null;
5007
5018
 
5008
5019
  // get keyName
5009
5020
  rx = right.match(/^(.*)\s*\(\s*([^\(\)]+)\s*\)\s*$/s);
@@ -5013,61 +5024,86 @@
5013
5024
  }
5014
5025
  right = right.trim();
5015
5026
 
5016
- let itemName, indexName, bind0 = null;
5017
- if(right[0] == '{') {
5018
- rx = right.match(/^(\{[^}]+\})(.*)$/s);
5019
- assert(rx, `Wrong #each expression '${data.value}'`);
5020
- let exp = rx[1], keywords;
5027
+ const makeKeyFunction = (keyLink) => {
5028
+ const e = parseJS(keyName).transform((n, pk) => {
5029
+ if(n.type != 'Identifier') return;
5030
+ if(pk == 'property') return;
5031
+ let r = keyLink[n.name];
5032
+ if(r) n.name = r;
5033
+ });
5034
+ let exp = e.build(e.ast.body[0].expression);
5035
+ keyFunction = xNode('key-function', {
5036
+ exp
5037
+ }, (ctx, n) => {
5038
+ ctx.write(`($$item, $index) => ${n.exp}`);
5039
+ });
5040
+ };
5021
5041
 
5042
+ let itemName, indexName, bind0 = null;
5043
+ if(right[0] == '{' || right[0] == '[') {
5044
+ let keywords, unwrap;
5022
5045
  try {
5023
- keywords = acorn.parse(`(${exp} = $$item)`, {sourceType: 'module', ecmaVersion: 12}).body[0].expression.left.properties.map(p => p.key.name);
5046
+ let exp = `[${right}]`;
5047
+ let e = parseJS(exp);
5048
+ assert(e.ast.body.length == 1);
5049
+
5050
+ itemName = '$$item';
5051
+ let n = e.ast.body[0];
5052
+ let a = n.expression.elements[0];
5053
+ unwrap = exp.substring(a.start, a.end);
5054
+ if(n.expression.elements.length == 1) {
5055
+ indexName = '$index';
5056
+ } else {
5057
+ assert(n.expression.elements.length == 2);
5058
+ let b = n.expression.elements[1];
5059
+ assert(b.type == 'Identifier');
5060
+ indexName = exp.substring(b.start, b.end);
5061
+ }
5062
+
5063
+ e = parseJS(`(${unwrap} = $$item)`);
5064
+ let l = e.ast.body[0].expression.left;
5065
+ if(l.type == 'ArrayPattern') {
5066
+ keywords = l.elements.map(p => p.name);
5067
+
5068
+ if(keyName) {
5069
+ let keyLink = {};
5070
+ for(let i in keywords) keyLink[keywords[i]] = `$$item[${i}]`;
5071
+ makeKeyFunction(keyLink);
5072
+ }
5073
+ } else {
5074
+ assert(l.type == 'ObjectPattern');
5075
+ keywords = l.properties.map(p => p.key.name);
5076
+
5077
+ if(keyName) {
5078
+ let keyLink = {};
5079
+ for(let k of keywords) keyLink[k] = `$$item.${k}`;
5080
+ makeKeyFunction(keyLink);
5081
+ }
5082
+ }
5024
5083
  } catch (e) {
5025
5084
  throw new Error('Wrong destructuring in each: ' + data.value);
5026
5085
  }
5027
5086
 
5028
- itemName = '$$item';
5029
- indexName = rx[2].trim();
5030
- if(indexName[0] == ',') indexName = indexName.substring(1).trim();
5031
- indexName = indexName || '$index';
5032
-
5033
5087
  bind0 = xNode('each:unwrap', {
5034
- exp,
5088
+ unwrap,
5035
5089
  keywords
5036
5090
  }, (ctx, n) => {
5037
5091
  ctx.writeLine(`let ${n.keywords.join(', ')};`);
5038
- ctx.writeLine(`$runtime.prefixPush($ctx.cd, () => (${n.exp} = $$item));`);
5092
+ ctx.writeLine(`$runtime.prefixPush($ctx.cd, () => (${n.unwrap} = $$item));`);
5039
5093
  });
5040
5094
  } else {
5041
5095
  rx = right.trim().split(/\s*\,\s*/);
5042
5096
  assert(rx.length <= 2, `Wrong #each expression '${data.value}'`);
5043
5097
  itemName = rx[0];
5044
5098
  indexName = rx[1] || '$index';
5099
+ if(keyName) {
5100
+ if(keyName == itemName) keyFunction = 'noop';
5101
+ else makeKeyFunction({[itemName]: '$$item', [indexName]: '$index'});
5102
+ }
5045
5103
  }
5046
5104
  assert(isSimpleName(itemName), `Wrong name '${itemName}'`);
5047
5105
  assert(isSimpleName(indexName), `Wrong name '${indexName}'`);
5048
5106
 
5049
- let keyFunction = null;
5050
- if(keyName == itemName) {
5051
- keyName = null;
5052
- keyFunction = 'noop';
5053
- }
5054
- if(keyName) assert(detectExpressionType(keyName) == 'identifier', `Wrong key '${keyName}'`);
5055
-
5056
- if(keyName) {
5057
- this.detectDependency(keyName);
5058
- keyFunction = xNode('function', {
5059
- inline: true,
5060
- arrow: true,
5061
- args: [itemName, 'i'],
5062
- body: [xNode('block', {
5063
- index: indexName,
5064
- key: keyName
5065
- }, (ctx, data) => {
5066
- if(data.key == data.index) ctx.writeLine('return i;');
5067
- else ctx.writeLine(`return ${data.key};`);
5068
- })]
5069
- });
5070
- }
5071
5107
  let bind;
5072
5108
  if(itemData.source) {
5073
5109
  bind = xNode('function', {
@@ -5888,7 +5924,7 @@
5888
5924
  return {event, fn};
5889
5925
  }
5890
5926
 
5891
- const version = '0.6.55';
5927
+ const version = '0.6.58';
5892
5928
 
5893
5929
 
5894
5930
  async function compile(source, config = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "malinajs",
3
- "version": "0.6.55",
3
+ "version": "0.6.58",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "prepare": "npm run build",