@ideasonpurpose/build-tools-wordpress 2.10.2 → 2.10.4
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/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/bin/zip.js +27 -38
- package/lib/AfterDoneReporterPlugin.js +47 -3
- package/lib/WatchRunReporterPlugin.js +12 -5
- package/lib/buildConfig.js +58 -16
- package/lib/prettier-hrtime.js +12 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### v2.10.3
|
|
8
|
+
|
|
9
|
+
> 17 July 2026
|
|
10
|
+
|
|
11
|
+
- More reporter tweaks
|
|
12
|
+
|
|
13
|
+
#### v2.10.2
|
|
14
|
+
|
|
15
|
+
> 16 July 2026
|
|
16
|
+
|
|
17
|
+
- tweak reporting
|
|
18
|
+
|
|
7
19
|
#### v2.10.1
|
|
8
20
|
|
|
9
21
|
> 15 July 2026
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ideasonpurpose/build-tools-wordpress
|
|
2
2
|
|
|
3
|
-
#### Version 2.10.
|
|
3
|
+
#### Version 2.10.4
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@ideasonpurpose/build-tools-wordpress)
|
|
6
6
|
[](https://github.com/ideasonpurpose/build-tools-wordpress#readme)
|
package/bin/zip.js
CHANGED
|
@@ -1,49 +1,46 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
|
+
// @ts-check
|
|
2
3
|
|
|
3
|
-
import { readJsonSync, ensureFileSync } from "fs-extra/esm";
|
|
4
|
-
import { stat } from "node:fs/promises";
|
|
5
|
-
|
|
6
|
-
import { basename, dirname, join } from "node:path/posix";
|
|
7
4
|
import { createReadStream, createWriteStream, statSync } from "node:fs";
|
|
8
|
-
|
|
5
|
+
import { basename, dirname, join } from "node:path/posix";
|
|
9
6
|
import { clearLine, cursorTo } from "node:readline";
|
|
10
7
|
|
|
11
|
-
import url from "url";
|
|
12
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
13
|
-
|
|
14
8
|
import { ZipArchive } from "archiver";
|
|
15
9
|
import chalk from "chalk";
|
|
16
|
-
import
|
|
10
|
+
import cliTruncate from "cli-truncate";
|
|
11
|
+
import { cosmiconfig } from "cosmiconfig";
|
|
17
12
|
import { filesize } from "filesize";
|
|
13
|
+
import { readJsonSync, ensureFileSync } from "fs-extra/esm";
|
|
18
14
|
import { globby } from "globby";
|
|
19
15
|
import isTextPath from "is-text-path";
|
|
20
|
-
import cliTruncate from "cli-truncate";
|
|
21
|
-
import stringLength from "string-length";
|
|
22
16
|
import replaceStream from "replacestream";
|
|
17
|
+
import stringLength from "string-length";
|
|
23
18
|
|
|
24
|
-
// import buildConfig from "../lib/buildConfig.js";
|
|
25
19
|
import { buildConfig } from "../index.js";
|
|
26
|
-
// import {dirname} from "node:path";
|
|
27
20
|
import { prettierHrtime } from "../lib/prettier-hrtime.js";
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {import("../lib/buildConfig.js").BuildConfig} BuildConfig
|
|
24
|
+
*
|
|
25
|
+
* @typedef {Object} ArchiveFile
|
|
26
|
+
* @property {string} path - Path relative to projectDir
|
|
27
|
+
* @property {import("node:fs").Stats} stat
|
|
28
|
+
* @property {import("node:stream").Readable} contents
|
|
29
|
+
*/
|
|
32
30
|
|
|
33
31
|
async function getConfig() {
|
|
34
32
|
const siteDir = process.cwd();
|
|
35
33
|
const explorer = cosmiconfig("ideasonpurpose");
|
|
36
34
|
const configFile = await explorer.search(siteDir);
|
|
37
|
-
const config = await buildConfig(configFile);
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
/** @type {BuildConfig} */
|
|
37
|
+
const config = await buildConfig(configFile);
|
|
41
38
|
|
|
42
39
|
return { config };
|
|
43
40
|
}
|
|
41
|
+
/** @type {{ config: BuildConfig }} */
|
|
44
42
|
const { config } = await getConfig();
|
|
45
43
|
|
|
46
|
-
// config.configFileUrl = new URL("package.json", config.configFileUrl);
|
|
47
44
|
const pkgJson = readJsonSync(new URL("package.json", config.configFileUrl));
|
|
48
45
|
pkgJson.name = pkgJson.name ?? "archive";
|
|
49
46
|
pkgJson.version = pkgJson.version ?? "";
|
|
@@ -56,14 +53,6 @@ const versionDirName = `${archiveName}${archiveVersion}`.replace(/[ .]/g, "_");
|
|
|
56
53
|
const zipFileName = `${versionDirName}.zip`;
|
|
57
54
|
const zipFile = new URL(`_builds/${zipFileName}`, config.configFileUrl);
|
|
58
55
|
|
|
59
|
-
// console.log({
|
|
60
|
-
// archiveName,
|
|
61
|
-
// archiveVersion,
|
|
62
|
-
// versionDirName,
|
|
63
|
-
// zipFile,
|
|
64
|
-
// zipFileName,
|
|
65
|
-
// });
|
|
66
|
-
|
|
67
56
|
ensureFileSync(zipFile.pathname);
|
|
68
57
|
const output = createWriteStream(zipFile);
|
|
69
58
|
|
|
@@ -80,7 +69,6 @@ const start = process.hrtime();
|
|
|
80
69
|
* files will be found relative to this.
|
|
81
70
|
*/
|
|
82
71
|
const projectDir = new URL(`${config.src}/../`, config.configFileUrl);
|
|
83
|
-
// process.exit();
|
|
84
72
|
|
|
85
73
|
/**
|
|
86
74
|
* Counters for total uncompressed size and number of files
|
|
@@ -143,7 +131,10 @@ globby(
|
|
|
143
131
|
inBytes += chunk.length;
|
|
144
132
|
});
|
|
145
133
|
|
|
146
|
-
file.contents.on("end", () =>
|
|
134
|
+
file.contents.on("end", () => {
|
|
135
|
+
fileCount += 1;
|
|
136
|
+
foundReporter(file);
|
|
137
|
+
});
|
|
147
138
|
|
|
148
139
|
/**
|
|
149
140
|
* Adding a data handler changes a stream's mode from paused to flowing
|
|
@@ -164,8 +155,11 @@ globby(
|
|
|
164
155
|
.then(() => archive.finalize())
|
|
165
156
|
.catch(console.error);
|
|
166
157
|
|
|
158
|
+
/**
|
|
159
|
+
* @param {ArchiveFile} file
|
|
160
|
+
*/
|
|
167
161
|
function foundReporter(file) {
|
|
168
|
-
|
|
162
|
+
if (!process.stdout.isTTY) return;
|
|
169
163
|
let outString = [
|
|
170
164
|
"🔍 ",
|
|
171
165
|
chalk.yellow("Found"),
|
|
@@ -181,9 +175,7 @@ function foundReporter(file) {
|
|
|
181
175
|
outString += chalk.blue(cliTruncate(file.path, cols, { position: "middle" }));
|
|
182
176
|
|
|
183
177
|
if (fileCount % 25 == 0) {
|
|
184
|
-
|
|
185
|
-
clearLine(process.stdout);
|
|
186
|
-
// process.stdout.cursorTo(0);
|
|
178
|
+
clearLine(process.stdout, 0);
|
|
187
179
|
cursorTo(process.stdout, 0);
|
|
188
180
|
process.stdout.write(outString);
|
|
189
181
|
}
|
|
@@ -196,10 +188,7 @@ function finishReporter() {
|
|
|
196
188
|
const savedBytes = inBytes - outBytes;
|
|
197
189
|
const savedPercent = ((1 - outBytes / inBytes) * 100).toFixed(2);
|
|
198
190
|
|
|
199
|
-
|
|
200
|
-
clearLine(process.stdout);
|
|
201
|
-
|
|
202
|
-
// process.stdout.cursorTo(0);
|
|
191
|
+
clearLine(process.stdout, 0);
|
|
203
192
|
cursorTo(process.stdout, 0);
|
|
204
193
|
|
|
205
194
|
console.log(
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
-
import
|
|
4
|
+
import { filesize } from "filesize";
|
|
5
|
+
import { prettierHrtime } from "./prettier-hrtime.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Clean post-compilation summary for dev server.
|
|
8
|
-
* Shows status, duration, and the local URL
|
|
9
|
+
* Shows status, duration, entrypoints with sizes, and the local URL.
|
|
9
10
|
*/
|
|
10
11
|
export class AfterDoneReporterPlugin {
|
|
11
12
|
constructor(options = {}) {
|
|
@@ -26,7 +27,7 @@ export class AfterDoneReporterPlugin {
|
|
|
26
27
|
const url = chalk.blue.underline(`http://${host}:${port}`);
|
|
27
28
|
|
|
28
29
|
const durationMs = stats.endTime && stats.startTime ? stats.endTime - stats.startTime : 0;
|
|
29
|
-
const time =
|
|
30
|
+
const time = prettierHrtime(durationMs);
|
|
30
31
|
|
|
31
32
|
const hasErrors = stats.hasErrors();
|
|
32
33
|
const hasWarnings = stats.hasWarnings();
|
|
@@ -41,6 +42,49 @@ export class AfterDoneReporterPlugin {
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
console.log(`\n${statusLine} → ${url}`);
|
|
45
|
+
|
|
46
|
+
// Entrypoint assets with sizes (exclude hot-update)
|
|
47
|
+
try {
|
|
48
|
+
const json = stats.toJson({
|
|
49
|
+
all: false,
|
|
50
|
+
assets: true,
|
|
51
|
+
entrypoints: true,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const assetMap = new Map();
|
|
55
|
+
for (const asset of json.assets ?? []) {
|
|
56
|
+
if (/hot-update/.test(asset.name)) continue;
|
|
57
|
+
assetMap.set(asset.name, asset);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const entrypoints = Object.entries(json.entrypoints ?? {}).sort(([a], [b]) =>
|
|
61
|
+
a.localeCompare(b),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (entrypoints.length) {
|
|
65
|
+
for (const [epName, epInfo] of entrypoints) {
|
|
66
|
+
const epAssets = (epInfo.assets ?? [])
|
|
67
|
+
.map((a) => assetMap.get(a.name ?? a))
|
|
68
|
+
.filter(Boolean)
|
|
69
|
+
.sort((a, b) => (b.size ?? 0) - (a.size ?? 0));
|
|
70
|
+
|
|
71
|
+
if (!epAssets.length) continue;
|
|
72
|
+
|
|
73
|
+
console.log(
|
|
74
|
+
` ${chalk.gray("↳")} ${chalk.bold(epName)} ${chalk.gray(`(${epAssets.length})`)}:`,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
for (const asset of epAssets) {
|
|
78
|
+
const size = asset.size != null ? filesize(asset.size) : "?";
|
|
79
|
+
console.log(
|
|
80
|
+
` ${chalk.gray("·")} ${chalk.white(asset.name)} ${chalk.gray(`— ${size}`)}`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
} catch {
|
|
86
|
+
// Non-fatal: don't clutter output if stats parsing fails
|
|
87
|
+
}
|
|
44
88
|
});
|
|
45
89
|
}
|
|
46
90
|
}
|
|
@@ -42,19 +42,26 @@ export class WatchRunReporterPlugin {
|
|
|
42
42
|
.map((p) => path.relative(root, p) || ".")
|
|
43
43
|
.sort();
|
|
44
44
|
|
|
45
|
+
const MAX_FILES = 6;
|
|
45
46
|
let changeMsg;
|
|
47
|
+
|
|
46
48
|
if (relFiles.length === 1) {
|
|
47
49
|
changeMsg = chalk.bold.yellow(relFiles[0]);
|
|
48
|
-
} else if (relFiles.length <=
|
|
50
|
+
} else if (relFiles.length <= MAX_FILES) {
|
|
49
51
|
changeMsg = chalk.bold.yellow(relFiles.join(", "));
|
|
50
52
|
} else {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
const visible = relFiles.slice(0, MAX_FILES).join(", ");
|
|
54
|
+
const remaining = relFiles.length - MAX_FILES;
|
|
55
|
+
changeMsg =
|
|
56
|
+
chalk.bold.yellow(visible) +
|
|
57
|
+
chalk.gray(` +${remaining} more`);
|
|
54
58
|
}
|
|
55
59
|
|
|
60
|
+
const count =
|
|
61
|
+
relFiles.length > 1 ? chalk.cyan(`(${relFiles.length})`) + " " : "";
|
|
62
|
+
|
|
56
63
|
console.log(
|
|
57
|
-
`\n${chalk.cyan("⟳")} Changed: ${changeMsg} ${this.config.message}`,
|
|
64
|
+
`\n${chalk.cyan("⟳")} Changed: ${count}${changeMsg} ${this.config.message}`,
|
|
58
65
|
);
|
|
59
66
|
});
|
|
60
67
|
}
|
package/lib/buildConfig.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
import fs from "fs-extra";
|
|
2
4
|
import { posix as path } from "path";
|
|
3
5
|
import chalk from "chalk";
|
|
4
6
|
import url from "url";
|
|
5
7
|
|
|
6
|
-
// import { findLocalPort } from "../index.js";
|
|
7
|
-
|
|
8
|
-
// import defaultConfig from "../default.config.js";
|
|
9
8
|
/**
|
|
10
9
|
* Future node versions should import package.json directly:
|
|
11
10
|
* import packageJson from "./package.json" with { type: "json" };
|
|
@@ -19,11 +18,46 @@ import url from "url";
|
|
|
19
18
|
* create a theme named 'iop-build-tools'.
|
|
20
19
|
*/
|
|
21
20
|
const pkgJsonPath = path.resolve(process.cwd(), "./package.json");
|
|
22
|
-
const packageJson = JSON.parse(fs.readFileSync(pkgJsonPath));
|
|
23
|
-
// import packageJson from "./package.json" with { type: "json" };
|
|
21
|
+
const packageJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
|
|
24
22
|
|
|
25
23
|
const { name: themeName } = packageJson;
|
|
26
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Resolved project config returned by {@link buildConfig}.
|
|
27
|
+
*
|
|
28
|
+
* @typedef {Object} BuildConfig
|
|
29
|
+
* @property {string} src - Absolute path to the project source directory
|
|
30
|
+
* @property {string} dist - Absolute path to the project dist directory
|
|
31
|
+
* @property {Record<string, string|string[]>} entry - Webpack entry map keyed by basename
|
|
32
|
+
* @property {string} publicPath - Public URL path for compiled assets
|
|
33
|
+
* @property {string} contentBase
|
|
34
|
+
* @property {string} manifestFile
|
|
35
|
+
* @property {string} esTarget
|
|
36
|
+
* @property {string|false} devtool
|
|
37
|
+
* @property {string[]} transpileDependencies
|
|
38
|
+
* @property {string|boolean} proxy
|
|
39
|
+
* @property {URL} configFileUrl - File URL for the discovered config/package.json
|
|
40
|
+
* @property {"theme"|"plugin"|string} [type] - Project type; plugins omit version from archive names
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* User-facing config values before path resolution and entry normalization.
|
|
45
|
+
*
|
|
46
|
+
* @typedef {Object} BuildConfigInput
|
|
47
|
+
* @property {string} [src]
|
|
48
|
+
* @property {string} [dist]
|
|
49
|
+
* @property {string|string[]|Record<string, string|string[]>} [entry]
|
|
50
|
+
* @property {string} [publicPath]
|
|
51
|
+
* @property {string} [contentBase]
|
|
52
|
+
* @property {string} [manifestFile]
|
|
53
|
+
* @property {string} [esTarget]
|
|
54
|
+
* @property {string|false} [devtool]
|
|
55
|
+
* @property {string|string[]} [transpileDependencies]
|
|
56
|
+
* @property {string|boolean} [proxy]
|
|
57
|
+
* @property {"theme"|"plugin"|string} [type]
|
|
58
|
+
* @property {URL} [configFileUrl]
|
|
59
|
+
*/
|
|
60
|
+
|
|
27
61
|
const defaultConfig = {
|
|
28
62
|
src: `./wp-content/themes/${themeName}/src`,
|
|
29
63
|
dist: `./wp-content/themes/${themeName}/dist`,
|
|
@@ -45,8 +79,10 @@ const defaultConfig = {
|
|
|
45
79
|
*
|
|
46
80
|
* Asynchronous values:
|
|
47
81
|
* -
|
|
82
|
+
*
|
|
83
|
+
* @param {{ filepath?: string, config?: BuildConfigInput } | null} [configFile]
|
|
84
|
+
* @returns {Promise<BuildConfig>}
|
|
48
85
|
*/
|
|
49
|
-
|
|
50
86
|
export async function buildConfig(configFile = { config: {} }) {
|
|
51
87
|
/**
|
|
52
88
|
* This is a temporary workaround for a problem with using `process.env.NAME` in
|
|
@@ -150,17 +186,22 @@ export async function buildConfig(configFile = { config: {} }) {
|
|
|
150
186
|
* Overlapping basenames will be joined into a single entrypoint
|
|
151
187
|
* ["./index.js", "./app.js", "./index.scss"] => { app: ["./app.js"], index: ["./index.js", "./index.scss"]}
|
|
152
188
|
*/
|
|
153
|
-
|
|
154
|
-
|
|
189
|
+
let entry = config.entry;
|
|
190
|
+
if (typeof entry === "string") {
|
|
191
|
+
entry = [entry];
|
|
155
192
|
}
|
|
156
|
-
if (Array.isArray(
|
|
157
|
-
|
|
158
|
-
obj
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
193
|
+
if (Array.isArray(entry)) {
|
|
194
|
+
entry = entry.reduce(
|
|
195
|
+
(obj, src) => {
|
|
196
|
+
obj[path.parse(src).name] = /** @type {string[]} */ ([])
|
|
197
|
+
.concat(obj[path.parse(src).name], src)
|
|
198
|
+
.filter((i) => i);
|
|
199
|
+
return obj;
|
|
200
|
+
},
|
|
201
|
+
/** @type {Record<string, string[]>} */ ({}),
|
|
202
|
+
);
|
|
163
203
|
}
|
|
204
|
+
config.entry = /** @type {Record<string, string | string[]>} */ (entry);
|
|
164
205
|
|
|
165
206
|
/**
|
|
166
207
|
* Remap proxy: true to default value
|
|
@@ -169,12 +210,13 @@ export async function buildConfig(configFile = { config: {} }) {
|
|
|
169
210
|
config.proxy = defaultConfig.proxy;
|
|
170
211
|
}
|
|
171
212
|
|
|
172
|
-
return config;
|
|
213
|
+
return /** @type {BuildConfig} */ (config);
|
|
173
214
|
}
|
|
174
215
|
|
|
175
216
|
/**
|
|
176
217
|
* Warnings are broken out below
|
|
177
218
|
*/
|
|
219
|
+
/** @param {string} src */
|
|
178
220
|
const noSrcExists = (src) => {
|
|
179
221
|
console.log(
|
|
180
222
|
"🛑 ",
|
package/lib/prettier-hrtime.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import prettyHrtime from "pretty-hrtime";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Format hrtime tuples or millisecond durations into a human string.
|
|
5
|
+
* Accepts:
|
|
6
|
+
* - [seconds, nanoseconds] (from process.hrtime())
|
|
7
|
+
* - number (milliseconds, e.g. stats.endTime - stats.startTime)
|
|
8
|
+
*/
|
|
3
9
|
export const prettierHrtime = (hrtime) => {
|
|
10
|
+
if (typeof hrtime === "number") {
|
|
11
|
+
const secs = Math.floor(hrtime / 1000);
|
|
12
|
+
const nsecs = Math.round((hrtime % 1000) * 1e6);
|
|
13
|
+
hrtime = [secs, nsecs];
|
|
14
|
+
}
|
|
15
|
+
|
|
4
16
|
let timeString;
|
|
5
17
|
const seconds = hrtime[1] > 5e6 ? " seconds" : " second";
|
|
6
18
|
if (hrtime[0] > 60) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ideasonpurpose/build-tools-wordpress",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.4",
|
|
4
4
|
"description": "Build scripts and dependencies for IOP's WordPress development environments.",
|
|
5
5
|
"homepage": "https://github.com/ideasonpurpose/build-tools-wordpress#readme",
|
|
6
6
|
"bugs": {
|