@useinsider/guido 1.0.0-beta.6ebce36 → 1.0.0-beta.6f8286c

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
@@ -43,8 +43,6 @@ export default {
43
43
  userId: '12345',
44
44
  guidoConfig: {
45
45
  translationsPath: 'window.trans.en'
46
- htmlCompilerRules: [],
47
- ignoreDefaultHtmlCompilerRules: false,
48
46
  }
49
47
  };
50
48
  }
@@ -70,16 +68,12 @@ export default {
70
68
  ```typescript
71
69
  interface GuidoConfig {
72
70
  translationsPath: string;
73
- htmlCompilerRules: CompilerRule[];
74
- ignoreDefaultHtmlCompilerRules: boolean;
75
71
  }
76
72
  ```
77
73
 
78
74
  | Property | Type | Default | Description |
79
75
  |----------|------|---------|-------------|
80
76
  | `translationsPath` | `string` | `'window.trans.en'` | JavaScript path to the translations object |
81
- | `htmlCompilerRules` | `CompilerRule[]` | `[]` | Additional compiler rules to apply to HTML content. See [HTML Compiler Rules](#-html-compiler-rules) section below |
82
- | `ignoreDefaultHtmlCompilerRules` | `boolean` | `false` | Skip default compiler rules and only use custom rules. Default rules: `src/config/compiler/htmlCompilerRules.ts` |
83
77
 
84
78
  ### TypeScript Types
85
79
 
@@ -107,185 +101,6 @@ type StripoEventType =
107
101
  | 'export:ready';
108
102
  ```
109
103
 
110
- ## 🔨 HTML Compiler Rules
111
-
112
- Guido includes a powerful HTML compiler system that allows you to transform HTML content with custom rules. You can define additional rules and optionally ignore the default rules.
113
-
114
- ### Rule Types
115
-
116
- There are 4 types of compiler rules:
117
-
118
- #### 1. Replace Rule
119
- Replace specific strings in HTML content.
120
-
121
- ```typescript
122
- {
123
- id: 'fix-encoding',
124
- description: 'Fix URL encoding issues',
125
- type: 'replace',
126
- search: '{%22', // String to find
127
- replacement: '%7B%22', // String to replace with
128
- replaceAll: true, // Replace all occurrences (default: true)
129
- priority: 10 // Execution priority (lower = earlier)
130
- }
131
- ```
132
-
133
- #### 2. Regex Rule
134
- Use regular expressions for complex pattern matching and replacement.
135
-
136
- ```typescript
137
- {
138
- id: 'remove-comments',
139
- description: 'Remove HTML comments',
140
- type: 'regex',
141
- pattern: '<!--.*?-->', // Regex pattern
142
- replacement: '', // Replacement string
143
- flags: 'g', // Regex flags (default: 'g')
144
- priority: 20
145
- }
146
- ```
147
-
148
- #### 3. Remove Rule
149
- Remove specific strings or patterns from HTML content.
150
-
151
- ```typescript
152
- {
153
- id: 'cleanup-scripts',
154
- description: 'Remove unwanted script tags',
155
- type: 'remove',
156
- targets: [ // Array of strings or RegExp objects
157
- '<script src="unwanted.js"></script>',
158
- /onclick="[^"]*"/g
159
- ],
160
- priority: 30
161
- }
162
- ```
163
-
164
- #### 4. Custom Rule
165
- Define complex transformation logic with a custom processor function.
166
-
167
- ```typescript
168
- {
169
- id: 'add-meta-tags',
170
- description: 'Add custom meta tags to head',
171
- type: 'custom',
172
- processor: (html: string): string => {
173
- // Custom transformation logic
174
- const metaTags = '<meta name="custom" content="value">';
175
- return html.replace('</head>', `${metaTags}</head>`);
176
- },
177
- priority: 40
178
- }
179
- ```
180
-
181
- ### Using HTML Compiler Rules
182
-
183
- #### Basic Usage with Custom Rules
184
-
185
- ```typescript
186
- const guidoConfig = {
187
- translationsPath: 'window.trans.en',
188
- htmlCompilerRules: [
189
- {
190
- id: 'replace-domain',
191
- description: 'Replace old domain with new one',
192
- type: 'replace',
193
- search: 'old-domain.com',
194
- replacement: 'new-domain.com',
195
- replaceAll: true,
196
- priority: 10
197
- },
198
- {
199
- id: 'remove-tracking',
200
- description: 'Remove tracking pixels',
201
- type: 'regex',
202
- pattern: '<img[^>]*tracking[^>]*>',
203
- replacement: '',
204
- flags: 'gi',
205
- priority: 20
206
- }
207
- ]
208
- };
209
- ```
210
-
211
- #### Ignoring Default Rules
212
-
213
- ```typescript
214
- const guidoConfig = {
215
- translationsPath: 'window.trans.en',
216
- ignoreDefaultHtmlCompilerRules: true, // Skip all default rules
217
- htmlCompilerRules: [
218
- // Only your custom rules will be applied
219
- {
220
- id: 'custom-transformation',
221
- type: 'replace',
222
- search: 'old-text',
223
- replacement: 'new-text',
224
- priority: 1
225
- }
226
- ]
227
- };
228
- ```
229
-
230
- ### Rule Execution Order
231
-
232
- Rules are executed in priority order (lower numbers first). Rules with the same priority are executed in array order.
233
-
234
- - **Priority 1-99**: Reserved for critical transformations
235
- - **Priority 100-999**: Standard transformations
236
- - **Priority 1000+**: Additional custom rules (automatically assigned)
237
-
238
- ### Default Rules
239
-
240
- Guido includes several default rules for common email HTML optimizations:
241
-
242
- - **URL encoding fixes**: Fixes malformed URL encoding in dynamic content
243
- - **Template tag restoration**: Restores `{{}}` template tags that got URL encoded
244
- - **HTML entity decoding**: Converts `&lt;` and `&gt;` back to `<` and `>`
245
- - **Cleanup rules**: Removes unwanted iframe and style elements
246
- - **MSO conditions**: Manages Outlook-specific conditional comments
247
- - **Domain replacement**: Updates old image domains to current ones
248
-
249
- You can view all default rules in: `src/config/compiler/htmlCompilerRules.ts`
250
-
251
- ### CompilerRule Interface
252
-
253
- ```typescript
254
- type CompilerRuleType = 'replace' | 'regex' | 'remove' | 'custom';
255
-
256
- interface BaseCompilerRule {
257
- id: string;
258
- description?: string;
259
- priority: number;
260
- }
261
-
262
- interface ReplaceRule extends BaseCompilerRule {
263
- type: 'replace';
264
- search: string;
265
- replacement: string;
266
- replaceAll?: boolean; // Default: true
267
- }
268
-
269
- interface RegexRule extends BaseCompilerRule {
270
- type: 'regex';
271
- pattern: string;
272
- replacement: string;
273
- flags?: string; // Default: 'g'
274
- }
275
-
276
- interface RemoveRule extends BaseCompilerRule {
277
- type: 'remove';
278
- targets: (string | RegExp)[]; // Array of strings or RegExp objects
279
- }
280
-
281
- interface CustomRule extends BaseCompilerRule {
282
- type: 'custom';
283
- processor: (html: string) => string;
284
- }
285
-
286
- type CompilerRule = ReplaceRule | RegexRule | RemoveRule | CustomRule;
287
- ```
288
-
289
104
  ---
290
105
 
291
106
  ## 🔧 Development
@@ -1,6 +1,3 @@
1
- import type { CompilerRule } from './html-compiler';
2
1
  export type GuidoConfig = {
3
2
  translationsPath: string;
4
- htmlCompilerRules?: CompilerRule[];
5
- ignoreDefaultHtmlCompilerRules?: boolean;
6
3
  };
@@ -2,7 +2,7 @@ import s from "./MiddleSlot.vue2.js";
2
2
  import i from "../../../_virtual/_plugin-vue2_normalizer.js";
3
3
  var n = function() {
4
4
  var e = this, o = e._self._c, t = e._self._setupProxy;
5
- return t.editorStore.isVersionHistoryOpen ? o("div", { staticClass: "d-f" }, [o(t.VersionHistory), o(t.VersionHistoryViewOptions)], 1) : o("div", { staticClass: "d-f" }, [o(t.InButtonV2, { attrs: { id: "guido__undo-button", "left-icon": "line-undo", styling: "ghost", type: "secondary", "label-text-status": !1 } }), o(t.InButtonV2, { attrs: { id: "guido__redo-button", "left-icon": "line-redo", styling: "ghost", type: "secondary", "label-text-status": !1 } }), o(t.InButtonV2, { attrs: { id: "guido__code-button", "left-icon": "line-code", styling: "ghost", "tooltip-text": "Code Editor", type: "secondary", "label-text-status": !1, "selected-status": t.editorStore.isCodeEditorOpen, "tooltip-options": t.getTooltipOptions("guido__code-button") } }), o(t.InButtonV2, { attrs: { id: "guido__preview-button", "left-icon": "line-show-on", styling: "ghost", type: "secondary", "label-text-status": !1, "tooltip-options": t.getTooltipOptions("guido__preview-button"), "tooltip-text": t.trans("newsletter.email-preview") } }), o(t.ViewOptions, { staticClass: "ml-3" })], 1);
5
+ return t.editorStore.isVersionHistoryOpen ? o("div", { staticClass: "d-f" }, [o(t.VersionHistory), o(t.VersionHistoryViewOptions)], 1) : o("div", { staticClass: "d-f" }, [o(t.InButtonV2, { attrs: { id: "guido__undo-button", "left-icon": "line-undo", styling: "ghost", type: "secondary", "label-text-status": !1 } }), o(t.InButtonV2, { attrs: { id: "guido__redo-button", "left-icon": "line-redo", styling: "ghost", type: "secondary", "label-text-status": !1 } }), o(t.InButtonV2, { attrs: { id: "guido__code-button", "data-testid": "Code Editor", "left-icon": "line-code", styling: "ghost", "tooltip-text": "Code Editor", type: "secondary", "label-text-status": !1, "selected-status": t.editorStore.isCodeEditorOpen, "tooltip-options": t.getTooltipOptions("guido__code-button") } }), o(t.InButtonV2, { attrs: { id: "guido__preview-button", "left-icon": "line-show-on", styling: "ghost", type: "secondary", "label-text-status": !1, "tooltip-options": t.getTooltipOptions("guido__preview-button"), "tooltip-text": t.trans("newsletter.email-preview") } }), o(t.ViewOptions, { staticClass: "ml-3" })], 1);
6
6
  }, l = [], r = /* @__PURE__ */ i(
7
7
  s,
8
8
  n,
@@ -1,3 +1,3 @@
1
1
  export declare const useExport: () => {
2
- exportHtml: (compile?: boolean) => Promise<void>;
2
+ exportHtml: () => Promise<void>;
3
3
  };
@@ -1,45 +1,30 @@
1
1
  import { useActionsApi as l } from "./useActionsApi.js";
2
- import { useHtmlCompiler as m } from "./useHtmlCompiler.js";
3
- import { useToaster as d } from "./useToaster.js";
4
- const h = () => {
5
- const a = (s, o, r) => {
6
- const i = new Blob([s], { type: r }), t = URL.createObjectURL(i), e = document.createElement("a");
7
- e.href = t, e.download = o, document.body.appendChild(e), e.click(), document.body.removeChild(e), URL.revokeObjectURL(t);
8
- }, c = (s) => {
9
- const o = /* @__PURE__ */ new Date(), r = String(o.getDate()).padStart(2, "0"), i = String(o.getMonth() + 1).padStart(2, "0"), t = o.getFullYear(), e = String(o.getHours()).padStart(2, "0"), n = String(o.getMinutes()).padStart(2, "0");
10
- return `${s}_${r}-${i}-${t}_${e}-${n}.html`;
2
+ import { useToaster as m } from "./useToaster.js";
3
+ const u = () => {
4
+ const a = (r, t, e) => {
5
+ const n = new Blob([r], { type: e }), s = URL.createObjectURL(n), o = document.createElement("a");
6
+ o.href = s, o.download = t, document.body.appendChild(o), o.click(), document.body.removeChild(o), URL.revokeObjectURL(s);
7
+ }, c = (r) => {
8
+ const t = /* @__PURE__ */ new Date(), e = String(t.getDate()).padStart(2, "0"), n = String(t.getMonth() + 1).padStart(2, "0"), s = t.getFullYear(), o = String(t.getHours()).padStart(2, "0"), i = String(t.getMinutes()).padStart(2, "0");
9
+ return `${r}_${e}-${n}-${s}_${o}-${i}.html`;
11
10
  };
12
- return { exportHtml: async (s = !0) => {
13
- const { getCompiledEmail: o } = l(), { showToaster: r } = d(), { compileHtml: i } = m();
11
+ return { exportHtml: async () => {
12
+ const { getCompiledEmail: r } = l(), { showToaster: t } = m();
14
13
  try {
15
- const { html: t } = await o();
16
- if (t) {
17
- let e = t;
18
- if (s) {
19
- const n = i(t);
20
- e = n.compiledHtml, console.debug("HTML Compilation Stats:", {
21
- originalSize: n.stats.originalSize,
22
- compiledSize: n.stats.compiledSize,
23
- reduction: `${n.stats.reductionPercentage.toFixed(2)}%`,
24
- appliedRules: n.appliedRules,
25
- executionTime: `${n.stats.executionTime.toFixed(2)}ms`
26
- });
27
- }
28
- a(e, c("HTML"), "text/html");
29
- } else
30
- r({
31
- type: "error",
32
- message: "No HTML content to download"
33
- });
34
- } catch (t) {
35
- const e = t instanceof Error ? t.message : String(t);
36
- r({
14
+ const { html: e } = await r();
15
+ e ? a(e, c("HTML"), "text/html") : t({
37
16
  type: "error",
38
- message: `Error compiling email: ${e}`
17
+ message: "No HTML content to download"
18
+ });
19
+ } catch (e) {
20
+ const n = e instanceof Error ? e.message : String(e);
21
+ t({
22
+ type: "error",
23
+ message: `Error compiling email: ${n}`
39
24
  });
40
25
  }
41
26
  } };
42
27
  };
43
28
  export {
44
- h as useExport
29
+ u as useExport
45
30
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "1.0.0-beta.6ebce36",
3
+ "version": "1.0.0-beta.6f8286c",
4
4
  "description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
5
5
  "main": "./dist/guido.umd.cjs",
6
6
  "module": "./dist/library.js",
@@ -10,9 +10,9 @@
10
10
  ],
11
11
  "exports": {
12
12
  ".": {
13
- "import": "./dist/library.js",
14
- "types": "./dist/components/Guido.vue.d.ts",
15
- "require": "./dist/components/Guido.vue.js"
13
+ "import": "./dist/library.js",
14
+ "types": "./dist/components/Guido.vue.d.ts",
15
+ "require": "./dist/components/Guido.vue.js"
16
16
  },
17
17
  "./style": "./dist/guido.css"
18
18
  },
@@ -21,7 +21,6 @@
21
21
  "start": "vite",
22
22
  "build": "vite build && vue-tsc --declaration --emitDeclarationOnly --project tsconfig.app.json",
23
23
  "preview": "vite preview",
24
- "test": "echo \"Error: no test specified\" && exit 1",
25
24
  "lint": "NODE_OPTIONS=--max-old-space-size=2048 eslint ./ && bun run type-check",
26
25
  "lint:fix": "NODE_OPTIONS=--max-old-space-size=2048 eslint --fix ./",
27
26
  "type-check": "vue-tsc --noEmit --project tsconfig.config.json && vue-tsc --noEmit --project tsconfig.app.json"
@@ -42,6 +41,7 @@
42
41
  "@cspell/eslint-plugin": "8.17.5",
43
42
  "@eslint/eslintrc": "3.3.0",
44
43
  "@eslint/js": "8.57.1",
44
+ "@playwright/test": "^1.54.2",
45
45
  "@stylistic/eslint-plugin": "3.1.0",
46
46
  "@stylistic/eslint-plugin-migrate": "3.1.0",
47
47
  "@types/eslint": "8.56.12",
@@ -1,4 +0,0 @@
1
- import type { CompilationResult } from '@@/Types/html-compiler';
2
- export declare const useHtmlCompiler: () => {
3
- compileHtml: (html: string) => CompilationResult;
4
- };
@@ -1,16 +0,0 @@
1
- import { defaultHtmlCompilerRules as r } from "../config/compiler/htmlCompilerRules.js";
2
- import { createHtmlCompiler as p } from "../utils/htmlCompiler.js";
3
- const a = () => {
4
- const e = typeof window < "u" ? window.GuidoConfig : void 0, l = (e == null ? void 0 : e.htmlCompilerRules) || [], t = [
5
- ...!!(e != null && e.ignoreDefaultHtmlCompilerRules) ? [] : r,
6
- ...l.map((o, m) => ({
7
- ...o,
8
- priority: o.priority + 1e3 + m
9
- // Ensure additional rules run after default rules
10
- }))
11
- ], i = p(t);
12
- return { compileHtml: (o) => i.compile(o) };
13
- };
14
- export {
15
- a as useHtmlCompiler
16
- };
@@ -1,2 +0,0 @@
1
- import type { CompilerRule } from '@@/Types/html-compiler';
2
- export declare const defaultHtmlCompilerRules: CompilerRule[];
@@ -1,145 +0,0 @@
1
- const a = [
2
- {
3
- id: "fix-url-encoding-start",
4
- description: "Replace {%22 with %7B%22 to fix URL encoding",
5
- type: "replace",
6
- search: "{%22",
7
- replacement: "%7B%22",
8
- replaceAll: !0,
9
- priority: 10
10
- },
11
- {
12
- id: "fix-url-encoding-end",
13
- description: "Replace %22} with %22%7D to fix URL encoding",
14
- type: "replace",
15
- search: "%22}",
16
- replacement: "%22%7D",
17
- replaceAll: !0,
18
- priority: 10
19
- },
20
- {
21
- id: "fix-tags-start",
22
- description: "Replace %7B%7B with {{ to fix URL encoding",
23
- type: "replace",
24
- search: "%7B%7B",
25
- replacement: "{{",
26
- replaceAll: !0,
27
- priority: 11
28
- },
29
- {
30
- id: "fix-tags-end",
31
- description: "Replace %7D%7D with }} to fix URL encoding",
32
- type: "replace",
33
- search: "%7D%7D",
34
- replacement: "}}",
35
- replaceAll: !0,
36
- priority: 12
37
- },
38
- {
39
- id: "unescape-inequality-operators-start",
40
- description: "Replace &lt; with < to fix URL encoding",
41
- type: "replace",
42
- search: "&lt;",
43
- replacement: "<",
44
- replaceAll: !0,
45
- priority: 13
46
- },
47
- {
48
- id: "unescape-inequality-operators-end",
49
- description: "Replace &gt; with > to fix URL encoding",
50
- type: "replace",
51
- search: "&gt;",
52
- replacement: ">",
53
- replaceAll: !0,
54
- priority: 14
55
- },
56
- {
57
- id: "remove-apty-iframe",
58
- description: "Cleanup Apty Iframe Code",
59
- type: "remove",
60
- targets: [
61
- '<iframe src="about:blank" id="letznav-iframe-script" allowtransparency="true" style="width:1px;height:1px"></iframe>',
62
- 'src="about:blank" id="letznav-iframe-script" allowtransparency="true" style="width:1px;height:1px"></iframe>'
63
- ],
64
- priority: 20
65
- },
66
- {
67
- id: "remove-apty-styles",
68
- description: "Removing Apty Styles",
69
- type: "regex",
70
- pattern: '<styles*data-styles="apty_styles"s* type="text/css"s*>((s|.)*?)</style>',
71
- replacement: "",
72
- flags: "g",
73
- priority: 21
74
- },
75
- {
76
- id: "remove-mso-conditions",
77
- description: "Removing MSO Conditions",
78
- type: "remove",
79
- targets: [
80
- "/<!--[ifs(mso 16)]>s*<styles*S*>s*as*{s*text-decorations*:s*nones*;*s*}s*</style>s*<![endif]-->/g",
81
- "/<!--[ifsgte mso 9]>s*<styles*S*>s*sups*{s*font-sizes*:s*100%s*!importants*;*s*}s*</style>s*<![endif]-->/g",
82
- "/<!--[ifsgte mso 9]>s*<noscript>s*<xml>s*<o:OfficeDocumentSettings>s*<o:AllowPNG>s*</o:AllowPNG>s*<o:PixelsPerInch>d+</o:PixelsPerInch>s*</o:OfficeDocumentSettings>s*</xml>s*</noscript>s*<![endif]-->/g",
83
- '/<!--[if mso]>s*<xml>s*<w:WordDocuments+xmlns:w="urn:schemas-microsoft-com:office:word">s*<w:DontUseAdvancedTypographyReadingMail></w:DontUseAdvancedTypographyReadingMail>s*</w:WordDocument>s*</xml>s*<![endif]-->/g',
84
- "/<!--[if !mso]><!--s*d*s*-->s*<!--[if !mso]><!--s*d*s*-->s*<!--<![endif]-->/g",
85
- "/<!--[ifs!mso]>s*<!-- d -->/g"
86
- ],
87
- priority: 22
88
- },
89
- {
90
- id: "add-mso-conditions",
91
- description: "Adding MSO Conditions",
92
- type: "custom",
93
- processor: (e) => {
94
- const t = [
95
- `<!--[if gte mso 9]>
96
- <style>sup {
97
- font-size: 100% !important;
98
- }</style><![endif]-->`,
99
- `<!--[if gte mso 9]>
100
- <noscript>
101
- <xml>
102
- <o:OfficeDocumentSettings>
103
- <o:AllowPNG></o:AllowPNG>
104
- <o:PixelsPerInch>96</o:PixelsPerInch>
105
- </o:OfficeDocumentSettings>
106
- </xml>
107
- </noscript><![endif]-->`,
108
- `<!--[if mso]>
109
- <xml>
110
- <w:WordDocument xmlns:w="urn:schemas-microsoft-com:office:word">
111
- <w:DontUseAdvancedTypographyReadingMail></w:DontUseAdvancedTypographyReadingMail>
112
- </w:WordDocument>
113
- </xml><![endif]-->`
114
- ], s = /<head>([\S\s]*)<\/head>/, o = new RegExp(s);
115
- if (!e.match(o))
116
- return e;
117
- let i = e;
118
- return t.forEach((r) => {
119
- i = i.replace("</head>", `${r}</head>`);
120
- }), i;
121
- },
122
- priority: 30
123
- },
124
- {
125
- id: "replace-old-image-domain",
126
- description: "Replacing old image domains",
127
- type: "replace",
128
- search: "stripo-editor-image.s3-eu-west-1.amazonaws.com",
129
- replacement: "email-static.useinsider.com",
130
- replaceAll: !0,
131
- priority: 40
132
- },
133
- {
134
- id: "replace-old-v2-image-domain",
135
- description: "Replacing old image domains",
136
- type: "replace",
137
- search: "email.static.useinsider.com",
138
- replacement: "email-static.useinsider.com",
139
- replaceAll: !0,
140
- priority: 41
141
- }
142
- ];
143
- export {
144
- a as defaultHtmlCompilerRules
145
- };
File without changes
@@ -1,12 +0,0 @@
1
- import type { CompilerRule, CompilationResult, HtmlCompiler } from '@@/Types/html-compiler';
2
- export declare class HtmlCompilerEngine implements HtmlCompiler {
3
- private rules;
4
- constructor(rules?: CompilerRule[]);
5
- compile(html: string, rules?: CompilerRule[]): CompilationResult;
6
- private applyRule;
7
- private applyReplaceRule;
8
- private applyRegexRule;
9
- private applyRemoveRule;
10
- private applyCustomRule;
11
- }
12
- export declare const createHtmlCompiler: (rules?: CompilerRule[]) => HtmlCompiler;
@@ -1,70 +0,0 @@
1
- var y = Object.defineProperty;
2
- var g = (p, e, r) => e in p ? y(p, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : p[e] = r;
3
- var u = (p, e, r) => g(p, typeof e != "symbol" ? e + "" : e, r);
4
- import { useToaster as m } from "../composables/useToaster.js";
5
- class d {
6
- constructor(e = []) {
7
- u(this, "rules");
8
- this.rules = e;
9
- }
10
- compile(e, r) {
11
- const l = performance.now(), t = e, o = e.length;
12
- let s = e;
13
- const a = [];
14
- (r || this.rules).sort((n, c) => n.priority - c.priority).forEach((n) => {
15
- const c = s.length;
16
- s = this.applyRule(s, n), s.length !== c && a.push(n.id);
17
- });
18
- const i = s.length, R = o > 0 ? (o - i) / o * 100 : 0;
19
- return {
20
- originalHtml: t,
21
- compiledHtml: s,
22
- appliedRules: a,
23
- // TODO: We can use stats for monitoring in the future
24
- stats: {
25
- originalSize: o,
26
- compiledSize: i,
27
- reductionPercentage: R,
28
- executionTime: performance.now() - l
29
- }
30
- };
31
- }
32
- applyRule(e, r) {
33
- try {
34
- switch (r.type) {
35
- case "replace":
36
- return this.applyReplaceRule(e, r);
37
- case "regex":
38
- return this.applyRegexRule(e, r);
39
- case "remove":
40
- return this.applyRemoveRule(e, r);
41
- case "custom":
42
- return this.applyCustomRule(e, r);
43
- default:
44
- return e;
45
- }
46
- } catch (l) {
47
- const { handleError: t } = m();
48
- return t(l, `Failed to apply rule ${r.id}:`), e;
49
- }
50
- }
51
- applyReplaceRule(e, r) {
52
- const { search: l, replacement: t, replaceAll: o = !0 } = r;
53
- return o ? e.replaceAll(l, t) : e.replace(l, t);
54
- }
55
- applyRegexRule(e, r) {
56
- const { pattern: l, replacement: t, flags: o = "g" } = r, s = new RegExp(l, o);
57
- return e.replace(s, t);
58
- }
59
- applyRemoveRule(e, r) {
60
- return r.targets.reduce((l, t) => t instanceof RegExp ? l.replace(t, "") : l.replaceAll(t, ""), e);
61
- }
62
- applyCustomRule(e, r) {
63
- return r.processor(e);
64
- }
65
- }
66
- const A = (p = []) => new d(p);
67
- export {
68
- d as HtmlCompilerEngine,
69
- A as createHtmlCompiler
70
- };