Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/cli/src/commands/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getConfigValue } from '../utils/config.js';
import { docExistsInAnyFramework, readBundledDoc, readLlmsTxt } from '../utils/docs.js';
import { formatInstallationCode } from '../utils/format.js';
import { mapRawSkin, type PartialInstallFlags, promptFramework, promptInstallOptions } from '../utils/prompts.js';
import { replaceMarker } from '../utils/replace.js';
import { replaceMarker, stripOmitMarkers } from '../utils/replace.js';

interface ParsedFlags {
framework?: string;
Expand Down Expand Up @@ -178,13 +178,13 @@ export async function handleDocs(flags: ParsedFlags, positionals: string[]): Pro
}

const generated = formatInstallationCode(opts);
const output = replaceMarker(markdown, 'installation', generated);
const output = stripOmitMarkers(replaceMarker(markdown, 'installation', generated));
printVersionHeader();
console.log(output);
return;
}

// Regular doc: print as-is
printVersionHeader();
console.log(markdown);
console.log(stripOmitMarkers(markdown));
}
6 changes: 6 additions & 0 deletions packages/cli/src/commands/tests/docs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const INSTALLATION_DOC = `# Installation

Intro paragraph.

<!-- cli:omit installation -->
Run the CLI to generate install code.
<!-- /cli:omit installation -->

<!-- cli:replace installation -->
Placeholder for CLI-generated code.
<!-- /cli:replace installation -->
Expand Down Expand Up @@ -205,6 +209,8 @@ describe('handleDocs', () => {
expect(out).toContain('## HTML');
expect(out).toContain('<video-player>');
expect(out).not.toContain('<!-- cli:replace');
expect(out).not.toContain('<!-- cli:omit');
expect(out).not.toContain('Run the CLI to generate install code');
expect(out).toContain('Intro paragraph');
expect(out).toContain('## Next steps');
});
Expand Down
5 changes: 5 additions & 0 deletions packages/cli/src/utils/replace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ export function replaceMarker(markdown: string, id: string, replacement: string)
const re = new RegExp(`<!-- cli:replace ${id} -->\\n[\\s\\S]*?\\n<!-- /cli:replace ${id} -->`);
return markdown.replace(re, () => replacement);
}

export function stripOmitMarkers(markdown: string): string {
const re = /\n?<!-- cli:omit \S+ -->\n[\s\S]*?\n<!-- \/cli:omit \S+ -->\n?/g;
return markdown.replace(re, '\n');
}
56 changes: 55 additions & 1 deletion packages/cli/src/utils/tests/replace.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
import { replaceMarker } from '../replace.js';
import { replaceMarker, stripOmitMarkers } from '../replace.js';

describe('replaceMarker', () => {
it('replaces content between markers', () => {
Expand Down Expand Up @@ -63,3 +63,57 @@ end`;
expect(result).toBe('start\nsingle line\nend');
});
});

describe('stripOmitMarkers', () => {
it('removes content between omit markers', () => {
const markdown = `# Title

<!-- cli:omit installation -->
CLI-only hint
<!-- /cli:omit installation -->

## Footer`;

const result = stripOmitMarkers(markdown);
expect(result).not.toContain('CLI-only hint');
expect(result).not.toContain('cli:omit');
expect(result).toContain('# Title');
expect(result).toContain('## Footer');
});

it('returns unchanged markdown when no markers are present', () => {
const markdown = '# Title\n\nSome content';
expect(stripOmitMarkers(markdown)).toBe(markdown);
});

it('removes multiple omit blocks with different ids', () => {
const markdown = `before
<!-- cli:omit one -->
alpha
<!-- /cli:omit one -->
middle
<!-- cli:omit two -->
beta
<!-- /cli:omit two -->
after`;

const result = stripOmitMarkers(markdown);
expect(result).not.toContain('alpha');
expect(result).not.toContain('beta');
expect(result).toContain('before');
expect(result).toContain('middle');
expect(result).toContain('after');
});

it('handles multiline content inside an omit block', () => {
const markdown = `start
<!-- cli:omit multi -->
line 1
line 2
line 3
<!-- /cli:omit multi -->
end`;

expect(stripOmitMarkers(markdown)).toBe('start\nend');
});
});
9 changes: 9 additions & 0 deletions site/integrations/llms-markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ export default function llmsMarkdown(): AstroIntegration {
},
});

// Wrap [data-cli-omit] content with text markers the CLI strips from its output
turndown.addRule('cli-omit', {
filter: (node) => node.nodeType === 1 && (node as Element).getAttribute('data-cli-omit') !== null,
replacement: (content, node) => {
const id = (node as Element).getAttribute('data-cli-omit');
return `\n<!-- cli:omit ${id} -->\n${content}\n<!-- /cli:omit ${id} -->\n`;
},
});

// Track all docs and blog pages for llms.txt index
const docsPages: PageEntry[] = [];
const blogPages: PageEntry[] = [];
Expand Down
11 changes: 7 additions & 4 deletions site/src/content/docs/how-to/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ Video.js is an **HTML video player built on custom elements** &mdash; lightweigh
</FrameworkCase>

<LLMCase>
<div data-cli-replace="installation">
<div data-cli-omit="installation">

Run `npx @videojs/cli docs how-to/installation` interactively, or pass all flags:
The code examples in this guide can be tailored to your use case. Run `npx @videojs/cli docs how-to/installation` interactively, or pass all flags:

```bash
npx @videojs/cli docs how-to/installation \
Expand All @@ -45,7 +45,6 @@ npx @videojs/cli docs how-to/installation \
--source-url <url> \
--install-method <cdn|npm|pnpm|yarn|bun>
```

</div>
</LLMCase>

Expand Down Expand Up @@ -81,6 +80,10 @@ Video.js supports a wide range of file types and hosting services. It's easy to
<RendererPicker client:idle />
</ContentWidth>

</HumanCase>

<div data-cli-replace="installation" class="contents">

## Install Video.js

<FrameworkCase frameworks={["html"]}>
Expand Down Expand Up @@ -142,7 +145,7 @@ Add it to your components folder in a new file.
</ContentWidth>
</FrameworkCase>

</HumanCase>
</div>

## CSP

Expand Down
Loading