diff --git a/adev/shared-docs/pipeline/shared/marked/extensions/docs-card/docs-card-container.mts b/adev/shared-docs/pipeline/shared/marked/extensions/docs-card/docs-card-container.mts index 3d8cfc0fe01..2c7096ff932 100644 --- a/adev/shared-docs/pipeline/shared/marked/extensions/docs-card/docs-card-container.mts +++ b/adev/shared-docs/pipeline/shared/marked/extensions/docs-card/docs-card-container.mts @@ -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))*)<\/docs-card-container>/s; + /^\s*]*))?>((?:.(?!\/docs-card-container))*)<\/docs-card-container>/s; const headerTitleRule = /headerTitle="([^"]*)"/; const headerImgSrcRule = /headerImgSrc="([^"]*)"/; diff --git a/adev/shared-docs/pipeline/shared/marked/extensions/docs-card/docs-card.mts b/adev/shared-docs/pipeline/shared/marked/extensions/docs-card/docs-card.mts index f21fa8469bc..3642e813c6b 100644 --- a/adev/shared-docs/pipeline/shared/marked/extensions/docs-card/docs-card.mts +++ b/adev/shared-docs/pipeline/shared/marked/extensions/docs-card/docs-card.mts @@ -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))*)<\/docs-card>/s; +const cardRule = /^\s*]*))?>((?:.(?!\/docs-card))*)<\/docs-card>/s; const titleRule = /title="([^"]*)"/; const linkRule = /link="([^"]*)"/; diff --git a/adev/shared-docs/pipeline/shared/marked/test/docs-card-container/docs-card-container.md b/adev/shared-docs/pipeline/shared/marked/test/docs-card-container/docs-card-container.md index 29511a71095..bfdc38e7438 100644 --- a/adev/shared-docs/pipeline/shared/marked/test/docs-card-container/docs-card-container.md +++ b/adev/shared-docs/pipeline/shared/marked/test/docs-card-container/docs-card-container.md @@ -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 + - - + + + +### Additional context + +More text after the first card container that should also be preserved. + +## Second Section + +Another paragraph before the second card container. + + + + + +## Final Section + +Concluding remarks at the end of the document. diff --git a/adev/shared-docs/pipeline/shared/marked/test/docs-card-container/docs-card-container.spec.mts b/adev/shared-docs/pipeline/shared/marked/test/docs-card-container/docs-card-container.spec.mts index 3b8363b56ec..86d39c25822 100644 --- a/adev/shared-docs/pipeline/shared/marked/test/docs-card-container/docs-card-container.spec.mts +++ b/adev/shared-docs/pipeline/shared/marked/test/docs-card-container/docs-card-container.spec.mts @@ -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(); }); });