@rse/nunjucks-cli 2.0.1 → 2.2.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/CHANGELOG.md +14 -0
- package/Dockerfile +8 -6
- package/README.md +19 -3
- package/nunjucks.md +21 -11
- package/nunjucks.ts +188 -156
- package/package.json +47 -41
- package/stx.conf +63 -31
- package/tsconfig.json +3 -3
- package/vite.mts +59 -0
- package/Dockerfile.mk +0 -104
- package/nunjucks.1 +0 -47
- package/nunjucks.js +0 -187
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
ChangeLog
|
|
3
3
|
=========
|
|
4
4
|
|
|
5
|
+
2.2.0 (2025-12-26)
|
|
6
|
+
------------------
|
|
7
|
+
|
|
8
|
+
- IMPROVEMENT: finally fix SEA packaging
|
|
9
|
+
- IMPROVEMENT: provide Docker container publishing
|
|
10
|
+
- CLEANUP: cleanup distribution archive packaging
|
|
11
|
+
|
|
12
|
+
2.1.0 (2025-12-26)
|
|
13
|
+
------------------
|
|
14
|
+
|
|
15
|
+
- REFACTOR: change option -e/--extension to option -p/--plugin
|
|
16
|
+
- IMPROVEMENT: add new option -e for loading custom .env files
|
|
17
|
+
- IMPROVEMENT: add new option -E for loading standard .env files
|
|
18
|
+
|
|
5
19
|
2.0.0 (2025-12-21)
|
|
6
20
|
------------------
|
|
7
21
|
|
package/Dockerfile
CHANGED
|
@@ -3,15 +3,19 @@
|
|
|
3
3
|
##
|
|
4
4
|
|
|
5
5
|
# build arguments (early)
|
|
6
|
-
ARG IMAGE_PREFIX=
|
|
6
|
+
ARG IMAGE_PREFIX=ghcr.io/rse/
|
|
7
7
|
ARG IMAGE_NAME=nunjucks-cli
|
|
8
|
-
ARG IMAGE_VERSION=2.
|
|
9
|
-
ARG IMAGE_RELEASE=
|
|
8
|
+
ARG IMAGE_VERSION=2.1.0
|
|
9
|
+
ARG IMAGE_RELEASE=20251226
|
|
10
10
|
ARG IMAGE_ALIAS=latest
|
|
11
11
|
|
|
12
12
|
# derive image from a certain base image
|
|
13
13
|
FROM node:24-alpine3.23
|
|
14
14
|
|
|
15
|
+
# link to Github repository
|
|
16
|
+
LABEL org.opencontainers.image.source=https://github.com/rse/nunjucks-cli
|
|
17
|
+
LABEL org.opencontainers.image.description="Nunjucks Template Rendering Command-Line Interface"
|
|
18
|
+
|
|
15
19
|
# add additional build tools
|
|
16
20
|
RUN apk update && \
|
|
17
21
|
apk upgrade
|
|
@@ -27,9 +31,7 @@ WORKDIR /app
|
|
|
27
31
|
ENV HOME=/app
|
|
28
32
|
|
|
29
33
|
# install tool
|
|
30
|
-
RUN npm install -g
|
|
31
|
-
@rse/nunjucks-cli@1.5.2 \
|
|
32
|
-
@rse/nunjucks-addons@1.0.8
|
|
34
|
+
RUN npm install -g @rse/nunjucks-cli
|
|
33
35
|
|
|
34
36
|
# cleanup Alpine
|
|
35
37
|
RUN rm -rf /var/cache/apk/*
|
package/README.md
CHANGED
|
@@ -48,6 +48,14 @@ $ npx --yes --package @rse/nunjucks-cli --package @rse/nunjucks-addons -- \
|
|
|
48
48
|
nunjucks -e @rse/nunjucks-addons [...]
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
Furthermore, instead of using NPM at all, you can also use Docker (at
|
|
52
|
+
least as long as you are working with stdin/stdout or perform the
|
|
53
|
+
corresponding bind-mounts):
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
$ docker run -i --rm ghcr.io/rse/nunjucks-cli [...] -
|
|
57
|
+
```
|
|
58
|
+
|
|
51
59
|
Command-Line Interface (CLI)
|
|
52
60
|
----------------------------
|
|
53
61
|
|
|
@@ -57,11 +65,13 @@ Short excerpt of the CLI options and arguments from the companion [Unix manpage]
|
|
|
57
65
|
$ nunjucks
|
|
58
66
|
[-h|--help]
|
|
59
67
|
[-V|--version]
|
|
68
|
+
[-e|--env <env-file>]
|
|
69
|
+
[-E|--envs]
|
|
60
70
|
[-c|--config <config-file>]
|
|
61
71
|
[-C|--option <key>=<value>]
|
|
62
72
|
[-d|--defines <context-file>]
|
|
63
73
|
[-D|--define <key>=<value>]
|
|
64
|
-
[-
|
|
74
|
+
[-p|--plugin <module-name>]
|
|
65
75
|
[-o|--output <output-file>|-]
|
|
66
76
|
<input-file>|-
|
|
67
77
|
```
|
|
@@ -70,6 +80,12 @@ $ nunjucks
|
|
|
70
80
|
Show usage help.
|
|
71
81
|
- `-V`|`--version`:<br/>
|
|
72
82
|
Show program version information.
|
|
83
|
+
- `-e`|`--env` *env-file*:<br/>
|
|
84
|
+
Load environment file with key/value definitions.
|
|
85
|
+
These can later be accessed with the global `env` variable.
|
|
86
|
+
- [`-E`|`--envs`]:<br/>
|
|
87
|
+
Automatically load environment files with key/value definitions
|
|
88
|
+
from all `.env` files in current and all parent directories.
|
|
73
89
|
- `-c`|`--config` `<config-file>`:<br/>
|
|
74
90
|
Load Nunjucks configuration YAML file.
|
|
75
91
|
- `-C`|`--option` `<key>=<value>`:<br/>
|
|
@@ -80,8 +96,8 @@ $ nunjucks
|
|
|
80
96
|
- `-D`|`--define` `<key>=<value>`:<br/>
|
|
81
97
|
Set context definition key/value.
|
|
82
98
|
Can occur multiple times.
|
|
83
|
-
- `-
|
|
84
|
-
Load Nunjucks JavaScript
|
|
99
|
+
- `-p`|`--plugin` `<module-name>`:<br/>
|
|
100
|
+
Load Nunjucks JavaScript plugin module (installed via NPM).
|
|
85
101
|
- `-o`|`--output` `<output-file>`|`-`:<br/>
|
|
86
102
|
Save output file (or stdout).
|
|
87
103
|
- `<input-file>`|`-`:<br/>
|
package/nunjucks.md
CHANGED
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
`nunjucks`
|
|
7
7
|
\[`-h`|`--help`\]
|
|
8
8
|
\[`-V`|`--version`\]
|
|
9
|
+
\[`-e`|`--env` *env-file*\]
|
|
10
|
+
\[`-E`|`--envs`\]
|
|
9
11
|
\[`-c`|`--config` *config-file*\]
|
|
10
12
|
\[`-C`|`--option` *key*=*value*\]
|
|
11
13
|
\[`-d`|`--defines` *context-file*\]
|
|
12
14
|
\[`-D`|`--define` *key*=*value*\]
|
|
13
|
-
\[`-
|
|
15
|
+
\[`-p`|`--plugin` *module-name*\]
|
|
14
16
|
\[`-o`|`--output` *output-file*|`-`\]
|
|
15
17
|
\[*input-file*|`-`\]
|
|
16
18
|
|
|
@@ -27,33 +29,41 @@ It optionally can load Nunjucks addons like the ones from the companion
|
|
|
27
29
|
|
|
28
30
|
The following top-level options and arguments exist:
|
|
29
31
|
|
|
30
|
-
- \[`-h`|`--help`\]
|
|
32
|
+
- \[`-h`|`--help`\]:
|
|
31
33
|
Show usage help.
|
|
32
34
|
|
|
33
|
-
- \[`-V`|`--version`\]
|
|
35
|
+
- \[`-V`|`--version`\]:
|
|
34
36
|
Show program version information.
|
|
35
37
|
|
|
36
|
-
- \[`-
|
|
38
|
+
- \[`-e`|`--env` *env-file*\]:
|
|
39
|
+
Load environment file with key/value definitions.
|
|
40
|
+
These can later be accessed with the global `env` variable.
|
|
41
|
+
|
|
42
|
+
- \[`-E`|`--envs`\]:
|
|
43
|
+
Automatically load environment files with key/value definitions
|
|
44
|
+
from all `.env` files in current and all parent directories.
|
|
45
|
+
|
|
46
|
+
- \[`-c`|`--config` *config-file*\]:
|
|
37
47
|
Load Nunjucks configuration YAML file.
|
|
38
48
|
|
|
39
|
-
- \[`-C`|`--option` *key*=*value*\]
|
|
49
|
+
- \[`-C`|`--option` *key*=*value*\]:
|
|
40
50
|
Set Nunjucks configuration option.
|
|
41
51
|
|
|
42
|
-
- \[`-d`|`--defines` *context-file*\]
|
|
52
|
+
- \[`-d`|`--defines` *context-file*\]:
|
|
43
53
|
Load context definition YAML file.
|
|
44
54
|
Can occur multiple times.
|
|
45
55
|
|
|
46
|
-
- \[`-D`|`--define` *key*=*value*\]
|
|
56
|
+
- \[`-D`|`--define` *key*=*value*\]:
|
|
47
57
|
Set context definition key/value.
|
|
48
58
|
Can occur multiple times.
|
|
49
59
|
|
|
50
|
-
- \[`-
|
|
51
|
-
Load Nunjucks JavaScript
|
|
60
|
+
- \[`-p`|`--plugin` *module-name*\]:
|
|
61
|
+
Load Nunjucks JavaScript plugin module (installed via NPM).
|
|
52
62
|
|
|
53
|
-
- \[`-o`|`--output` *output-file*|`-`\]
|
|
63
|
+
- \[`-o`|`--output` *output-file*|`-`\]:
|
|
54
64
|
Save output file (or stdout).
|
|
55
65
|
|
|
56
|
-
- \[`<input-file>`|`-`\]
|
|
66
|
+
- \[`<input-file>`|`-`\]:
|
|
57
67
|
Load input file (or stdin).
|
|
58
68
|
|
|
59
69
|
## EXAMPLE
|
package/nunjucks.ts
CHANGED
|
@@ -16,6 +16,11 @@ import chalk from "chalk"
|
|
|
16
16
|
import jsYAML from "js-yaml"
|
|
17
17
|
import nunjucks from "nunjucks"
|
|
18
18
|
import deepmerge from "deepmerge"
|
|
19
|
+
import dotenvx from "@dotenvx/dotenvx"
|
|
20
|
+
import * as findup from "find-up"
|
|
21
|
+
|
|
22
|
+
/* internal requirements */
|
|
23
|
+
import pkg from "./package.json" with { type: "json" }
|
|
19
24
|
|
|
20
25
|
/* type definitions */
|
|
21
26
|
type PackageInfo = {
|
|
@@ -38,196 +43,223 @@ type OptionsType = {
|
|
|
38
43
|
type CLIOptions = {
|
|
39
44
|
help: boolean
|
|
40
45
|
version: boolean
|
|
46
|
+
env: string[]
|
|
47
|
+
envs: boolean
|
|
41
48
|
config: string
|
|
42
49
|
option: string[]
|
|
43
50
|
defines: string[]
|
|
44
51
|
define: string[]
|
|
45
|
-
|
|
52
|
+
plugin: string[]
|
|
46
53
|
output: string
|
|
47
54
|
_: string[]
|
|
48
55
|
}
|
|
49
56
|
|
|
50
|
-
/*
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const program = new Command()
|
|
55
|
-
const reduceArray = (v: string, l: string[]) => l.concat([ v ])
|
|
56
|
-
program.name("nunjucks")
|
|
57
|
-
.description("Nunjucks Template Rendering Command-Line Interface")
|
|
58
|
-
.showHelpAfterError("hint: use option --help for usage information")
|
|
59
|
-
.option("-h, --help", "show usage help", false)
|
|
60
|
-
.option("-V, --version", "show program version information", false)
|
|
61
|
-
.option("-c, --config <config-file>", "load Nunjucks configuration YAML file", "")
|
|
62
|
-
.option("-C, --option <key>=<value>", "set Nunjucks configuration option", reduceArray, [])
|
|
63
|
-
.option("-d, --defines <context-file>", "load context definition YAML file", reduceArray, [])
|
|
64
|
-
.option("-D, --define <key>=<value>", "set context definition key/value", reduceArray, [])
|
|
65
|
-
.option("-e, --extension <module-name>", "load Nunjucks JavaScript extension module", reduceArray, [])
|
|
66
|
-
.option("-o, --output <output-file>", "save output file", "-")
|
|
67
|
-
.argument("[<input-file>]", "input file")
|
|
68
|
-
program.parse(process.argv)
|
|
69
|
-
const argv: CLIOptions = {
|
|
70
|
-
...program.opts(),
|
|
71
|
-
_: program.args
|
|
72
|
-
} as CLIOptions
|
|
73
|
-
|
|
74
|
-
/* handle special help request */
|
|
75
|
-
if (argv.help) {
|
|
76
|
-
console.log(program.helpInformation())
|
|
77
|
-
console.log("Example:\n $ echo \"Hello, {{ who }}!\" | nunjucks -Dwho=World -\n")
|
|
78
|
-
process.exit(0)
|
|
79
|
-
}
|
|
57
|
+
/* establish asynchronous environment */
|
|
58
|
+
;(async () => {
|
|
59
|
+
/* load my own information */
|
|
60
|
+
const my = pkg as PackageInfo
|
|
80
61
|
|
|
81
|
-
/*
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
62
|
+
/* parse command-line arguments */
|
|
63
|
+
const program = new Command()
|
|
64
|
+
const reduceArray = (v: string, l: string[]) => l.concat([ v ])
|
|
65
|
+
program.name("nunjucks")
|
|
66
|
+
.description("Nunjucks Template Rendering Command-Line Interface")
|
|
67
|
+
.showHelpAfterError("hint: use option --help for usage information")
|
|
68
|
+
.option("-h, --help", "show usage help", false)
|
|
69
|
+
.option("-V, --version", "show program version information", false)
|
|
70
|
+
.option("-e, --env <env-file>", "load environment key/value file", reduceArray, [])
|
|
71
|
+
.option("-E, --envs", "load all environment key/value files", false)
|
|
72
|
+
.option("-c, --config <config-file>", "load Nunjucks configuration YAML file", "")
|
|
73
|
+
.option("-C, --option <key>=<value>", "set Nunjucks configuration option", reduceArray, [])
|
|
74
|
+
.option("-d, --defines <context-file>", "load context definition YAML file", reduceArray, [])
|
|
75
|
+
.option("-D, --define <key>=<value>", "set context definition key/value", reduceArray, [])
|
|
76
|
+
.option("-p, --plugin <module-name>", "load Nunjucks JavaScript plugin module", reduceArray, [])
|
|
77
|
+
.option("-o, --output <output-file>", "save output file", "-")
|
|
78
|
+
.argument("[<input-file>]", "input file")
|
|
79
|
+
program.parse(process.argv)
|
|
80
|
+
const argv: CLIOptions = {
|
|
81
|
+
...program.opts(),
|
|
82
|
+
_: program.args
|
|
83
|
+
} as CLIOptions
|
|
89
84
|
|
|
90
|
-
/*
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
85
|
+
/* handle special help request */
|
|
86
|
+
if (argv.help) {
|
|
87
|
+
console.log(program.helpInformation())
|
|
88
|
+
console.log("Example:\n $ echo \"Hello, {{ who }}!\" | nunjucks -Dwho=World -\n")
|
|
89
|
+
process.exit(0)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* handle special version request */
|
|
93
|
+
if (argv.version) {
|
|
94
|
+
console.log(`${my.name} ${my.version} (Node.js ${process.versions.node}, Nunjucks: ${my.dependencies.nunjucks})`)
|
|
95
|
+
console.log(`${my.description}`)
|
|
96
|
+
console.log(`Copyright (c) 2019-2025 ${my.author.name} <${my.author.url}>`)
|
|
97
|
+
console.log(`Licensed under ${my.license} <http://spdx.org/licenses/${my.license}.html>`)
|
|
98
|
+
process.exit(0)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* read input file */
|
|
102
|
+
let input = ""
|
|
103
|
+
if (argv._.length > 1) {
|
|
104
|
+
console.error(chalk.red("nunjucks: ERROR: invalid number of arguments (zero or one input file expected)"))
|
|
105
|
+
process.exit(1)
|
|
106
|
+
}
|
|
107
|
+
let inputFile: string = argv._[0] ?? "-"
|
|
108
|
+
if (inputFile === "-") {
|
|
109
|
+
inputFile = "<stdin>"
|
|
110
|
+
process.stdin.setEncoding("utf-8")
|
|
111
|
+
const BUFSIZE = 256
|
|
112
|
+
const buf = Buffer.alloc(BUFSIZE)
|
|
113
|
+
while (true) {
|
|
114
|
+
let bytesRead = 0
|
|
115
|
+
try {
|
|
116
|
+
bytesRead = fs.readSync(process.stdin.fd, buf, 0, BUFSIZE, null)
|
|
117
|
+
}
|
|
118
|
+
catch (ex: any) {
|
|
119
|
+
if (ex.code === "EAGAIN") continue
|
|
120
|
+
else if (ex.code === "EOF") break
|
|
121
|
+
else throw ex
|
|
122
|
+
}
|
|
123
|
+
if (bytesRead === 0)
|
|
124
|
+
break
|
|
125
|
+
input += buf.toString("utf8", 0, bytesRead)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
if (!fs.existsSync(inputFile)) {
|
|
130
|
+
console.error(chalk.red(`nunjucks: ERROR: failed to find input file: "${inputFile}"`))
|
|
131
|
+
process.exit(1)
|
|
132
|
+
}
|
|
133
|
+
input = fs.readFileSync(inputFile, { encoding: "utf8" })
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* provide context variables for template */
|
|
137
|
+
let context: ContextType = {}
|
|
138
|
+
for (const define of argv.defines) {
|
|
104
139
|
try {
|
|
105
|
-
|
|
140
|
+
context = deepmerge(context, jsYAML.load(fs.readFileSync(define, { encoding: "utf8" })) as ContextType)
|
|
106
141
|
}
|
|
107
142
|
catch (ex: any) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
else throw ex
|
|
143
|
+
console.error(chalk.red(`nunjucks: ERROR: failed to load context YAML file: ${ex.toString()}`))
|
|
144
|
+
process.exit(1)
|
|
111
145
|
}
|
|
112
|
-
if (bytesRead === 0)
|
|
113
|
-
break
|
|
114
|
-
input += buf.toString("utf8", 0, bytesRead)
|
|
115
146
|
}
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
if (!fs.existsSync(inputFile)) {
|
|
119
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to find input file: ${inputFile}`))
|
|
120
|
-
process.exit(1)
|
|
121
|
-
}
|
|
122
|
-
input = fs.readFileSync(inputFile, { encoding: "utf8" })
|
|
123
|
-
}
|
|
124
147
|
|
|
125
|
-
/*
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
148
|
+
/* load environment variables from all default files */
|
|
149
|
+
if (argv.envs) {
|
|
150
|
+
const files = findup.findUpMultipleSync(".env")
|
|
151
|
+
if (files.length > 0)
|
|
152
|
+
dotenvx.config({ path: files, quiet: true })
|
|
130
153
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
154
|
+
|
|
155
|
+
/* load environment variables from environment files */
|
|
156
|
+
if (argv.env.length > 0) {
|
|
157
|
+
for (const env of argv.env) {
|
|
158
|
+
if (!fs.existsSync(env)) {
|
|
159
|
+
console.error(chalk.red(`nunjucks: ERROR: environment file not found: "${env}"`))
|
|
160
|
+
process.exit(1)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
dotenvx.config({ path: argv.env, quiet: true })
|
|
134
164
|
}
|
|
135
|
-
}
|
|
136
165
|
|
|
137
|
-
/* expose environment variables to template */
|
|
138
|
-
context.env = process.env
|
|
139
|
-
|
|
140
|
-
/* add context defines */
|
|
141
|
-
argv.define.forEach((define: string) => {
|
|
142
|
-
const match = define.match(/^([^=]+)(?:=(.*))?$/)
|
|
143
|
-
if (!match)
|
|
144
|
-
return
|
|
145
|
-
let [ , key, val ]: (string | undefined)[] = match
|
|
146
|
-
if (!key)
|
|
147
|
-
return
|
|
148
|
-
if (val === undefined)
|
|
149
|
-
val = "true"
|
|
150
|
-
context[key] = val
|
|
151
|
-
})
|
|
166
|
+
/* expose environment variables to template */
|
|
167
|
+
context.env = process.env
|
|
152
168
|
|
|
153
|
-
/*
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
169
|
+
/* add context defines */
|
|
170
|
+
argv.define.forEach((define: string) => {
|
|
171
|
+
const match = define.match(/^([^=]+)(?:=(.*))?$/)
|
|
172
|
+
if (!match)
|
|
173
|
+
return
|
|
174
|
+
let [ , key, val ]: (string | undefined)[] = match
|
|
175
|
+
if (!key)
|
|
176
|
+
return
|
|
177
|
+
if (val === undefined)
|
|
178
|
+
val = "true"
|
|
179
|
+
context[key] = val
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
/* determine Nunjucks options */
|
|
183
|
+
let options: OptionsType = {}
|
|
184
|
+
if (argv.config) {
|
|
185
|
+
try {
|
|
186
|
+
options = jsYAML.load(fs.readFileSync(argv.config, { encoding: "utf8" })) as OptionsType
|
|
187
|
+
}
|
|
188
|
+
catch (ex: any) {
|
|
189
|
+
console.error(chalk.red(`nunjucks: ERROR: failed to load options YAML file: ${ex.toString()}`))
|
|
190
|
+
process.exit(1)
|
|
191
|
+
}
|
|
158
192
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
193
|
+
if (argv.option.length > 0)
|
|
194
|
+
options = Object.assign(options, argv.option)
|
|
195
|
+
options = {
|
|
196
|
+
autoescape: false,
|
|
197
|
+
throwOnUndefined: false,
|
|
198
|
+
trimBlocks: true,
|
|
199
|
+
lstripBlocks: true,
|
|
200
|
+
watch: false,
|
|
201
|
+
noCache: true,
|
|
202
|
+
...options
|
|
162
203
|
}
|
|
163
|
-
}
|
|
164
|
-
if (argv.option.length > 0)
|
|
165
|
-
options = Object.assign(options, argv.option)
|
|
166
|
-
options = {
|
|
167
|
-
autoescape: false,
|
|
168
|
-
throwOnUndefined: false,
|
|
169
|
-
trimBlocks: true,
|
|
170
|
-
lstripBlocks: true,
|
|
171
|
-
watch: false,
|
|
172
|
-
noCache: true,
|
|
173
|
-
...options
|
|
174
|
-
}
|
|
175
204
|
|
|
176
|
-
/* configure environment */
|
|
177
|
-
const env = nunjucks.configure(inputFile, options)
|
|
205
|
+
/* configure environment */
|
|
206
|
+
const env = nunjucks.configure(inputFile, options)
|
|
178
207
|
|
|
179
|
-
/* load external
|
|
180
|
-
for (const
|
|
181
|
-
|
|
182
|
-
|
|
208
|
+
/* load external plugin modules */
|
|
209
|
+
for (const plugin of argv.plugin) {
|
|
210
|
+
let modpath: string | null = path.resolve(plugin)
|
|
211
|
+
if (!fs.existsSync(modpath)) {
|
|
212
|
+
try {
|
|
213
|
+
const require = createRequire(import.meta.url)
|
|
214
|
+
modpath = require.resolve(plugin)
|
|
215
|
+
}
|
|
216
|
+
catch (_ex) {
|
|
217
|
+
modpath = null
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (modpath === null) {
|
|
221
|
+
console.error(chalk.red(`nunjucks: ERROR: failed to find plugin module: ${plugin}`))
|
|
222
|
+
process.exit(1)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/* dynamically import the module */
|
|
226
|
+
let mod: any
|
|
183
227
|
try {
|
|
184
|
-
|
|
185
|
-
|
|
228
|
+
mod = await import(modpath)
|
|
229
|
+
|
|
230
|
+
/* handle both default and named exports */
|
|
231
|
+
mod = mod.default ?? mod
|
|
186
232
|
}
|
|
187
|
-
catch (
|
|
188
|
-
|
|
233
|
+
catch (ex: any) {
|
|
234
|
+
console.error(chalk.red(`nunjucks: ERROR: failed to load plugin module: ${ex.toString()}`))
|
|
235
|
+
process.exit(1)
|
|
189
236
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
237
|
+
if (!(mod !== null && typeof mod === "function")) {
|
|
238
|
+
console.error(chalk.red(`nunjucks: ERROR: failed to call plugin file: "${modpath}"`))
|
|
239
|
+
process.exit(1)
|
|
240
|
+
}
|
|
241
|
+
mod(env)
|
|
194
242
|
}
|
|
195
243
|
|
|
196
|
-
/*
|
|
197
|
-
let
|
|
244
|
+
/* render Nunjucks template */
|
|
245
|
+
let output: string
|
|
198
246
|
try {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
/* handle both default and named exports */
|
|
202
|
-
mod = mod.default ?? mod
|
|
247
|
+
output = env.renderString(input, context)
|
|
203
248
|
}
|
|
204
249
|
catch (ex: any) {
|
|
205
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to
|
|
206
|
-
process.exit(1)
|
|
207
|
-
}
|
|
208
|
-
if (!(mod !== null && typeof mod === "function")) {
|
|
209
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to call extension file: ${modpath}`))
|
|
250
|
+
console.error(chalk.red(`nunjucks: ERROR: failed to render template: ${ex.toString()}`))
|
|
210
251
|
process.exit(1)
|
|
211
252
|
}
|
|
212
|
-
mod(env)
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/* render Nunjucks template */
|
|
216
|
-
let output: string
|
|
217
|
-
try {
|
|
218
|
-
output = env.renderString(input, context)
|
|
219
|
-
}
|
|
220
|
-
catch (ex: any) {
|
|
221
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to render template: ${ex.toString()}`))
|
|
222
|
-
process.exit(1)
|
|
223
|
-
}
|
|
224
253
|
|
|
225
|
-
/* write output */
|
|
226
|
-
if (argv.output === "-")
|
|
227
|
-
|
|
228
|
-
else
|
|
229
|
-
|
|
254
|
+
/* write output */
|
|
255
|
+
if (argv.output === "-")
|
|
256
|
+
process.stdout.write(output)
|
|
257
|
+
else
|
|
258
|
+
fs.writeFileSync(argv.output, output, { encoding: "utf8" })
|
|
230
259
|
|
|
231
|
-
/* die gracefully */
|
|
232
|
-
process.exit(0)
|
|
260
|
+
/* die gracefully */
|
|
261
|
+
process.exit(0)
|
|
262
|
+
})().catch((err: any) => {
|
|
263
|
+
console.error(chalk.red(`nunjucks: ERROR: ${err.toString()}`))
|
|
264
|
+
})
|
|
233
265
|
|
package/package.json
CHANGED
|
@@ -1,60 +1,66 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name":
|
|
3
|
-
"publishConfig":
|
|
4
|
-
"version":
|
|
5
|
-
"stdver":
|
|
6
|
-
"description":
|
|
2
|
+
"name": "@rse/nunjucks-cli",
|
|
3
|
+
"publishConfig": { "access": "public" },
|
|
4
|
+
"version": "2.2.0",
|
|
5
|
+
"stdver": "2.2.0-GA",
|
|
6
|
+
"description": "Nunjucks Template Rendering Command-Line Interface",
|
|
7
7
|
"author": {
|
|
8
|
-
"name":
|
|
9
|
-
"email":
|
|
10
|
-
"url":
|
|
8
|
+
"name": "Dr. Ralf S. Engelschall",
|
|
9
|
+
"email": "rse@engelschall.com",
|
|
10
|
+
"url": "http://engelschall.com"
|
|
11
11
|
},
|
|
12
|
-
"license":
|
|
12
|
+
"license": "MIT",
|
|
13
13
|
"repository": {
|
|
14
|
-
"type":
|
|
15
|
-
"url":
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/rse/nunjucks-cli.git"
|
|
16
16
|
},
|
|
17
17
|
"bugs": {
|
|
18
|
-
"url":
|
|
18
|
+
"url": "http://github.com/rse/nunjucks-cli/issues"
|
|
19
19
|
},
|
|
20
20
|
"bin": {
|
|
21
|
-
"nunjucks":
|
|
21
|
+
"nunjucks": "dst-stage1/nunjucks.js"
|
|
22
22
|
},
|
|
23
|
-
"man":
|
|
24
|
-
"type":
|
|
23
|
+
"man": "dst-stage1/nunjucks.1",
|
|
24
|
+
"type": "module",
|
|
25
25
|
"engines": {
|
|
26
|
-
"node":
|
|
26
|
+
"node": ">=22.18.0"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"nunjucks":
|
|
30
|
-
"chalk":
|
|
31
|
-
"commander":
|
|
32
|
-
"js-yaml":
|
|
33
|
-
"deepmerge":
|
|
29
|
+
"nunjucks": "3.2.4",
|
|
30
|
+
"chalk": "5.6.2",
|
|
31
|
+
"commander": "14.0.2",
|
|
32
|
+
"js-yaml": "4.1.1",
|
|
33
|
+
"deepmerge": "4.3.1",
|
|
34
|
+
"@dotenvx/dotenvx": "1.51.2",
|
|
35
|
+
"find-up": "8.0.0"
|
|
34
36
|
},
|
|
35
37
|
"devDependencies": {
|
|
36
|
-
"eslint":
|
|
37
|
-
"@eslint/js":
|
|
38
|
-
"neostandard":
|
|
39
|
-
"eslint-plugin-promise":
|
|
40
|
-
"eslint-plugin-import":
|
|
41
|
-
"eslint-plugin-n":
|
|
42
|
-
"globals":
|
|
43
|
-
"remark-cli":
|
|
44
|
-
"remark":
|
|
45
|
-
"remark-man":
|
|
46
|
-
"typescript":
|
|
47
|
-
"typescript-eslint":
|
|
48
|
-
"@rse/stx":
|
|
49
|
-
"shx":
|
|
50
|
-
"@yao-pkg/pkg":
|
|
38
|
+
"eslint": "9.39.2",
|
|
39
|
+
"@eslint/js": "9.39.2",
|
|
40
|
+
"neostandard": "0.12.2",
|
|
41
|
+
"eslint-plugin-promise": "7.2.1",
|
|
42
|
+
"eslint-plugin-import": "2.32.0",
|
|
43
|
+
"eslint-plugin-n": "17.23.1",
|
|
44
|
+
"globals": "16.5.0",
|
|
45
|
+
"remark-cli": "12.0.1",
|
|
46
|
+
"remark": "15.0.1",
|
|
47
|
+
"remark-man": "9.0.0",
|
|
48
|
+
"typescript": "5.9.3",
|
|
49
|
+
"typescript-eslint": "8.50.1",
|
|
50
|
+
"@rse/stx": "1.1.4",
|
|
51
|
+
"shx": "0.4.0",
|
|
52
|
+
"@yao-pkg/pkg": "6.11.0",
|
|
53
|
+
"vite": "7.3.0",
|
|
54
|
+
"@wroud/vite-plugin-tsc": "0.12.2",
|
|
55
|
+
"rollup-plugin-node-externals": "8.1.2",
|
|
56
|
+
"terser": "5.44.1",
|
|
51
57
|
|
|
52
|
-
"@types/node":
|
|
53
|
-
"@types/js-yaml":
|
|
54
|
-
"@types/nunjucks":
|
|
58
|
+
"@types/node": "25.0.3",
|
|
59
|
+
"@types/js-yaml": "4.0.9",
|
|
60
|
+
"@types/nunjucks": "3.2.6"
|
|
55
61
|
},
|
|
56
62
|
"scripts": {
|
|
57
|
-
"start":
|
|
58
|
-
"test":
|
|
63
|
+
"start": "stx -v4 -c stx.conf",
|
|
64
|
+
"test": "npm start test"
|
|
59
65
|
}
|
|
60
66
|
}
|
package/stx.conf
CHANGED
|
@@ -11,28 +11,47 @@ lint
|
|
|
11
11
|
|
|
12
12
|
# build JavaScript from TypeScript
|
|
13
13
|
build
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# build manual page
|
|
17
|
-
man
|
|
18
|
-
remark --quiet --use remark-man --output nunjucks.1 nunjucks.md
|
|
14
|
+
vite --config vite.mts build --mode production &&
|
|
15
|
+
remark --quiet --use remark-man --output dst-stage1/nunjucks.man nunjucks.md
|
|
19
16
|
|
|
20
17
|
# execute simple smole test
|
|
21
18
|
test : build
|
|
22
19
|
echo 'Hello, {{who}}!' | node nunjucks.js -D who=world -
|
|
23
20
|
|
|
24
|
-
# build all-in-one packages
|
|
25
|
-
build:pkg [hostname=en4.*]
|
|
26
|
-
|
|
27
21
|
# package distribution archives
|
|
28
|
-
package :
|
|
29
|
-
|
|
22
|
+
package : package:docker package:sea [hostname=en4.*]
|
|
23
|
+
|
|
24
|
+
# package as Docker container image
|
|
25
|
+
package:docker [hostname=en4.*]
|
|
26
|
+
IMAGE_PREFIX=`egrep "ARG.*IMAGE_PREFIX" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
27
|
+
IMAGE_NAME=`egrep "ARG.*IMAGE_NAME" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
28
|
+
IMAGE_VERSION=`egrep "ARG.*IMAGE_VERSION" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
29
|
+
IMAGE_RELEASE=`egrep "ARG.*IMAGE_RELEASE" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
30
|
+
IMAGE_ALIAS=`egrep "ARG.*IMAGE_ALIAS" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
31
|
+
docker buildx build \
|
|
32
|
+
--progress plain \
|
|
33
|
+
--pull \
|
|
34
|
+
--no-cache \
|
|
35
|
+
--platform linux/amd64,linux/arm64 \
|
|
36
|
+
-t $IMAGE_PREFIX$IMAGE_NAME:$IMAGE_ALIAS \
|
|
37
|
+
-t $IMAGE_PREFIX$IMAGE_NAME:$IMAGE_VERSION \
|
|
38
|
+
-t $IMAGE_PREFIX$IMAGE_NAME:$IMAGE_VERSION-$IMAGE_RELEASE \
|
|
39
|
+
-f Dockerfile . && \
|
|
40
|
+
docker image ls $IMAGE_PREFIX$IMAGE_NAME:$IMAGE_VERSION-$IMAGE_RELEASE
|
|
41
|
+
|
|
42
|
+
# package as Single Excecutable Application (SEA)
|
|
43
|
+
package:sea [hostname=en4.*]
|
|
44
|
+
rm -rf dst-stage3 && \
|
|
45
|
+
mkdir dst-stage3 && \
|
|
46
|
+
cd dst-stage3 && \
|
|
47
|
+
VERSION=`sed -n '/"version":/ s/.*: *"\(.*\)".*/\1/p' ../package.json` && \
|
|
30
48
|
targets="node24-linux-x64,node24-linux-arm64" && \
|
|
31
49
|
targets="$targets,node24-win-x64,node24-win-arm64" && \
|
|
32
50
|
targets="$targets,node24-macos-x64,node24-macos-arm64" && \
|
|
33
|
-
sed -e 's;@rse/nunjucks-cli;nunjucks;'
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
sed -e 's;@rse/nunjucks-cli;nunjucks;' -e '/"type"/d' <../package.json >package.json && \
|
|
52
|
+
cp ../dst-stage2/nunjucks.cjs nunjucks.cjs && \
|
|
53
|
+
cp ../dst-stage1/nunjucks.man nunjucks.man && \
|
|
54
|
+
pkg --public --no-bytecode -c package.json -t "$targets" nunjucks.cjs && \
|
|
36
55
|
shx mv nunjucks-linux-x64 nunjucks-lnx-x64 && \
|
|
37
56
|
shx mv nunjucks-linux-arm64 nunjucks-lnx-a64 && \
|
|
38
57
|
shx mv nunjucks-win-x64.exe nunjucks-win-x64.exe && \
|
|
@@ -46,20 +65,20 @@ package : build build:pkg [hostname=en4.*]
|
|
|
46
65
|
mkdir -p nunjucks-$VERSION-mac-a64/ && \
|
|
47
66
|
mkdir -p nunjucks-$VERSION-lnx-x64/ && \
|
|
48
67
|
mkdir -p nunjucks-$VERSION-lnx-a64/ && \
|
|
49
|
-
cp -p nunjucks.
|
|
68
|
+
cp -p nunjucks.cjs nunjucks-$VERSION/nunjucks.cjs && \
|
|
50
69
|
cp -p nunjucks-win-x64.exe nunjucks-$VERSION-win-x64/nunjucks.exe && \
|
|
51
70
|
cp -p nunjucks-win-a64.exe nunjucks-$VERSION-win-a64/nunjucks.exe && \
|
|
52
71
|
cp -p nunjucks-mac-x64 nunjucks-$VERSION-mac-x64/nunjucks && \
|
|
53
72
|
cp -p nunjucks-mac-a64 nunjucks-$VERSION-mac-a64/nunjucks && \
|
|
54
73
|
cp -p nunjucks-lnx-x64 nunjucks-$VERSION-lnx-x64/nunjucks && \
|
|
55
74
|
cp -p nunjucks-lnx-a64 nunjucks-$VERSION-lnx-a64/nunjucks && \
|
|
56
|
-
cp -p nunjucks.
|
|
57
|
-
cp -p nunjucks.
|
|
58
|
-
cp -p nunjucks.
|
|
59
|
-
cp -p nunjucks.
|
|
60
|
-
cp -p nunjucks.
|
|
61
|
-
cp -p nunjucks.
|
|
62
|
-
cp -p nunjucks.
|
|
75
|
+
cp -p nunjucks.man nunjucks-$VERSION/nunjucks.man && \
|
|
76
|
+
cp -p nunjucks.man nunjucks-$VERSION-win-x64/nunjucks.man && \
|
|
77
|
+
cp -p nunjucks.man nunjucks-$VERSION-win-a64/nunjucks.man && \
|
|
78
|
+
cp -p nunjucks.man nunjucks-$VERSION-mac-x64/nunjucks.man && \
|
|
79
|
+
cp -p nunjucks.man nunjucks-$VERSION-mac-a64/nunjucks.man && \
|
|
80
|
+
cp -p nunjucks.man nunjucks-$VERSION-lnx-x64/nunjucks.man && \
|
|
81
|
+
cp -p nunjucks.man nunjucks-$VERSION-lnx-a64/nunjucks.man && \
|
|
63
82
|
zip -9 -r nunjucks-$VERSION.zip nunjucks-$VERSION/ && \
|
|
64
83
|
zip -9 -r nunjucks-$VERSION-win-x64.zip nunjucks-$VERSION-win-x64/ && \
|
|
65
84
|
zip -9 -r nunjucks-$VERSION-win-a64.zip nunjucks-$VERSION-win-a64/ && \
|
|
@@ -69,24 +88,37 @@ package : build build:pkg [hostname=en4.*]
|
|
|
69
88
|
zip -9 -r nunjucks-$VERSION-lnx-a64.zip nunjucks-$VERSION-lnx-a64/
|
|
70
89
|
|
|
71
90
|
# publish distribution archives
|
|
72
|
-
publish :
|
|
91
|
+
publish : publish:docker publish:sea [hostname=en4.*]
|
|
92
|
+
|
|
93
|
+
# publish Docker container image
|
|
94
|
+
publish:docker [hostname=en4.*]
|
|
95
|
+
IMAGE_PREFIX=`egrep "ARG.*IMAGE_PREFIX" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
96
|
+
IMAGE_NAME=`egrep "ARG.*IMAGE_NAME" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
97
|
+
IMAGE_VERSION=`egrep "ARG.*IMAGE_VERSION" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
98
|
+
IMAGE_RELEASE=`egrep "ARG.*IMAGE_RELEASE" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
99
|
+
IMAGE_ALIAS=`egrep "ARG.*IMAGE_ALIAS" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
100
|
+
docker push $IMAGE_PREFIX$IMAGE_NAME:$IMAGE_VERSION-$IMAGE_RELEASE && \
|
|
101
|
+
docker push $IMAGE_PREFIX$IMAGE_NAME:$IMAGE_VERSION && \
|
|
102
|
+
docker push $IMAGE_PREFIX$IMAGE_NAME:$IMAGE_ALIAS
|
|
103
|
+
|
|
104
|
+
# publish Single Excecutable Application (SEA)
|
|
105
|
+
publish:sea [hostname=en4.*]
|
|
73
106
|
VERSION=`sed -n '/"version":/ s/.*: *"\(.*\)".*/\1/p' package.json` && \
|
|
74
107
|
V=`echo "$VERSION" | sed -e 's;\.;\\.;g'` && \
|
|
75
108
|
sed -n -e "/^${V} /, /^[0-9]\\./ { /^${V} /p; /^[0-9]\\./!p; }" <CHANGELOG.md >.notes.md && \
|
|
76
109
|
gh release create --title "Nunjucks $VERSION" --notes-file .notes.md --verify-tag $VERSION \
|
|
77
|
-
nunjucks-$VERSION.zip \
|
|
78
|
-
nunjucks-$VERSION-win-x64.zip \
|
|
79
|
-
nunjucks-$VERSION-win-a64.zip \
|
|
80
|
-
nunjucks-$VERSION-mac-x64.zip \
|
|
81
|
-
nunjucks-$VERSION-mac-a64.zip \
|
|
82
|
-
nunjucks-$VERSION-lnx-x64.zip \
|
|
83
|
-
nunjucks-$VERSION-lnx-a64.zip && \
|
|
110
|
+
dst-stage3/nunjucks-$VERSION.zip \
|
|
111
|
+
dst-stage3/nunjucks-$VERSION-win-x64.zip \
|
|
112
|
+
dst-stage3/nunjucks-$VERSION-win-a64.zip \
|
|
113
|
+
dst-stage3/nunjucks-$VERSION-mac-x64.zip \
|
|
114
|
+
dst-stage3/nunjucks-$VERSION-mac-a64.zip \
|
|
115
|
+
dst-stage3/nunjucks-$VERSION-lnx-x64.zip \
|
|
116
|
+
dst-stage3/nunjucks-$VERSION-lnx-a64.zip && \
|
|
84
117
|
rm -f .notes.md
|
|
85
118
|
|
|
86
119
|
# remove all generated artifacts
|
|
87
120
|
clean
|
|
88
|
-
shx rm -
|
|
89
|
-
shx rm -rf nunjucks-*.zip
|
|
121
|
+
shx rm -rf dst-stage*
|
|
90
122
|
|
|
91
123
|
# remove all generated artifacts
|
|
92
124
|
distclean: clean
|
package/tsconfig.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "ES2024",
|
|
4
|
-
"module": "
|
|
4
|
+
"module": "nodenext",
|
|
5
5
|
"lib": [ "ES2024" ],
|
|
6
|
-
"moduleResolution": "
|
|
6
|
+
"moduleResolution": "nodenext",
|
|
7
7
|
"resolveJsonModule": true,
|
|
8
8
|
"declaration": false,
|
|
9
9
|
"allowSyntheticDefaultImports": true,
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"forceConsistentCasingInFileNames": true,
|
|
12
12
|
"strict": true,
|
|
13
13
|
"skipLibCheck": true,
|
|
14
|
-
"outDir": "
|
|
14
|
+
"outDir": "dst-stage1",
|
|
15
15
|
"types": [ "node" ]
|
|
16
16
|
},
|
|
17
17
|
"include": [
|
package/vite.mts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** nunjucks -- Nunjucks Template Rendering Command-Line Interface
|
|
3
|
+
** Copyright (c) 2019-2025 Dr. Ralf S. Engelschall <http://engelschall.com>
|
|
4
|
+
** Licensed under MIT <http://spdx.org/licenses/MIT.html>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as Vite from "vite"
|
|
8
|
+
import { tscPlugin } from "@wroud/vite-plugin-tsc"
|
|
9
|
+
import nodeExternals from "rollup-plugin-node-externals"
|
|
10
|
+
|
|
11
|
+
export default Vite.defineConfig(({ command, mode }) => ({
|
|
12
|
+
logLevel: "info",
|
|
13
|
+
appType: "custom",
|
|
14
|
+
base: "",
|
|
15
|
+
root: "",
|
|
16
|
+
plugins: [
|
|
17
|
+
tscPlugin({
|
|
18
|
+
tscArgs: [ "--project", "tsconfig.json", ...(mode === "development" ? [ "--sourceMap" ] : []) ],
|
|
19
|
+
packageManager: "npx" as "npm",
|
|
20
|
+
prebuild: true
|
|
21
|
+
}),
|
|
22
|
+
nodeExternals({
|
|
23
|
+
builtins: true,
|
|
24
|
+
devDeps: false,
|
|
25
|
+
deps: false,
|
|
26
|
+
optDeps: false,
|
|
27
|
+
peerDeps: false
|
|
28
|
+
})
|
|
29
|
+
],
|
|
30
|
+
resolve: {
|
|
31
|
+
mainFields: [ "module", "jsnext:main", "jsnext" ],
|
|
32
|
+
conditions: [ "node" ],
|
|
33
|
+
},
|
|
34
|
+
build: {
|
|
35
|
+
lib: {
|
|
36
|
+
entry: "dst-stage1/nunjucks.js",
|
|
37
|
+
formats: [ "cjs" ],
|
|
38
|
+
name: "Nunjucks",
|
|
39
|
+
fileName: () => "nunjucks.cjs"
|
|
40
|
+
},
|
|
41
|
+
target: "esnext",
|
|
42
|
+
outDir: "dst-stage2",
|
|
43
|
+
assetsDir: "",
|
|
44
|
+
emptyOutDir: (mode === "production"),
|
|
45
|
+
chunkSizeWarningLimit: 5000,
|
|
46
|
+
assetsInlineLimit: 0,
|
|
47
|
+
sourcemap: (mode === "development"),
|
|
48
|
+
minify: (mode === "production" ? "terser" : false),
|
|
49
|
+
reportCompressedSize: true,
|
|
50
|
+
rollupOptions: {
|
|
51
|
+
onwarn (warning, warn) {
|
|
52
|
+
if (warning.message.match(/Use of eval.*?is strongly discouraged/))
|
|
53
|
+
return
|
|
54
|
+
warn(warning)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}))
|
|
59
|
+
|
package/Dockerfile.mk
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
##
|
|
2
|
-
## Makefile: Docker Build Procedure
|
|
3
|
-
##
|
|
4
|
-
|
|
5
|
-
# ==== DEFAULT ====
|
|
6
|
-
# default build target
|
|
7
|
-
TARGETS ?= build
|
|
8
|
-
all: $(TARGETS)
|
|
9
|
-
|
|
10
|
-
# ==== COMMON ====
|
|
11
|
-
# configuration of container image
|
|
12
|
-
DOCKER_IMAGE_CONFIG ?= __dummy=1
|
|
13
|
-
IMAGE_CONFIG = \
|
|
14
|
-
IMAGE_PREFIX=`egrep "ARG.*IMAGE_PREFIX" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
15
|
-
IMAGE_NAME=`egrep "ARG.*IMAGE_NAME" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
16
|
-
IMAGE_VERSION=`egrep "ARG.*IMAGE_VERSION" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
17
|
-
IMAGE_RELEASE=`egrep "ARG.*IMAGE_RELEASE" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
18
|
-
IMAGE_ALIAS=`egrep "ARG.*IMAGE_ALIAS" Dockerfile | sed -e 's;^.*=;;' | head -1` && \
|
|
19
|
-
$(DOCKER_IMAGE_CONFIG)
|
|
20
|
-
|
|
21
|
-
# ==== BUILD ====
|
|
22
|
-
# (re)build a container image
|
|
23
|
-
DOCKER_BUILD_FLAGS ?= --pull --no-cache
|
|
24
|
-
build: Dockerfile
|
|
25
|
-
@$(IMAGE_CONFIG) && \
|
|
26
|
-
echo "++ building Docker image $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE} ($${IMAGE_ALIAS})" && \
|
|
27
|
-
docker build \
|
|
28
|
-
$(DOCKER_BUILD_FLAGS) \
|
|
29
|
-
--build-arg "IMAGE_PREFIX=$${IMAGE_PREFIX}" \
|
|
30
|
-
--build-arg "IMAGE_NAME=$${IMAGE_NAME}" \
|
|
31
|
-
--build-arg "IMAGE_VERSION=$${IMAGE_VERSION}" \
|
|
32
|
-
--build-arg "IMAGE_RELEASE=$${IMAGE_RELEASE}" \
|
|
33
|
-
--build-arg "IMAGE_ALIAS=$${IMAGE_ALIAS}" \
|
|
34
|
-
-t $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_ALIAS} \
|
|
35
|
-
-t $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION} \
|
|
36
|
-
-t $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE} \
|
|
37
|
-
-f Dockerfile . && \
|
|
38
|
-
docker image ls $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE}
|
|
39
|
-
|
|
40
|
-
# ==== RUN ====
|
|
41
|
-
# run a container image
|
|
42
|
-
DOCKER_RUN_FLAGS ?= --rm -i -t -e TERM --init
|
|
43
|
-
DOCKER_RUN_ARGS ?=
|
|
44
|
-
run:
|
|
45
|
-
@$(IMAGE_CONFIG) && \
|
|
46
|
-
echo "++ running Docker image $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE}" && \
|
|
47
|
-
docker run \
|
|
48
|
-
--name "$${IMAGE_NAME}-temp" \
|
|
49
|
-
$(DOCKER_RUN_FLAGS) \
|
|
50
|
-
$${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE} \
|
|
51
|
-
$(DOCKER_RUN_ARGS)
|
|
52
|
-
|
|
53
|
-
# ==== INSPECT ====
|
|
54
|
-
# inspect a container image
|
|
55
|
-
DOCKER_INSPECT_FLAGS ?= --rm -i -t -e TERM -u root --entrypoint "/bin/bash"
|
|
56
|
-
DOCKER_INSPECT_ARGS ?=
|
|
57
|
-
inspect:
|
|
58
|
-
@$(IMAGE_CONFIG) && \
|
|
59
|
-
echo "++ inspecting Docker image $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE}" && \
|
|
60
|
-
docker run \
|
|
61
|
-
--name "$${IMAGE_NAME}-temp" \
|
|
62
|
-
$(DOCKER_INSPECT_FLAGS) \
|
|
63
|
-
$${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE} \
|
|
64
|
-
$(DOCKER_INSPECT_ARGS)
|
|
65
|
-
|
|
66
|
-
# ==== EXEC ====
|
|
67
|
-
# enter a running container image
|
|
68
|
-
DOCKER_EXEC_FLAGS ?= -i -t -e TERM
|
|
69
|
-
DOCKER_EXEC_ARGS ?= /bin/bash
|
|
70
|
-
exec:
|
|
71
|
-
@$(IMAGE_CONFIG) && \
|
|
72
|
-
echo "++ executing command in Docker container of Docker image $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE}" && \
|
|
73
|
-
docker exec \
|
|
74
|
-
$(DOCKER_EXEC_FLAGS) \
|
|
75
|
-
`docker ps --filter "ancestor=$${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE}" --format "{{ .ID }}"` \
|
|
76
|
-
$(DOCKER_EXEC_ARGS)
|
|
77
|
-
|
|
78
|
-
# ==== PUSH ====
|
|
79
|
-
# push container image to registry
|
|
80
|
-
push:
|
|
81
|
-
@$(IMAGE_CONFIG) && \
|
|
82
|
-
echo "++ pushing Docker image $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE} ($${IMAGE_ALIAS})" && \
|
|
83
|
-
docker push $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE} && \
|
|
84
|
-
docker push $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION} && \
|
|
85
|
-
docker push $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_ALIAS}
|
|
86
|
-
|
|
87
|
-
# ==== CLEAN ====
|
|
88
|
-
# remove container image
|
|
89
|
-
clean:
|
|
90
|
-
@$(IMAGE_CONFIG) && \
|
|
91
|
-
echo "++ removing Docker image $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE} ($${IMAGE_ALIAS})" && \
|
|
92
|
-
docker image rm $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION}-$${IMAGE_RELEASE} >/dev/null 2>&1 || true && \
|
|
93
|
-
docker image rm $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_VERSION} >/dev/null 2>&1 || true && \
|
|
94
|
-
docker image rm $${IMAGE_PREFIX}$${IMAGE_NAME}:$${IMAGE_ALIAS} >/dev/null 2>&1 || true && \
|
|
95
|
-
|
|
96
|
-
# ==== PRUNE ====
|
|
97
|
-
# prune entire Docker environment
|
|
98
|
-
prune:
|
|
99
|
-
@echo "++ pruning Docker environment"
|
|
100
|
-
docker container prune -f
|
|
101
|
-
docker network prune -f
|
|
102
|
-
docker volume prune -f
|
|
103
|
-
docker image prune -f
|
|
104
|
-
|
package/nunjucks.1
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
.TH "NUNJUCKS" "1" "June 2025" "" ""
|
|
2
|
-
.SH "NAME"
|
|
3
|
-
\fBnunjucks\fR - Template Rendering Engine
|
|
4
|
-
.SH "SYNOPSIS"
|
|
5
|
-
.P
|
|
6
|
-
\fBnunjucks\fR \[lB]\fB-h\fR|\fB--help\fR\[rB] \[lB]\fB-V\fR|\fB--version\fR\[rB] \[lB]\fB-c\fR|\fB--config\fR \fIconfig-file\fR\[rB] \[lB]\fB-C\fR|\fB--option\fR \fIkey\fR=\fIvalue\fR\[rB] \[lB]\fB-d\fR|\fB--defines\fR \fIcontext-file\fR\[rB] \[lB]\fB-D\fR|\fB--define\fR \fIkey\fR=\fIvalue\fR\[rB] \[lB]\fB-e\fR|\fB--extension\fR \fImodule-name\fR\[rB] \[lB]\fB-o\fR|\fB--output\fR \fIoutput-file\fR|\fB-\fR\[rB] \[lB]\fIinput-file\fR|\fB-\fR\[rB]
|
|
7
|
-
.SH "DESCRIPTION"
|
|
8
|
-
.P
|
|
9
|
-
\fBnunjucks\fR(1) is a small command-line utility to render templates with the rich and powerful templating language \fBMozilla Nunjucks\fR \fI\(lahttps://mozilla.github.io/nunjucks/\(ra\fR. This allows you to define your configuration in a YAML file and then render an output file based on a template input file where your configuration can be expanded. It optionally can load Nunjucks addons like the ones from the companion \fBNunjucks Addons\fR \fI\(lahttps://github.com/rse/nunjucks-addons\(ra\fR package.
|
|
10
|
-
.SH "OPTIONS"
|
|
11
|
-
.P
|
|
12
|
-
The following top-level options and arguments exist:
|
|
13
|
-
.RS 0
|
|
14
|
-
.IP \(bu 4
|
|
15
|
-
\[lB]\fB-h\fR|\fB--help\fR\[rB] Show usage help.
|
|
16
|
-
.IP \(bu 4
|
|
17
|
-
\[lB]\fB-V\fR|\fB--version\fR\[rB] Show program version information.
|
|
18
|
-
.IP \(bu 4
|
|
19
|
-
\[lB]\fB-c\fR|\fB--config\fR \fIconfig-file\fR\[rB] Load Nunjucks configuration YAML file.
|
|
20
|
-
.IP \(bu 4
|
|
21
|
-
\[lB]\fB-C\fR|\fB--option\fR \fIkey\fR=\fIvalue\fR\[rB] Set Nunjucks configuration option.
|
|
22
|
-
.IP \(bu 4
|
|
23
|
-
\[lB]\fB-d\fR|\fB--defines\fR \fIcontext-file\fR\[rB] Load context definition YAML file. Can occur multiple times.
|
|
24
|
-
.IP \(bu 4
|
|
25
|
-
\[lB]\fB-D\fR|\fB--define\fR \fIkey\fR=\fIvalue\fR\[rB] Set context definition key/value. Can occur multiple times.
|
|
26
|
-
.IP \(bu 4
|
|
27
|
-
\[lB]\fB-e\fR|\fB--extension\fR \fImodule-name\fR\[rB] Load Nunjucks JavaScript extension module (installed via NPM).
|
|
28
|
-
.IP \(bu 4
|
|
29
|
-
\[lB]\fB-o\fR|\fB--output\fR \fIoutput-file\fR|\fB-\fR\[rB] Save output file (or stdout).
|
|
30
|
-
.IP \(bu 4
|
|
31
|
-
\[lB]\fB<input-file>\fR|\fB-\fR\[rB] Load input file (or stdin).
|
|
32
|
-
.RE 0
|
|
33
|
-
|
|
34
|
-
.SH "EXAMPLE"
|
|
35
|
-
.P
|
|
36
|
-
.RS 2
|
|
37
|
-
.nf
|
|
38
|
-
$ echo "Hello, {{who}}!" | nunjucks -D who=world -
|
|
39
|
-
Hello, world!
|
|
40
|
-
.fi
|
|
41
|
-
.RE
|
|
42
|
-
.SH "HISTORY"
|
|
43
|
-
.P
|
|
44
|
-
The \fBnunjucks\fR(1) utility was developed in August 2023 for being able to easily generate multiple configuration files for a complex \fIDocker-Compose\fR based setup.
|
|
45
|
-
.SH "AUTHOR"
|
|
46
|
-
.P
|
|
47
|
-
Dr. Ralf S. Engelschall \fI\(larse@engelschall.com\(ra\fR
|
package/nunjucks.js
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*
|
|
3
|
-
** nunjucks -- Nunjucks Template Rendering Command-Line Interface
|
|
4
|
-
** Copyright (c) 2019-2025 Dr. Ralf S. Engelschall <http://engelschall.com>
|
|
5
|
-
** Licensed under MIT <http://spdx.org/licenses/MIT.html>
|
|
6
|
-
*/
|
|
7
|
-
/* built-in requirements */
|
|
8
|
-
import fs from "node:fs";
|
|
9
|
-
import path from "node:path";
|
|
10
|
-
import { createRequire } from "node:module";
|
|
11
|
-
/* external requirements */
|
|
12
|
-
import { Command } from "commander";
|
|
13
|
-
import chalk from "chalk";
|
|
14
|
-
import jsYAML from "js-yaml";
|
|
15
|
-
import nunjucks from "nunjucks";
|
|
16
|
-
import deepmerge from "deepmerge";
|
|
17
|
-
/* load my own information */
|
|
18
|
-
const my = JSON.parse(await fs.promises.readFile(new URL("./package.json", import.meta.url), "utf-8"));
|
|
19
|
-
/* parse command-line arguments */
|
|
20
|
-
const program = new Command();
|
|
21
|
-
const reduceArray = (v, l) => l.concat([v]);
|
|
22
|
-
program.name("nunjucks")
|
|
23
|
-
.description("Nunjucks Template Rendering Command-Line Interface")
|
|
24
|
-
.showHelpAfterError("hint: use option --help for usage information")
|
|
25
|
-
.option("-h, --help", "show usage help", false)
|
|
26
|
-
.option("-V, --version", "show program version information", false)
|
|
27
|
-
.option("-c, --config <config-file>", "load Nunjucks configuration YAML file", "")
|
|
28
|
-
.option("-C, --option <key>=<value>", "set Nunjucks configuration option", reduceArray, [])
|
|
29
|
-
.option("-d, --defines <context-file>", "load context definition YAML file", reduceArray, [])
|
|
30
|
-
.option("-D, --define <key>=<value>", "set context definition key/value", reduceArray, [])
|
|
31
|
-
.option("-e, --extension <module-name>", "load Nunjucks JavaScript extension module", reduceArray, [])
|
|
32
|
-
.option("-o, --output <output-file>", "save output file", "-")
|
|
33
|
-
.argument("[<input-file>]", "input file");
|
|
34
|
-
program.parse(process.argv);
|
|
35
|
-
const argv = {
|
|
36
|
-
...program.opts(),
|
|
37
|
-
_: program.args
|
|
38
|
-
};
|
|
39
|
-
/* handle special help request */
|
|
40
|
-
if (argv.help) {
|
|
41
|
-
console.log(program.helpInformation());
|
|
42
|
-
console.log("Example:\n $ echo \"Hello, {{ who }}!\" | nunjucks -Dwho=World -\n");
|
|
43
|
-
process.exit(0);
|
|
44
|
-
}
|
|
45
|
-
/* handle special version request */
|
|
46
|
-
if (argv.version) {
|
|
47
|
-
console.log(`${my.name} ${my.version} (Node.js ${process.versions.node}, Nunjucks: ${my.dependencies.nunjucks})`);
|
|
48
|
-
console.log(`${my.description}`);
|
|
49
|
-
console.log(`Copyright (c) 2019-2025 ${my.author.name} <${my.author.url}>`);
|
|
50
|
-
console.log(`Licensed under ${my.license} <http://spdx.org/licenses/${my.license}.html>`);
|
|
51
|
-
process.exit(0);
|
|
52
|
-
}
|
|
53
|
-
/* read input file */
|
|
54
|
-
let input = "";
|
|
55
|
-
if (argv._.length > 1) {
|
|
56
|
-
console.error(chalk.red("nunjucks: ERROR: invalid number of arguments (zero or one input file expected)"));
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
let inputFile = argv._[0] ?? "-";
|
|
60
|
-
if (inputFile === "-") {
|
|
61
|
-
inputFile = "<stdin>";
|
|
62
|
-
process.stdin.setEncoding("utf-8");
|
|
63
|
-
const BUFSIZE = 256;
|
|
64
|
-
const buf = Buffer.alloc(BUFSIZE);
|
|
65
|
-
while (true) {
|
|
66
|
-
let bytesRead = 0;
|
|
67
|
-
try {
|
|
68
|
-
bytesRead = fs.readSync(process.stdin.fd, buf, 0, BUFSIZE, null);
|
|
69
|
-
}
|
|
70
|
-
catch (ex) {
|
|
71
|
-
if (ex.code === "EAGAIN")
|
|
72
|
-
continue;
|
|
73
|
-
else if (ex.code === "EOF")
|
|
74
|
-
break;
|
|
75
|
-
else
|
|
76
|
-
throw ex;
|
|
77
|
-
}
|
|
78
|
-
if (bytesRead === 0)
|
|
79
|
-
break;
|
|
80
|
-
input += buf.toString("utf8", 0, bytesRead);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
if (!fs.existsSync(inputFile)) {
|
|
85
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to find input file: ${inputFile}`));
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
input = fs.readFileSync(inputFile, { encoding: "utf8" });
|
|
89
|
-
}
|
|
90
|
-
/* provide context variables for template */
|
|
91
|
-
let context = {};
|
|
92
|
-
for (const define of argv.defines) {
|
|
93
|
-
try {
|
|
94
|
-
context = deepmerge(context, jsYAML.load(fs.readFileSync(define, { encoding: "utf8" })));
|
|
95
|
-
}
|
|
96
|
-
catch (ex) {
|
|
97
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to load context YAML file: ${ex.toString()}`));
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
/* expose environment variables to template */
|
|
102
|
-
context.env = process.env;
|
|
103
|
-
/* add context defines */
|
|
104
|
-
argv.define.forEach((define) => {
|
|
105
|
-
const match = define.match(/^([^=]+)(?:=(.*))?$/);
|
|
106
|
-
if (!match)
|
|
107
|
-
return;
|
|
108
|
-
let [, key, val] = match;
|
|
109
|
-
if (!key)
|
|
110
|
-
return;
|
|
111
|
-
if (val === undefined)
|
|
112
|
-
val = "true";
|
|
113
|
-
context[key] = val;
|
|
114
|
-
});
|
|
115
|
-
/* determine Nunjucks options */
|
|
116
|
-
let options = {};
|
|
117
|
-
if (argv.config) {
|
|
118
|
-
try {
|
|
119
|
-
options = jsYAML.load(fs.readFileSync(argv.config, { encoding: "utf8" }));
|
|
120
|
-
}
|
|
121
|
-
catch (ex) {
|
|
122
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to load options YAML file: ${ex.toString()}`));
|
|
123
|
-
process.exit(1);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
if (argv.option.length > 0)
|
|
127
|
-
options = Object.assign(options, argv.option);
|
|
128
|
-
options = {
|
|
129
|
-
autoescape: false,
|
|
130
|
-
throwOnUndefined: false,
|
|
131
|
-
trimBlocks: true,
|
|
132
|
-
lstripBlocks: true,
|
|
133
|
-
watch: false,
|
|
134
|
-
noCache: true,
|
|
135
|
-
...options
|
|
136
|
-
};
|
|
137
|
-
/* configure environment */
|
|
138
|
-
const env = nunjucks.configure(inputFile, options);
|
|
139
|
-
/* load external extension files */
|
|
140
|
-
for (const extension of argv.extension) {
|
|
141
|
-
let modpath = path.resolve(extension);
|
|
142
|
-
if (!fs.existsSync(modpath)) {
|
|
143
|
-
try {
|
|
144
|
-
const require = createRequire(import.meta.url);
|
|
145
|
-
modpath = require.resolve(extension);
|
|
146
|
-
}
|
|
147
|
-
catch (_ex) {
|
|
148
|
-
modpath = null;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (modpath === null) {
|
|
152
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to find extension module: ${extension}`));
|
|
153
|
-
process.exit(1);
|
|
154
|
-
}
|
|
155
|
-
/* dynamically import the module */
|
|
156
|
-
let mod;
|
|
157
|
-
try {
|
|
158
|
-
mod = await import(modpath);
|
|
159
|
-
/* handle both default and named exports */
|
|
160
|
-
mod = mod.default ?? mod;
|
|
161
|
-
}
|
|
162
|
-
catch (ex) {
|
|
163
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to load extension module: ${ex.toString()}`));
|
|
164
|
-
process.exit(1);
|
|
165
|
-
}
|
|
166
|
-
if (!(mod !== null && typeof mod === "function")) {
|
|
167
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to call extension file: ${modpath}`));
|
|
168
|
-
process.exit(1);
|
|
169
|
-
}
|
|
170
|
-
mod(env);
|
|
171
|
-
}
|
|
172
|
-
/* render Nunjucks template */
|
|
173
|
-
let output;
|
|
174
|
-
try {
|
|
175
|
-
output = env.renderString(input, context);
|
|
176
|
-
}
|
|
177
|
-
catch (ex) {
|
|
178
|
-
console.error(chalk.red(`nunjucks: ERROR: failed to render template: ${ex.toString()}`));
|
|
179
|
-
process.exit(1);
|
|
180
|
-
}
|
|
181
|
-
/* write output */
|
|
182
|
-
if (argv.output === "-")
|
|
183
|
-
process.stdout.write(output);
|
|
184
|
-
else
|
|
185
|
-
fs.writeFileSync(argv.output, output, { encoding: "utf8" });
|
|
186
|
-
/* die gracefully */
|
|
187
|
-
process.exit(0);
|