@webywz/vibe-commit 0.1.7 → 0.1.8

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.
@@ -21,9 +21,13 @@ export declare function detectBreakingKind(diff: StagedDiff, forced?: boolean):
21
21
  export declare function formatBreakingReason(kind: BreakingKind): string;
22
22
  /** Detail text for the BREAKING CHANGE footer, or undefined when not inferred. */
23
23
  export declare function breakingFooterDetail(diff: StagedDiff): string | undefined;
24
+ /** Generic bilingual footer when no better reason (or empty subject) exists. */
25
+ export declare const DEFAULT_BREAKING_FOOTER_DETAIL = "incompatible API change \u00B7 \u4E0D\u517C\u5BB9\u7684 API \u53D8\u66F4";
24
26
  /**
25
27
  * Ensure body carries a conventional BREAKING CHANGE footer when breaking.
26
- * Skips if the body already mentions one. Uses subject as a last-resort reason.
28
+ * Skips if the body already mentions one.
29
+ * Prefers subject when reason is empty or the generic bilingual default.
30
+ * Heuristic major/export/footer-specific bilingual details are kept as-is.
27
31
  */
28
32
  export declare function ensureBreakingFooter(message: ProposedMessage, reason?: string): ProposedMessage;
29
33
  export declare function collectAddedIdentifiers(hunks: DiffHunk[]): string[];
package/dist/heuristic.js CHANGED
@@ -37,7 +37,9 @@ export function proposeHeuristic(input) {
37
37
  engine: "heuristic",
38
38
  breakingReason: kind ? formatBreakingReason(kind) : undefined,
39
39
  };
40
- return ensureBreakingFooter(message, breakingFooterDetail(diff));
40
+ // Forced --breaking: prefer subject in the footer (not bilingual default).
41
+ const footerReason = kind === "forced" ? message.subject : breakingFooterDetail(diff);
42
+ return ensureBreakingFooter(message, footerReason);
41
43
  }
42
44
  export function inferType(diff) {
43
45
  const files = diff.files;
@@ -269,9 +271,13 @@ export function breakingFooterDetail(diff) {
269
271
  }
270
272
  return undefined;
271
273
  }
274
+ /** Generic bilingual footer when no better reason (or empty subject) exists. */
275
+ export const DEFAULT_BREAKING_FOOTER_DETAIL = "incompatible API change · 不兼容的 API 变更";
272
276
  /**
273
277
  * Ensure body carries a conventional BREAKING CHANGE footer when breaking.
274
- * Skips if the body already mentions one. Uses subject as a last-resort reason.
278
+ * Skips if the body already mentions one.
279
+ * Prefers subject when reason is empty or the generic bilingual default.
280
+ * Heuristic major/export/footer-specific bilingual details are kept as-is.
275
281
  */
276
282
  export function ensureBreakingFooter(message, reason) {
277
283
  if (!message.breaking)
@@ -280,8 +286,13 @@ export function ensureBreakingFooter(message, reason) {
280
286
  if (/BREAKING CHANGE:/i.test(body)) {
281
287
  return body === (message.body ?? "") ? message : { ...message, body };
282
288
  }
283
- const detail = (reason ?? message.subject).replace(/\s+/g, " ").trim() ||
284
- "incompatible API change · 不兼容的 API 变更";
289
+ const subject = message.subject.replace(/\s+/g, " ").trim();
290
+ const normalized = (reason ?? "").replace(/\s+/g, " ").trim();
291
+ const useSubject = Boolean(subject) &&
292
+ (!normalized || normalized === DEFAULT_BREAKING_FOOTER_DETAIL);
293
+ const detail = (useSubject ? subject : normalized) ||
294
+ subject ||
295
+ DEFAULT_BREAKING_FOOTER_DETAIL;
285
296
  const footer = `BREAKING CHANGE: ${detail}`;
286
297
  return {
287
298
  ...message,
@@ -298,7 +309,7 @@ function detectBreakingFooter(diff) {
298
309
  }
299
310
  // Presence of the token alone still counts as breaking.
300
311
  if (diff.hunks.some((hunk) => hunk.lines.some((line) => /^\+\s*BREAKING CHANGE:/i.test(line)))) {
301
- return "incompatible API change · 不兼容的 API 变更";
312
+ return DEFAULT_BREAKING_FOOTER_DETAIL;
302
313
  }
303
314
  return undefined;
304
315
  }
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { proposeWithAi } from "./ai.ts";
2
2
  export { formatCommit, parseCommit, normalizeSubject } from "./format.ts";
3
3
  export { inspectStaged, commitWithMessage, GitError } from "./git.ts";
4
- export { proposeHeuristic, inferType, inferScope, inferSubject, inferBreaking, detectBreakingKind, formatBreakingReason, breakingFooterDetail, ensureBreakingFooter, classifyPath, } from "./heuristic.ts";
4
+ export { proposeHeuristic, inferType, inferScope, inferSubject, inferBreaking, detectBreakingKind, formatBreakingReason, breakingFooterDetail, DEFAULT_BREAKING_FOOTER_DETAIL, ensureBreakingFooter, classifyPath, } from "./heuristic.ts";
5
5
  export type { BreakingKind } from "./heuristic.ts";
6
6
  export { parseArgs, helpText, UsageError } from "./parse-args.ts";
7
7
  export { assembleDiff, parseUnifiedDiff } from "./parse-diff.ts";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { proposeWithAi } from "./ai.js";
2
2
  export { formatCommit, parseCommit, normalizeSubject } from "./format.js";
3
3
  export { inspectStaged, commitWithMessage, GitError } from "./git.js";
4
- export { proposeHeuristic, inferType, inferScope, inferSubject, inferBreaking, detectBreakingKind, formatBreakingReason, breakingFooterDetail, ensureBreakingFooter, classifyPath, } from "./heuristic.js";
4
+ export { proposeHeuristic, inferType, inferScope, inferSubject, inferBreaking, detectBreakingKind, formatBreakingReason, breakingFooterDetail, DEFAULT_BREAKING_FOOTER_DETAIL, ensureBreakingFooter, classifyPath, } from "./heuristic.js";
5
5
  export { parseArgs, helpText, UsageError } from "./parse-args.js";
6
6
  export { assembleDiff, parseUnifiedDiff } from "./parse-diff.js";
7
7
  export { installHook, uninstallHook, runPrepareCommitMsg, shouldSkipPrepareCommitMsg, hasNonCommentContent, HOOK_BEGIN, HOOK_END, } from "./hook.js";
package/dist/propose.js CHANGED
@@ -30,6 +30,9 @@ export async function proposeMessage(diff, options, env = process.env) {
30
30
  : breaking
31
31
  ? heuristic.breakingReason ?? message.breakingReason
32
32
  : undefined;
33
- return ensureBreakingFooter({ ...message, breaking, breakingReason }, breakingFooterDetail(diff));
33
+ const withMeta = { ...message, breaking, breakingReason };
34
+ // Forced --breaking: footer uses subject, not bilingual default.
35
+ const footerReason = kind === "forced" ? withMeta.subject : breakingFooterDetail(diff);
36
+ return ensureBreakingFooter(withMeta, footerReason);
34
37
  }
35
38
  //# sourceMappingURL=propose.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webywz/vibe-commit",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Stylish conventional commit messages with personality. Offline-first, AI-optional.",
5
5
  "keywords": [
6
6
  "git",