Skip to content

Commit 89a4bf0

Browse files
committed
feat: js-import generator
1 parent 01e49f4 commit 89a4bf0

File tree

7 files changed

+158
-1
lines changed

7 files changed

+158
-1
lines changed

docs/2.generators/js-import.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# js-import
2+
3+
The `js-import` generator generates JavaScript usage example to be imported.
4+
5+
<!-- automd:example cjs cdn generator=js-import name=pkg imports="foo,bar" -->
6+
7+
## Example
8+
9+
### Input
10+
11+
<!-- automd:js-import cjs=true cdn=true name=pkg imports=foo,bar -->
12+
<!-- /automd -->
13+
14+
### Output
15+
16+
<!-- automd:js-import cjs=true cdn=true name=pkg imports=foo,bar -->
17+
18+
**ESM** (Node.js, Bun)
19+
20+
```js
21+
import {
22+
foo,
23+
bar,
24+
} from "pkg";
25+
```
26+
27+
**CommonJS** (Legacy Node.js)
28+
29+
```js
30+
const {
31+
foo,
32+
bar,
33+
} = require("pkg");
34+
```
35+
36+
**CDN** (Deno, Bun and Browsers)
37+
38+
```js
39+
import {
40+
foo,
41+
bar,
42+
} from "https://esm.sh/pkg";
43+
```
44+
45+
<!-- /automd -->
46+
47+
<!-- /automd -->
48+
49+
## Arguments
50+
51+
- `name`: The package name (by default tries to read from the `name` field in `package.json`).
52+
- `import`/`imports`: Array or comma seperated list of export names.
53+
- `no-esm`: Disable ESM instructions.
54+
- `cdn`: Generate CDN import usage.
55+
- `cjs`: Generate CommonJS require usage.
56+
- `src`: Auto scan export names from src using [unjs/mlly](https://mlly.unjs.io).

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"didyoumean2": "^6.0.1",
4444
"globby": "^14.0.1",
4545
"magic-string": "^0.30.7",
46+
"mlly": "^1.5.0",
4647
"ofetch": "^1.3.3",
4748
"omark": "^0.1.0",
4849
"pathe": "^1.1.2",

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/generators/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ import { jsdocs } from "./jsdocs";
33
import { badges } from "./badges";
44
import { pmX, pmInstall } from "./pm";
55
import { fetch as _fetch } from "./fetch";
6-
6+
import { jsimport } from "./jsimport";
77
export default {
88
jsdocs,
99
badges,
1010
"pm-i": pmInstall,
1111
"pm-install": pmInstall,
1212
"pm-x": pmX,
1313
fetch: _fetch,
14+
jsimport,
15+
"js-import": jsimport,
1416
} as Record<string, Generator>;

src/generators/jsimport.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { readFile } from "node:fs/promises";
2+
import { codeBlock } from "omark";
3+
import { findExportNames, resolvePath } from "mlly";
4+
import { getPkg } from "../_utils";
5+
import { defineGenerator } from "../generator";
6+
7+
const DEFAULT_CDN = "https://esm.sh/";
8+
9+
export const jsimport = defineGenerator({
10+
name: "js-import",
11+
async generate({ config, args }) {
12+
const { name } = await getPkg(config.dir, args);
13+
14+
const importPath = name + (args.path || "");
15+
16+
const importNames: string[] = ([] as string[])
17+
.concat(args.import, args.imports) // eslint-disable-line unicorn/prefer-spread
18+
.filter(Boolean)
19+
.flatMap((i) => i.split(/\s*,\s*/));
20+
21+
if (args.src) {
22+
const resolved = await resolvePath(args.src, { url: config.dir });
23+
const contents = await readFile(resolved, "utf8");
24+
const exportNames = findExportNames(contents);
25+
if (exportNames && exportNames.length > 0) {
26+
importNames.push(...exportNames);
27+
}
28+
}
29+
30+
const lines: string[] = [];
31+
32+
const fmtImports =
33+
importNames.length > 1
34+
? `\n${importNames.map((i) => " " + i + ",").join("\n")}\n`
35+
: (importNames[0] && ` ${importNames[0]} `) || "";
36+
37+
if (args.esm !== false) {
38+
const code = `import {${fmtImports}} from "${importPath}";`;
39+
lines.push("**ESM** (Node.js, Bun)", codeBlock(code, "js"));
40+
}
41+
42+
if (args.cjs) {
43+
const code = `const {${fmtImports}} = require("${importPath}");`;
44+
lines.push("**CommonJS** (Legacy Node.js)", codeBlock(code, "js"));
45+
}
46+
47+
if (args.cdn) {
48+
const cdnBase = typeof args.cdn === "string" ? args.cdn : DEFAULT_CDN;
49+
const code = `import {${fmtImports}} from "${cdnBase}${importPath}";`;
50+
lines.push("**CDN** (Deno, Bun and Browsers)", codeBlock(code, "js"));
51+
}
52+
53+
return {
54+
contents: lines.join("\n\n"),
55+
};
56+
},
57+
});

test/fixture/INPUT.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,8 @@
2424

2525
<!-- automd:fetch url="https://gist.github.com/pi0/c176defbba5568b6d06ea619a75f6104/raw" -->
2626
<!-- /automd -->
27+
28+
## `js-import`
29+
30+
<!-- automd:js-import cjs=true cdn=true name=pkg imports=foo,bar -->
31+
<!-- /automd -->

test/fixture/OUTPUT.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,37 @@ When your code doesn't work, don't blame yourself. It's clearly the compiler's f
100100
Why waste time solving problems when someone else has already done it for you? Stack Overflow is your best friend, your mentor, and your savior. Just make sure to upvote the answers that save your bacon.
101101

102102

103+
<!-- /automd -->
104+
105+
## `js-import`
106+
107+
<!-- automd:js-import cjs=true cdn=true name=pkg imports=foo,bar -->
108+
109+
**ESM** (Node.js, Bun)
110+
111+
```js
112+
import {
113+
foo,
114+
bar,
115+
} from "pkg";
116+
```
117+
118+
**CommonJS** (Legacy Node.js)
119+
120+
```js
121+
const {
122+
foo,
123+
bar,
124+
} = require("pkg");
125+
```
126+
127+
**CDN** (Deno, Bun and Browsers)
128+
129+
```js
130+
import {
131+
foo,
132+
bar,
133+
} from "https://esm.sh/pkg";
134+
```
135+
103136
<!-- /automd -->

0 commit comments

Comments
 (0)