Skip to content

Commit be0990f

Browse files
authored
feat(cli): override non-js-like extensions via --ext (#1105)
* feat: introduce `--ext-override` option to process non-std (non js/ts like) file extensions resolves #1104 * refactor(cli): use `ext` option to override non-js-like script extensions
1 parent 82a5e0b commit be0990f

File tree

5 files changed

+46
-6
lines changed

5 files changed

+46
-6
lines changed

docs/cli.md

+12-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,16 @@ assumes that it is
1313
an [ESM](https://nodejs.org/api/modules.html#modules_module_createrequire_filename)
1414
module unless the `--ext` option is specified.
1515

16+
## Non-standard extension
17+
`zx` internally loads scripts via `import` API, so you can use any extension supported by the runtime (nodejs, deno, bun) or apply a [custom loader](https://nodejs.org/api/cli.html#--experimental-loadermodule).
18+
However, if the script has a non-js-like extension (`/^\.[mc]?[jt]sx?$/`) and the `--ext` is specified, it will be used.
1619

20+
```bash
21+
zx script.zx # Unknown file extension "\.zx"
22+
zx --ext=mjs script.zx # OK
23+
```
24+
25+
## Markdown
1726
```bash
1827
zx docs/markdown.md
1928
```
@@ -89,10 +98,10 @@ Enable verbose mode.
8998

9099
## `--shell`
91100

92-
Specify a custom shell binary.
101+
Specify a custom shell binary path. By default, zx refers to `bash`.
93102

94103
```bash
95-
zx --shell=/bin/bash script.mjs
104+
zx --shell=/bin/another/sh script.mjs
96105
```
97106

98107
## `--prefer-local, -l`
@@ -131,7 +140,7 @@ When `cwd` option is specified, it will be used as base path:
131140

132141
## `--ext`
133142

134-
Override the default (temp) script extension. Default is `.mjs`.
143+
Overrides the default script extension (`.mjs`).
135144

136145
## `--version, -v`
137146

man/zx.1

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ prefer locally installed packages bins
2424
.SS --eval=<js>, -e
2525
evaluate script
2626
.SS --ext=<.mjs>
27-
default extension
27+
script extension
2828
.SS --install, -i
2929
install dependencies
3030
.SS --registry=<URL>

src/cli.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { randomId, bufToString } from './util.js'
3535
import { createRequire, type minimist } from './vendor.js'
3636

3737
const EXT = '.mjs'
38+
const EXT_RE = /^\.[mc]?[jt]sx?$/
3839

3940
isMain() &&
4041
main().catch((err) => {
@@ -64,7 +65,7 @@ export function printUsage() {
6465
--prefer-local, -l prefer locally installed packages bins
6566
--cwd=<path> set current directory
6667
--eval=<js>, -e evaluate script
67-
--ext=<.mjs> default extension
68+
--ext=<.mjs> script extension
6869
--install, -i install dependencies
6970
--registry=<URL> npm registry, defaults to https://registry.npmjs.org/
7071
--version, -v print current zx version
@@ -180,7 +181,7 @@ async function readScript() {
180181
}
181182

182183
const { ext, base, dir } = path.parse(tempPath || scriptPath)
183-
if (ext === '') {
184+
if (ext === '' || (argv.ext && !EXT_RE.test(ext))) {
184185
tempPath = getFilepath(dir, base)
185186
}
186187
if (ext === '.md') {

test/cli.test.js

+11
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,17 @@ describe('cli', () => {
223223
)
224224
})
225225

226+
test('scripts with non standard extension', async () => {
227+
const o =
228+
await $`node build/cli.js --ext='.mjs' test/fixtures/non-std-ext.zx`
229+
assert.ok(o.stdout.trim().endsWith('zx/test/fixtures/non-std-ext.zx.mjs'))
230+
231+
await assert.rejects(
232+
$`node build/cli.js test/fixtures/non-std-ext.zx`,
233+
/Unknown file extension "\.zx"/
234+
)
235+
})
236+
226237
test22('scripts from stdin with explicit extension', async () => {
227238
const out =
228239
await $`node --experimental-strip-types build/cli.js --ext='.ts' <<< 'const foo: string = "bar"; console.log(foo)'`

test/fixtures/non-std-ext.zx

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env zx
2+
3+
// Copyright 2024 Google LLC
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// https://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
console.log(chalk.yellowBright`If file has non-std ext and 'ext-override' option specified, zx assumes it's ESM.`)
18+
await $`pwd`
19+
console.log('__filename =', __filename)

0 commit comments

Comments
 (0)