⚡ Give @tinacms/mdx a light sanitize-url subpath so rich-text skips the parser#7233
Conversation
…he parser TinaMarkdown/StaticTinaMarkdown only needed sanitizeUrl from @tinacms/mdx, but importing anything from the package root pulled in its whole remark/mdast/micromark bundle (~2MB) into every site's client bundle. Adds a dedicated @tinacms/mdx/sanitize-url entry (same multi-entry pattern as @tinacms/bridge) and points tinacms's rich-text renderer at it. The root @tinacms/mdx export of sanitizeUrl is unchanged. Fixes #7232 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: c86202f The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Playwright E2E Test ResultsDetails
Skipped testschromium › retain-input-value-from-localstorage.spec.ts › Local storage retain edit test |
joshbermanssw
left a comment
There was a problem hiding this comment.
Approving. Built the branch and verified the numbers rather than reading them: dist/sanitize-url.js is 658 bytes with no remark/mdast/micromark/prettier in it, dist/index.js is untouched at 2,013,373 bytes, both rich-text entries emit the subpath import, the subpath and root export resolve identically at runtime, and the types task emits a real .d.ts (not the build-time stub). mdx tests and the tinacms typecheck pass. The sanitizer body is a byte-identical move, which is the right call for a security-relevant function.
Two follow-ups, neither blocking:
-
Latent footgun worth a comment.
@tinacms/scripts(src/index.ts:411-435) hardcodesdist/index.js/dist/index.browser.jsas outfiles in the@tinacms/mdxbranch, ignoring the entry's computed output path. The new entry is safe only because it's a plain string, which normalizes totarget: 'browser'and takes the Vite path instead. If someone later rewrites it in object form withtarget: 'node'to match its sibling (which reads as harmless tidying), it silently overwrites the 2MB root bundle with the 658-byte sanitizer. Worth a note on the entry inpackage.json, or fixing the script to useoutInfo.outfile. -
The description's mechanism isn't quite right.
bundleDepsisn't read anywhere in@tinacms/scripts; theEntrytype hasbundle: string[](graphql/datalayer only) andtarget. mdx's dep bundling comes from that hardcoded package-name branch. The outcome is correct, but the causal story will mislead whoever touches this next.
Nits: the sanitizeUrl tests still live in parse/remarkToPlate.test.ts and import from ./remarkToPlate, so they exercise the re-export shim rather than the new module (src/sanitize-url.test.ts would be the natural home). And the changeset says "~15-line sanitizer" while the PR body says "~40-line"; the changeset is the one that lands in the public CHANGELOG.
📦 Tagged Release PublishedYour tagged PR has been published! You can install the packages using their version tags: pnpm add @tinacms/app@0.0.0-2f4b2ec-20260715013251
pnpm add @tinacms/astro@0.0.0-2f4b2ec-20260715013251
pnpm add @tinacms/bridge@0.0.0-2f4b2ec-20260715013251
pnpm add @tinacms/cli@0.0.0-2f4b2ec-20260715013251
pnpm add @tinacms/datalayer@0.0.0-2f4b2ec-20260715013251
pnpm add @tinacms/graphql@0.0.0-2f4b2ec-20260715013251
pnpm add @tinacms/mdx@0.0.0-2f4b2ec-20260715013251
pnpm add @tinacms/search@0.0.0-2f4b2ec-20260715013251
pnpm add @tinacms/vercel-previews@0.0.0-2f4b2ec-20260715013251
pnpm add next-tinacms-azure@0.0.0-2f4b2ec-20260715013251
pnpm add next-tinacms-cloudinary@0.0.0-2f4b2ec-20260715013251
pnpm add next-tinacms-dos@0.0.0-2f4b2ec-20260715013251
pnpm add next-tinacms-s3@0.0.0-2f4b2ec-20260715013251
pnpm add tinacms-authjs@0.0.0-2f4b2ec-20260715013251
pnpm add tinacms-clerk@0.0.0-2f4b2ec-20260715013251
pnpm add tinacms-gitprovider-github@0.0.0-2f4b2ec-20260715013251
pnpm add tinacms@0.0.0-2f4b2ec-20260715013251Published Packages:
Commit: |
Tagged: tina-io-git-jb-test-7233-tinacms.vercel.app
Summary
packages/tinacms/src/rich-text/index.tsxandstatic.tsx(source ofTinaMarkdown/StaticTinaMarkdown) importedsanitizeUrlfrom the root@tinacms/mdxentry, which is built withbundleDeps: trueand inlines the entire remark/mdast/micromark/prettier markdown-parsing toolchain (~2MB) — even thoughsanitizeUrlis a ~40-line URL-scheme check.@tinacms/mdx/sanitize-urlsubpath (own entry point inbuildConfig.entryPoints, ownexportsmap entry — same multi-entry pattern@tinacms/bridgealready uses) and points the rich-text renderer at it instead.@tinacms/mdxexport ofsanitizeUrlis unchanged (still re-exported fromparse/remarkToPlate.ts), so this is purely additive/non-breaking.Fixes #7232
Measured before/after
Built both packages from
main(711ba30f6) vs. this branch withpnpm exec turbo run build --filter=@tinacms/mdx --filter=tinacms --force, then measured the actual emitted files:tinacms/dist/rich-text/index.jsimportfrom "@tinacms/mdx"from "@tinacms/mdx/sanitize-url"@tinacms/mdx/dist/index.js— 2,013,349 bytes (Node/SSR) ordist/index.browser.js— 1,976,351 bytes (browser condition)@tinacms/mdx/dist/sanitize-url.js— 658 bytesrich-text/index.jsitselfThat's a ~99.3% reduction — the new
sanitize-url.jswas also grepped to confirm it contains noremark/mdast/micromark/prettierreferences.Test plan
pnpm testfrom repo root (full suite, not filtered) — 58/58 tasks passed, including@tinacms/mdx's existingsanitizeUrlunit tests (remarkToPlate.test.ts, 21 tests, unchanged) andtinacms's full vitest suite (444 passed, 5 skipped)packages/@tinacms/mdx/dist/sanitize-url.jsis 658 bytes and free of remark/mdast/micromark/prettier importspackages/tinacms/dist/rich-text/index.jsnow imports@tinacms/mdx/sanitize-url, not the@tinacms/mdxroottsc(thetypestask) emits a real.d.tsfor the new entry point@tinacms/mdx: minor,tinacms: patch)🤖 Generated with Claude Code