@useinsider/guido 1.0.3-beta.a5608d9 → 1.0.3-beta.a61888c
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 +487 -151
- package/dist/composables/useStripo.js +31 -29
- package/dist/config/migrator/couponBlockMigrator.d.ts +1 -0
- package/dist/config/migrator/couponBlockMigrator.js +67 -0
- package/dist/config/migrator/index.js +6 -5
- package/dist/extensions/Blocks/Checkbox/block.d.ts +1 -0
- package/dist/extensions/Blocks/Checkbox/block.js +15 -24
- package/dist/extensions/Blocks/Checkbox/control.js +24 -38
- package/dist/extensions/Blocks/Checkbox/extension.js +5 -16
- package/dist/extensions/Blocks/Checkbox/iconsRegistry.d.ts +4 -0
- package/dist/extensions/Blocks/Checkbox/iconsRegistry.js +18 -0
- package/dist/extensions/Blocks/Checkbox/settingsPanel.js +12 -25
- package/dist/extensions/Blocks/Checkbox/template.js +5 -16
- package/dist/extensions/Blocks/CouponBlock/block.d.ts +12 -0
- package/dist/extensions/Blocks/CouponBlock/block.js +33 -0
- package/dist/extensions/Blocks/CouponBlock/extension.d.ts +2 -0
- package/dist/extensions/Blocks/CouponBlock/extension.js +8 -0
- package/dist/extensions/Blocks/CouponBlock/iconsRegistry.d.ts +4 -0
- package/dist/extensions/Blocks/CouponBlock/iconsRegistry.js +33 -0
- package/dist/extensions/Blocks/CouponBlock/settingsPanel.d.ts +4 -0
- package/dist/extensions/Blocks/CouponBlock/settingsPanel.js +24 -0
- package/dist/extensions/Blocks/CouponBlock/template.d.ts +3 -0
- package/dist/extensions/Blocks/CouponBlock/template.js +18 -0
- package/dist/extensions/Blocks/RadioButton/block.d.ts +1 -0
- package/dist/extensions/Blocks/RadioButton/block.js +13 -22
- package/dist/extensions/Blocks/RadioButton/control.js +32 -46
- package/dist/extensions/Blocks/RadioButton/extension.js +4 -15
- package/dist/extensions/Blocks/RadioButton/iconsRegistry.d.ts +4 -0
- package/dist/extensions/Blocks/RadioButton/iconsRegistry.js +14 -0
- package/dist/extensions/Blocks/RadioButton/settingsPanel.js +13 -26
- package/dist/extensions/Blocks/RadioButton/template.js +7 -18
- package/dist/extensions/Blocks/_Boilerplate/block.d.ts +1 -0
- package/dist/extensions/Blocks/_Boilerplate/iconsRegistry.d.ts +4 -0
- package/dist/extensions/DynamicContent/dynamic-content.js +31 -45
- package/dist/extensions/DynamicContent/extension.js +6 -18
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +647 -0
- package/package.json +2 -2
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/Extension.js +0 -75
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/ExtensionBuilder.js +0 -77
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/blocks/Block.js +0 -123
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/AiAssistantValueType.js +0 -7
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/BlockCompositionType.js +0 -7
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/BlockName.js +0 -12
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/BlockType.js +0 -7
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/BuiltInControlTypes.js +0 -119
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/ContextActionType.js +0 -7
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/EditorStatePropertyType.js +0 -7
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/PanelPosition.js +0 -7
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/Popover.js +0 -12
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/PreviewDeviceMode.js +0 -7
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/SettingsTab.js +0 -7
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/UIElementType.js +0 -7
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/constants/UIElementsAttributes.js +0 -24
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/controls/Control.js +0 -24
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/controls/SettingsPanelRegistry.js +0 -11
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/controls/SettingsPanelTab.js +0 -33
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/modifications/ModificationDescription.js +0 -22
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/ui-elements/UIElement.js +0 -40
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/ui-elements/UIElementTagRegistry.js +0 -5
package/README.md
CHANGED
|
@@ -4,309 +4,645 @@
|
|
|
4
4
|
</a>
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
# @useinsider/guido
|
|
8
9
|
|
|
9
10
|
Guido is a Vue 2 + TypeScript wrapper for the Stripo Email Editor plugin. Easily embed the professional email editor in your Vue applications with a clean, customizable interface.
|
|
10
11
|
|
|
11
|
-
## 📚 Table of Contents
|
|
12
|
-
|
|
13
|
-
- [Install](#-install)
|
|
14
|
-
- [Quick Start](#-quick-start)
|
|
15
|
-
- [Documentation](#-documentation)
|
|
16
|
-
- [Development](#-development)
|
|
17
|
-
- [Contributing](#-contributing)
|
|
18
|
-
- [License](#-license)
|
|
19
|
-
|
|
20
|
-
## 📖 Documentation
|
|
21
|
-
|
|
22
|
-
**For comprehensive documentation, visit our [Wiki](./wiki/Home.md):**
|
|
23
|
-
|
|
24
|
-
- **[Getting Started Guide](./wiki/Getting-Started.md)** - Installation, setup, and basic usage
|
|
25
|
-
- **[API Reference](./wiki/API-Reference.md)** - Complete API documentation with examples
|
|
26
|
-
- **[HTML Compiler Rules](./wiki/HTML-Compiler-Rules.md)** - Advanced HTML transformation guide
|
|
27
|
-
- **[Architecture](./wiki/Architecture.md)** - Project structure and design patterns
|
|
28
|
-
- **[Contributing Guide](./wiki/Contributing.md)** - Development workflow and coding standards
|
|
29
|
-
|
|
30
12
|
## 📦 Install
|
|
31
13
|
|
|
32
14
|
```bash
|
|
33
15
|
npm install @useinsider/guido
|
|
34
16
|
```
|
|
35
|
-
|
|
36
|
-
Or using bun:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
bun add @useinsider/guido
|
|
40
|
-
```
|
|
41
|
-
|
|
42
17
|
### Prerequisites
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// webpack.config.js or vue.config.js
|
|
53
|
-
{
|
|
18
|
+
🍍 Your project should have `pinia`
|
|
19
|
+
You need to be sure those lines added in your config file:
|
|
20
|
+
|
|
21
|
+
ℹ️ It helps to optimize your dependencies and sharing by Guido. This is why Guido pretty fast and tiny.
|
|
22
|
+
|
|
23
|
+
#### For Webpack
|
|
24
|
+
`/webpack.config.js` or `/vue.config.js`
|
|
25
|
+
```js
|
|
26
|
+
// ... Previous Configs
|
|
54
27
|
shared: {
|
|
55
28
|
vue: { singleton: true },
|
|
56
29
|
pinia: { singleton: true },
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
</details>
|
|
61
|
-
|
|
62
|
-
<details>
|
|
63
|
-
<summary>Vite Configuration</summary>
|
|
30
|
+
},
|
|
31
|
+
// ... Upcoming Configs
|
|
32
|
+
```
|
|
64
33
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
34
|
+
##### For Vite:
|
|
35
|
+
`/vite.config.js`
|
|
36
|
+
```js
|
|
37
|
+
// ... Previous Configs
|
|
68
38
|
resolve: {
|
|
69
39
|
dedupe: ['vue', 'pinia'],
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
</details>
|
|
74
|
-
|
|
40
|
+
},
|
|
41
|
+
// ... Upcoming Configs
|
|
42
|
+
```
|
|
75
43
|
---
|
|
76
|
-
## 🚀
|
|
44
|
+
## 🚀 Usage
|
|
45
|
+
|
|
46
|
+
### Basic Usage
|
|
77
47
|
|
|
78
|
-
```
|
|
48
|
+
```html
|
|
79
49
|
<template>
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
50
|
+
<div>
|
|
51
|
+
<Guido
|
|
52
|
+
ref="guidoEditor"
|
|
53
|
+
:template-id="templateId"
|
|
54
|
+
:user-id="userId"
|
|
55
|
+
:guido-config="guidoConfig"
|
|
56
|
+
:html="initialHtml"
|
|
57
|
+
:css="initialCss"
|
|
58
|
+
@dynamic-content:open="handleDynamicContentOpen"
|
|
59
|
+
@back="handleBack"
|
|
60
|
+
@save:start="handleSaveStart"
|
|
61
|
+
@save:complete="handleSaveComplete"
|
|
62
|
+
/>
|
|
63
|
+
</div>
|
|
87
64
|
</template>
|
|
88
65
|
|
|
89
66
|
<script lang="ts">
|
|
90
67
|
import { Guido } from '@useinsider/guido';
|
|
91
|
-
import '@useinsider/guido/style';
|
|
92
68
|
|
|
93
69
|
export default {
|
|
94
|
-
components: {
|
|
95
|
-
|
|
70
|
+
components: {
|
|
71
|
+
Guido
|
|
72
|
+
},
|
|
96
73
|
data() {
|
|
97
74
|
return {
|
|
98
75
|
templateId: 'template-123',
|
|
99
76
|
userId: 'user-456',
|
|
77
|
+
initialHtml: '<p>Initial HTML content</p>',
|
|
78
|
+
initialCss: 'p { color: #333; }',
|
|
100
79
|
guidoConfig: {
|
|
101
80
|
translationsPath: 'window.trans.en',
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
senderName: 'Your Company',
|
|
105
|
-
subject: 'Email Subject'
|
|
106
|
-
},
|
|
107
|
-
partner: {
|
|
108
|
-
partnerName: 'your-partner',
|
|
109
|
-
productType: 1,
|
|
110
|
-
messageType: 1
|
|
111
|
-
},
|
|
81
|
+
htmlCompilerRules: [],
|
|
82
|
+
ignoreDefaultHtmlCompilerRules: false,
|
|
112
83
|
features: {
|
|
113
84
|
dynamicContent: true,
|
|
114
85
|
saveAsTemplate: true,
|
|
115
86
|
versionHistory: true
|
|
116
87
|
}
|
|
117
|
-
}
|
|
88
|
+
},
|
|
89
|
+
dynamicContentModalVisible: false
|
|
118
90
|
};
|
|
119
91
|
},
|
|
120
92
|
|
|
121
93
|
methods: {
|
|
122
|
-
|
|
123
|
-
console.log('
|
|
94
|
+
handleDynamicContentOpen(detail) {
|
|
95
|
+
console.log('Dynamic content requested:', detail);
|
|
96
|
+
this.dynamicContentModalVisible = true;
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
handleBack() {
|
|
100
|
+
console.log('User clicked back button');
|
|
101
|
+
// Handle navigation back
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
handleSaveStart() {
|
|
105
|
+
console.log('Save process started');
|
|
106
|
+
// Show loading indicator
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
handleSaveComplete(template) {
|
|
110
|
+
console.log('Save completed:', template);
|
|
111
|
+
// Handle saved template data
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
// ⚠️ Your own Dynamic Content Modal should have this id: #guido-dynamic-content-modal
|
|
115
|
+
handleDynamicContentInsert() {
|
|
116
|
+
this.$refs.guidoEditor?.dynamicContent.insert({
|
|
117
|
+
text: 'Display Text',
|
|
118
|
+
value: 'actual-value',
|
|
119
|
+
fallback: 'Fallback Text'
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
this.dynamicContentModalVisible = false;
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
// ⚠️ It's mandatory. There is no way to understand if user closes the modal without selection.
|
|
126
|
+
handleDynamicContentClose() {
|
|
127
|
+
this.$refs.guidoEditor?.dynamicContent.close();
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
// If you need to trigger save manually like leave modal cases, you can use this method.
|
|
131
|
+
save () {
|
|
132
|
+
this.$refs.guidoEditor?.saveSilent();
|
|
124
133
|
}
|
|
125
134
|
}
|
|
126
135
|
};
|
|
127
136
|
</script>
|
|
128
137
|
```
|
|
129
138
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
## 📚 API Quick Reference
|
|
139
|
+
## 📚 API
|
|
133
140
|
|
|
134
|
-
### Props
|
|
141
|
+
### Guido Component Props
|
|
135
142
|
|
|
136
|
-
| Prop | Type | Required | Description |
|
|
137
|
-
|
|
138
|
-
| `templateId` | `string` | ✅ | Unique identifier for the email template |
|
|
139
|
-
| `userId` | `string` | ✅ | Unique identifier for the user |
|
|
140
|
-
| `guidoConfig` | `GuidoConfig` | ✅ | Configuration object for the editor |
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
+
| Prop | Type | Required | Default | Description |
|
|
144
|
+
|------|------|----------|---------|-------------|
|
|
145
|
+
| `templateId` | `string` | ✅ | - | Unique identifier for the email template |
|
|
146
|
+
| `userId` | `string` | ✅ | - | Unique identifier for the user |
|
|
147
|
+
| `guidoConfig` | `GuidoConfig` | ✅ | - | Configuration object for the editor |
|
|
148
|
+
| `partnerName` | `string` | ⚪ | From URL host | Partner identifier |
|
|
149
|
+
| `productType` | `string` | ⚪ | From URL path | Product type identifier |
|
|
150
|
+
| `username` | `string` | ⚪ | `'Guido User'` | Display name for the user |
|
|
151
|
+
| `html` | `string` | ⚪ | `''` | Initial HTML content for the template |
|
|
152
|
+
| `css` | `string` | ⚪ | `''` | Initial CSS styles for the template |
|
|
143
153
|
|
|
144
|
-
### Events
|
|
154
|
+
### Guido Component Events
|
|
145
155
|
|
|
146
156
|
| Event | Payload | Description |
|
|
147
157
|
|-------|---------|-------------|
|
|
148
|
-
| `
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
158
|
+
| `dynamic-content:open` | `DynamicContent \| null` | Fired when user requests to insert dynamic content |
|
|
159
|
+
| `back` | - | Fired when user clicks the back button |
|
|
160
|
+
| `save:start` | - | Fired when the save process begins |
|
|
161
|
+
| `save:complete` | `Omit<Template, 'forceRecreate'>` | Fired when template is successfully saved |
|
|
162
|
+
| `on-change` | void | It Fires once for managing leave modal etc. |
|
|
163
|
+
| `ready` | void | Fired when the editor is ready and template is loaded |
|
|
164
|
+
|
|
165
|
+
### Guido Exposed Methods
|
|
166
|
+
```typescript
|
|
167
|
+
dynamicContent.insert(DynamicContent);
|
|
168
|
+
dynamicContent.close();
|
|
169
|
+
saveSilent();
|
|
170
|
+
```
|
|
154
171
|
|
|
155
|
-
###
|
|
172
|
+
### Guido Interfaces
|
|
156
173
|
|
|
157
174
|
```typescript
|
|
158
|
-
|
|
159
|
-
|
|
175
|
+
interface GuidoConfig {
|
|
176
|
+
translationsPath: string;
|
|
177
|
+
htmlCompilerRules?: CompilerRule[];
|
|
178
|
+
ignoreDefaultHtmlCompilerRules?: boolean;
|
|
179
|
+
useHeader: boolean
|
|
180
|
+
emailHeader: {
|
|
181
|
+
senderName: string;
|
|
182
|
+
subject: string;
|
|
183
|
+
};
|
|
184
|
+
partner: {
|
|
185
|
+
partnerName: string;
|
|
186
|
+
productType: number;
|
|
187
|
+
messageType: number;
|
|
188
|
+
};
|
|
189
|
+
features: {
|
|
190
|
+
dynamicContent: boolean;
|
|
191
|
+
saveAsTemplate: boolean;
|
|
192
|
+
versionHistory: boolean;
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
```
|
|
160
196
|
|
|
161
|
-
|
|
162
|
-
|
|
197
|
+
| Property | Type | Default | Description |
|
|
198
|
+
|----------|------|---------|-------------|
|
|
199
|
+
| `translationsPath` | `string` | `'window.trans.en'` | JavaScript path to the translations object |
|
|
200
|
+
| `htmlCompilerRules` | `CompilerRule[]` | `[]` | Additional compiler rules to apply to HTML content. See [HTML Compiler Rules](#-html-compiler-rules) section below |
|
|
201
|
+
| `ignoreDefaultHtmlCompilerRules` | `boolean` | `false` | Skip default compiler rules and only use custom rules. Default rules: `src/config/compiler/htmlCompilerRules.ts` |
|
|
202
|
+
| `useHeader` | `boolean` | `true` | Adds extra spaces to height for adjusting. If you don't use Inone Page header, override as `false` |
|
|
203
|
+
| `features` | `Features` | `{ dynamicContent: true, saveAsTemplate: true, versionHistory: true }` | Feature flags to enable/disable editor functionality |
|
|
204
|
+
| `features.dynamicContent` | `boolean` | `true` | Enable dynamic content insertion feature |
|
|
205
|
+
| `features.saveAsTemplate` | `boolean` | `true` | Enable save as template feature |
|
|
206
|
+
| `features.versionHistory` | `boolean` | `true` | Enable version history feature |
|
|
163
207
|
|
|
164
|
-
|
|
165
|
-
|
|
208
|
+
```typescript
|
|
209
|
+
interface DynamicContent {
|
|
210
|
+
value: string;
|
|
211
|
+
text: string;
|
|
212
|
+
fallback?: string;
|
|
213
|
+
}
|
|
166
214
|
```
|
|
215
|
+
---
|
|
167
216
|
|
|
168
|
-
|
|
217
|
+
| Property | Type | Default | Description |
|
|
218
|
+
|----------|------|---------|-------------|
|
|
219
|
+
| `value` | `string` | '' | Value of the dynamic content |
|
|
220
|
+
| `text` | `string` | '' | Visible value of the dynamic content |
|
|
221
|
+
| `fallback?` | `string` | '' | Fallback value of the dynamic content. Optional |
|
|
222
|
+
|
|
223
|
+
### TypeScript Types
|
|
224
|
+
|
|
225
|
+
The library exports the following TypeScript types:
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
// Main component
|
|
229
|
+
import { Guido } from '@useinsider/guido';
|
|
230
|
+
|
|
231
|
+
// Types
|
|
232
|
+
import type { GuidoConfig } from '@useinsider/guido';
|
|
233
|
+
import type { StripoEventType } from '@useinsider/guido';
|
|
234
|
+
```
|
|
169
235
|
|
|
170
236
|
## 🔨 HTML Compiler Rules
|
|
171
237
|
|
|
172
|
-
|
|
238
|
+
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.
|
|
239
|
+
|
|
240
|
+
### Rule Types
|
|
173
241
|
|
|
174
|
-
|
|
175
|
-
|
|
242
|
+
There are 4 types of compiler rules:
|
|
243
|
+
|
|
244
|
+
#### 1. Replace Rule
|
|
245
|
+
Replace specific strings in HTML content.
|
|
176
246
|
|
|
177
247
|
```typescript
|
|
178
248
|
{
|
|
179
249
|
id: 'fix-encoding',
|
|
250
|
+
description: 'Fix URL encoding issues',
|
|
180
251
|
type: 'replace',
|
|
181
|
-
search: '{%22',
|
|
182
|
-
replacement: '%7B%22',
|
|
183
|
-
|
|
252
|
+
search: '{%22', // String to find
|
|
253
|
+
replacement: '%7B%22', // String to replace with
|
|
254
|
+
replaceAll: true, // Replace all occurrences (default: true)
|
|
255
|
+
priority: 10 // Execution priority (lower = earlier)
|
|
184
256
|
}
|
|
185
257
|
```
|
|
186
|
-
</details>
|
|
187
258
|
|
|
188
|
-
|
|
189
|
-
|
|
259
|
+
#### 2. Regex Rule
|
|
260
|
+
Use regular expressions for complex pattern matching and replacement.
|
|
190
261
|
|
|
191
262
|
```typescript
|
|
192
263
|
{
|
|
193
264
|
id: 'remove-comments',
|
|
265
|
+
description: 'Remove HTML comments',
|
|
194
266
|
type: 'regex',
|
|
195
|
-
pattern: '<!--.*?-->',
|
|
196
|
-
replacement: '',
|
|
197
|
-
flags: 'g',
|
|
267
|
+
pattern: '<!--.*?-->', // Regex pattern
|
|
268
|
+
replacement: '', // Replacement string
|
|
269
|
+
flags: 'g', // Regex flags (default: 'g')
|
|
198
270
|
priority: 20
|
|
199
271
|
}
|
|
200
272
|
```
|
|
201
|
-
</details>
|
|
202
273
|
|
|
203
|
-
|
|
204
|
-
|
|
274
|
+
#### 3. Remove Rule
|
|
275
|
+
Remove specific strings or patterns from HTML content.
|
|
205
276
|
|
|
206
277
|
```typescript
|
|
207
278
|
{
|
|
208
279
|
id: 'cleanup-scripts',
|
|
280
|
+
description: 'Remove unwanted script tags',
|
|
209
281
|
type: 'remove',
|
|
210
|
-
targets: [
|
|
282
|
+
targets: [ // Array of strings or RegExp objects
|
|
211
283
|
'<script src="unwanted.js"></script>',
|
|
212
284
|
/onclick="[^"]*"/g
|
|
213
285
|
],
|
|
214
286
|
priority: 30
|
|
215
287
|
}
|
|
216
288
|
```
|
|
217
|
-
</details>
|
|
218
289
|
|
|
219
|
-
|
|
220
|
-
|
|
290
|
+
#### 4. Custom Rule
|
|
291
|
+
Define complex transformation logic with a custom processor function.
|
|
221
292
|
|
|
222
293
|
```typescript
|
|
223
294
|
{
|
|
224
295
|
id: 'add-meta-tags',
|
|
296
|
+
description: 'Add custom meta tags to head',
|
|
225
297
|
type: 'custom',
|
|
226
298
|
processor: (html: string): string => {
|
|
299
|
+
// Custom transformation logic
|
|
227
300
|
const metaTags = '<meta name="custom" content="value">';
|
|
228
301
|
return html.replace('</head>', `${metaTags}</head>`);
|
|
229
302
|
},
|
|
230
303
|
priority: 40
|
|
231
304
|
}
|
|
232
305
|
```
|
|
233
|
-
</details>
|
|
234
306
|
|
|
235
|
-
###
|
|
307
|
+
### Using HTML Compiler Rules
|
|
308
|
+
|
|
309
|
+
#### Basic Usage with Custom Rules
|
|
236
310
|
|
|
237
311
|
```typescript
|
|
238
312
|
const guidoConfig = {
|
|
313
|
+
translationsPath: 'window.trans.en',
|
|
314
|
+
features: {
|
|
315
|
+
dynamicContent: true,
|
|
316
|
+
saveAsTemplate: true,
|
|
317
|
+
versionHistory: false // Disable version history
|
|
318
|
+
},
|
|
239
319
|
htmlCompilerRules: [
|
|
240
320
|
{
|
|
241
321
|
id: 'replace-domain',
|
|
322
|
+
description: 'Replace old domain with new one',
|
|
242
323
|
type: 'replace',
|
|
243
324
|
search: 'old-domain.com',
|
|
244
325
|
replacement: 'new-domain.com',
|
|
326
|
+
replaceAll: true,
|
|
245
327
|
priority: 10
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
id: 'remove-tracking',
|
|
331
|
+
description: 'Remove tracking pixels',
|
|
332
|
+
type: 'regex',
|
|
333
|
+
pattern: '<img[^>]*tracking[^>]*>',
|
|
334
|
+
replacement: '',
|
|
335
|
+
flags: 'gi',
|
|
336
|
+
priority: 20
|
|
337
|
+
}
|
|
338
|
+
]
|
|
339
|
+
};
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### Ignoring Default Rules
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
const guidoConfig = {
|
|
346
|
+
translationsPath: 'window.trans.en',
|
|
347
|
+
features: {
|
|
348
|
+
dynamicContent: true,
|
|
349
|
+
saveAsTemplate: true,
|
|
350
|
+
versionHistory: true
|
|
351
|
+
},
|
|
352
|
+
ignoreDefaultHtmlCompilerRules: true, // Skip all default rules
|
|
353
|
+
htmlCompilerRules: [
|
|
354
|
+
// Only your custom rules will be applied
|
|
355
|
+
{
|
|
356
|
+
id: 'custom-transformation',
|
|
357
|
+
type: 'replace',
|
|
358
|
+
search: 'old-text',
|
|
359
|
+
replacement: 'new-text',
|
|
360
|
+
priority: 1
|
|
246
361
|
}
|
|
247
362
|
]
|
|
248
363
|
};
|
|
249
364
|
```
|
|
250
365
|
|
|
251
|
-
|
|
366
|
+
### Rule Execution Order
|
|
367
|
+
|
|
368
|
+
Rules are executed in priority order (lower numbers first). Rules with the same priority are executed in array order.
|
|
369
|
+
|
|
370
|
+
- **Priority 1-99**: Reserved for critical transformations
|
|
371
|
+
- **Priority 100-999**: Standard transformations
|
|
372
|
+
- **Priority 1000+**: Additional custom rules (automatically assigned)
|
|
373
|
+
|
|
374
|
+
### Default Rules
|
|
375
|
+
|
|
376
|
+
Guido includes several default rules for common email HTML optimizations:
|
|
377
|
+
|
|
378
|
+
- **URL encoding fixes**: Fixes malformed URL encoding in dynamic content
|
|
379
|
+
- **Template tag restoration**: Restores `{{}}` template tags that got URL encoded
|
|
380
|
+
- **HTML entity decoding**: Converts `<` and `>` back to `<` and `>`
|
|
381
|
+
- **Cleanup rules**: Removes unwanted iframe and style elements
|
|
382
|
+
- **MSO conditions**: Manages Outlook-specific conditional comments
|
|
383
|
+
- **Domain replacement**: Updates old image domains to current ones
|
|
384
|
+
|
|
385
|
+
You can view all default rules in: `src/config/compiler/htmlCompilerRules.ts`
|
|
386
|
+
|
|
387
|
+
### CompilerRule Interface
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
type CompilerRuleType = 'replace' | 'regex' | 'remove' | 'custom';
|
|
391
|
+
|
|
392
|
+
interface BaseCompilerRule {
|
|
393
|
+
id: string;
|
|
394
|
+
description?: string;
|
|
395
|
+
priority: number;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
interface ReplaceRule extends BaseCompilerRule {
|
|
399
|
+
type: 'replace';
|
|
400
|
+
search: string;
|
|
401
|
+
replacement: string;
|
|
402
|
+
replaceAll?: boolean; // Default: true
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
interface RegexRule extends BaseCompilerRule {
|
|
406
|
+
type: 'regex';
|
|
407
|
+
pattern: string;
|
|
408
|
+
replacement: string;
|
|
409
|
+
flags?: string; // Default: 'g'
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
interface RemoveRule extends BaseCompilerRule {
|
|
413
|
+
type: 'remove';
|
|
414
|
+
targets: (string | RegExp)[]; // Array of strings or RegExp objects
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
interface CustomRule extends BaseCompilerRule {
|
|
418
|
+
type: 'custom';
|
|
419
|
+
processor: (html: string) => string;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
type CompilerRule = ReplaceRule | RegexRule | RemoveRule | CustomRule;
|
|
423
|
+
```
|
|
252
424
|
|
|
253
425
|
---
|
|
254
426
|
|
|
255
427
|
## 🔧 Development
|
|
256
428
|
|
|
257
|
-
###
|
|
429
|
+
### Prerequisites
|
|
430
|
+
|
|
431
|
+
- 🧄 `Bun` (strongly recommended)
|
|
432
|
+
or
|
|
433
|
+
- NodeJS 18+ & `npm`
|
|
434
|
+
|
|
435
|
+
### Setup
|
|
258
436
|
|
|
259
437
|
```bash
|
|
260
438
|
# Install dependencies
|
|
261
439
|
bun install
|
|
262
440
|
|
|
263
|
-
# Start
|
|
441
|
+
# Start development server
|
|
264
442
|
bun start
|
|
265
443
|
|
|
266
|
-
# Build
|
|
444
|
+
# Build for production
|
|
267
445
|
bun run build
|
|
268
446
|
|
|
269
|
-
#
|
|
447
|
+
# Type checking
|
|
448
|
+
bun run type-check
|
|
449
|
+
|
|
450
|
+
# Linting
|
|
270
451
|
bun run lint
|
|
271
452
|
```
|
|
272
453
|
|
|
273
|
-
###
|
|
454
|
+
### Environment Variables
|
|
274
455
|
|
|
275
|
-
|
|
456
|
+
Create a `.env` file with the following variables: (You can get env variables from your senior)
|
|
276
457
|
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
|
|
458
|
+
```env
|
|
459
|
+
VITE_STRIPO_PLUGIN_ID=your_plugin_id
|
|
460
|
+
VITE_STRIPO_SECRET_KEY=your_secret_key
|
|
461
|
+
VITE_STRIPO_ROLE=your_role
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Project Structure
|
|
280
465
|
|
|
281
|
-
|
|
282
|
-
|
|
466
|
+
```
|
|
467
|
+
src/
|
|
468
|
+
├── components/ # Vue components
|
|
469
|
+
├── composables/ # Vue composables & business logic
|
|
470
|
+
├── services/ # API layer
|
|
471
|
+
├── stores/ # State management
|
|
472
|
+
├── @types/ # TypeScript definitions
|
|
473
|
+
├── static/ # Static assets & templates
|
|
474
|
+
├── utils/ # Utility functions
|
|
475
|
+
├── enums/ # Constants & enums
|
|
476
|
+
├── mock/ # Mock data for development
|
|
477
|
+
├── plugins/ # Vue plugins
|
|
478
|
+
└── library.ts # Main export
|
|
283
479
|
```
|
|
284
480
|
|
|
285
|
-
|
|
481
|
+
## 🔌 Provide/Inject Utilities
|
|
286
482
|
|
|
287
|
-
|
|
483
|
+
Guido includes type-safe utilities for Vue's provide/inject system to facilitate dependency injection between components.
|
|
484
|
+
|
|
485
|
+
### useProvideInject
|
|
486
|
+
|
|
487
|
+
The `useProvideInject` composable provides two helper functions for type-safe dependency injection:
|
|
488
|
+
|
|
489
|
+
#### Basic Usage
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
// Parent component
|
|
493
|
+
import { provideValue } from '@useinsider/guido';
|
|
494
|
+
import { InjectionKey } from 'vue';
|
|
495
|
+
|
|
496
|
+
// Define a typed injection key
|
|
497
|
+
const MyServiceKey: InjectionKey<MyService> = Symbol('MyService');
|
|
288
498
|
|
|
289
|
-
|
|
499
|
+
// Provide the value
|
|
500
|
+
const myService = new MyService();
|
|
501
|
+
provideValue(MyServiceKey, myService);
|
|
290
502
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
- **PR Requirements**:
|
|
294
|
-
- Fill PR labels
|
|
295
|
-
- Assign to yourself
|
|
296
|
-
- Include tests
|
|
297
|
-
- Pass all checks before review
|
|
503
|
+
// Child component
|
|
504
|
+
import { useInjectedValue } from '@useinsider/guido';
|
|
298
505
|
|
|
299
|
-
|
|
506
|
+
// Inject the value with type safety
|
|
507
|
+
const myService = useInjectedValue(MyServiceKey);
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
#### With Default Value
|
|
511
|
+
|
|
512
|
+
```typescript
|
|
513
|
+
// Inject with a fallback value
|
|
514
|
+
const myService = useInjectedValue(MyServiceKey, new DefaultService());
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
#### Error Handling
|
|
518
|
+
|
|
519
|
+
The `useInjectedValue` function will throw a descriptive error if no provider is found and no default value is provided:
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
// This will throw an error if no provider exists
|
|
523
|
+
try {
|
|
524
|
+
const myService = useInjectedValue(MyServiceKey);
|
|
525
|
+
} catch (error) {
|
|
526
|
+
console.error('No provider found for MyService');
|
|
527
|
+
}
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### API Reference
|
|
531
|
+
|
|
532
|
+
#### `provideValue`
|
|
533
|
+
|
|
534
|
+
```typescript
|
|
535
|
+
provideValue<T>(key: InjectionKey<T>, value: T): void
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
Provides a value using Vue's provide system with type safety.
|
|
539
|
+
|
|
540
|
+
| Parameter | Type | Description |
|
|
541
|
+
|-----------|------|-------------|
|
|
542
|
+
| `key` | `InjectionKey<T>` | The typed injection key |
|
|
543
|
+
| `value` | `T` | The value to provide |
|
|
544
|
+
|
|
545
|
+
#### `useInjectedValue`
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
useInjectedValue<T>(key: InjectionKey<T>, defaultValue?: T): T
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
Injects a value using Vue's inject system with type safety and error handling.
|
|
552
|
+
|
|
553
|
+
| Parameter | Type | Required | Description |
|
|
554
|
+
|-----------|------|----------|-------------|
|
|
555
|
+
| `key` | `InjectionKey<T>` | ✅ | The typed injection key |
|
|
556
|
+
| `defaultValue` | `T` | ⚪ | Optional fallback value |
|
|
557
|
+
|
|
558
|
+
**Returns:** `T` - The injected value
|
|
559
|
+
|
|
560
|
+
**Throws:** `Error` - When no provider is found and no default value is provided
|
|
561
|
+
|
|
562
|
+
## 🌐 i18n
|
|
563
|
+
Before running the project, it sends to request to inone.useinsider.com/translations and writes the JSON file into - [trans.json](src/mock/responses/trans.json).
|
|
564
|
+
It allows to use production or local translations on your code. 🚀
|
|
565
|
+
Example usage:
|
|
566
|
+
```js
|
|
567
|
+
import { useTranslations } from '@@/Composables/useTranslations';
|
|
568
|
+
|
|
569
|
+
const trans = useTranslations();
|
|
570
|
+
|
|
571
|
+
// use everywhere like this:
|
|
572
|
+
trans('foo.bar')
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
## 📦 Local Building (Recommended)
|
|
576
|
+
|
|
577
|
+
Run this commands if you want to test the package on your local before sending to NPM.
|
|
578
|
+
```sh
|
|
579
|
+
bun run build
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
Since bun does not have packaging yet, use npm here: 🥲
|
|
583
|
+
```sh
|
|
584
|
+
npm pack
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
It'll crate like `useinsider-guido-1.0.0.tgz` file.
|
|
588
|
+
|
|
589
|
+
Move this file to your project path like: `email-fe` via:
|
|
590
|
+
```sh
|
|
591
|
+
cp useinsider-guido-1.0.0.tgz ../email-fe
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
Install the file to your project:
|
|
595
|
+
```sh
|
|
596
|
+
npm i ./useinsider-guido-1.0.0.tgz
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
Then you just need to rebuild to your project or restart the Container. 🎉
|
|
600
|
+
|
|
601
|
+
For Future, we can create a shell script for it. Feel free to help 🙃
|
|
602
|
+
|
|
603
|
+
## 📦 Build Output
|
|
604
|
+
|
|
605
|
+
The library builds to multiple formats:
|
|
606
|
+
|
|
607
|
+
- **ES Module**: `dist/library.js` (recommended)
|
|
608
|
+
- **CSS**: `dist/guido.css` (custom styles)
|
|
609
|
+
|
|
610
|
+
### Package Exports
|
|
611
|
+
|
|
612
|
+
```json
|
|
613
|
+
{
|
|
614
|
+
"exports": {
|
|
615
|
+
".": {
|
|
616
|
+
"import": "./dist/library.js",
|
|
617
|
+
"types": "./dist/components/Guido.vue.d.ts",
|
|
618
|
+
"require": "./dist/components/Guido.vue.js"
|
|
619
|
+
},
|
|
620
|
+
"./style": "./dist/guido.css"
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
## 🤝 Contributing
|
|
626
|
+
- PR Titles should be structured like `TASK-ID | 🔥 | Some Clear Task Descriptions`
|
|
627
|
+
- PR Labels should be filled.
|
|
628
|
+
- PR Assignee required.
|
|
629
|
+
- Tests should be covered.
|
|
630
|
+
- All required checks should be passed before sending review request.
|
|
300
631
|
|
|
301
632
|
## 📄 License
|
|
302
633
|
|
|
303
634
|
ISC License
|
|
304
635
|
|
|
305
|
-
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
## 🔗 Related
|
|
306
639
|
|
|
307
640
|
- [Stripo Email Editor](https://stripo.email/) - The underlying email editor
|
|
308
641
|
- [@useinsider/design-system-vue](https://github.com/useinsider/design-system-vue) - Insider's Vue design system
|
|
309
642
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
643
|
+
## 🎯 TODO:
|
|
644
|
+
- CSS part should be optimized with variables & `sass-loader`.
|
|
645
|
+
- Master Version Generator should be fixed.
|
|
646
|
+
- Playwright integrationBoilerplate/control.ts
|
|
647
|
+
- Commitlint & Precommit Hooks integration
|
|
648
|
+
- Get Pre-built display conditions from API
|