@jakubmazanec/template 1.0.0-a3e1bca

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.
Files changed (47) hide show
  1. package/LICENSE.md +840 -0
  2. package/README.md +102 -0
  3. package/dist/Template.d.ts +89 -0
  4. package/dist/Template.js +156 -0
  5. package/dist/Template.js.map +1 -0
  6. package/dist/TemplateError.d.ts +14 -0
  7. package/dist/TemplateError.js +11 -0
  8. package/dist/TemplateError.js.map +1 -0
  9. package/dist/constants.d.ts +1 -0
  10. package/dist/constants.js +3 -0
  11. package/dist/constants.js.map +1 -0
  12. package/dist/main.d.ts +3 -0
  13. package/dist/main.js +5 -0
  14. package/dist/main.js.map +1 -0
  15. package/dist/types/TemplateAttributes.d.ts +21 -0
  16. package/dist/types/TemplateAttributes.js +11 -0
  17. package/dist/types/TemplateAttributes.js.map +1 -0
  18. package/dist/types/TemplateContent.d.ts +4 -0
  19. package/dist/types/TemplateContent.js +5 -0
  20. package/dist/types/TemplateContent.js.map +1 -0
  21. package/dist/types/TemplateFunction.d.ts +4 -0
  22. package/dist/types/TemplateFunction.js +5 -0
  23. package/dist/types/TemplateFunction.js.map +1 -0
  24. package/dist/types/TemplateRender.d.ts +17 -0
  25. package/dist/types/TemplateRender.js +3 -0
  26. package/dist/types/TemplateRender.js.map +1 -0
  27. package/dist/types/TemplateRenders.d.ts +3 -0
  28. package/dist/types/TemplateRenders.js +3 -0
  29. package/dist/types/TemplateRenders.js.map +1 -0
  30. package/dist/types/TemplateVariables.d.ts +9 -0
  31. package/dist/types/TemplateVariables.js +9 -0
  32. package/dist/types/TemplateVariables.js.map +1 -0
  33. package/dist/types.d.ts +5 -0
  34. package/dist/types.js +7 -0
  35. package/dist/types.js.map +1 -0
  36. package/package.json +49 -0
  37. package/src/Template.ts +266 -0
  38. package/src/TemplateError.ts +21 -0
  39. package/src/constants.ts +1 -0
  40. package/src/main.ts +3 -0
  41. package/src/types/TemplateAttributes.ts +19 -0
  42. package/src/types/TemplateContent.ts +4 -0
  43. package/src/types/TemplateFunction.ts +4 -0
  44. package/src/types/TemplateRender.ts +26 -0
  45. package/src/types/TemplateRenders.ts +8 -0
  46. package/src/types/TemplateVariables.ts +14 -0
  47. package/src/types.ts +5 -0
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ <div align="center">
2
+
3
+ # @jakubmazanec/template
4
+
5
+ TypeScript-first library for working with templates using EJS and Zod.
6
+
7
+ </div>
8
+
9
+ ## Installation
10
+
11
+ ```sh
12
+ npm install @jakubmazanec/template
13
+ ```
14
+
15
+ ⚠️ This is an [ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) package!
16
+ It cannot be required from a CommonJS module.
17
+
18
+ #### Prerequisites
19
+
20
+ - Node.js 16 or later
21
+ - TypeScript 5 or later
22
+
23
+ ## Usage
24
+
25
+ Write templates using [EJS](https://ejs.co/) with YAML front matter:
26
+
27
+ ```
28
+ ---
29
+ to: <%- attributes.variables.path %>
30
+ if: <%- attributes.variables.enabled %>
31
+ variables:
32
+ - path: foo-<%- value %>.json
33
+ enabled: true
34
+ - name: bar-<%- value %>.json
35
+ enabled: false
36
+ ---
37
+ {
38
+ "value": <%- value %>
39
+ }
40
+ ```
41
+
42
+ The front matter is used for specifying template attributes that control how is the template
43
+ rendered. Some attributes can be written in EJS too and are rendered before the template content is
44
+ rendered.
45
+
46
+ It is expected that attribute `if` renders to a string that can be parsed as YAML value; if that
47
+ value is `false`, the rendering of the whole template is cancelled.
48
+
49
+ Attribute `to` is also rendered and it represents the path of file the resulting template render is
50
+ supposed to be written into. The extension is also used for file format detection by Prettier.
51
+
52
+ Attribute `variables` is an object that is merged with the data object before rendering. If
53
+ attribute `variables` is an array of objects, that leads to multiple renders, each with different
54
+ variables object merged with the data. Each variable that is a string is also rendered.
55
+
56
+ The JavaScript variable `value` (used in EJS tags `<% %>`) is not defined, so it must be passed as a
57
+ data during the template rendering:
58
+
59
+ ```TypeScript
60
+ let template = await Template.read('template.ejs', {
61
+ dataSchema: z.object({value: z.number()}) // we have to specify the schema that represent the template data type
62
+ });
63
+
64
+ console.log(await template.render({value: 1}));
65
+ // ->
66
+ // [{
67
+ // attributes: {
68
+ // to: 'foo-1.json',
69
+ // variables: { path: 'foo-1.json', enabled: true }
70
+ // },
71
+ // data: { value: 1 },
72
+ // content: '{\n "value": 1\n}\n'
73
+ // }]
74
+
75
+ console.log(await template.render({value: 2}));
76
+ // ->
77
+ // [{
78
+ // attributes: {
79
+ // to: 'foo-2.json',
80
+ // variables: { path: 'foo-2.json', enabled: true }
81
+ // },
82
+ // data: { value: 2 },
83
+ // content: '{\n "value": 2\n}\n'
84
+ // }]
85
+ ```
86
+
87
+ Because `variables` is an array, we can expect two renders; but because one of the variables,
88
+ `enabled` is used for rendering the value of `if` attribute and is set to `false` in the second
89
+ case, only one render is actually returned.
90
+
91
+ ## Documentation
92
+
93
+ See [API reference](./docs) for auto-generated documentation.
94
+
95
+ ## Contributing
96
+
97
+ If you want to contribute, see [CONTRIBUTING](./CONTRIBUTING.md) for details.
98
+
99
+ ## License
100
+
101
+ This package is licensed under the GNU Lesser General Public License v3. See [LICENSE](./LICENSE.md)
102
+ for details.
@@ -0,0 +1,89 @@
1
+ import prettier from 'prettier';
2
+ import { type z, type AnyZodObject } from 'zod';
3
+ import { type TemplateAttributes, type TemplateRenders } from './types.js';
4
+ export type TemplateOptions<A extends AnyZodObject | undefined = undefined, D extends AnyZodObject | undefined = undefined> = {
5
+ /** Template content. */
6
+ content: string;
7
+ /** Template attributes. */
8
+ attributes: A extends undefined ? TemplateAttributes : TemplateAttributes & z.infer<NonNullable<A>>;
9
+ /** Zod schema for custom template attributes. */
10
+ attributesSchema?: A | undefined;
11
+ /** Zod schema for template data. */
12
+ dataSchema?: D | undefined;
13
+ };
14
+ export type TemplateReadOptions<A extends AnyZodObject | undefined = undefined, D extends AnyZodObject | undefined = undefined> = {
15
+ /** Zod schema for custom template attributes. */
16
+ attributesSchema?: A | undefined;
17
+ /** Zod schema for template data. */
18
+ dataSchema?: D | undefined;
19
+ };
20
+ export type TemplateReadAndRenderOptions<A extends AnyZodObject | undefined = undefined, D extends AnyZodObject | undefined = undefined> = {
21
+ /** Prettier options. */
22
+ prettierOptions?: prettier.Options | undefined;
23
+ /** Disable formatting the rendered template using Prettier. */
24
+ disablePrettier?: boolean | undefined;
25
+ /** Zod schema for custom template attributes. */
26
+ attributesSchema?: A | undefined;
27
+ /** Zod schema for template data. */
28
+ dataSchema?: D | undefined;
29
+ };
30
+ export type TemplateRenderOptions = {
31
+ /** Prettier options. */
32
+ prettierOptions?: prettier.Options | undefined;
33
+ /** Disable formatting the rendered template using Prettier. */
34
+ disablePrettier?: boolean | undefined;
35
+ };
36
+ /**
37
+ * The `Template` object stores all information about a template and has methods for reading and rendering.
38
+ *
39
+ * ```TypeScript
40
+ * let template = new Template({
41
+ * content: '<%- value %>',
42
+ * attributes: {
43
+ * to: 'value.txt',
44
+ * },
45
+ * dataSchema: z.object({value: z.number()}),
46
+ * });
47
+ *
48
+ * console.log(await template.render({value: 42})); // -> [{attributes: {to: 'value.txt'}, data: {value: 42}, content: '42'}]
49
+ * ```
50
+ *
51
+ * @typeParam A A Zod schema type used to define the custom template attributes type.
52
+ * @typeParam D A Zod schema type used to define the template datatype.
53
+ */
54
+ export declare class Template<A extends AnyZodObject | undefined = undefined, D extends AnyZodObject | undefined = undefined> {
55
+ /** Template content. Templates are written in [EJS](https://ejs.co/). */
56
+ readonly content: string;
57
+ /** Template attributes. These control how the template is rendered. Some attributes can be written in [EJS](https://ejs.co/) and are rendered before the template content is rendered. It is expected that attribute `if` renders to a string that can be parsed as YAML value; if that value is `false`, the rendering is cancelled. Attribute `to` is also rendered and it represents the path of file the resulting template render is supposed to be written into (by the user). Attribute `variables` is an object that is merged with the data object before rendering. If attribute `variables` is an array of objects, that leads to multiple renders, each with different variables object merged with the data. Each variable that is a string is also rendered. */
58
+ readonly attributes: A extends undefined ? TemplateAttributes : TemplateAttributes & z.infer<NonNullable<A>>;
59
+ /** Template function. */
60
+ private readonly fn;
61
+ /** Zod schema for custom template attributes. */
62
+ readonly attributesSchema: A extends AnyZodObject ? A : null;
63
+ /** Zod schema for template data. */
64
+ readonly dataSchema: D extends AnyZodObject ? D : null;
65
+ constructor({ content, attributes, attributesSchema, dataSchema }: TemplateOptions<A, D>);
66
+ /**
67
+ * Reads a template from a file.
68
+ *
69
+ * @param templateFilePath Path to the template file.
70
+ */
71
+ static read<A extends AnyZodObject | undefined = undefined, D extends AnyZodObject | undefined = undefined>(templateFilePath: string, options?: TemplateReadOptions<A, D>): Promise<Template<A, D>>;
72
+ /**
73
+ * Reads a template from a file and then renders it.
74
+ *
75
+ * @param templateFilePath Path to the template file.
76
+ * @param data Data used for rendering the template.
77
+ * @param options Options object.
78
+ * @return Template renders.
79
+ */
80
+ static readAndRender<A extends AnyZodObject | undefined = undefined, D extends AnyZodObject | undefined = undefined>(templateFilePath: string, data: D extends undefined ? null : z.infer<NonNullable<D>>, options?: TemplateReadAndRenderOptions<A, D>): Promise<TemplateRenders<A, D>>;
81
+ /**
82
+ * Renders the template using data.
83
+ *
84
+ * @param data Data used for rendering the template.
85
+ * @param options Options object.
86
+ * @return Template renders.
87
+ */
88
+ render(data: D extends undefined ? null : z.infer<NonNullable<D>>, options?: TemplateRenderOptions): Promise<TemplateRenders<A, D>>;
89
+ }
@@ -0,0 +1,156 @@
1
+ import ejs from 'ejs';
2
+ import fs from 'fs-extra';
3
+ import matter from 'gray-matter';
4
+ import omit from 'lodash.omit';
5
+ import prettier from 'prettier';
6
+ import yaml from 'yaml';
7
+ import { NO_INFERRED_PARSER_REGEXP } from './constants.js';
8
+ import { TemplateError } from './TemplateError.js';
9
+ import { templateAttributesSchema } from './types.js';
10
+ /**
11
+ * The `Template` object stores all information about a template and has methods for reading and rendering.
12
+ *
13
+ * ```TypeScript
14
+ * let template = new Template({
15
+ * content: '<%- value %>',
16
+ * attributes: {
17
+ * to: 'value.txt',
18
+ * },
19
+ * dataSchema: z.object({value: z.number()}),
20
+ * });
21
+ *
22
+ * console.log(await template.render({value: 42})); // -> [{attributes: {to: 'value.txt'}, data: {value: 42}, content: '42'}]
23
+ * ```
24
+ *
25
+ * @typeParam A A Zod schema type used to define the custom template attributes type.
26
+ * @typeParam D A Zod schema type used to define the template datatype.
27
+ */ export class Template {
28
+ constructor({ content , attributes , attributesSchema , dataSchema }){
29
+ this.content = content;
30
+ this.attributes = attributes;
31
+ this.fn = ejs.compile(this.content);
32
+ if (attributesSchema) {
33
+ this.attributesSchema = attributesSchema;
34
+ } else {
35
+ this.attributesSchema = null;
36
+ }
37
+ if (dataSchema) {
38
+ this.dataSchema = dataSchema;
39
+ } else {
40
+ this.dataSchema = null;
41
+ }
42
+ }
43
+ /**
44
+ * Reads a template from a file.
45
+ *
46
+ * @param templateFilePath Path to the template file.
47
+ */ static async read(templateFilePath, options) {
48
+ let { data: attributes , content } = matter(await fs.readFile(templateFilePath, 'utf8'));
49
+ let attributesSchema = (options === null || options === void 0 ? void 0 : options.attributesSchema) ? templateAttributesSchema.merge(options.attributesSchema) : templateAttributesSchema;
50
+ let attributesParseResult = attributesSchema.safeParse(attributes);
51
+ if (!attributesParseResult.success) {
52
+ throw new TemplateError('INVALID_ATTRIBUTES', {
53
+ cause: attributesParseResult.error,
54
+ data: {
55
+ path: templateFilePath,
56
+ zodIssues: attributesParseResult.error.issues
57
+ }
58
+ });
59
+ }
60
+ return new this({
61
+ attributes,
62
+ content,
63
+ attributesSchema: options === null || options === void 0 ? void 0 : options.attributesSchema,
64
+ dataSchema: options === null || options === void 0 ? void 0 : options.dataSchema
65
+ });
66
+ }
67
+ /**
68
+ * Reads a template from a file and then renders it.
69
+ *
70
+ * @param templateFilePath Path to the template file.
71
+ * @param data Data used for rendering the template.
72
+ * @param options Options object.
73
+ * @return Template renders.
74
+ */ static async readAndRender(templateFilePath, data, options) {
75
+ let template = await Template.read(templateFilePath, {
76
+ attributesSchema: options === null || options === void 0 ? void 0 : options.attributesSchema,
77
+ dataSchema: options === null || options === void 0 ? void 0 : options.dataSchema
78
+ });
79
+ return template.render(data, {
80
+ prettierOptions: options === null || options === void 0 ? void 0 : options.prettierOptions,
81
+ disablePrettier: options === null || options === void 0 ? void 0 : options.disablePrettier
82
+ });
83
+ }
84
+ /**
85
+ * Renders the template using data.
86
+ *
87
+ * @param data Data used for rendering the template.
88
+ * @param options Options object.
89
+ * @return Template renders.
90
+ */ async render(data, options) {
91
+ let renders = [];
92
+ for (let variables of Array.isArray(this.attributes.variables) ? this.attributes.variables : [
93
+ this.attributes.variables
94
+ ]){
95
+ let renderedAttributes = omit(this.attributes, [
96
+ 'if'
97
+ ]);
98
+ let renderedVariables = variables;
99
+ if (renderedVariables) {
100
+ for (let [variableName, variableValue] of Object.entries(renderedVariables)){
101
+ if (typeof variableValue === 'string') {
102
+ renderedVariables[variableName] = ejs.render(variableValue, {
103
+ ...data
104
+ });
105
+ } else {
106
+ renderedVariables[variableName] = variableValue;
107
+ }
108
+ }
109
+ renderedAttributes.variables = renderedVariables;
110
+ }
111
+ let dataWithAttributes = {
112
+ ...data,
113
+ attributes: renderedAttributes
114
+ };
115
+ if (this.attributes.if) {
116
+ let renderedIf = ejs.render(this.attributes.if, dataWithAttributes);
117
+ let parsedIf = yaml.parse(renderedIf);
118
+ if (parsedIf === false) {
119
+ continue;
120
+ }
121
+ }
122
+ renderedAttributes.to = ejs.render(renderedAttributes.to, dataWithAttributes);
123
+ dataWithAttributes.attributes = renderedAttributes;
124
+ let content;
125
+ try {
126
+ content = this.fn(dataWithAttributes);
127
+ } catch (error) {
128
+ throw new TemplateError('FAILED_RENDER', {
129
+ cause: error
130
+ });
131
+ }
132
+ if (!(options === null || options === void 0 ? void 0 : options.disablePrettier)) {
133
+ try {
134
+ content = prettier.format(content, {
135
+ ...options === null || options === void 0 ? void 0 : options.prettierOptions,
136
+ filepath: renderedAttributes.to
137
+ });
138
+ } catch (error1) {
139
+ if (!NO_INFERRED_PARSER_REGEXP.test(error1.message)) {
140
+ throw new TemplateError('FAILED_FORMAT', {
141
+ cause: error1
142
+ });
143
+ }
144
+ }
145
+ }
146
+ renders.push({
147
+ attributes: renderedAttributes,
148
+ data: data ?? null,
149
+ content
150
+ });
151
+ }
152
+ return renders;
153
+ }
154
+ }
155
+
156
+ //# sourceMappingURL=Template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/Template.ts"],"sourcesContent":["import ejs from 'ejs';\nimport fs from 'fs-extra';\nimport matter from 'gray-matter';\nimport omit from 'lodash.omit';\nimport prettier from 'prettier';\nimport yaml from 'yaml';\nimport {type z, type AnyZodObject} from 'zod';\n\nimport {NO_INFERRED_PARSER_REGEXP} from './constants.js';\nimport {TemplateError} from './TemplateError.js';\nimport {\n templateAttributesSchema,\n type TemplateAttributes,\n type TemplateFunction,\n type TemplateRender,\n type TemplateRenders,\n} from './types.js';\n\nexport type TemplateOptions<\n A extends AnyZodObject | undefined = undefined,\n D extends AnyZodObject | undefined = undefined,\n> = {\n /** Template content. */\n content: string;\n\n /** Template attributes. */\n attributes: A extends undefined\n ? TemplateAttributes\n : TemplateAttributes & z.infer<NonNullable<A>>;\n\n /** Zod schema for custom template attributes. */\n attributesSchema?: A | undefined;\n\n /** Zod schema for template data. */\n dataSchema?: D | undefined;\n};\n\nexport type TemplateReadOptions<\n A extends AnyZodObject | undefined = undefined,\n D extends AnyZodObject | undefined = undefined,\n> = {\n /** Zod schema for custom template attributes. */\n attributesSchema?: A | undefined;\n\n /** Zod schema for template data. */\n dataSchema?: D | undefined;\n};\n\nexport type TemplateReadAndRenderOptions<\n A extends AnyZodObject | undefined = undefined,\n D extends AnyZodObject | undefined = undefined,\n> = {\n /** Prettier options. */\n prettierOptions?: prettier.Options | undefined;\n\n /** Disable formatting the rendered template using Prettier. */\n disablePrettier?: boolean | undefined;\n\n /** Zod schema for custom template attributes. */\n attributesSchema?: A | undefined;\n\n /** Zod schema for template data. */\n dataSchema?: D | undefined;\n};\n\nexport type TemplateRenderOptions = {\n /** Prettier options. */\n prettierOptions?: prettier.Options | undefined;\n\n /** Disable formatting the rendered template using Prettier. */\n disablePrettier?: boolean | undefined;\n};\n\n/**\n * The `Template` object stores all information about a template and has methods for reading and rendering.\n *\n * ```TypeScript\n * let template = new Template({\n * content: '<%- value %>',\n * attributes: {\n * to: 'value.txt',\n * },\n * dataSchema: z.object({value: z.number()}),\n * });\n *\n * console.log(await template.render({value: 42})); // -> [{attributes: {to: 'value.txt'}, data: {value: 42}, content: '42'}]\n * ```\n *\n * @typeParam A A Zod schema type used to define the custom template attributes type.\n * @typeParam D A Zod schema type used to define the template datatype.\n */\nexport class Template<\n A extends AnyZodObject | undefined = undefined,\n D extends AnyZodObject | undefined = undefined,\n> {\n /** Template content. Templates are written in [EJS](https://ejs.co/). */\n readonly content: string;\n\n /** Template attributes. These control how the template is rendered. Some attributes can be written in [EJS](https://ejs.co/) and are rendered before the template content is rendered. It is expected that attribute `if` renders to a string that can be parsed as YAML value; if that value is `false`, the rendering is cancelled. Attribute `to` is also rendered and it represents the path of file the resulting template render is supposed to be written into (by the user). Attribute `variables` is an object that is merged with the data object before rendering. If attribute `variables` is an array of objects, that leads to multiple renders, each with different variables object merged with the data. Each variable that is a string is also rendered. */\n readonly attributes: A extends undefined\n ? TemplateAttributes\n : TemplateAttributes & z.infer<NonNullable<A>>;\n\n /** Template function. */\n private readonly fn: TemplateFunction;\n\n /** Zod schema for custom template attributes. */\n readonly attributesSchema: A extends AnyZodObject ? A : null;\n\n /** Zod schema for template data. */\n readonly dataSchema: D extends AnyZodObject ? D : null;\n\n constructor({content, attributes, attributesSchema, dataSchema}: TemplateOptions<A, D>) {\n this.content = content;\n this.attributes = attributes;\n this.fn = ejs.compile(this.content);\n\n if (attributesSchema) {\n this.attributesSchema = attributesSchema as A extends AnyZodObject ? A : null;\n } else {\n this.attributesSchema = null as A extends AnyZodObject ? A : null;\n }\n\n if (dataSchema) {\n this.dataSchema = dataSchema as D extends AnyZodObject ? D : null;\n } else {\n this.dataSchema = null as D extends AnyZodObject ? D : null;\n }\n }\n\n /**\n * Reads a template from a file.\n *\n * @param templateFilePath Path to the template file.\n */\n static async read<\n A extends AnyZodObject | undefined = undefined,\n D extends AnyZodObject | undefined = undefined,\n >(templateFilePath: string, options?: TemplateReadOptions<A, D>): Promise<Template<A, D>> {\n let {data: attributes, content} = matter(await fs.readFile(templateFilePath, 'utf8'));\n let attributesSchema = options?.attributesSchema\n ? templateAttributesSchema.merge(options.attributesSchema)\n : templateAttributesSchema;\n let attributesParseResult = attributesSchema.safeParse(attributes);\n\n if (!attributesParseResult.success) {\n throw new TemplateError('INVALID_ATTRIBUTES', {\n cause: attributesParseResult.error,\n data: {\n path: templateFilePath,\n zodIssues: attributesParseResult.error.issues,\n },\n });\n }\n\n return new this({\n attributes,\n content,\n attributesSchema: options?.attributesSchema,\n dataSchema: options?.dataSchema,\n } as TemplateOptions<A, D>);\n }\n\n /**\n * Reads a template from a file and then renders it.\n *\n * @param templateFilePath Path to the template file.\n * @param data Data used for rendering the template.\n * @param options Options object.\n * @return Template renders.\n */\n static async readAndRender<\n A extends AnyZodObject | undefined = undefined,\n D extends AnyZodObject | undefined = undefined,\n >(\n templateFilePath: string,\n data: D extends undefined ? null : z.infer<NonNullable<D>>,\n options?: TemplateReadAndRenderOptions<A, D>,\n ) {\n let template = await Template.read<A, D>(templateFilePath, {\n attributesSchema: options?.attributesSchema,\n dataSchema: options?.dataSchema,\n });\n\n return template.render(data, {\n prettierOptions: options?.prettierOptions,\n disablePrettier: options?.disablePrettier,\n });\n }\n\n /**\n * Renders the template using data.\n *\n * @param data Data used for rendering the template.\n * @param options Options object.\n * @return Template renders.\n */\n async render(\n data: D extends undefined ? null : z.infer<NonNullable<D>>,\n options?: TemplateRenderOptions,\n ): Promise<TemplateRenders<A, D>> {\n let renders: TemplateRenders<A, D> = [];\n\n for (let variables of Array.isArray(this.attributes.variables)\n ? this.attributes.variables\n : [this.attributes.variables]) {\n let renderedAttributes = omit(this.attributes, ['if']);\n let renderedVariables = variables;\n\n if (renderedVariables) {\n for (let [variableName, variableValue] of Object.entries(renderedVariables)) {\n if (typeof variableValue === 'string') {\n renderedVariables[variableName] = ejs.render(variableValue, {...data});\n } else {\n renderedVariables[variableName] = variableValue;\n }\n }\n\n renderedAttributes.variables = renderedVariables;\n }\n\n let dataWithAttributes = {...data, attributes: renderedAttributes};\n\n if (this.attributes.if) {\n let renderedIf = ejs.render(this.attributes.if, dataWithAttributes);\n let parsedIf = yaml.parse(renderedIf) as unknown;\n\n if (parsedIf === false) {\n continue;\n }\n }\n\n renderedAttributes.to = ejs.render(renderedAttributes.to, dataWithAttributes);\n dataWithAttributes.attributes = renderedAttributes;\n\n let content;\n\n try {\n content = this.fn(dataWithAttributes);\n } catch (error: unknown) {\n throw new TemplateError('FAILED_RENDER', {cause: error});\n }\n\n if (!options?.disablePrettier) {\n try {\n content = prettier.format(content, {\n ...options?.prettierOptions,\n filepath: renderedAttributes.to,\n });\n } catch (error: unknown) {\n if (!NO_INFERRED_PARSER_REGEXP.test((error as Error).message)) {\n throw new TemplateError('FAILED_FORMAT', {cause: error});\n }\n }\n }\n\n renders.push({\n attributes: renderedAttributes,\n data: data ?? null,\n content,\n } as TemplateRender<A, D>);\n }\n\n return renders;\n }\n}\n"],"names":["ejs","fs","matter","omit","prettier","yaml","NO_INFERRED_PARSER_REGEXP","TemplateError","templateAttributesSchema","Template","constructor","content","attributes","attributesSchema","dataSchema","fn","compile","read","templateFilePath","options","data","readFile","merge","attributesParseResult","safeParse","success","cause","error","path","zodIssues","issues","readAndRender","template","render","prettierOptions","disablePrettier","renders","variables","Array","isArray","renderedAttributes","renderedVariables","variableName","variableValue","Object","entries","dataWithAttributes","if","renderedIf","parsedIf","parse","to","format","filepath","test","message","push"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type ZodIssue } from 'zod';
2
+ import { type Template } from './Template.js';
3
+ /**
4
+ * A subclass of `Error` that indicates a template failure.
5
+ */
6
+ export declare const TemplateError: new (code: "INVALID_ATTRIBUTES" | "FAILED_FORMAT" | "FAILED_RENDER", options?: import("@jakubmazanec/error").CustomErrorWithDataOptions<{
7
+ template?: Template;
8
+ path?: string;
9
+ zodIssues?: ZodIssue[];
10
+ }> | undefined) => import("@jakubmazanec/error").CustomErrorWithData<"INVALID_ATTRIBUTES" | "FAILED_FORMAT" | "FAILED_RENDER" | "UNKNOWN_ERROR", {
11
+ template?: Template;
12
+ path?: string;
13
+ zodIssues?: ZodIssue[];
14
+ }>;
@@ -0,0 +1,11 @@
1
+ import { createCustomErrorWithData } from '@jakubmazanec/error';
2
+ /**
3
+ * A subclass of `Error` that indicates a template failure.
4
+ */ export const TemplateError = createCustomErrorWithData('TemplateError', {
5
+ INVALID_ATTRIBUTES: 'Invalid template attributes.',
6
+ FAILED_FORMAT: 'Template render formatting has failed.',
7
+ FAILED_RENDER: 'Rendering has failed.'
8
+ }, class TemplateErrorData {
9
+ });
10
+
11
+ //# sourceMappingURL=TemplateError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/TemplateError.ts"],"sourcesContent":["import {createCustomErrorWithData} from '@jakubmazanec/error';\nimport {type ZodIssue} from 'zod';\n\nimport {type Template} from './Template.js';\n\n/**\n * A subclass of `Error` that indicates a template failure.\n */\nexport const TemplateError = createCustomErrorWithData(\n 'TemplateError',\n {\n INVALID_ATTRIBUTES: 'Invalid template attributes.',\n FAILED_FORMAT: 'Template render formatting has failed.',\n FAILED_RENDER: 'Rendering has failed.',\n },\n class TemplateErrorData {\n template?: Template;\n path?: string;\n zodIssues?: ZodIssue[];\n },\n);\n"],"names":["createCustomErrorWithData","TemplateError","INVALID_ATTRIBUTES","FAILED_FORMAT","FAILED_RENDER","TemplateErrorData"],"mappings":"AAAA,SAAQA,yBAAyB,QAAO,sBAAsB;AAK9D;;CAEC,GACD,OAAO,MAAMC,gBAAgBD,0BAC3B,iBACA;IACEE,oBAAoB;IACpBC,eAAe;IACfC,eAAe;AACjB,GACA,MAAMC;AAIN,GACA"}
@@ -0,0 +1 @@
1
+ export declare const NO_INFERRED_PARSER_REGEXP: RegExp;
@@ -0,0 +1,3 @@
1
+ export const NO_INFERRED_PARSER_REGEXP = /parser.*inferred/i;
2
+
3
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["export const NO_INFERRED_PARSER_REGEXP = /parser.*inferred/i;\n"],"names":["NO_INFERRED_PARSER_REGEXP"],"mappings":"AAAA,OAAO,MAAMA,4BAA4B,oBAAoB"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './Template.js';
2
+ export * from './TemplateError.js';
3
+ export * from './types.js';
package/dist/main.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './Template.js';
2
+ export * from './TemplateError.js';
3
+ export * from './types.js';
4
+
5
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/main.ts"],"sourcesContent":["export * from './Template.js';\nexport * from './TemplateError.js';\nexport * from './types.js';\n"],"names":[],"mappings":"AAAA,cAAc,gBAAgB;AAC9B,cAAc,qBAAqB;AACnC,cAAc,aAAa"}
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Zod schema for {@linkcode TemplateAttributes}.
4
+ */
5
+ export declare const templateAttributesSchema: z.ZodObject<{
6
+ to: z.ZodString;
7
+ if: z.ZodOptional<z.ZodString>;
8
+ variables: z.ZodOptional<z.ZodUnion<[z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">]>>;
9
+ }, "strict", z.ZodTypeAny, {
10
+ to: string;
11
+ if?: string | undefined;
12
+ variables?: Record<string, unknown> | Record<string, unknown>[] | undefined;
13
+ }, {
14
+ to: string;
15
+ if?: string | undefined;
16
+ variables?: Record<string, unknown> | Record<string, unknown>[] | undefined;
17
+ }>;
18
+ /**
19
+ * Type representing template attributes.
20
+ */
21
+ export type TemplateAttributes = z.infer<typeof templateAttributesSchema>;
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ import { templateVariablesSchema } from './TemplateVariables.js';
3
+ /**
4
+ * Zod schema for {@linkcode TemplateAttributes}.
5
+ */ export const templateAttributesSchema = z.object({
6
+ to: z.string(),
7
+ if: z.string().optional(),
8
+ variables: templateVariablesSchema.optional()
9
+ }).strict();
10
+
11
+ //# sourceMappingURL=TemplateAttributes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/TemplateAttributes.ts"],"sourcesContent":["import {z} from 'zod';\n\nimport {templateVariablesSchema} from './TemplateVariables.js';\n\n/**\n * Zod schema for {@linkcode TemplateAttributes}.\n */\nexport const templateAttributesSchema = z\n .object({\n to: z.string(),\n if: z.string().optional(),\n variables: templateVariablesSchema.optional(),\n })\n .strict();\n\n/**\n * Type representing template attributes.\n */\nexport type TemplateAttributes = z.infer<typeof templateAttributesSchema>;\n"],"names":["z","templateVariablesSchema","templateAttributesSchema","object","to","string","if","optional","variables","strict"],"mappings":"AAAA,SAAQA,CAAC,QAAO,MAAM;AAEtB,SAAQC,uBAAuB,QAAO,yBAAyB;AAE/D;;CAEC,GACD,OAAO,MAAMC,2BAA2BF,EACrCG,MAAM,CAAC;IACNC,IAAIJ,EAAEK,MAAM;IACZC,IAAIN,EAAEK,MAAM,GAAGE,QAAQ;IACvBC,WAAWP,wBAAwBM,QAAQ;AAC7C,GACCE,MAAM,GAAG"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Type representing a template content.
3
+ */
4
+ export type TemplateContent = string;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Type representing a template content.
3
+ */ export { };
4
+
5
+ //# sourceMappingURL=TemplateContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/TemplateContent.ts"],"sourcesContent":["/**\n * Type representing a template content.\n */\nexport type TemplateContent = string;\n"],"names":[],"mappings":"AAAA;;CAEC,GACD,WAAqC"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Type representing a template function that takes data and returns rendered string.
3
+ */
4
+ export type TemplateFunction = (data?: Record<string, unknown>) => string;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Type representing a template function that takes data and returns rendered string.
3
+ */ export { };
4
+
5
+ //# sourceMappingURL=TemplateFunction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/TemplateFunction.ts"],"sourcesContent":["/**\n * Type representing a template function that takes data and returns rendered string.\n */\nexport type TemplateFunction = (data?: Record<string, unknown>) => string;\n"],"names":[],"mappings":"AAAA;;CAEC,GACD,WAA0E"}
@@ -0,0 +1,17 @@
1
+ import { type z } from 'zod';
2
+ import { type TemplateAttributes } from './TemplateAttributes.js';
3
+ /**
4
+ * An object type representing the result of a template render.
5
+ *
6
+ * @typeParam A Type of Zod schema used to validate the custom template attributes.
7
+ * @typeParam D Type of Zod schema used to define the type of template data.
8
+ */
9
+ export type TemplateRender<A extends z.AnyZodObject | undefined = undefined, D extends z.AnyZodObject | undefined = undefined> = {
10
+ /** Rendered template attributes. They created from the `to` and `variables` attributes, and from all of the custom template attributes.
11
+ */
12
+ attributes: A extends undefined ? Omit<TemplateAttributes, 'if'> : Omit<TemplateAttributes, 'if'> & z.infer<NonNullable<A>>;
13
+ /** Data used to render the template. */
14
+ data: D extends undefined ? null : z.infer<NonNullable<D>>;
15
+ /** Rendered template content. */
16
+ content: string;
17
+ };
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=TemplateRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/TemplateRender.ts"],"sourcesContent":["import {type z} from 'zod';\n\nimport {type TemplateAttributes} from './TemplateAttributes.js';\n\n/**\n * An object type representing the result of a template render.\n *\n * @typeParam A Type of Zod schema used to validate the custom template attributes.\n * @typeParam D Type of Zod schema used to define the type of template data.\n */\nexport type TemplateRender<\n A extends z.AnyZodObject | undefined = undefined,\n D extends z.AnyZodObject | undefined = undefined,\n> = {\n /** Rendered template attributes. They created from the `to` and `variables` attributes, and from all of the custom template attributes.\n */\n attributes: A extends undefined\n ? Omit<TemplateAttributes, 'if'>\n : Omit<TemplateAttributes, 'if'> & z.infer<NonNullable<A>>;\n\n /** Data used to render the template. */\n data: D extends undefined ? null : z.infer<NonNullable<D>>;\n\n /** Rendered template content. */\n content: string;\n};\n"],"names":[],"mappings":"AAAA,WAyBE"}
@@ -0,0 +1,3 @@
1
+ import { type z } from 'zod';
2
+ import { type TemplateRender } from './TemplateRender.js';
3
+ export type TemplateRenders<A extends z.AnyZodObject | undefined = undefined, D extends z.AnyZodObject | undefined = undefined> = Array<TemplateRender<A, D>>;
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=TemplateRenders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/TemplateRenders.ts"],"sourcesContent":["import {type z} from 'zod';\n\nimport {type TemplateRender} from './TemplateRender.js';\n\nexport type TemplateRenders<\n A extends z.AnyZodObject | undefined = undefined,\n D extends z.AnyZodObject | undefined = undefined,\n> = Array<TemplateRender<A, D>>;\n"],"names":[],"mappings":"AAAA,WAOgC"}
@@ -0,0 +1,9 @@
1
+ import * as z from 'zod';
2
+ /**
3
+ * Zod schema for {@linkcode TemplateAttributesVariables}.
4
+ */
5
+ export declare const templateVariablesSchema: z.ZodUnion<[z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">]>;
6
+ /**
7
+ * Type of `variables`` property of {@linkcode TemplateAttributes}.
8
+ */
9
+ export type TemplateAttributesVariables = z.infer<typeof templateVariablesSchema>;
@@ -0,0 +1,9 @@
1
+ import * as z from 'zod';
2
+ /**
3
+ * Zod schema for {@linkcode TemplateAttributesVariables}.
4
+ */ export const templateVariablesSchema = z.union([
5
+ z.record(z.unknown()),
6
+ z.array(z.record(z.unknown()))
7
+ ]);
8
+
9
+ //# sourceMappingURL=TemplateVariables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/TemplateVariables.ts"],"sourcesContent":["import * as z from 'zod';\n\n/**\n * Zod schema for {@linkcode TemplateAttributesVariables}.\n */\nexport const templateVariablesSchema = z.union([\n z.record(z.unknown()),\n z.array(z.record(z.unknown())),\n]);\n\n/**\n * Type of `variables`` property of {@linkcode TemplateAttributes}.\n */\nexport type TemplateAttributesVariables = z.infer<typeof templateVariablesSchema>;\n"],"names":["z","templateVariablesSchema","union","record","unknown","array"],"mappings":"AAAA,YAAYA,OAAO,MAAM;AAEzB;;CAEC,GACD,OAAO,MAAMC,0BAA0BD,EAAEE,KAAK,CAAC;IAC7CF,EAAEG,MAAM,CAACH,EAAEI,OAAO;IAClBJ,EAAEK,KAAK,CAACL,EAAEG,MAAM,CAACH,EAAEI,OAAO;CAC3B,EAAE"}
@@ -0,0 +1,5 @@
1
+ export * from './types/TemplateAttributes.js';
2
+ export * from './types/TemplateVariables.js';
3
+ export * from './types/TemplateFunction.js';
4
+ export * from './types/TemplateRender.js';
5
+ export * from './types/TemplateRenders.js';
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ export * from './types/TemplateAttributes.js';
2
+ export * from './types/TemplateVariables.js';
3
+ export * from './types/TemplateFunction.js';
4
+ export * from './types/TemplateRender.js';
5
+ export * from './types/TemplateRenders.js';
6
+
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["export * from './types/TemplateAttributes.js';\nexport * from './types/TemplateVariables.js';\nexport * from './types/TemplateFunction.js';\nexport * from './types/TemplateRender.js';\nexport * from './types/TemplateRenders.js';\n"],"names":[],"mappings":"AAAA,cAAc,gCAAgC;AAC9C,cAAc,+BAA+B;AAC7C,cAAc,8BAA8B;AAC5C,cAAc,4BAA4B;AAC1C,cAAc,6BAA6B"}