x4js 2.3.1 → 2.3.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.
@@ -3,6 +3,7 @@ import { fileURLToPath } from "node:url";
3
3
  import { sassPlugin } from "esbuild-sass-plugin";
4
4
  import { lessPlugin } from "./less-plugin.mjs";
5
5
  import { copyPlugin } from "./copy-plugin.mjs";
6
+ import { rawFilePlugin } from "./rawfile-plugin.mjs";
6
7
 
7
8
  const cliDir = path.dirname(fileURLToPath(import.meta.url));
8
9
  const devClient = path.join(cliDir, "dev-client.js");
@@ -28,7 +29,7 @@ export function createBuildOptions(config, mode) {
28
29
  format: "iife",
29
30
  target: "es2020",
30
31
  minify: production,
31
- sourcemap: production ? false : "inline",
32
+ sourcemap: production ? false : "linked",
32
33
  logLevel: "info",
33
34
  external: config.external,
34
35
  assetNames: "assets/[name]-[hash]",
@@ -47,6 +48,10 @@ export function createBuildOptions(config, mode) {
47
48
  VERSION_ID: versionId(),
48
49
  },
49
50
  plugins: [
51
+ rawFilePlugin({
52
+ filter: /\.svg$/,
53
+ mime: "image/svg+xml",
54
+ }),
50
55
  sassPlugin({
51
56
  type: "css",
52
57
  filter: /\.s[ac]ss$/,
package/cli/config.mjs CHANGED
@@ -9,7 +9,6 @@ const DEFAULTS = Object.freeze({
9
9
  define: {},
10
10
  dev: {
11
11
  host: "127.0.0.1",
12
- port: 8000,
13
12
  https: false,
14
13
  },
15
14
  });
@@ -96,8 +95,8 @@ export function loadConfig(root = process.cwd(), env = process.env) {
96
95
  if (typeof host !== "string" || !host)
97
96
  throw new Error("x4.dev.host must be a non-empty string");
98
97
 
99
- const port = devCfg.port ?? DEFAULTS.dev.port;
100
- if (!Number.isInteger(port) || port < 0 || port > 65535)
98
+ const port = devCfg.port;
99
+ if (port !== undefined && (!Number.isInteger(port) || port < 0 || port > 65535))
101
100
  throw new Error("x4.dev.port must be an integer between 0 and 65535");
102
101
 
103
102
  const https = devCfg.https ?? DEFAULTS.dev.https;
@@ -133,7 +132,7 @@ export function loadConfig(root = process.cwd(), env = process.env) {
133
132
  })),
134
133
  external: [...external],
135
134
  define: { ...define },
136
- dev: {
135
+ dev: {
137
136
  host,
138
137
  port,
139
138
  https,
package/cli/create.mjs CHANGED
@@ -33,12 +33,6 @@ async function ensureEmptyTarget(target) {
33
33
  }
34
34
  }
35
35
 
36
- async function clearDirectory(target) {
37
- const entries = await fs.readdir(target, { withFileTypes: true });
38
- await Promise.all(entries.map((entry) =>
39
- fs.rm(path.join(target, entry.name), { recursive: true, force: true })
40
- ));
41
- }
42
36
 
43
37
  async function patchPackage(target, projectName, version) {
44
38
  const filename = path.join(target, "package.json");
@@ -66,18 +60,39 @@ async function patchPackage(target, projectName, version) {
66
60
  }
67
61
 
68
62
  async function npmInstall(target) {
69
- const command = process.platform === "win32" ? "npm.cmd" : "npm";
63
+ let command;
64
+ let args;
65
+
66
+ if (process.platform === "win32") {
67
+ command = process.env.ComSpec || "cmd.exe";
68
+ args = ["/d", "/s", "/c", "npm install"];
69
+ }
70
+ else {
71
+ command = "npm";
72
+ args = ["install"];
73
+ }
74
+
70
75
  await new Promise((resolve, reject) => {
71
- const child = spawn(command, ["install"], {
76
+ const child = spawn(command, args, {
72
77
  cwd: target,
73
78
  stdio: "inherit",
74
79
  });
80
+
75
81
  child.on("error", reject);
82
+
76
83
  child.on("exit", (code, signal) => {
77
- if (code === 0)
84
+ if (code === 0) {
78
85
  resolve();
79
- else
80
- reject(new Error(`npm install failed${signal ? ` (${signal})` : ` (exit ${code})`}`));
86
+ return;
87
+ }
88
+
89
+ reject(
90
+ new Error(
91
+ `npm install failed${
92
+ signal ? ` (${signal})` : ` (exit ${code})`
93
+ }`
94
+ )
95
+ );
81
96
  });
82
97
  });
83
98
  }
@@ -105,6 +120,7 @@ export async function create(argv = [], { version = "unknown", cwd = process.cwd
105
120
  throw new Error(`Unknown template '${values.template}'. Run 'x4js templates' to list templates.`);
106
121
 
107
122
  const targetCreated = await ensureEmptyTarget(target);
123
+ let projectReady = false;
108
124
  info("create", target);
109
125
  info("template", values.template);
110
126
 
@@ -121,6 +137,7 @@ export async function create(argv = [], { version = "unknown", cwd = process.cwd
121
137
  }));
122
138
 
123
139
  await patchPackage(target, projectName, version);
140
+ projectReady = true;
124
141
 
125
142
  if (!values["no-install"]) {
126
143
  info("install", "npm");
@@ -130,10 +147,11 @@ export async function create(argv = [], { version = "unknown", cwd = process.cwd
130
147
  success("created", target);
131
148
  }
132
149
  catch (error) {
133
- if (targetCreated)
150
+ // Never remove a directory that existed before `x4js create`.
151
+ // Once package.json has been patched, the project is considered
152
+ // created and is also kept if `npm install` fails.
153
+ if (targetCreated && !projectReady)
134
154
  await fs.rm(target, { recursive: true, force: true });
135
- else
136
- await clearDirectory(target);
137
155
  throw error;
138
156
  }
139
157
  }
package/cli/dev.mjs CHANGED
@@ -52,7 +52,7 @@ function serverUrl(host, port, https) {
52
52
  displayHost = "[::1]";
53
53
  else if (host.includes(":") && !host.startsWith("["))
54
54
  displayHost = `[${host}]`;
55
- return `${https ? "https" : "http"}://${displayHost}:${port}/`;
55
+ return `${https ? "https" : "http"}://${displayHost}:${port}`;
56
56
  }
57
57
 
58
58
  export async function dev(argv = [], root = process.cwd()) {
@@ -85,16 +85,18 @@ export async function dev(argv = [], root = process.cwd()) {
85
85
  async function start(config) {
86
86
  const host = values.host ?? config.dev.host;
87
87
  const port = values.port === undefined ? config.dev.port : Number(values.port);
88
- if (port < 0 || port > 65535)
88
+ if (port !== undefined && (port < 0 || port > 65535))
89
89
  throw new Error("--port must be between 0 and 65535");
90
90
 
91
91
  const useHttps = protocolConfig(config, values);
92
92
  const serveOptions = {
93
93
  host,
94
- port,
95
94
  servedir: config.outdir,
96
95
  };
97
96
 
97
+ if (port !== undefined)
98
+ serveOptions.port = port;
99
+
98
100
  if (useHttps)
99
101
  Object.assign(serveOptions, resolveTls(config));
100
102
 
@@ -108,7 +110,7 @@ export async function dev(argv = [], root = process.cwd()) {
108
110
  const url = serverUrl(actualHost, result.port, useHttps);
109
111
  info("mode", "dev");
110
112
  info("outdir", config.outdir);
111
- success("listening", url);
113
+ success("server", url);
112
114
 
113
115
  if (values.open && !browserOpened) {
114
116
  browserOpened = true;
@@ -0,0 +1,43 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ export function rawFilePlugin({ filter, mime }) {
5
+ const namespace = "x4-raw-file";
6
+
7
+ return {
8
+ name: "x4-raw-file",
9
+
10
+ setup(build) {
11
+ build.onResolve({ filter }, (args) => {
12
+ // Seulement les imports JS/TS.
13
+ if (
14
+ args.kind !== "import-statement" &&
15
+ args.kind !== "dynamic-import"
16
+ ) {
17
+ return;
18
+ }
19
+
20
+ return {
21
+ path: path.resolve(args.resolveDir, args.path),
22
+ namespace,
23
+ };
24
+ });
25
+
26
+ build.onLoad(
27
+ { filter: /.*/, namespace },
28
+ async (args) => {
29
+ const data = await fs.readFile(args.path);
30
+
31
+ const value =
32
+ `data:${mime};base64,${data.toString("base64")}`;
33
+
34
+ return {
35
+ contents:
36
+ `export default ${JSON.stringify(value)};`,
37
+ loader: "js",
38
+ };
39
+ }
40
+ );
41
+ },
42
+ };
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x4js",
3
- "version": "2.3.1",
3
+ "version": "2.3.3",
4
4
  "type": "module",
5
5
  "main": "src/x4.ts",
6
6
  "module": "src/x4.ts",
@@ -14,7 +14,7 @@
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  **/
16
16
 
17
- @import "../shared.scss";
17
+ @use "../shared";
18
18
 
19
19
  :root {
20
20
  --color-dialog-caption: var( --color-primary-a80 );
@@ -14,77 +14,77 @@
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  **/
16
16
 
17
+ @use "sass:color";
17
18
 
18
19
  $color--base: #569cd6;
19
20
  $color--interval: 8.4%;
20
21
 
21
22
  :root {
22
23
  --color-primary-a0: #ffffff;
23
- --color-primary-a5: #{lighten($color--base, 35%)};
24
- --color-primary-a10: #{lighten($color--base, $color--interval * 4)};
25
- --color-primary-a20: #{lighten($color--base, $color--interval * 3)};
26
- --color-primary-a30: #{lighten($color--base, $color--interval * 2)};
27
- --color-primary-a40: #{lighten($color--base, $color--interval)};
24
+ --color-primary-a5: #{color.adjust($color--base, $lightness: 35%)};
25
+ --color-primary-a10: #{color.adjust($color--base, $lightness: $color--interval * 4)};
26
+ --color-primary-a20: #{color.adjust($color--base, $lightness: $color--interval * 3)};
27
+ --color-primary-a30: #{color.adjust($color--base, $lightness: $color--interval * 2)};
28
+ --color-primary-a40: #{color.adjust($color--base, $lightness: $color--interval)};
28
29
  --color-primary-a50: #{$color--base};
29
- --color-primary-a55: #{darken($color--base,5%)};
30
- --color-primary-a60: #{darken($color--base, $color--interval )};
31
- --color-primary-a70: #{darken($color--base, $color--interval * 2)};
32
- --color-primary-a80: #{darken($color--base, $color--interval * 3)};
33
- --color-primary-a90: #{darken($color--base, $color--interval * 4)};
30
+ --color-primary-a55: #{color.adjust($color--base, $lightness: -5%)};
31
+ --color-primary-a60: #{color.adjust($color--base, $lightness: -$color--interval)};
32
+ --color-primary-a70: #{color.adjust($color--base, $lightness: -$color--interval * 2)};
33
+ --color-primary-a80: #{color.adjust($color--base, $lightness: -$color--interval * 3)};
34
+ --color-primary-a90: #{color.adjust($color--base, $lightness: -$color--interval * 4)};
34
35
  --color-primary-a100: #000000;
35
36
 
36
- --color-danger-a30: #{lighten(#c01010,30%)};
37
+ --color-danger-a30: #{color.adjust(#c01010, $lightness: 30%)};
37
38
  --color-danger-a50: #c01010;
38
- --color-danger-a60: #{darken(#c01010,10%)};
39
+ --color-danger-a60: #{color.adjust(#c01010, $lightness: -10%)};
39
40
 
40
41
  --color-warning-a50: #b67b0d;
41
42
 
42
43
  --color-success-a50: #10c01f;
43
- --color-success-a60: #{darken(#10c01f,10%)};
44
+ --color-success-a60: #{color.adjust(#10c01f, $lightness: -10%)};
44
45
  }
45
46
 
46
47
  :root {
47
48
  // Backgrounds
48
- --background-primary: var(--color-primary-a0); // Fond principal
49
- --background-secondary: var(--color-primary-a10); // Fond secondaire
50
- --background-ternary: #f4f4f4; // Fond secondaire
49
+ --background-primary: var(--color-primary-a0);
50
+ --background-secondary: var(--color-primary-a10);
51
+ --background-ternary: #f4f4f4;
51
52
 
52
53
  // Texts
53
- --text-primary: var(--color-primary-a100); // Texte principal
54
- --text-secondary: #999; // Texte secondaire
55
- --text-ternary: #666; // Texte tertiaire
54
+ --text-primary: var(--color-primary-a100);
55
+ --text-secondary: #999;
56
+ --text-ternary: #666;
56
57
 
57
- // disabled
58
+ // Disabled
58
59
  --disabled-background: #ccc;
59
60
  --disabled-color: white;
60
61
  --disabled-color-dark: #aaa;
61
62
 
62
- // accents
63
- --accent-background: var(--color-primary-a60);
64
- --accent-background-hover: var(--color-primary-a55);
63
+ // Accents
64
+ --accent-background: var(--color-primary-a60);
65
+ --accent-background-hover: var(--color-primary-a55);
65
66
  --accent-background-focus: var(--color-primary-a70);
66
- --accent-background-active: var(--color-primary-a80);
67
+ --accent-background-active: var(--color-primary-a80);
67
68
 
68
- --accent-color: var(--color-primary-a0);
69
- --accent-color-hover: var(--color-primary-a0);
69
+ --accent-color: var(--color-primary-a0);
70
+ --accent-color-hover: var(--color-primary-a0);
70
71
  --accent-color-focus: var(--color-primary-a0);
71
- --accent-color-active: var(--color-primary-a0);
72
+ --accent-color-active: var(--color-primary-a0);
72
73
 
73
74
  // Borders
74
- --border: #e1e1e1; // Bordures
75
- --border-light: #eaeaea; // Bordures
76
- --border-hover: #c2c2c2; // Bordures au survol
77
- --border-focus: var( --accent-background ); // Bordures si focus
78
-
79
- --alert-background: var( --color-danger-a50 );
80
- --alert-background-active: var( --color-danger-a60 );
81
- --alert-color: var( --color-primary-a0 );
82
-
83
- --warning-background: var( --color-warning-a50 );
84
- --warning-color: var( --color-primary-a0 );
85
-
86
- --success-background: var( --color-success-a50 );
87
- --success-background-active: var( --color-success-a60 );
88
- --success-color: var( --color-success-a0 );
89
- }
90
-
75
+ --border: #e1e1e1;
76
+ --border-light: #eaeaea;
77
+ --border-hover: #c2c2c2;
78
+ --border-focus: var(--accent-background);
79
+
80
+ --alert-background: var(--color-danger-a50);
81
+ --alert-background-active: var(--color-danger-a60);
82
+ --alert-color: var(--color-primary-a0);
83
+
84
+ --warning-background: var(--color-warning-a50);
85
+ --warning-color: var(--color-primary-a0);
86
+
87
+ --success-background: var(--color-success-a50);
88
+ --success-background-active: var(--color-success-a60);
89
+ --success-color: var(--color-primary-a0);
90
+ }
package/src/x4.scss CHANGED
@@ -14,7 +14,7 @@
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  **/
16
16
 
17
- @import "./components/normalize.scss";
18
- @import "./components/colors.scss";
19
- @import "./components/themes.scss";
20
- @import "./components/base.scss";
17
+ @use "./components/normalize";
18
+ @use "./components/colors";
19
+ @use "./components/themes";
20
+ @use "./components/base";