apparel 0.0.1
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 +176 -0
- package/dist/index.js +2 -0
- package/examples/config.json +8 -0
- package/examples/config.toml +6 -0
- package/examples/config.xml +14 -0
- package/examples/config.yml +10 -0
- package/examples/output.txt +22 -0
- package/examples/template.ejs +15 -0
- package/examples/template.hbs +21 -0
- package/examples/template.j2 +21 -0
- package/examples/template.liquid +21 -0
- package/package.json +33 -0
- package/tsup.config.js +8 -0
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Apparel
|
|
2
|
+
|
|
3
|
+
A powerful NPX script that fills templates with variables from configuration files. Supports multiple config formats and template engines.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multiple Config Formats**: JSON, JSON5, YAML, TOML, XML
|
|
8
|
+
- **Multiple Template Engines**: Handlebars, EJS, Liquid, Jinja/Nunjucks
|
|
9
|
+
- **Local and Remote Files**: Support for local files, URLs, and GitHub repos
|
|
10
|
+
- **GitHub Integration**: Use `@repo/file` format to fetch from n-p-x organization
|
|
11
|
+
- **Flexible Output**: Write to file or stdout
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Install globally to use as an NPX command:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g apparel
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or use directly with npx:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx apparel <src> <tpl> [dst]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
apparel <src> <tpl> [dst]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Arguments
|
|
34
|
+
|
|
35
|
+
- `src` (required): Config file path
|
|
36
|
+
- `tpl` (required): Template file path
|
|
37
|
+
- `dst` (optional): Output file path (defaults to stdout)
|
|
38
|
+
|
|
39
|
+
### File Sources
|
|
40
|
+
|
|
41
|
+
Files can be loaded from:
|
|
42
|
+
|
|
43
|
+
1. **Local files**: `./config.json`, `../templates/email.hbs`
|
|
44
|
+
2. **URLs**: `https://example.com/config.json`
|
|
45
|
+
3. **GitHub repos**: `@myrepo/config.json` (fetches from `n-p-x/myrepo`)
|
|
46
|
+
|
|
47
|
+
## Supported Config Formats
|
|
48
|
+
|
|
49
|
+
| Extension | Format | Parser |
|
|
50
|
+
|-----------|--------|---------|
|
|
51
|
+
| `.json` | JSON | Native JSON.parse |
|
|
52
|
+
| `.json5` | JSON5 | json5 |
|
|
53
|
+
| `.yml`, `.yaml` | YAML | js-yaml |
|
|
54
|
+
| `.toml` | TOML | toml |
|
|
55
|
+
| `.xml` | XML | fast-xml-parser |
|
|
56
|
+
|
|
57
|
+
## Supported Template Engines
|
|
58
|
+
|
|
59
|
+
| Extension | Engine | Library |
|
|
60
|
+
|-----------|--------|---------|
|
|
61
|
+
| `.hbs`, `.handlebars` | Handlebars | handlebars |
|
|
62
|
+
| `.ejs` | EJS | ejs |
|
|
63
|
+
| `.liquid` | Liquid | liquidjs |
|
|
64
|
+
| `.jinja`, `.j2` | Jinja | nunjucks |
|
|
65
|
+
|
|
66
|
+
## Examples
|
|
67
|
+
|
|
68
|
+
### Basic Usage
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# JSON config with Handlebars template
|
|
72
|
+
apparel config.json template.hbs output.txt
|
|
73
|
+
|
|
74
|
+
# YAML config with EJS template to stdout
|
|
75
|
+
apparel config.yml template.ejs
|
|
76
|
+
|
|
77
|
+
# Remote config with local template
|
|
78
|
+
apparel https://example.com/config.json template.hbs
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### GitHub Integration
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Fetch config from n-p-x/configs repo
|
|
85
|
+
apparel @configs/prod.json template.hbs
|
|
86
|
+
|
|
87
|
+
# Fetch both config and template from GitHub
|
|
88
|
+
apparel @configs/prod.json @templates/email.hbs output.html
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Example Files
|
|
92
|
+
|
|
93
|
+
#### Config (config.json)
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"name": "John Doe",
|
|
97
|
+
"email": "john@example.com",
|
|
98
|
+
"role": "Developer",
|
|
99
|
+
"skills": ["JavaScript", "TypeScript", "Node.js"]
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### Handlebars Template (template.hbs)
|
|
104
|
+
```handlebars
|
|
105
|
+
Hello {{name}},
|
|
106
|
+
|
|
107
|
+
Your role: {{role}}
|
|
108
|
+
Skills: {{#each skills}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Output
|
|
112
|
+
```
|
|
113
|
+
Hello John Doe,
|
|
114
|
+
|
|
115
|
+
Your role: Developer
|
|
116
|
+
Skills: JavaScript, TypeScript, Node.js
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Template Syntax Examples
|
|
120
|
+
|
|
121
|
+
### Handlebars
|
|
122
|
+
```handlebars
|
|
123
|
+
{{name}} - {{email}}
|
|
124
|
+
{{#each skills}}
|
|
125
|
+
- {{this}}
|
|
126
|
+
{{/each}}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### EJS
|
|
130
|
+
```ejs
|
|
131
|
+
<%= name %> - <%= email %>
|
|
132
|
+
<% skills.forEach(skill => { %>
|
|
133
|
+
- <%= skill %>
|
|
134
|
+
<% }); %>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Liquid
|
|
138
|
+
```liquid
|
|
139
|
+
{{ name }} - {{ email }}
|
|
140
|
+
{% for skill in skills %}
|
|
141
|
+
- {{ skill }}
|
|
142
|
+
{% endfor %}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Jinja/Nunjucks
|
|
146
|
+
```jinja
|
|
147
|
+
{{ name }} - {{ email }}
|
|
148
|
+
{% for skill in skills %}
|
|
149
|
+
- {{ skill }}
|
|
150
|
+
{% endfor %}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Error Handling
|
|
154
|
+
|
|
155
|
+
The script provides detailed error messages for:
|
|
156
|
+
- File not found or network errors
|
|
157
|
+
- Invalid config file format
|
|
158
|
+
- Template rendering errors
|
|
159
|
+
- Missing required arguments
|
|
160
|
+
|
|
161
|
+
## Development
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Install dependencies
|
|
165
|
+
npm install
|
|
166
|
+
|
|
167
|
+
# Build the project
|
|
168
|
+
npm run build
|
|
169
|
+
|
|
170
|
+
# Test locally
|
|
171
|
+
node dist/index.js examples/config.json examples/template.hbs
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## License
|
|
175
|
+
|
|
176
|
+
ISC
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{Command as h}from"commander";import{promises as f}from"fs";import m from"js-yaml";import*as d from"toml";import g from"json5";import{XMLParser as y}from"fast-xml-parser";import p from"handlebars";import{Liquid as $}from"liquidjs";import x from"ejs";import w from"nunjucks";import s from"path";import{fileURLToPath as b}from"url";var j=b(import.meta.url),U=s.dirname(j);w.configure({autoescape:!1});async function l(r){let e=await fetch(r);if(!e.ok)throw new Error(`Failed to fetch ${r}: ${e.status} ${e.statusText}`);return e.text()}async function u(r){if(r.startsWith("@")){let[,e,...t]=r.split("/"),o=t.join("/"),a=`https://raw.githubusercontent.com/n-p-x/${e}/main/${o}`;return l(a)}return r.startsWith("http://")||r.startsWith("https://")?l(r):f.readFile(r,"utf8")}function L(r,e){let t=s.extname(e).toLowerCase();try{switch(t){case".json":return JSON.parse(r);case".json5":return g.parse(r);case".yml":case".yaml":return m.load(r);case".toml":return d.parse(r);case".xml":return new y({ignoreAttributes:!1,attributeNamePrefix:"@_",parseAttributeValue:!0}).parse(r);default:try{return JSON.parse(r)}catch{return m.load(r)}}}catch(o){throw new Error(`Failed to parse config file ${e}: ${o.message}`)}}async function F(r,e,t){let o=s.extname(e).toLowerCase();try{switch(o){case".hbs":case".handlebars":return p.compile(r)(t);case".liquid":return new $().parseAndRender(r,t);case".ejs":return x.render(r,t);case".jinja":case".j2":return w.renderString(r,t);default:return p.compile(r)(t)}}catch(a){throw new Error(`Failed to render template ${e}: ${a.message}`)}}async function T(){let r=new h;r.name("apparel").description("Fill templates with variables from config files").version("0.0.1").argument("<src>","Config file path (local file, URL, or @repo/file format)").argument("<tpl>","Template file path (local file, URL, or @repo/file format)").argument("[dst]","Output file path (optional, defaults to stdout)").action(async(e,t,o)=>{try{console.error(`Loading config from: ${e}`);let a=await u(e),n=L(a,e);console.error(`Loading template from: ${t}`);let i=await u(t);console.error("Rendering template...");let c=await F(i,t,n);o?(await f.writeFile(o,c,"utf8"),console.error(`Output written to: ${o}`)):process.stdout.write(c)}catch(a){console.error(`Error: ${a.message}`),process.exit(1)}}),await r.parseAsync()}(async()=>await T())();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<config>
|
|
3
|
+
<name>John Doe</name>
|
|
4
|
+
<email>john.doe@example.com</email>
|
|
5
|
+
<role>Software Engineer</role>
|
|
6
|
+
<company>Tech Corp</company>
|
|
7
|
+
<skills>
|
|
8
|
+
<skill>JavaScript</skill>
|
|
9
|
+
<skill>TypeScript</skill>
|
|
10
|
+
<skill>Node.js</skill>
|
|
11
|
+
<skill>React</skill>
|
|
12
|
+
</skills>
|
|
13
|
+
<experience>5</experience>
|
|
14
|
+
</config>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: John Doe
|
|
2
|
+
email: john.doe@example.com
|
|
3
|
+
role: Software Engineer
|
|
4
|
+
company: Tech Corp
|
|
5
|
+
experience: 5 years
|
|
6
|
+
|
|
7
|
+
Skills:
|
|
8
|
+
- JavaScript
|
|
9
|
+
- TypeScript
|
|
10
|
+
- Node.js
|
|
11
|
+
- React
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
Hello John Doe,
|
|
16
|
+
|
|
17
|
+
Thank you for your interest in joining Tech Corp as a Software Engineer.
|
|
18
|
+
With 5 years of experience and your skills in JavaScript, TypeScript, Node.js, React,
|
|
19
|
+
you would be a great fit for our team.
|
|
20
|
+
|
|
21
|
+
Best regards,
|
|
22
|
+
HR Team
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Hello <%= name %>,
|
|
2
|
+
|
|
3
|
+
Welcome to <%= company %>! We're excited to have you join our team as a <%= role %>.
|
|
4
|
+
|
|
5
|
+
Your profile:
|
|
6
|
+
- Email: <%= email %>
|
|
7
|
+
- Experience: <%= experience %> years
|
|
8
|
+
- Skills: <% skills.forEach((skill, index) => { %>
|
|
9
|
+
• <%= skill %><% if (index < skills.length - 1) { %>,<% } %>
|
|
10
|
+
<% }); %>
|
|
11
|
+
|
|
12
|
+
We look forward to working with you!
|
|
13
|
+
|
|
14
|
+
Best regards,
|
|
15
|
+
The <%= company %> Team
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: {{name}}
|
|
2
|
+
email: {{email}}
|
|
3
|
+
role: {{role}}
|
|
4
|
+
company: {{company}}
|
|
5
|
+
experience: {{experience}} years
|
|
6
|
+
|
|
7
|
+
Skills:
|
|
8
|
+
{{#each skills}}
|
|
9
|
+
- {{this}}
|
|
10
|
+
{{/each}}
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Hello {{name}},
|
|
15
|
+
|
|
16
|
+
Thank you for your interest in joining {{company}} as a {{role}}.
|
|
17
|
+
With {{experience}} years of experience and your skills in {{#each skills}}{{this}}{{#unless @last}}, {{/unless}}{{/each}},
|
|
18
|
+
you would be a great fit for our team.
|
|
19
|
+
|
|
20
|
+
Best regards,
|
|
21
|
+
HR Team
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: {{ name }}
|
|
2
|
+
email: {{ email }}
|
|
3
|
+
role: {{ role }}
|
|
4
|
+
company: {{ company }}
|
|
5
|
+
experience: {{ experience }} years
|
|
6
|
+
|
|
7
|
+
Skills:
|
|
8
|
+
{% for skill in skills %}
|
|
9
|
+
- {{ skill }}
|
|
10
|
+
{% endfor %}
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Hello {{ name }},
|
|
15
|
+
|
|
16
|
+
Thank you for your interest in joining {{ company }} as a {{ role }}.
|
|
17
|
+
With {{ experience }} years of experience and your skills in {% for skill in skills %}{{ skill }}{% if not loop.last %}, {% endif %}{% endfor %},
|
|
18
|
+
you would be a great fit for our team.
|
|
19
|
+
|
|
20
|
+
Best regards,
|
|
21
|
+
HR Team
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: {{ name }}
|
|
2
|
+
email: {{ email }}
|
|
3
|
+
role: {{ role }}
|
|
4
|
+
company: {{ company }}
|
|
5
|
+
experience: {{ experience }} years
|
|
6
|
+
|
|
7
|
+
Skills:
|
|
8
|
+
{% for skill in skills %}
|
|
9
|
+
- {{ skill }}
|
|
10
|
+
{% endfor %}
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Hello {{ name }},
|
|
15
|
+
|
|
16
|
+
Thank you for your interest in joining {{ company }} as a {{ role }}.
|
|
17
|
+
With {{ experience }} years of experience and your skills in {% for skill in skills %}{{ skill }}{% unless forloop.last %}, {% endunless %}{% endfor %},
|
|
18
|
+
you would be a great fit for our team.
|
|
19
|
+
|
|
20
|
+
Best regards,
|
|
21
|
+
HR Team
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "apparel",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Dress templates with variables.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": "./dist/index.js",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsup"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": "Asfandyar Sheikh",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"commander": "^14.0.3",
|
|
16
|
+
"ejs": "^4.0.1",
|
|
17
|
+
"fast-xml-parser": "^5.3.7",
|
|
18
|
+
"handlebars": "^4.7.8",
|
|
19
|
+
"js-yaml": "^4.1.1",
|
|
20
|
+
"json5": "^2.2.3",
|
|
21
|
+
"liquidjs": "^10.24.0",
|
|
22
|
+
"nunjucks": "^3.2.4",
|
|
23
|
+
"toml": "^3.0.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"tsup": "^8.5.1",
|
|
27
|
+
"typescript": "^5.9.3"
|
|
28
|
+
},
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/asfandyarsheikh/apparel.git"
|
|
32
|
+
}
|
|
33
|
+
}
|