js-template-engine 1.0.1 → 2.0.0
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 +104 -157
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +10 -0
- package/dist/commands/render.d.ts +29 -0
- package/dist/commands/render.js +73 -0
- package/dist/commands/validate.d.ts +10 -0
- package/dist/commands/validate.js +42 -0
- package/dist/component-name.d.ts +15 -0
- package/dist/component-name.js +30 -0
- package/dist/extensions.d.ts +23 -0
- package/dist/extensions.js +38 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +29 -0
- package/dist/output.d.ts +11 -0
- package/dist/output.js +22 -0
- package/dist/program.d.ts +16 -0
- package/dist/program.js +74 -0
- package/dist/reporting.d.ts +15 -0
- package/dist/reporting.js +27 -0
- package/dist/template-sources.d.ts +22 -0
- package/dist/template-sources.js +71 -0
- package/package.json +47 -23
- package/.eslintrc.js +0 -26
- package/bin/cli.js +0 -129
- package/dist/bem.html +0 -12
- package/examples/bem.js +0 -81
- package/examples/react.js +0 -109
- package/examples/slots.js +0 -103
- package/src/engine/TemplateEngine.js +0 -249
- package/src/extensions/bem.js +0 -108
- package/src/extensions/react.js +0 -102
- package/src/handlers/FileHandler.js +0 -116
- package/src/helpers/createLogger.js +0 -19
- package/src/helpers/mergeNodeExtensionOptions.js +0 -8
- package/src/index.js +0 -12
package/README.md
CHANGED
|
@@ -1,184 +1,131 @@
|
|
|
1
|
-
#
|
|
1
|
+
# js-template-engine
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The command-line interface for the JS Template Engine. Renders UI components
|
|
4
|
+
defined as plain, typed data to vanilla HTML/CSS/JS or to React, Vue, and
|
|
5
|
+
Svelte components — with styling methodologies (BEM, Tailwind) applied as
|
|
6
|
+
extensions.
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
- Customizable: Does it not yet support your templating language of choice? The abstract logic allows you to create and use your own extensions.
|
|
9
|
-
- Native Extensions: There's a growing ecosystem of extensions, i.e. React to generate JSX components and BEM to enforce consistent class naming.
|
|
10
|
-
- CLI Interface: A convenient CLI tool that can both process single JSON files and traverse through nested folder structures from the command line.
|
|
11
|
-
- Flexible Configuration: Customize the output directory, apply framework-specific extensions, and more through CLI options or configuration files.
|
|
8
|
+
```bash
|
|
9
|
+
npx js-template-engine render button.json --framework react
|
|
10
|
+
```
|
|
12
11
|
|
|
13
12
|
## Installation
|
|
14
13
|
|
|
15
|
-
```
|
|
16
|
-
npm install js-template-engine
|
|
14
|
+
```bash
|
|
15
|
+
npm install --save-dev js-template-engine
|
|
16
|
+
# or globally:
|
|
17
|
+
npm install --global js-template-engine
|
|
17
18
|
```
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
## Commands
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
yarn add js-template-engine
|
|
23
|
-
```
|
|
22
|
+
### `render <source>`
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
Renders a template file — or every template in a directory — and writes the
|
|
25
|
+
generated files.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
```bash
|
|
28
|
+
# Vanilla HTML/CSS/JS (the default):
|
|
29
|
+
js-template-engine render button.json
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
# A React component with BEM classes:
|
|
32
|
+
js-template-engine render button.json --framework react --styling bem
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
js-template-engine render
|
|
34
|
+
# Every template in src/components, as Svelte components, into dist/svelte:
|
|
35
|
+
js-template-engine render src/components --framework svelte --output-directory dist/svelte
|
|
33
36
|
```
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
38
|
+
| Option | Default | |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `--framework <name>` | — | `react`, `vue`, or `svelte`; omitted renders HTML |
|
|
41
|
+
| `--styling <names>` | — | comma-separated styling extensions (`bem`, `tailwind`), applied in order |
|
|
42
|
+
| `-o, --output-directory <path>` | `./output` | directory generated files are written to |
|
|
43
|
+
| `-n, --component-name <name>` | filename | component name for templates that declare none |
|
|
44
|
+
| `--styling-strategy <strategy>` | `in-file` | `inline`, `in-file`, or `separate-file` |
|
|
45
|
+
| `--styling-language <language>` | `css` | `css`, or `scss` for nested output; react and HTML require `--styling-strategy separate-file` under `scss` |
|
|
46
|
+
| `--scripting-strategy <strategy>` | `in-file` | `inline`, `in-file`, or `separate-file` |
|
|
47
|
+
| `--scripting-language <language>` | `javascript` | `javascript`, or `typescript` to type the generated prop consts; affects HTML mode only and requires `--scripting-strategy separate-file` (writing `<Name>.ts`) |
|
|
48
|
+
| `--bem-element-separator <separator>` | `__` | separator between BEM block and element |
|
|
49
|
+
| `--bem-modifier-separator <separator>` | `--` | separator before a BEM modifier |
|
|
50
|
+
| `--tailwind-output <output>` | `classes` | `classes` passes utilities through for Tailwind's build; `styles` converts them into the generated CSS |
|
|
51
|
+
| `--tailwind-convert-styles` | off | convert each element's authored `style` into Tailwind utility classes |
|
|
52
|
+
|
|
53
|
+
Warnings are printed to stderr; written files are listed on stdout. When a
|
|
54
|
+
template in a directory fails, the remaining templates still render and the
|
|
55
|
+
command exits non-zero.
|
|
56
|
+
|
|
57
|
+
### `validate <source>`
|
|
58
|
+
|
|
59
|
+
Validates a template file — or every template in a directory — against the
|
|
60
|
+
template format, without writing anything.
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
js-template-engine validate src/components
|
|
56
64
|
```
|
|
57
65
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
},
|
|
66
|
+
Each valid template is confirmed on stdout; each invalid one is reported on
|
|
67
|
+
stderr with the path of the offending node. The command exits non-zero when
|
|
68
|
+
any template is invalid.
|
|
69
|
+
|
|
70
|
+
## Template files
|
|
71
|
+
|
|
72
|
+
A template is plain serializable data, so the CLI accepts it in several
|
|
73
|
+
forms:
|
|
74
|
+
|
|
75
|
+
- **`.json`** — the transport form.
|
|
76
|
+
- **`.ts`, `.js`, `.mjs`, `.cjs`** — a module whose default export is the
|
|
77
|
+
template. TypeScript files are loaded directly; no build step is needed.
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
// button.ts
|
|
81
|
+
import { defineTemplate } from '@js-template-engine/types';
|
|
82
|
+
|
|
83
|
+
export default defineTemplate({
|
|
84
|
+
type: 'component',
|
|
85
|
+
name: 'Button',
|
|
86
|
+
children: [
|
|
87
|
+
{
|
|
88
|
+
type: 'element',
|
|
89
|
+
tag: 'button',
|
|
90
|
+
attributes: { class: ['button'] },
|
|
91
|
+
events: [{ name: 'click', handler: 'handleClick' }],
|
|
92
|
+
children: [{ type: 'text', content: 'Click me' }],
|
|
83
93
|
},
|
|
84
|
-
|
|
85
|
-
{
|
|
86
|
-
tag: "ul",
|
|
87
|
-
|
|
88
|
-
extensions: {
|
|
89
|
-
bem: {
|
|
90
|
-
element: "list",
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
children: [
|
|
94
|
-
{
|
|
95
|
-
tag: "li",
|
|
96
|
-
|
|
97
|
-
extensions: {
|
|
98
|
-
bem: {
|
|
99
|
-
element: "item",
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
children: [
|
|
103
|
-
{
|
|
104
|
-
tag: "a",
|
|
105
|
-
extensions: {
|
|
106
|
-
bem: {
|
|
107
|
-
element: "text",
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
attributes: {
|
|
111
|
-
href: "/",
|
|
112
|
-
},
|
|
113
|
-
children: [
|
|
114
|
-
{
|
|
115
|
-
type: "text",
|
|
116
|
-
content: "Home",
|
|
117
|
-
},
|
|
118
|
-
],
|
|
119
|
-
},
|
|
120
|
-
],
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
tag: "li",
|
|
124
|
-
extensions: {
|
|
125
|
-
bem: {
|
|
126
|
-
element: "item",
|
|
127
|
-
modifier: "current",
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
children: [
|
|
131
|
-
{
|
|
132
|
-
tag: "span",
|
|
133
|
-
extensions: {
|
|
134
|
-
bem: {
|
|
135
|
-
element: "text",
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
children: [
|
|
139
|
-
{
|
|
140
|
-
type: "text",
|
|
141
|
-
content: "About",
|
|
142
|
-
},
|
|
143
|
-
],
|
|
144
|
-
},
|
|
145
|
-
],
|
|
146
|
-
},
|
|
147
|
-
],
|
|
148
|
-
},
|
|
149
|
-
],
|
|
150
|
-
},
|
|
151
|
-
];
|
|
152
|
-
|
|
153
|
-
templateEngine.render(breadcrumbsTemplate, {
|
|
154
|
-
name: "breadcrumbs",
|
|
155
|
-
extensions: [bemExtension],
|
|
94
|
+
],
|
|
156
95
|
});
|
|
157
96
|
```
|
|
158
97
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
<nav class="breadcrumbs">
|
|
163
|
-
<ul class="breadcrumbs__list">
|
|
164
|
-
<li class="breadcrumbs__item">
|
|
165
|
-
<a href="/" class="breadcrumbs__text">Home</a>
|
|
166
|
-
</li>
|
|
167
|
-
<li class="breadcrumbs__item breadcrumbs__item--current">
|
|
168
|
-
<span class="breadcrumbs__text">About</span>
|
|
169
|
-
</li>
|
|
170
|
-
</ul>
|
|
171
|
-
</nav>
|
|
98
|
+
```bash
|
|
99
|
+
js-template-engine render button.ts --framework vue
|
|
100
|
+
# wrote output/Button.vue
|
|
172
101
|
```
|
|
173
102
|
|
|
174
|
-
|
|
103
|
+
When a directory is given, every template file directly inside it is
|
|
104
|
+
rendered; subdirectories are not searched.
|
|
105
|
+
|
|
106
|
+
## Component names
|
|
107
|
+
|
|
108
|
+
The name decides the generated file names (`Button.tsx`, `Button.vue`, …)
|
|
109
|
+
and the component identifier inside them. It is resolved in order:
|
|
175
110
|
|
|
176
|
-
|
|
111
|
+
1. the template's own `name`, when it has a `component` root;
|
|
112
|
+
2. the `--component-name` flag;
|
|
113
|
+
3. the source filename, PascalCased (`icon-badge.json` → `IconBadge`).
|
|
177
114
|
|
|
178
|
-
##
|
|
115
|
+
## Programmatic use
|
|
179
116
|
|
|
180
|
-
|
|
117
|
+
The CLI is a thin shell over `@js-template-engine/core`. For build scripts
|
|
118
|
+
and tooling, use the engine directly — extensions are passed as objects, no
|
|
119
|
+
name mapping involved:
|
|
181
120
|
|
|
182
|
-
|
|
121
|
+
```ts
|
|
122
|
+
import { process } from '@js-template-engine/core';
|
|
123
|
+
import { react } from '@js-template-engine/extension-react';
|
|
124
|
+
import { bem } from '@js-template-engine/extension-bem';
|
|
125
|
+
|
|
126
|
+
const result = process(template, { extensions: [react(), bem()] });
|
|
127
|
+
// result.files → [{ path: 'Button.tsx', content: '...' }]
|
|
128
|
+
```
|
|
183
129
|
|
|
184
|
-
|
|
130
|
+
Third-party extensions plug in through that API; the CLI's `--framework`
|
|
131
|
+
and `--styling` flags cover the published extensions.
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const program_1 = require("./program");
|
|
5
|
+
void (0, program_1.createProgram)()
|
|
6
|
+
.parseAsync(process.argv)
|
|
7
|
+
.catch((error) => {
|
|
8
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { OutputStrategy } from '@js-template-engine/types';
|
|
2
|
+
import { type FrameworkName, type StylingName } from '../extensions';
|
|
3
|
+
/** The `render` command's parsed options. */
|
|
4
|
+
export interface RenderCommandOptions {
|
|
5
|
+
framework?: FrameworkName;
|
|
6
|
+
styling: StylingName[];
|
|
7
|
+
outputDirectory: string;
|
|
8
|
+
componentName?: string;
|
|
9
|
+
stylingStrategy: OutputStrategy;
|
|
10
|
+
stylingLanguage: 'css' | 'scss';
|
|
11
|
+
scriptingStrategy: OutputStrategy;
|
|
12
|
+
scriptingLanguage: 'javascript' | 'typescript';
|
|
13
|
+
bemElementSeparator?: string;
|
|
14
|
+
bemModifierSeparator?: string;
|
|
15
|
+
tailwindOutput?: 'classes' | 'styles';
|
|
16
|
+
tailwindConvertStyles?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Renders one template file, or every template in a directory, and writes
|
|
20
|
+
* the generated files under the output directory.
|
|
21
|
+
*
|
|
22
|
+
* Warnings go to stderr; written files are listed on stdout. A template
|
|
23
|
+
* that fails to load or process is reported and does not stop the
|
|
24
|
+
* remaining templates; any failure makes the command exit non-zero.
|
|
25
|
+
*
|
|
26
|
+
* @param source - A template file or a directory of template files.
|
|
27
|
+
* @param options - The parsed command-line options.
|
|
28
|
+
*/
|
|
29
|
+
export declare function renderCommand(source: string, options: RenderCommandOptions): Promise<void>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderCommand = renderCommand;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const core_1 = require("@js-template-engine/core");
|
|
6
|
+
const component_name_1 = require("../component-name");
|
|
7
|
+
const extensions_1 = require("../extensions");
|
|
8
|
+
const output_1 = require("../output");
|
|
9
|
+
const reporting_1 = require("../reporting");
|
|
10
|
+
const template_sources_1 = require("../template-sources");
|
|
11
|
+
/**
|
|
12
|
+
* Renders one template file, or every template in a directory, and writes
|
|
13
|
+
* the generated files under the output directory.
|
|
14
|
+
*
|
|
15
|
+
* Warnings go to stderr; written files are listed on stdout. A template
|
|
16
|
+
* that fails to load or process is reported and does not stop the
|
|
17
|
+
* remaining templates; any failure makes the command exit non-zero.
|
|
18
|
+
*
|
|
19
|
+
* @param source - A template file or a directory of template files.
|
|
20
|
+
* @param options - The parsed command-line options.
|
|
21
|
+
*/
|
|
22
|
+
async function renderCommand(source, options) {
|
|
23
|
+
let sources;
|
|
24
|
+
try {
|
|
25
|
+
sources = (0, template_sources_1.resolveTemplateSources)(source);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
console.error(`error: ${(0, reporting_1.formatError)(error)}`);
|
|
29
|
+
process.exitCode = 1;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
let failed = false;
|
|
33
|
+
for (const filePath of sources) {
|
|
34
|
+
const label = (0, reporting_1.sourceLabel)(filePath);
|
|
35
|
+
try {
|
|
36
|
+
const template = await (0, template_sources_1.loadTemplate)(filePath);
|
|
37
|
+
const result = (0, core_1.process)(template, {
|
|
38
|
+
componentName: options.componentName ?? (0, component_name_1.componentNameFromFilePath)(filePath),
|
|
39
|
+
extensions: (0, extensions_1.buildExtensions)(options.framework, options.styling, {
|
|
40
|
+
elementSeparator: options.bemElementSeparator,
|
|
41
|
+
modifierSeparator: options.bemModifierSeparator,
|
|
42
|
+
}, {
|
|
43
|
+
output: options.tailwindOutput,
|
|
44
|
+
convertStyles: options.tailwindConvertStyles,
|
|
45
|
+
}),
|
|
46
|
+
styling: {
|
|
47
|
+
outputStrategy: options.stylingStrategy,
|
|
48
|
+
language: options.stylingLanguage,
|
|
49
|
+
},
|
|
50
|
+
scripting: {
|
|
51
|
+
outputStrategy: options.scriptingStrategy,
|
|
52
|
+
language: options.scriptingLanguage,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
for (const warning of result.warnings) {
|
|
56
|
+
const location = warning.nodePath === undefined || warning.nodePath === ''
|
|
57
|
+
? ''
|
|
58
|
+
: ` (at ${warning.nodePath})`;
|
|
59
|
+
console.error(`${label}: warning: ${warning.message}${location}`);
|
|
60
|
+
}
|
|
61
|
+
for (const writtenPath of (0, output_1.writeOutputFiles)(result.files, options.outputDirectory)) {
|
|
62
|
+
console.log(`wrote ${(0, node_path_1.relative)(process.cwd(), writtenPath)}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
failed = true;
|
|
67
|
+
console.error(`${label}: error: ${(0, reporting_1.formatError)(error)}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (failed) {
|
|
71
|
+
process.exitCode = 1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates one template file, or every template in a directory.
|
|
3
|
+
*
|
|
4
|
+
* Each valid template is confirmed on stdout; each invalid one is reported
|
|
5
|
+
* on stderr with the offending node path. The command exits non-zero when
|
|
6
|
+
* any template fails to load or validate.
|
|
7
|
+
*
|
|
8
|
+
* @param source - A template file or a directory of template files.
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateCommand(source: string): Promise<void>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateCommand = validateCommand;
|
|
4
|
+
const core_1 = require("@js-template-engine/core");
|
|
5
|
+
const reporting_1 = require("../reporting");
|
|
6
|
+
const template_sources_1 = require("../template-sources");
|
|
7
|
+
/**
|
|
8
|
+
* Validates one template file, or every template in a directory.
|
|
9
|
+
*
|
|
10
|
+
* Each valid template is confirmed on stdout; each invalid one is reported
|
|
11
|
+
* on stderr with the offending node path. The command exits non-zero when
|
|
12
|
+
* any template fails to load or validate.
|
|
13
|
+
*
|
|
14
|
+
* @param source - A template file or a directory of template files.
|
|
15
|
+
*/
|
|
16
|
+
async function validateCommand(source) {
|
|
17
|
+
let sources;
|
|
18
|
+
try {
|
|
19
|
+
sources = (0, template_sources_1.resolveTemplateSources)(source);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error(`error: ${(0, reporting_1.formatError)(error)}`);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
let failed = false;
|
|
27
|
+
for (const filePath of sources) {
|
|
28
|
+
const label = (0, reporting_1.sourceLabel)(filePath);
|
|
29
|
+
try {
|
|
30
|
+
const template = await (0, template_sources_1.loadTemplate)(filePath);
|
|
31
|
+
(0, core_1.validateTemplate)(template);
|
|
32
|
+
console.log(`${label}: valid`);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
failed = true;
|
|
36
|
+
console.error(`${label}: invalid — ${(0, reporting_1.formatError)(error)}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (failed) {
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derives a component name from a template file path.
|
|
3
|
+
*
|
|
4
|
+
* The file's base name is split on every non-alphanumeric character and the
|
|
5
|
+
* segments are joined in PascalCase: `theme-toggle.json` → `ThemeToggle`,
|
|
6
|
+
* `user_card.ts` → `UserCard`. A name starting with a digit is prefixed
|
|
7
|
+
* with an underscore to stay a valid JavaScript identifier.
|
|
8
|
+
*
|
|
9
|
+
* Used when the template carries no component name of its own and no
|
|
10
|
+
* `--component-name` flag is given.
|
|
11
|
+
*
|
|
12
|
+
* @param filePath - The template file path.
|
|
13
|
+
* @returns The derived component name.
|
|
14
|
+
*/
|
|
15
|
+
export declare function componentNameFromFilePath(filePath: string): string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.componentNameFromFilePath = componentNameFromFilePath;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
/**
|
|
6
|
+
* Derives a component name from a template file path.
|
|
7
|
+
*
|
|
8
|
+
* The file's base name is split on every non-alphanumeric character and the
|
|
9
|
+
* segments are joined in PascalCase: `theme-toggle.json` → `ThemeToggle`,
|
|
10
|
+
* `user_card.ts` → `UserCard`. A name starting with a digit is prefixed
|
|
11
|
+
* with an underscore to stay a valid JavaScript identifier.
|
|
12
|
+
*
|
|
13
|
+
* Used when the template carries no component name of its own and no
|
|
14
|
+
* `--component-name` flag is given.
|
|
15
|
+
*
|
|
16
|
+
* @param filePath - The template file path.
|
|
17
|
+
* @returns The derived component name.
|
|
18
|
+
*/
|
|
19
|
+
function componentNameFromFilePath(filePath) {
|
|
20
|
+
const stem = (0, node_path_1.basename)(filePath, (0, node_path_1.extname)(filePath));
|
|
21
|
+
const name = stem
|
|
22
|
+
.split(/[^a-zA-Z0-9]+/)
|
|
23
|
+
.filter((segment) => segment.length > 0)
|
|
24
|
+
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|
25
|
+
.join('');
|
|
26
|
+
if (name === '') {
|
|
27
|
+
return 'Component';
|
|
28
|
+
}
|
|
29
|
+
return /^[0-9]/.test(name) ? `_${name}` : name;
|
|
30
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type BemOptions } from '@js-template-engine/extension-bem';
|
|
2
|
+
import { type TailwindOptions } from '@js-template-engine/extension-tailwind';
|
|
3
|
+
import type { Extension } from '@js-template-engine/types';
|
|
4
|
+
/** The framework names the CLI can render with. */
|
|
5
|
+
export declare const frameworkNames: readonly ["react", "vue", "svelte"];
|
|
6
|
+
/** The styling extension names the CLI can apply. */
|
|
7
|
+
export declare const stylingNames: readonly ["bem", "tailwind"];
|
|
8
|
+
export type FrameworkName = (typeof frameworkNames)[number];
|
|
9
|
+
export type StylingName = (typeof stylingNames)[number];
|
|
10
|
+
/**
|
|
11
|
+
* Builds the extension list for one `process()` call.
|
|
12
|
+
*
|
|
13
|
+
* Styling extensions come first, in the order they were named on the
|
|
14
|
+
* command line — the order their classes are contributed in — followed by
|
|
15
|
+
* the framework extension, if any.
|
|
16
|
+
*
|
|
17
|
+
* @param framework - The framework to render with; `undefined` renders HTML.
|
|
18
|
+
* @param styling - Styling extension names, in application order.
|
|
19
|
+
* @param bemOptions - Options forwarded to the BEM extension factory.
|
|
20
|
+
* @param tailwindOptions - Options forwarded to the Tailwind extension factory.
|
|
21
|
+
* @returns Extension instances ready for `process()`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildExtensions(framework: FrameworkName | undefined, styling: readonly StylingName[], bemOptions?: BemOptions, tailwindOptions?: TailwindOptions): Extension[];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stylingNames = exports.frameworkNames = void 0;
|
|
4
|
+
exports.buildExtensions = buildExtensions;
|
|
5
|
+
const extension_bem_1 = require("@js-template-engine/extension-bem");
|
|
6
|
+
const extension_react_1 = require("@js-template-engine/extension-react");
|
|
7
|
+
const extension_svelte_1 = require("@js-template-engine/extension-svelte");
|
|
8
|
+
const extension_tailwind_1 = require("@js-template-engine/extension-tailwind");
|
|
9
|
+
const extension_vue_1 = require("@js-template-engine/extension-vue");
|
|
10
|
+
/** The framework names the CLI can render with. */
|
|
11
|
+
exports.frameworkNames = ['react', 'vue', 'svelte'];
|
|
12
|
+
/** The styling extension names the CLI can apply. */
|
|
13
|
+
exports.stylingNames = ['bem', 'tailwind'];
|
|
14
|
+
const frameworkFactories = {
|
|
15
|
+
react: extension_react_1.react,
|
|
16
|
+
vue: extension_vue_1.vue,
|
|
17
|
+
svelte: extension_svelte_1.svelte,
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Builds the extension list for one `process()` call.
|
|
21
|
+
*
|
|
22
|
+
* Styling extensions come first, in the order they were named on the
|
|
23
|
+
* command line — the order their classes are contributed in — followed by
|
|
24
|
+
* the framework extension, if any.
|
|
25
|
+
*
|
|
26
|
+
* @param framework - The framework to render with; `undefined` renders HTML.
|
|
27
|
+
* @param styling - Styling extension names, in application order.
|
|
28
|
+
* @param bemOptions - Options forwarded to the BEM extension factory.
|
|
29
|
+
* @param tailwindOptions - Options forwarded to the Tailwind extension factory.
|
|
30
|
+
* @returns Extension instances ready for `process()`.
|
|
31
|
+
*/
|
|
32
|
+
function buildExtensions(framework, styling, bemOptions = {}, tailwindOptions = {}) {
|
|
33
|
+
const extensions = styling.map((name) => name === 'bem' ? (0, extension_bem_1.bem)(bemOptions) : (0, extension_tailwind_1.tailwind)(tailwindOptions));
|
|
34
|
+
if (framework !== undefined) {
|
|
35
|
+
extensions.push(frameworkFactories[framework]());
|
|
36
|
+
}
|
|
37
|
+
return extensions;
|
|
38
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command-line interface for the JS Template Engine.
|
|
3
|
+
*
|
|
4
|
+
* The `js-template-engine` binary renders data-defined component templates
|
|
5
|
+
* to HTML, React, Vue, or Svelte (`render`) and validates template files
|
|
6
|
+
* (`validate`). This module exposes the program and its building blocks
|
|
7
|
+
* for programmatic use.
|
|
8
|
+
*/
|
|
9
|
+
export { componentNameFromFilePath } from './component-name';
|
|
10
|
+
export { renderCommand, type RenderCommandOptions } from './commands/render';
|
|
11
|
+
export { validateCommand } from './commands/validate';
|
|
12
|
+
export { buildExtensions, frameworkNames, stylingNames, type FrameworkName, type StylingName, } from './extensions';
|
|
13
|
+
export { writeOutputFiles } from './output';
|
|
14
|
+
export { createProgram, parseStylingList } from './program';
|
|
15
|
+
export { loadTemplate, resolveTemplateSources } from './template-sources';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveTemplateSources = exports.loadTemplate = exports.parseStylingList = exports.createProgram = exports.writeOutputFiles = exports.stylingNames = exports.frameworkNames = exports.buildExtensions = exports.validateCommand = exports.renderCommand = exports.componentNameFromFilePath = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Command-line interface for the JS Template Engine.
|
|
6
|
+
*
|
|
7
|
+
* The `js-template-engine` binary renders data-defined component templates
|
|
8
|
+
* to HTML, React, Vue, or Svelte (`render`) and validates template files
|
|
9
|
+
* (`validate`). This module exposes the program and its building blocks
|
|
10
|
+
* for programmatic use.
|
|
11
|
+
*/
|
|
12
|
+
var component_name_1 = require("./component-name");
|
|
13
|
+
Object.defineProperty(exports, "componentNameFromFilePath", { enumerable: true, get: function () { return component_name_1.componentNameFromFilePath; } });
|
|
14
|
+
var render_1 = require("./commands/render");
|
|
15
|
+
Object.defineProperty(exports, "renderCommand", { enumerable: true, get: function () { return render_1.renderCommand; } });
|
|
16
|
+
var validate_1 = require("./commands/validate");
|
|
17
|
+
Object.defineProperty(exports, "validateCommand", { enumerable: true, get: function () { return validate_1.validateCommand; } });
|
|
18
|
+
var extensions_1 = require("./extensions");
|
|
19
|
+
Object.defineProperty(exports, "buildExtensions", { enumerable: true, get: function () { return extensions_1.buildExtensions; } });
|
|
20
|
+
Object.defineProperty(exports, "frameworkNames", { enumerable: true, get: function () { return extensions_1.frameworkNames; } });
|
|
21
|
+
Object.defineProperty(exports, "stylingNames", { enumerable: true, get: function () { return extensions_1.stylingNames; } });
|
|
22
|
+
var output_1 = require("./output");
|
|
23
|
+
Object.defineProperty(exports, "writeOutputFiles", { enumerable: true, get: function () { return output_1.writeOutputFiles; } });
|
|
24
|
+
var program_1 = require("./program");
|
|
25
|
+
Object.defineProperty(exports, "createProgram", { enumerable: true, get: function () { return program_1.createProgram; } });
|
|
26
|
+
Object.defineProperty(exports, "parseStylingList", { enumerable: true, get: function () { return program_1.parseStylingList; } });
|
|
27
|
+
var template_sources_1 = require("./template-sources");
|
|
28
|
+
Object.defineProperty(exports, "loadTemplate", { enumerable: true, get: function () { return template_sources_1.loadTemplate; } });
|
|
29
|
+
Object.defineProperty(exports, "resolveTemplateSources", { enumerable: true, get: function () { return template_sources_1.resolveTemplateSources; } });
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { OutputFile } from '@js-template-engine/types';
|
|
2
|
+
/**
|
|
3
|
+
* Writes generated output files under the output directory.
|
|
4
|
+
*
|
|
5
|
+
* Directories are created as needed; existing files are overwritten.
|
|
6
|
+
*
|
|
7
|
+
* @param files - The files a `process()` call produced.
|
|
8
|
+
* @param outputDirectory - The directory the files are written into.
|
|
9
|
+
* @returns The written file paths.
|
|
10
|
+
*/
|
|
11
|
+
export declare function writeOutputFiles(files: OutputFile[], outputDirectory: string): string[];
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.writeOutputFiles = writeOutputFiles;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
/**
|
|
7
|
+
* Writes generated output files under the output directory.
|
|
8
|
+
*
|
|
9
|
+
* Directories are created as needed; existing files are overwritten.
|
|
10
|
+
*
|
|
11
|
+
* @param files - The files a `process()` call produced.
|
|
12
|
+
* @param outputDirectory - The directory the files are written into.
|
|
13
|
+
* @returns The written file paths.
|
|
14
|
+
*/
|
|
15
|
+
function writeOutputFiles(files, outputDirectory) {
|
|
16
|
+
return files.map((file) => {
|
|
17
|
+
const filePath = (0, node_path_1.join)(outputDirectory, file.path);
|
|
18
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(filePath), { recursive: true });
|
|
19
|
+
(0, node_fs_1.writeFileSync)(filePath, file.content);
|
|
20
|
+
return filePath;
|
|
21
|
+
});
|
|
22
|
+
}
|