Skip to content

Enhance LLM export with llms.txt index and copyToLLM styling#336

Merged
jinzhongjia merged 2 commits into
mainfrom
compare-llm-paste
Jun 24, 2026
Merged

Enhance LLM export with llms.txt index and copyToLLM styling#336
jinzhongjia merged 2 commits into
mainfrom
compare-llm-paste

Conversation

@jinzhongjia

Copy link
Copy Markdown
Member

Summary

  • Add llms.txt and llms-full.txt index generation following llmstxt.org standard for LLM-friendly content discovery
  • Recognize <llm-only> as a custom Vue element, hidden on web but included in LLM exports
  • Extract inline styles from copyToLLM component into dedicated CSS file with improved accessibility (ARIA attributes, focus states, transitions)
  • Add click-outside and Escape key handlers to close the copy menu for better UX
  • Pass site title and description to LLM markdown generation for metadata headers

Changes

config.mts: Configure Vue to recognize <llm-only> elements; pass title/description to plugin

llmMarkdown.ts: Generate llms.txt (linked index) and llms-full.txt (concatenated content); implement unwrapLlmOnly() to strip tags for LLM output while keeping them for web display

copyToLLM.ts: Move inline styles to CSS classes; add keyboard/click event handlers for menu closure; add ARIA attributes for accessibility

copyToLLM.css (new): Style copy menu, trigger button, and hide <llm-only> blocks on web

index.ts: Import new stylesheet

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request enhances the LLM-friendly markdown generation by introducing llms.txt and llms-full.txt indexes, supporting <llm-only> custom elements to hide web-only content, and refactoring the copy-to-LLM UI component to use external CSS and support keyboard/click-away interactions. The review feedback suggests three key improvements: using relative paths in llms.txt for better portability, stripping custom VitePress anchors from headings when parsing titles, and updating the <llm-only> regex to handle potential HTML attributes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

const links = pages
.map((page) => {
const title = firstHeading(page.markdown) ?? page.relativePath;
return `- [${title}](${ORIGIN}/llms/${page.relativePath})`;

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.

medium

Using relative paths in llms.txt is more robust and portable than hardcoding ORIGIN. It allows the index to work correctly on local previews, staging environments, or if the site is hosted under a different domain or base path. LLM clients will resolve these relative links against the URL of the llms.txt file itself.

Suggested change
return `- [${title}](${ORIGIN}/llms/${page.relativePath})`;
return "- [" + title + "](llms/" + page.relativePath + ")";

Comment on lines +111 to 113
function firstHeading(markdown: string): string | null {
return markdown.match(/^#\s+(.+)$/m)?.[1].trim() ?? null;
}

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.

medium

VitePress headings often contain custom anchors like {#custom-id} (e.g., # Zig 语言圣经 {#zig-bible}). The current regex will include these anchors in the title, which looks messy in the llms.txt index. Stripping them out ensures a clean title.

function firstHeading(markdown: string): string | null {
  const match = markdown.match(/^#\\s+(.+)$/m);
  if (!match) return null;
  return match[1].replace(/\\{#[\\w-]+\\\}\\s*$/, "").trim();
}

Comment on lines +289 to +291
function unwrapLlmOnly(markdown: string): string {
return markdown.replace(/<\/?llm-only\s*>/gi, "");
}

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.

medium

If the <llm-only> tag has any attributes (such as classes, styles, or Vue directives) or multiple spaces, the current regex /<\\/?llm-only\\s*>/gi will fail to match and strip it. Updating the regex to support optional attributes ensures that the tags are always stripped correctly from the LLM markdown output.

function unwrapLlmOnly(markdown: string): string {
  return markdown.replace(/<\\/?llm-only(?:\\s+[^>]*)?>/gi, "");
}

@jinzhongjia jinzhongjia merged commit 3510015 into main Jun 24, 2026
5 checks passed
@jinzhongjia jinzhongjia deleted the compare-llm-paste branch June 24, 2026 16:51
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.

1 participant