@sola-air-ui/compiler 1.5.1 → 1.5.3

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +41 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sola-air-ui/compiler",
3
- "version": "1.5.1",
3
+ "version": "1.5.3",
4
4
  "description": "Compiler for Sola single-file components (.sola) \u2014 transforms template + script + style to ES modules",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/index.js CHANGED
@@ -1301,7 +1301,7 @@ export function compile(source, options = {}) {
1301
1301
  }
1302
1302
  }
1303
1303
 
1304
- function emitNode(node, parentVar, locals = new Set()) {
1304
+ function emitNode(node, parentVar, locals = new Set(), inSvg = false) {
1305
1305
  if (!node) return;
1306
1306
  // Template-expression rewrite with the current template scope (each-item /
1307
1307
  // each-index names shadow signals of the same name).
@@ -1450,7 +1450,7 @@ export function compile(source, options = {}) {
1450
1450
  domCode += ` ${cid}_ctx = pushContext();\n`;
1451
1451
  domCode += ` try {\n`;
1452
1452
  domCode += ` const f = document.createDocumentFragment();\n`;
1453
- branch.children.forEach(child => emitNode(child, 'f', locals));
1453
+ branch.children.forEach(child => emitNode(child, 'f', locals, inSvg));
1454
1454
  domCode += ` Array.from(f.childNodes).forEach(n => ${cid}_els.push(n));\n`;
1455
1455
  domCode += ` ${cid}_a.parentNode.insertBefore(f, ${cid}_a.nextSibling);\n`;
1456
1456
  domCode += ` } finally { popContext(${cid}_ctx); }\n`;
@@ -1504,12 +1504,24 @@ export function compile(source, options = {}) {
1504
1504
  domCode += ` const _key = String(${keyExpr});\n`;
1505
1505
  domCode += ` _seen.add(_key);\n`;
1506
1506
  domCode += ` let _entry = ${eid}_keyMap.get(_key);\n`;
1507
+ // A row's bindings read the item it was built with. When the list hands
1508
+ // back a different object for the same key (an immutable update such as
1509
+ // items.map(i => i.id === id ? { ...i, done: true } : i)), or the index the
1510
+ // row shows has changed, rebuild that row; rows whose item is the same
1511
+ // object are kept as they are.
1512
+ domCode += ` if (_entry && (_entry.item !== ${node.attribs.item}${node.attribs.index ? ` || _entry.index !== _i` : ''})) {\n`;
1513
+ domCode += ` __flush_destroys(_entry.ctx);\n`;
1514
+ domCode += ` const _old = _entry.nodes;\n`;
1515
+ domCode += ` if (_old.includes(_cursor)) _cursor = _old[_old.length - 1].nextSibling;\n`;
1516
+ domCode += ` _old.forEach(n => n.remove());\n`;
1517
+ domCode += ` _entry = null;\n`;
1518
+ domCode += ` }\n`;
1507
1519
  domCode += ` if (!_entry) {\n`;
1508
1520
  domCode += ` const _kctx = pushContext();\n`;
1509
1521
  domCode += ` try {\n`;
1510
1522
  domCode += ` const f = document.createDocumentFragment();\n`;
1511
- node.children.forEach(child => emitNode(child, 'f', eachLocals));
1512
- domCode += ` _entry = { nodes: Array.from(f.childNodes), ctx: _kctx };\n`;
1523
+ node.children.forEach(child => emitNode(child, 'f', eachLocals, inSvg));
1524
+ domCode += ` _entry = { nodes: Array.from(f.childNodes), ctx: _kctx, item: ${node.attribs.item}${node.attribs.index ? ', index: _i' : ''} };\n`;
1513
1525
  domCode += ` } finally { popContext(_kctx); }\n`;
1514
1526
  domCode += ` ${eid}_keyMap.set(_key, _entry);\n`;
1515
1527
  domCode += ` }\n`;
@@ -1537,7 +1549,7 @@ export function compile(source, options = {}) {
1537
1549
  domCode += ` for (let _i = 0; _i < _items.length; _i++) {\n`;
1538
1550
  domCode += ` const ${node.attribs.item} = _items[_i];\n`;
1539
1551
  if (node.attribs.index) domCode += ` const ${node.attribs.index} = _i;\n`;
1540
- node.children.forEach(child => emitNode(child, 'f', eachLocals));
1552
+ node.children.forEach(child => emitNode(child, 'f', eachLocals, inSvg));
1541
1553
  domCode += ` }\n`;
1542
1554
  domCode += ` Array.from(f.childNodes).forEach(n => ${eid}_els.push(n));\n`;
1543
1555
  domCode += ` ${eid}_a.parentNode.insertBefore(f, ${eid}_a.nextSibling);\n`;
@@ -1548,8 +1560,14 @@ export function compile(source, options = {}) {
1548
1560
  }
1549
1561
 
1550
1562
  // Normal element
1563
+ const isSvg = inSvg || node.name === 'svg';
1564
+ const childSvg = isSvg && node.name !== 'foreignObject';
1551
1565
  const id = `n${uid++}`;
1552
- domCode += ` const ${id} = document.createElement('${node.name}');\n`;
1566
+ if (isSvg) {
1567
+ domCode += ` const ${id} = document.createElementNS('http://www.w3.org/2000/svg', '${node.name}');\n`;
1568
+ } else {
1569
+ domCode += ` const ${id} = document.createElement('${node.name}');\n`;
1570
+ }
1553
1571
 
1554
1572
  if (hasStyles) {
1555
1573
  domCode += ` ${id}.classList.add('${scopeHash}');\n`;
@@ -1565,7 +1583,11 @@ export function compile(source, options = {}) {
1565
1583
  domCode += ` createEffect(() => { const _v = !!(${expr}); if (_v) ${id}.setAttribute('${key}', ''); else ${id}.removeAttribute('${key}'); });\n`;
1566
1584
  } else if (key === 'class' || key === 'className') {
1567
1585
  const suffix = hasStyles ? ` + ' ${scopeHash}'` : '';
1568
- domCode += ` createEffect(() => { ${id}.className = (${expr})${suffix}; });\n`;
1586
+ if (isSvg) {
1587
+ domCode += ` createEffect(() => { ${id}.setAttribute('class', (${expr})${suffix}); });\n`;
1588
+ } else {
1589
+ domCode += ` createEffect(() => { ${id}.className = (${expr})${suffix}; });\n`;
1590
+ }
1569
1591
  } else {
1570
1592
  domCode += ` createEffect(() => { ${id}.setAttribute('${key}', String(${expr})); });\n`;
1571
1593
  }
@@ -1597,7 +1619,12 @@ export function compile(source, options = {}) {
1597
1619
  // Static values: emit as a plain string literal. A template literal here
1598
1620
  // would let a backtick or ${ in the markup break out into expression
1599
1621
  // position; JSON.stringify cannot.
1600
- domCode += ` ${id}.className += ' ' + ${JSON.stringify(val)};\n`;
1622
+ if (isSvg) {
1623
+ const clsVal = hasStyles ? `${scopeHash} ${val}` : val;
1624
+ domCode += ` ${id}.setAttribute('class', ${JSON.stringify(clsVal)});\n`;
1625
+ } else {
1626
+ domCode += ` ${id}.className += ' ' + ${JSON.stringify(val)};\n`;
1627
+ }
1601
1628
  } else {
1602
1629
  domCode += ` ${id}.setAttribute(${JSON.stringify(key)}, ${JSON.stringify(val)});\n`;
1603
1630
  }
@@ -1607,7 +1634,7 @@ export function compile(source, options = {}) {
1607
1634
 
1608
1635
  if (node.children && !VOID_ELEMENTS.has(node.name)) {
1609
1636
  for (const child of node.children) {
1610
- emitNode(child, id, locals);
1637
+ emitNode(child, id, locals, childSvg);
1611
1638
  }
1612
1639
  }
1613
1640
  }
@@ -1651,7 +1678,8 @@ export function compile(source, options = {}) {
1651
1678
  output += `\n`;
1652
1679
  output += `export default function mount(__target, props = {}) {\n`;
1653
1680
  }
1654
- output += ` const __ctx = pushContext();\n\n`;
1681
+ output += ` const __ctx = pushContext();\n`;
1682
+ output += ` try {\n\n`;
1655
1683
 
1656
1684
  if (hasStyles) {
1657
1685
  // Styles go into whichever root the component actually lives in: the
@@ -1685,9 +1713,11 @@ export function compile(source, options = {}) {
1685
1713
  output += domCode;
1686
1714
 
1687
1715
  output += `\n __flush_mounts(__ctx);\n`;
1716
+ output += ` } finally {\n`;
1717
+ output += ` popContext(__ctx);\n`;
1718
+ output += ` }\n`;
1688
1719
  output += `\n return () => {\n`;
1689
1720
  output += ` __flush_destroys(__ctx);\n`;
1690
- output += ` popContext(__ctx);\n`;
1691
1721
  output += ` __target.innerHTML = '';\n`;
1692
1722
  output += ` };\n`;
1693
1723
  output += `};\n`;