@travetto/email-inky 3.1.24 → 3.1.26
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 +6 -6
- package/jsx-runtime.ts +14 -1
- package/package.json +3 -3
- package/src/render/html.ts +4 -2
- package/src/render/renderer.ts +9 -1
- package/src/wrapper.ts +16 -12
package/README.md
CHANGED
|
@@ -13,27 +13,27 @@ npm install @travetto/email-inky
|
|
|
13
13
|
yarn add @travetto/email-inky
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
This module provides [inky](https://github.com/zurb/inky) support via [JSX](https://en.wikipedia.org/wiki/JSX_(JavaScript)) tags for integration with the [Email
|
|
16
|
+
This module provides [inky](https://github.com/zurb/inky) support via [JSX](https://en.wikipedia.org/wiki/JSX_(JavaScript)) tags for integration with the [Email Compilation Support](https://github.com/travetto/travetto/tree/main/module/email-compiler#readme "Email compiling module") engine.
|
|
17
17
|
|
|
18
18
|
**Code: Sample Inky Template**
|
|
19
19
|
```typescript
|
|
20
20
|
/** @jsxImportSource @travetto/email-inky */
|
|
21
21
|
|
|
22
|
-
import { Title, Container, Summary, Row, Column, If,
|
|
22
|
+
import { Title, Container, Summary, Row, Column, If, Button, Value, InkyTemplate } from '@travetto/email-inky';
|
|
23
23
|
|
|
24
|
-
export default
|
|
24
|
+
export default <InkyTemplate>
|
|
25
25
|
<Title>Test Email</Title>
|
|
26
26
|
<Summary>Email Summary</Summary>
|
|
27
27
|
<Container>
|
|
28
|
-
<If
|
|
28
|
+
<If attr='person'>
|
|
29
29
|
<Row>
|
|
30
30
|
<Column small={5}>
|
|
31
|
-
<Button href='https://google.com/
|
|
31
|
+
<Button href='https://google.com/{{query}}'>Hello <Value attr='name' /></Button>
|
|
32
32
|
</Column>
|
|
33
33
|
</Row>
|
|
34
34
|
</If>
|
|
35
35
|
</Container>
|
|
36
|
-
|
|
36
|
+
</InkyTemplate>;
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Please see the [inky](https://github.com/zurb/inky) documentation for more information on the [component specifications](#https-get-foundation-emails-docs-inky-html)
|
package/jsx-runtime.ts
CHANGED
|
@@ -59,12 +59,25 @@ export function createElement<T extends string | ConcreteClass | JSXComponentFun
|
|
|
59
59
|
return { [JSXRuntimeTag]: { id: (id += 1) }, key: '', type, props };
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
export function createRootElement<T extends string | ConcreteClass | JSXComponentFunction<P>, P extends {}>(
|
|
63
|
+
type: T, props: P & JSXProps
|
|
64
|
+
): JSXElement<T, P> {
|
|
65
|
+
const res: JSXElement<T, P> = { [JSXRuntimeTag]: { id: (id += 1) }, key: '', type, props };
|
|
66
|
+
// @ts-expect-error
|
|
67
|
+
res.wrap = async (): Promise<unknown> => {
|
|
68
|
+
const { wrap } = await import('@travetto/email-inky');
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
70
|
+
return wrap(res as JSXElement);
|
|
71
|
+
};
|
|
72
|
+
return res;
|
|
73
|
+
}
|
|
74
|
+
|
|
62
75
|
export function createFragment<P extends {}>(props: P & JSXProps): JSXElement<typeof JSXFragmentType, P> {
|
|
63
76
|
return createElement(JSXFragmentType, props);
|
|
64
77
|
}
|
|
65
78
|
|
|
66
79
|
export const jsx = createElement;
|
|
67
|
-
export const jsxs =
|
|
80
|
+
export const jsxs = createRootElement;
|
|
68
81
|
export const Fragment = createFragment;
|
|
69
82
|
export function isJSXElement(el: unknown): el is JSXElement {
|
|
70
83
|
return el !== undefined && el !== null && typeof el === 'object' && JSXRuntimeTag in el;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/email-inky",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.26",
|
|
4
4
|
"description": "Email Inky templating module",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"email",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"foundation-emails": "^2.4.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@travetto/email-
|
|
37
|
+
"@travetto/email-compiler": "^3.1.20"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@travetto/cli": "^3.1.
|
|
40
|
+
"@travetto/cli": "^3.1.7"
|
|
41
41
|
},
|
|
42
42
|
"peerDependenciesMeta": {
|
|
43
43
|
"@travetto/cli": {
|
package/src/render/html.ts
CHANGED
|
@@ -43,6 +43,7 @@ const allowedProps = new Set([
|
|
|
43
43
|
]);
|
|
44
44
|
|
|
45
45
|
const propsToStr = (props: Record<string, unknown>, ...addClasses: string[]): string => {
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
46
47
|
const out = { ...props, class: classStr(props.class as string, ...addClasses) };
|
|
47
48
|
return Object.entries(out)
|
|
48
49
|
.filter(([k, v]) => allowedProps.has(k) && v !== undefined && v !== null && v !== '')
|
|
@@ -112,15 +113,16 @@ export const Html: RenderProvider<RenderContext> = {
|
|
|
112
113
|
const colCount = kids.length || 1;
|
|
113
114
|
|
|
114
115
|
const parent = stack[stack.length - 1];
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
115
117
|
const pProps = parent.props as { columnVisited: boolean };
|
|
116
118
|
if (!pProps.columnVisited) {
|
|
117
119
|
pProps.columnVisited = true;
|
|
120
|
+
|
|
118
121
|
const sibs = getKids(parent).filter(x => isOfType(x, 'Column'));
|
|
119
122
|
if (sibs.length) {
|
|
120
123
|
sibs[0].props.class = classStr(sibs[0].props.class ?? '', 'first');
|
|
121
124
|
sibs[sibs.length - 1].props.class = classStr(sibs[sibs.length - 1].props.class ?? '', 'last');
|
|
122
125
|
}
|
|
123
|
-
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
// Check for sizes. If no attribute is provided, default to small-12. Divide evenly for large columns
|
|
@@ -148,7 +150,7 @@ export const Html: RenderProvider<RenderContext> = {
|
|
|
148
150
|
classes.push('hide-for-small');
|
|
149
151
|
}
|
|
150
152
|
if (props.largeOffset) {
|
|
151
|
-
classes.push(`large-offset-${props.
|
|
153
|
+
classes.push(`large-offset-${props.largeOffset}`);
|
|
152
154
|
}
|
|
153
155
|
if (props.hideLarge) {
|
|
154
156
|
classes.push('hide-for-large');
|
package/src/render/renderer.ts
CHANGED
|
@@ -71,6 +71,7 @@ export class InkyRenderer {
|
|
|
71
71
|
// @ts-expect-error
|
|
72
72
|
): RenderState<JSXElementByFn<K>, RenderContext> {
|
|
73
73
|
const el = ctx.createElement(key, props);
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
74
75
|
const newStack = [...state.stack, el] as JSXElement[];
|
|
75
76
|
return { ...state, el, props: el.props, recurse: () => this.#render(ctx, renderer, el.props.children ?? [], newStack) };
|
|
76
77
|
}
|
|
@@ -81,7 +82,14 @@ export class InkyRenderer {
|
|
|
81
82
|
*/
|
|
82
83
|
static async render(root: DocumentShape, provider: RenderProvider<RenderContext>): Promise<string> {
|
|
83
84
|
const ctx = new RenderContext();
|
|
84
|
-
|
|
85
|
+
let par: JSXElement;
|
|
86
|
+
|
|
87
|
+
// We are at the root element
|
|
88
|
+
if (isJSXElement(root.text)) {
|
|
89
|
+
par = root.text;
|
|
90
|
+
} else {
|
|
91
|
+
par = { props: { children: Array.isArray(root.text) ? root.text : [] }, type: '', key: '' };
|
|
92
|
+
}
|
|
85
93
|
const text = await this.#render(ctx, provider, root.text, [par]);
|
|
86
94
|
|
|
87
95
|
let cleaned = `${text.replace(/\n{3,100}/msg, '\n\n').trim()}\n`;
|
package/src/wrapper.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from 'module';
|
|
2
2
|
|
|
3
3
|
import { MessageCompilationSource } from '@travetto/email';
|
|
4
|
-
import { JSXElement } from '@travetto/email-inky/jsx-runtime';
|
|
4
|
+
import { JSXComponentFunction, JSXElement } from '@travetto/email-inky/jsx-runtime';
|
|
5
5
|
import { RootIndex, path } from '@travetto/manifest';
|
|
6
6
|
|
|
7
7
|
import { InkyRenderer } from './render/renderer';
|
|
@@ -9,19 +9,23 @@ import { Html, HtmlWrap } from './render/html';
|
|
|
9
9
|
import { Markdown } from './render/markdown';
|
|
10
10
|
import { Subject } from './render/subject';
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
export const wrap = (content: JSXElement): MessageCompilationSource => {
|
|
13
|
+
const req = createRequire(`${RootIndex.manifest.workspacePath}/node_modules`);
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
return {
|
|
16
|
+
file: '',
|
|
17
|
+
html: InkyRenderer.render.bind(InkyRenderer, { text: content.props.children, wrap: HtmlWrap }, Html),
|
|
18
|
+
text: InkyRenderer.render.bind(InkyRenderer, { text: content.props.children }, Markdown),
|
|
19
|
+
subject: InkyRenderer.render.bind(InkyRenderer, { text: content.props.children }, Subject),
|
|
20
|
+
styles: {
|
|
21
|
+
search: [path.dirname(req.resolve('foundation-emails/scss/_global.scss'))],
|
|
22
|
+
global: `
|
|
22
23
|
@import 'email/inky.variables';
|
|
23
24
|
@import '_global';
|
|
24
25
|
@import 'foundation-emails';
|
|
25
26
|
`
|
|
26
|
-
|
|
27
|
-
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const InkyTemplate: JSXComponentFunction<{}> = (): JSXElement => ({ type: '', key: '', props: {} });
|