{
+ const markdown = [
+ '```ts [g1:TypeScript]',
+ 'const x: number = 1',
+ '```',
+ ].join('\n')
+
+ html = await processWithFullPipeline(markdown)
+})
+
+describe('rehype-shiki (Layer 3: E2E)', () => {
+ it('should emit Shiki-highlighted ', () => {
+ expect(html).toContain(' {
+ const markdown = ['```js [g1:JavaScript]', 'console.log(1)', '```'].join('\n')
+ html = await processWithFullPipeline(markdown)
+})
+
+describe('remark-code-tabs (Layer 3: E2E)', () => {
+ it('should render data attributes in final HTML', () => {
+ expect(html).toContain('data-code-tabs-group="g1"')
+ expect(html).toContain('data-code-tabs-tab="JavaScript"')
+ })
+})
diff --git a/src/lib/markdown/__tests__/integration/rehype-code-tabs-astro.spec.ts b/src/lib/markdown/__tests__/integration/rehype-code-tabs-astro.spec.ts
new file mode 100644
index 000000000..7bf033d59
--- /dev/null
+++ b/src/lib/markdown/__tests__/integration/rehype-code-tabs-astro.spec.ts
@@ -0,0 +1,22 @@
+import { describe, it, expect } from 'vitest'
+import { processWithFullPipeline } from '@lib/markdown/helpers/processors'
+
+describe('rehype-code-tabs (Layer 2: Astro pipeline)', () => {
+ it('should wrap consecutive grouped code blocks in ', async () => {
+ const markdown = [
+ '```js [g1:JavaScript]',
+ 'console.log(1)',
+ '```',
+ '',
+ '```ts [g1:TypeScript]',
+ 'console.log(2)',
+ '```',
+ ].join('\n')
+
+ const html = await processWithFullPipeline(markdown)
+
+ expect(html).toContain(' {
+ it('should highlight code fences and preserve code-tabs data attributes', async () => {
+ const markdown = [
+ '```ts [g1:TypeScript]',
+ 'const x: number = 1',
+ '```',
+ '',
+ '```ts [g1:TypeScript]',
+ 'const y: number = 2',
+ '```',
+ ].join('\n')
+
+ const html = await processWithFullPipeline(markdown)
+
+ expect(html).toContain(' {
+ it('should keep code block output and attach group/tab data attributes', async () => {
+ const markdown = ['```js [g1:JavaScript]', 'console.log(1)', '```'].join('\n')
+
+ const html = await processWithFullPipeline(markdown)
+
+ expect(html).toContain('data-code-tabs-group="g1"')
+ expect(html).toContain('data-code-tabs-tab="JavaScript"')
+ })
+})
diff --git a/src/lib/markdown/__tests__/units/remark-smartypants.spec.ts b/src/lib/markdown/__tests__/units/remark-smartypants.spec.ts
deleted file mode 100644
index 1cdf938ad..000000000
--- a/src/lib/markdown/__tests__/units/remark-smartypants.spec.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import { describe, it, expect } from 'vitest'
-import { remark } from 'remark'
-import remarkRehype from 'remark-rehype'
-import rehypeStringify from 'rehype-stringify'
-import remarkSmartypants from '@lib/markdown/plugins/remark-smartypants'
-
-import { processIsolated } from '@lib/markdown/helpers/processors'
-
-describe('remark-smartypants (Layer 1: Isolated)', () => {
- it('should convert straight quotes into curly quotes', async () => {
- const markdown = 'He said, "Hello" and \'goodbye\'.'
-
- const html = await processIsolated({ markdown, plugin: remarkSmartypants })
-
- expect(html).toContain('He said, “Hello”')
- expect(html).toContain('‘goodbye’')
- })
-
- it('should convert backticks-style quotes (``like this\'\') into curly quotes', async () => {
- const markdown = "He said, ``like this'' and left."
-
- const html = await processIsolated({ markdown, plugin: remarkSmartypants })
-
- expect(html).toContain('He said, “like this”')
- })
-
- it('should convert -- and --- into en and em dashes', async () => {
- const markdown = 'One -- two --- three.'
-
- const html = await processIsolated({ markdown, plugin: remarkSmartypants })
-
- expect(html).toContain('One – two — three')
- })
-
- it('should convert ... and . . . into ellipsis', async () => {
- const markdown = 'Wait... or wait . . .'
-
- const html = await processIsolated({ markdown, plugin: remarkSmartypants })
-
- expect(html).toContain('Wait… or wait …')
- })
-
- it('should not modify content inside inline code or code blocks', async () => {
- const markdown = [
- 'Outside: "Hello" -- ...',
- '',
- 'Inline: `"Hello" -- ...`',
- '',
- '```text',
- '"Hello" -- ...',
- '```',
- ].join('\n')
-
- const html = await processIsolated({ markdown, plugin: remarkSmartypants })
-
- // Outside should be transformed
- expect(html).toContain('Outside: “Hello” – …')
-
- // Inline + block code should remain literal
- expect(html).toContain('"Hello" -- ...')
- expect(html).toContain('"Hello" -- ...\n')
- })
-
- it('should not modify content within raw HTML blocks like , , ,