chocola 1.5.2 → 1.6.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.
@@ -22,6 +22,28 @@ function scopeSelector(sel, cssId) {
22
22
  }
23
23
 
24
24
  function scopeCss(cssString, cssId) {
25
+ const keyframeRegex = /@(-webkit-)?keyframes\s+(\S+)/gi;
26
+ const animNames = new Set();
27
+ let match;
28
+ while ((match = keyframeRegex.exec(cssString))) {
29
+ animNames.add(match[2]);
30
+ }
31
+
32
+ if (animNames.size > 0) {
33
+ const sorted = [...animNames].sort((a, b) => b.length - a.length);
34
+ const esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
35
+ for (const name of sorted) {
36
+ cssString = cssString.replace(
37
+ new RegExp(`(@(?:-webkit-)?keyframes\\s+)${esc(name)}`, "gi"),
38
+ `$1${name}-${cssId}`
39
+ );
40
+ cssString = cssString.replace(
41
+ new RegExp(`((?:animation|animation-name)\\s*:\\s*[^;{]*?)\\b${esc(name)}\\b`, "gi"),
42
+ `$1${name}-${cssId}`
43
+ );
44
+ }
45
+ }
46
+
25
47
  function findMatchingBrace(s, openIndex) {
26
48
  let depth = 0;
27
49
  for (let i = openIndex; i < s.length; i++) {
@@ -35,6 +57,8 @@ function scopeCss(cssString, cssId) {
35
57
  return s.length - 1;
36
58
  }
37
59
 
60
+ const scopeInnerAtRules = new Set(["@media", "@supports", "@container", "@layer"]);
61
+
38
62
  function processBlock(str) {
39
63
  str = str.replaceAll(":root", `.${cssId}`);
40
64
 
@@ -49,11 +73,16 @@ function scopeCss(cssString, cssId) {
49
73
  const header = str.substring(i, braceIndex);
50
74
  const endBrace = findMatchingBrace(str, braceIndex);
51
75
  const inner = str.substring(braceIndex + 1, endBrace);
52
- const innerScoped = processBlock(inner);
53
76
 
54
77
  if (header.trim().startsWith("@")) {
55
- out += header + "{" + innerScoped + "}";
78
+ const atKeyword = header.trim().split(/\s+/)[0].toLowerCase();
79
+ if (scopeInnerAtRules.has(atKeyword)) {
80
+ out += header + "{" + processBlock(inner) + "}";
81
+ } else {
82
+ out += header + "{" + inner + "}";
83
+ }
56
84
  } else {
85
+ const innerScoped = processBlock(inner);
57
86
  const selectors = header
58
87
  .split(",")
59
88
  .map(s => s.trim())
@@ -72,6 +101,23 @@ function scopeCss(cssString, cssId) {
72
101
  return processBlock(cssString);
73
102
  }
74
103
 
104
+ const warnedDeprecated = new Set();
105
+ function hasDelIfAttr(el, sourceLoc) {
106
+ if (el.hasAttribute("del-if") && !el.hasAttribute("del:if") && !warnedDeprecated.has(sourceLoc)) {
107
+ warnedDeprecated.add(sourceLoc);
108
+ const name = sourceLoc ? sourceLoc.split(/[\\/]/).pop() : "unknown";
109
+ console.warn(chalk.yellow(`[deprecation] "del-if" is deprecated in ${chalk.cyan(name)} and will be removed in Chocola 2. Use "del:if" instead.`));
110
+ }
111
+ return el.hasAttribute("del-if") || el.hasAttribute("del:if");
112
+ }
113
+ function getDelIfAttr(el) {
114
+ return el.getAttribute("del:if") ?? el.getAttribute("del-if");
115
+ }
116
+ function removeDelIfAttr(el) {
117
+ el.removeAttribute("del-if");
118
+ el.removeAttribute("del:if");
119
+ }
120
+
75
121
  function interpolateNode(node, ctxProxy) {
76
122
  if (node.nodeType === 3) {
77
123
  node.textContent = node.textContent.replace(/\{([^}]+)\}/g, (_, expr) => {
@@ -93,7 +139,7 @@ function validateChainStructure(parent, sourceFile, sourceContent, parentContent
93
139
 
94
140
  for (const child of children) {
95
141
  const hasIf = child.hasAttribute("if");
96
- const hasDelIf = child.hasAttribute("del-if");
142
+ const hasDelIf = hasDelIfAttr(child, sourceFile);
97
143
  const hasElif = child.hasAttribute("elif");
98
144
  const hasElse = child.hasAttribute("else");
99
145
 
@@ -224,7 +270,7 @@ export function processComponentElement(
224
270
  const condChain = condChains.get(parent);
225
271
 
226
272
  const hasIf = child.hasAttribute("if");
227
- const hasDelIf = child.hasAttribute("del-if");
273
+ const hasDelIf = hasDelIfAttr(child, instance.__sourceFile || compName);
228
274
  const hasElif = child.hasAttribute("elif");
229
275
  const hasElse = child.hasAttribute("else");
230
276
 
@@ -257,8 +303,8 @@ export function processComponentElement(
257
303
  condChain.active = false;
258
304
  }
259
305
  } else if (hasIf || hasDelIf) {
260
- const attr = hasIf ? "if" : "del-if";
261
- const expr = child.getAttribute(attr).slice(1, -1);
306
+ const raw = hasIf ? child.getAttribute("if") : getDelIfAttr(child);
307
+ const expr = raw.slice(1, -1);
262
308
  const fn = new Function("ctx", `with(ctx) { return (${expr}); }`);
263
309
  condChain.active = true;
264
310
  if (fn(ctxProxy)) {
@@ -276,7 +322,7 @@ export function processComponentElement(
276
322
  return;
277
323
  }
278
324
 
279
- const reservedAttrs = ["if", "del-if", "elif", "else"];
325
+ const reservedAttrs = ["if", "del-if", "del:if", "elif", "else"];
280
326
 
281
327
  Array.from(child.attributes).forEach(attribute => {
282
328
  if (!attribute || attribute === undefined) return;
@@ -321,7 +367,7 @@ export function processComponentElement(
321
367
  }
322
368
  child.removeAttribute("if");
323
369
  } else if (hasDelIf) {
324
- const expr = child.getAttribute("del-if").slice(1, -1);
370
+ const expr = getDelIfAttr(child).slice(1, -1);
325
371
  const fn = new Function("ctx", `with(ctx) { return (${expr}); }`);
326
372
  condChain.active = true;
327
373
  if (fn(ctxProxy)) {
@@ -330,7 +376,7 @@ export function processComponentElement(
330
376
  child.remove();
331
377
  condChain.rendered = false;
332
378
  }
333
- child.removeAttribute("del-if");
379
+ removeDelIfAttr(child);
334
380
  } else if (hasElif) {
335
381
  const expr = child.getAttribute("elif").slice(1, -1);
336
382
  const fn = new Function("ctx", `with(ctx) { return (${expr}); }`);
@@ -44,7 +44,15 @@ export function extractContextFromElement(element) {
44
44
  const ctx = {};
45
45
  for (const attr of element.attributes) {
46
46
  const key = attr.name;
47
- ctx[key] = attr.value;
47
+ const val = attr.value;
48
+ const matches = [...val.matchAll(/\{([^}]+)\}/g)];
49
+ if (matches.length === 1 && matches[0][0] === val) {
50
+ try {
51
+ ctx[key] = Function(`"use strict"; return (${matches[0][1]})`)();
52
+ continue;
53
+ } catch {}
54
+ }
55
+ ctx[key] = val;
48
56
  }
49
57
  return ctx;
50
58
  }
package/compiler/index.js CHANGED
@@ -1,168 +1,254 @@
1
- import { promises as fs } from "fs";
2
- import chalk from "chalk";
3
- import { loadConfig, resolvePaths } from "./config.js";
4
- import {
5
- createDOM,
6
- validateAppContainer,
7
- getAppElements,
8
- getAssetLinks,
9
- appendRuntimeScript,
10
- appendStylesheetLink,
11
- serializeDOM,
12
- writeHTMLOutput,
13
- writeCSSOutput,
14
- } from "./dom-processor.js";
15
- import { processAllComponents } from "./component-processor.js";
16
- import { generateRuntimeScript } from "./runtime-generator.js";
17
- import { genRandomId, throwError } from "./utils.js";
18
- import {
19
- copyResources,
20
- copyStaticDir,
21
- getComponents,
22
- getSrcIndex,
23
- processIcons,
24
- processStylesheet,
25
- } from "./pipeline.js";
26
-
27
-
28
- const logSeparation = chalk.yellow(`
29
- ________________________________________________________________________
30
- ========================================================================
31
- `);
32
-
33
- function logBanner() {
34
- console.log(chalk.bold.hex("#945e33")(`\n RUNNING CHOCOLA BUNDLER`));
35
- console.log(logSeparation);
36
- console.log(
37
- chalk.hex("#945e33")(`
38
-
39
-
40
- ▄████▄ ██░ ██ ▒█████ ▄████▄ ▒█████ ██▓ ▄▄▄
41
- ▒██▀ ▀█ ▓██░ ██▒▒██▒ ██▒▒██▀ ▀█ ▒██▒ ██▒▓██▒ ▒████▄
42
- ▒▓█ ▄ ▒██▀▀██░▒██░ ██▒▒▓█ ▄ ▒██░ ██▒▒██░ ▒██ ▀█▄
43
- ▒▓▓▄ ▄██▒░▓█ ░██ ▒██ ██░▒▓▓▄ ▄██▒▒██ ██░▒██░ ░██▄▄▄▄██
44
- ▒ ▓███▀ ░░▓█▒░██▓░ ████▓▒░▒ ▓███▀ ░░ ████▓▒░░██████▒▓█ ▓██▒
45
- ░ ░▒ ▒ ░ ▒ ░░▒░▒░ ▒░▒░▒░ ░ ░▒ ▒ ░░ ▒░▒░▒░ ░ ▒░▓ ░▒▒ ▓▒█░
46
- ░ ▒ ▒ ░▒░ ░ ░ ░ ▒ ▒░ ░ ▒ ░ ░ ▒░ ░ ░ ▒ ░ ░ ▒▒ ░
47
- ░ ░ ░░ ░░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒
48
- ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
49
- ░ ░
50
-
51
-
52
- `)
53
- );
54
- }
55
-
56
- function logSuccess(outDirPath) {
57
- console.log(`
58
- ▄▄ ▄▄▄ ▄▄▄▄ ▄▄▄▄ ▄▄▄ ▄▄ ▄▄ ▄▄▄▄▄ ██
59
- ██ ██▀██ ██▄██ ██▀██ ██▀██ ███▄██ ██▄▄ ██
60
- ▄▄█▀ ▀███▀ ██▄█▀ ████▀ ▀███▀ ██ ▀██ ██▄▄▄ ▄▄
61
-
62
- `);
63
- console.log(
64
- chalk.bold.green(">"),
65
- "Project bundled succesfully at",
66
- chalk.green.underline(outDirPath) + "\n\n"
67
- );
68
- }
69
-
70
- async function setupOutputDirectory(outDirPath, emptyOutDir) {
71
- if (emptyOutDir) {
72
- await fs.rm(outDirPath, { recursive: true, force: true });
73
- await fs.mkdir(outDirPath);
74
- }
75
- }
76
-
77
- async function loadAndDisplayComponents(srcComponentsPath) {
78
- const foundComponents = await getComponents(srcComponentsPath);
79
- const { loadedComponents, notDefComps, componentsLib } = foundComponents;
80
-
81
- console.log(` LOADING COMPONENTS`);
82
- console.log(chalk.bold.green(">"), "Components found in", chalk.green.underline(srcComponentsPath) + ":");
83
- console.log(" ", componentsLib, "\n");
84
-
85
- if (notDefComps.length > 0) {
86
- console.warn(chalk.bold.yellow("WARNING!"), "The following components don't include a default export:");
87
- console.log(" ", notDefComps);
88
- }
89
-
90
- return loadedComponents;
91
- }
92
-
93
- async function processAssets(doc, rootDir, srcDir, outDirPath) {
94
- const { stylesheets, icons } = getAssetLinks(doc);
95
- const fileIds = [];
96
- let cssContents = [];
97
-
98
- for (const link of stylesheets) {
99
- const css = await processStylesheet(link, rootDir, srcDir, outDirPath, fileIds);
100
- cssContents.push(css);
101
- }
102
-
103
- for (const link of icons) {
104
- await processIcons(link, rootDir, srcDir, outDirPath);
105
- }
106
- return cssContents
107
- }
108
-
109
- /**
110
- * Compiles a static build of your Chocola project from the directory provided.
111
- * @param {import("fs").PathLike} rootDir
112
- * @param {Object<{
113
- * isHotReload?: boolean
114
- * }
115
- * >} config
116
- */
117
- export default async function runtime(rootDir, buildConfig) {
118
- const isHotReload = buildConfig?.isHotReload || null;
119
- !isHotReload && logBanner();
120
-
121
- const config = await loadConfig(rootDir);
122
- const paths = resolvePaths(rootDir, config);
123
- !isHotReload && console.log(logSeparation);
124
-
125
- await setupOutputDirectory(paths.outDir, config.emptyOutDir);
126
-
127
- const indexFiles = await getSrcIndex(paths.src);
128
- const srcIndexContent = indexFiles.srcHtmlFile || indexFiles.srcChocoFile;
129
- const pageSourcePath = indexFiles.srcPath;
130
-
131
- const loadedComponents = await loadAndDisplayComponents(paths.components);
132
- !isHotReload && console.log(logSeparation);
133
- !isHotReload && console.log(` BUNDLING STATIC BUILD`);
134
- !isHotReload && console.log(chalk.bold.green(">"), "Creating Chocola static build in directory", chalk.green.underline(paths.outDir) + "\n");
135
- !isHotReload && console.log(logSeparation);
136
-
137
- const dom = createDOM(srcIndexContent);
138
- const doc = dom.window.document;
139
- const appContainer = validateAppContainer(doc);
140
- const appElements = getAppElements(appContainer);
141
-
142
- const { runtimeScript, scopesCss } = processAllComponents(appElements, loadedComponents, pageSourcePath, srcIndexContent);
143
- const runtimeFilename = await generateRuntimeScript(runtimeScript, paths.outDir);
144
- const globalCss = (await processAssets(doc, rootDir, config.srcDir, paths.outDir)).join("\n");
145
-
146
- if (scopesCss) {
147
- const fileName = "sc-" + genRandomId(null, 6) + ".css";
148
- await writeCSSOutput(scopesCss, paths.outDir, fileName);
149
- appendStylesheetLink(doc, fileName);
150
- };
151
-
152
- appendRuntimeScript(doc, runtimeFilename);
153
- const html = await serializeDOM(dom);
154
- await writeHTMLOutput(html, paths.outDir);
155
-
156
- try {
157
- if (config.assetImport === "static") {
158
- await copyStaticDir(paths.src, paths.outDir);
159
- } else {
160
- await copyResources(rootDir, scopesCss, globalCss, config.srcDir, paths.outDir);
161
- }
162
- } catch (err) {
163
- throwError(err.message || err);
164
- }
165
-
166
- !isHotReload && logSuccess(paths.outDir);
167
- isHotReload && console.log("Dev server updated");
168
- }
1
+ import { promises as fs } from "fs";
2
+ import chalk from "chalk";
3
+ import { loadConfig, resolvePaths } from "./config.js";
4
+ import {
5
+ createDOM,
6
+ validateAppContainer,
7
+ getAppElements,
8
+ getAssetLinks,
9
+ appendRuntimeScript,
10
+ appendStylesheetLink,
11
+ serializeDOM,
12
+ writeHTMLOutput,
13
+ writeCSSOutput,
14
+ } from "./dom-processor.js";
15
+ import { processAllComponents } from "./component-processor.js";
16
+ import { generateRuntimeScript } from "./runtime-generator.js";
17
+ import { genRandomId, throwError } from "./utils.js";
18
+ import {
19
+ copyResources,
20
+ copyStaticDir,
21
+ getComponents,
22
+ getSrcIndex,
23
+ processIcons,
24
+ processStylesheet,
25
+ } from "./pipeline.js";
26
+
27
+
28
+ const logSeparation = chalk.yellow(`
29
+ ________________________________________________________________________
30
+ ========================================================================
31
+ `);
32
+
33
+ function logBanner() {
34
+ console.log(chalk.bold.hex("#945e33")(`\n RUNNING CHOCOLA BUNDLER`));
35
+ console.log(logSeparation);
36
+ console.log(
37
+ chalk.hex("#945e33")(`
38
+
39
+
40
+ ▄████▄ ██░ ██ ▒█████ ▄████▄ ▒█████ ██▓ ▄▄▄
41
+ ▒██▀ ▀█ ▓██░ ██▒▒██▒ ██▒▒██▀ ▀█ ▒██▒ ██▒▓██▒ ▒████▄
42
+ ▒▓█ ▄ ▒██▀▀██░▒██░ ██▒▒▓█ ▄ ▒██░ ██▒▒██░ ▒██ ▀█▄
43
+ ▒▓▓▄ ▄██▒░▓█ ░██ ▒██ ██░▒▓▓▄ ▄██▒▒██ ██░▒██░ ░██▄▄▄▄██
44
+ ▒ ▓███▀ ░░▓█▒░██▓░ ████▓▒░▒ ▓███▀ ░░ ████▓▒░░██████▒▓█ ▓██▒
45
+ ░ ░▒ ▒ ░ ▒ ░░▒░▒░ ▒░▒░▒░ ░ ░▒ ▒ ░░ ▒░▒░▒░ ░ ▒░▓ ░▒▒ ▓▒█░
46
+ ░ ▒ ▒ ░▒░ ░ ░ ░ ▒ ▒░ ░ ▒ ░ ░ ▒░ ░ ░ ▒ ░ ░ ▒▒ ░
47
+ ░ ░ ░░ ░░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒
48
+ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
49
+ ░ ░
50
+
51
+
52
+ `)
53
+ );
54
+ }
55
+
56
+ function logSuccess(outDirPath) {
57
+ console.log(`
58
+ ▄▄ ▄▄▄ ▄▄▄▄ ▄▄▄▄ ▄▄▄ ▄▄ ▄▄ ▄▄▄▄▄ ██
59
+ ██ ██▀██ ██▄██ ██▀██ ██▀██ ███▄██ ██▄▄ ██
60
+ ▄▄█▀ ▀███▀ ██▄█▀ ████▀ ▀███▀ ██ ▀██ ██▄▄▄ ▄▄
61
+
62
+ `);
63
+ console.log(
64
+ chalk.bold.green(">"),
65
+ "Project bundled succesfully at",
66
+ chalk.green.underline(outDirPath) + "\n\n"
67
+ );
68
+ }
69
+
70
+ async function setupOutputDirectory(outDirPath, emptyOutDir) {
71
+ if (emptyOutDir) {
72
+ await fs.rm(outDirPath, { recursive: true, force: true });
73
+ await fs.mkdir(outDirPath);
74
+ }
75
+ }
76
+
77
+ async function loadAndDisplayComponents(srcComponentsPath) {
78
+ const foundComponents = await getComponents(srcComponentsPath);
79
+ const { loadedComponents, notDefComps, componentsLib } = foundComponents;
80
+
81
+ console.log(` LOADING COMPONENTS`);
82
+ console.log(chalk.bold.green(">"), "Components found in", chalk.green.underline(srcComponentsPath) + ":");
83
+ console.log(" ", componentsLib, "\n");
84
+
85
+ if (notDefComps.length > 0) {
86
+ console.warn(chalk.bold.yellow("WARNING!"), "The following components don't include a default export:");
87
+ console.log(" ", notDefComps);
88
+ }
89
+
90
+ return loadedComponents;
91
+ }
92
+
93
+ async function processAssets(doc, rootDir, srcDir, outDirPath) {
94
+ const { stylesheets, icons } = getAssetLinks(doc);
95
+ const fileIds = [];
96
+ let cssContents = [];
97
+
98
+ for (const link of stylesheets) {
99
+ const css = await processStylesheet(link, rootDir, srcDir, outDirPath, fileIds);
100
+ cssContents.push(css);
101
+ }
102
+
103
+ for (const link of icons) {
104
+ await processIcons(link, rootDir, srcDir, outDirPath);
105
+ }
106
+ return cssContents
107
+ }
108
+
109
+ /**
110
+ * Compiles a static build of your Chocola project from the directory provided.
111
+ * @param {import("fs").PathLike} rootDir
112
+ * @param {Object<{
113
+ * isHotReload?: boolean
114
+ * }
115
+ * >} config
116
+ */
117
+ export default async function runtime(rootDir, buildConfig) {
118
+ const isHotReload = buildConfig?.isHotReload || null;
119
+ !isHotReload && logBanner();
120
+
121
+ const config = await loadConfig(rootDir);
122
+ const paths = resolvePaths(rootDir, config);
123
+ !isHotReload && console.log(logSeparation);
124
+
125
+ await setupOutputDirectory(paths.outDir, config.emptyOutDir);
126
+
127
+ const indexFiles = await getSrcIndex(paths.src);
128
+ const srcIndexContent = indexFiles.srcHtmlFile;
129
+ const pageSourcePath = indexFiles.srcPath;
130
+
131
+ const loadedComponents = await loadAndDisplayComponents(paths.components);
132
+ !isHotReload && console.log(logSeparation);
133
+ !isHotReload && console.log(` BUNDLING STATIC BUILD`);
134
+ !isHotReload && console.log(chalk.bold.green(">"), "Creating Chocola static build in directory", chalk.green.underline(paths.outDir) + "\n");
135
+ !isHotReload && console.log(logSeparation);
136
+
137
+ const dom = createDOM(srcIndexContent);
138
+ const doc = dom.window.document;
139
+ const appContainer = validateAppContainer(doc);
140
+
141
+ const warnedDeprecated = new Set();
142
+ function hasDelIfAttr(el, sourceLoc) {
143
+ if (el.hasAttribute("del-if") && !el.hasAttribute("del:if") && !warnedDeprecated.has(sourceLoc)) {
144
+ warnedDeprecated.add(sourceLoc);
145
+ const name = sourceLoc ? sourceLoc.split(/[\\/]/).pop() : "unknown";
146
+ console.warn(chalk.yellow(`[deprecation] "del-if" is deprecated in ${chalk.cyan(name)} and will be removed in Chocola 2. Use "del:if" instead.`));
147
+ }
148
+ return el.hasAttribute("del-if") || el.hasAttribute("del:if");
149
+ }
150
+ function getDelIfAttr(el) {
151
+ return el.getAttribute("del:if") ?? el.getAttribute("del-if");
152
+ }
153
+ function removeDelIfAttr(el) {
154
+ el.removeAttribute("del-if");
155
+ el.removeAttribute("del:if");
156
+ }
157
+
158
+ function processPageConditionals(parent) {
159
+ const children = [...parent.children];
160
+ let chainActive = false;
161
+ let chainRendered = false;
162
+
163
+ for (const child of children) {
164
+ const hasIf = child.hasAttribute("if");
165
+ const hasDelIf = hasDelIfAttr(child, pageSourcePath);
166
+ const hasElif = child.hasAttribute("elif");
167
+ const hasElse = child.hasAttribute("else");
168
+
169
+ if (hasElif || hasElse) {
170
+ if (!chainActive) continue;
171
+ if (chainRendered) { child.remove(); continue; }
172
+ }
173
+
174
+ if (hasIf) {
175
+ const raw = child.getAttribute("if");
176
+ const expr = raw.startsWith("{") ? raw.slice(1, -1) : raw;
177
+ const fn = new Function(`"use strict"; return (${expr})`);
178
+ const result = fn();
179
+ chainActive = true;
180
+ if (result) {
181
+ chainRendered = true;
182
+ } else {
183
+ child.remove();
184
+ chainRendered = false;
185
+ }
186
+ child.removeAttribute("if");
187
+ } else if (hasDelIf) {
188
+ const raw = getDelIfAttr(child);
189
+ const expr = raw.startsWith("{") ? raw.slice(1, -1) : raw;
190
+ const fn = new Function(`"use strict"; return (${expr})`);
191
+ const result = fn();
192
+ chainActive = true;
193
+ if (result) {
194
+ chainRendered = true;
195
+ } else {
196
+ child.remove();
197
+ chainRendered = false;
198
+ }
199
+ removeDelIfAttr(child);
200
+ } else if (hasElif) {
201
+ const raw = child.getAttribute("elif");
202
+ const expr = raw.startsWith("{") ? raw.slice(1, -1) : raw;
203
+ const fn = new Function(`"use strict"; return (${expr})`);
204
+ const result = fn();
205
+ if (result) {
206
+ chainRendered = true;
207
+ } else {
208
+ child.remove();
209
+ }
210
+ child.removeAttribute("elif");
211
+ } else if (hasElse) {
212
+ chainRendered = true;
213
+ chainActive = false;
214
+ child.removeAttribute("else");
215
+ } else {
216
+ chainActive = false;
217
+ chainRendered = false;
218
+ }
219
+
220
+ if (child.parentNode) {
221
+ processPageConditionals(child);
222
+ }
223
+ }
224
+ }
225
+ processPageConditionals(appContainer);
226
+
227
+ const appElements = getAppElements(appContainer);
228
+ const { runtimeScript, scopesCss } = processAllComponents(appElements, loadedComponents, pageSourcePath, srcIndexContent);
229
+ const runtimeFilename = await generateRuntimeScript(runtimeScript, paths.outDir);
230
+ const globalCss = (await processAssets(doc, rootDir, config.srcDir, paths.outDir)).join("\n");
231
+
232
+ if (scopesCss) {
233
+ const fileName = "sc-" + genRandomId(null, 6) + ".css";
234
+ await writeCSSOutput(scopesCss, paths.outDir, fileName);
235
+ appendStylesheetLink(doc, fileName);
236
+ };
237
+
238
+ appendRuntimeScript(doc, runtimeFilename);
239
+ const html = await serializeDOM(dom);
240
+ await writeHTMLOutput(html, paths.outDir);
241
+
242
+ try {
243
+ if (config.assetImport === "static") {
244
+ await copyStaticDir(paths.src, paths.outDir);
245
+ } else {
246
+ await copyResources(rootDir, scopesCss, globalCss, config.srcDir, paths.outDir);
247
+ }
248
+ } catch (err) {
249
+ throwError(err.message || err);
250
+ }
251
+
252
+ !isHotReload && logSuccess(paths.outDir);
253
+ isHotReload && console.log("Dev server updated");
254
+ }
@@ -70,32 +70,19 @@ export async function getComponents(libDir) {
70
70
  */
71
71
  export async function getSrcIndex(srcPath) {
72
72
  const srcHtmlPath = path.join(srcPath, "index.html");
73
- const srcChocoPath = path.join(srcPath, "index.choco");
74
73
 
75
74
  const htmlExists = await checkFile(srcHtmlPath);
76
- const chocoExists = await checkFile(srcChocoPath);
77
75
 
78
76
  let srcHtmlFile = null;
79
- let srcChocoFile = null;
80
-
81
- if (htmlExists && chocoExists) {
82
- throwError(
83
- "Can't have both .choco and .html source index files at a time: please remove one of the two"
84
- );
85
- }
86
77
 
87
78
  if (htmlExists) {
88
79
  try {
89
80
  srcHtmlFile = await readMyFile(srcHtmlPath);
90
- return { srcHtmlFile, srcChocoFile, srcPath: srcHtmlPath };
81
+ return { srcHtmlFile, srcPath: srcHtmlPath };
91
82
  } catch (err) {
92
83
  throwError(err);
93
84
  }
94
85
  }
95
-
96
- if (chocoExists) {
97
- throwError(".choco files are not supported yet");
98
- }
99
86
  }
100
87
 
101
88
  /**
@@ -244,7 +231,7 @@ export async function copyResources(rootDir, scopesCss, globalCss, srcDir, outDi
244
231
  `Failed to copy resource from inline style on <${el.tagName.toLowerCase()}> url("${filePath}")` +
245
232
  (getComponentSource(el) ? ` in component "${getComponentSource(el)}"` : "") +
246
233
  `: ${err.message || err}`
247
- );
234
+ );
248
235
  }
249
236
  }
250
237
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chocola",
3
- "version": "1.5.2",
3
+ "version": "1.6.0",
4
4
  "description": "The sweetest way to build the web",
5
5
  "keywords": [
6
6
  "web",
package/.gitattributes DELETED
@@ -1,2 +0,0 @@
1
- # Auto detect text files and perform LF normalization
2
- * text=auto