Skip to content

fix(docs): export clean selected-language markdown from Copy page button#460

Merged
g-despot merged 6 commits into
mainfrom
fix/copy-page-markdown-export
Jul 1, 2026
Merged

fix(docs): export clean selected-language markdown from Copy page button#460
g-despot merged 6 commits into
mainfrom
fix/copy-page-markdown-export

Conversation

@g-despot

Copy link
Copy Markdown
Contributor

Problem

The docs "Copy page" button copied page chrome and didn't produce real markdown. Reported by the team:

  • copies headers / other page content that shouldn't be included
  • the "markdown" output includes HTML tags / doesn't look right

Root cause: copyPageAsMarkdown scraped document.querySelector("article").innerText. The <article> wrapper includes breadcrumbs, the version badge, the mobile TOC, and the footer ("Edit this page", tags), and innerText is rendered text, not markdown (code fences, heading #, and link syntax are all lost).

Fix

Rewrote copyPageAsMarkdown to produce clean markdown:

  • Scope extraction to .theme-doc-markdown (the content body; page chrome is a sibling outside it).
  • Convert HTML → Markdown with turndown + turndown-plugin-gfm, dynamically imported inside the handler so the site still server-renders at build time (turndown touches the DOM).
  • Capture only the currently-selected code language. The custom code Tabs render every language into the DOM and hide the non-selected ones, so the copy strips [aria-hidden="true"].
  • Strip the remaining in-content chrome: default-tab label strips + inactive panels ([role="tablist"], [hidden]), decorative icons (img[alt=""]), the code-tab header controls (the .code container header — language selector, "API docs" link, "More info"), and Cloud/Academy badges.
  • Preserve Prism code blocks as fenced blocks with the correct language tag and line breaks.
  • Robustness: a new error copy state ("Copy failed"), a navigator.clipboard guard, and aria-live="polite" on the status label.

A reusable data-copy-exclude opt-out marker was added to CloudOnlyBadge and AcademyBadge so their text no longer leaks into the copied markdown.

Verification

  • yarn build passes (exit 0).
  • The turndown pipeline was validated against the real built DOM: page chrome excluded, selected-language-only confirmed by element counts (non-selected language code blocks drop to zero), code blocks fenced with language + line breaks, headings/links/lists correct, and Cloud/Academy badge text stripped.

Out of scope / follow-ups

  • The llms-txt plugin path was intentionally not used, to keep this change self-contained.
  • For a later PR: "View as markdown" builds a 404 when a page has no source and pins main (version drift); the prompts-variant copy doesn't use the new error state.

Files

  • src/components/ContextualMenu/index.js — the fix
  • src/components/CloudOnlyBadge/index.jsx, src/components/AcademyBadge/index.jsxdata-copy-exclude markers
  • package.json, yarn.lock — add turndown + turndown-plugin-gfm

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)

@orca-security-eu orca-security-eu 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.

Orca Security Scan Summary

Status Check Issues by priority
Passed Passed Infrastructure as Code high 0   medium 0   low 0   info 0 View in Orca
Passed Passed SAST high 0   medium 0   low 0   info 0 View in Orca
Passed Passed Secrets high 0   medium 0   low 0   info 0 View in Orca
Passed Passed Vulnerabilities high 0   medium 0   low 0   info 0 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.

Copilot AI 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.

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 copyPageAsMarkdown to clone the rendered doc body, strip UI chrome/hidden panels, and convert HTML → Markdown via turndown (+ GFM plugin) loaded dynamically in the click handler.
  • Adds a reusable data-copy-exclude marker 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.

Comment thread _includes/docs-feedback.mdx
Comment thread src/components/ContextualMenu/index.js
g-despot added 2 commits July 1, 2026 10:26
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.

Copilot AI 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.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.

Comment thread src/components/ContextualMenu/index.js
Comment thread src/components/ContextualMenu/index.js
g-despot added 2 commits July 1, 2026 15:06
…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
@g-despot g-despot merged commit a82ba70 into main Jul 1, 2026
12 of 13 checks passed
@g-despot g-despot deleted the fix/copy-page-markdown-export branch July 1, 2026 15:25
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