From 99021649ae713073b95b95a8a3397820e93fdfa6 Mon Sep 17 00:00:00 2001 From: Ethan Setnik Date: Tue, 7 Jul 2026 07:22:03 -0400 Subject: [PATCH 1/2] fix: normalize page path metadata to posix separators The emitted file path (this.resourcePath split at pages/app) carries backslashes on Windows, failing the cross-platform toEqual assertions added in #67 and shipping OS-dependent path metadata to the app. Co-Authored-By: Claude Fable 5 --- src/loader.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/loader.js b/src/loader.js index b555321..7bd186c 100644 --- a/src/loader.js +++ b/src/loader.js @@ -4,18 +4,19 @@ const Markdoc = require('@markdoc/markdoc'); const DEFAULT_SCHEMA_PATH = './markdoc'; -function normalize(s) { - return s.replace(/\\/g, path.win32.sep.repeat(2)); -} - function getRelativeImportPath(from, to) { const relative = path.relative(path.dirname(from), to); if (!relative) { return './'; } - const request = relative.startsWith('.') ? relative : `./${relative}`; - return normalize(request); + // Module specifiers always use forward slashes, on every platform. + // Emitting Windows separators (or escaping them, as the old `normalize` + // helper did for absolute paths) produces per-OS-different loader output — + // the Windows snapshot failure that got #67 reverted — and separators that + // bundlers do not treat as path delimiters. + const request = relative.split(path.sep).join(path.posix.sep); + return request.startsWith('.') ? request : `./${request}`; } async function gatherPartials(ast, schemaDir, tokenizer, parseOptions) { @@ -85,7 +86,13 @@ async function load(source) { // This array access @ index 1 is safe since Next.js guarantees that // all pages will be located under either {app,pages}/ or src/{app,pages}/ // https://nextjs.org/docs/app/building-your-application/configuring/src-directory - const filepath = this.resourcePath.split(appDir ? 'app' : 'pages')[1]; + // Normalized to posix separators so the emitted `path` value is identical + // on every platform (Windows resourcePaths contain backslashes). Undefined + // for resources outside {app,pages}/, e.g. .md files imported as components. + const rawFilepath = this.resourcePath.split(appDir ? 'app' : 'pages')[1]; + const filepath = rawFilepath + ? rawFilepath.split(path.sep).join(path.posix.sep) + : rawFilepath; const partials = await gatherPartials.call( this, From ffae166da9b874251399e4da04e8088ea8ef72dc Mon Sep 17 00:00:00 2001 From: Ethan Setnik Date: Tue, 7 Jul 2026 07:32:28 -0400 Subject: [PATCH 2/2] fix(tests): make the component resourcePath replace OS-portable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'import as frontend component' test replaced a posix-joined substring inside a path.join-built resourcePath, which never matched on Windows — leaving the test exercising the page pathway there. Co-Authored-By: Claude Fable 5 --- tests/index.test.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/index.test.js b/tests/index.test.js index 21f3d6f..c8b5e8d 100644 --- a/tests/index.test.js +++ b/tests/index.test.js @@ -338,8 +338,12 @@ test('mode="server"', async () => { test('import as frontend component', async () => { const o = options(); - // Use a non-page pathway - o.resourcePath = o.resourcePath.replace('pages/test/index.md', 'components/table.md'); + // Use a non-page pathway (join with OS-native separators so the replace + // also matches the backslash resourcePath on Windows) + o.resourcePath = o.resourcePath.replace( + path.join('pages', 'test', 'index.md'), + path.join('components', 'table.md') + ); const output = await callLoader(o, source); expect(normalizeOperatingSystemPaths(output)).toMatchSnapshot();