@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 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
+ [![npm version](https://img.shields.io/npm/v/@milesight/changelog)](https://www.npmjs.com/package/@milesight/changelog)
6
+ [![license](https://img.shields.io/npm/l/@milesight/changelog)](./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
@@ -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 };
@@ -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
+ }