@milesight/changelog 1.0.0
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/LICENSE +21 -0
- package/README.md +169 -0
- package/dist/index.d.mts +71 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.js +185 -0
- package/dist/index.mjs +157 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Milesight
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# @milesight/changelog
|
|
2
|
+
|
|
3
|
+
> A [Changesets](https://github.com/changesets/changesets) changelog generator with [Conventional Commits](https://www.conventionalcommits.org/) support and built-in i18n.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@milesight/changelog)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Conventional Commits** — Parses `type(scope)!: description` format and maps each type to an emoji automatically
|
|
11
|
+
- **i18n** — Ships with English and Chinese locales; configurable via `.changeset/config.json`
|
|
12
|
+
- **Custom types** — Extend or override the built-in commit type set per project
|
|
13
|
+
- **Rich summary formats** — Supports single-line, title + details, and multiple independent entries
|
|
14
|
+
- **Dual output** — Ships both CJS (`dist/index.js`) and ESM (`dist/index.mjs`) builds
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# npm
|
|
20
|
+
npm add -D @milesight/changelog
|
|
21
|
+
|
|
22
|
+
# pnpm
|
|
23
|
+
pnpm add -D @milesight/changelog
|
|
24
|
+
|
|
25
|
+
# yarn
|
|
26
|
+
yarn add -D @milesight/changelog
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
Set `changelog` in your `.changeset/config.json`:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"changelog": ["@milesight/changelog", { "locale": "en" }]
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
That's it. Run `changeset version` as usual — changelogs are generated automatically.
|
|
40
|
+
|
|
41
|
+
## Options
|
|
42
|
+
|
|
43
|
+
| Option | Type | Default | Description |
|
|
44
|
+
| ------------- | ---------------------------------------- | ------- | ------------------------------------------------ |
|
|
45
|
+
| `locale` | `"en" \| "zh"` | `"en"` | Display language for type labels and UI strings |
|
|
46
|
+
| `customTypes` | `Record<string, TypeConfig>` | — | Additional or overriding commit types |
|
|
47
|
+
|
|
48
|
+
### `TypeConfig`
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
interface TypeConfig {
|
|
52
|
+
/** Emoji to display for this commit type */
|
|
53
|
+
emoji: string;
|
|
54
|
+
/**
|
|
55
|
+
* Localized labels keyed by locale code.
|
|
56
|
+
* Falls back to the English label, then the type key itself.
|
|
57
|
+
*/
|
|
58
|
+
labels?: Partial<Record<'en' | 'zh', string>>;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Built-in Commit Types
|
|
63
|
+
|
|
64
|
+
| Type | Emoji | English Label | Chinese Label |
|
|
65
|
+
| ---------- | ----- | ------------- | ------------- |
|
|
66
|
+
| `feat` | ✨ | New Feature | 新特性 |
|
|
67
|
+
| `fix` | 🐛 | Bug Fix | 问题修复 |
|
|
68
|
+
| `perf` | ⚡ | Performance | 性能优化 |
|
|
69
|
+
| `refactor` | ♻️ | Refactor | 代码重构 |
|
|
70
|
+
| `docs` | 📝 | Documentation | 文档 |
|
|
71
|
+
| `style` | 💅 | Style | 样式 |
|
|
72
|
+
| `test` | ✅ | Tests | 测试 |
|
|
73
|
+
| `build` | 🏗️ | Build | 构建 |
|
|
74
|
+
| `ci` | 👷 | CI/CD | CI/CD |
|
|
75
|
+
| `chore` | 🔧 | Chore | 杂项 |
|
|
76
|
+
| `revert` | ⏪ | Revert | 回退 |
|
|
77
|
+
|
|
78
|
+
Unrecognised types fall back to 📦.
|
|
79
|
+
|
|
80
|
+
## Custom Types
|
|
81
|
+
|
|
82
|
+
Add project-specific commit types via `customTypes`:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"changelog": [
|
|
87
|
+
"@milesight/changelog",
|
|
88
|
+
{
|
|
89
|
+
"locale": "zh",
|
|
90
|
+
"customTypes": {
|
|
91
|
+
"release": {
|
|
92
|
+
"emoji": "🚀",
|
|
93
|
+
"labels": { "en": "Release", "zh": "正式发布" }
|
|
94
|
+
},
|
|
95
|
+
"security": {
|
|
96
|
+
"emoji": "🔒",
|
|
97
|
+
"labels": { "en": "Security", "zh": "安全修复" }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Custom types are **merged** with the built-in set. If a key already exists (e.g. `feat`), the custom entry takes precedence.
|
|
106
|
+
|
|
107
|
+
## Changeset Summary Formats
|
|
108
|
+
|
|
109
|
+
The generator supports four summary formats:
|
|
110
|
+
|
|
111
|
+
**1. Single title**
|
|
112
|
+
```
|
|
113
|
+
fix: resolve null pointer in form submit
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**2. Title + details**
|
|
117
|
+
```
|
|
118
|
+
feat: add theme token system
|
|
119
|
+
- supports light/dark variable sets
|
|
120
|
+
- exposes getCSSVariable helper
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**3. Multiple independent titles**
|
|
124
|
+
```
|
|
125
|
+
feat: add useTheme hook
|
|
126
|
+
fix: correct focus ring on Safari
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**4. Multiple titles each with details** (blank line as separator)
|
|
130
|
+
```
|
|
131
|
+
feat: add useTheme hook
|
|
132
|
+
- supports ThemeProvider injection
|
|
133
|
+
- reactive to system preference
|
|
134
|
+
|
|
135
|
+
fix: correct focus ring on Safari
|
|
136
|
+
- affected input and button components
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Output Example
|
|
140
|
+
|
|
141
|
+
Given a changeset with the summary above, the generated changelog entry looks like:
|
|
142
|
+
|
|
143
|
+
```markdown
|
|
144
|
+
- ✨ add useTheme hook
|
|
145
|
+
- supports ThemeProvider injection
|
|
146
|
+
- reactive to system preference
|
|
147
|
+
|
|
148
|
+
- 🐛 correct focus ring on Safari
|
|
149
|
+
- affected input and button components
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## i18n
|
|
153
|
+
|
|
154
|
+
Switch to Chinese by setting `"locale": "zh"`:
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{ "changelog": ["@milesight/changelog", { "locale": "zh" }] }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Breaking change markers and dependency update messages will then appear in Chinese:
|
|
161
|
+
|
|
162
|
+
```markdown
|
|
163
|
+
- ✨ 重新设计 API 接口 **[破坏性变更]**
|
|
164
|
+
- 📦 依赖 `lodash` 升级至 `4.18.0`
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
[MIT](./LICENSE) © Milesight
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @milesight/changelog - TypeScript type definitions
|
|
3
|
+
*/
|
|
4
|
+
/** Supported locale codes */
|
|
5
|
+
type Locale = 'en' | 'zh';
|
|
6
|
+
/** Configuration for a custom commit type */
|
|
7
|
+
interface TypeConfig {
|
|
8
|
+
/** Emoji to display for this commit type */
|
|
9
|
+
emoji: string;
|
|
10
|
+
/**
|
|
11
|
+
* Localized labels for this type, keyed by locale code.
|
|
12
|
+
* Falls back to the English label, then the type key itself.
|
|
13
|
+
*/
|
|
14
|
+
labels?: Partial<Record<Locale, string>>;
|
|
15
|
+
}
|
|
16
|
+
/** Options passed via .changeset/config.json (second element of changelog array) */
|
|
17
|
+
interface ChangelogOptions {
|
|
18
|
+
/** Display language. Defaults to 'en'. */
|
|
19
|
+
locale?: Locale;
|
|
20
|
+
/**
|
|
21
|
+
* Additional or overriding commit types merged with the built-in set.
|
|
22
|
+
* Use this to add project-specific types or override emoji/labels.
|
|
23
|
+
*/
|
|
24
|
+
customTypes?: Record<string, TypeConfig>;
|
|
25
|
+
}
|
|
26
|
+
type VersionType = 'major' | 'minor' | 'patch';
|
|
27
|
+
interface NewChangeset {
|
|
28
|
+
id: string;
|
|
29
|
+
summary: string;
|
|
30
|
+
releases: Array<{
|
|
31
|
+
name: string;
|
|
32
|
+
type: VersionType;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
interface DependencyRelease {
|
|
36
|
+
name: string;
|
|
37
|
+
type: VersionType;
|
|
38
|
+
newVersion?: string;
|
|
39
|
+
changesets: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @milesight/changelog
|
|
44
|
+
*
|
|
45
|
+
* Changesets changelog generator with Conventional Commits support and i18n.
|
|
46
|
+
*
|
|
47
|
+
* Usage in .changeset/config.json:
|
|
48
|
+
* ```json
|
|
49
|
+
* {
|
|
50
|
+
* "changelog": ["@milesight/changelog", { "locale": "zh" }]
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* Supported locales: "en" (default), "zh"
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Generates the changelog entry line for a single changeset release.
|
|
59
|
+
*
|
|
60
|
+
* Called by @changesets/apply-release-plan for each package in the release.
|
|
61
|
+
*/
|
|
62
|
+
declare function getReleaseLine(changeset: NewChangeset, _type: VersionType, options?: ChangelogOptions): Promise<string>;
|
|
63
|
+
/**
|
|
64
|
+
* Generates the changelog entry line for a dependency version bump.
|
|
65
|
+
*
|
|
66
|
+
* Called by @changesets/apply-release-plan when a package version changes
|
|
67
|
+
* due to a dependency update (not a direct changeset).
|
|
68
|
+
*/
|
|
69
|
+
declare function getDependencyReleaseLine(_changesets: NewChangeset[], dependencyRelease: DependencyRelease, options?: ChangelogOptions): Promise<string | undefined>;
|
|
70
|
+
|
|
71
|
+
export { type ChangelogOptions, type Locale, type TypeConfig, getDependencyReleaseLine, getReleaseLine };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @milesight/changelog - TypeScript type definitions
|
|
3
|
+
*/
|
|
4
|
+
/** Supported locale codes */
|
|
5
|
+
type Locale = 'en' | 'zh';
|
|
6
|
+
/** Configuration for a custom commit type */
|
|
7
|
+
interface TypeConfig {
|
|
8
|
+
/** Emoji to display for this commit type */
|
|
9
|
+
emoji: string;
|
|
10
|
+
/**
|
|
11
|
+
* Localized labels for this type, keyed by locale code.
|
|
12
|
+
* Falls back to the English label, then the type key itself.
|
|
13
|
+
*/
|
|
14
|
+
labels?: Partial<Record<Locale, string>>;
|
|
15
|
+
}
|
|
16
|
+
/** Options passed via .changeset/config.json (second element of changelog array) */
|
|
17
|
+
interface ChangelogOptions {
|
|
18
|
+
/** Display language. Defaults to 'en'. */
|
|
19
|
+
locale?: Locale;
|
|
20
|
+
/**
|
|
21
|
+
* Additional or overriding commit types merged with the built-in set.
|
|
22
|
+
* Use this to add project-specific types or override emoji/labels.
|
|
23
|
+
*/
|
|
24
|
+
customTypes?: Record<string, TypeConfig>;
|
|
25
|
+
}
|
|
26
|
+
type VersionType = 'major' | 'minor' | 'patch';
|
|
27
|
+
interface NewChangeset {
|
|
28
|
+
id: string;
|
|
29
|
+
summary: string;
|
|
30
|
+
releases: Array<{
|
|
31
|
+
name: string;
|
|
32
|
+
type: VersionType;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
interface DependencyRelease {
|
|
36
|
+
name: string;
|
|
37
|
+
type: VersionType;
|
|
38
|
+
newVersion?: string;
|
|
39
|
+
changesets: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @milesight/changelog
|
|
44
|
+
*
|
|
45
|
+
* Changesets changelog generator with Conventional Commits support and i18n.
|
|
46
|
+
*
|
|
47
|
+
* Usage in .changeset/config.json:
|
|
48
|
+
* ```json
|
|
49
|
+
* {
|
|
50
|
+
* "changelog": ["@milesight/changelog", { "locale": "zh" }]
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* Supported locales: "en" (default), "zh"
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Generates the changelog entry line for a single changeset release.
|
|
59
|
+
*
|
|
60
|
+
* Called by @changesets/apply-release-plan for each package in the release.
|
|
61
|
+
*/
|
|
62
|
+
declare function getReleaseLine(changeset: NewChangeset, _type: VersionType, options?: ChangelogOptions): Promise<string>;
|
|
63
|
+
/**
|
|
64
|
+
* Generates the changelog entry line for a dependency version bump.
|
|
65
|
+
*
|
|
66
|
+
* Called by @changesets/apply-release-plan when a package version changes
|
|
67
|
+
* due to a dependency update (not a direct changeset).
|
|
68
|
+
*/
|
|
69
|
+
declare function getDependencyReleaseLine(_changesets: NewChangeset[], dependencyRelease: DependencyRelease, options?: ChangelogOptions): Promise<string | undefined>;
|
|
70
|
+
|
|
71
|
+
export { type ChangelogOptions, type Locale, type TypeConfig, getDependencyReleaseLine, getReleaseLine };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
getDependencyReleaseLine: () => getDependencyReleaseLine,
|
|
24
|
+
getReleaseLine: () => getReleaseLine
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
|
|
28
|
+
// src/locales/en.ts
|
|
29
|
+
var en = {
|
|
30
|
+
breaking: "[Breaking Change]",
|
|
31
|
+
fallbackTitle: "Version update",
|
|
32
|
+
dependencyUpdate: "Dependency `{name}` updated to `{version}`",
|
|
33
|
+
typeLabels: {
|
|
34
|
+
feat: "New Feature",
|
|
35
|
+
fix: "Bug Fix",
|
|
36
|
+
perf: "Performance",
|
|
37
|
+
refactor: "Refactor",
|
|
38
|
+
docs: "Documentation",
|
|
39
|
+
style: "Style",
|
|
40
|
+
test: "Tests",
|
|
41
|
+
build: "Build",
|
|
42
|
+
ci: "CI/CD",
|
|
43
|
+
chore: "Chore",
|
|
44
|
+
revert: "Revert"
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var en_default = en;
|
|
48
|
+
|
|
49
|
+
// src/locales/zh.ts
|
|
50
|
+
var zh = {
|
|
51
|
+
breaking: "[\u7834\u574F\u6027\u53D8\u66F4]",
|
|
52
|
+
fallbackTitle: "\u7248\u672C\u66F4\u65B0",
|
|
53
|
+
dependencyUpdate: "\u4F9D\u8D56 `{name}` \u5347\u7EA7\u81F3 `{version}`",
|
|
54
|
+
typeLabels: {
|
|
55
|
+
feat: "\u65B0\u7279\u6027",
|
|
56
|
+
fix: "\u95EE\u9898\u4FEE\u590D",
|
|
57
|
+
perf: "\u6027\u80FD\u4F18\u5316",
|
|
58
|
+
refactor: "\u4EE3\u7801\u91CD\u6784",
|
|
59
|
+
docs: "\u6587\u6863",
|
|
60
|
+
style: "\u6837\u5F0F",
|
|
61
|
+
test: "\u6D4B\u8BD5",
|
|
62
|
+
build: "\u6784\u5EFA",
|
|
63
|
+
ci: "CI/CD",
|
|
64
|
+
chore: "\u6742\u9879",
|
|
65
|
+
revert: "\u56DE\u9000"
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
var zh_default = zh;
|
|
69
|
+
|
|
70
|
+
// src/locales/index.ts
|
|
71
|
+
var LOCALES = { en: en_default, zh: zh_default };
|
|
72
|
+
function getLocale(locale) {
|
|
73
|
+
return LOCALES[locale ?? "en"] ?? en_default;
|
|
74
|
+
}
|
|
75
|
+
function interpolate(template, vars) {
|
|
76
|
+
return template.replace(/\{(\w+)\}/g, (_, key) => vars[key] ?? "");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/parser.ts
|
|
80
|
+
var EMOJI_MAP = {
|
|
81
|
+
feat: "\u2728",
|
|
82
|
+
fix: "\u{1F41B}",
|
|
83
|
+
perf: "\u26A1",
|
|
84
|
+
refactor: "\u267B\uFE0F",
|
|
85
|
+
docs: "\u{1F4DD}",
|
|
86
|
+
style: "\u{1F485}",
|
|
87
|
+
test: "\u2705",
|
|
88
|
+
build: "\u{1F3D7}\uFE0F",
|
|
89
|
+
ci: "\u{1F477}",
|
|
90
|
+
chore: "\u{1F527}",
|
|
91
|
+
revert: "\u23EA"
|
|
92
|
+
};
|
|
93
|
+
var DEFAULT_EMOJI = "\u{1F4E6}";
|
|
94
|
+
function parseCommitSummary(line, resolvedTypeMap) {
|
|
95
|
+
const match = line.match(/^(\w+)(?:\([\w\-*]+\))?(!)?\s*:\s*(.+)/);
|
|
96
|
+
if (!match) {
|
|
97
|
+
return {
|
|
98
|
+
emoji: DEFAULT_EMOJI,
|
|
99
|
+
label: "Change",
|
|
100
|
+
description: line.trim(),
|
|
101
|
+
isBreaking: false
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const [, type, breaking, description] = match;
|
|
105
|
+
const typeInfo = resolvedTypeMap[type.toLowerCase()] ?? { emoji: DEFAULT_EMOJI, label: type };
|
|
106
|
+
return {
|
|
107
|
+
...typeInfo,
|
|
108
|
+
description: description.trim(),
|
|
109
|
+
isBreaking: breaking === "!"
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function parseEntries(summary) {
|
|
113
|
+
const entries = [];
|
|
114
|
+
let current = null;
|
|
115
|
+
for (const raw of summary.split("\n")) {
|
|
116
|
+
const line = raw.trim();
|
|
117
|
+
if (!line) continue;
|
|
118
|
+
if (/^[-*]\s/.test(line)) {
|
|
119
|
+
if (current) {
|
|
120
|
+
current.details.push(line.replace(/^[-*]\s*/, "").trim());
|
|
121
|
+
} else {
|
|
122
|
+
entries.push({ title: line, details: [] });
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
if (current) entries.push(current);
|
|
126
|
+
current = { title: line, details: [] };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (current) entries.push(current);
|
|
130
|
+
return entries;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/index.ts
|
|
134
|
+
function buildTypeMap(t, locale, customTypes) {
|
|
135
|
+
const map = {};
|
|
136
|
+
for (const [type, emoji] of Object.entries(EMOJI_MAP)) {
|
|
137
|
+
map[type] = { emoji, label: t.typeLabels[type] ?? type };
|
|
138
|
+
}
|
|
139
|
+
if (customTypes) {
|
|
140
|
+
for (const [type, config] of Object.entries(customTypes)) {
|
|
141
|
+
const label = config.labels?.[locale] ?? config.labels?.en ?? type;
|
|
142
|
+
map[type] = { emoji: config.emoji, label };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return map;
|
|
146
|
+
}
|
|
147
|
+
async function getReleaseLine(changeset, _type, options) {
|
|
148
|
+
const locale = options?.locale ?? "en";
|
|
149
|
+
const t = getLocale(locale);
|
|
150
|
+
const typeMap = buildTypeMap(t, locale, options?.customTypes);
|
|
151
|
+
const entries = parseEntries(changeset.summary);
|
|
152
|
+
if (entries.length === 0) {
|
|
153
|
+
return `
|
|
154
|
+
|
|
155
|
+
- ${DEFAULT_EMOJI} ${t.fallbackTitle}`;
|
|
156
|
+
}
|
|
157
|
+
const formatted = entries.map(({ title, details }) => {
|
|
158
|
+
const { emoji, description, isBreaking } = parseCommitSummary(title, typeMap);
|
|
159
|
+
const breakingMark = isBreaking ? ` **${t.breaking}**` : "";
|
|
160
|
+
const header = `- ${emoji} ${description}${breakingMark}`;
|
|
161
|
+
if (details.length === 0) return header;
|
|
162
|
+
const detailLines = details.map((d) => ` - ${d}`);
|
|
163
|
+
return `${header}
|
|
164
|
+
${detailLines.join("\n")}`;
|
|
165
|
+
});
|
|
166
|
+
return `
|
|
167
|
+
|
|
168
|
+
${formatted.join("\n\n")}`;
|
|
169
|
+
}
|
|
170
|
+
async function getDependencyReleaseLine(_changesets, dependencyRelease, options) {
|
|
171
|
+
if (!dependencyRelease.newVersion) return void 0;
|
|
172
|
+
const t = getLocale(options?.locale);
|
|
173
|
+
const message = interpolate(t.dependencyUpdate, {
|
|
174
|
+
name: dependencyRelease.name,
|
|
175
|
+
version: dependencyRelease.newVersion
|
|
176
|
+
});
|
|
177
|
+
return `
|
|
178
|
+
|
|
179
|
+
- ${DEFAULT_EMOJI} ${message}`;
|
|
180
|
+
}
|
|
181
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
182
|
+
0 && (module.exports = {
|
|
183
|
+
getDependencyReleaseLine,
|
|
184
|
+
getReleaseLine
|
|
185
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// src/locales/en.ts
|
|
2
|
+
var en = {
|
|
3
|
+
breaking: "[Breaking Change]",
|
|
4
|
+
fallbackTitle: "Version update",
|
|
5
|
+
dependencyUpdate: "Dependency `{name}` updated to `{version}`",
|
|
6
|
+
typeLabels: {
|
|
7
|
+
feat: "New Feature",
|
|
8
|
+
fix: "Bug Fix",
|
|
9
|
+
perf: "Performance",
|
|
10
|
+
refactor: "Refactor",
|
|
11
|
+
docs: "Documentation",
|
|
12
|
+
style: "Style",
|
|
13
|
+
test: "Tests",
|
|
14
|
+
build: "Build",
|
|
15
|
+
ci: "CI/CD",
|
|
16
|
+
chore: "Chore",
|
|
17
|
+
revert: "Revert"
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
var en_default = en;
|
|
21
|
+
|
|
22
|
+
// src/locales/zh.ts
|
|
23
|
+
var zh = {
|
|
24
|
+
breaking: "[\u7834\u574F\u6027\u53D8\u66F4]",
|
|
25
|
+
fallbackTitle: "\u7248\u672C\u66F4\u65B0",
|
|
26
|
+
dependencyUpdate: "\u4F9D\u8D56 `{name}` \u5347\u7EA7\u81F3 `{version}`",
|
|
27
|
+
typeLabels: {
|
|
28
|
+
feat: "\u65B0\u7279\u6027",
|
|
29
|
+
fix: "\u95EE\u9898\u4FEE\u590D",
|
|
30
|
+
perf: "\u6027\u80FD\u4F18\u5316",
|
|
31
|
+
refactor: "\u4EE3\u7801\u91CD\u6784",
|
|
32
|
+
docs: "\u6587\u6863",
|
|
33
|
+
style: "\u6837\u5F0F",
|
|
34
|
+
test: "\u6D4B\u8BD5",
|
|
35
|
+
build: "\u6784\u5EFA",
|
|
36
|
+
ci: "CI/CD",
|
|
37
|
+
chore: "\u6742\u9879",
|
|
38
|
+
revert: "\u56DE\u9000"
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var zh_default = zh;
|
|
42
|
+
|
|
43
|
+
// src/locales/index.ts
|
|
44
|
+
var LOCALES = { en: en_default, zh: zh_default };
|
|
45
|
+
function getLocale(locale) {
|
|
46
|
+
return LOCALES[locale ?? "en"] ?? en_default;
|
|
47
|
+
}
|
|
48
|
+
function interpolate(template, vars) {
|
|
49
|
+
return template.replace(/\{(\w+)\}/g, (_, key) => vars[key] ?? "");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/parser.ts
|
|
53
|
+
var EMOJI_MAP = {
|
|
54
|
+
feat: "\u2728",
|
|
55
|
+
fix: "\u{1F41B}",
|
|
56
|
+
perf: "\u26A1",
|
|
57
|
+
refactor: "\u267B\uFE0F",
|
|
58
|
+
docs: "\u{1F4DD}",
|
|
59
|
+
style: "\u{1F485}",
|
|
60
|
+
test: "\u2705",
|
|
61
|
+
build: "\u{1F3D7}\uFE0F",
|
|
62
|
+
ci: "\u{1F477}",
|
|
63
|
+
chore: "\u{1F527}",
|
|
64
|
+
revert: "\u23EA"
|
|
65
|
+
};
|
|
66
|
+
var DEFAULT_EMOJI = "\u{1F4E6}";
|
|
67
|
+
function parseCommitSummary(line, resolvedTypeMap) {
|
|
68
|
+
const match = line.match(/^(\w+)(?:\([\w\-*]+\))?(!)?\s*:\s*(.+)/);
|
|
69
|
+
if (!match) {
|
|
70
|
+
return {
|
|
71
|
+
emoji: DEFAULT_EMOJI,
|
|
72
|
+
label: "Change",
|
|
73
|
+
description: line.trim(),
|
|
74
|
+
isBreaking: false
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const [, type, breaking, description] = match;
|
|
78
|
+
const typeInfo = resolvedTypeMap[type.toLowerCase()] ?? { emoji: DEFAULT_EMOJI, label: type };
|
|
79
|
+
return {
|
|
80
|
+
...typeInfo,
|
|
81
|
+
description: description.trim(),
|
|
82
|
+
isBreaking: breaking === "!"
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function parseEntries(summary) {
|
|
86
|
+
const entries = [];
|
|
87
|
+
let current = null;
|
|
88
|
+
for (const raw of summary.split("\n")) {
|
|
89
|
+
const line = raw.trim();
|
|
90
|
+
if (!line) continue;
|
|
91
|
+
if (/^[-*]\s/.test(line)) {
|
|
92
|
+
if (current) {
|
|
93
|
+
current.details.push(line.replace(/^[-*]\s*/, "").trim());
|
|
94
|
+
} else {
|
|
95
|
+
entries.push({ title: line, details: [] });
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
if (current) entries.push(current);
|
|
99
|
+
current = { title: line, details: [] };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (current) entries.push(current);
|
|
103
|
+
return entries;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// src/index.ts
|
|
107
|
+
function buildTypeMap(t, locale, customTypes) {
|
|
108
|
+
const map = {};
|
|
109
|
+
for (const [type, emoji] of Object.entries(EMOJI_MAP)) {
|
|
110
|
+
map[type] = { emoji, label: t.typeLabels[type] ?? type };
|
|
111
|
+
}
|
|
112
|
+
if (customTypes) {
|
|
113
|
+
for (const [type, config] of Object.entries(customTypes)) {
|
|
114
|
+
const label = config.labels?.[locale] ?? config.labels?.en ?? type;
|
|
115
|
+
map[type] = { emoji: config.emoji, label };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return map;
|
|
119
|
+
}
|
|
120
|
+
async function getReleaseLine(changeset, _type, options) {
|
|
121
|
+
const locale = options?.locale ?? "en";
|
|
122
|
+
const t = getLocale(locale);
|
|
123
|
+
const typeMap = buildTypeMap(t, locale, options?.customTypes);
|
|
124
|
+
const entries = parseEntries(changeset.summary);
|
|
125
|
+
if (entries.length === 0) {
|
|
126
|
+
return `
|
|
127
|
+
|
|
128
|
+
- ${DEFAULT_EMOJI} ${t.fallbackTitle}`;
|
|
129
|
+
}
|
|
130
|
+
const formatted = entries.map(({ title, details }) => {
|
|
131
|
+
const { emoji, description, isBreaking } = parseCommitSummary(title, typeMap);
|
|
132
|
+
const breakingMark = isBreaking ? ` **${t.breaking}**` : "";
|
|
133
|
+
const header = `- ${emoji} ${description}${breakingMark}`;
|
|
134
|
+
if (details.length === 0) return header;
|
|
135
|
+
const detailLines = details.map((d) => ` - ${d}`);
|
|
136
|
+
return `${header}
|
|
137
|
+
${detailLines.join("\n")}`;
|
|
138
|
+
});
|
|
139
|
+
return `
|
|
140
|
+
|
|
141
|
+
${formatted.join("\n\n")}`;
|
|
142
|
+
}
|
|
143
|
+
async function getDependencyReleaseLine(_changesets, dependencyRelease, options) {
|
|
144
|
+
if (!dependencyRelease.newVersion) return void 0;
|
|
145
|
+
const t = getLocale(options?.locale);
|
|
146
|
+
const message = interpolate(t.dependencyUpdate, {
|
|
147
|
+
name: dependencyRelease.name,
|
|
148
|
+
version: dependencyRelease.newVersion
|
|
149
|
+
});
|
|
150
|
+
return `
|
|
151
|
+
|
|
152
|
+
- ${DEFAULT_EMOJI} ${message}`;
|
|
153
|
+
}
|
|
154
|
+
export {
|
|
155
|
+
getDependencyReleaseLine,
|
|
156
|
+
getReleaseLine
|
|
157
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@milesight/changelog",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Changesets changelog generator with Conventional Commits support and i18n",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"changesets",
|
|
7
|
+
"changelog",
|
|
8
|
+
"conventional-commits",
|
|
9
|
+
"i18n",
|
|
10
|
+
"monorepo"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Milesight",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"module": "./dist/index.mjs",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/index.mjs",
|
|
26
|
+
"require": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public",
|
|
31
|
+
"registry": "https://registry.npmjs.org/"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@changesets/cli": ">=2.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@milesight/spec": "^1.0.5",
|
|
38
|
+
"tsup": "^8.5.1",
|
|
39
|
+
"typescript": "^5.9.3"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
43
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
44
|
+
"clean": "rm -rf dist",
|
|
45
|
+
"lint": "eslint . --cache --cache-location=./node_modules/.cache/.eslintcache",
|
|
46
|
+
"lint:fix": "eslint . --fix --cache --cache-location=./node_modules/.cache/.eslintcache"
|
|
47
|
+
}
|
|
48
|
+
}
|