fix(docs): export clean selected-language markdown from Copy page button#460
Merged
Conversation
The "Copy page" button scraped `article.innerText`, capturing page chrome (breadcrumbs, version badge, mobile TOC, footer "Edit this page"/tags) and emitting rendered text instead of markdown. Rewrite `copyPageAsMarkdown` to scope to `.theme-doc-markdown` and convert with turndown (dynamically imported for SSR safety), capturing only the currently-selected code language. - Strip hidden language panels, default-tab chrome (role=tablist / hidden), decorative icons, the code-tab header controls, and Cloud/Academy badges - Preserve Prism code blocks as fenced blocks with language + line breaks - Add an `error` copy state, a clipboard guard, and aria-live on the status - Add a `data-copy-exclude` opt-out marker (CloudOnlyBadge, AcademyBadge)
There was a problem hiding this comment.
Orca Security Scan Summary
| Status | Check | Issues by priority | |
|---|---|---|---|
| Infrastructure as Code | View in Orca | ||
| SAST | View in Orca | ||
| Secrets | View in Orca | ||
| Vulnerabilities | View in Orca |
The docs-feedback partial (the "reach us" Community Forum / Support cards) is imported into page content, so the Copy page button captured it and turndown rendered each card link as a broken empty-link block. Wrap the partial in a `data-copy-exclude` container so it is dropped from the copy while still rendering normally on the page.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes the docs “Copy page” action so it exports clean, content-only Markdown (instead of scraped rendered text + page chrome), while preserving the currently selected code-tab language and improving robustness/accessibility of copy status reporting.
Changes:
- Rewrites
copyPageAsMarkdownto clone the rendered doc body, strip UI chrome/hidden panels, and convert HTML → Markdown viaturndown(+ GFM plugin) loaded dynamically in the click handler. - Adds a reusable
data-copy-excludemarker to UI badge components (and uses it in an include) so their text doesn’t leak into copied Markdown. - Adds new dependencies (
turndown,turndown-plugin-gfm) to support HTML → Markdown conversion.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/components/ContextualMenu/index.js |
New Markdown extraction pipeline using turndown, selected-language-only stripping, and an error state + aria-live status label. |
src/components/CloudOnlyBadge/index.jsx |
Adds data-copy-exclude attribute so the badge can be removed from copied Markdown. |
src/components/AcademyBadge/index.jsx |
Adds data-copy-exclude attribute so the badge can be removed from copied Markdown. |
_includes/docs-feedback.mdx |
Wraps a feedback block in data-copy-exclude so it can be excluded from copied Markdown. |
package.json |
Adds turndown and turndown-plugin-gfm dependencies. |
yarn.lock |
Lockfile updates for the newly added dependencies (and transitive deps). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Handle more component types so the copied markdown reads cleanly on pages like the quickstart: - Strip Docusaurus heading hash-link anchors (they use aria-label, so the aria-hidden strip missed them) — headings no longer emit `[](#... "Direct link to ...")`. - Exclude glossary Tooltip popups and the PromptStarter CTA via data-copy-exclude (their text was leaking into the copy). - Stop blanket-stripping <button>, which deleted the inline KapaAI "Ask AI" link mid-sentence; strip only the code-block copy/word-wrap buttons by aria-label/title instead. - Render CardsSection content cards as clean single-line links ([title](href) — description) by rewriting them in the DOM before conversion, rather than a turndown rule that block-separated every inline link.
…n Copy page Extend the Copy page markdown export to convert more component types cleanly (found via an edge-case sweep across 16 diverse pages): - Tables: flatten <br>, multi-paragraph, and list cells to inline so GFM rows stay valid (previously they split and orphaned following rows). - KaTeX: emit the LaTeX annotation as $...$ / $$...$$ instead of the duplicated MathML glyph text. - Admonitions: render as GitHub callout blockquotes (> [!NOTE], [!WARNING], [!CAUTION], [!TIP]) with the body quoted, instead of a bare type word. - <details>: render as a bold summary line + body. - Non-code (content) tabs: emit every panel under its "### <label>" heading instead of dropping the non-selected ones (code tabs stay selected-language). - Exclude the WeaviateConfigurator widget's "Loading..." placeholder. - Squeeze runs of 3+ blank lines to 2.
…mport, prompt error state) - Narrow the copy strip selector from `.badge` to `a.badge`, so it removes only FilteredTextBlock chrome badge links and preserves content badges such as `<span class="badge">Expected time: 30 minutes</span>`. - Harden the dynamic `turndown-plugin-gfm` import against CJS/ESM interop (resolve `gfm` from the module namespace or its `.default`). - Surface the "Copy failed" error state in the prompts variant too, matching the docs variant.
Add a Playwright test that loads a docs page, clicks "Copy page", reads the
clipboard, and asserts the exported markdown is clean — it starts with the
page's own `Source:` URL, contains a fenced code block, and leaks no page
chrome ("Direct link to", "Edit this page"). Runs against DOCS_BASE_URL
(default https://docs.weaviate.io) on a weekly schedule + manual dispatch;
it is not a PR gate and goes green once the Copy page fix deploys.
- tests/test_docs_functionalities.py: the `functionalities`-marked test
- .github/workflows/docs_functionalities_tests.yml: scheduled/dispatch job
(installs chromium; sets DOCS_GITHUB_ENV=true so it skips the Weaviate stack)
- pytest.ini: register the `functionalities` marker; skip node_modules
- pyproject.toml / uv.lock: add the playwright dependency
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The docs "Copy page" button copied page chrome and didn't produce real markdown. Reported by the team:
Root cause:
copyPageAsMarkdownscrapeddocument.querySelector("article").innerText. The<article>wrapper includes breadcrumbs, the version badge, the mobile TOC, and the footer ("Edit this page", tags), andinnerTextis rendered text, not markdown (code fences, heading#, and link syntax are all lost).Fix
Rewrote
copyPageAsMarkdownto produce clean markdown:.theme-doc-markdown(the content body; page chrome is a sibling outside it).turndown+turndown-plugin-gfm, dynamically imported inside the handler so the site still server-renders at build time (turndown touches the DOM).[aria-hidden="true"].[role="tablist"],[hidden]), decorative icons (img[alt=""]), the code-tab header controls (the.codecontainer header — language selector, "API docs" link, "More info"), and Cloud/Academy badges.errorcopy state ("Copy failed"), anavigator.clipboardguard, andaria-live="polite"on the status label.A reusable
data-copy-excludeopt-out marker was added toCloudOnlyBadgeandAcademyBadgeso their text no longer leaks into the copied markdown.Verification
yarn buildpasses (exit 0).Out of scope / follow-ups
llms-txtplugin path was intentionally not used, to keep this change self-contained.sourceand pinsmain(version drift); the prompts-variant copy doesn't use the new error state.Files
src/components/ContextualMenu/index.js— the fixsrc/components/CloudOnlyBadge/index.jsx,src/components/AcademyBadge/index.jsx—data-copy-excludemarkerspackage.json,yarn.lock— addturndown+turndown-plugin-gfm