@elenajs/bundler 0.6.0 → 0.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elenajs/bundler",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Bundler for Progressive Web Component libraries built with Elena.",
5
5
  "author": "Elena <hi@elenajs.com>",
6
6
  "homepage": "https://elenajs.com/",
@@ -24,25 +24,27 @@
24
24
  "node": ">= 20"
25
25
  },
26
26
  "scripts": {
27
- "format": "prettier --write \"src/**/*.js\" \"test/**/*.mjs\"",
28
27
  "test": "vitest run"
29
28
  },
30
29
  "dependencies": {
31
30
  "@custom-elements-manifest/analyzer": "0.11.0",
32
- "@elenajs/plugin-cem-define": "^0.1.0",
33
- "@elenajs/plugin-cem-tag": "^0.1.0",
34
- "@elenajs/plugin-cem-typescript": "^0.2.0",
35
- "@elenajs/plugin-rollup-css": "^0.3.0",
31
+ "@elenajs/plugin-cem-define": "^0.2.0",
32
+ "@elenajs/plugin-cem-tag": "^0.2.0",
33
+ "@elenajs/plugin-cem-typescript": "^0.3.0",
34
+ "@elenajs/plugin-rollup-css": "^0.4.0",
36
35
  "@rollup/plugin-node-resolve": "16.0.3",
37
36
  "@rollup/plugin-terser": "0.4.4",
37
+ "@rollup/plugin-typescript": "^12.1.0",
38
38
  "custom-element-jsx-integration": "1.6.0",
39
- "globby": "11.0.4",
40
- "rollup": "4.57.1",
39
+ "globby": "16.1.1",
40
+ "rollup": "4.58.0",
41
41
  "rollup-plugin-minify-html-literals-v3": "^1.3.4",
42
- "rollup-plugin-summary": "3.0.1"
42
+ "rollup-plugin-summary": "3.0.1",
43
+ "tslib": "^2.8.0",
44
+ "typescript": "^5.8.0"
43
45
  },
44
46
  "devDependencies": {
45
47
  "vitest": "4.0.18"
46
48
  },
47
- "gitHead": "3da2b4411c0a4d36085b1095feabbaabea50909f"
49
+ "gitHead": "81fe2fc78111f605854c07df2001f746231d9dfc"
48
50
  }
@@ -1,18 +1,32 @@
1
+ /**
2
+ * ██████████ ████
3
+ * ░░███░░░░░█░░███
4
+ * ░███ █ ░ ███ ██████ ████████ ██████
5
+ * ░██████ ███ ███░░███░░███░░███ ░░░░░███
6
+ * ░███░░█ ███ ░███████ ░███ ░███ ███████
7
+ * ░███ ░ █ ███ ░███░░░ ░███ ░███ ███░░███
8
+ * ██████████ █████░░██████ ████ █████░░████████
9
+ * ░░░░░░░░░░ ░░░░░ ░░░░░░ ░░░░ ░░░░░ ░░░░░░░░
10
+ *
11
+ * Elena Bundler CEM Analyze
12
+ * https://elenajs.com
13
+ */
14
+
1
15
  import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
2
16
  import { join, resolve } from "path";
3
17
  import { create, ts } from "@custom-elements-manifest/analyzer";
4
- import globby from "globby";
18
+ import { globby } from "globby";
5
19
  import { customElementJsxPlugin as elenaJsxPlugin } from "custom-element-jsx-integration";
6
20
  import { elenaDefinePlugin } from "@elenajs/plugin-cem-define";
7
21
  import { elenaTagPlugin } from "@elenajs/plugin-cem-tag";
8
22
  import { elenaTypeScriptPlugin } from "@elenajs/plugin-cem-typescript";
9
- import { color } from "./utils/color.js";
23
+ import { color } from "./common/color.js";
10
24
 
11
25
  /**
12
26
  * Returns the CEM config object for the given Elena config. Useful for advanced
13
27
  * users who still call the CEM CLI with a thin `elena.config.js` wrapper.
14
28
  *
15
- * @param {import("./utils/load-config.js").ElenaConfig} [options]
29
+ * @param {import("./common/load-config.js").ElenaConfig} [options]
16
30
  * @returns {object} CEM config object
17
31
  */
18
32
  export function createCemConfig(options = {}) {
@@ -24,8 +38,8 @@ export function createCemConfig(options = {}) {
24
38
  outdir,
25
39
  watch: false,
26
40
  dev: false,
27
- globs: [`${src}/**/*.js`],
28
- exclude: [`${src}/**/*.ts`, "**/*.test.js", "node_modules"],
41
+ globs: [`${src}/**/*.js`, `${src}/**/*.ts`],
42
+ exclude: ["**/*.test.js", "**/*.test.ts", "node_modules"],
29
43
  plugins: [
30
44
  elenaDefinePlugin(),
31
45
  elenaTagPlugin("status"),
@@ -41,7 +55,7 @@ export function createCemConfig(options = {}) {
41
55
  * Runs the CEM analyzer programmatically using `create()` from
42
56
  * `@custom-elements-manifest/analyzer`, writes the manifest to disk.
43
57
  *
44
- * @param {import("./utils/load-config.js").ElenaConfig} config
58
+ * @param {import("./common/load-config.js").ElenaConfig} config
45
59
  * @param {string} [cwd]
46
60
  * @returns {Promise<void>}
47
61
  */
@@ -57,14 +71,15 @@ export async function runCemAnalyze(config, cwd = process.cwd()) {
57
71
  console.log(` `);
58
72
 
59
73
  const globs = await globby(
60
- [`${src}/**/*.js`, `!${src}/**/*.ts`, "!**/*.test.js", "!node_modules"],
74
+ [`${src}/**/*.js`, `${src}/**/*.ts`, "!**/*.test.js", "!**/*.test.ts", "!node_modules"],
61
75
  { cwd }
62
76
  );
63
77
 
64
78
  const modules = globs.map(glob => {
65
79
  const fullPath = resolve(cwd, glob);
66
80
  const source = readFileSync(fullPath).toString();
67
- return ts.createSourceFile(glob, source, ts.ScriptTarget.ES2015, true);
81
+ const scriptKind = glob.endsWith(".ts") ? ts.ScriptKind.TS : ts.ScriptKind.JS;
82
+ return ts.createSourceFile(glob, source, ts.ScriptTarget.ES2015, true, scriptKind);
68
83
  });
69
84
 
70
85
  const plugins = [
package/src/cli.js CHANGED
@@ -1,9 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { loadConfig } from "./utils/load-config.js";
3
+ /**
4
+ * ██████████ ████
5
+ * ░░███░░░░░█░░███
6
+ * ░███ █ ░ ███ ██████ ████████ ██████
7
+ * ░██████ ███ ███░░███░░███░░███ ░░░░░███
8
+ * ░███░░█ ███ ░███████ ░███ ░███ ███████
9
+ * ░███ ░ █ ███ ░███░░░ ░███ ░███ ███░░███
10
+ * ██████████ █████░░██████ ████ █████░░████████
11
+ * ░░░░░░░░░░ ░░░░░ ░░░░░░ ░░░░ ░░░░░ ░░░░░░░░
12
+ *
13
+ * Elena Bundler CLI
14
+ * https://elenajs.com
15
+ */
16
+
17
+ import { loadConfig } from "./common/load-config.js";
4
18
  import { runRollupBuild } from "./rollup-build.js";
5
19
  import { runCemAnalyze } from "./cem-analyze.js";
6
- import { color } from "./utils/color.js";
20
+ import { color } from "./common/color.js";
7
21
 
8
22
  const BANNER = `
9
23
  ██████████ ████
@@ -18,6 +32,7 @@ const BANNER = `
18
32
 
19
33
  const [, , command = "build"] = process.argv;
20
34
 
35
+ /** Loads the Elena config and runs the Rollup build + CEM analysis. */
21
36
  async function main() {
22
37
  if (command !== "build") {
23
38
  console.error(`Unknown command: ${command}. Usage: elena [build]`);
package/src/index.js CHANGED
@@ -1,2 +1,16 @@
1
+ /**
2
+ * ██████████ ████
3
+ * ░░███░░░░░█░░███
4
+ * ░███ █ ░ ███ ██████ ████████ ██████
5
+ * ░██████ ███ ███░░███░░███░░███ ░░░░░███
6
+ * ░███░░█ ███ ░███████ ░███ ░███ ███████
7
+ * ░███ ░ █ ███ ░███░░░ ░███ ░███ ███░░███
8
+ * ██████████ █████░░██████ ████ █████░░████████
9
+ * ░░░░░░░░░░ ░░░░░ ░░░░░░ ░░░░ ░░░░░ ░░░░░░░░
10
+ *
11
+ * Elena Bundler
12
+ * https://elenajs.com
13
+ */
14
+
1
15
  export { createRollupConfig, runRollupBuild } from "./rollup-build.js";
2
16
  export { createCemConfig, runCemAnalyze } from "./cem-analyze.js";
@@ -1,17 +1,38 @@
1
- import { readdirSync } from "fs";
1
+ /**
2
+ * ██████████ ████
3
+ * ░░███░░░░░█░░███
4
+ * ░███ █ ░ ███ ██████ ████████ ██████
5
+ * ░██████ ███ ███░░███░░███░░███ ░░░░░███
6
+ * ░███░░█ ███ ░███████ ░███ ░███ ███████
7
+ * ░███ ░ █ ███ ░███░░░ ░███ ░███ ███░░███
8
+ * ██████████ █████░░██████ ████ █████░░████████
9
+ * ░░░░░░░░░░ ░░░░░ ░░░░░░ ░░░░ ░░░░░ ░░░░░░░░
10
+ *
11
+ * Elena Bundler Rollup Config
12
+ * https://elenajs.com
13
+ */
14
+
15
+ import { existsSync, readdirSync } from "fs";
2
16
  import { rollup } from "rollup";
3
17
  import resolve from "@rollup/plugin-node-resolve";
4
18
  import terser from "@rollup/plugin-terser";
19
+ import typescript from "@rollup/plugin-typescript";
5
20
  import minifyHtmlLiterals from "rollup-plugin-minify-html-literals-v3";
6
21
  import summary from "rollup-plugin-summary";
7
22
  import { cssPlugin, cssBundlePlugin } from "@elenajs/plugin-rollup-css";
8
- import { color } from "./utils/color.js";
23
+ import { color } from "./common/color.js";
9
24
 
10
25
  const TREESHAKE = {
11
26
  moduleSideEffects: false,
12
27
  propertyReadSideEffects: false,
13
28
  };
14
29
 
30
+ /**
31
+ * Suppresses noisy Rollup warnings.
32
+ *
33
+ * @param {import("rollup").RollupWarning} warning
34
+ * @param {function} warn
35
+ */
15
36
  function onwarn(warning, warn) {
16
37
  if (warning.code === "UNUSED_EXTERNAL_IMPORT") {
17
38
  return;
@@ -22,15 +43,36 @@ function onwarn(warning, warn) {
22
43
  /**
23
44
  * Builds the plugin list for a single Rollup build target.
24
45
  *
25
- * @param {{ src: string; outdir: string; hasSummary: boolean; includeCssBundle: boolean; extraPlugins?: import("rollup").Plugin[] }} opts
46
+ * @param {{ src: string; outdir: string; hasSummary: boolean; includeCssBundle: boolean; extraPlugins?: import("rollup").Plugin[]; hasTs?: boolean }} opts
26
47
  * @returns {import("rollup").Plugin[]}
27
48
  */
28
- function buildPlugins({ src, outdir, hasSummary, includeCssBundle, extraPlugins = [] }) {
29
- const plugins = [
30
- resolve({ extensions: [".js", ".css"] }),
49
+ function buildPlugins({
50
+ src,
51
+ outdir,
52
+ hasSummary,
53
+ includeCssBundle,
54
+ extraPlugins = [],
55
+ hasTs = false,
56
+ }) {
57
+ const plugins = [resolve({ extensions: [".js", ".ts", ".css"] })];
58
+
59
+ if (hasTs) {
60
+ plugins.push(
61
+ typescript({
62
+ sourceMap: true,
63
+ compilerOptions: {
64
+ declaration: false,
65
+ declarationMap: false,
66
+ },
67
+ include: ["**/*.ts"],
68
+ })
69
+ );
70
+ }
71
+
72
+ plugins.push(
31
73
  minifyHtmlLiterals({
32
74
  options: {
33
- // Elena components use this.template`...` rather than html`...`
75
+ // Minify any template literal containing HTML, regardless of tag name
34
76
  shouldMinify: template => template.parts.some(({ text }) => /<[a-z]/i.test(text)),
35
77
  },
36
78
  }),
@@ -38,8 +80,8 @@ function buildPlugins({ src, outdir, hasSummary, includeCssBundle, extraPlugins
38
80
  ecma: 2020,
39
81
  module: true,
40
82
  }),
41
- cssPlugin(src),
42
- ];
83
+ cssPlugin(src)
84
+ );
43
85
 
44
86
  if (includeCssBundle) {
45
87
  plugins.push(cssBundlePlugin(src, "bundle.css"));
@@ -56,7 +98,7 @@ function buildPlugins({ src, outdir, hasSummary, includeCssBundle, extraPlugins
56
98
  }
57
99
 
58
100
  /**
59
- * Returns the Rollup config array for the given Elena config. Useful for advanced
101
+ * Returns the Rollup config array for the given Elena config. Useful for
60
102
  * users who want to call `rollup -c` with a thin wrapper config file.
61
103
  *
62
104
  * @param {import("./utils/load-config.js").ElenaConfig} [options]
@@ -67,13 +109,24 @@ export function createRollupConfig(options = {}) {
67
109
  const outdir = options.output?.dir ?? "dist";
68
110
  const format = options.output?.format ?? "esm";
69
111
  const sourcemap = options.output?.sourcemap ?? true;
70
- const bundle = options.bundle !== undefined ? options.bundle : "src/index.js";
112
+ let bundle = options.bundle !== undefined ? options.bundle : "src/index.js";
71
113
  const extraPlugins = options.plugins ?? [];
72
114
 
73
115
  const entries = readdirSync(src, { recursive: true })
74
- .filter(f => f.endsWith(".js"))
116
+ .filter(
117
+ f =>
118
+ (f.endsWith(".js") || f.endsWith(".ts")) &&
119
+ !f.endsWith(".test.js") &&
120
+ !f.endsWith(".test.ts")
121
+ )
75
122
  .map(f => `${src}/${f}`);
76
123
 
124
+ const hasTs = entries.some(f => f.endsWith(".ts"));
125
+
126
+ if (bundle === "src/index.js" && !existsSync(bundle) && existsSync("src/index.ts")) {
127
+ bundle = "src/index.ts";
128
+ }
129
+
77
130
  const configs = [
78
131
  {
79
132
  input: entries,
@@ -83,8 +136,14 @@ export function createRollupConfig(options = {}) {
83
136
  hasSummary: false,
84
137
  includeCssBundle: true,
85
138
  extraPlugins,
139
+ hasTs,
86
140
  }),
87
- output: { format, sourcemap, dir: outdir },
141
+ output: {
142
+ format,
143
+ sourcemap,
144
+ dir: outdir,
145
+ ...(hasTs && { entryFileNames: "[name].js" }),
146
+ },
88
147
  preserveEntrySignatures: "strict",
89
148
  treeshake: TREESHAKE,
90
149
  onwarn,
@@ -100,6 +159,7 @@ export function createRollupConfig(options = {}) {
100
159
  hasSummary: true,
101
160
  includeCssBundle: false,
102
161
  extraPlugins,
162
+ hasTs,
103
163
  }),
104
164
  output: { format, sourcemap, file: `${outdir}/bundle.js` },
105
165
  preserveEntrySignatures: "strict",
@@ -112,62 +172,30 @@ export function createRollupConfig(options = {}) {
112
172
  }
113
173
 
114
174
  /**
115
- * Runs both Rollup build targets programmatically using the Rollup Node.js API.
116
- *
117
- * Note: the `output` key inside `RollupOptions` is ignored by the `rollup()` API.
118
- * Output options must be passed separately to `build.write()`.
175
+ * Runs Rollup build targets programmatically using the Rollup Node.js API.
176
+ * Reuses `createRollupConfig` to avoid duplicating config resolution logic.
119
177
  *
120
178
  * @param {import("./utils/load-config.js").ElenaConfig} config
121
179
  * @returns {Promise<void>}
122
180
  */
123
181
  export async function runRollupBuild(config) {
124
- const src = config.input ?? "src";
125
- const outdir = config.output?.dir ?? "dist";
126
- const format = config.output?.format ?? "esm";
127
- const sourcemap = config.output?.sourcemap ?? true;
128
- const bundle = config.bundle !== undefined ? config.bundle : "src/index.js";
129
- const extraPlugins = config.plugins ?? [];
182
+ const configs = createRollupConfig(config);
130
183
 
131
- const entries = readdirSync(src, { recursive: true })
132
- .filter(f => f.endsWith(".js"))
133
- .map(f => `${src}/${f}`);
134
-
135
- // Build 1: individual modules + CSS bundle
136
184
  console.log(color(`░█ [ELENA]: Building Progressive Web Components...`));
137
185
  console.log(` `);
138
- for (const entry of entries) {
139
- console.log(color(`░█ [ELENA]: Generating and minifying ${entry}...`));
140
- }
141
-
142
- const build1 = await rollup({
143
- input: entries,
144
- plugins: buildPlugins({ src, outdir, hasSummary: false, includeCssBundle: true, extraPlugins }),
145
- preserveEntrySignatures: "strict",
146
- treeshake: TREESHAKE,
147
- onwarn,
148
- });
149
- await build1.write({ format, sourcemap, dir: outdir });
150
- await build1.close();
151
-
152
- // Build 2: single-file JS bundle (optional)
153
- if (bundle) {
154
- console.log(color(`░█ [ELENA]: Generating and minifying JS bundle...`));
155
- console.log(` `);
156
186
 
157
- const build2 = await rollup({
158
- input: bundle,
159
- plugins: buildPlugins({
160
- src,
161
- outdir,
162
- hasSummary: true,
163
- includeCssBundle: false,
164
- extraPlugins,
165
- }),
166
- preserveEntrySignatures: "strict",
167
- treeshake: TREESHAKE,
168
- onwarn,
169
- });
170
- await build2.write({ format, sourcemap, file: `${outdir}/bundle.js` });
171
- await build2.close();
187
+ for (const { output, ...inputOpts } of configs) {
188
+ if (Array.isArray(inputOpts.input)) {
189
+ for (const entry of inputOpts.input) {
190
+ console.log(color(`░█ [ELENA]: Generating and minifying ${entry}...`));
191
+ }
192
+ } else {
193
+ console.log(color(`░█ [ELENA]: Generating and minifying JS bundle...`));
194
+ console.log(` `);
195
+ }
196
+
197
+ const build = await rollup(inputOpts);
198
+ await build.write(output);
199
+ await build.close();
172
200
  }
173
201
  }
File without changes
File without changes