feat(code-highlighter): add showLineNumber / wrapLongLines / showCopyButton props - #2003
feat(code-highlighter): add showLineNumber / wrapLongLines / showCopyButton props#2003Y-MuYi wants to merge 2 commits into
Conversation
…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>
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
📝 WalkthroughWalkthroughCodeHighlighter 新增行号、长行换行和复制按钮配置。组件实现、测试、示例及中英文 API 文档同步更新。 ChangesCodeHighlighter 配置
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (6)
packages/x/components/code-highlighter/CodeHighlighter.tsxpackages/x/components/code-highlighter/__tests__/index.test.tsxpackages/x/components/code-highlighter/demo/flexible-config.tsxpackages/x/components/code-highlighter/index.en-US.mdpackages/x/components/code-highlighter/index.zh-CN.mdpackages/x/components/code-highlighter/interface.ts
| 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'); | ||
| }); |
There was a problem hiding this comment.
📐 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.tsxRepository: 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.tsxRepository: 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 || trueRepository: 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 -nRepository: 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:
- 1: https://github.com/react-syntax-highlighter/react-syntax-highlighter
- 2: https://www.npmjs.com/package/react-syntax-highlighter
- 3: wrapLongLines + line numbering with wrapped lines react-syntax-highlighter/react-syntax-highlighter#309
- 4:
wrapLongLinesandshowLineNumbersoverwrites the 'display' property of the style attribute fromlinePropsreact-syntax-highlighter/react-syntax-highlighter#518 - 5: Fix not being able to override styles when wrapLongLines is true react-syntax-highlighter/react-syntax-highlighter#487
- 6:
wrapLongLinesprop doesn't wrap long lines with Prism.js react-syntax-highlighter/react-syntax-highlighter#597 - 7: Address code wrapping visual issue when both wrapLongLines and showLineNumbers are set to true react-syntax-highlighter/react-syntax-highlighter#483
等待最终高亮 DOM 再检查 wrapLongLines 效果。
fallback 直接渲染 <code style={{ whiteSpace: 'pre-wrap' }}>,所以当前 waitFor 可能在 SyntaxHighlighter 加载前通过,断言值也不能直接反映 props 生效情况。建议先等待 pre,再断言 pre code 的 whiteSpace;如需更明确,可使用更长或带换行的代码内容。
🤖 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
| showLineNumbers={showLineNumber} | ||
| wrapLongLines={wrapLongLines} |
There was a problem hiding this comment.
🎯 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.tsxRepository: 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 -120Repository: 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:
- 1: https://unpkg.com/react-syntax-highlighter@16.1.0/README.md
- 2: https://github.com/react-syntax-highlighter/react-syntax-highlighter/tree/v16.1.0
- 3: wrapLongLines + line numbering with wrapped lines react-syntax-highlighter/react-syntax-highlighter#309
- 4:
wrapLongLinesprop doesn't wrap long lines with Prism.js react-syntax-highlighter/react-syntax-highlighter#597
让 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
Closes #1951
背景
CodeHighlighter当前只能通过highlightProps透传react-syntax-highlighter的配置,缺少几个常用开关的显式入口(showLineNumbers/wrapLongLines),以及无法单独关闭默认 header 里的复制按钮。改动
在
CodeHighlighterProps上新增 3 个配置项,并按需透传给react-syntax-highlighter(复制按钮在组件内自行控制):showLineNumberbooleanfalsewrapLongLinesbooleanfalseshowCopyButtonbooleantrueinterface.ts:补充 props 定义(含@default)。CodeHighlighter.tsx:showLineNumbers/wrapLongLines透传给SyntaxHighlighter;默认 header 的Actions.Copy根据showCopyButton条件渲染(自定义 header 不受影响)。demo/flexible-config.tsx,演示三个开关及组合使用。index.zh-CN.md/index.en-US.md)注册 demo 并更新 API 表格。验证
react-syntax-highlighter@15.6.6源码核实:行号渲染为<span class=\"linenumber\">,wrapLongLines设置<code>的whiteSpace: pre-wrap。Summary by CodeRabbit
新功能
文档