Skip to content

fix: preserve problem Markdown and add full-statement copying - #1031

Merged
boomzero merged 30 commits into
devfrom
codex/fix-1030-markdown-copy
Oct 3, 2026
Merged

boomzero merged 30 commits into
devfrom
codex/fix-1030-markdown-copy

Conversation

@boomzero

@boomzero boomzero commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

What does this PR aim to accomplish?:

Fix copied problem Markdown losing TeX expressions and paragraph/line breaks, and add the requested section, sample, and full-statement copying controls. Closes #1030. Closes #1011.

How does this PR accomplish the above?:

  • Recover original TeX from KaTeX and MathJax, including XMOJ's MathJax 3.0.5, without modifying the rendered math.
  • Preserve paragraph and hard line breaks, normalize HTML formatting indentation in prose, preserve preformatted explanations as fenced code blocks, keep display formulas and paragraph separation within table cells, preserve empty columns, and retain list separation. Remove paragraph collapsing from the legacy copy path.
  • Serialize ordinary header tables as Markdown with alignment, escaped pipes and multiline cells. Preserve headerless, merged, nested, preformatted and linked tables as HTML, restoring TeX and resolving image/link URLs.
  • Add a copy button beside the problem title and on the samples section in both interfaces. Every problem section copy includes its ## heading.
  • Build complete statements with a # title, ordered section headings, numbered sample headings and plain code fences, sample explanations, data ranges and hints. Omit absent/empty sections and preserve sample whitespace.
  • Read the currently displayed language, exclude copy-button labels and injected problem IDs from the output, and avoid duplicate controls during rerenders.
  • Run 44 browser fixture cases automatically with npm test and the Test workflow. Playwright remains test tooling; no userscript runtime dependency is added.

Validation:

  • node --check XMOJ.user.js and git diff --check passed.
  • npm test: all 15 Node test entries passed, including 44 browser fixture cases, the existing contest tests, and missing/duplicate extraction-anchor checks.
  • Reproduce with npm install, npx playwright install chromium, and npm test. XMOJ_CHROMIUM can select an existing Chromium executable.
  • The actual Vue contest bundle was tested against mocked read-only API data: full-statement and samples buttons, paragraph/TeX preservation, active-language switching, empty-section omission, and duplicate-control prevention passed.
  • The human table review is covered by section/full-copy callbacks and table regressions. A Marked 4.3.0 render check verifies 14 table examples, including formulas, merged cells, nested tables, captions, links and preformatted whitespace.
  • The human review’s boarding example is covered by section/full-copy regressions: seat diagrams remain fenced, and prose has no extra blank lines or leading tabs. A separate Marked 4.3.0 render check preserves all four code blocks and both diagrams exactly.
  • Classic markup fixtures exercise the real shared clipboard callbacks, visible-language switching in both directions, wrapped sample containers, numbered samples, and untrimmed preformatted whitespace.
  • Real KaTeX 0.16.11 and XMOJ's MathJax 3.0.5 were also verified in the original copy-button checks.

By submitting this pull request, I confirm the following:

  • 1. Read the contributor's guide and the entire template; this branch is based on and targets dev.
  • 2. Commented on the proposed changes within the code.
  • 3. Tested the changes as described above.
  • 4. Maintainer confirmation: willingness to help maintain this change.
  • 5. Compatible with the repository's GNU General Public License v3.
  • 6. The fix and review feedback are grouped into focused commits.
  • 7. Checked for another open PR for this fix; none exists.
  • 8. The change fixes the reported loss of formulas and formatting.
  • 9. Maintainer confirmation: acceptance of the submission policy.
  • 10. Maintainer confirmation: contribution terms.
  • 11. Human verification on the live site in both the new and old/classic UIs is pending. Browser fixtures and automated tests were verified; live-site coverage is not claimed.

  • I have read the above and my PR is ready for review. Check this box to confirm

Summary by Sourcery

Preserve formulas and Markdown formatting when copying content from contest problem and solution pages.

Bug Fixes:

  • Preserve TeX source, math delimiters, paragraph spacing, Markdown hard breaks, and preformatted whitespace when copying contest content as Markdown.

Enhancements:

  • Support TeX extraction from KaTeX, MathML, and both legacy and current MathJax APIs without modifying the rendered DOM.

CI:

  • Run browser-based Markdown copy regression tests in CI with Playwright and Chromium.

Tests:

  • Add browser regression coverage for mathematical content, Markdown formatting, tables, lists, legacy copying, whitespace, DOM preservation, and extraction-anchor validation.

Chores:

  • Bump the userscript and package version to 3.7.2.

Summary by cubic

Preserves TeX source and Markdown formatting when copying contest problem and solution content, and adds copy buttons for full statements, titled sections, and samples. Closes #1030 and #1011.

  • Recovers TeX from KaTeX annotations, MathML, and both modern and legacy MathJax expression lists without touching rendered math.
  • Converts simple tables to pipe tables with alignment; keeps merged, nested, math-bearing, or link-bearing tables as HTML with TeX restored and absolute URLs. Preserves math delimiters, paragraph and hard line breaks, preformatted explanations and samples as fenced code blocks, list separation, and wrapped sample containers; code fences keep the language from pre and code classes and outlast backtick runs in the source.
  • Adds copy buttons beside titles and section headings; full statements use # and ## headings, numbered samples with plain fences, explanations, ranges, and hints, omitting empty sections.
  • Reads the currently displayed language and excludes copy-button labels and injected problem IDs from the output; controls stay idempotent across rerenders.
  • Adds Playwright-based browser fixture coverage run through npm test and the Test workflow, and bumps the version to 3.7.2.

Written for commit 461e353. Summary will update on new commits.

Review in cubic

@hendragon-bot hendragon-bot Bot added the user-script This issue or pull request is related to the main user script label Oct 2, 2026
@sourcery-ai

sourcery-ai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Updates Markdown extraction to recover source TeX from KaTeX and both legacy/current MathJax representations, preserve paragraph spacing, hard breaks, and preformatted whitespace without mutating the DOM, and adds ten browser regressions plus version metadata updates.

Flow diagram for Markdown copy extraction

flowchart TD
    A[Contest content element] --> B[GetMDText]
    B --> C[Collect MathJax expressions]
    C --> D{Math source available}
    D -->|MathJax| E[AppendMath with source and display delimiters]
    D -->|KaTeX annotation| E
    D -->|No| F[Traverse DOM nodes]
    F --> G{Node formatting}
    G -->|BR| H[Append hard break or preformatted newline]
    G -->|Block| I[Append paragraph or list spacing]
    G -->|PRE| J[Preserve whitespace]
    G -->|Other text| K[Append text content]
    E --> L[Markdown result]
    H --> L
    I --> L
    J --> L
    K --> L
Loading

File-Level Changes

Change Details Files
Extract original TeX from rendered math while leaving the page DOM untouched.
  • Build a MathJax root-to-expression map using both newer lookup APIs and XMOJ’s legacy expression list.
  • Read KaTeX/MathML TeX annotations and emit inline or display Markdown delimiters.
  • Avoid traversing duplicated visual and accessibility math trees.
XMOJ.user.js
Preserve Markdown structural whitespace during recursive HTML conversion.
  • Emit blank lines around block elements and distinguish list/table row spacing.
  • Convert non-preformatted
    elements to Markdown hard breaks while retaining plain newlines in
    .
  • Continue converting images and table cells while maintaining existing whitespace behavior.
XMOJ.user.js
Add browser regression coverage for Markdown copying behavior.
  • Cover paragraphs, hard breaks, KaTeX, MathML, both MathJax API shapes, raw TeX, preformatted content, images, and tables.
  • Assert the source fixture DOM is unchanged after conversion.
tests/markdown-copy.html
Synchronize release metadata for the fix.
  • Bump userscript and package versions to 3.7.2.
  • Update distribution metadata.
XMOJ.user.js
package.json
Update.json

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Deploying xmoj-script-dev-channel with  Cloudflare Pages  Cloudflare Pages

Latest commit: 461e353
Status: ✅  Deploy successful!
Preview URL: https://70a97966.xmoj-script-dev-channel.pages.dev
Branch Preview URL: https://codex-fix-1030-markdown-copy.xmoj-script-dev-channel.pages.dev

View logs

@boomzero
boomzero marked this pull request as ready for review October 2, 2026 14:33
@github-actions
github-actions Bot force-pushed the codex/fix-1030-markdown-copy branch from bcbf199 to b2a7504 Compare October 2, 2026 14:33
@github-actions
github-actions Bot force-pushed the codex/fix-1030-markdown-copy branch from b2a7504 to ddad45a Compare October 2, 2026 14:33
@boomzero

boomzero commented Oct 2, 2026 •

Copy link
Copy Markdown
Member Author

@zsTree0830

sourcery-ai[bot]
sourcery-ai Bot previously approved these changes Oct 2, 2026

@sourcery-ai sourcery-ai 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.

Sourcery assessment

Approved.

sourcery-ai[bot]
sourcery-ai Bot previously approved these changes Oct 2, 2026

@sourcery-ai sourcery-ai 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.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 32945a4e16

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread XMOJ.user.js Resolved

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread XMOJ.user.js Resolved
Comment thread XMOJ.user.js Resolved
Comment thread XMOJ.user.js Resolved
Comment thread XMOJ.user.js Resolved
Comment thread tests/markdown-copy.html Resolved
Comment thread tests/markdown-copy.html Resolved

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 4 files

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.

Re-trigger cubic

Comment thread tests/markdown-copy.html Resolved
@zsTree0830

Copy link
Copy Markdown
Member

@boomzero TeX 好了但是换行还是坏的

boomzero commented Oct 2, 2026

Copy link
Copy Markdown
Member Author

@boomzero TeX 好了但是换行还是坏的

Working on it

boomzero commented Oct 2, 2026

Copy link
Copy Markdown
Member Author

#1011 too

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 6 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread XMOJ.user.js Resolved
Comment thread package.json Resolved
Comment thread tests/markdown-copy.test.cjs Resolved
Comment thread XMOJ.user.js Resolved
@sourcery-ai
sourcery-ai Bot dismissed their stale review October 2, 2026 15:23

Sourcery withdrew this approval because it has stopped reviewing this pull request.

@sourcery-ai

sourcery-ai Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Sourcery has withdrawn its approval of this pull request. It auto-reviews a pull request 5 times, and this push is past that limit, so the approval no longer reflects code Sourcery has read.

Comment @sourcery-ai review to get a fresh review, which can approve again.

Re-reviews, rate limits and approvals

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread tests/markdown-copy.html Resolved
@boomzero

boomzero commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

Works in my tests.

@zsTree0830 zsTree0830 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

我说真的
这个还是坏的:

## 样例输入输出

### 样例输入 #1

```plain
3
2 5
3 10
1 5
```

### 样例输出 #1

```plain
19
```

### 样例说明 #1

一开始的状况是:

人  123
       123 座位


	第一秒,每个人向右移动一个位置,$3$ 到了自己的座位 $1$。然后 $3$ 要花 $5$ 秒放行李,$1$ 和 $2$ 跟着等待。

人      12
       123 座位


	之后 $1$ 和 $2$ 花 $3$ 秒同时移动到自己的座位,分别要花 $5$ 秒和 $10$ 秒放行李,总共放行李的时间是 $10$ 秒。


	总时间是:$1+5+3+10=19$ 秒。
Image

代码块没有了
还有每段之间多了一个换行
除了第一段,其他段的段首都多了一个 Tab

@zsTree0830

Copy link
Copy Markdown
Member

@boomzero

boomzero commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

@zsTree0830 前面漏看了你这条正式 review,抱歉。你指出的三个问题已在 e37be7b 中处理:

  • 样例说明里的 <pre> 现在输出 fenced code block,座位示意图的空格和换行保留;已有代码语言标签也会保留。
  • 普通段落中的 HTML 排版换行、缩进会规范化,不再与段落分隔叠加出额外空行。
  • 段首的排版 Tab 不再带入 Markdown;代码块内部的 Tab 和空格保持原样。

新增了按你贴出的登机样例构造的回归用例,同时验证「样例输入输出」和整题复制按钮。旧实现能重现多余换行和 Tab;修复后 35 个浏览器用例全部通过。另用脚本已有的 Marked 4.3.0 渲染复制结果,确认得到 4 个代码块,两幅座位图内容完全保留,说明段落没有额外空行或段首 Tab。请用最新提交复测原题。

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread XMOJ.user.js Resolved
@boomzero
boomzero requested a review from zsTree0830 October 3, 2026 06:36

@zsTree0830 zsTree0830 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@boomzero 表格

boomzero commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

@zsTree0830 表格已在 9dd0add 中处理。之前确实只是把单元格连接成 Tab 分隔文本,粘贴后不会渲染成表格。

现在有表头的普通表格会生成 Markdown 表格,保留列对齐,单元格内的换行用 <br>,竖线会转义,KaTeX/MathJax 仍复制原始 TeX。没有表头、含合并单元格、嵌套表格或代码块的表格会保留 HTML 结构,避免增加空表头或丢失结构;其中的公式也会替换回 TeX,图片和链接会保留正确的地址。

新增并更新了表格回归用例,同时检查分节复制和整题复制。全部 43 个浏览器用例通过;另用 Marked 4.3.0 渲染 13 个表格示例,验证了行列、竖线、公式、单元格换行、合并/嵌套表格和代码块空白。请用最新提交复测。

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread XMOJ.user.js Resolved
@boomzero
boomzero merged commit 6c8faf1 into dev Oct 3, 2026
10 checks passed
@boomzero
boomzero deleted the codex/fix-1030-markdown-copy branch October 3, 2026 12:39
@boomzero boomzero mentioned this pull request Oct 3, 2026
1 task done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

GitHub-related size/XL user-script This issue or pull request is related to the main user script

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 新 UI 比赛中题目复制 Markdown 出现问题 [Feature Request] For Copy Problem Statement Markdown

2 participants