@ideasonpurpose/build-tools-wordpress 2.1.2 → 2.1.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 CHANGED
@@ -4,6 +4,19 @@ 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.1.3
8
+
9
+ > 16 April 2025
10
+
11
+ - Use self-closing html tags as tokens. Closes #11
12
+
13
+ #### v2.1.2
14
+
15
+ > 14 April 2025
16
+
17
+ - bump deps
18
+ - experimental html & php formatter
19
+
7
20
  #### v2.1.1
8
21
 
9
22
  > 9 April 2025
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ideasonpurpose/build-tools-wordpress
2
2
 
3
- #### Version 2.1.2
3
+ #### Version 2.1.4
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)
@@ -44,7 +44,7 @@ Running a simple watch script to re-install on changes will make things somewhat
44
44
  ```sh
45
45
  cd dev-project-working-dir
46
46
  npm chokidar-cli "../../build-tools-wordpress/**/*" -c "npm install"
47
-
47
+ ```
48
48
 
49
49
  ### Additional Notes
50
50
 
@@ -23,17 +23,69 @@ const phpOptions = prettierConfig.overrides.find(
23
23
  (o) => o.files === "*.php",
24
24
  )?.options;
25
25
 
26
- function tokenizeHTML(htmlContent) {
26
+ /**
27
+ * Replaces PHP Code Blocks with tokens, returns tokenized HTML and an object containing
28
+ * PHP Code Blocks
29
+ *
30
+ * For code blocks between tags (bounded by > & <) tokens will be self-closing HTML
31
+ * tags, similar to this: <php_14______ /> PHP Code blocks at the beginning and end of
32
+ * the file will be tokenized as self-closing if they preceed or follow an HTML tag.
33
+ *
34
+ * All other PHP Code Blocks are represented as HTML attribute-safe padded strings, up
35
+ * to 80 characters long.
36
+ *
37
+ * NOTE: Because Prettier's HTML formatter will always add a space before self-closing
38
+ * tags' closing slash, we just include the space in the token to prevent it from
39
+ * being mutilated by the HTML formatting step. Cleaner than adding a string.replace
40
+ * to unTokenizeHTML().
41
+ */
42
+ export function tokenizeHTML(htmlContent) {
27
43
  const phpCodeBlocks = {};
28
44
  let tokenCount = 0;
29
45
 
30
- // Tokens are end-padded to the length of the span, up to 80 characters
31
- const tokenizedHTML = htmlContent.replace(
32
- /<\?(?:php|=)[\s\S]*?\?>/gs,
33
- (phpCodeBlock) => {
34
- const codeLength = Math.min(phpCodeBlock.length, 80);
35
- const token = `__php_${tokenCount++}__`.padEnd(codeLength, "_");
46
+ // const pattern = /<\?(?:php|=)[\s\S]*?\?>/gs;
47
+ // const pattern =
48
+ // /(?<before>(?:[^\s]|\s|^)\s*)(?<php><\?(?:php|=).*?(?:\?>|$))(?<after>(?:\s*)[^\s]|$)/gs;
49
+ // const pattern =
50
+ // /((?:[^\s]|\s|^)\s*)(<\?(?:php|=).*?(?:\?>|$))((?:\s*)[^\s]|$)/gms;
51
+ // // const pattern = /([^\s]+)\s*(<\?(?:php|=).*?(?:\?>|$))\s*([^\s]*)/gms;
52
+ // const pattern =
53
+ // /([^\s]?\s*)?(<\?(?:php|=).*?(?:\?>|$))((?:\s*)[^\s]|$)/gms;
54
+ const pattern =
55
+ /(?<=((?:[^\s]|\s|^)\s*))(<\?(?:php|=).*?\?>)(?=((?:\s*)[^\s]|$))/gms;
56
+
57
+ let tokenizedHTML = htmlContent.replace(
58
+ pattern,
59
+ (string, before, phpCodeBlock, after, offset) => {
60
+ const start = [">", ""].includes(before.trim()) ? "<" : "_";
61
+ const end = ["<", ""].includes(after.trim()) ? " />" : "___";
62
+
63
+ // end-pad the token to the length of the span, up to 80 characters
64
+ const codeLength = Math.min(phpCodeBlock.length, 80 - end.length);
65
+ const token =
66
+ `${start}php_${tokenCount++}__`.padEnd(codeLength, "_") + end;
67
+ phpCodeBlocks[token] = phpCodeBlock;
68
+
69
+ return token;
70
+ },
71
+ );
72
+
73
+ /**
74
+ * special case followup for open-ended PHP tags at the end of the document
75
+ * TODO: Merge this back up into a single pattern
76
+ */
77
+ tokenizedHTML = tokenizedHTML.replace(
78
+ /(?<=((?:[^\s]|\s|^)\s*))(<\?(?:php|=).*$)/gms,
79
+
80
+ (string, before, phpCodeBlock, offset) => {
81
+ const start = [">", ""].includes(before.trim()) ? "<" : "_";
82
+ const end = start === "<" ? " />" : "___";
83
+
84
+ const codeLength = Math.min(phpCodeBlock.length, 80 - end.length);
85
+ const token =
86
+ `${start}php_${tokenCount++}__`.padEnd(codeLength, "_") + end;
36
87
  phpCodeBlocks[token] = phpCodeBlock;
88
+
37
89
  return token;
38
90
  },
39
91
  );
@@ -41,7 +93,7 @@ function tokenizeHTML(htmlContent) {
41
93
  return { tokenizedHTML, phpCodeBlocks };
42
94
  }
43
95
 
44
- function unTokenizeHTML(htmlContent, tokens) {
96
+ export function unTokenizeHTML(htmlContent, tokens) {
45
97
  let phpContent = htmlContent;
46
98
  for (const token in tokens) {
47
99
  phpContent = phpContent.replace(new RegExp(token, "g"), tokens[token]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ideasonpurpose/build-tools-wordpress",
3
- "version": "2.1.2",
3
+ "version": "2.1.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": {
@@ -0,0 +1,7 @@
1
+ <?php $a = 1; ?>
2
+
3
+ <div>
4
+ <a href="<?= $href ?>"> <?php echo $text; ?></a>
5
+ </div>
6
+
7
+ <?php $end = 1;
@@ -0,0 +1,20 @@
1
+
2
+
3
+
4
+ <!-- START template-parts/items/card.php -->
5
+
6
+ <a
7
+ href="<?php the_permalink(); ?>"
8
+ <?php post_class('card col-12 col-md-6'); ?>
9
+ data-ga-action="Article"
10
+ >
11
+ <?php get_template_part('template-parts/partials/card-media'); ?>
12
+ <div class="card__details">
13
+ <h4 class="card__title"><?= $cardTitle ?></h4>
14
+ <h5 class="card__desc"><?= $cardDesc ?></h5>
15
+ </div>
16
+ </a>
17
+
18
+ <!-- END template-parts/items/card.php -->
19
+
20
+
@@ -0,0 +1,71 @@
1
+ //@ts-check
2
+
3
+ import { describe, expect, test } from "vitest";
4
+
5
+ import { readFile } from "node:fs/promises";
6
+
7
+ import { tokenizeHTML } from "../bin/format-php-prettier.js";
8
+
9
+ describe("HTML-PHP Prettier", () => {
10
+ test("All tokens exist", async () => {
11
+ const input = (
12
+ await readFile("./test/fixtures/format-php-prettier/basic-html.php")
13
+ ).toString();
14
+
15
+ const { tokenizedHTML, phpCodeBlocks } = tokenizeHTML(input);
16
+
17
+ Object.keys(phpCodeBlocks).forEach((token) =>
18
+ expect(tokenizedHTML.includes(token)).toBe(true),
19
+ );
20
+ });
21
+
22
+ test("make tokens self-closing tags", async () => {
23
+ const input = (
24
+ await readFile("./test/fixtures/format-php-prettier/basic-html.php")
25
+ ).toString();
26
+
27
+ const { phpCodeBlocks: codeBlocks } = tokenizeHTML(input);
28
+
29
+ const tokens = Object.keys(codeBlocks);
30
+
31
+ expect(tokens[0]).toMatch(/^<php_\d+_* \/>$/);
32
+ expect(tokens[1]).toMatch(/^_php_\d+_*$/);
33
+ expect(tokens[2]).toMatch(/^<php_\d+_* \/>$/);
34
+ expect(tokens[3]).toMatch(/^<php_\d+_* \/>$/);
35
+ });
36
+
37
+ test("single open PHP code block #11", async () => {
38
+ const input = (
39
+ await readFile(
40
+ "./test/fixtures/format-php-prettier/single-open-php-block.php",
41
+ )
42
+ ).toString();
43
+
44
+ const { phpCodeBlocks: codeBlocks } = tokenizeHTML(input);
45
+
46
+ const tokens = Object.keys(codeBlocks);
47
+
48
+ expect(tokens).toHaveLength(1);
49
+ });
50
+
51
+
52
+ test("bare attribute in tag", async () => {
53
+ const input = (
54
+ await readFile(
55
+ "./test/fixtures/format-php-prettier/card-attribute-bug.php",
56
+ )
57
+ ).toString();
58
+
59
+ const { phpCodeBlocks: codeBlocks } = tokenizeHTML(input);
60
+
61
+ const tokens = Object.keys(codeBlocks);
62
+
63
+ expect(tokens[0]).toMatch(/^_php_\d+_*$/);
64
+ expect(tokens[1]).toMatch(/^_php_\d+_*$/);
65
+ expect(tokens[2]).toMatch(/^<php_\d+_* \/>$/);
66
+ expect(tokens[3]).toMatch(/^<php_\d+_* \/>$/);
67
+ expect(tokens[4]).toMatch(/^<php_\d+_* \/>$/);
68
+
69
+ expect(tokens).toHaveLength(5);
70
+ });
71
+ });