Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .changeset/chubby-waves-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@opennextjs/cloudflare": patch
---

fix: bump `@opennextjs/aws` version for `package.json#imports` tracing
23 changes: 23 additions & 0 deletions examples/playground16/app/api/mathjax/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Regression reproduction for https://github.com/opennextjs/opennextjs-cloudflare/issues/1229
import { mathjax } from "@mathjax/src/js/mathjax.js";
import { TeX } from "@mathjax/src/js/input/tex.js";
import "@mathjax/src/js/input/tex/mhchem/MhchemConfiguration.js";
import { SVG } from "@mathjax/src/js/output/svg.js";
import { liteAdaptor } from "@mathjax/src/js/adaptors/liteAdaptor.js";
import { RegisterHTMLHandler } from "@mathjax/src/js/handlers/html.js";

export async function GET() {
const adaptor = liteAdaptor();
RegisterHTMLHandler(adaptor as never);

const tex = new TeX({ packages: ["base", "mhchem"] });
const svg = new SVG({ fontCache: "none" });
const html = mathjax.document("", { InputJax: tex, OutputJax: svg });

const node = html.convert("\\ce{H2O}", { display: true });
const rendered = adaptor.innerHTML(node as never);

return new Response(JSON.stringify({ rendered }), {
headers: { "content-type": "application/json" },
});
}
37 changes: 37 additions & 0 deletions examples/playground16/app/mathjax-mdx/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Regression reproduction for https://github.com/opennextjs/opennextjs-cloudflare/issues/1229
// Mirrors https://github.com/314systems/opennextjs-cloudflare/commit/f7d0420 — exercises the
// same `package.json#imports` remap bug as ../api/mathjax/route.ts, but via the
// `@mdx-js/mdx` + `rehype-mathjax` + `@mathjax/mathjax-fira-font` toolchain (which transitively
// pulls in `@mathjax/src` and its `#default-font/*` / `#mhchem/*` subpath imports).
//
// The page is statically prerendered, so the MDX `evaluate` runs in Node at build time. The
// failure mode under test is at bundling-time: NFT must trace the remap targets and esbuild
// must resolve them when building the OpenNext server bundle.
import { MathJaxFiraFont } from "@mathjax/mathjax-fira-font/mjs/svg.js";
import { evaluate } from "@mdx-js/mdx";
import * as runtime from "react/jsx-runtime";
// @ts-expect-error: no types for the rehype-mathjax MathJax 4 fork
import rehypeMathjax from "rehype-mathjax";
import remarkMath from "remark-math";

async function compileMdx(source: string) {
const { default: MDXContent } = await evaluate(source, {
...(runtime as never),
baseUrl: import.meta.url,
rehypePlugins: [[rehypeMathjax, { svg: { fontData: MathJaxFiraFont } }]],
remarkPlugins: [remarkMath],
});
return { MDXContent };
}

export default async function Page() {
const { MDXContent } = await compileMdx(String.raw`$$ E = mc^2 $$`);
return (
<main className="p-4">
<h1>MathJax MDX Example</h1>
<div data-testid="mathjax-mdx">
<MDXContent />
</div>
</main>
);
}
44 changes: 44 additions & 0 deletions examples/playground16/e2e/mathjax.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { expect, test } from "@playwright/test";

// Regression tests for https://github.com/opennextjs/opennextjs-cloudflare/issues/1229
// `@mathjax/src` uses Node.js package.json#imports to resolve internal subpath
// specifiers (e.g. `#mhchem/*` → `mhchemparser/esm/*`). NFT does not follow the
// `imports` field, so remap targets were missing from the traced output and esbuild
// failed to resolve them. The two tests below exercise the same underlying bug
// through different consumers of `@mathjax/src`.

// Direct consumer: API route calls the MathJax API explicitly. Verifies both build
// (esbuild can resolve the `#mhchem/*` → `mhchemparser` remap) and runtime (the
// remapped module is actually loadable in the worker).
test("mathjax tex→svg via API route (exercises package.json#imports remap)", async ({ request }) => {
const response = await request.get("/api/mathjax");
expect(response.status()).toEqual(200);

const json = await response.json();
expect(json).toHaveProperty("rendered");
// The rendered output should contain an SVG (proves MathJax actually executed,
// which in turn proves the `#mhchem/*` → mhchemparser remap resolved at runtime).
expect(typeof json.rendered).toBe("string");
expect(json.rendered).toMatch(/<svg/);
});

// Indirect consumer: server-component page using `@mdx-js/mdx` + `rehype-mathjax`
// + `@mathjax/mathjax-fira-font`. Mirrors the reproduction in
// https://github.com/314systems/opennextjs-cloudflare/commit/f7d0420. `rehype-mathjax`
// pulls in `@mathjax/src` transitively, exercising the same `package.json#imports`
// remap (`#default-font/*`, `#mhchem/*`) through a different import chain. The page is
// statically prerendered, so MDX `evaluate` runs at build time in Node — the failure
// surfaces during esbuild bundling of the OpenNext server.
test("mathjax via MDX + rehype-mathjax page (exercises remap through transitive import)", async ({
page,
}) => {
const response = await page.goto("/mathjax-mdx");
expect(response?.status()).toEqual(200);

// rehype-mathjax replaces `$$ … $$` with inline SVG at MDX-compile time (one
// SVG per glyph plus a wrapper). Seeing at least one `<svg>` proves the chain
// (mdx → rehype-mathjax → @mathjax/src + @mathjax/mathjax-fira-font) bundled
// and ran successfully.
const svgs = page.getByTestId("mathjax-mdx").locator("svg");
expect(await svgs.count()).toBeGreaterThan(0);
});
2 changes: 1 addition & 1 deletion examples/playground16/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ initOpenNextCloudflareForDev();

const nextConfig: NextConfig = {
typescript: { ignoreBuildErrors: true },
serverExternalPackages: ["shiki"],
serverExternalPackages: ["shiki", "@mathjax/src"],
};

export default nextConfig;
7 changes: 6 additions & 1 deletion examples/playground16/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@
"cf-typegen": "wrangler types --env-interface CloudflareEnv"
},
"dependencies": {
"@mathjax/mathjax-fira-font": "^4.1.1",
"@mathjax/src": "4.1.1",
"@mdx-js/mdx": "^3.1.1",
"next": "16.2.3",
"react-dom": "19.2.4",
"react": "19.2.4",
"shiki": "^3.22.0"
"rehype-mathjax": "github:jajaperson/remark-math#mathjax4&path:packages/rehype-mathjax",
"remark-math": "^6.0.0",
"shiki": "3.22.0"
},
"devDependencies": {
"@opennextjs/cloudflare": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"dependencies": {
"@ast-grep/napi": "^0.40.5",
"@dotenvx/dotenvx": "catalog:",
"@opennextjs/aws": "3.10.4",
"@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@ba2794f",
"ci-info": "^4.2.0",
"cloudflare": "^4.4.1",
"comment-json": "^4.5.1",
Expand Down
Loading
Loading