leanweb 3.0.8 → 3.10.0
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/commands/build.js +9 -1
- package/commands/dist.js +0 -1
- package/commands/init.js +1 -1
- package/leanweb.js +1 -1
- package/lib/lw-html-parser.js +2 -2
- package/package.json +7 -7
- package/templates/lib/lw-element.js +16 -7
- package/templates/lib/lw-expr-parser.js +20 -11
package/commands/build.js
CHANGED
|
@@ -44,6 +44,13 @@ const buildModule = (projectPath) => {
|
|
|
44
44
|
utils.writeIfChanged(`${utils.dirs.build}/${project.name}.js`, jsString);
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
+
const buildGlobalStyles = () => {
|
|
48
|
+
const globalCssPath = `${utils.dirs.build}/global-styles.css`;
|
|
49
|
+
const globalCss = fs.existsSync(globalCssPath) ? fs.readFileSync(globalCssPath, 'utf8') : '';
|
|
50
|
+
const jsModule = `const sheet = new CSSStyleSheet();\nsheet.replaceSync(${JSON.stringify(globalCss)});\nexport default sheet;\n`;
|
|
51
|
+
utils.writeIfChanged(`${utils.dirs.build}/global-styles.js`, jsModule);
|
|
52
|
+
};
|
|
53
|
+
|
|
47
54
|
const buildHTML = () => {
|
|
48
55
|
try {
|
|
49
56
|
project.components.forEach(cmp => {
|
|
@@ -53,7 +60,7 @@ const buildModule = (projectPath) => {
|
|
|
53
60
|
if (htmlFileExists) {
|
|
54
61
|
const cssFilename = `${utils.dirs.build}/components/${cmp}/${cmpName}.css`;
|
|
55
62
|
const cssFileExists = fs.existsSync(cssFilename);
|
|
56
|
-
let cssString =
|
|
63
|
+
let cssString = '';
|
|
57
64
|
if (cssFileExists) {
|
|
58
65
|
cssString += fs.readFileSync(cssFilename, 'utf8');
|
|
59
66
|
}
|
|
@@ -82,6 +89,7 @@ const buildModule = (projectPath) => {
|
|
|
82
89
|
copySrc();
|
|
83
90
|
copyEnv();
|
|
84
91
|
buildJS();
|
|
92
|
+
buildGlobalStyles();
|
|
85
93
|
buildHTML();
|
|
86
94
|
|
|
87
95
|
return project.name;
|
package/commands/dist.js
CHANGED
|
@@ -60,7 +60,6 @@ const appCSS = fs.readFileSync(`./${utils.dirs.build}/${project.name}.css`, 'utf
|
|
|
60
60
|
fs.writeFileSync(`./${utils.dirs.dist}/${project.name}.css`, appCSS);
|
|
61
61
|
|
|
62
62
|
fse.copySync(`./${utils.dirs.build}/favicon.svg`, `./${utils.dirs.dist}/favicon.svg`);
|
|
63
|
-
fse.copySync(`./${utils.dirs.build}/global-styles.css`, `./${utils.dirs.dist}/global-styles.css`);
|
|
64
63
|
project.resources?.forEach(resource => {
|
|
65
64
|
const source = `./${utils.dirs.build}/${resource}`;
|
|
66
65
|
if (fs.existsSync(source)) {
|
package/commands/init.js
CHANGED
package/leanweb.js
CHANGED
|
@@ -42,7 +42,7 @@ import * as utils from './commands/utils.js';
|
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
if (leanwebJSONExisted && target === 'version' || target === 'serve' || target === 'dist') {
|
|
45
|
+
if (leanwebJSONExisted && (target === 'version' || target === 'serve' || target === 'dist')) {
|
|
46
46
|
const leanwebPackageJSON = require(`${__dirname}/package.json`);
|
|
47
47
|
const projectLeanwebJSON = require(`${process.cwd()}/${utils.dirs.src}/leanweb.json`);
|
|
48
48
|
const upgradeAvailable = semver.gt(leanwebPackageJSON.version, projectLeanwebJSON.version);
|
package/lib/lw-html-parser.js
CHANGED
|
@@ -6,7 +6,7 @@ let astKey = 0;
|
|
|
6
6
|
const removeASTLocation = ast => {
|
|
7
7
|
if (Array.isArray(ast)) {
|
|
8
8
|
ast.forEach(a => removeASTLocation(a));
|
|
9
|
-
} else if (typeof ast === 'object') {
|
|
9
|
+
} else if (ast !== null && typeof ast === 'object') {
|
|
10
10
|
delete ast['loc'];
|
|
11
11
|
delete ast['start'];
|
|
12
12
|
delete ast['end'];
|
|
@@ -77,7 +77,7 @@ const walkNode = (node, interpolation) => {
|
|
|
77
77
|
|
|
78
78
|
if (attr.name === 'lw-bind:class') {
|
|
79
79
|
const classAttr = node.attrs.find(a => a.name === 'class');
|
|
80
|
-
node.attrs.push({ name: 'lw-init-class', value: classAttr
|
|
80
|
+
node.attrs.push({ name: 'lw-init-class', value: classAttr?.value ?? '' });
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
const ast = getAST(attr.value);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leanweb",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.10.0",
|
|
4
4
|
"description": "Builds framework agnostic web components.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"leanweb": "leanweb.js",
|
|
@@ -20,15 +20,15 @@
|
|
|
20
20
|
"author": "Qian Chen",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@babel/parser": "^7.
|
|
24
|
-
"esbuild": "^0.
|
|
25
|
-
"fs-extra": "^11.3.
|
|
26
|
-
"globby": "^
|
|
23
|
+
"@babel/parser": "^7.29.0",
|
|
24
|
+
"esbuild": "^0.27.3",
|
|
25
|
+
"fs-extra": "^11.3.4",
|
|
26
|
+
"globby": "^16.1.1",
|
|
27
27
|
"html-minifier": "^4.0.0",
|
|
28
|
-
"isomorphic-git": "^1.
|
|
28
|
+
"isomorphic-git": "^1.37.2",
|
|
29
29
|
"live-server": "^1.2.2",
|
|
30
30
|
"node-watch": "^0.7.4",
|
|
31
31
|
"parse5": "^8.0.0",
|
|
32
|
-
"semver": "^7.7.
|
|
32
|
+
"semver": "^7.7.4"
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as parser from './lw-expr-parser.js';
|
|
2
2
|
import LWEventBus from './lw-event-bus.js';
|
|
3
|
+
import globalStyleSheet from '../global-styles.js';
|
|
3
4
|
|
|
4
5
|
globalThis.leanweb = globalThis.leanweb ?? {
|
|
5
6
|
componentsListeningOnUrlChanges: [],
|
|
@@ -106,8 +107,11 @@ export default class LWElement extends HTMLElement {
|
|
|
106
107
|
leanweb.builderVersion = ast.builderVersion;
|
|
107
108
|
|
|
108
109
|
const node = document.createElement('template');
|
|
109
|
-
|
|
110
|
+
const componentSheet = new CSSStyleSheet();
|
|
111
|
+
componentSheet.replaceSync(ast.css);
|
|
112
|
+
node.innerHTML = ast.html;
|
|
110
113
|
this.attachShadow({ mode: 'open' }).appendChild(node.content);
|
|
114
|
+
this.shadowRoot.adoptedStyleSheets = [globalStyleSheet, componentSheet];
|
|
111
115
|
|
|
112
116
|
this._bindMethods();
|
|
113
117
|
setTimeout(() => {
|
|
@@ -322,7 +326,7 @@ export default class LWElement extends HTMLElement {
|
|
|
322
326
|
}
|
|
323
327
|
|
|
324
328
|
updateModel(modelNode) {
|
|
325
|
-
if (modelNode.do_not_update && modelNode.type === 'number') {
|
|
329
|
+
if (modelNode.do_not_update && (modelNode.type === 'number' || modelNode.type === 'range')) {
|
|
326
330
|
return;
|
|
327
331
|
}
|
|
328
332
|
const key = modelNode.getAttribute('lw-model');
|
|
@@ -388,7 +392,7 @@ export default class LWElement extends HTMLElement {
|
|
|
388
392
|
const parsed = parser.evaluate(interpolation.ast, context, interpolation.loc);
|
|
389
393
|
|
|
390
394
|
const hasLwFalse = ifNode.hasAttribute('lw-false');
|
|
391
|
-
if (parsed[0]
|
|
395
|
+
if (parsed[0]) {
|
|
392
396
|
hasLwFalse && ifNode.removeAttribute('lw-false');
|
|
393
397
|
setTimeout(() => {
|
|
394
398
|
ifNode.turnedOn?.call(ifNode);
|
|
@@ -438,12 +442,17 @@ export default class LWElement extends HTMLElement {
|
|
|
438
442
|
if (cls) bindNode.classList.add(cls);
|
|
439
443
|
});
|
|
440
444
|
}
|
|
441
|
-
//
|
|
445
|
+
// Remove previously applied dynamic class
|
|
446
|
+
const prevClass = bindNode['lw-prev-class-' + attrValue];
|
|
447
|
+
if (prevClass && prevClass !== dynamicClass) {
|
|
448
|
+
bindNode.classList.remove(prevClass);
|
|
449
|
+
}
|
|
450
|
+
// Add or record the dynamic class
|
|
442
451
|
if (dynamicClass) {
|
|
443
452
|
bindNode.classList.add(dynamicClass);
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
bindNode
|
|
453
|
+
bindNode['lw-prev-class-' + attrValue] = dynamicClass;
|
|
454
|
+
} else {
|
|
455
|
+
bindNode['lw-prev-class-' + attrValue] = null;
|
|
447
456
|
}
|
|
448
457
|
} else {
|
|
449
458
|
if (parsed[0] !== false && parsed[0] !== undefined && parsed[0] !== null) {
|
|
@@ -43,11 +43,6 @@ const assignmentOperations = {
|
|
|
43
43
|
'^=': (c, a, b) => { c[a] ^= b; },
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
const logicalOperators = {
|
|
47
|
-
'||': (a, b) => a || b,
|
|
48
|
-
'&&': (a, b) => a && b,
|
|
49
|
-
'??': (a, b) => a ?? b,
|
|
50
|
-
};
|
|
51
46
|
|
|
52
47
|
const unaryOperators = {
|
|
53
48
|
'-': a => -a,
|
|
@@ -110,7 +105,12 @@ const nodeHandlers = {
|
|
|
110
105
|
}
|
|
111
106
|
assignmentOperations[node.operator](obj, prop, evalNode(node.right, context));
|
|
112
107
|
},
|
|
113
|
-
'LogicalExpression': (node, context) =>
|
|
108
|
+
'LogicalExpression': (node, context) => {
|
|
109
|
+
const left = evalNode(node.left, context);
|
|
110
|
+
if (node.operator === '&&') return left ? evalNode(node.right, context) : left;
|
|
111
|
+
if (node.operator === '||') return left ? left : evalNode(node.right, context);
|
|
112
|
+
if (node.operator === '??') return left ?? evalNode(node.right, context);
|
|
113
|
+
},
|
|
114
114
|
'UnaryExpression': (node, context) => unaryOperators[node.operator](evalNode(node.argument, context)),
|
|
115
115
|
'UpdateExpression': (node, context) => {
|
|
116
116
|
// Support complex left-hand sides (e.g., ++obj.prop, ++obj[expr])
|
|
@@ -128,9 +128,7 @@ const nodeHandlers = {
|
|
|
128
128
|
},
|
|
129
129
|
'ConditionalExpression': (node, context) => {
|
|
130
130
|
const test = evalNode(node.test, context);
|
|
131
|
-
|
|
132
|
-
const alternate = evalNode(node.alternate, context);
|
|
133
|
-
return test ? consequent : alternate;
|
|
131
|
+
return test ? evalNode(node.consequent, context) : evalNode(node.alternate, context);
|
|
134
132
|
},
|
|
135
133
|
'MemberExpression': (node, context) => {
|
|
136
134
|
const object = evalNode(node.object, context);
|
|
@@ -164,7 +162,7 @@ const nodeHandlers = {
|
|
|
164
162
|
return arr;
|
|
165
163
|
},
|
|
166
164
|
'ObjectExpression': (node, context) => node.properties.reduce((acc, prop) => ({ ...acc, ...evalNode(prop, context) }), {}),
|
|
167
|
-
'ObjectProperty': (node, context) => ({ [evalNode(node.key, context)]: evalNode(node.value, context) }),
|
|
165
|
+
'ObjectProperty': (node, context) => ({ [node.computed ? evalNode(node.key, context) : (node.key.name ?? node.key.value)]: evalNode(node.value, context) }),
|
|
168
166
|
'SpreadElement': (node, context) => evalNode(node.argument, context),
|
|
169
167
|
|
|
170
168
|
'Identifier': (node, context) => {
|
|
@@ -181,7 +179,18 @@ const nodeHandlers = {
|
|
|
181
179
|
|
|
182
180
|
'CallExpression': (node, context) => callFunction(node, context),
|
|
183
181
|
'OptionalCallExpression': (node, context) => callFunction(node, context),
|
|
184
|
-
'NewExpression': (node, context) =>
|
|
182
|
+
'NewExpression': (node, context) => {
|
|
183
|
+
const callee = evalNode(node.callee, context);
|
|
184
|
+
const args = [];
|
|
185
|
+
node.arguments.map(argument => {
|
|
186
|
+
if (argument.type === 'SpreadElement') {
|
|
187
|
+
args.push(...evalNode(argument, context));
|
|
188
|
+
} else {
|
|
189
|
+
args.push(evalNode(argument, context));
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
return new callee(...args);
|
|
193
|
+
},
|
|
185
194
|
|
|
186
195
|
'Directive': (node, context) => evalNode(node.value, context),
|
|
187
196
|
'DirectiveLiteral': (node, context) => node.value,
|