@ideasonpurpose/build-tools-wordpress 2.10.7 → 2.10.9

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ideasonpurpose/build-tools-wordpress
2
2
 
3
- #### Version 2.10.7
3
+ #### Version 2.10.9
4
4
 
5
5
  [![NPM Version](https://img.shields.io/npm/v/%40ideasonpurpose%2Fbuild-tools-wordpress?logo=npm)](https://www.npmjs.com/package/@ideasonpurpose/build-tools-wordpress)
6
6
  [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/ideasonpurpose/build-tools-wordpress/npm-publish.yml?logo=github&logoColor=white)](https://github.com/ideasonpurpose/build-tools-wordpress/actions/workflows/npm-publish.yml)
@@ -8,7 +8,9 @@
8
8
 
9
9
  Build scripts and shared dependencies for WordPress development. Used in production at [Ideas On Purpose](https://www.ideasonpurpose.com).
10
10
 
11
- This package centralizes Webpack configuration, asset pipelines, and helper CLIs so host projects stay thin: a small `package.json`, a one-line `webpack.config.js`, and an optional config file.
11
+ This package centralizes Webpack configuration, asset pipelines, and helper CLIs so host projects stay fast and thin: a small `package.json`, a one-line `webpack.config.js`, and an optional config file.
12
+
13
+ Use with IOP's lightning-fast [Docker-based WordPress development image](https://github.com/ideasonpurpose/docker-wordpress-dev).
12
14
 
13
15
  ## Requirements
14
16
 
@@ -46,14 +48,16 @@ Prettier and Stylelint configs are re-exported from this package’s dependencie
46
48
 
47
49
  ## Quick start
48
50
 
49
- **1. Point Webpack at this package**
51
+ ### 1. Point Webpack at this package
50
52
 
51
53
  ```js
52
54
  // webpack.config.js
53
55
  export { webpackConfig as default } from "@ideasonpurpose/build-tools-wordpress";
54
56
  ```
55
57
 
56
- **2. Lay out sources** under the default theme paths (package `name` → theme folder):
58
+ ### 2. Source files
59
+
60
+ The project should have these files:
57
61
 
58
62
  ```text
59
63
  wp-content/themes/<package-name>/
@@ -61,18 +65,17 @@ wp-content/themes/<package-name>/
61
65
  js/main.js
62
66
  js/admin.js
63
67
  js/editor.js
64
- sass/ # or styles/
65
- dist/ # build output
68
+ styles/ # formerly 'sass'
66
69
  ```
67
70
 
68
- **3. Run**
71
+ ### 3. Run
69
72
 
70
73
  ```sh
71
- npm start # webpack-dev-server (proxies local WordPress when available)
72
- NODE_ENV=production npm run build # production build + zip (if postbuild is set)
74
+ npm run dev
75
+
73
76
  ```
74
77
 
75
- Full IOP projects also use Docker Compose tooling from this package (`tooling/docker-compose.yml`) and scripts like `bootstrap`, `db:dump`, and `project:refresh`. Those are optional if you only need the asset pipeline.
78
+ ### 4. Build
76
79
 
77
80
  ## Configuration
78
81
 
@@ -204,6 +207,21 @@ Notes:
204
207
  - Custom: remove top-level `fill="none"`
205
208
  - `removeUselessStrokeAndFill` with `removeNone: true`
206
209
 
210
+ ## WP-CLI
211
+
212
+ The WordPress base image includes [wp-cli](https://wordpress.org/cli/) and all commands can be run on the image using the `wp-cli` npm script. Commands with flags need to include a double-hyphen, but we just include them for everything. These all work as expected:
213
+
214
+ ```sh
215
+ # list users
216
+ npm run wp-cli -- wp user list
217
+
218
+ # Update to pre-release
219
+ npm run wp-cli -- wp core update --version=7.1-RC4
220
+
221
+ # Add a user for e2e testing
222
+ wp user create test test@example.com --role=administrator --user_pass=test123
223
+ ```
224
+
207
225
  ## CLI tools
208
226
 
209
227
  | Command | Purpose |
@@ -27,8 +27,10 @@ import prettier from "prettier";
27
27
  * - wp:gallery
28
28
  */
29
29
 
30
- import { readFile, writeFile } from "fs/promises";
31
- import { resolve, basename } from "path";
30
+ import { realpathSync } from "node:fs";
31
+ import { readFile, writeFile } from "node:fs/promises";
32
+ import { basename, resolve } from "node:path";
33
+ import { fileURLToPath } from "node:url";
32
34
 
33
35
  /**
34
36
  *
@@ -146,7 +148,7 @@ export function trimInsideListElements(content) {
146
148
  .replace(/\s*<!-- wp:list /g, "<!-- wp:list ")
147
149
  .replace(/>\s*<!-- wp:list /g, ">\n\n<!-- wp:list ")
148
150
  .replace(/>\s*<!-- wp:list-item /g, ">\n\n<!-- wp:list-item ")
149
- .replace(/<!-- \/wp:list-item -->\s*</g, "<!-- \/wp:list-item -->\n\n<")
151
+ .replace(/<!-- \/wp:list-item -->\s*</g, "<!-- /wp:list-item -->\n\n<")
150
152
  .replace(/<li>\s*/g, "<li>")
151
153
  .replace(/\s*<\/li>/g, "</li>");
152
154
  }
@@ -177,12 +179,10 @@ export function formatWithPrettier(content) {
177
179
  }
178
180
 
179
181
  /**
180
- * @param {String} filepath
182
+ * @param {string} content
183
+ * @returns {Promise<string>}
181
184
  */
182
- export async function formatWPBlockPattern(filepath) {
183
- const startTime = process.hrtime.bigint();
184
- const rawFile = await readFile(filepath, "utf8");
185
-
185
+ export async function formatWPBlockPatternContent(content) {
186
186
  const formatters = [
187
187
  formatWithPrettier,
188
188
  normalizeCommentTagSpacing,
@@ -192,10 +192,19 @@ export async function formatWPBlockPattern(filepath) {
192
192
  normalizeNewlines,
193
193
  ];
194
194
 
195
- const outputHtml = await formatters.reduce(
195
+ return formatters.reduce(
196
196
  async (acc, fn) => fn(await acc),
197
- Promise.resolve(rawFile),
197
+ Promise.resolve(content),
198
198
  );
199
+ }
200
+
201
+ /**
202
+ * @param {string} filepath
203
+ */
204
+ export async function formatWPBlockPattern(filepath) {
205
+ const startTime = process.hrtime.bigint();
206
+ const rawFile = await readFile(filepath, "utf8");
207
+ const outputHtml = await formatWPBlockPatternContent(rawFile);
199
208
 
200
209
  await writeFile(filepath, outputHtml, "utf8");
201
210
  const endTime = process.hrtime.bigint();
@@ -204,11 +213,49 @@ export async function formatWPBlockPattern(filepath) {
204
213
  console.log(`${basename(filepath)} ${(duration / 1e6).toFixed(2)}ms`);
205
214
  }
206
215
 
216
+ /**
217
+ * @returns {Promise<string>}
218
+ */
219
+ async function readStdin() {
220
+ const chunks = [];
221
+ for await (const chunk of process.stdin) {
222
+ chunks.push(chunk);
223
+ }
224
+ return Buffer.concat(chunks).toString("utf8");
225
+ }
226
+
207
227
  export async function main(filepath = process.argv[2]) {
208
- if (!filepath) {
209
- console.error("Error: A filepath is required.");
210
- return;
228
+ try {
229
+ if (filepath) {
230
+ await formatWPBlockPattern(resolve(filepath));
231
+ return;
232
+ }
233
+
234
+ if (process.stdin.isTTY) {
235
+ console.error(
236
+ "Usage: iop-format-wp-block-pattern <filepath>\n iop-format-wp-block-pattern < input.php",
237
+ );
238
+ process.exitCode = 1;
239
+ return;
240
+ }
241
+
242
+ const formatted = await formatWPBlockPatternContent(await readStdin());
243
+ process.stdout.write(formatted);
244
+ } catch (error) {
245
+ console.error("Error:", error);
246
+ process.exitCode = 1;
211
247
  }
212
- await formatWPBlockPattern(resolve(filepath));
213
248
  }
214
- if (process.argv[2]) main();
249
+
250
+ const isMain = (() => {
251
+ if (process.argv[1] == null) return false;
252
+ try {
253
+ return (
254
+ fileURLToPath(import.meta.url) === realpathSync(resolve(process.argv[1]))
255
+ );
256
+ } catch {
257
+ return false;
258
+ }
259
+ })();
260
+
261
+ if (isMain) main();
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+
3
+ //@ts-check
4
+
5
+ import { execFileSync } from "node:child_process";
6
+ import { realpathSync } from "node:fs";
7
+ import { resolve } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+
10
+ const blockPatternPath = /(?:^|\/)wp-content\/themes\/[^/]+\/patterns\/.*\.php$/;
11
+
12
+ /**
13
+ * @param {string} filepath
14
+ * @returns {string}
15
+ */
16
+ export function getFormatter(filepath) {
17
+ const normalizedPath = filepath.replaceAll("\\", "/");
18
+ return blockPatternPath.test(normalizedPath)
19
+ ? "iop-format-wp-block-pattern"
20
+ : "format-mixed-php-html";
21
+ }
22
+
23
+ /**
24
+ * @param {string[]} args
25
+ */
26
+ export async function main(args = process.argv.slice(2)) {
27
+ const fileFlagIndex = args.indexOf("--file");
28
+ const filepath = args[fileFlagIndex + 1];
29
+
30
+ if (fileFlagIndex === -1 || !filepath) {
31
+ console.error(
32
+ "Usage: iop-format-wp-php --file <filepath> < input.php",
33
+ );
34
+ process.exitCode = 1;
35
+ return;
36
+ }
37
+
38
+ if (process.stdin.isTTY) {
39
+ console.error(
40
+ "Usage: iop-format-wp-php --file <filepath> < input.php",
41
+ );
42
+ process.exitCode = 1;
43
+ return;
44
+ }
45
+
46
+ const formatter = getFormatter(filepath);
47
+
48
+ try {
49
+ const formatted = execFileSync(formatter, [], {
50
+ input: await readStdin(),
51
+ encoding: "utf8",
52
+ stdio: ["pipe", "pipe", "inherit"],
53
+ });
54
+ process.stdout.write(formatted);
55
+ } catch (error) {
56
+ console.error(`Error running ${formatter}:`, error);
57
+ process.exitCode = 1;
58
+ }
59
+ }
60
+
61
+ /**
62
+ * @returns {Promise<string>}
63
+ */
64
+ async function readStdin() {
65
+ const chunks = [];
66
+ for await (const chunk of process.stdin) {
67
+ chunks.push(chunk);
68
+ }
69
+ return Buffer.concat(chunks).toString("utf8");
70
+ }
71
+
72
+ const isMain = (() => {
73
+ if (process.argv[1] == null) return false;
74
+ try {
75
+ return (
76
+ fileURLToPath(import.meta.url) === realpathSync(resolve(process.argv[1]))
77
+ );
78
+ } catch {
79
+ return false;
80
+ }
81
+ })();
82
+
83
+ if (isMain) main();
@@ -55,7 +55,7 @@
55
55
  "version": "version-everything && git add -u",
56
56
  "postversion": "npm run build",
57
57
  "webgrind": "docker compose run --rm --service-ports webgrind",
58
- "wp-cli": "docker compose exec -u wp wordpress",
58
+ "wp-cli": "docker compose exec wordpress",
59
59
  "zip": "iop-build-zip-archive"
60
60
  },
61
61
  "prettier": "@ideasonpurpose/prettier-config",
@@ -63,7 +63,7 @@
63
63
  "extends": "@ideasonpurpose/stylelint-config"
64
64
  },
65
65
  "devDependencies": {
66
- "@ideasonpurpose/build-tools-wordpress": "^2.5.1"
66
+ "@ideasonpurpose/build-tools-wordpress": "^2.10.8"
67
67
  },
68
68
  "version-everything": {
69
69
  "files": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ideasonpurpose/build-tools-wordpress",
3
- "version": "2.10.7",
3
+ "version": "2.10.9",
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": {
@@ -23,6 +23,7 @@
23
23
  "iop-build-zip-archive": "./bin/zip.js",
24
24
  "iop-html-php-prettier": "./bin/format-php-prettier.js",
25
25
  "iop-format-wp-block-pattern": "./bin/format-wp-block-pattern.js",
26
+ "iop-format-wp-php": "./bin/format-wp-php.js",
26
27
  "iop-project-refresh": "./bin/refresh.js",
27
28
  "iop-vscode-svgo": "./bin/vscode-svgo.js"
28
29
  },
@@ -42,43 +43,43 @@
42
43
  "@rollup/plugin-json": "^6.1.0",
43
44
  "@rollup/plugin-node-resolve": "^16.0.3",
44
45
  "@svgr/webpack": "^8.1.0",
45
- "@wordpress/dependency-extraction-webpack-plugin": "^6.51.0",
46
+ "@wordpress/dependency-extraction-webpack-plugin": "^6.53.0",
46
47
  "ansi-html": "^0.0.9",
47
48
  "archiver": "^8.0.0",
48
- "autoprefixer": "^10.5.3",
49
+ "autoprefixer": "^10.5.4",
49
50
  "babel-loader": "^10.1.1",
50
- "caniuse-lite": "^1.0.30001805",
51
- "chalk": "^5.6.2",
51
+ "caniuse-lite": "^1.0.30001809",
52
+ "chalk": "^6.0.0",
52
53
  "chalk-cli": "^6.0.0",
53
54
  "classnames": "^2.5.1",
54
55
  "cli-truncate": "^6.1.1",
55
56
  "copy-webpack-plugin": "^14.0.0",
56
- "cosmiconfig": "^9.0.2",
57
+ "cosmiconfig": "^10.0.0",
57
58
  "css-loader": "^7.1.4",
58
- "cssnano": "^8.0.2",
59
+ "cssnano": "^8.0.6",
59
60
  "dotenv": "^17.4.2",
60
61
  "esbuild-loader": "^4.5.0",
61
- "eslint": "^10.7.0",
62
+ "eslint": "^10.8.1",
62
63
  "filesize": "^11.0.22",
63
- "fs-extra": "^11.3.6",
64
- "globby": "^16.2.1",
65
- "html-webpack-plugin": "^5.6.7",
64
+ "fs-extra": "^11.4.0",
65
+ "globby": "^16.2.3",
66
+ "html-webpack-plugin": "^5.6.8",
66
67
  "humanize-duration": "^3.34.0",
67
68
  "image-minimizer-webpack-plugin": "^5.0.0",
68
69
  "is-text-path": "^3.0.0",
69
70
  "lodash": "^4.18.1",
70
71
  "mini-css-extract-plugin": "^2.10.2",
71
- "open": "^11.0.0",
72
+ "open": "^11.0.1",
72
73
  "ora": "^9.4.1",
73
- "postcss": "^8.5.19",
74
+ "postcss": "^8.5.26",
74
75
  "postcss-loader": "^8.2.1",
75
76
  "postcss-scss": "^4.0.9",
76
- "prettier": "^3.9.5",
77
+ "prettier": "^3.9.6",
77
78
  "pretty-hrtime": "^1.0.3",
78
79
  "read-package-up": "^12.0.0",
79
80
  "replacestream": "^4.0.3",
80
81
  "rimraf": "^6.1.3",
81
- "sass-embedded": "^1.100.0",
82
+ "sass-embedded": "^1.102.0",
82
83
  "sass-loader": "^17.0.0",
83
84
  "semver": "^7.8.5",
84
85
  "sharp": "^0.35.3",
@@ -88,9 +89,9 @@
88
89
  "svgo": "^4.0.2",
89
90
  "svgo-loader": "^5.0.0",
90
91
  "version-everything": "^0.12.2",
91
- "webpack": "^5.108.4",
92
+ "webpack": "^5.109.2",
92
93
  "webpack-bundle-analyzer": "^5.3.1",
93
- "webpack-cli": "^6.0.1",
94
+ "webpack-cli": "^7.2.2",
94
95
  "webpack-dev-server": "^6.0.0",
95
96
  "webpack-manifest-plugin": "^6.0.1"
96
97
  },
@@ -98,8 +99,8 @@
98
99
  "node": ">=22.15.0"
99
100
  },
100
101
  "devDependencies": {
101
- "@vitest/coverage-v8": "^4.1.10",
102
- "vitest": "^4.1.10"
102
+ "@vitest/coverage-v8": "^4.1.11",
103
+ "vitest": "^4.1.11"
103
104
  },
104
105
  "version-everything": {
105
106
  "files": [