Skip to content

feat(code-highlighter): add showLineNumber / wrapLongLines / showCopyButton props - #2003

Open
Y-MuYi wants to merge 2 commits into
ant-design:mainfrom
Y-MuYi:feat-1951-code-highlighter-config
Open

feat(code-highlighter): add showLineNumber / wrapLongLines / showCopyButton props#2003
Y-MuYi wants to merge 2 commits into
ant-design:mainfrom
Y-MuYi:feat-1951-code-highlighter-config

Conversation

@Y-MuYi

@Y-MuYi Y-MuYi commented Aug 3, 2026

Copy link
Copy Markdown

Closes #1951

关联原始 issue:#1647

背景

CodeHighlighter 当前只能通过 highlightProps 透传 react-syntax-highlighter 的配置,缺少几个常用开关的显式入口(showLineNumbers / wrapLongLines),以及无法单独关闭默认 header 里的复制按钮。

改动

CodeHighlighterProps 上新增 3 个配置项,并按需透传给 react-syntax-highlighter(复制按钮在组件内自行控制):

属性 说明 类型 默认值
showLineNumber 是否显示行号 boolean false
wrapLongLines 是否自动换行 boolean false
showCopyButton 是否显示复制按钮,仅在默认 header 下生效 boolean true
  • interface.ts:补充 props 定义(含 @default)。
  • CodeHighlighter.tsxshowLineNumbers / wrapLongLines 透传给 SyntaxHighlighter;默认 header 的 Actions.Copy 根据 showCopyButton 条件渲染(自定义 header 不受影响)。
  • 新增 demo/flexible-config.tsx,演示三个开关及组合使用。
  • 中英文 API 文档(index.zh-CN.md / index.en-US.md)注册 demo 并更新 API 表格。
  • 新增单元测试覆盖三个开关。

说明:highlightProps 仍保留为 escape hatch,沿用既有 spread 顺序——传 highlightProps.showLineNumbers 会覆盖 showLineNumber,与现有 wrapLines={true}highlightProps 覆盖的行为保持一致。

验证

  • biome 格式检查通过。
  • 单测断言已对照 react-syntax-highlighter@15.6.6 源码核实:行号渲染为 <span class=\"linenumber\">wrapLongLines 设置 <code>whiteSpace: pre-wrap

备注:与 #1945(语言注册/样式)同改了 code-highlighter,如已合入我会 rebase 处理冲突。

Summary by CodeRabbit

  • 新功能

    • 代码高亮组件支持配置是否显示行号、是否自动换行,以及是否显示复制按钮。
    • 复制按钮默认显示,并可按需隐藏。
    • 新增灵活配置示例,展示多种组合用法。
  • 文档

    • 补充新增配置项、默认值及使用说明。

…Button props

Provide explicit, commonly-used configuration switches on CodeHighlighterProps
instead of forcing them through `highlightProps`. The three props are passed
through to react-syntax-highlighter (or used to toggle the default header's copy
button directly).

Closes ant-design#1951

Co-Authored-By: Claude <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@dosubot dosubot Bot added documentation Improvements or additions to documentation enhancement New feature or request javascript Pull requests that update Javascript code labels Aug 3, 2026
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

CodeHighlighter 新增行号、长行换行和复制按钮配置。组件实现、测试、示例及中英文 API 文档同步更新。

Changes

CodeHighlighter 配置

Layer / File(s) Summary
配置接口与渲染逻辑
packages/x/components/code-highlighter/interface.ts, packages/x/components/code-highlighter/CodeHighlighter.tsx
新增 showLineNumberwrapLongLinesshowCopyButton。默认值分别为 falsefalsetrue
配置行为测试
packages/x/components/code-highlighter/__tests__/index.test.tsx
测试行号、长行换行、复制按钮默认显示与禁用,以及自定义 header 行为。
配置示例与 API 文档
packages/x/components/code-highlighter/demo/flexible-config.tsx, packages/x/components/code-highlighter/index.en-US.md, packages/x/components/code-highlighter/index.zh-CN.md
新增灵活配置示例,并更新中英文 API 文档。

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • ant-design/x#1976:包含相同的 CodeHighlighter 配置、渲染逻辑、测试、示例和文档变更。

Suggested reviewers: kimteayon

Poem

兔子捧着代码跑,
行号整齐排成行。
长线弯腰不越界,
复制按钮听指令。
配置文档一起亮。

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了新增的三个 CodeHighlighter 配置属性,内容清晰且与变更一致。
Linked Issues check ✅ Passed PR 已实现新增属性、配置演示、单元测试和 API 文档更新等需求,符合关联 issue #1951
Out of Scope Changes check ✅ Passed 代码、测试、演示和文档变更均围绕 CodeHighlighter 配置扩展,没有发现无关变更。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/x/components/code-highlighter/__tests__/index.test.tsx`:
- Around line 549-560: Update the wrapLongLines test around CodeHighlighter so
it waits for the final SyntaxHighlighter DOM by targeting the rendered pre
element, then assert whiteSpace on the nested pre code element. Use content with
a line break or sufficient length if needed, ensuring the assertion verifies the
prop behavior rather than the fallback code path.

In `@packages/x/components/code-highlighter/CodeHighlighter.tsx`:
- Around line 166-167: Update the Suspense fallback styling in CodeHighlighter
so its whiteSpace behavior is derived from wrapLongLines: use wrapping when
enabled and preserve pre-style whitespace when disabled, matching the final
react-syntax-highlighter rendering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d3dffd9-8716-4715-9783-a30a54ef37d9

📥 Commits

Reviewing files that changed from the base of the PR and between b529d8e and 7002747.

📒 Files selected for processing (6)
  • packages/x/components/code-highlighter/CodeHighlighter.tsx
  • packages/x/components/code-highlighter/__tests__/index.test.tsx
  • packages/x/components/code-highlighter/demo/flexible-config.tsx
  • packages/x/components/code-highlighter/index.en-US.md
  • packages/x/components/code-highlighter/index.zh-CN.md
  • packages/x/components/code-highlighter/interface.ts

Comment on lines +549 to +560
it('should pass wrapLongLines to SyntaxHighlighter', async () => {
const { container } = render(
<CodeHighlighter lang="javascript" wrapLongLines>
{`console.log("test");`}
</CodeHighlighter>,
);
await waitFor(() => {
expect(container.querySelector('code')).toBeInTheDocument();
});
// wrapLongLines sets whiteSpace: pre-wrap on the rendered code element
expect(container.querySelector('code')?.style.whiteSpace).toBe('pre-wrap');
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
rg -n -A14 -B4 'should pass wrapLongLines' \
  packages/x/components/code-highlighter/__tests__/index.test.tsx

Repository: ant-design/x

Length of output: 931


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== files =="
git ls-files packages/x/components/code-highlight | head -50

echo "== component outline =="
ast-grep outline packages/x/components/code-highlight -view expanded || true

echo "== relevant source snippets =="
for f in $(git ls-files packages/x/components/code-highlight | grep -E '\.(tsx|ts|jsx|js)$' | head -20); do
  if rg -n "function CodeHighlighter|const CodeHighlighter|SyntaxHighlighter|wrapLongLines|fallback|Suspense|react-syntax-highlighter" "$f" >/dev/null; then
    echo "--- $f ---"
    rg -n -A30 -B30 "function CodeHighlighter|const CodeHighlighter|SyntaxHighlighter|wrapLongLines|fallback|Suspense|react-syntax-highlighter" "$f" | sed -n '1,220p'
  fi
done

echo "== test imports and surrounding tests =="
sed -n '1,90p;510,580p' packages/x/components/code-highlight/__tests__/index.test.tsx

Repository: ant-design/x

Length of output: 529


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== all code-highlight paths =="
git ls-files | grep -E '(^|/)code[-_]highlight' || true

echo "== exact test file =="
git ls-files | grep 'CodeHighlighter.*test\.tsx$' || true
git ls-files | grep 'index\.test\.tsx$' | grep -i 'highlight' || true

echo "== files matching CodeHighlighter =="
git ls-files | xargs rg -l "CodeHighlighter" || true

echo "== package directory snapshot =="
for d in $(git ls-files | sed -n 's#^packages/[^/]*$#&`#p`' | sort | head -50); do
  true
done
git ls-files packages | grep code-highlight || true

Repository: ant-design/x

Length of output: 3521


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== CodeHighlighter.tsx size =="
wc -l packages/x/components/code-highlighter/CodeHighlighter.tsx
echo

echo "== CodeHighlighter.tsx outline =="
ast-grep outline packages/x/components/code-highlighter/CodeHighlighter.tsx --view expanded || true
echo

echo "== CodeHighlighter.tsx relevant lines =="
sed -n '1,260p' packages/x/components/code-highlighter/CodeHighlighter.tsx | cat -n
echo

echo "== Tests relevant section =="
sed -n '530,565p' packages/x/components/code-highlighter/__tests__/index.test.tsx | cat -n

Repository: ant-design/x

Length of output: 9625


🌐 Web query:

react-syntax-highlighter wrapLongLines whiteSpace code element pre code

💡 Result:

In react-syntax-highlighter, the wrapLongLines prop is a boolean used to control how code blocks handle long lines [1][2]. When set to true, it applies white-space: pre-wrap to the code element, allowing text to wrap within the container instead of overflowing [1][3]. When set to false (the default), it uses white-space: pre [1][2]. Key technical details and behaviors include: 1. Automatic Line Wrapping: Enabling wrapLongLines effectively overrides the need to manually apply white-space styling via CSS or codeTagProps [3]. It also forces each line of code to be wrapped in its own span element, similar to how wrapLines={true} behaves [3]. 2. Interaction with showLineNumbers: When both wrapLongLines and showLineNumbers are enabled, the library applies display: flex to the line elements to ensure line numbers remain correctly aligned with their corresponding code [3]. 3. Known Issues and Workarounds: - Flexbox Conflicts: Users have reported that the library's internal use of display: flex can sometimes interfere with custom styling provided via lineProps [4]. If you need to override these styles, it is often necessary to use more specific CSS or target the wrapper elements directly [4][5]. - Prism.js Inconsistencies: Some users have noted that wrapLongLines may not behave as expected with Prism.js in certain versions [6]. A common workaround for persistent wrapping issues is to force the style directly using the codeTagProps prop: codeTagProps={{ style: { whiteSpace: 'pre-wrap' } }} [6]. - Layout Alignment: When using wrapLongLines and showLineNumbers together, long lines may occasionally cause layout misalignment. Recent updates have introduced word-break: break-word and nested structures to help mitigate these visual issues [7].

Citations:


等待最终高亮 DOM 再检查 wrapLongLines 效果。

fallback 直接渲染 <code style={{ whiteSpace: 'pre-wrap' }}>,所以当前 waitFor 可能在 SyntaxHighlighter 加载前通过,断言值也不能直接反映 props 生效情况。建议先等待 pre,再断言 pre codewhiteSpace;如需更明确,可使用更长或带换行的代码内容。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/x/components/code-highlighter/__tests__/index.test.tsx` around lines
549 - 560, Update the wrapLongLines test around CodeHighlighter so it waits for
the final SyntaxHighlighter DOM by targeting the rendered pre element, then
assert whiteSpace on the nested pre code element. Use content with a line break
or sufficient length if needed, ensuring the assertion verifies the prop
behavior rather than the fallback code path.

Source: MCP tools

Comment on lines +166 to +167
showLineNumbers={showLineNumber}
wrapLongLines={wrapLongLines}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
rg -n -C 5 'fallback|wrapLongLines|whiteSpace' \
  packages/x/components/code-highlighter/CodeHighlighter.tsx

Repository: ant-design/x

Length of output: 1051


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== locate package files =="
fd -a 'package.json|CodeHighlighter.tsx' . | sed 's#^\./##' | rg 'code-highlighter|package.json' | head -80

echo
echo "== package versions =="
python3 - <<'PY'
import json, os
for root, dirs, files in os.walk('packages'):
    for f in files:
        if f == 'package.json':
            p=os.path.join(root,f)
            try:
                data=json.load(open(p,encoding='utf-8'))
            except Exception as e:
                continue
            name=data.get('name','')
            deps={}
            for k in ('dependencies','devDependencies','peerDependencies'):
                deps.update(data.get(k,{}))
            if any('react-syntax' in v or name.endswith('code-highlighter') or 'code-highlighter' in name for v in deps.values()) or 'code-highlighter' in name:
                print(p)
                for k in deps:
                    for n,v in deps.get(k,{}).items():
                        if 'react-syntax' in n:
                            print(f"  {k}: {n}={v}")
PY

echo
echo "== code highlighter file size/context =="
wc -l packages/x/components/code-highlighter/CodeHighlighter.tsx
sed -n '1,220p' packages/x/components/code-highlighter/CodeHighlighter.tsx

echo
echo "== react-syntax-highlighter usage/imports =="
rg -n "react-syntax-highlighter|Highlighter" packages/x/components/code-highlighter packages -g '*.ts' -g '*.tsx' | head -120

Repository: ant-design/x

Length of output: 20968


🌐 Web query:

react-syntax-highlighter v16.1.0 wrapLongLines codeTagProps white-space pre-wrap pre

💡 Result:

In react-syntax-highlighter, the wrapLongLines prop is the intended mechanism for controlling line wrapping, as it explicitly toggles the white-space CSS property on the code tag [1][2][3]. When wrapLongLines is set to true, the library automatically applies white-space: pre-wrap to the code element [1][3]. Conversely, when it is false (the default), it applies white-space: pre [3]. It is recommended to use the wrapLongLines prop instead of manually overriding white-space via codeTagProps [3]. Manually setting white-space: pre-wrap via codeTagProps may be overridden by the library's internal styling, which explicitly sets white-space: pre by default [3]. If you encounter issues where lines are not wrapping despite using wrapLongLines (especially when combined with showLineNumbers), it is often due to the internal structure of the generated code block, which may require additional CSS adjustments such as adding flex-wrap: wrap to the line-level elements [4].

Citations:


Suspense fallback 遵守 wrapLongLines

当前代码在 wrapLongLines={false} 时仍使用 whiteSpace: 'pre-wrap' 作为 fallback;异步语言模块加载期间,fallback 会渲染换行,随后再切换为 react-syntax-highlighter 的 pre 样式。fallback 应与最终高亮使用相同的换行配置。

修正建议
-      fallback={<code style={{ whiteSpace: 'pre-wrap' }}>{children.replace(/\n$/, '')}</code>}
+      fallback={
+        <code style={{ whiteSpace: wrapLongLines ? 'pre-wrap' : 'pre' }}>
+          {children.replace(/\n$/, '')}
+        </code>
+      }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/x/components/code-highlighter/CodeHighlighter.tsx` around lines 166
- 167, Update the Suspense fallback styling in CodeHighlighter so its whiteSpace
behavior is derived from wrapLongLines: use wrapping when enabled and preserve
pre-style whitespace when disabled, matching the final react-syntax-highlighter
rendering.

Source: MCP tools

@Y-MuYi

Y-MuYi commented Aug 3, 2026

Copy link
Copy Markdown
Author

#1951

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request javascript Pull requests that update Javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Good First Issue] CodeHighlighter 支持更灵活的配置

1 participant