yuku-codegen 0.5.15 → 0.5.17
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 +21 -19
- package/encode.js +26 -12
- package/index.d.ts +16 -9
- package/index.js +24 -17
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -16,15 +16,15 @@ npm install yuku-codegen
|
|
|
16
16
|
import { parse } from "yuku-parser";
|
|
17
17
|
import { print } from "yuku-codegen";
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
const { code } = print(
|
|
19
|
+
const { program } = parse("const x = 1 + 2;");
|
|
20
|
+
const { code } = print(program);
|
|
21
21
|
|
|
22
22
|
console.log(code); // "const x = 1 + 2;"
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## API
|
|
26
26
|
|
|
27
|
-
All three entry points take the `ParseResult` returned by [`yuku-parser`](https://www.npmjs.com/package/yuku-parser) and share the same options and result shape.
|
|
27
|
+
All three entry points take the `Program` node off the `ParseResult` returned by [`yuku-parser`](https://www.npmjs.com/package/yuku-parser) and share the same options and result shape.
|
|
28
28
|
|
|
29
29
|
| Function | Behavior |
|
|
30
30
|
| -------- | ----------------------------------------------------------------------------------------------------- |
|
|
@@ -47,12 +47,12 @@ interface CodegenResult {
|
|
|
47
47
|
## Options
|
|
48
48
|
|
|
49
49
|
```js
|
|
50
|
-
const out = print(
|
|
50
|
+
const out = print(program, {
|
|
51
51
|
format: "pretty",
|
|
52
52
|
indent: 2,
|
|
53
53
|
quotes: "double",
|
|
54
54
|
comments: "some",
|
|
55
|
-
sourceMaps:
|
|
55
|
+
sourceMaps: { lineStarts },
|
|
56
56
|
});
|
|
57
57
|
```
|
|
58
58
|
|
|
@@ -62,21 +62,22 @@ const out = print(result, {
|
|
|
62
62
|
| `indent` | `number` | `2` | Spaces per indentation level. Applies in pretty mode only. |
|
|
63
63
|
| `quotes` | `"double" \| "single"` | `"double"` | Quote style for emitted string literals. |
|
|
64
64
|
| `comments` | `boolean \| "some" \| "line" \| "block"` | `"some"` | Comment passthrough filter. See [Comments](#comments). |
|
|
65
|
-
| `sourceMaps` | `
|
|
65
|
+
| `sourceMaps` | `SourceMapOptions` | `undefined` | Pass an object to emit a Source Map V3. Its `lineStarts` is required, the rest of the metadata is optional. See [Source maps](#source-maps). |
|
|
66
66
|
|
|
67
67
|
## Source maps
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
Pass a `SourceMapOptions` object to emit a Source Map V3. Its `lineStarts` field is required: feed it the `lineStarts` array from the parser's `ParseResult` (this is what maps generated positions back to the source). The remaining fields (`file`, `sources`, `sourcesContent`, `sourceRoot`) are optional metadata.
|
|
70
70
|
|
|
71
71
|
```js
|
|
72
72
|
import { parse } from "yuku-parser";
|
|
73
73
|
import { print } from "yuku-codegen";
|
|
74
74
|
|
|
75
75
|
const source = `const greet = (name) => "Hello, " + name;`;
|
|
76
|
-
const
|
|
76
|
+
const { program, lineStarts } = parse(source);
|
|
77
77
|
|
|
78
|
-
const { code, map } = print(
|
|
78
|
+
const { code, map } = print(program, {
|
|
79
79
|
sourceMaps: {
|
|
80
|
+
lineStarts,
|
|
80
81
|
file: "out.js",
|
|
81
82
|
sourceFileName: "in.js",
|
|
82
83
|
sourcesContent: source,
|
|
@@ -89,9 +90,10 @@ await Bun.write("out.js.map", JSON.stringify(map));
|
|
|
89
90
|
|
|
90
91
|
### `SourceMapOptions`
|
|
91
92
|
|
|
92
|
-
| Field | Type
|
|
93
|
-
| ---------------- |
|
|
94
|
-
| `
|
|
93
|
+
| Field | Type | Description |
|
|
94
|
+
| ---------------- | ---------- | --------------------------------------------------------------------------------- |
|
|
95
|
+
| `lineStarts` | `number[]` | **Required.** The parser's `ParseResult.lineStarts`, used to map positions to the source. |
|
|
96
|
+
| `file` | `string` | Output filename, embedded as the map's `file`. |
|
|
95
97
|
| `sourceFileName` | `string` | Source filename, embedded as the single entry of `sources`. |
|
|
96
98
|
| `sourceRoot` | `string` | Prefix embedded as `sourceRoot`. |
|
|
97
99
|
| `sourcesContent` | `string` | When set, embedded as the single entry of the map's `sourcesContent`. Omit to skip. |
|
|
@@ -122,8 +124,8 @@ Columns are 0-indexed UTF-16 code units, matching Chrome DevTools and consumer-s
|
|
|
122
124
|
import { parse } from "yuku-parser";
|
|
123
125
|
import { strip } from "yuku-codegen";
|
|
124
126
|
|
|
125
|
-
const
|
|
126
|
-
console.log(strip(
|
|
127
|
+
const { program } = parse(`const x: number = 1;`, { lang: "ts" });
|
|
128
|
+
console.log(strip(program).code); // "const x = 1;"
|
|
127
129
|
```
|
|
128
130
|
|
|
129
131
|
Type annotations, type aliases, interfaces, and other type-only constructs are dropped. Constructs that have no clean JavaScript equivalent (`enum`, `namespace`, `import = require()`, `export =`) are reported in `errors` and elided. The output is always syntactically valid JavaScript.
|
|
@@ -133,8 +135,8 @@ Type annotations, type aliases, interfaces, and other type-only constructs are d
|
|
|
133
135
|
Comments live on the AST nodes they were attached to during parsing. To preserve them, parse with `attachComments: true`:
|
|
134
136
|
|
|
135
137
|
```js
|
|
136
|
-
const
|
|
137
|
-
print(
|
|
138
|
+
const { program } = parse(source, { attachComments: true });
|
|
139
|
+
print(program).code;
|
|
138
140
|
```
|
|
139
141
|
|
|
140
142
|
The `comments` option then selects which attached comments are emitted. The default is `"some"`, which matches the bundler convention of keeping legal banners, JSDoc, and tree-shaking annotations while dropping plain noise.
|
|
@@ -148,8 +150,8 @@ The `comments` option then selects which attached comments are emitted. The defa
|
|
|
148
150
|
| `"block"` | Emit `/* ... */` only. |
|
|
149
151
|
|
|
150
152
|
```js
|
|
151
|
-
const
|
|
152
|
-
print(
|
|
153
|
+
const { program } = parse(`// hello\nconst x = 1;`, { attachComments: true });
|
|
154
|
+
print(program, { comments: true }).code;
|
|
153
155
|
// "// hello\nconst x = 1;"
|
|
154
156
|
```
|
|
155
157
|
|
|
@@ -171,7 +173,7 @@ Combine with `format: "compact"` for full minification:
|
|
|
171
173
|
```js
|
|
172
174
|
import { minify } from "yuku-codegen";
|
|
173
175
|
|
|
174
|
-
const { code } = minify(
|
|
176
|
+
const { code } = minify(program, { format: "compact" });
|
|
175
177
|
```
|
|
176
178
|
|
|
177
179
|
## License
|
package/encode.js
CHANGED
|
@@ -35,18 +35,18 @@ const ACCESSIBILITY_INV = (v) =>
|
|
|
35
35
|
: 3;
|
|
36
36
|
const TS_MAPPED_OPTIONAL_INV = (v) => v === true ? 1 : v === "+" ? 2 : v === "-" ? 3 : 0;
|
|
37
37
|
const TS_MAPPED_READONLY_INV = (v) => v === true ? 1 : v === "+" ? 2 : v === "-" ? 3 : 0;
|
|
38
|
-
function encode(
|
|
39
|
-
const root =
|
|
40
|
-
const
|
|
41
|
-
let nodeCap = 512;
|
|
38
|
+
function encode(program, lineStarts) {
|
|
39
|
+
const root = program;
|
|
40
|
+
const sizeHint = root.end || 0;
|
|
41
|
+
let nodeCap = Math.max(512, (sizeHint / 7) | 0);
|
|
42
42
|
let nodeAB = new ArrayBuffer(nodeCap * NODE_SIZE);
|
|
43
43
|
let nU8 = new Uint8Array(nodeAB);
|
|
44
44
|
let nU32 = new Uint32Array(nodeAB);
|
|
45
45
|
let nodeCount = 0;
|
|
46
|
-
let extraCap = 512;
|
|
46
|
+
let extraCap = Math.max(512, (sizeHint / 20) | 0);
|
|
47
47
|
let extras = new Uint32Array(extraCap);
|
|
48
48
|
let extraCount = 0;
|
|
49
|
-
let poolCap = 4096;
|
|
49
|
+
let poolCap = Math.max(4096, (sizeHint / 8) | 0);
|
|
50
50
|
let pool = new Uint8Array(poolCap);
|
|
51
51
|
let poolLen = 0;
|
|
52
52
|
const strMap = new Map();
|
|
@@ -119,15 +119,29 @@ function encode(result) {
|
|
|
119
119
|
if (s == null || s === "") return { start: 0, end: 0 };
|
|
120
120
|
const hit = strMap.get(s);
|
|
121
121
|
if (hit !== undefined) return hit;
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
poolCap *= 2;
|
|
122
|
+
const n = s.length;
|
|
123
|
+
if (poolLen + n * 3 > poolCap) {
|
|
124
|
+
do { poolCap *= 2; } while (poolLen + n * 3 > poolCap);
|
|
125
125
|
const np = new Uint8Array(poolCap);
|
|
126
126
|
np.set(pool); pool = np;
|
|
127
127
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
const start = poolLen;
|
|
129
|
+
let p = start;
|
|
130
|
+
let ascii = true;
|
|
131
|
+
for (let i = 0; i < n; i++) {
|
|
132
|
+
const c = s.charCodeAt(i);
|
|
133
|
+
if (c < 0x80) { pool[p++] = c; } else { ascii = false; break; }
|
|
134
|
+
}
|
|
135
|
+
let r;
|
|
136
|
+
if (ascii) {
|
|
137
|
+
r = { start, end: p };
|
|
138
|
+
poolLen = p;
|
|
139
|
+
} else {
|
|
140
|
+
const bytes = _enc.encode(s);
|
|
141
|
+
pool.set(bytes, start);
|
|
142
|
+
r = { start, end: start + bytes.length };
|
|
143
|
+
poolLen = start + bytes.length;
|
|
144
|
+
}
|
|
131
145
|
strMap.set(s, r);
|
|
132
146
|
return r;
|
|
133
147
|
}
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Comment,
|
|
1
|
+
import type { Comment, Program } from "yuku-parser";
|
|
2
2
|
|
|
3
3
|
/** Whitespace mode for the generated output. */
|
|
4
4
|
export type Format = "pretty" | "compact";
|
|
@@ -21,6 +21,12 @@ export type { Comment };
|
|
|
21
21
|
|
|
22
22
|
/** Source-map configuration. Pass to `CodegenOptions.sourceMaps` to enable. */
|
|
23
23
|
export interface SourceMapOptions {
|
|
24
|
+
/**
|
|
25
|
+
* UTF-16 line-start offsets, taken straight from the parser's
|
|
26
|
+
* `ParseResult.lineStarts`. Required: this is what maps generated positions
|
|
27
|
+
* back to the original source.
|
|
28
|
+
*/
|
|
29
|
+
lineStarts: number[];
|
|
24
30
|
/** Output filename, embedded as the map's `file`. */
|
|
25
31
|
file?: string;
|
|
26
32
|
/** Source filename, embedded as the single entry of `sources`. */
|
|
@@ -43,12 +49,13 @@ export interface CodegenOptions {
|
|
|
43
49
|
/** @default "double" */
|
|
44
50
|
quotes?: Quotes;
|
|
45
51
|
/**
|
|
46
|
-
* Enable Source Map V3 output.
|
|
47
|
-
*
|
|
48
|
-
* `
|
|
49
|
-
*
|
|
52
|
+
* Enable Source Map V3 output. Pass a {@link SourceMapOptions} object. Its
|
|
53
|
+
* `lineStarts` (from the parser) is required. The rest of the metadata
|
|
54
|
+
* (`file`, `sources`, `sourcesContent`, `sourceRoot`) is optional. Omit to
|
|
55
|
+
* disable.
|
|
56
|
+
* @default undefined
|
|
50
57
|
*/
|
|
51
|
-
sourceMaps?:
|
|
58
|
+
sourceMaps?: SourceMapOptions;
|
|
52
59
|
/**
|
|
53
60
|
* Comment passthrough filter. Defaults to `"some"`, which preserves
|
|
54
61
|
* legal headers, JSDoc, and tree-shaking annotations.
|
|
@@ -88,13 +95,13 @@ export interface CodegenResult {
|
|
|
88
95
|
}
|
|
89
96
|
|
|
90
97
|
/** Renders the AST verbatim, preserving TypeScript syntax. */
|
|
91
|
-
export function print(
|
|
98
|
+
export function print(program: Program, options?: CodegenOptions): CodegenResult;
|
|
92
99
|
|
|
93
100
|
/** Renders the AST as JavaScript, dropping TypeScript-specific syntax. */
|
|
94
|
-
export function strip(
|
|
101
|
+
export function strip(program: Program, options?: CodegenOptions): CodegenResult;
|
|
95
102
|
|
|
96
103
|
/**
|
|
97
104
|
* Renders the AST with size-reducing rewrites. Combine with
|
|
98
105
|
* `format: "compact"` for full minification.
|
|
99
106
|
*/
|
|
100
|
-
export function minify(
|
|
107
|
+
export function minify(program: Program, options?: CodegenOptions): CodegenResult;
|
package/index.js
CHANGED
|
@@ -7,37 +7,44 @@ function normalizeOptions(options) {
|
|
|
7
7
|
const c = next.comments;
|
|
8
8
|
if (c === true) next.comments = "all";
|
|
9
9
|
else if (c === false) next.comments = "none";
|
|
10
|
+
// `lineStarts` is consumed by the encoder, not the native binding, so strip
|
|
11
|
+
// it from the source-map options. Only V3 metadata reaches the binding.
|
|
10
12
|
const s = next.sourceMaps;
|
|
11
|
-
if (s
|
|
12
|
-
|
|
13
|
+
if (s) {
|
|
14
|
+
const { lineStarts, ...meta } = s;
|
|
15
|
+
next.sourceMaps = meta;
|
|
16
|
+
} else {
|
|
17
|
+
next.sourceMaps = undefined;
|
|
18
|
+
}
|
|
13
19
|
return next;
|
|
14
20
|
}
|
|
15
21
|
|
|
16
|
-
function
|
|
17
|
-
if (!
|
|
22
|
+
function run(method, program, options) {
|
|
23
|
+
if (!program || !program.type) {
|
|
18
24
|
throw new TypeError(
|
|
19
|
-
"Expected a `
|
|
20
|
-
(
|
|
25
|
+
"Expected a `Program` node from yuku-parser, got " +
|
|
26
|
+
(program === null ? "null" : typeof program),
|
|
21
27
|
);
|
|
22
28
|
}
|
|
23
|
-
|
|
29
|
+
const sourceMaps = options?.sourceMaps;
|
|
30
|
+
const lineStarts = sourceMaps ? sourceMaps.lineStarts : null;
|
|
31
|
+
if (sourceMaps && !Array.isArray(lineStarts)) {
|
|
24
32
|
throw new Error(
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"either drop `sourceMaps` or attach a `lineStarts` array.",
|
|
33
|
+
"`sourceMaps` requires a `lineStarts` array. Pass the parser's " +
|
|
34
|
+
"`ParseResult.lineStarts`, e.g. `{ sourceMaps: { lineStarts } }`.",
|
|
28
35
|
);
|
|
29
36
|
}
|
|
30
|
-
return encode(
|
|
37
|
+
return binding[method](encode(program, lineStarts), normalizeOptions(options));
|
|
31
38
|
}
|
|
32
39
|
|
|
33
|
-
export function print(
|
|
34
|
-
return
|
|
40
|
+
export function print(program, options) {
|
|
41
|
+
return run("print", program, options);
|
|
35
42
|
}
|
|
36
43
|
|
|
37
|
-
export function strip(
|
|
38
|
-
return
|
|
44
|
+
export function strip(program, options) {
|
|
45
|
+
return run("strip", program, options);
|
|
39
46
|
}
|
|
40
47
|
|
|
41
|
-
export function minify(
|
|
42
|
-
return
|
|
48
|
+
export function minify(program, options) {
|
|
49
|
+
return run("minify", program, options);
|
|
43
50
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yuku-codegen",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.17",
|
|
4
4
|
"description": "High-performance JavaScript/TypeScript code generator written in Zig",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -17,17 +17,17 @@
|
|
|
17
17
|
"encode.js"
|
|
18
18
|
],
|
|
19
19
|
"optionalDependencies": {
|
|
20
|
-
"@yuku-codegen/binding-linux-x64-gnu": "0.5.
|
|
21
|
-
"@yuku-codegen/binding-linux-arm64-gnu": "0.5.
|
|
22
|
-
"@yuku-codegen/binding-linux-arm-gnu": "0.5.
|
|
23
|
-
"@yuku-codegen/binding-linux-x64-musl": "0.5.
|
|
24
|
-
"@yuku-codegen/binding-linux-arm64-musl": "0.5.
|
|
25
|
-
"@yuku-codegen/binding-linux-arm-musl": "0.5.
|
|
26
|
-
"@yuku-codegen/binding-darwin-x64": "0.5.
|
|
27
|
-
"@yuku-codegen/binding-darwin-arm64": "0.5.
|
|
28
|
-
"@yuku-codegen/binding-win32-x64": "0.5.
|
|
29
|
-
"@yuku-codegen/binding-win32-arm64": "0.5.
|
|
30
|
-
"@yuku-codegen/binding-freebsd-x64": "0.5.
|
|
20
|
+
"@yuku-codegen/binding-linux-x64-gnu": "0.5.17",
|
|
21
|
+
"@yuku-codegen/binding-linux-arm64-gnu": "0.5.17",
|
|
22
|
+
"@yuku-codegen/binding-linux-arm-gnu": "0.5.17",
|
|
23
|
+
"@yuku-codegen/binding-linux-x64-musl": "0.5.17",
|
|
24
|
+
"@yuku-codegen/binding-linux-arm64-musl": "0.5.17",
|
|
25
|
+
"@yuku-codegen/binding-linux-arm-musl": "0.5.17",
|
|
26
|
+
"@yuku-codegen/binding-darwin-x64": "0.5.17",
|
|
27
|
+
"@yuku-codegen/binding-darwin-arm64": "0.5.17",
|
|
28
|
+
"@yuku-codegen/binding-win32-x64": "0.5.17",
|
|
29
|
+
"@yuku-codegen/binding-win32-arm64": "0.5.17",
|
|
30
|
+
"@yuku-codegen/binding-freebsd-x64": "0.5.17"
|
|
31
31
|
},
|
|
32
32
|
"keywords": [
|
|
33
33
|
"ast",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"printer",
|
|
40
40
|
"typescript"
|
|
41
41
|
],
|
|
42
|
-
"
|
|
42
|
+
"peerDependencies": {
|
|
43
43
|
"yuku-parser": "0.5.14"
|
|
44
44
|
}
|
|
45
45
|
}
|