vite-plugin-qingkuai 1.0.22 → 1.0.24
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/.github/workflows/release.yml +106 -0
- package/.husky/pre-commit +1 -0
- package/dist/index.cjs +63 -16
- package/dist/index.js +64 -17
- package/package.json +54 -43
- package/scripts/release.js +94 -0
- package/.vscode/extensions.json +0 -3
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
tag:
|
|
10
|
+
type: string
|
|
11
|
+
required: false
|
|
12
|
+
description: "Optional tag to release (for example: v1.0.66). Leave empty to auto-create from package version."
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: write
|
|
16
|
+
id-token: write
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
release:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout source
|
|
24
|
+
uses: actions/checkout@v6
|
|
25
|
+
with:
|
|
26
|
+
fetch-depth: 0
|
|
27
|
+
|
|
28
|
+
- name: Resolve release tag
|
|
29
|
+
id: tag
|
|
30
|
+
env:
|
|
31
|
+
INPUT_TAG: ${{ inputs.tag }}
|
|
32
|
+
REF_NAME: ${{ github.ref_name }}
|
|
33
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
34
|
+
run: |
|
|
35
|
+
if [[ "$EVENT_NAME" == "push" ]]; then
|
|
36
|
+
echo "value=$REF_NAME" >> "$GITHUB_OUTPUT"
|
|
37
|
+
exit 0
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
if [[ -n "$INPUT_TAG" ]]; then
|
|
41
|
+
echo "value=$INPUT_TAG" >> "$GITHUB_OUTPUT"
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
package_version="$(node -p 'require("./package.json").version')"
|
|
46
|
+
echo "value=v$package_version" >> "$GITHUB_OUTPUT"
|
|
47
|
+
|
|
48
|
+
- name: Ensure tag exists on workflow dispatch
|
|
49
|
+
if: ${{ github.event_name == 'workflow_dispatch' }}
|
|
50
|
+
env:
|
|
51
|
+
TAG: ${{ steps.tag.outputs.value }}
|
|
52
|
+
run: |
|
|
53
|
+
git fetch origin --tags --prune
|
|
54
|
+
|
|
55
|
+
if git rev-parse --verify --quiet "refs/tags/$TAG" >/dev/null; then
|
|
56
|
+
echo "Tag already exists: $TAG"
|
|
57
|
+
else
|
|
58
|
+
git config user.name "github-actions[bot]"
|
|
59
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
60
|
+
git tag "$TAG"
|
|
61
|
+
git push origin "$TAG"
|
|
62
|
+
echo "Created and pushed tag: $TAG"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
- name: Checkout resolved tag
|
|
66
|
+
env:
|
|
67
|
+
TAG: ${{ steps.tag.outputs.value }}
|
|
68
|
+
run: |
|
|
69
|
+
git fetch origin --tags --prune
|
|
70
|
+
git checkout "refs/tags/$TAG"
|
|
71
|
+
|
|
72
|
+
- name: Setup pnpm
|
|
73
|
+
uses: pnpm/action-setup@v6
|
|
74
|
+
|
|
75
|
+
- name: Setup Node.js
|
|
76
|
+
uses: actions/setup-node@v6
|
|
77
|
+
with:
|
|
78
|
+
node-version: 24
|
|
79
|
+
cache: pnpm
|
|
80
|
+
registry-url: https://registry.npmjs.org
|
|
81
|
+
|
|
82
|
+
- name: Install dependencies
|
|
83
|
+
run: pnpm install --frozen-lockfile --ignore-scripts
|
|
84
|
+
|
|
85
|
+
- name: Validate tag equals package version
|
|
86
|
+
env:
|
|
87
|
+
TAG: ${{ steps.tag.outputs.value }}
|
|
88
|
+
run: |
|
|
89
|
+
package_version="$(node -p 'require("./package.json").version')"
|
|
90
|
+
if [[ "v$package_version" != "$TAG" ]]; then
|
|
91
|
+
echo "Tag and package.json version mismatch: $TAG vs v$package_version"
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
- name: Build
|
|
96
|
+
run: pnpm build
|
|
97
|
+
|
|
98
|
+
- name: Publish package to npm (Trusted Publishing)
|
|
99
|
+
run: npm publish --access public --provenance
|
|
100
|
+
|
|
101
|
+
- name: Create GitHub Release
|
|
102
|
+
uses: softprops/action-gh-release@v2
|
|
103
|
+
with:
|
|
104
|
+
tag_name: ${{ steps.tag.outputs.value }}
|
|
105
|
+
name: ${{ steps.tag.outputs.value }}
|
|
106
|
+
body: "Release ${{ steps.tag.outputs.value }}"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pnpm lint-staged
|
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,9 @@ function _interopNamespaceDefault(e) {
|
|
|
30
30
|
|
|
31
31
|
var vite__namespace = /*#__PURE__*/_interopNamespaceDefault(vite);
|
|
32
32
|
|
|
33
|
+
function isNumber(v) {
|
|
34
|
+
return typeof v === "number";
|
|
35
|
+
}
|
|
33
36
|
function isUndefined(v) {
|
|
34
37
|
return void 0 === v;
|
|
35
38
|
}
|
|
@@ -211,24 +214,66 @@ function qingkuai(options = {}) {
|
|
|
211
214
|
}
|
|
212
215
|
let virtualFileName;
|
|
213
216
|
const compileRes = compileResultCache.get(fileId);
|
|
214
|
-
const
|
|
217
|
+
const styleDescriptor = compileRes.styleDescriptors[index];
|
|
215
218
|
while (true) {
|
|
216
219
|
const hash = nodeCrypto.randomBytes(6).toString("hex");
|
|
217
|
-
virtualFileName = `${fileId}.${hash}.${
|
|
220
|
+
virtualFileName = `${fileId}.${hash}.${styleDescriptor.lang}`;
|
|
218
221
|
if (!nodeFs.existsSync(virtualFileName)) {
|
|
219
222
|
break;
|
|
220
223
|
}
|
|
221
224
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
...viteConfig
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
let preprocessRes;
|
|
226
|
+
try {
|
|
227
|
+
preprocessRes = await vite__namespace.preprocessCSS(styleDescriptor.code, virtualFileName, {
|
|
228
|
+
...viteConfig,
|
|
229
|
+
css: {
|
|
230
|
+
...viteConfig.css,
|
|
231
|
+
postcss: {
|
|
232
|
+
from: virtualFileName
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
} catch (err) {
|
|
237
|
+
let errorPos = null;
|
|
238
|
+
const lac = new linesAndColumns.LinesAndColumns(styleDescriptor.code);
|
|
239
|
+
switch (styleDescriptor.lang) {
|
|
240
|
+
case "css":
|
|
241
|
+
case "less":
|
|
242
|
+
case "stylus": {
|
|
243
|
+
delete err.loc;
|
|
244
|
+
err.message += `
|
|
245
|
+
|
|
246
|
+
Caused by: "${fileId}".`;
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
case "sass":
|
|
250
|
+
case "scss": {
|
|
251
|
+
if (err.sassMessage) {
|
|
252
|
+
err.message = err.sassMessage;
|
|
253
|
+
}
|
|
254
|
+
if (isNumber(err.line) && isNumber(err.column)) {
|
|
255
|
+
errorPos = lac.indexForLocation({
|
|
256
|
+
line: err.line - 1,
|
|
257
|
+
column: err.column - 1
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
break;
|
|
228
261
|
}
|
|
229
262
|
}
|
|
230
|
-
|
|
231
|
-
|
|
263
|
+
if (isNumber(errorPos) && !isNaN(errorPos)) {
|
|
264
|
+
const loc = lac.locationForIndex(errorPos + styleDescriptor.loc.start.index);
|
|
265
|
+
if (loc) {
|
|
266
|
+
err.loc = {
|
|
267
|
+
file: fileId,
|
|
268
|
+
line: loc.line + 1,
|
|
269
|
+
column: loc.column
|
|
270
|
+
};
|
|
271
|
+
delete err.frame;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return this.error(err);
|
|
275
|
+
}
|
|
276
|
+
if (!cssSourcemap || styleDescriptor.global) {
|
|
232
277
|
return preprocessRes;
|
|
233
278
|
}
|
|
234
279
|
const assertedPreprocessMap = preprocessRes.map;
|
|
@@ -248,8 +293,8 @@ function qingkuai(options = {}) {
|
|
|
248
293
|
offsetSourceMap(
|
|
249
294
|
attachScopeResult.mappings,
|
|
250
295
|
currentSourceIndex,
|
|
251
|
-
|
|
252
|
-
|
|
296
|
+
styleDescriptor.loc.start.line - 1,
|
|
297
|
+
styleDescriptor.loc.start.column - 1
|
|
253
298
|
)
|
|
254
299
|
);
|
|
255
300
|
if (attachScopeResult.error) {
|
|
@@ -271,11 +316,11 @@ function qingkuai(options = {}) {
|
|
|
271
316
|
}
|
|
272
317
|
});
|
|
273
318
|
}
|
|
274
|
-
const preprocessedIndex = new linesAndColumns.LinesAndColumns(
|
|
319
|
+
const preprocessedIndex = new linesAndColumns.LinesAndColumns(styleDescriptor.code).indexForLocation({
|
|
275
320
|
line: preprocessedPosition.line - 1,
|
|
276
321
|
column: preprocessedPosition.column
|
|
277
322
|
}) || 0;
|
|
278
|
-
const position = compileRes.positions[
|
|
323
|
+
const position = compileRes.positions[styleDescriptor.loc.start.index + preprocessedIndex];
|
|
279
324
|
this.error({
|
|
280
325
|
message: attachScopeResult.error.message,
|
|
281
326
|
loc: {
|
|
@@ -383,8 +428,10 @@ function qingkuai(options = {}) {
|
|
|
383
428
|
})
|
|
384
429
|
};
|
|
385
430
|
} catch (err) {
|
|
386
|
-
if (
|
|
387
|
-
err.
|
|
431
|
+
if (compiler.isCompileError(err)) {
|
|
432
|
+
this.error(err.message, err.loc.start.index);
|
|
433
|
+
} else if (err.cause && isNumber(err.cause.pos)) {
|
|
434
|
+
this.error(err, err.cause.pos);
|
|
388
435
|
} else {
|
|
389
436
|
this.error(
|
|
390
437
|
"Qingkuai compile result is invalid. Please report this at https://github.com/qingkuai-js/qingkuai/issues and include your .qk source for reproduction."
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,16 @@ import * as vite from 'vite';
|
|
|
2
2
|
import nodeFs from 'node:fs';
|
|
3
3
|
import nodePath from 'node:path';
|
|
4
4
|
import nodeCrypto from 'node:crypto';
|
|
5
|
-
import { util, compile } from 'qingkuai/compiler';
|
|
5
|
+
import { util, compile, isCompileError } from 'qingkuai/compiler';
|
|
6
6
|
import { LinesAndColumns } from 'lines-and-columns';
|
|
7
7
|
import { decode, encode } from '@jridgewell/sourcemap-codec';
|
|
8
8
|
import postcss from 'postcss';
|
|
9
9
|
import selectorParser from 'postcss-selector-parser';
|
|
10
10
|
import { SourceMapConsumer } from 'source-map-js';
|
|
11
11
|
|
|
12
|
+
function isNumber(v) {
|
|
13
|
+
return typeof v === "number";
|
|
14
|
+
}
|
|
12
15
|
function isUndefined(v) {
|
|
13
16
|
return void 0 === v;
|
|
14
17
|
}
|
|
@@ -190,24 +193,66 @@ function qingkuai(options = {}) {
|
|
|
190
193
|
}
|
|
191
194
|
let virtualFileName;
|
|
192
195
|
const compileRes = compileResultCache.get(fileId);
|
|
193
|
-
const
|
|
196
|
+
const styleDescriptor = compileRes.styleDescriptors[index];
|
|
194
197
|
while (true) {
|
|
195
198
|
const hash = nodeCrypto.randomBytes(6).toString("hex");
|
|
196
|
-
virtualFileName = `${fileId}.${hash}.${
|
|
199
|
+
virtualFileName = `${fileId}.${hash}.${styleDescriptor.lang}`;
|
|
197
200
|
if (!nodeFs.existsSync(virtualFileName)) {
|
|
198
201
|
break;
|
|
199
202
|
}
|
|
200
203
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
...viteConfig
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
let preprocessRes;
|
|
205
|
+
try {
|
|
206
|
+
preprocessRes = await vite.preprocessCSS(styleDescriptor.code, virtualFileName, {
|
|
207
|
+
...viteConfig,
|
|
208
|
+
css: {
|
|
209
|
+
...viteConfig.css,
|
|
210
|
+
postcss: {
|
|
211
|
+
from: virtualFileName
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
} catch (err) {
|
|
216
|
+
let errorPos = null;
|
|
217
|
+
const lac = new LinesAndColumns(styleDescriptor.code);
|
|
218
|
+
switch (styleDescriptor.lang) {
|
|
219
|
+
case "css":
|
|
220
|
+
case "less":
|
|
221
|
+
case "stylus": {
|
|
222
|
+
delete err.loc;
|
|
223
|
+
err.message += `
|
|
224
|
+
|
|
225
|
+
Caused by: "${fileId}".`;
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
case "sass":
|
|
229
|
+
case "scss": {
|
|
230
|
+
if (err.sassMessage) {
|
|
231
|
+
err.message = err.sassMessage;
|
|
232
|
+
}
|
|
233
|
+
if (isNumber(err.line) && isNumber(err.column)) {
|
|
234
|
+
errorPos = lac.indexForLocation({
|
|
235
|
+
line: err.line - 1,
|
|
236
|
+
column: err.column - 1
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
207
240
|
}
|
|
208
241
|
}
|
|
209
|
-
|
|
210
|
-
|
|
242
|
+
if (isNumber(errorPos) && !isNaN(errorPos)) {
|
|
243
|
+
const loc = lac.locationForIndex(errorPos + styleDescriptor.loc.start.index);
|
|
244
|
+
if (loc) {
|
|
245
|
+
err.loc = {
|
|
246
|
+
file: fileId,
|
|
247
|
+
line: loc.line + 1,
|
|
248
|
+
column: loc.column
|
|
249
|
+
};
|
|
250
|
+
delete err.frame;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return this.error(err);
|
|
254
|
+
}
|
|
255
|
+
if (!cssSourcemap || styleDescriptor.global) {
|
|
211
256
|
return preprocessRes;
|
|
212
257
|
}
|
|
213
258
|
const assertedPreprocessMap = preprocessRes.map;
|
|
@@ -227,8 +272,8 @@ function qingkuai(options = {}) {
|
|
|
227
272
|
offsetSourceMap(
|
|
228
273
|
attachScopeResult.mappings,
|
|
229
274
|
currentSourceIndex,
|
|
230
|
-
|
|
231
|
-
|
|
275
|
+
styleDescriptor.loc.start.line - 1,
|
|
276
|
+
styleDescriptor.loc.start.column - 1
|
|
232
277
|
)
|
|
233
278
|
);
|
|
234
279
|
if (attachScopeResult.error) {
|
|
@@ -250,11 +295,11 @@ function qingkuai(options = {}) {
|
|
|
250
295
|
}
|
|
251
296
|
});
|
|
252
297
|
}
|
|
253
|
-
const preprocessedIndex = new LinesAndColumns(
|
|
298
|
+
const preprocessedIndex = new LinesAndColumns(styleDescriptor.code).indexForLocation({
|
|
254
299
|
line: preprocessedPosition.line - 1,
|
|
255
300
|
column: preprocessedPosition.column
|
|
256
301
|
}) || 0;
|
|
257
|
-
const position = compileRes.positions[
|
|
302
|
+
const position = compileRes.positions[styleDescriptor.loc.start.index + preprocessedIndex];
|
|
258
303
|
this.error({
|
|
259
304
|
message: attachScopeResult.error.message,
|
|
260
305
|
loc: {
|
|
@@ -362,8 +407,10 @@ function qingkuai(options = {}) {
|
|
|
362
407
|
})
|
|
363
408
|
};
|
|
364
409
|
} catch (err) {
|
|
365
|
-
if (err
|
|
366
|
-
err.
|
|
410
|
+
if (isCompileError(err)) {
|
|
411
|
+
this.error(err.message, err.loc.start.index);
|
|
412
|
+
} else if (err.cause && isNumber(err.cause.pos)) {
|
|
413
|
+
this.error(err, err.cause.pos);
|
|
367
414
|
} else {
|
|
368
415
|
this.error(
|
|
369
416
|
"Qingkuai compile result is invalid. Please report this at https://github.com/qingkuai-js/qingkuai/issues and include your .qk source for reproduction."
|
package/package.json
CHANGED
|
@@ -1,46 +1,57 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
],
|
|
13
|
-
"exports": {
|
|
14
|
-
".": {
|
|
15
|
-
"import": "./dist/index.js",
|
|
16
|
-
"require": "./dist/index.cjs"
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"scripts": {
|
|
20
|
-
"dev": "rollup -c -w",
|
|
21
|
-
"build": "rimraf dist && tsc && rollup -c && rimraf dist/temp-types",
|
|
22
|
-
"postpublish": "curl -X PUT 'https://registry-direct.npmmirror.com/-/package/vite-plugin-qingkuai/syncs'"
|
|
23
|
-
},
|
|
24
|
-
"devDependencies": {
|
|
25
|
-
"@types/fs-extra": "^11.0.4",
|
|
26
|
-
"@types/node": "^22.13.14",
|
|
27
|
-
"fs-extra": "^11.3.0",
|
|
28
|
-
"qingkuai": "^1.0.45",
|
|
29
|
-
"rimraf": "^6.0.1",
|
|
30
|
-
"rollup": "^4.38.0",
|
|
31
|
-
"rollup-plugin-dts": "^6.2.1",
|
|
32
|
-
"rollup-plugin-esbuild": "^6.2.1",
|
|
33
|
-
"vite": "8.0.0"
|
|
34
|
-
},
|
|
35
|
-
"peerDependencies": {
|
|
36
|
-
"qingkuai": ">=1.0.50",
|
|
37
|
-
"vite": ">=6.2.4 <9"
|
|
38
|
-
},
|
|
39
|
-
"dependencies": {
|
|
40
|
-
"@jridgewell/sourcemap-codec": "^1.5.0",
|
|
41
|
-
"lines-and-columns": "^2.0.4",
|
|
42
|
-
"postcss": "^8.5.3",
|
|
43
|
-
"postcss-selector-parser": "^7.1.0",
|
|
44
|
-
"source-map-js": "^1.2.1"
|
|
2
|
+
"name": "vite-plugin-qingkuai",
|
|
3
|
+
"author": "mlgq",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"version": "1.0.24",
|
|
7
|
+
"packageManager": "pnpm@9.9.0",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"require": "./dist/index.cjs"
|
|
45
12
|
}
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/qingkuai-js/vite-plugin.git"
|
|
17
|
+
},
|
|
18
|
+
"lint-staged": {
|
|
19
|
+
"*.{ts,js,mjs,cjs,json,md,yml,yaml}": "prettier --write"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"dev": "rollup -c -w",
|
|
23
|
+
"release": "node scripts/release.js",
|
|
24
|
+
"build": "rimraf dist && tsc && rollup -c && rimraf dist/temp-types",
|
|
25
|
+
"postpublish": "curl -X PUT 'https://registry-direct.npmmirror.com/-/package/vite-plugin-qingkuai/syncs'"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/fs-extra": "^11.0.4",
|
|
29
|
+
"@types/node": "^22.13.14",
|
|
30
|
+
"fs-extra": "^11.3.0",
|
|
31
|
+
"husky": "^9.1.7",
|
|
32
|
+
"lint-staged": "^17.3.0",
|
|
33
|
+
"qingkuai": "^1.0.83",
|
|
34
|
+
"rimraf": "^6.0.1",
|
|
35
|
+
"rollup": "^4.38.0",
|
|
36
|
+
"rollup-plugin-dts": "^6.2.1",
|
|
37
|
+
"rollup-plugin-esbuild": "^6.2.1",
|
|
38
|
+
"vite": "8.0.0"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"qingkuai": ">=1.0.50",
|
|
42
|
+
"vite": ">=6.2.4 <9"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@jridgewell/sourcemap-codec": "^1.5.0",
|
|
46
|
+
"lines-and-columns": "^2.0.4",
|
|
47
|
+
"postcss": "^8.5.3",
|
|
48
|
+
"postcss-selector-parser": "^7.1.0",
|
|
49
|
+
"source-map-js": "^1.2.1"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"vite",
|
|
53
|
+
"qingkuai",
|
|
54
|
+
"vite plugin",
|
|
55
|
+
"vite-plugin"
|
|
56
|
+
]
|
|
46
57
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import nodeFs from "node:fs"
|
|
3
|
+
import nodePath from "node:path"
|
|
4
|
+
|
|
5
|
+
import { spawnSync } from "node:child_process"
|
|
6
|
+
|
|
7
|
+
const ROOT = nodePath.resolve(process.cwd())
|
|
8
|
+
const PKG_PATH = nodePath.join(ROOT, "package.json")
|
|
9
|
+
|
|
10
|
+
main()
|
|
11
|
+
|
|
12
|
+
function readPackageJson() {
|
|
13
|
+
return JSON.parse(nodeFs.readFileSync(PKG_PATH, "utf-8"))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function writePackageJson(pkg) {
|
|
17
|
+
nodeFs.writeFileSync(PKG_PATH, JSON.stringify(pkg, null, 2) + "\n", "utf-8")
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function bumpVersion(version) {
|
|
21
|
+
const parts = version.split(".").map(Number)
|
|
22
|
+
if (parts.length !== 3 || parts.some(n => Number.isNaN(n) || n < 0)) {
|
|
23
|
+
throw new Error(`Unsupported version format: ${version}`)
|
|
24
|
+
}
|
|
25
|
+
parts[2] += 1
|
|
26
|
+
return parts.join(".")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function run(command, args, opts = {}) {
|
|
30
|
+
const result = spawnSync(command, args, { stdio: "inherit", ...opts })
|
|
31
|
+
if (result.error) {
|
|
32
|
+
throw result.error
|
|
33
|
+
}
|
|
34
|
+
if (result.status !== 0) {
|
|
35
|
+
throw new Error(`Command failed: ${command} ${args.join(" ")}`)
|
|
36
|
+
}
|
|
37
|
+
return result
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function verifyCleanWorkingTree() {
|
|
41
|
+
const result = spawnSync("git", ["status", "--porcelain"], {
|
|
42
|
+
encoding: "utf-8",
|
|
43
|
+
stdio: ["ignore", "pipe", "inherit"]
|
|
44
|
+
})
|
|
45
|
+
if (result.error) {
|
|
46
|
+
throw result.error
|
|
47
|
+
}
|
|
48
|
+
if (result.status !== 0) {
|
|
49
|
+
throw new Error("Failed to check git working tree status")
|
|
50
|
+
}
|
|
51
|
+
if (result.stdout.trim()) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
"Git working tree is not clean. Please commit or stash your changes before releasing."
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function release() {
|
|
59
|
+
verifyCleanWorkingTree()
|
|
60
|
+
const pkg = readPackageJson()
|
|
61
|
+
const currentVersion = pkg.version
|
|
62
|
+
if (!currentVersion) {
|
|
63
|
+
throw new Error("package.json is missing version")
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const arg = process.argv[2]
|
|
67
|
+
const newVersion = arg ? arg.replace(/^v/, "") : bumpVersion(currentVersion)
|
|
68
|
+
const tag = `v${newVersion}`
|
|
69
|
+
|
|
70
|
+
if (newVersion === currentVersion) {
|
|
71
|
+
console.log(`Version unchanged: ${newVersion}`)
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
pkg.version = newVersion
|
|
76
|
+
writePackageJson(pkg)
|
|
77
|
+
|
|
78
|
+
await run("git", ["add", "package.json"])
|
|
79
|
+
await run("git", ["commit", "-m", `release: bump version to ${tag}`])
|
|
80
|
+
await run("git", ["tag", tag])
|
|
81
|
+
await run("git", ["push"])
|
|
82
|
+
await run("git", ["push", "origin", tag])
|
|
83
|
+
|
|
84
|
+
console.log(`Released ${tag}`)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function main() {
|
|
88
|
+
try {
|
|
89
|
+
await release()
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error(error instanceof Error ? error.message : error)
|
|
92
|
+
process.exit(1)
|
|
93
|
+
}
|
|
94
|
+
}
|
package/.vscode/extensions.json
DELETED