Skip to content

feat(toc): add configurable badge style (number/katakana/roman)#446

Open
Dawn6666666 wants to merge 1 commit into
LyraVoid:masterfrom
Dawn6666666:feat/toc-badge-style
Open

feat(toc): add configurable badge style (number/katakana/roman)#446
Dawn6666666 wants to merge 1 commit into
LyraVoid:masterfrom
Dawn6666666:feat/toc-badge-style

Conversation

@Dawn6666666
Copy link
Copy Markdown

@Dawn6666666 Dawn6666666 commented Apr 28, 2026

Summary

  • add badgeStyle support for TOC badges while keeping useJapaneseBadge as a deprecated compatibility option
  • centralize badge generation through getTOCBadge() and runtime validation through normalizeTOCBadgeStyle()
  • limit roman badge output to single-character numerals (-) so fixed-width badge layouts do not overflow

Validation

  • pnpm exec astro check

Copilot AI review requested due to automatic review settings April 28, 2026 12:26
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR replaces the legacy useJapaneseBadge boolean TOC option with a more flexible badgeStyle field (supporting "number", "katakana", and "roman"), while keeping backward compatibility by falling back to useJapaneseBadge when badgeStyle is not provided.

Changes:

  • Introduces badgeStyle across config types and frontend consumers, with fallback behavior for useJapaneseBadge.
  • Centralizes badge generation via getTOCBadge() and adds a Roman numeral character set.
  • Updates TOC renderers (sidebar/floating/card/mobile) and the config carrier to pass/consume badgeStyle.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/utils/tocManager.ts Adds badgeStyle support and uses shared getTOCBadge() for badge generation.
src/types/config.ts Adds badgeStyle to site config TOC options and marks useJapaneseBadge as deprecated.
src/global.d.ts Extends global TOC config typing with badgeStyle.
src/config.ts Updates example/default config to use badgeStyle: "katakana".
src/components/widgets/card-toc/CardTOC.astro Passes badgeStyle through data-* and into TOCManager.
src/components/misc/ConfigCarrier.astro Ships badgeStyle to window.siteConfig and keeps a compatibility boolean.
src/components/features/toc/utils/toc-utils.ts Switches TOC item badge generation to getTOCBadge() and adds badgeStyle to config getter.
src/components/features/toc/utils/toc-calculator.ts Replaces boolean badge selection with badgeStyle + getTOCBadge().
src/components/features/toc/utils/japanese-katakana.ts Adds ROMAN_NUMERALS, introduces TOCBadgeStyle, and unifies badge generation in getTOCBadge().
src/components/features/toc/types/toc.ts Updates TOC types to include badgeStyle and deprecate useJapaneseBadge.
src/components/features/toc/types.ts Mirrors TOC type updates for shared exports.
src/components/features/toc/index.ts Re-exports getTOCBadge, ROMAN_NUMERALS, and TOCBadgeStyle.
src/components/features/toc/hooks/useTocNavigation.ts Adds badgeStyle to returned config and derives legacy boolean.
src/components/features/toc/hooks/useMobileTOC.ts Updates mobile TOC badge generation to use getTOCBadge() + badgeStyle.
src/components/features/toc/SidebarTOC.astro Updates sidebar badge rendering to use getTOCBadge() with badgeStyle.
src/components/features/toc/FloatingTOC.astro Updates floating TOC wrapper to carry badgeStyle.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +69 to +104
/**
* 罗马数字字符集(30 个)
* Ⅰ-Ⅻ 使用 Unicode 罗马数字字符,XIII-XXX 使用拉丁字母
*/
export const ROMAN_NUMERALS = [
"Ⅰ",
"Ⅱ",
"Ⅲ",
"Ⅳ",
"Ⅴ",
"Ⅵ",
"Ⅶ",
"Ⅷ",
"Ⅸ",
"Ⅹ",
"Ⅺ",
"Ⅻ",
"XIII",
"XIV",
"XV",
"XVI",
"XVII",
"XVIII",
"XIX",
"XX",
"XXI",
"XXII",
"XXIII",
"XXIV",
"XXV",
"XXVI",
"XXVII",
"XXVIII",
"XXIX",
"XXX",
] as const;
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ROMAN_NUMERALS contains multi-character strings (e.g. "XXVIII"), but TOC badge containers are fixed-width (e.g. .toc-badge { width: 1.35rem; } in src/styles/toc.css). This will likely overflow/clip and break layout for posts with many top-level headings. Consider either (a) limiting roman output to a range that stays single-character (e.g. Ⅰ–Ⅻ) and falling back to numbers beyond that, or (b) updating badge CSS to support variable-width/padding specifically for the roman style.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines +83 to +92
toc?: { depth?: number; badgeStyle?: string; useJapaneseBadge?: boolean };
};
}
).siteConfig;
const badgeStyle = (siteConfig?.toc?.badgeStyle as "number" | "katakana" | "roman") ??
(siteConfig?.toc?.useJapaneseBadge ? "katakana" : "number");
return {
depth: siteConfig?.toc?.depth ?? 3,
useJapaneseBadge: siteConfig?.toc?.useJapaneseBadge ?? false,
badgeStyle,
useJapaneseBadge: badgeStyle === "katakana",
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

siteConfig?.toc?.badgeStyle is a plain string, but it’s cast directly to the union type. If the global config contains an unexpected value (typo/custom injection), badgeStyle will be an invalid runtime value while TypeScript assumes it’s safe, which can cause inconsistent behavior (e.g. useJapaneseBadge derivation and any future style branching). Add a small runtime normalizer/guard that only accepts "number" | "katakana" | "roman" and otherwise falls back to the legacy boolean or "number".

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines +83 to +88
const badgeStyle = (root.dataset.badgeStyle || "number") as "number" | "katakana" | "roman";

const manager = new TOCManager({
contentElement: tocContent,
maxLevel: 3,
useJapaneseBadge,
badgeStyle,
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

root.dataset.badgeStyle is cast to the badge-style union without validating the string. If the attribute is missing/modified (or future markup changes), an invalid value can flow into TOCManager while TypeScript still treats it as safe. Recommend normalizing/validating the dataset value against the allowed styles and defaulting to "number" if it doesn’t match.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines 141 to 147
const badgeStyle: TOCBadgeStyle =
(window.siteConfig?.toc?.badgeStyle as TOCBadgeStyle) ??
(window.siteConfig?.toc?.useJapaneseBadge ? "katakana" : "number");
return {
useJapaneseBadge: window.siteConfig?.toc?.useJapaneseBadge ?? false,
badgeStyle,
depth: window.siteConfig?.toc?.depth ?? 3,
};
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

window.siteConfig?.toc?.badgeStyle is cast to TOCBadgeStyle without validating the runtime value. To keep behavior predictable (and consistent with the deprecated boolean fallback), add a guard that only accepts the known styles and otherwise falls back to (useJapaneseBadge ? "katakana" : "number").

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Replace the boolean `useJapaneseBadge` with a new `badgeStyle` config
option that supports three TOC badge styles:

- "number": plain numeric badges (1, 2, 3...)
- "katakana": Japanese katakana badges (original style)
- "roman": Roman numeral badges (new)

The old `useJapaneseBadge` boolean is kept as deprecated for backward
compatibility. All TOC components (Sidebar, Floating, Mobile, Card)
are updated to use the new unified `getTOCBadge()` function.
@Dawn6666666 Dawn6666666 force-pushed the feat/toc-badge-style branch from c06d8fc to 63512a2 Compare April 28, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants