@ideasonpurpose/build-tools-wordpress 2.6.3 → 2.6.6

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.
@@ -15,10 +15,10 @@ jobs:
15
15
  runs-on: ubuntu-24.04
16
16
  steps:
17
17
  # https://github.com/marketplace/actions/checkout
18
- - uses: actions/checkout@v4
18
+ - uses: actions/checkout@v6
19
19
 
20
20
  # https://github.com/actions/setup-node
21
- - uses: actions/setup-node@v4
21
+ - uses: actions/setup-node@v6
22
22
  with:
23
23
  node-version: '24'
24
24
  registry-url: 'https://registry.npmjs.org'
package/CHANGELOG.md CHANGED
@@ -4,6 +4,26 @@ 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.6.5
8
+
9
+ > 5 April 2026
10
+
11
+ - fix: update setup-node action version to v6 for consistency
12
+
13
+ #### v2.6.4
14
+
15
+ > 5 April 2026
16
+
17
+ - chore: update actions versions in npm-publish workflow and bump version-everything dependency
18
+ - feat: add new formatting functions for handling list elements and normalize newlines
19
+
20
+ #### v2.6.3
21
+
22
+ > 4 April 2026
23
+
24
+ - bump deps
25
+ - feat: add formatter for WordPress block pattern PHP files and corresponding tests
26
+
7
27
  #### v2.6.2
8
28
 
9
29
  > 23 March 2026
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ideasonpurpose/build-tools-wordpress
2
2
 
3
- #### Version 2.6.3
3
+ #### Version 2.6.6
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#readme)
@@ -41,6 +41,20 @@ Webpack handles SVG files differently based on import context:
41
41
 
42
42
  Data URIs are generated as `data:image/svg+xml,<url-encoded-content>` using more efficient URL-encoding, not base64.
43
43
 
44
+ ## Experimental formatting helpers
45
+
46
+ This package includes two experimental formatting scripts:
47
+
48
+ ### `iop-html-php-prettier`
49
+
50
+ This uses [Prettier](https://prettier.io) to double-format mixed HTML and PHP files (like WordPress templates). PHP blocks are tokenized so Prettier can safely format the file as HTML, then PHP blocks are restored and the file is formatted again as PHP using [@prettier/plugin-php](https://github.com/prettier/plugin-php).
51
+ **Usage:** `npx iop-html-php-prettier path/to/file.php`
52
+
53
+ ### `iop-format-wp-block-pattern`
54
+
55
+ A specialized formatter for WordPress PHP block patterns. This makes block markup easier to read, expands JSON settings, and adjusts whitespace to work around Block Editor quirks.
56
+ **Usage:** `npx iop-format-wp-block-pattern path/to/pattern.php`
57
+
44
58
  ## Local Development
45
59
 
46
60
  Because this project makes use of bin scripts, conventional `npm link` workflows won't work correctly. To work on this code in a development project, change the project's package.json to install from a local file path, probably something like this:
@@ -84,6 +84,7 @@ export function normalizeCommentTagSpacing(content) {
84
84
  "wp:heading",
85
85
  "wp:image",
86
86
  "wp:list",
87
+ "wp:list-item",
87
88
  "wp:media-text",
88
89
  "wp:paragraph",
89
90
  "wp:pattern",
@@ -111,6 +112,60 @@ export function normalizeCommentTagSpacing(content) {
111
112
  return newContent;
112
113
  }
113
114
 
115
+ /**
116
+ * Remove extra blank lines (more than 2) and trim leading/trailing whitespace
117
+ * @param {string} content
118
+ * @returns {string}
119
+ */
120
+ export function normalizeNewlines(content) {
121
+ return (
122
+ content
123
+ .replace(/^[ \t]+$/gm, "")
124
+ .replace(/\n{3,}/g, "\n\n")
125
+ .trim() + "\n"
126
+ );
127
+ }
128
+
129
+ /**
130
+ * Special handling of space inside <li> elements
131
+ * @param {string} content
132
+ * @returns {string}
133
+ */
134
+ export function trimInsideListElements(content) {
135
+ return content
136
+ .replace(/\s*<!-- wp:list /g, "<!-- wp:list ")
137
+ .replace(/>\s*<!-- wp:list /g, ">\n\n<!-- wp:list ")
138
+ .replace(/>\s*<!-- wp:list-item /g, ">\n\n<!-- wp:list-item ")
139
+ .replace(/<!-- \/wp:list-item -->\s*</g, "<!-- \/wp:list-item -->\n\n<")
140
+ .replace(/<li>\s*/g, "<li>")
141
+ .replace(/\s*<\/li>/g, "</li>");
142
+ }
143
+
144
+ /**
145
+ * Special whitespace handling inside <h1..h6> elements
146
+ * @param {string} content
147
+ * @returns {string}
148
+ */
149
+ export function trimInsideHeadings(content) {
150
+ return content
151
+ .replace(/(<h[1-6][^>]*>)\s*/g, "$1")
152
+ .replace(/\s*(<\/h[1-6]>)/g, "$1");
153
+ }
154
+
155
+ /**
156
+ * @param {string} content
157
+ * @returns {Promise<string>}
158
+ */
159
+ export function formatWithPrettier(content) {
160
+ return prettier.format(content, {
161
+ parser: "html",
162
+ tabWidth: 2,
163
+ useTabs: false,
164
+ printWidth: 80,
165
+ htmlWhitespaceSensitivity: "css",
166
+ });
167
+ }
168
+
114
169
  /**
115
170
  * @param {String} filepath
116
171
  */
@@ -119,20 +174,21 @@ async function formatWPBlockPattern(filepath) {
119
174
  const startTime = process.hrtime.bigint();
120
175
  const rawFile = await readFile(filepath, "utf8");
121
176
 
122
- const formattedHTML = await prettier.format(rawFile, {
123
- parser: "html",
124
- tabWidth: 0,
125
- useTabs: false,
126
- printWidth: 80,
127
- htmlWhitespaceSensitivity: "css",
128
- });
129
-
130
- const cleanedWhiteSpace = normalizeCommentTagSpacing(formattedHTML);
131
- const formattedCommentsJSON = formatAllWpComments(cleanedWhiteSpace);
132
- const finalFormatted =
133
- formattedCommentsJSON.replace(/\n{3,}/g, "\n\n").trim() + "\n";
177
+ const formatters = [
178
+ formatWithPrettier,
179
+ normalizeCommentTagSpacing,
180
+ formatAllWpComments,
181
+ trimInsideListElements,
182
+ trimInsideHeadings,
183
+ normalizeNewlines,
184
+ ];
185
+
186
+ const outputHtml = await formatters.reduce(
187
+ async (acc, fn) => fn(await acc),
188
+ Promise.resolve(rawFile),
189
+ );
134
190
 
135
- await writeFile(filepath, finalFormatted, "utf8");
191
+ await writeFile(filepath, outputHtml, "utf8");
136
192
  const endTime = process.hrtime.bigint();
137
193
  const duration = Number(endTime - startTime);
138
194
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ideasonpurpose/build-tools-wordpress",
3
- "version": "2.6.3",
3
+ "version": "2.6.6",
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": {
@@ -41,13 +41,13 @@
41
41
  "@rollup/plugin-json": "^6.1.0",
42
42
  "@rollup/plugin-node-resolve": "^16.0.3",
43
43
  "@svgr/webpack": "^8.1.0",
44
- "@wordpress/dependency-extraction-webpack-plugin": "^6.43.0",
44
+ "@wordpress/dependency-extraction-webpack-plugin": "^6.44.0",
45
45
  "ansi-html": "^0.0.9",
46
46
  "archiver": "^7.0.1",
47
47
  "auto-changelog": "^2.5.0",
48
- "autoprefixer": "^10.4.27",
48
+ "autoprefixer": "^10.5.0",
49
49
  "babel-loader": "^10.1.1",
50
- "caniuse-lite": "^1.0.30001785",
50
+ "caniuse-lite": "^1.0.30001791",
51
51
  "chalk": "^5.6.2",
52
52
  "chalk-cli": "^6.0.0",
53
53
  "classnames": "^2.5.1",
@@ -56,25 +56,25 @@
56
56
  "cosmiconfig": "^9.0.1",
57
57
  "cross-env": "^10.1.0",
58
58
  "css-loader": "^7.1.4",
59
- "cssnano": "^7.1.4",
60
- "dotenv": "^17.4.0",
59
+ "cssnano": "^7.1.7",
60
+ "dotenv": "^17.4.2",
61
61
  "esbuild-loader": "^4.4.3",
62
- "eslint": "^10.2.0",
63
- "filesize": "^11.0.15",
62
+ "eslint": "^10.2.1",
63
+ "filesize": "^11.0.17",
64
64
  "fs-extra": "^11.3.4",
65
65
  "globby": "^16.2.0",
66
- "html-webpack-plugin": "^5.6.6",
66
+ "html-webpack-plugin": "^5.6.7",
67
67
  "http-proxy": "^1.18.1",
68
68
  "humanize-duration": "^3.33.2",
69
69
  "image-minimizer-webpack-plugin": "^5.0.0",
70
70
  "is-text-path": "^3.0.0",
71
71
  "lodash": "^4.18.1",
72
72
  "mini-css-extract-plugin": "^2.10.2",
73
- "ora": "^9.3.0",
74
- "postcss": "^8.5.8",
73
+ "ora": "^9.4.0",
74
+ "postcss": "^8.5.12",
75
75
  "postcss-loader": "^8.2.1",
76
76
  "postcss-scss": "^4.0.9",
77
- "prettier": "^3.8.1",
77
+ "prettier": "^3.8.3",
78
78
  "pretty-hrtime": "^1.0.3",
79
79
  "read-package-up": "^12.0.0",
80
80
  "replacestream": "^4.0.3",
@@ -88,10 +88,10 @@
88
88
  "style-loader": "^4.0.0",
89
89
  "svgo": "^4.0.1",
90
90
  "svgo-loader": "^5.0.0",
91
- "version-everything": "^0.11.4",
92
- "webpack": "^5.105.4",
91
+ "version-everything": "^0.12.2",
92
+ "webpack": "^5.106.2",
93
93
  "webpack-bundle-analyzer": "^5.3.0",
94
- "webpack-dev-middleware": "^8.0.2",
94
+ "webpack-dev-middleware": "^8.0.3",
95
95
  "webpack-dev-server": "^5.2.3",
96
96
  "webpack-manifest-plugin": "^6.0.1"
97
97
  },
@@ -99,8 +99,8 @@
99
99
  "webpack-cli": "^6.0.1"
100
100
  },
101
101
  "devDependencies": {
102
- "@vitest/coverage-v8": "^4.1.2",
103
- "vitest": "^4.1.2"
102
+ "@vitest/coverage-v8": "^4.1.5",
103
+ "vitest": "^4.1.5"
104
104
  },
105
105
  "version-everything": {
106
106
  "files": [
@@ -0,0 +1,25 @@
1
+ <!-- wp:list -->
2
+ <ul class="wp-block-list"><!-- wp:list-item -->
3
+ <li> UL Item 1 </li>
4
+ <!-- /wp:list-item -->
5
+
6
+ <!-- wp:list-item -->
7
+ <li>UL Item 2<!-- wp:list -->
8
+ <ul class="wp-block-list"><!-- wp:list-item -->
9
+ <li> UL Second level item 3<!-- wp:list -->
10
+ <ul class="wp-block-list">
11
+
12
+ <!-- wp:list-item -->
13
+ <li>
14
+ UL Third level item 4
15
+ </li>
16
+ <!-- /wp:list-item --></ul>
17
+ <!-- /wp:list --></li>
18
+ <!-- /wp:list-item --></ul>
19
+ <!-- /wp:list --></li>
20
+ <!-- /wp:list-item -->
21
+
22
+ <!-- wp:list-item -->
23
+ <li>UL Item 5</li>
24
+ <!-- /wp:list-item --></ul>
25
+ <!-- /wp:list -->
@@ -0,0 +1,33 @@
1
+ <!-- wp:list -->
2
+ <ul class="wp-block-list">
3
+
4
+ <!-- wp:list-item -->
5
+ <li>UL Item 1</li>
6
+ <!-- /wp:list-item -->
7
+
8
+ <!-- wp:list-item -->
9
+ <li>UL Item 2<!-- wp:list -->
10
+ <ul class="wp-block-list">
11
+
12
+ <!-- wp:list-item -->
13
+ <li>UL Second level item 3<!-- wp:list -->
14
+ <ul class="wp-block-list">
15
+
16
+ <!-- wp:list-item -->
17
+ <li>UL Third level item 4</li>
18
+ <!-- /wp:list-item -->
19
+
20
+ </ul>
21
+ <!-- /wp:list --></li>
22
+ <!-- /wp:list-item -->
23
+
24
+ </ul>
25
+ <!-- /wp:list --></li>
26
+ <!-- /wp:list-item -->
27
+
28
+ <!-- wp:list-item -->
29
+ <li>UL Item 5</li>
30
+ <!-- /wp:list-item -->
31
+
32
+ </ul>
33
+ <!-- /wp:list -->
@@ -8,6 +8,7 @@ import {
8
8
  formatWpCommentJson,
9
9
  formatAllWpComments,
10
10
  normalizeCommentTagSpacing,
11
+ trimInsideListElements,
11
12
  } from "../bin/format-wp-block-pattern.js";
12
13
 
13
14
  describe("Format JSON in WP Block comments", () => {
@@ -36,16 +37,20 @@ describe("Format JSON in WP Block comments", () => {
36
37
  });
37
38
 
38
39
  test("Return short JSON for two-key wp:* comments", async () => {
39
- const input = '<!-- wp:group { "align": "full", "className": "group-name"} -->';
40
- const expected = '<!-- wp:group {"align":"full","className":"group-name"} -->';
40
+ const input =
41
+ '<!-- wp:group { "align": "full", "className": "group-name"} -->';
42
+ const expected =
43
+ '<!-- wp:group {"align":"full","className":"group-name"} -->';
41
44
 
42
45
  const actual = formatWpCommentJson(input);
43
46
  expect(actual).toBe(expected);
44
47
  });
45
48
 
46
49
  test("Prettyprint three-key wp:* comments", async () => {
47
- const input = '<!-- wp:group { "align": "full","isLink":true, "className": "group-name"} -->';
48
- const expected = '<!-- wp:group {\n "align": "full",\n "isLink": true,\n "className": "group-name"\n} -->';
50
+ const input =
51
+ '<!-- wp:group { "align": "full","isLink":true, "className": "group-name"} -->';
52
+ const expected =
53
+ '<!-- wp:group {\n "align": "full",\n "isLink": true,\n "className": "group-name"\n} -->';
49
54
 
50
55
  const actual = formatWpCommentJson(input);
51
56
  expect(actual).toBe(expected);
@@ -84,7 +89,6 @@ describe("Format WP Block Patterns", () => {
84
89
  });
85
90
  });
86
91
 
87
-
88
92
  describe("Normalize whitespace", () => {
89
93
  test("Fix Comment tag spacing", async () => {
90
94
  const input = (
@@ -96,7 +100,21 @@ describe("Normalize whitespace", () => {
96
100
  const actual = normalizeCommentTagSpacing(input);
97
101
  expect(actual).toMatch(/<\/div>\n<!-- \/wp:group -->/);
98
102
  });
99
- });
100
103
 
104
+ test("List handling", async () => {
105
+ const input = (
106
+ await readFile("./test/fixtures/format-wp-block-pattern/nested-list.php")
107
+ ).toString();
108
+
109
+ const expected = (
110
+ await readFile("./test/fixtures/format-wp-block-pattern/nested-list__formatted.php")
111
+ ).toString();
112
+
113
+ const actual = trimInsideListElements(input);
114
+ expect(actual).toMatch(/<li>UL/);
115
+
116
+ expect(actual).toBe(expected);
117
+ });
118
+ });
101
119
 
102
- // {"align":"full","className":"group-name"}
120
+ // {"align":"full","className":"group-name"}