@ideasonpurpose/build-tools-wordpress 2.6.2 → 2.6.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.
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ 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.2
|
|
8
|
+
|
|
9
|
+
> 23 March 2026
|
|
10
|
+
|
|
11
|
+
- feat: add error handling for WebSocket proxy requests
|
|
12
|
+
|
|
7
13
|
#### v2.6.1
|
|
8
14
|
|
|
9
15
|
> 23 March 2026
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ideasonpurpose/build-tools-wordpress
|
|
2
2
|
|
|
3
|
-
#### Version 2.6.
|
|
3
|
+
#### Version 2.6.3
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@ideasonpurpose/build-tools-wordpress)
|
|
6
6
|
[](https://github.com/ideasonpurpose/build-tools-wordpress#readme)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
//@ts-check
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Work in progress formatter for WordPress block pattern PHP files.
|
|
7
|
+
*
|
|
8
|
+
* TODO: Testing, naming, modularization, VS Code extension
|
|
9
|
+
*/
|
|
10
|
+
import prettier from "prettier";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* These container blocks should always have a single blank line
|
|
14
|
+
* before their opening comment and another blank line after their
|
|
15
|
+
* closing comment.
|
|
16
|
+
* - wp:paragraph
|
|
17
|
+
* - wp:column
|
|
18
|
+
* - wp:group
|
|
19
|
+
* - wp:image
|
|
20
|
+
* - wp:heading
|
|
21
|
+
* - wp:list
|
|
22
|
+
* - wp:quote
|
|
23
|
+
* - wp:pullquote
|
|
24
|
+
* - wp:buttons
|
|
25
|
+
* - wp:columns
|
|
26
|
+
* - wp:media-text
|
|
27
|
+
* - wp:gallery
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { readFile, writeFile } from "fs/promises";
|
|
31
|
+
import { resolve, basename } from "path";
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @param {String} wpCommentTag
|
|
36
|
+
*/
|
|
37
|
+
export function formatWpCommentJson(wpCommentTag) {
|
|
38
|
+
const match = wpCommentTag.match(/<!--\s*wp:[\w-]+?\s*(\{.*?\})\s*-->/s);
|
|
39
|
+
if (!match) {
|
|
40
|
+
return wpCommentTag; // Return original if no match
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const jsonStr = match[1];
|
|
44
|
+
try {
|
|
45
|
+
const jsonObj = JSON.parse(jsonStr);
|
|
46
|
+
const indent =
|
|
47
|
+
JSON.stringify(jsonObj).length > 50 || Object.keys(jsonObj).length > 2
|
|
48
|
+
? 2
|
|
49
|
+
: 0;
|
|
50
|
+
const prettyJson = JSON.stringify(jsonObj, null, indent);
|
|
51
|
+
return wpCommentTag.replace(jsonStr, prettyJson);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
54
|
+
throw new Error(`Invalid JSON in wp comment: ${message}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {string} content
|
|
60
|
+
* @returns {string}
|
|
61
|
+
*/
|
|
62
|
+
export function formatAllWpComments(content) {
|
|
63
|
+
const htmlCommentRegex = /<!--[\s\S]*?-->/g;
|
|
64
|
+
return content.replace(
|
|
65
|
+
htmlCommentRegex,
|
|
66
|
+
/** @param {string} comment */ (comment) => {
|
|
67
|
+
return formatWpCommentJson(comment);
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @param {string} content
|
|
74
|
+
* @returns {string}
|
|
75
|
+
*/
|
|
76
|
+
export function normalizeCommentTagSpacing(content) {
|
|
77
|
+
let newContent = content;
|
|
78
|
+
const containerBlocks = [
|
|
79
|
+
"wp:buttons",
|
|
80
|
+
"wp:column",
|
|
81
|
+
"wp:columns",
|
|
82
|
+
"wp:gallery",
|
|
83
|
+
"wp:group",
|
|
84
|
+
"wp:heading",
|
|
85
|
+
"wp:image",
|
|
86
|
+
"wp:list",
|
|
87
|
+
"wp:media-text",
|
|
88
|
+
"wp:paragraph",
|
|
89
|
+
"wp:pattern",
|
|
90
|
+
"wp:pullquote",
|
|
91
|
+
"wp:quote",
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
containerBlocks.forEach((block) => {
|
|
95
|
+
const openingTagRegex = new RegExp(`(<!--\\s*${block}[^>]*-->)`, "g");
|
|
96
|
+
const closingTagRegex = new RegExp(`>\\s*(<!--\\s*/${block}\\s*-->)`, "g");
|
|
97
|
+
|
|
98
|
+
// Ensure one blank line before opening tag
|
|
99
|
+
newContent = newContent.replace(
|
|
100
|
+
openingTagRegex,
|
|
101
|
+
/** @param {string} match @param {string} p1 */ (match, p1) => `\n${p1}`,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// Ensure one blank line after closing tag
|
|
105
|
+
newContent = newContent.replace(
|
|
106
|
+
closingTagRegex,
|
|
107
|
+
/** @param {string} match @param {string} p1 */ (match, p1) =>
|
|
108
|
+
`>\n${p1}\n`,
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
return newContent;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @param {String} filepath
|
|
116
|
+
*/
|
|
117
|
+
async function formatWPBlockPattern(filepath) {
|
|
118
|
+
try {
|
|
119
|
+
const startTime = process.hrtime.bigint();
|
|
120
|
+
const rawFile = await readFile(filepath, "utf8");
|
|
121
|
+
|
|
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";
|
|
134
|
+
|
|
135
|
+
await writeFile(filepath, finalFormatted, "utf8");
|
|
136
|
+
const endTime = process.hrtime.bigint();
|
|
137
|
+
const duration = Number(endTime - startTime);
|
|
138
|
+
|
|
139
|
+
console.log(`${basename(filepath)} ${(duration / 1e6).toFixed(2)}ms`);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error("Error:", error);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (process.argv[2]) {
|
|
146
|
+
const fullPath = resolve(process.argv[2]);
|
|
147
|
+
formatWPBlockPattern(fullPath);
|
|
148
|
+
} else {
|
|
149
|
+
console.error("Error: A filepath is required.");
|
|
150
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ideasonpurpose/build-tools-wordpress",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.3",
|
|
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": {
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"iop-build-port-reporter": "./bin/port-reporter.js",
|
|
23
23
|
"iop-build-zip-archive": "./bin/zip.js",
|
|
24
24
|
"iop-project-init": "./bin/project-init.js",
|
|
25
|
-
"iop-html-php-prettier": "./bin/format-php-prettier.js"
|
|
25
|
+
"iop-html-php-prettier": "./bin/format-php-prettier.js",
|
|
26
|
+
"iop-format-wp-block-pattern": "./bin/format-wp-block-pattern.js"
|
|
26
27
|
},
|
|
27
28
|
"directories": {
|
|
28
29
|
"lib": "lib"
|
|
@@ -35,40 +36,40 @@
|
|
|
35
36
|
"dependencies": {
|
|
36
37
|
"@ideasonpurpose/prettier-config": "^1.0.1",
|
|
37
38
|
"@ideasonpurpose/stylelint-config": "^1.1.4",
|
|
38
|
-
"@prettier/plugin-php": "^0.
|
|
39
|
+
"@prettier/plugin-php": "^0.25.0",
|
|
39
40
|
"@rollup/plugin-commonjs": "^29.0.2",
|
|
40
41
|
"@rollup/plugin-json": "^6.1.0",
|
|
41
42
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
42
43
|
"@svgr/webpack": "^8.1.0",
|
|
43
|
-
"@wordpress/dependency-extraction-webpack-plugin": "^6.
|
|
44
|
+
"@wordpress/dependency-extraction-webpack-plugin": "^6.43.0",
|
|
44
45
|
"ansi-html": "^0.0.9",
|
|
45
46
|
"archiver": "^7.0.1",
|
|
46
47
|
"auto-changelog": "^2.5.0",
|
|
47
48
|
"autoprefixer": "^10.4.27",
|
|
48
49
|
"babel-loader": "^10.1.1",
|
|
49
|
-
"caniuse-lite": "^1.0.
|
|
50
|
+
"caniuse-lite": "^1.0.30001785",
|
|
50
51
|
"chalk": "^5.6.2",
|
|
51
52
|
"chalk-cli": "^6.0.0",
|
|
52
53
|
"classnames": "^2.5.1",
|
|
53
|
-
"cli-truncate": "^
|
|
54
|
+
"cli-truncate": "^6.0.0",
|
|
54
55
|
"copy-webpack-plugin": "^14.0.0",
|
|
55
56
|
"cosmiconfig": "^9.0.1",
|
|
56
57
|
"cross-env": "^10.1.0",
|
|
57
58
|
"css-loader": "^7.1.4",
|
|
58
|
-
"cssnano": "^7.1.
|
|
59
|
-
"dotenv": "^17.
|
|
60
|
-
"esbuild-loader": "^4.4.
|
|
61
|
-
"eslint": "^10.
|
|
62
|
-
"filesize": "^11.0.
|
|
59
|
+
"cssnano": "^7.1.4",
|
|
60
|
+
"dotenv": "^17.4.0",
|
|
61
|
+
"esbuild-loader": "^4.4.3",
|
|
62
|
+
"eslint": "^10.2.0",
|
|
63
|
+
"filesize": "^11.0.15",
|
|
63
64
|
"fs-extra": "^11.3.4",
|
|
64
|
-
"globby": "^16.
|
|
65
|
+
"globby": "^16.2.0",
|
|
65
66
|
"html-webpack-plugin": "^5.6.6",
|
|
66
67
|
"http-proxy": "^1.18.1",
|
|
67
68
|
"humanize-duration": "^3.33.2",
|
|
68
69
|
"image-minimizer-webpack-plugin": "^5.0.0",
|
|
69
70
|
"is-text-path": "^3.0.0",
|
|
70
|
-
"lodash": "^4.
|
|
71
|
-
"mini-css-extract-plugin": "^2.10.
|
|
71
|
+
"lodash": "^4.18.1",
|
|
72
|
+
"mini-css-extract-plugin": "^2.10.2",
|
|
72
73
|
"ora": "^9.3.0",
|
|
73
74
|
"postcss": "^8.5.8",
|
|
74
75
|
"postcss-loader": "^8.2.1",
|
|
@@ -78,7 +79,7 @@
|
|
|
78
79
|
"read-package-up": "^12.0.0",
|
|
79
80
|
"replacestream": "^4.0.3",
|
|
80
81
|
"rimraf": "^6.1.3",
|
|
81
|
-
"sass-embedded": "^1.
|
|
82
|
+
"sass-embedded": "^1.99.0",
|
|
82
83
|
"sass-loader": "^16.0.7",
|
|
83
84
|
"semver": "^7.7.4",
|
|
84
85
|
"sharp": "^0.34.5",
|
|
@@ -86,11 +87,11 @@
|
|
|
86
87
|
"string-length": "^7.0.1",
|
|
87
88
|
"style-loader": "^4.0.0",
|
|
88
89
|
"svgo": "^4.0.1",
|
|
89
|
-
"svgo-loader": "^
|
|
90
|
+
"svgo-loader": "^5.0.0",
|
|
90
91
|
"version-everything": "^0.11.4",
|
|
91
92
|
"webpack": "^5.105.4",
|
|
92
|
-
"webpack-bundle-analyzer": "^5.
|
|
93
|
-
"webpack-dev-middleware": "^8.0.
|
|
93
|
+
"webpack-bundle-analyzer": "^5.3.0",
|
|
94
|
+
"webpack-dev-middleware": "^8.0.2",
|
|
94
95
|
"webpack-dev-server": "^5.2.3",
|
|
95
96
|
"webpack-manifest-plugin": "^6.0.1"
|
|
96
97
|
},
|
|
@@ -98,8 +99,8 @@
|
|
|
98
99
|
"webpack-cli": "^6.0.1"
|
|
99
100
|
},
|
|
100
101
|
"devDependencies": {
|
|
101
|
-
"@vitest/coverage-v8": "^4.1.
|
|
102
|
-
"vitest": "^4.1.
|
|
102
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
103
|
+
"vitest": "^4.1.2"
|
|
103
104
|
},
|
|
104
105
|
"version-everything": {
|
|
105
106
|
"files": [
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
/**
|
|
3
|
+
* Title: Home Carousel & News Hero
|
|
4
|
+
* Slug: iop/home-carousel-news-hero
|
|
5
|
+
* Description: Carousel and news panel for top of home template
|
|
6
|
+
* Categories: home-page
|
|
7
|
+
* Viewport Width: 940
|
|
8
|
+
* Inserter: true
|
|
9
|
+
*/
|
|
10
|
+
?>
|
|
11
|
+
|
|
12
|
+
<!-- wp:group {"align":"full", "className":"home-carousel-hero"} -->
|
|
13
|
+
<div class="wp-block-group alignfull home-carousel-hero">
|
|
14
|
+
|
|
15
|
+
<!-- wp:pattern {"slug":"iop/carousel"} /-->
|
|
16
|
+
|
|
17
|
+
<!-- wp:group { "align": "full", "style": { "color": { "background": "#9deaaa" }, "spacing": { "blockGap": "0", "margin": { "top": "0", "bottom": "0" } } }, "layout": { "type": "constrained" }
|
|
18
|
+
} -->
|
|
19
|
+
<div class="wp-block-group alignfull has-background" style="background-color:#9deaaa;margin-top:0;margin-bottom:0">
|
|
20
|
+
|
|
21
|
+
<!-- wp:pattern {"slug":"iop/home-news-panel"} /-->
|
|
22
|
+
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<!-- /wp:group -->
|
|
26
|
+
|
|
27
|
+
</div>
|
|
28
|
+
<!-- /wp:group -->
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
formatWpCommentJson,
|
|
9
|
+
formatAllWpComments,
|
|
10
|
+
normalizeCommentTagSpacing,
|
|
11
|
+
} from "../bin/format-wp-block-pattern.js";
|
|
12
|
+
|
|
13
|
+
describe("Format JSON in WP Block comments", () => {
|
|
14
|
+
test("Pass through wp:* comments with no JSON", async () => {
|
|
15
|
+
const input = "<!-- wp:post-date /-->";
|
|
16
|
+
const expected = "<!-- wp:post-date /-->";
|
|
17
|
+
|
|
18
|
+
const actual = formatWpCommentJson(input);
|
|
19
|
+
expect(actual).toBe(expected);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("Return short JSON for simple wp:* comments", async () => {
|
|
23
|
+
const input = '<!-- wp:group { "align": "full"} -->';
|
|
24
|
+
const expected = '<!-- wp:group {"align":"full"} -->';
|
|
25
|
+
|
|
26
|
+
const actual = formatWpCommentJson(input);
|
|
27
|
+
expect(actual).toBe(expected);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("Return cleaned short JSON for simple wp:* comments", async () => {
|
|
31
|
+
const input = '<!-- wp:group {\n "align": "full"\n} -->';
|
|
32
|
+
const expected = '<!-- wp:group {"align":"full"} -->';
|
|
33
|
+
|
|
34
|
+
const actual = formatWpCommentJson(input);
|
|
35
|
+
expect(actual).toBe(expected);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
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"} -->';
|
|
41
|
+
|
|
42
|
+
const actual = formatWpCommentJson(input);
|
|
43
|
+
expect(actual).toBe(expected);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
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} -->';
|
|
49
|
+
|
|
50
|
+
const actual = formatWpCommentJson(input);
|
|
51
|
+
expect(actual).toBe(expected);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("Prettyprint long JSON in wp:* comments", async () => {
|
|
55
|
+
const input =
|
|
56
|
+
'<!-- wp:group {"className":"group-name","layout":{"type":"constrained"}} -->';
|
|
57
|
+
const expected =
|
|
58
|
+
'<!-- wp:group {\n "className": "group-name",\n "layout": {\n "type": "constrained"\n }\n} -->';
|
|
59
|
+
|
|
60
|
+
const actual = formatWpCommentJson(input);
|
|
61
|
+
expect(actual).toBe(expected);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("Throw error on malformed JSON", async () => {
|
|
65
|
+
const input = '<!-- wp:group {"just-a-key"} -->';
|
|
66
|
+
|
|
67
|
+
expect(() => formatWpCommentJson(input)).toThrow();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe("Format WP Block Patterns", () => {
|
|
72
|
+
test("Format JSON in all comments", async () => {
|
|
73
|
+
const input = (
|
|
74
|
+
await readFile(
|
|
75
|
+
"./test/fixtures/format-wp-block-pattern/basic-pattern.php",
|
|
76
|
+
)
|
|
77
|
+
).toString();
|
|
78
|
+
|
|
79
|
+
const actual = formatAllWpComments(input);
|
|
80
|
+
expect(actual).toMatch(/"layout":\s+\{\n\s+"type": "constrained"\n\s+\}/);
|
|
81
|
+
expect(actual).toMatch(/"align":"full"/);
|
|
82
|
+
expect(actual).toMatch(/\s+"align": "full",/);
|
|
83
|
+
// console.log(actual);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
describe("Normalize whitespace", () => {
|
|
89
|
+
test("Fix Comment tag spacing", async () => {
|
|
90
|
+
const input = (
|
|
91
|
+
await readFile(
|
|
92
|
+
"./test/fixtures/format-wp-block-pattern/basic-pattern.php",
|
|
93
|
+
)
|
|
94
|
+
).toString();
|
|
95
|
+
|
|
96
|
+
const actual = normalizeCommentTagSpacing(input);
|
|
97
|
+
expect(actual).toMatch(/<\/div>\n<!-- \/wp:group -->/);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
// {"align":"full","className":"group-name"}
|