@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 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 Templating](https://github.com/travetto/travetto/tree/main/module/email-template#readme "Email templating module") engine.
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, inkyTpl, Button, Value } from '@travetto/email-inky';
22
+ import { Title, Container, Summary, Row, Column, If, Button, Value, InkyTemplate } from '@travetto/email-inky';
23
23
 
24
- export default inkyTpl(<>
24
+ export default <InkyTemplate>
25
25
  <Title>Test Email</Title>
26
26
  <Summary>Email Summary</Summary>
27
27
  <Container>
28
- <If key='person'>
28
+ <If attr='person'>
29
29
  <Row>
30
30
  <Column small={5}>
31
- <Button href='https://google.com/[[query]]'>Hello <Value key='name' /></Button>
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 = createElement;
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.24",
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-template": "^3.1.18"
37
+ "@travetto/email-compiler": "^3.1.20"
38
38
  },
39
39
  "peerDependencies": {
40
- "@travetto/cli": "^3.1.6"
40
+ "@travetto/cli": "^3.1.7"
41
41
  },
42
42
  "peerDependenciesMeta": {
43
43
  "@travetto/cli": {
@@ -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.smallOffset}`);
153
+ classes.push(`large-offset-${props.largeOffset}`);
152
154
  }
153
155
  if (props.hideLarge) {
154
156
  classes.push('hide-for-large');
@@ -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
- const par = { props: { children: Array.isArray(root.text) ? root.text : [root.text] }, type: '', key: '' };
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 req = createRequire(`${RootIndex.manifest.workspacePath}/node_modules`);
12
+ export const wrap = (content: JSXElement): MessageCompilationSource => {
13
+ const req = createRequire(`${RootIndex.manifest.workspacePath}/node_modules`);
13
14
 
14
- export const inkyTpl = (content: JSXElement | JSXElement[]): MessageCompilationSource => ({
15
- file: '',
16
- html: InkyRenderer.render.bind(InkyRenderer, { text: content, wrap: HtmlWrap }, Html),
17
- text: InkyRenderer.render.bind(InkyRenderer, { text: content }, Markdown),
18
- subject: InkyRenderer.render.bind(InkyRenderer, { text: content }, Subject),
19
- styles: {
20
- search: [path.dirname(req.resolve('foundation-emails/scss/_global.scss'))],
21
- global: `
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: {} });