Skip to content

Commit

Permalink
feat(cli): override non-js-like extensions via --ext (#1105)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
antongolub authored Feb 22, 2025
1 parent 82a5e0b commit be0990f
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 6 deletions.
15 changes: 12 additions & 3 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,16 @@ assumes that it is
an [ESM](https://nodejs.org/api/modules.html#modules_module_createrequire_filename)
module unless the `--ext` option is specified.

## Non-standard extension
`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).
However, if the script has a non-js-like extension (`/^\.[mc]?[jt]sx?$/`) and the `--ext` is specified, it will be used.

```bash
zx script.zx # Unknown file extension "\.zx"
zx --ext=mjs script.zx # OK
```

## Markdown
```bash
zx docs/markdown.md
```
Expand Down Expand Up @@ -89,10 +98,10 @@ Enable verbose mode.

## `--shell`

Specify a custom shell binary.
Specify a custom shell binary path. By default, zx refers to `bash`.

```bash
zx --shell=/bin/bash script.mjs
zx --shell=/bin/another/sh script.mjs
```

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

## `--ext`

Override the default (temp) script extension. Default is `.mjs`.
Overrides the default script extension (`.mjs`).

## `--version, -v`

Expand Down
2 changes: 1 addition & 1 deletion man/zx.1
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ prefer locally installed packages bins
.SS --eval=<js>, -e
evaluate script
.SS --ext=<.mjs>
default extension
script extension
.SS --install, -i
install dependencies
.SS --registry=<URL>
Expand Down
5 changes: 3 additions & 2 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { randomId, bufToString } from './util.js'
import { createRequire, type minimist } from './vendor.js'

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

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

const { ext, base, dir } = path.parse(tempPath || scriptPath)
if (ext === '') {
if (ext === '' || (argv.ext && !EXT_RE.test(ext))) {
tempPath = getFilepath(dir, base)
}
if (ext === '.md') {
Expand Down
11 changes: 11 additions & 0 deletions test/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,17 @@ describe('cli', () => {
)
})

test('scripts with non standard extension', async () => {
const o =
await $`node build/cli.js --ext='.mjs' test/fixtures/non-std-ext.zx`
assert.ok(o.stdout.trim().endsWith('zx/test/fixtures/non-std-ext.zx.mjs'))

await assert.rejects(
$`node build/cli.js test/fixtures/non-std-ext.zx`,
/Unknown file extension "\.zx"/
)
})

test22('scripts from stdin with explicit extension', async () => {
const out =
await $`node --experimental-strip-types build/cli.js --ext='.ts' <<< 'const foo: string = "bar"; console.log(foo)'`
Expand Down
19 changes: 19 additions & 0 deletions test/fixtures/non-std-ext.zx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env zx

// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

console.log(chalk.yellowBright`If file has non-std ext and 'ext-override' option specified, zx assumes it's ESM.`)
await $`pwd`
console.log('__filename =', __filename)

0 comments on commit be0990f

Please sign in to comment.