Skip to content

Commit 9b44372

Browse files
committed
feat(plugin-security): 增加安全插件
1 parent a8a27df commit 9b44372

9 files changed

Lines changed: 3522 additions & 1651 deletions

File tree

.github/workflows/release.yml

Lines changed: 109 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,128 @@
1-
# This action will publish the package to npm and create a GitHub release.
21
name: Release
32

43
on:
5-
# Run `npm run bump` to bump the version and create a git tag.
64
push:
75
tags:
8-
- "v*"
9-
6+
- 'v*'
107
workflow_dispatch:
11-
12-
permissions:
13-
contents: write
14-
id-token: write
8+
inputs:
9+
version:
10+
description: '发布版本 (例如: 1.0.0)'
11+
required: true
12+
type: string
1513

1614
jobs:
17-
publish:
15+
release:
1816
runs-on: ubuntu-latest
17+
permissions:
18+
contents: write
19+
packages: write
20+
id-token: write
21+
1922
steps:
20-
- name: Checkout
23+
- name: 检出代码
2124
uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0
2227

23-
- name: Install Pnpm
24-
run: corepack enable
25-
26-
- name: Setup Node.js
28+
- name: 设置 Node.js
2729
uses: actions/setup-node@v4
2830
with:
29-
node-version: 22
30-
cache: "pnpm"
31+
node-version: '18'
32+
registry-url: 'https://registry.npmjs.org'
33+
34+
- name: 安装 pnpm
35+
uses: pnpm/action-setup@v4
36+
with:
37+
version: 10
3138

32-
- name: Install Dependencies
33-
run: pnpm install
39+
- name: 获取 pnpm store 目录
40+
shell: bash
41+
run: |
42+
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
3443
35-
- name: Publish
36-
uses: JS-DevTools/npm-publish@v3
44+
- name: 设置 pnpm 缓存
45+
uses: actions/cache@v4
3746
with:
38-
token: ${{ secrets.NPM_TOKEN }}
47+
path: ${{ env.STORE_PATH }}
48+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
49+
restore-keys: |
50+
${{ runner.os }}-pnpm-store-
51+
52+
- name: 安装依赖
53+
run: |
54+
# 尝试使用 frozen lockfile,如果失败则更新 lockfile
55+
pnpm install --frozen-lockfile || {
56+
echo "⚠️ Lockfile 不匹配,正在更新..."
57+
pnpm install --no-frozen-lockfile
58+
}
3959
40-
- name: Create GitHub Release
41-
uses: ncipollo/release-action@v1
60+
- name: 格式检查
61+
run: pnpm run lint
62+
63+
- name: 构建项目
64+
run: pnpm run build
65+
66+
- name: 获取版本号
67+
id: get_version
68+
run: |
69+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
70+
echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
71+
echo "tag_name=v${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
72+
else
73+
echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
74+
echo "tag_name=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
75+
fi
76+
77+
- name: 更新版本号 (手动触发时)
78+
if: github.event_name == 'workflow_dispatch'
79+
run: |
80+
npm version ${{ steps.get_version.outputs.version }} --no-git-tag-version
81+
git config --local user.email "action@github.com"
82+
git config --local user.name "GitHub Action"
83+
git add package.json
84+
git commit -m "chore: bump version to ${{ steps.get_version.outputs.version }}"
85+
git tag ${{ steps.get_version.outputs.tag_name }}
86+
git push origin HEAD:${{ github.ref_name }}
87+
git push origin ${{ steps.get_version.outputs.tag_name }}
88+
89+
- name: 生成变更日志
90+
id: changelog
91+
run: |
92+
# 获取上一个标签
93+
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
94+
95+
if [ -z "$PREV_TAG" ]; then
96+
# 如果没有上一个标签,获取所有提交
97+
CHANGELOG=$(git log --pretty=format:"- %s (%h)" --no-merges)
98+
else
99+
# 获取两个标签之间的提交
100+
CHANGELOG=$(git log ${PREV_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges)
101+
fi
102+
103+
# 保存到文件以避免特殊字符问题
104+
echo "$CHANGELOG" > changelog.txt
105+
echo "changelog_file=changelog.txt" >> $GITHUB_OUTPUT
106+
107+
- name: 发布到 npm
108+
run: pnpm publish --no-git-checks
109+
env:
110+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
111+
112+
- name: 创建 GitHub Release
113+
uses: actions/create-release@v1
114+
env:
115+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42116
with:
43-
generateReleaseNotes: "true"
117+
tag_name: ${{ steps.get_version.outputs.tag_name }}
118+
release_name: Release ${{ steps.get_version.outputs.tag_name }}
119+
body_path: ${{ steps.changelog.outputs.changelog_file }}
120+
draft: false
121+
prerelease: false
122+
123+
- name: 通知发布成功
124+
run: |
125+
echo "🎉 发布成功!"
126+
echo "📦 版本: ${{ steps.get_version.outputs.version }}"
127+
echo "🏷️ 标签: ${{ steps.get_version.outputs.tag_name }}"
128+
echo "📝 npm: https://www.npmjs.com/package/@winner-fed/plugin-check-syntax"

.github/workflows/test.yml

Lines changed: 0 additions & 39 deletions
This file was deleted.

README.md

Lines changed: 72 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,90 @@
1-
# winjs-plugin-example
1+
# winjs-plugin-security
22

3-
Example plugin for WinJS.
3+
一个为 WinJS 项目提供安全增强功能的插件,主要用于生成 SRI(Subresource Integrity)属性。
44

5-
<p>
6-
<a href="https://npmjs.com/package/winjs-plugin-example">
7-
<img src="https://img.shields.io/npm/v/winjs-plugin-example?style=flat-square&colorA=564341&colorB=EDED91" alt="npm version" />
8-
</a>
9-
<img src="https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square&colorA=564341&colorB=EDED91" alt="license" />
10-
<a href="https://npmcharts.com/compare/winjs-plugin-example?minimal=true"><img src="https://img.shields.io/npm/dm/winjs-plugin-example.svg?style=flat-square&colorA=564341&colorB=EDED91" alt="downloads" /></a>
11-
</p>
5+
## 功能特性
126

13-
## Usage
7+
- 自动为 HTML 文件中的 `<script>``<link>` 标签生成 SRI 属性
8+
- 支持 SHA-512 哈希算法
9+
- 自动添加 `crossorigin="anonymous"` 属性以确保 SRI 正常工作
10+
- 仅在生产环境下生效,开发环境自动跳过
1411

15-
Install:
12+
## 安装
1613

1714
```bash
18-
npm add winjs-plugin-example -D
15+
pnpm add @winner-fed/winjs-plugin-security
1916
```
2017

21-
Add plugin to your `.winrc.ts`:
18+
## 使用方法
2219

23-
```ts
24-
// .winrc.ts
25-
export default {
26-
plugins: ['winjs-plugin-example'],
27-
// 开启配置
28-
example: {}
29-
};
20+
在你的 `.winrc.ts` 配置文件中添加插件配置:
21+
22+
```typescript
23+
import { defineConfig } from '@winner-fed/winjs';
24+
25+
export default defineConfig({
26+
plugins: ['@winner-fed/winjs-plugin-security'],
27+
security: {
28+
sri: true // 启用 SRI 功能
29+
},
30+
});
3031
```
3132

32-
## Options
33+
## 配置选项
34+
35+
### `sri`
36+
37+
- **类型**: `boolean`
38+
- **默认值**: 需要手动设置
39+
- **描述**: 是否启用 SRI(子资源完整性)功能
40+
41+
当设置为 `true` 时,插件会:
42+
43+
1. 扫描构建后的 HTML 文件
44+
2. 为所有带有 `src` 属性的 `<script>` 标签添加 `integrity` 属性
45+
3. 为所有带有 `href` 属性的 `<link>` 标签添加 `integrity` 属性
46+
4. 自动添加 `crossorigin="anonymous"` 属性(如果不存在)
3347

34-
### foo
48+
## 示例
3549

36-
Some description.
50+
### 输入 HTML
3751

38-
- Type: `string`
39-
- Default: `undefined`
40-
- Example:
52+
```html
53+
<!DOCTYPE html>
54+
<html>
55+
<head>
56+
<link rel="stylesheet" href="/assets/app.css">
57+
</head>
58+
<body>
59+
<script src="/assets/app.js"></script>
60+
</body>
61+
</html>
62+
```
63+
64+
### 输出 HTML(启用 SRI 后)
4165

42-
```js
43-
export default {
44-
plugins: ['winjs-plugin-example'],
45-
// 开启配置
46-
example: {
47-
foo: 'bar'
48-
}
49-
};
66+
```html
67+
<!DOCTYPE html>
68+
<html>
69+
<head>
70+
<link rel="stylesheet" href="/assets/app.css" integrity="sha512-ABC123..." crossorigin="anonymous">
71+
</head>
72+
<body>
73+
<script src="/assets/app.js" integrity="sha512-XYZ789..." crossorigin="anonymous"></script>
74+
</body>
75+
</html>
5076
```
5177

52-
## License
78+
## 安全说明
79+
80+
SRI(子资源完整性)是一种安全特性,允许浏览器验证获取的资源(例如从 CDN 获取的资源)没有被恶意修改。当浏览器加载资源时,会计算资源的哈希值并与 `integrity` 属性中指定的哈希值进行比较。如果哈希值不匹配,浏览器将拒绝加载该资源。
81+
82+
## 注意事项
83+
84+
1. 此插件仅在生产构建时生效,开发环境会自动跳过
85+
2. 需要确保资源文件在构建输出目录中可访问
86+
3. `integrity` 属性必须与 `crossorigin` 属性配合使用才能正常工作
87+
88+
## 许可证
5389

54-
[MIT](./LICENSE).
90+
MIT

biome.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
"linter": {
2626
"enabled": true,
2727
"rules": {
28-
"recommended": true
28+
"recommended": true,
29+
"suspicious": {
30+
"noExplicitAny": "off"
31+
}
2932
}
3033
}
3134
}

package.json

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"name": "winjs-plugin-example",
2+
"name": "@winner-fed/winjs-plugin-security",
33
"version": "0.0.0",
4-
"repository": "https://github.com/winjs-dev/winjs-plugin-template",
4+
"repository": "https://github.com/winjs-dev/winjs-plugin-security",
55
"license": "MIT",
66
"type": "module",
77
"exports": {
@@ -30,8 +30,8 @@
3030
"devDependencies": {
3131
"@biomejs/biome": "^1.9.4",
3232
"@playwright/test": "^1.49.0",
33-
"@winner-fed/winjs": "^0.11.21",
34-
"@winner-fed/utils": "^0.11.21",
33+
"@winner-fed/winjs": "^0.15.0",
34+
"@winner-fed/utils": "^0.15.0",
3535
"@rslib/core": "^0.1.1",
3636
"@types/node": "^22.10.1",
3737
"playwright": "^1.49.0",
@@ -40,8 +40,8 @@
4040
},
4141
"peerDependencies": {
4242
"@rsbuild/core": "1.x",
43-
"@winner-fed/winjs": "^0.11.21",
44-
"@winner-fed/utils": "^0.11.21"
43+
"@winner-fed/winjs": "^0.15.0",
44+
"@winner-fed/utils": "^0.15.0"
4545
},
4646
"peerDependenciesMeta": {
4747
"@rsbuild/core": {
@@ -51,7 +51,6 @@
5151
"optional": true
5252
}
5353
},
54-
"packageManager": "pnpm@9.14.4",
5554
"publishConfig": {
5655
"access": "public",
5756
"registry": "https://registry.npmjs.org/"

playground/.winrc.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { defineConfig } from 'win';
22

33
export default defineConfig({
44
plugins: ['../src'],
5-
example: {
6-
foo: 'bar',
5+
security: {
6+
sri: true,
77
},
88
});

0 commit comments

Comments
 (0)