Resolver
ts.md の import 文字列を絶対パスとチャンク名に分解するユーティリティです。
cleanImporter: importer の整形
importer のパスから ts-md:
やクエリなどの付加情報を取り除きます。
export function cleanImporter(importer: string): string { return importer .replace(/^\0?ts-md:/, '') .replace(/\?.*$/, '') .replace(/__[^/]+\.ts$/, '');}
resolveImport: import 解析
import path from 'node:path';import { cleanImporter } from ':cleanImporter';
export function resolveImport( specifier: string, importer: string,): { absPath: string; chunk: string } | undefined { const base = cleanImporter(importer);
if (specifier.endsWith('.ts.md') && !specifier.includes(':')) { const absPath = path.resolve(path.dirname(base), specifier); return { absPath, chunk: 'main' }; }
if (!(specifier.includes('.ts.md:') || specifier.startsWith(':'))) { return undefined; } const idx = specifier.lastIndexOf(':'); if (idx === -1) return undefined; const rel = specifier.slice(0, idx); const chunk = specifier.slice(idx + 1); if (!chunk) return undefined; const absPath = rel ? path.resolve(path.dirname(base), rel) : base; if (path.resolve(absPath) !== path.resolve(base)) { return undefined; } return { absPath, chunk };}
公開インタフェース
export { resolveImport } from ':resolveImport';
if (import.meta.vitest) { await import(':resolveImport.test');}
Tests
import { describe, expect, it } from 'vitest';import path from 'node:path';import { resolveImport } from ':resolveImport';
describe('resolveImport', () => { it('resolves relative path', () => { const res = resolveImport('./foo.ts.md', '/a/b/main.ts.md'); expect(res).toEqual({ absPath: '/a/b/foo.ts.md', chunk: 'main' }); }); it('resolves parent dir', () => { const res = resolveImport('../foo.ts.md', '/a/b/c/app.ts.md'); expect(res).toEqual({ absPath: '/a/b/foo.ts.md', chunk: 'main' }); }); it('resolves chunk in same file', () => { const res = resolveImport('./doc.ts.md:qux', '/a/b/doc.ts.md'); expect(res).toEqual({ absPath: '/a/b/doc.ts.md', chunk: 'qux' }); }); it('resolves shorthand same-file import', () => { const res = resolveImport(':qux', '/a/b/doc.ts.md'); expect(res).toEqual({ absPath: '/a/b/doc.ts.md', chunk: 'qux' }); });});
describe('resolveImport with fixture', () => { it('resolves fixture import', () => { const dir = path.join(process.cwd(), 'test', 'fixtures'); const importer = path.join(dir, 'doc.ts.md'); const res = resolveImport('./dep.ts.md', importer); expect(res).toEqual({ absPath: path.join(dir, 'dep.ts.md'), chunk: 'main' }); });});