@postalsys/email-text-tools 2.1.16 → 2.3.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.
@@ -6,32 +6,32 @@ on:
6
6
  permissions:
7
7
  contents: write
8
8
  pull-requests: write
9
+ issues: write
9
10
  id-token: write
10
11
 
11
12
  name: release
12
13
  jobs:
13
14
  release-please:
14
15
  runs-on: ubuntu-latest
16
+ outputs:
17
+ release_created: ${{ steps.release.outputs.release_created }}
15
18
  steps:
16
- - uses: google-github-actions/release-please-action@v3
19
+ - uses: googleapis/release-please-action@v4
17
20
  id: release
21
+
22
+ publish:
23
+ needs: release-please
24
+ if: ${{ needs.release-please.outputs.release_created }}
25
+ runs-on: ubuntu-latest
26
+ environment: npm-publish
27
+ permissions:
28
+ contents: read
29
+ id-token: write
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+ - uses: actions/setup-node@v4
18
33
  with:
19
- release-type: node
20
- package-name: ${{vars.NPM_MODULE_NAME}}
21
- pull-request-title-pattern: 'chore${scope}: release ${version} [skip-ci]'
22
- # The logic below handles the npm publication:
23
- - uses: actions/checkout@v3
24
- # these if statements ensure that a publication only occurs when
25
- # a new release is created:
26
- if: ${{ steps.release.outputs.release_created }}
27
- - uses: actions/setup-node@v3
28
- with:
29
- node-version: 20
34
+ node-version: 24
30
35
  registry-url: 'https://registry.npmjs.org'
31
- if: ${{ steps.release.outputs.release_created }}
32
36
  - run: npm ci
33
- if: ${{ steps.release.outputs.release_created }}
34
37
  - run: npm publish --provenance --access public
35
- env:
36
- NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
37
- if: ${{ steps.release.outputs.release_created }}
package/.ncurc.js CHANGED
@@ -2,7 +2,6 @@ module.exports = {
2
2
  upgrade: true,
3
3
  reject: [
4
4
  // Block package upgrades that moved to ESM
5
- 'nanoid',
6
- 'eslint-config-prettier'
5
+ 'nanoid'
7
6
  ]
8
7
  };
@@ -0,0 +1,14 @@
1
+ # Auto-generated files
2
+ CHANGELOG.md
3
+
4
+ # Dependencies
5
+ node_modules/
6
+ package-lock.json
7
+
8
+ # Build output
9
+ dist/
10
+ build/
11
+ coverage/
12
+
13
+ # Logs
14
+ *.log
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "2.3.3"
3
+ }
package/CHANGELOG.md CHANGED
@@ -1,108 +1,158 @@
1
1
  # Changelog
2
2
 
3
- ## [2.1.16](https://github.com/postalsys/email-text-tools/compare/v2.1.15...v2.1.16) (2025-06-29)
3
+ ## [2.3.3](https://github.com/postalsys/email-text-tools/compare/email-text-tools-v2.3.2...email-text-tools-v2.3.3) (2025-10-23)
4
4
 
5
5
 
6
6
  ### Bug Fixes
7
7
 
8
- * removed unneeded console log lines ([3a10214](https://github.com/postalsys/email-text-tools/commit/3a1021483029a1c99df122241c4e0f6062b91059))
8
+ * remove registry-url to enable OIDC authentication for trusted publishing ([319e61e](https://github.com/postalsys/email-text-tools/commit/319e61ed7c83af3db4f0a58f4b5b85c296f6f6a6))
9
+ * upgrade Node.js to version 24 for OIDC trusted publishing support ([fd41ca2](https://github.com/postalsys/email-text-tools/commit/fd41ca22a959c06eb2df4e8b957a0da86f42d9da))
9
10
 
10
- ## [2.1.15](https://github.com/postalsys/email-text-tools/compare/v2.1.14...v2.1.15) (2025-05-20)
11
+ ## [2.3.2](https://github.com/postalsys/email-text-tools/compare/email-text-tools-v2.3.1...email-text-tools-v2.3.2) (2025-10-23)
11
12
 
12
13
 
13
14
  ### Bug Fixes
14
15
 
15
- * Bumped deps ([519eb91](https://github.com/postalsys/email-text-tools/commit/519eb913a2aa91afe2eb1c782186f4f043ce1c55))
16
+ * separate publish job with npm-publish environment for trusted publishing ([1ea55bd](https://github.com/postalsys/email-text-tools/commit/1ea55bdcfa0726f48d927fb970cf900a4cd4943f))
16
17
 
17
- ## [2.1.14](https://github.com/postalsys/email-text-tools/compare/v2.1.13...v2.1.14) (2025-02-22)
18
+ ## [2.3.1](https://github.com/postalsys/email-text-tools/compare/email-text-tools-v2.3.0...email-text-tools-v2.3.1) (2025-10-23)
18
19
 
19
20
 
20
21
  ### Bug Fixes
21
22
 
22
- * Bumped deps ([00af333](https://github.com/postalsys/email-text-tools/commit/00af333ece8b1e6d14091fda1aea7662f314c721))
23
+ * trigger release to test npm publishing configuration ([88e7110](https://github.com/postalsys/email-text-tools/commit/88e711007a73a88e0f40b5bfb278826821c1fc6a))
23
24
 
24
- ## [2.1.13](https://github.com/postalsys/email-text-tools/compare/v2.1.12...v2.1.13) (2025-01-26)
25
+ ## [2.3.0](https://github.com/postalsys/email-text-tools/compare/email-text-tools-v2.2.0...email-text-tools-v2.3.0) (2025-10-23)
26
+
27
+
28
+ ### Features
29
+
30
+ * **mime-html:** add timeout protection for CSS processing with juice ([9bd3542](https://github.com/postalsys/email-text-tools/commit/9bd35426642c00c20fa1a8ce9c898f7ab7fc7e43))
25
31
 
26
32
 
27
33
  ### Bug Fixes
28
34
 
35
+ * bumped deps ([45f4533](https://github.com/postalsys/email-text-tools/commit/45f453390e00a8b5dea00c0ab3a7b4a742e9b3ce))
36
+ * Bumped deps ([519eb91](https://github.com/postalsys/email-text-tools/commit/519eb913a2aa91afe2eb1c782186f4f043ce1c55))
37
+ * Bumped deps ([00af333](https://github.com/postalsys/email-text-tools/commit/00af333ece8b1e6d14091fda1aea7662f314c721))
38
+ * Bumped deps ([da979c9](https://github.com/postalsys/email-text-tools/commit/da979c9feef5c8fd4e08b9967cbffcc058a70677))
39
+ * **deploy:** Set up automatic deployment ([21e55be](https://github.com/postalsys/email-text-tools/commit/21e55be18bb2ac1b991ee6000928c429a5b09ddd))
40
+ * **deploy:** Set up automatic deployment ([c816aaf](https://github.com/postalsys/email-text-tools/commit/c816aafa0457318cfd84497dfcd4e5628503c5b4))
29
41
  * **deps:** Bumped deps ([3b71891](https://github.com/postalsys/email-text-tools/commit/3b71891b2c6bcb5d87fb9f583a2aec221bcb142f))
42
+ * **deps:** Bumped deps ([498e56a](https://github.com/postalsys/email-text-tools/commit/498e56a011321f2f437c461008724ca07233eb41))
43
+ * **deps:** Bumped deps ([59e44d8](https://github.com/postalsys/email-text-tools/commit/59e44d8cb0877e407becac7ef6744a4dfcdba083))
44
+ * **deps:** Bumped deps ([4f8a120](https://github.com/postalsys/email-text-tools/commit/4f8a1208b2841d343baf610c1391788b60b4297c))
45
+ * **deps:** Bumped deps ([a6711a1](https://github.com/postalsys/email-text-tools/commit/a6711a1938d8e2e75f5afd83b5a8c443be0adb9c))
46
+ * **deps:** Bumped deps ([15233fa](https://github.com/postalsys/email-text-tools/commit/15233fa7850f3227bfbc4f06500f0f267e651913))
47
+ * **deps:** Bumped deps ([4815314](https://github.com/postalsys/email-text-tools/commit/4815314f9d36da2b2163d6990acc8f68fc1bc356))
48
+ * **deps:** Bumped deps (juice) ([69eaee3](https://github.com/postalsys/email-text-tools/commit/69eaee36cceadbbf5ebf23caaf24385c38859a03))
49
+ * **deps:** fixed deps ([ccf26e2](https://github.com/postalsys/email-text-tools/commit/ccf26e2f0f8047482b9cc7e71cd0a3e61b286ddc))
50
+ * **deps:** removed js-beautify ([a73ccc9](https://github.com/postalsys/email-text-tools/commit/a73ccc97a4acf9bfa7e439939c41869c2554b073))
51
+ * **mime-html:** ensure async version pre-filters problematic CSS selectors ([5166f71](https://github.com/postalsys/email-text-tools/commit/5166f714b8532c62aa33c76b2b4e2ac3c8642ca6))
52
+ * removed unneeded console log lines ([3a10214](https://github.com/postalsys/email-text-tools/commit/3a1021483029a1c99df122241c4e0f6062b91059))
53
+ * rename release-please config file to remove dot prefix ([0bb0343](https://github.com/postalsys/email-text-tools/commit/0bb0343f7c4d35f62b66b159604ba0f19665a177))
54
+ * upgrade tooling and configure release-please v4 ([4620dd7](https://github.com/postalsys/email-text-tools/commit/4620dd7d67c70486789af35abb1732ee151545c0))
55
+ * **worker-pool:** properly return workers to free list after task completion ([2d6cd2c](https://github.com/postalsys/email-text-tools/commit/2d6cd2c451941932d44d2ce025a5ba867ec66fec))
30
56
 
31
- ## [2.1.12](https://github.com/postalsys/email-text-tools/compare/v2.1.11...v2.1.12) (2024-12-03)
57
+ ## [2.2.0](https://github.com/postalsys/email-text-tools/compare/v2.1.16...v2.2.0) (2025-09-29)
32
58
 
59
+ ### Features
60
+
61
+ - **mime-html:** add timeout protection for CSS processing with juice ([9bd3542](https://github.com/postalsys/email-text-tools/commit/9bd35426642c00c20fa1a8ce9c898f7ab7fc7e43))
33
62
 
34
63
  ### Bug Fixes
35
64
 
36
- * **deps:** Bumped deps ([498e56a](https://github.com/postalsys/email-text-tools/commit/498e56a011321f2f437c461008724ca07233eb41))
65
+ - **mime-html:** ensure async version pre-filters problematic CSS selectors ([5166f71](https://github.com/postalsys/email-text-tools/commit/5166f714b8532c62aa33c76b2b4e2ac3c8642ca6))
66
+ - **worker-pool:** properly return workers to free list after task completion ([2d6cd2c](https://github.com/postalsys/email-text-tools/commit/2d6cd2c451941932d44d2ce025a5ba867ec66fec))
37
67
 
38
- ## [2.1.11](https://github.com/postalsys/email-text-tools/compare/v2.1.10...v2.1.11) (2024-09-08)
68
+ ## [2.1.16](https://github.com/postalsys/email-text-tools/compare/v2.1.15...v2.1.16) (2025-06-29)
39
69
 
70
+ ### Bug Fixes
71
+
72
+ - removed unneeded console log lines ([3a10214](https://github.com/postalsys/email-text-tools/commit/3a1021483029a1c99df122241c4e0f6062b91059))
73
+
74
+ ## [2.1.15](https://github.com/postalsys/email-text-tools/compare/v2.1.14...v2.1.15) (2025-05-20)
40
75
 
41
76
  ### Bug Fixes
42
77
 
43
- * Bumped deps ([da979c9](https://github.com/postalsys/email-text-tools/commit/da979c9feef5c8fd4e08b9967cbffcc058a70677))
78
+ - Bumped deps ([519eb91](https://github.com/postalsys/email-text-tools/commit/519eb913a2aa91afe2eb1c782186f4f043ce1c55))
44
79
 
45
- ## [2.1.10](https://github.com/postalsys/email-text-tools/compare/v2.1.9...v2.1.10) (2024-08-22)
80
+ ## [2.1.14](https://github.com/postalsys/email-text-tools/compare/v2.1.13...v2.1.14) (2025-02-22)
46
81
 
82
+ ### Bug Fixes
83
+
84
+ - Bumped deps ([00af333](https://github.com/postalsys/email-text-tools/commit/00af333ece8b1e6d14091fda1aea7662f314c721))
85
+
86
+ ## [2.1.13](https://github.com/postalsys/email-text-tools/compare/v2.1.12...v2.1.13) (2025-01-26)
47
87
 
48
88
  ### Bug Fixes
49
89
 
50
- * **deps:** Bumped deps (juice) ([69eaee3](https://github.com/postalsys/email-text-tools/commit/69eaee36cceadbbf5ebf23caaf24385c38859a03))
90
+ - **deps:** Bumped deps ([3b71891](https://github.com/postalsys/email-text-tools/commit/3b71891b2c6bcb5d87fb9f583a2aec221bcb142f))
51
91
 
52
- ## [2.1.9](https://github.com/postalsys/email-text-tools/compare/v2.1.8...v2.1.9) (2024-07-03)
92
+ ## [2.1.12](https://github.com/postalsys/email-text-tools/compare/v2.1.11...v2.1.12) (2024-12-03)
53
93
 
94
+ ### Bug Fixes
95
+
96
+ - **deps:** Bumped deps ([498e56a](https://github.com/postalsys/email-text-tools/commit/498e56a011321f2f437c461008724ca07233eb41))
97
+
98
+ ## [2.1.11](https://github.com/postalsys/email-text-tools/compare/v2.1.10...v2.1.11) (2024-09-08)
54
99
 
55
100
  ### Bug Fixes
56
101
 
57
- * bumped deps ([45f4533](https://github.com/postalsys/email-text-tools/commit/45f453390e00a8b5dea00c0ab3a7b4a742e9b3ce))
102
+ - Bumped deps ([da979c9](https://github.com/postalsys/email-text-tools/commit/da979c9feef5c8fd4e08b9967cbffcc058a70677))
58
103
 
59
- ## [2.1.8](https://github.com/postalsys/email-text-tools/compare/v2.1.7...v2.1.8) (2024-04-12)
104
+ ## [2.1.10](https://github.com/postalsys/email-text-tools/compare/v2.1.9...v2.1.10) (2024-08-22)
60
105
 
106
+ ### Bug Fixes
107
+
108
+ - **deps:** Bumped deps (juice) ([69eaee3](https://github.com/postalsys/email-text-tools/commit/69eaee36cceadbbf5ebf23caaf24385c38859a03))
109
+
110
+ ## [2.1.9](https://github.com/postalsys/email-text-tools/compare/v2.1.8...v2.1.9) (2024-07-03)
61
111
 
62
112
  ### Bug Fixes
63
113
 
64
- * **deps:** Bumped deps ([59e44d8](https://github.com/postalsys/email-text-tools/commit/59e44d8cb0877e407becac7ef6744a4dfcdba083))
114
+ - bumped deps ([45f4533](https://github.com/postalsys/email-text-tools/commit/45f453390e00a8b5dea00c0ab3a7b4a742e9b3ce))
65
115
 
66
- ## [2.1.7](https://github.com/postalsys/email-text-tools/compare/v2.1.6...v2.1.7) (2024-02-29)
116
+ ## [2.1.8](https://github.com/postalsys/email-text-tools/compare/v2.1.7...v2.1.8) (2024-04-12)
117
+
118
+ ### Bug Fixes
119
+
120
+ - **deps:** Bumped deps ([59e44d8](https://github.com/postalsys/email-text-tools/commit/59e44d8cb0877e407becac7ef6744a4dfcdba083))
67
121
 
122
+ ## [2.1.7](https://github.com/postalsys/email-text-tools/compare/v2.1.6...v2.1.7) (2024-02-29)
68
123
 
69
124
  ### Bug Fixes
70
125
 
71
- * **deps:** Bumped deps ([4f8a120](https://github.com/postalsys/email-text-tools/commit/4f8a1208b2841d343baf610c1391788b60b4297c))
126
+ - **deps:** Bumped deps ([4f8a120](https://github.com/postalsys/email-text-tools/commit/4f8a1208b2841d343baf610c1391788b60b4297c))
72
127
 
73
128
  ## [2.1.6](https://github.com/postalsys/email-text-tools/compare/v2.1.5...v2.1.6) (2024-02-18)
74
129
 
75
-
76
130
  ### Bug Fixes
77
131
 
78
- * **deps:** removed js-beautify ([a73ccc9](https://github.com/postalsys/email-text-tools/commit/a73ccc97a4acf9bfa7e439939c41869c2554b073))
132
+ - **deps:** removed js-beautify ([a73ccc9](https://github.com/postalsys/email-text-tools/commit/a73ccc97a4acf9bfa7e439939c41869c2554b073))
79
133
 
80
134
  ## [2.1.5](https://github.com/postalsys/email-text-tools/compare/v2.1.4...v2.1.5) (2024-02-18)
81
135
 
82
-
83
136
  ### Bug Fixes
84
137
 
85
- * **deps:** fixed deps ([ccf26e2](https://github.com/postalsys/email-text-tools/commit/ccf26e2f0f8047482b9cc7e71cd0a3e61b286ddc))
138
+ - **deps:** fixed deps ([ccf26e2](https://github.com/postalsys/email-text-tools/commit/ccf26e2f0f8047482b9cc7e71cd0a3e61b286ddc))
86
139
 
87
140
  ## [2.1.4](https://github.com/postalsys/email-text-tools/compare/v2.1.3...v2.1.4) (2024-02-18)
88
141
 
89
-
90
142
  ### Bug Fixes
91
143
 
92
- * **deps:** Bumped deps ([a6711a1](https://github.com/postalsys/email-text-tools/commit/a6711a1938d8e2e75f5afd83b5a8c443be0adb9c))
93
- * **deps:** Bumped deps ([15233fa](https://github.com/postalsys/email-text-tools/commit/15233fa7850f3227bfbc4f06500f0f267e651913))
144
+ - **deps:** Bumped deps ([a6711a1](https://github.com/postalsys/email-text-tools/commit/a6711a1938d8e2e75f5afd83b5a8c443be0adb9c))
145
+ - **deps:** Bumped deps ([15233fa](https://github.com/postalsys/email-text-tools/commit/15233fa7850f3227bfbc4f06500f0f267e651913))
94
146
 
95
147
  ## [2.1.3](https://github.com/postalsys/email-text-tools/compare/v2.1.2...v2.1.3) (2023-10-31)
96
148
 
97
-
98
149
  ### Bug Fixes
99
150
 
100
- * **deps:** Bumped deps ([4815314](https://github.com/postalsys/email-text-tools/commit/4815314f9d36da2b2163d6990acc8f68fc1bc356))
151
+ - **deps:** Bumped deps ([4815314](https://github.com/postalsys/email-text-tools/commit/4815314f9d36da2b2163d6990acc8f68fc1bc356))
101
152
 
102
153
  ## [2.1.2](https://github.com/postalsys/email-text-tools/compare/v2.1.1...v2.1.2) (2023-10-20)
103
154
 
104
-
105
155
  ### Bug Fixes
106
156
 
107
- * **deploy:** Set up automatic deployment ([21e55be](https://github.com/postalsys/email-text-tools/commit/21e55be18bb2ac1b991ee6000928c429a5b09ddd))
108
- * **deploy:** Set up automatic deployment ([c816aaf](https://github.com/postalsys/email-text-tools/commit/c816aafa0457318cfd84497dfcd4e5628503c5b4))
157
+ - **deploy:** Set up automatic deployment ([21e55be](https://github.com/postalsys/email-text-tools/commit/21e55be18bb2ac1b991ee6000928c429a5b09ddd))
158
+ - **deploy:** Set up automatic deployment ([c816aaf](https://github.com/postalsys/email-text-tools/commit/c816aafa0457318cfd84497dfcd4e5628503c5b4))
@@ -0,0 +1,358 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const mimeHtml = require('../lib/mime-html');
7
+
8
+ // Test data sets
9
+ const testCases = {
10
+ simple: {
11
+ name: 'Simple HTML',
12
+ html: `
13
+ <!DOCTYPE html>
14
+ <html>
15
+ <head>
16
+ <style>
17
+ body { font-family: Arial; }
18
+ p { color: blue; }
19
+ </style>
20
+ </head>
21
+ <body>
22
+ <h1>Hello World</h1>
23
+ <p>This is a simple test email.</p>
24
+ </body>
25
+ </html>
26
+ `
27
+ },
28
+
29
+ moderate: {
30
+ name: 'Moderate HTML with inline styles',
31
+ html: `
32
+ <!DOCTYPE html>
33
+ <html>
34
+ <head>
35
+ <style>
36
+ body { font-family: Arial, sans-serif; background: #f0f0f0; }
37
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
38
+ h1 { color: #333; border-bottom: 2px solid #007bff; }
39
+ p { line-height: 1.6; color: #666; }
40
+ .button { display: inline-block; padding: 10px 20px; background: #007bff; color: white; text-decoration: none; }
41
+ .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; }
42
+ </style>
43
+ </head>
44
+ <body>
45
+ <div class="container">
46
+ <h1>Newsletter Title</h1>
47
+ <p>This is a moderately complex email template with various styles.</p>
48
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
49
+ <a href="#" class="button">Call to Action</a>
50
+ <div class="footer">
51
+ <p>Footer content here</p>
52
+ </div>
53
+ </div>
54
+ </body>
55
+ </html>
56
+ `
57
+ },
58
+
59
+ complex: {
60
+ name: 'Complex HTML with media queries',
61
+ html: `
62
+ <!DOCTYPE html>
63
+ <html>
64
+ <head>
65
+ <style>
66
+ * { margin: 0; padding: 0; box-sizing: border-box; }
67
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif; }
68
+ .wrapper { max-width: 600px; margin: 0 auto; }
69
+ .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px 20px; }
70
+ .header h1 { color: white; font-size: 32px; }
71
+ .content { padding: 40px 20px; background: white; }
72
+ .card { border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; margin-bottom: 20px; }
73
+ .card h2 { color: #333; margin-bottom: 10px; }
74
+ .grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
75
+ @media only screen and (max-width: 600px) {
76
+ .grid { grid-template-columns: 1fr; }
77
+ .header h1 { font-size: 24px; }
78
+ }
79
+ table { width: 100%; border-collapse: collapse; }
80
+ th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
81
+ .button { display: inline-block; padding: 12px 24px; background: #007bff; color: white; text-decoration: none; border-radius: 4px; }
82
+ .footer { background: #f8f9fa; padding: 30px 20px; text-align: center; color: #6c757d; }
83
+ </style>
84
+ </head>
85
+ <body>
86
+ <div class="wrapper">
87
+ <div class="header">
88
+ <h1>Complex Email Template</h1>
89
+ </div>
90
+ <div class="content">
91
+ <div class="card">
92
+ <h2>Feature One</h2>
93
+ <p>Description of the first feature with detailed information.</p>
94
+ </div>
95
+ <div class="grid">
96
+ <div class="card">
97
+ <h2>Item 1</h2>
98
+ <p>Grid item content</p>
99
+ </div>
100
+ <div class="card">
101
+ <h2>Item 2</h2>
102
+ <p>Grid item content</p>
103
+ </div>
104
+ </div>
105
+ <table>
106
+ <tr><th>Product</th><th>Price</th><th>Quantity</th></tr>
107
+ <tr><td>Item A</td><td>$10</td><td>2</td></tr>
108
+ <tr><td>Item B</td><td>$20</td><td>1</td></tr>
109
+ </table>
110
+ <a href="#" class="button">Shop Now</a>
111
+ </div>
112
+ <div class="footer">
113
+ <p>Copyright 2024. All rights reserved.</p>
114
+ </div>
115
+ </div>
116
+ </body>
117
+ </html>
118
+ `
119
+ },
120
+
121
+ problematic: {
122
+ name: 'HTML with problematic CSS (modern selectors)',
123
+ html: `
124
+ <!DOCTYPE html>
125
+ <html>
126
+ <head>
127
+ <style>
128
+ body { font-family: system-ui, sans-serif; }
129
+ /* Modern CSS that might cause issues */
130
+ .container:is(.active, .highlighted) { background: yellow; }
131
+ .item:where(.primary) { color: blue; }
132
+ .parent:has(> .child) { border: 1px solid red; }
133
+ /* Standard CSS */
134
+ h1 { color: #333; }
135
+ p { line-height: 1.6; }
136
+ .box:not(.special) { padding: 10px; }
137
+ </style>
138
+ </head>
139
+ <body>
140
+ <div class="container active">
141
+ <h1>Test with Modern CSS</h1>
142
+ <div class="parent">
143
+ <div class="child">Child element</div>
144
+ </div>
145
+ <p class="item primary">This uses modern selectors</p>
146
+ <div class="box">Regular box</div>
147
+ <div class="box special">Special box</div>
148
+ </div>
149
+ </body>
150
+ </html>
151
+ `
152
+ }
153
+ };
154
+
155
+ // Load the failing.html if it exists
156
+ try {
157
+ const failingHtml = fs.readFileSync(path.join(__dirname, '../examples/failing.html'), 'utf8');
158
+ testCases.realWorld = {
159
+ name: 'Real-world problematic HTML',
160
+ html: failingHtml
161
+ };
162
+ } catch (_err) {
163
+ // File doesn't exist, skip it
164
+ }
165
+
166
+ // Benchmark runner
167
+ class Benchmark {
168
+ constructor() {
169
+ this.results = [];
170
+ }
171
+
172
+ async runTest(name, fn, iterations = 100) {
173
+ const times = [];
174
+ const errors = [];
175
+
176
+ // Warmup
177
+ for (let i = 0; i < 5; i++) {
178
+ try {
179
+ await fn();
180
+ } catch (_err) {
181
+ // Ignore warmup errors
182
+ }
183
+ }
184
+
185
+ // Actual test
186
+ for (let i = 0; i < iterations; i++) {
187
+ const start = process.hrtime.bigint();
188
+ try {
189
+ await fn();
190
+ const end = process.hrtime.bigint();
191
+ times.push(Number(end - start) / 1000000); // Convert to milliseconds
192
+ } catch (err) {
193
+ errors.push(err.message);
194
+ }
195
+ }
196
+
197
+ if (times.length > 0) {
198
+ times.sort((a, b) => a - b);
199
+ const avg = times.reduce((a, b) => a + b, 0) / times.length;
200
+ const median = times[Math.floor(times.length / 2)];
201
+ const min = times[0];
202
+ const max = times[times.length - 1];
203
+ const p95 = times[Math.floor(times.length * 0.95)];
204
+ const p99 = times[Math.floor(times.length * 0.99)];
205
+
206
+ return {
207
+ name,
208
+ iterations,
209
+ successful: times.length,
210
+ failed: errors.length,
211
+ avg: avg.toFixed(2),
212
+ median: median.toFixed(2),
213
+ min: min.toFixed(2),
214
+ max: max.toFixed(2),
215
+ p95: p95.toFixed(2),
216
+ p99: p99.toFixed(2),
217
+ errors: errors.length > 0 ? errors[0] : null
218
+ };
219
+ } else {
220
+ return {
221
+ name,
222
+ iterations,
223
+ successful: 0,
224
+ failed: errors.length,
225
+ errors: errors[0] || 'All iterations failed'
226
+ };
227
+ }
228
+ }
229
+
230
+ formatResults(results) {
231
+ console.log('\n' + '='.repeat(80));
232
+ console.log(`Test Case: ${results.testCase}`);
233
+ console.log('='.repeat(80));
234
+
235
+ const table = [];
236
+ results.tests.forEach(test => {
237
+ if (test.successful > 0) {
238
+ table.push({
239
+ Method: test.name,
240
+ 'Success Rate': `${test.successful}/${test.iterations}`,
241
+ 'Avg (ms)': test.avg,
242
+ 'Median (ms)': test.median,
243
+ 'Min (ms)': test.min,
244
+ 'Max (ms)': test.max,
245
+ 'P95 (ms)': test.p95,
246
+ 'P99 (ms)': test.p99
247
+ });
248
+ } else {
249
+ table.push({
250
+ Method: test.name,
251
+ 'Success Rate': `${test.successful}/${test.iterations}`,
252
+ Error: test.errors
253
+ });
254
+ }
255
+ });
256
+
257
+ console.table(table);
258
+
259
+ // Calculate speedup if both succeeded
260
+ const syncTest = results.tests.find(t => t.name === 'Sync');
261
+ const asyncTest = results.tests.find(t => t.name === 'Async (with pool)');
262
+
263
+ if (syncTest && asyncTest && syncTest.successful > 0 && asyncTest.successful > 0) {
264
+ const speedup = (parseFloat(syncTest.avg) / parseFloat(asyncTest.avg)).toFixed(2);
265
+ if (speedup > 1) {
266
+ console.log(`\nAsync is ${speedup}x faster than Sync`);
267
+ } else {
268
+ console.log(`\nSync is ${(1 / speedup).toFixed(2)}x faster than Async`);
269
+ }
270
+ }
271
+ }
272
+
273
+ async runBenchmarks() {
274
+ console.log('Starting Mime HTML Benchmarks...');
275
+ console.log('================================\n');
276
+
277
+ for (const [_key, testCase] of Object.entries(testCases)) {
278
+ const results = {
279
+ testCase: testCase.name,
280
+ tests: []
281
+ };
282
+
283
+ // Test sync version
284
+ results.tests.push(
285
+ await this.runTest(
286
+ 'Sync',
287
+ () => {
288
+ return Promise.resolve(mimeHtml.sync({ html: testCase.html }));
289
+ },
290
+ 100
291
+ )
292
+ );
293
+
294
+ // Test async version with pool
295
+ results.tests.push(
296
+ await this.runTest(
297
+ 'Async (with pool)',
298
+ async () => {
299
+ return await mimeHtml.async(
300
+ { html: testCase.html },
301
+ {
302
+ useWorkerPool: true,
303
+ timeout: 5000,
304
+ minWorkers: 2,
305
+ maxWorkers: 4
306
+ }
307
+ );
308
+ },
309
+ 100
310
+ )
311
+ );
312
+
313
+ // Test async version without pool
314
+ results.tests.push(
315
+ await this.runTest(
316
+ 'Async (no pool)',
317
+ async () => {
318
+ return await mimeHtml.async(
319
+ { html: testCase.html },
320
+ {
321
+ useWorkerPool: false,
322
+ timeout: 5000
323
+ }
324
+ );
325
+ },
326
+ 100
327
+ )
328
+ );
329
+
330
+ this.formatResults(results);
331
+ }
332
+
333
+ // Show worker pool stats
334
+ const stats = mimeHtml.getWorkerPoolStats();
335
+ if (stats) {
336
+ console.log('\n' + '='.repeat(80));
337
+ console.log('Worker Pool Stats:');
338
+ console.log('='.repeat(80));
339
+ console.table([stats]);
340
+ }
341
+
342
+ // Clean up
343
+ await mimeHtml.closeWorkerPool();
344
+ }
345
+ }
346
+
347
+ // Run benchmarks
348
+ const benchmark = new Benchmark();
349
+ benchmark
350
+ .runBenchmarks()
351
+ .then(() => {
352
+ console.log('\nBenchmark complete!');
353
+ process.exit(0);
354
+ })
355
+ .catch(err => {
356
+ console.error('Benchmark failed:', err);
357
+ process.exit(1);
358
+ });