docs(docs-infra): preserve content before docs-card-container in adev

The tokenizer regex pattern `[^<]*` was consuming all non-`<` content
before custom HTML tags, causing lost content.

Changed to `\s*` which only allows leading whitespace, letting marked
properly tokenize preceding content.
This commit is contained in:
SkyZeroZx
2026-02-19 18:09:27 -05:00
committed by Jessica Janiuk
parent a1501bc90a
commit bc473cf60f
4 changed files with 93 additions and 8 deletions
@@ -21,7 +21,7 @@ interface DocsCardContainerToken extends Tokens.Generic {
// Capture group 1: all attributes on the opening tag
// Capture group 2: all content between the open and close tags
const cardContainerRule =
/^[^<]*<docs-card-container(?:\s([^>]*))?>((?:.(?!\/docs-card-container))*)<\/docs-card-container>/s;
/^\s*<docs-card-container(?:\s([^>]*))?>((?:.(?!\/docs-card-container))*)<\/docs-card-container>/s;
const headerTitleRule = /headerTitle="([^"]*)"/;
const headerImgSrcRule = /headerImgSrc="([^"]*)"/;
@@ -23,7 +23,7 @@ interface DocsCardToken extends Tokens.Generic {
// Capture group 1: all attributes on the opening tag
// Capture group 2: all content between the open and close tags
const cardRule = /^[^<]*<docs-card(?:\s([^>]*))?>((?:.(?!\/docs-card))*)<\/docs-card>/s;
const cardRule = /^\s*<docs-card(?:\s([^>]*))?>((?:.(?!\/docs-card))*)<\/docs-card>/s;
const titleRule = /title="([^"]*)"/;
const linkRule = /link="([^"]*)"/;
@@ -1,4 +1,39 @@
Introductory paragraph that should be preserved before any card containers.
## First Section
This section contains important information about the feature status.
### Available features
- Feature one
- Feature two
- Feature three
### In progress
The following items are currently being developed:
1. Item A with description
2. Item B with description
<docs-card-container>
<docs-card></docs-card>
<docs-card></docs-card>
<docs-card title="Card One"></docs-card>
<docs-card title="Card Two"></docs-card>
</docs-card-container>
### Additional context
More text after the first card container that should also be preserved.
## Second Section
Another paragraph before the second card container.
<docs-card-container>
<docs-card title="Card Three"></docs-card>
</docs-card-container>
## Final Section
Concluding remarks at the end of the document.
@@ -20,10 +20,60 @@ describe('markdown to html', () => {
markdownDocument = JSDOM.fragment(await parseMarkdown(markdownContent, rendererContext));
});
it('creates card containers containing multiple cards', () => {
const containerEl = markdownDocument.querySelector('.docs-card-grid');
it('creates multiple card containers with correct card counts', () => {
const containers = markdownDocument.querySelectorAll('.docs-card-grid');
expect(containerEl!.children.length).toBe(2);
expect(containerEl!.classList.contains('docs-card-grid')).toBeTrue();
expect(containers.length).toBe(2);
expect(containers[0].children.length).toBe(2);
expect(containers[1].children.length).toBe(1);
});
it('preserves all h2 section headings', () => {
const h2Elements = markdownDocument.querySelectorAll('h2');
expect(h2Elements.length).toBe(3);
expect(h2Elements[0].textContent).toContain('First Section');
expect(h2Elements[1].textContent).toContain('Second Section');
expect(h2Elements[2].textContent).toContain('Final Section');
});
it('preserves all h3 subsection headings outside card containers', () => {
// Card titles also render as h3, so we filter to only h3s not inside card containers
const allH3s = Array.from(markdownDocument.querySelectorAll('h3'));
const sectionH3s = allH3s.filter((h3) => !h3.closest('.docs-card-grid'));
expect(sectionH3s.length).toBe(3);
expect(sectionH3s[0].textContent).toContain('Available features');
expect(sectionH3s[1].textContent).toContain('In progress');
expect(sectionH3s[2].textContent).toContain('Additional context');
});
it('preserves unordered lists before card containers', () => {
const ulElements = markdownDocument.querySelectorAll('ul');
expect(ulElements.length).toBeGreaterThanOrEqual(1);
expect(ulElements[0].children.length).toBe(3);
expect(ulElements[0].textContent).toContain('Feature one');
});
it('preserves ordered lists before card containers', () => {
const olElements = markdownDocument.querySelectorAll('ol');
expect(olElements.length).toBe(1);
expect(olElements[0].children.length).toBe(2);
expect(olElements[0].textContent).toContain('Item A');
});
it('preserves paragraphs throughout the document', () => {
const paragraphs = markdownDocument.querySelectorAll('p');
expect(paragraphs.length).toBeGreaterThanOrEqual(5);
const paragraphTexts = Array.from(paragraphs).map((p) => p.textContent);
expect(paragraphTexts.some((t) => t?.includes('Introductory paragraph'))).toBeTrue();
expect(paragraphTexts.some((t) => t?.includes('important information'))).toBeTrue();
expect(paragraphTexts.some((t) => t?.includes('More text after'))).toBeTrue();
expect(paragraphTexts.some((t) => t?.includes('Another paragraph'))).toBeTrue();
expect(paragraphTexts.some((t) => t?.includes('Concluding remarks'))).toBeTrue();
});
});