Skip to content
This repository was archived by the owner on Apr 27, 2026. It is now read-only.
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
7 changes: 6 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,12 @@ jobs:
working-directory: crates/napi
run: pnpm run smoke:napi -- fixtures/core/markdown/hello.md

- name: Run NAPI tests (AVA)
- name: Install Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Run NAPI tests (Bun)
working-directory: crates/napi
run: pnpm test

Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ jobs:
working-directory: crates/napi
run: pnpm run smoke:napi -- fixtures/core/markdown/hello.md

- name: Install Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Run NAPI tests
working-directory: crates/napi
run: pnpm test
Expand Down
10 changes: 1 addition & 9 deletions crates/napi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@
"build": "napi build --platform --release --esm",
"build:napi": "pnpm run build",
"smoke:napi": "node ../../scripts/smoke-napi.mjs",
"test": "ava"
"test": "bun test"
},
"devDependencies": {
"@napi-rs/cli": "^3.4.1",
"ava": "^6.4.1",
"prettier": "^3.6.2"
},
"keywords": [
Expand All @@ -37,12 +36,5 @@
},
"engines": {
"node": ">= 10"
},
"ava": {
"files": [
"tests/**/*.test.js"
],
"timeout": "30s",
"workerThreads": false
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import test from 'ava';
import { test, expect } from 'bun:test';
import { createCompiler } from '../index.js';

const compiler = createCompiler();

test('compile converts directive to Aside component', (t) => {
test('compile converts directive to Aside component', () => {
const source = ':::note\nBody\n:::';
const result = compiler.compile(source, '/virtual.mdx');

// Directive should be converted to Aside component with type in spread props
t.true(result.code.includes('<Aside'));
t.true(result.code.includes('"type": "note"'));
expect(result.code.includes('<Aside')).toBe(true);
expect(result.code.includes('"type": "note"')).toBe(true);
});

test('compile preserves existing Aside import without duplication', (t) => {
test('compile preserves existing Aside import without duplication', () => {
const source = "import { Aside } from '@astrojs/starlight/components';\n\n:::note\nBody\n:::";
const result = compiler.compile(source, '/virtual.mdx');

// User-provided import should be preserved
t.true(result.code.includes("import { Aside } from '@astrojs/starlight/components';"));
expect(result.code.includes("import { Aside } from '@astrojs/starlight/components';")).toBe(true);

// Should not be duplicated
const occurrences = result.code.split("import { Aside } from '@astrojs/starlight/components';").length - 1;
t.is(occurrences, 1);
expect(occurrences).toBe(1);
});
24 changes: 0 additions & 24 deletions crates/napi/tests/fixtures-parity.test.js

This file was deleted.

24 changes: 24 additions & 0 deletions crates/napi/tests/fixtures-parity.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { test, expect } from 'bun:test';
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';

import { compileIr } from '../index.js';

const fixturePath = resolve(import.meta.dir, '../../../fixtures/core/markdown/hello.md');
const markdown = readFileSync(fixturePath, 'utf8');

test('compileIr produces consistent output for hello.md', () => {
const result = compileIr(markdown, '/hello.md');

expect(typeof result.html).toBe('string');
expect(result.html.length > 0).toBe(true);
expect(Array.isArray(result.headings)).toBe(true);
});

test('compileIr with url option produces same html', () => {
const result1 = compileIr(markdown, '/hello.md');
const result2 = compileIr(markdown, '/hello.md', { url: '/test' });

expect(result1.html).toBe(result2.html);
expect(result2.url).toBe('/test');
});
85 changes: 0 additions & 85 deletions crates/napi/tests/parse.test.js

This file was deleted.

85 changes: 85 additions & 0 deletions crates/napi/tests/parse.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { test, expect } from 'bun:test';
import { compileIr } from '../index.js';

test('compileIr() converts markdown to HTML', () => {
const input = '# Hello World';
const result = compileIr(input, '/virtual.md');

expect(result.html.includes('<h1')).toBe(true);
expect(result.html.includes('Hello World')).toBe(true);
expect(result.html.includes('</h1>')).toBe(true);
});

test('compileIr() handles bold and italic text', () => {
const input = 'This is **bold** and *italic* text';
const result = compileIr(input, '/virtual.md');

expect(result.html.includes('<strong>bold</strong>')).toBe(true);
expect(result.html.includes('<em>italic</em>')).toBe(true);
});

test('compileIr() handles code blocks', () => {
const input = '```javascript\nconsole.log("test");\n```';
const result = compileIr(input, '/virtual.md');

expect(result.html.includes('<pre')).toBe(true);
expect(result.html.includes('<code')).toBe(true);
expect(result.html.includes('language-javascript')).toBe(true);
});

test('compileIr() handles images', () => {
const input = '![Alt text](image.png)';
const result = compileIr(input, '/virtual.md');

// HTML is now inside a JSON string (via set:html), so quotes are escaped
expect(result.html.includes('alt=\\"Alt text\\"')).toBe(true);
expect(result.html.includes('src=\\"image.png\\"')).toBe(true);
});

test('compileIr() handles lists', () => {
const input = '- Item 1\n- Item 2\n- Item 3';
const result = compileIr(input, '/virtual.md');

expect(result.html.includes('<ul>')).toBe(true);
expect(result.html.includes('<li>')).toBe(true);
expect(result.html.includes('Item 1')).toBe(true);
expect(result.html.includes('Item 2')).toBe(true);
expect(result.html.includes('</ul>')).toBe(true);
});

test('compileIr() assigns heading ids', () => {
const input = '# Hello Heading';
const result = compileIr(input, '/virtual.md');

// HTML is now inside a JSON string (via set:html), so quotes are escaped
expect(result.html.includes('id=\\"hello-heading\\"')).toBe(true);
});

test('compileIr() handles links', () => {
const input = '[Link text](https://example.com)';
const result = compileIr(input, '/virtual.md');

// HTML is now inside a JSON string (via set:html), so quotes are escaped
expect(result.html.includes('<a href=\\"https://example.com\\">')).toBe(true);
expect(result.html.includes('Link text')).toBe(true);
expect(result.html.includes('</a>')).toBe(true);
});

test('compileIr() returns an object with html', () => {
const result = compileIr('# Test', '/virtual.md');
expect(typeof result).toBe('object');
expect(typeof result.html).toBe('string');
});

test('compileIr() handles empty input', () => {
const result = compileIr('', '/virtual.md');
expect(typeof result.html).toBe('string');
});

test('compileIr() passes through HTML blocks', () => {
const input = '<section>Hello</section>\n\nSome text';
const result = compileIr(input, '/virtual.md');

// Raw HTML is preserved (possibly as JSX spread format)
expect(result.html.includes('section') || result.html.includes('Hello')).toBe(true);
});
52 changes: 0 additions & 52 deletions crates/napi/tests/parseWithOptions.test.js

This file was deleted.

Loading
Loading