[
  {
    "path": ".editorconfig",
    "content": "# Stop the editor from looking for .editorconfig files in the parent directories\nroot = true\n\n[*]\n# Non-configurable Prettier behaviors\ncharset = utf-8\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n# Configurable Prettier behaviors\nend_of_line = lf\nindent_style = space\nindent_size = 2\nmax_line_length = 96\n\n[*.md]\ntrim_trailing_whitespace = false\nmax_line_length = off"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [ipikuka]\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: main\non:\n  pull_request:\n    branches:\n      - \"**\"\n  push:\n    branches:\n      - \"**\"\njobs:\n  test:\n    name: Test (Node ${{ matrix.node }})\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        node: [20, 22, 24]\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n      - name: Setup Node ${{ matrix.node }}\n        uses: actions/setup-node@v6\n        with:\n          node-version: ${{ matrix.node }}\n          cache: npm\n      - run: npm ci\n      - run: npm test\n      - run: npm run format\n  coverage:\n    name: Code Coverage (Node 22)\n    needs: test\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n      - name: Setup Node 22\n        uses: actions/setup-node@v6\n        with:\n          node-version: 22\n          cache: npm\n      - run: npm ci\n      - run: npm run test-coverage\n      - name: Upload coverage to Codecov\n        uses: codecov/codecov-action@v5\n        with:\n          directory: ./coverage/\n          files: ./coverage.json\n          fail_ci_if_error: true\n          verbose: true\n          token: ${{ secrets.CODECOV_TOKEN }}\n          slug: ipikuka/next-mdx-remote-client\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: publish to npm\non:\n  release:\n    types: [published]\njobs:\n  publish:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      id-token: write # for provenance\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n      - name: Setup Node 22\n        uses: actions/setup-node@v6\n        with:\n          node-version: 22\n          registry-url: https://registry.npmjs.org/\n          cache: npm\n      - run: npm ci\n      - run: npm run build\n      - run: npm publish --provenance --access public\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.vscode\ndist\nnode_modules\narchive\ncoverage"
  },
  {
    "path": ".npmignore",
    "content": "dist/*.tsbuildinfo"
  },
  {
    "path": ".npmrc",
    "content": "ignore-scripts=true"
  },
  {
    "path": ".prettierignore",
    "content": ".DS_Store\n.vscode\ndist\nnode_modules\npackage-lock.json\narchive\ncoverage\nREADME.md\nmigration_guide.md"
  },
  {
    "path": ".prettierrc.json",
    "content": "{\n  \"singleQuote\": false,\n  \"bracketSpacing\": true,\n  \"trailingComma\": \"all\",\n  \"tabWidth\": 2,\n  \"useTabs\": false,\n  \"semi\": true,\n  \"arrowParens\": \"always\",\n  \"endOfLine\": \"lf\",\n  \"printWidth\": 96,\n  \"objectWrap\": \"preserve\"\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "# Mozilla Public License Version 2.0\n\nCopyright (c) 2026 @talatkuyuk AKA @ipikuka\n\n1. Definitions\n\n---\n\n1.1. \"Contributor\"\nmeans each individual or legal entity that creates, contributes to\nthe creation of, or owns Covered Software.\n\n1.2. \"Contributor Version\"\nmeans the combination of the Contributions of others (if any) used\nby a Contributor and that particular Contributor's Contribution.\n\n1.3. \"Contribution\"\nmeans Covered Software of a particular Contributor.\n\n1.4. \"Covered Software\"\nmeans Source Code Form to which the initial Contributor has attached\nthe notice in Exhibit A, the Executable Form of such Source Code\nForm, and Modifications of such Source Code Form, in each case\nincluding portions thereof.\n\n1.5. \"Incompatible With Secondary Licenses\"\nmeans\n\n    (a) that the initial Contributor has attached the notice described\n        in Exhibit B to the Covered Software; or\n\n    (b) that the Covered Software was made available under the terms of\n        version 1.1 or earlier of the License, but not also under the\n        terms of a Secondary License.\n\n1.6. \"Executable Form\"\nmeans any form of the work other than Source Code Form.\n\n1.7. \"Larger Work\"\nmeans a work that combines Covered Software with other material, in\na separate file or files, that is not Covered Software.\n\n1.8. \"License\"\nmeans this document.\n\n1.9. \"Licensable\"\nmeans having the right to grant, to the maximum extent possible,\nwhether at the time of the initial grant or subsequently, any and\nall of the rights conveyed by this License.\n\n1.10. \"Modifications\"\nmeans any of the following:\n\n    (a) any file in Source Code Form that results from an addition to,\n        deletion from, or modification of the contents of Covered\n        Software; or\n\n    (b) any new file in Source Code Form that contains any Covered\n        Software.\n\n1.11. \"Patent Claims\" of a Contributor\nmeans any patent claim(s), including without limitation, method,\nprocess, and apparatus claims, in any patent Licensable by such\nContributor that would be infringed, but for the grant of the\nLicense, by the making, using, selling, offering for sale, having\nmade, import, or transfer of either its Contributions or its\nContributor Version.\n\n1.12. \"Secondary License\"\nmeans either the GNU General Public License, Version 2.0, the GNU\nLesser General Public License, Version 2.1, the GNU Affero General\nPublic License, Version 3.0, or any later versions of those\nlicenses.\n\n1.13. \"Source Code Form\"\nmeans the form of the work preferred for making modifications.\n\n1.14. \"You\" (or \"Your\")\nmeans an individual or a legal entity exercising rights under this\nLicense. For legal entities, \"You\" includes any entity that\ncontrols, is controlled by, or is under common control with You. For\npurposes of this definition, \"control\" means (a) the power, direct\nor indirect, to cause the direction or management of such entity,\nwhether by contract or otherwise, or (b) ownership of more than\nfifty percent (50%) of the outstanding shares or beneficial\nownership of such entity.\n\n2. License Grants and Conditions\n\n---\n\n2.1. Grants\n\nEach Contributor hereby grants You a world-wide, royalty-free,\nnon-exclusive license:\n\n(a) under intellectual property rights (other than patent or trademark)\nLicensable by such Contributor to use, reproduce, make available,\nmodify, display, perform, distribute, and otherwise exploit its\nContributions, either on an unmodified basis, with Modifications, or\nas part of a Larger Work; and\n\n(b) under Patent Claims of such Contributor to make, use, sell, offer\nfor sale, have made, import, and otherwise transfer either its\nContributions or its Contributor Version.\n\n2.2. Effective Date\n\nThe licenses granted in Section 2.1 with respect to any Contribution\nbecome effective for each Contribution on the date the Contributor first\ndistributes such Contribution.\n\n2.3. Limitations on Grant Scope\n\nThe licenses granted in this Section 2 are the only rights granted under\nthis License. No additional rights or licenses will be implied from the\ndistribution or licensing of Covered Software under this License.\nNotwithstanding Section 2.1(b) above, no patent license is granted by a\nContributor:\n\n(a) for any code that a Contributor has removed from Covered Software;\nor\n\n(b) for infringements caused by: (i) Your and any other third party's\nmodifications of Covered Software, or (ii) the combination of its\nContributions with other software (except as part of its Contributor\nVersion); or\n\n(c) under Patent Claims infringed by Covered Software in the absence of\nits Contributions.\n\nThis License does not grant any rights in the trademarks, service marks,\nor logos of any Contributor (except as may be necessary to comply with\nthe notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\nNo Contributor makes additional grants as a result of Your choice to\ndistribute the Covered Software under a subsequent version of this\nLicense (see Section 10.2) or under the terms of a Secondary License (if\npermitted under the terms of Section 3.3).\n\n2.5. Representation\n\nEach Contributor represents that the Contributor believes its\nContributions are its original creation(s) or it has sufficient rights\nto grant the rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\nThis License is not intended to limit any rights You have under\napplicable copyright doctrines of fair use, fair dealing, or other\nequivalents.\n\n2.7. Conditions\n\nSections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted\nin Section 2.1.\n\n3. Responsibilities\n\n---\n\n3.1. Distribution of Source Form\n\nAll distribution of Covered Software in Source Code Form, including any\nModifications that You create or to which You contribute, must be under\nthe terms of this License. You must inform recipients that the Source\nCode Form of the Covered Software is governed by the terms of this\nLicense, and how they can obtain a copy of this License. You may not\nattempt to alter or restrict the recipients' rights in the Source Code\nForm.\n\n3.2. Distribution of Executable Form\n\nIf You distribute Covered Software in Executable Form then:\n\n(a) such Covered Software must also be made available in Source Code\nForm, as described in Section 3.1, and You must inform recipients of\nthe Executable Form how they can obtain a copy of such Source Code\nForm by reasonable means in a timely manner, at a charge no more\nthan the cost of distribution to the recipient; and\n\n(b) You may distribute such Executable Form under the terms of this\nLicense, or sublicense it under different terms, provided that the\nlicense for the Executable Form does not attempt to limit or alter\nthe recipients' rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\nYou may create and distribute a Larger Work under terms of Your choice,\nprovided that You also comply with the requirements of this License for\nthe Covered Software. If the Larger Work is a combination of Covered\nSoftware with a work governed by one or more Secondary Licenses, and the\nCovered Software is not Incompatible With Secondary Licenses, this\nLicense permits You to additionally distribute such Covered Software\nunder the terms of such Secondary License(s), so that the recipient of\nthe Larger Work may, at their option, further distribute the Covered\nSoftware under the terms of either this License or such Secondary\nLicense(s).\n\n3.4. Notices\n\nYou may not remove or alter the substance of any license notices\n(including copyright notices, patent notices, disclaimers of warranty,\nor limitations of liability) contained within the Source Code Form of\nthe Covered Software, except that You may alter any license notices to\nthe extent required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\nYou may choose to offer, and to charge a fee for, warranty, support,\nindemnity or liability obligations to one or more recipients of Covered\nSoftware. However, You may do so only on Your own behalf, and not on\nbehalf of any Contributor. You must make it absolutely clear that any\nsuch warranty, support, indemnity, or liability obligation is offered by\nYou alone, and You hereby agree to indemnify every Contributor for any\nliability incurred by such Contributor as a result of warranty, support,\nindemnity or liability terms You offer. You may include additional\ndisclaimers of warranty and limitations of liability specific to any\njurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n\n---\n\nIf it is impossible for You to comply with any of the terms of this\nLicense with respect to some or all of the Covered Software due to\nstatute, judicial order, or regulation then You must: (a) comply with\nthe terms of this License to the maximum extent possible; and (b)\ndescribe the limitations and the code they affect. Such description must\nbe placed in a text file included with all distributions of the Covered\nSoftware under this License. Except to the extent prohibited by statute\nor regulation, such description must be sufficiently detailed for a\nrecipient of ordinary skill to be able to understand it.\n\n5. Termination\n\n---\n\n5.1. The rights granted under this License will terminate automatically\nif You fail to comply with any of its terms. However, if You become\ncompliant, then the rights granted under this License from a particular\nContributor are reinstated (a) provisionally, unless and until such\nContributor explicitly and finally terminates Your grants, and (b) on an\nongoing basis, if such Contributor fails to notify You of the\nnon-compliance by some reasonable means prior to 60 days after You have\ncome back into compliance. Moreover, Your grants from a particular\nContributor are reinstated on an ongoing basis if such Contributor\nnotifies You of the non-compliance by some reasonable means, this is the\nfirst time You have received notice of non-compliance with this License\nfrom such Contributor, and You become compliant prior to 30 days after\nYour receipt of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\ninfringement claim (excluding declaratory judgment actions,\ncounter-claims, and cross-claims) alleging that a Contributor Version\ndirectly or indirectly infringes any patent, then the rights granted to\nYou by any and all Contributors for the Covered Software under Section\n2.1 of this License shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all\nend user license agreements (excluding distributors and resellers) which\nhave been validly granted by You or Your distributors under this License\nprior to termination shall survive termination.\n\n---\n\n-                                                                      *\n- 6.  Disclaimer of Warranty \\*\n- ------------------------- \\*\n-                                                                      *\n- Covered Software is provided under this License on an \"as is\" \\*\n- basis, without warranty of any kind, either expressed, implied, or \\*\n- statutory, including, without limitation, warranties that the \\*\n- Covered Software is free of defects, merchantable, fit for a \\*\n- particular purpose or non-infringing. The entire risk as to the \\*\n- quality and performance of the Covered Software is with You. \\*\n- Should any Covered Software prove defective in any respect, You \\*\n- (not any Contributor) assume the cost of any necessary servicing, \\*\n- repair, or correction. This disclaimer of warranty constitutes an \\*\n- essential part of this License. No use of any Covered Software is \\*\n- authorized under this License except under this disclaimer. \\*\n-                                                                      *\n\n---\n\n---\n\n-                                                                      *\n- 7.  Limitation of Liability \\*\n- -------------------------- \\*\n-                                                                      *\n- Under no circumstances and under no legal theory, whether tort \\*\n- (including negligence), contract, or otherwise, shall any \\*\n- Contributor, or anyone who distributes Covered Software as \\*\n- permitted above, be liable to You for any direct, indirect, \\*\n- special, incidental, or consequential damages of any character \\*\n- including, without limitation, damages for lost profits, loss of \\*\n- goodwill, work stoppage, computer failure or malfunction, or any \\*\n- and all other commercial damages or losses, even if such party \\*\n- shall have been informed of the possibility of such damages. This \\*\n- limitation of liability shall not apply to liability for death or \\*\n- personal injury resulting from such party's negligence to the \\*\n- extent applicable law prohibits such limitation. Some \\*\n- jurisdictions do not allow the exclusion or limitation of \\*\n- incidental or consequential damages, so this exclusion and \\*\n- limitation may not apply to You. \\*\n-                                                                      *\n\n---\n\n8. Litigation\n\n---\n\nAny litigation relating to this License may be brought only in the\ncourts of a jurisdiction where the defendant maintains its principal\nplace of business and such litigation shall be governed by laws of that\njurisdiction, without reference to its conflict-of-law provisions.\nNothing in this Section shall prevent a party's ability to bring\ncross-claims or counter-claims.\n\n9. Miscellaneous\n\n---\n\nThis License represents the complete agreement concerning the subject\nmatter hereof. If any provision of this License is held to be\nunenforceable, such provision shall be reformed only to the extent\nnecessary to make it enforceable. Any law or regulation which provides\nthat the language of a contract shall be construed against the drafter\nshall not be used to construe this License against a Contributor.\n\n10. Versions of the License\n\n---\n\n10.1. New Versions\n\nMozilla Foundation is the license steward. Except as provided in Section\n10.3, no one other than the license steward has the right to modify or\npublish new versions of this License. Each version will be given a\ndistinguishing version number.\n\n10.2. Effect of New Versions\n\nYou may distribute the Covered Software under the terms of the version\nof the License under which You originally received the Covered Software,\nor under the terms of any subsequent version published by the license\nsteward.\n\n10.3. Modified Versions\n\nIf you create software not governed by this License, and you want to\ncreate a new license for such software, you may create and use a\nmodified version of this License if you rename the license and remove\nany references to the name of the license steward (except to note that\nsuch modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary\nLicenses\n\nIf You choose to distribute Source Code Form that is Incompatible With\nSecondary Licenses under the terms of this version of the License, the\nnotice described in Exhibit B of this License must be attached.\n\n## Exhibit A - Source Code Form License Notice\n\nThis Source Code Form is subject to the terms of the Mozilla Public\nLicense, v. 2.0. If a copy of the MPL was not distributed with this\nfile, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular\nfile, then You may include the notice in a location (such as a LICENSE\nfile in a relevant directory) where a recipient would be likely to look\nfor such a notice.\n\nYou may add additional accurate notices of copyright ownership.\n\n## Exhibit B - \"Incompatible With Secondary Licenses\" Notice\n\nThis Source Code Form is \"Incompatible With Secondary Licenses\", as\ndefined by the Mozilla Public License, v. 2.0.\n"
  },
  {
    "path": "README.md",
    "content": "**A robust Next.js newsletter `Next.js Weekly` is sponsoring me** 💖\n[![NextjsWeekly banner](./assets/next-js-weekly.png)](https://nextjsweekly.com/)\n\n### [Become a sponsor](https://github.com/sponsors/ipikuka/) 🚀\n\nIf you find **`next-mdx-remote-client`** useful in your projects, consider supporting my work.  \nYour sponsorship means a lot 💖\n\nMy sponsors are going to be featured here and on [my sponsor wall](https://github.com/sponsors/ipikuka).\n\nA warm thanks 🙌 to [@ErfanEbrahimnia](https://github.com/ErfanEbrahimnia), [@recepkyk](https://github.com/recepkyk), and [@LSeaburg](https://github.com/LSeaburg) for the support!\n\nThank you for supporting open source! 🙌\n\n# next-mdx-remote-client\n\n[![npm version][badge-npm-version]][url-npm-package]\n[![npm downloads][badge-npm-download]][url-npm-package]\n[![publish to npm][badge-publish-to-npm]][url-publish-github-actions]\n[![code-coverage][badge-codecov]][url-codecov]\n[![type-coverage][badge-type-coverage]][url-github-package]\n[![typescript][badge-typescript]][url-typescript]\n[![license][badge-license]][url-license]\n\n**`next-mdx-remote-client`** is recommended in the [`Next.js` official documentation](https://nextjs.org/docs/15/app/guides/mdx#remote-mdx).\n\n> [!IMPORTANT]\n> **If you are using `react18`, use ver.1 of `next-mdx-remote-client`, currently `v1.1`**\n>\n> **If you are using `react19`, use ver.2 of `next-mdx-remote-client`, currently `v2.1`**\n>\n> *The both serve the same features and APIs. I am going to maintain both.*\n\n**`next-mdx-remote-client`** is a wrapper of **`@mdx-js/mdx`** for **`nextjs`** applications in order to load MDX content. It is a fork of **`next-mdx-remote`**.\n\nSee some blog applications in which **`next-mdx-remote-client`** is used:\n+ for a **`app` router demo application** visit [source code](https://github.com/talatkuyuk/next-mdx-remote-client-in-app-router) or [living web site](https://nmrc-in-app-router.vercel.app/),\n+ for a **`pages` router demo application** visit [source code](https://github.com/talatkuyuk/next-mdx-remote-client-in-pages-router) or [living web site](https://nmrc-in-pages-router.vercel.app/),\n+ for a **testing application** which uses **both `app` and `pages` router**, visit [source code](https://github.com/talatkuyuk/testing-app-for-next-mdx-remote-client) or [living web site](https://testing-app-for-nmrc.vercel.app/).\n\n## Why `next-mdx-remote-client` ?\n\nI started to create **`next-mdx-remote-client`** in line with the mindset of **`@mdx-js/mdx`** in early 2024 considering **`next-mdx-remote`** had not been updated for a long time, and finally, a brand new package emerged.\n\n**`next-mdx-remote-client`** serves as a **viable alternative** to **`next-mdx-remote`** having **more features**.\n\n**I would like to highlight some main features:**\n+ It supports MDX version 3.\n+ It provides well designed components and functions for both \"pages\" router and \"app\" router, which completely isolated from eachother.\n+ It provides internal error handling mechanism.\n+ It supports `import statements` and `export statements` in MDX source, which can be disabled as well.\n+ Creating table of contents (TOC) is so easy since it supports passing `vfile.data` into the `scope`.\n+ You can get frontmatter without compiling the source for example for listing articles/posts via `getFrontmatter`.\n+ It exports some components and types from `@mdx-js/mdx` so as you don't need to install.\n\nLet's compare the features of **`next-mdx-remote`** and **`next-mdx-remote-client`**.\n\n| Features                                                    | `next-mdx-remote`   | `next-mdx-remote-client` |\n| :---------------------------------------------------------- | :-----------------: | :----------------------: |\n| support MDX version 3                                       | ✅                  | ✅                        |\n| ensure internal error handling mechanism in `app` router    | ❌                  | ✅                        |\n| ensure internal error handling mechanism in `pages` router  | ❌                  | ✅                        |\n| support _export-from-MDX_ in `app` router                   | ❌                  | ✅                        |\n| support _export-from-MDX_ in `pages` router                 | ❌                  | ✅                        | \n| support _import-into-MDX_ in `app` router                   | ❌                  | ✅                        |\n| support _import-into-MDX_ in `pages` router                 | ❌                  | ❌                        |\n| get frontmatter and mutated scope in `app` router           | ❌                  | ✅                        |\n| get frontmatter and mutated scope in `pages` router         | ✅                  | ✅                        |\n| support options for disabling imports and exports in MDX    | ✅                  | ✅                        |\n| support passing `vfile.data` into the `scope`               | ❌                  | ✅                        |\n| provide utility for getting frontmatter without compiling   | ❌                  | ✅                        |\n| expose `MDXProvider` from `@mdx-js/mdx`                     | ❌                  | ✅                        |\n| provide option for disabling parent `MDXProvider` contexts  | ❌                  | ✅                        |\n| expose the necessary types from `mdx/types`                 | ❌                  | ✅                        |\n| injects `React` instance into runtime options               | ❌                  | ✅                        |\n\n> [!IMPORTANT]\n> You will see a lot the abbreviatons **`csr`** and **`rsc`**. _Pay attention to the both are spelled backwards._\\\n> \\\n> **`csr`** stands for \"client side rendering\" which is related with **`pages`** router\\\n> **`rsc`** stands for \"react server component\" which is related with **`app`** router\n\n## General considerations about development\n\n- It is ESM only package\n- Needs `react` version 19.1+, works with `next@15` and `next@16` versions (tested)\n- Needs `node` version 20.9.0+ in line with `Next.js` does\n- Vitest is used instead of jest for testing\n- Rollup is removed for bundling\n- Test coverage is 100%\n- Type coverage is 100%\n- The parts client side (csr) and server side (rsc) are completely isolated from each other\n- Exported a small utility to get frontmatter without compiling the source\n- **All functions take named parameters**\n- Supports `import statements` and `export statements` in MDX\n- Export statements in MDX work for **both** `app` and `pages` router\n- Import statements in MDX work for **only** `app` router\n\n> [!IMPORTANT]\n> **Imported modules in MDX with relative path should be transpiled into javascript before or during build process, otherwise will not work.** I believe the community can find a solution to import reqular **`.jsx`** or **`.tsx`** modules into MDX. With the support of the **`next/mdx`**, it is viable to import **`.mdx`** into MDX, but not tested yet.\n\n## Installation\n\nThis package is ESM only, requires Node.js (version 18.18+).\n\n```bash\n# in general\nnpm install next-mdx-remote-client\n\n# specifically for react18 users\nnpm install next-mdx-remote-client@^1\n\n# specifically for react19 users\nnpm install next-mdx-remote-client@^2\n```\n\nor\n\n```bash\nyarn add next-mdx-remote-client\n```\n\n> [!WARNING]  \n> **`next-mdx-remote`** users may follow the [migration guide](/migration_guide.md).\n\n## Initial Security Concerns\n\nBefore diving into **`next-mdx-remote-client`**, it’s important to highlight the security risks associated with rendering MDX content.\n\nBecause MDX supports JavaScript expressions, it introduces serious security considerations. If the content is not fully trusted and controlled, it can enable **cross-site scripting (XSS)** attacks and even lead to **remote code execution (RCE)**. In the worst-case scenario, attackers could steal sensitive data, inject malicious scripts, install malware, or compromise your server.\n\n> **Never render user-supplied MDX without proper sanitization.**\n\nMDX provides three powerful constructs: **JSX syntax**, **JavaScript expressions**, and **ESM blocks (`mdxjsEsm`)** such as `import` and `export`. **`next-mdx-remote-client`** provides options to disable **ESM blocks (`mdxjsEsm`)**. However, it does **not** take responsibility for securing MDX content itself, as **it operates purely at the rendering layer**. Content sanitization and JS expression control should be handled earlier in the processing pipeline (e.g., at the remark/recma/compilation stage).\n\nIf you do not have full control over the MDX source, you should at minimum strip **dangerous JavaScript expressions** before rendering. A recommended approach is to use the remark plugin [**`remark-mdx-remove-expressions`**](https://github.com/ipikuka/remark-mdx-remove-expressions), which removes executable/dangerous MDX expressions at the syntax level.\n\nFor further security concerns you can visit [Security section](#security).\n\n## The package's exported subpaths\n\nThe main entry point **`/`** also refers to **`/csr`** subpath.\n\n```typescript\n// main entry point, which is related \"pages\" router\nimport /* */ from \"next-mdx-remote-client\";\n\n// isolated subpath for the \"serialize\" function\nimport /* */ from \"next-mdx-remote-client/serialize\";\n\n// sub entry point related with \"pages\" router\nimport /* */ from \"next-mdx-remote-client/csr\";\n\n// sub entry point related with \"app\" router\nimport /* */ from \"next-mdx-remote-client/rsc\";\n\n// isolated subpath for the utils\nimport /* */ from \"next-mdx-remote-client/utils\";\n```\n\n## The part associated with Next.js `app` router\n\n_Go to [the part associated with Next.js pages router](#the-part-associated-with-nextjs-pages-router)_\n\n**`next-mdx-remote-client`** exposes **`evaluate`** function and **`MDXRemote`** component for **\"app\" router**.\n\n```typescript\nimport { evaluate, MDXRemote } from \"next-mdx-remote-client/rsc\";\n```\n\n> [!TIP]\n> If you need to get the **exports** from MDX --> use **`evaluate`**\\\n> If you don't need --> use **`MDXRemote`**\\\n> \\\n> If you need to get the **frontmatter** and the **mutated scope** --> use **`evaluate`**\\\n> If you don't need --> use **`MDXRemote`**\n\nLet's give some examples how to use **`next-mdx-remote-client`** in \"app\" router first, then explain the exposed function and component.\n\n### Examples for `app` router\n\nSee a **demo application** with **`app` router**, visit [source code](https://github.com/talatkuyuk/next-mdx-remote-client-in-app-router) or [living web site](https://nmrc-in-app-router.vercel.app/).\n\n#### An example with `javascript`\n\n```jsx\nimport { Suspense } from \"react\";\nimport { MDXRemote } from \"next-mdx-remote-client/rsc\";\n\nimport { ErrorComponent, LoadingComponent } from \"../components\";\nimport { Test } from '../mdxComponents';\n\nconst components = {\n  Test,\n  wrapper: ({ children }) => <div className=\"mdx-wrapper\">{children}</div>,\n}\n\nexport default async function Page() {\n  const source = \"Some **bold text** in MDX, with a component <Test />\";\n\n  return (\n    <Suspense fallback={<LoadingComponent />}>\n      <MDXRemote\n        source={source}\n        components={components}\n        onError={ErrorComponent}\n      />\n    </Suspense>\n  );\n};\n```\n\n#### An example with `typescript`, parsing frontmatter and providing custom data with scope\n\n```tsx\nimport { Suspense } from \"react\";\nimport { MDXRemote } from \"next-mdx-remote-client/rsc\";\nimport type { MDXRemoteOptions, MDXComponents } from \"next-mdx-remote-client/rsc\";\n\nimport { calculateSomeHow, getSourceSomeHow } from \"../utils\";\nimport { ErrorComponent, LoadingComponent } from \"../components\";\nimport { Test } from '../mdxComponents';\n\nconst components: MDXComponents = { \n  Test,\n  wrapper: function ({ children }: React.ComponentPropsWithoutRef<\"div\">) {\n    return <div className=\"mdx-wrapper\">{children}</div>;\n  },\n}\n\nexport default async function Page() {\n  const source = await getSourceSomeHow();\n\n  if (!source) {\n    return <ErrorComponent error=\"The source could not found !\" />;\n  }\n\n  const options: MDXRemoteOptions = {\n    mdxOptions: {\n      // ...\n    },\n    parseFrontmatter: true,\n    scope: {\n      readingTime: calculateSomeHow(source),\n    },\n  };\n\n  return (\n    <Suspense fallback={<LoadingComponent />}>\n      <MDXRemote\n        source={source}\n        options={options}\n        components={components}\n        onError={ErrorComponent}\n      />\n    </Suspense>\n  );\n}\n```\n\n#### An example with creating a table of contents (TOC)\n\nI assume you have a MDX content having `<TableOfContentComponent />` inside; and you've provided it in MDX components.\n\n```markdown\n---\ntitle: My Article\n---\n# {frontmatter.title}\n\n<TableOfContentComponent toc={toc} />\n\nrest of the article...\n```\n\nYou can have a look at an example [TableOfContentComponent](https://github.com/talatkuyuk/next-mdx-remote-client-in-app-router/blob/main/mdxComponents/Toc.tsx) in the demo application.\n\nIn order to create a table of contents (TOC) I use **`remark-flexible-toc`** in the remark plugins and pass the table of contents objects `vFile.data.toc` into the `scope` via the option `vfileDataIntoScope`.\n\nThat's it! So easy!\n\n```tsx\nimport { Suspense } from \"react\";\nimport { MDXRemote, type MDXRemoteOptions } from \"next-mdx-remote-client/rsc\";\nimport remarkFlexibleToc from \"remark-flexible-toc\"; // <---------\n\nimport { calculateSomeHow, getSourceSomeHow } from \"../utils\";\nimport { ErrorComponent, LoadingComponent } from \"../components\";\nimport { components } from '../mdxComponents';\n\nexport default async function Page() {\n  const source = await getSourceSomeHow();\n\n  if (!source) {\n    return <ErrorComponent error=\"The source could not found !\" />;\n  }\n\n  const options: MDXRemoteOptions = {\n    mdxOptions: {\n      remarkPlugins: [\n        // ...\n        remarkFlexibleToc, // <---------\n      ], \n    },\n    parseFrontmatter: true,\n    scope: {\n      readingTime: calculateSomeHow(source),\n    },\n    vfileDataIntoScope: \"toc\", // <---------\n  };\n\n  return (\n    <Suspense fallback={<LoadingComponent />}>\n      <MDXRemote\n        source={source}\n        options={options}\n        components={components}\n        onError={ErrorComponent}\n      />\n    </Suspense>\n  );\n}\n```\n\n#### An example with using \"frontmatter\" and \"scope\" in JSX in \"app\" router\n\n```tsx\nimport { Suspense } from \"react\";\nimport { evaluate, type EvaluateOptions } from \"next-mdx-remote-client/rsc\";\nimport remarkFlexibleToc, { type TocItem } from \"remark-flexible-toc\";\n\nimport { calculateSomeHow, getSourceSomeHow } from \"../utils\";\nimport { ErrorComponent, LoadingComponent, TableOfContentComponent } from \"../components\";\nimport { components } from \"../mdxComponents\";\n\ntype Scope = {\n  readingTime: string;\n  toc?: TocItem[];\n};\n\ntype Frontmatter = {\n  title: string;\n  author: string;\n};\n\nexport default async function Page() {\n  const source = await getSourceSomeHow();\n\n  if (!source) {\n    return <ErrorComponent error=\"The source could not found !\" />;\n  }\n\n  const options: EvaluateOptions<Scope> = {\n    mdxOptions: {\n      remarkPlugins: [\n        // ...\n        remarkFlexibleToc,\n      ], \n    },\n    parseFrontmatter: true,\n    scope: {\n      readingTime: calculateSomeHow(source),\n    },\n    vfileDataIntoScope: \"toc\",\n  };\n\n  const { content, frontmatter, scope, error } = await evaluate<Frontmatter, Scope>({\n    source,\n    options,\n    components,\n  });\n\n  if (error) {\n    return <ErrorComponent error={error} />;\n  }\n\n  return (\n    <>\n      <h1>{frontmatter.title}</h1>\n      <p>Written by {frontmatter.author}; read in {scope.readingTime}</p>\n      <TableOfContentComponent toc={scope.toc} />\n      <Suspense fallback={<LoadingComponent />}>\n        {content}\n      </Suspense>\n    </>\n  );\n}\n```\n\nActually, you may not need to access the \"frontmatter\" and \"scope\" in JSX, you can use them within MDX directly, and return just `content` only.\n\n```tsx\n// ...\nexport default async function Page({ source }: Props) {\n  // ...\n  return (\n    <Suspense fallback={<LoadingComponent />}>\n      {content}\n    </Suspense>\n  );\n}\n```\n\n_article.mdx_\n```markdown\n# {frontmatter.title}\n\nWritten by {frontmatter.author}; read in {readingTime}\n\n<TableOfContentComponent toc={toc} />\n\nrest of the article...\n```\n\nAfter the examples given, let's dive into the exposed function and component by **`next-mdx-remote-client`** for \"app\" router.\n\n### The `evaluate` function\n\n_Go to the [MDXRemote](#the-mdxremote-component) component_\n\nThe `evaluate` function is used for **compiling** MDX source, **constructing compiled source**, getting exported information from MDX and returning MDX content to be rendered on the server side, as a react server component.\n\n```typescript\nasync function evaluate(props: EvaluateProps): Promise<EvaluateResult> {}\n```\n\nThe `evaluate` function takes `EvaluateProps` and returns `EvaluateResult` as a promise.\n\n**Props of the `evaluate` function**\n\n```typescript\ntype EvaluateProps<TScope> = {\n  source: Compatible;\n  options?: EvaluateOptions<TScope>;\n  components?: MDXComponents;\n};\n```\n\n**Result of the `evaluate` function**\n\n```typescript\ntype EvaluateResult<TFrontmatter, TScope> = {\n  content: React.JSX.Element;\n  mod: Record<string, unknown>;\n  frontmatter: TFrontmatter;\n  scope: TScope;\n  error?: Error;\n};\n```\n\nThe `evaluate` has **internal error handling mechanism** as much as it can, in order to do so, it returns an **`error`** object if it is catched.\n\n> [!CAUTION]\n> The eval of the compiled source returns a module `MDXModule`, and does not throw errors except syntax errors. Some errors throw during the render process which needs you to use an **ErrorBoundary**.\n\n```tsx\nimport { Suspense } from \"react\";\nimport { evaluate, type EvaluateOptions } from \"next-mdx-remote-client/rsc\";\n\nimport { ErrorComponent, LoadingComponent, TableOfContentComponent } from \"../components\";\nimport { components } from \"../mdxComponents\";\nimport type { Frontmatter, Scope } from \"../types\"\n\nexport default async function MDXComponent({ source }: {source?: string}) {\n  if (!source) {\n    return <ErrorComponent error=\"The source could not found !\" />;\n  }\n\n  const options: EvaluateOptions = {\n    /* */\n  };\n\n  const { content, mod, frontmatter, scope, error } = await evaluate<Frontmatter, Scope>({\n    source,\n    options,\n    components,\n  });\n\n  if (error) {\n    return <ErrorComponent error={error} />;\n  }\n\n  /**\n   * Use \"mod\", \"frontmatter\" and \"scope\" as you wish\n   *\n   * \"mod\" object is for exported information from MDX\n   * \"frontmatter\" is available even if a MDX syntax error occurs\n   * \"scope\" is for mutated scope if the `vfileDataIntoScope` option is used\n   */\n\n  return (\n    <>\n      <h1>{frontmatter.title}</h1>\n      <div><em>{mod.something}</em></div>\n      <TableOfContentComponent toc={scope.toc} />\n      <Suspense fallback={<LoadingComponent />}>\n        {content}\n      </Suspense>\n    </>\n  );\n};\n```\n\nIf you provide **the generic type parameters** like `await evaluate<Frontmatter, Scope>(){}`, the `frontmatter` and the `scope` get the types, otherwise `Record<string, unknown>` by default for both.\n\n> [!WARNING]\n> Pay attention to the order of the generic type parameters.\\\n> \\\n> The type parameters `Frontmatter` and `Scope` should extend `Record<string, unknown>`. You should use **`type`** instead of **`interface`** for type parameters otherwise, you will receive an error saying `Type 'Xxxx' does not satisfy the constraint 'Record<string, unknown>'.` See this [issue](https://github.com/ipikuka/next-mdx-remote-client/issues/2) for more explanation.\n\nIn the above example, I assume you use **`remark-flexible-toc`** remark plugin in order to collect the headings from MDX content, and you pass that information into the `scope` via `vfileDataIntoScope` option.\n\n### The evaluate options (`EvaluateOptions`)\n\nAll options are optional.\n\n```typescript\ntype EvaluateOptions<TScope> = {\n  mdxOptions?: EvaluateMdxOptions;\n  disableExports?: boolean;\n  disableImports?: boolean;\n  parseFrontmatter?: boolean;\n  scope?: TScope;\n  vfileDataIntoScope?: VfileDataIntoScope;\n};\n```\n\n#### `mdxOptions`\n\nIt is an **`EvaluateMdxOptions`** option to be passed to **`@mdx-js/mdx`** compiler.\n\n```typescript\nimport { type EvaluateOptions as OriginalEvaluateOptions } from \"@mdx-js/mdx\";\n\ntype EvaluateMdxOptions = Omit<\n  OriginalEvaluateOptions,\n  | \"Fragment\"\n  | \"jsx\"\n  | \"jsxs\"\n  | \"jsxDEV\"\n  | \"useMDXComponents\"\n  | \"providerImportSource\"\n  | \"outputFormat\"\n>;\n```\n\nAs you see, some of the options are omitted and opinionated within the package. For example the `outputFormat` is always `function-body` by default. Visit https://mdxjs.com/packages/mdx/#evaluateoptions for available mdxOptions.\n\n```typescript\nconst options: EvaluateOptions = {\n  // ...\n  mdxOptions: {\n    format: \"mdx\",\n    baseUrl: import.meta.url,\n    development: true,\n    remarkPlugins: [/* */],\n    rehypePlugins: [/* */],\n    recmaPlugins: [/* */],\n    remarkRehypeOptions: {handlers: {/* */}},\n    // ...\n  };\n};\n```\n\nFor more information see [the MDX documentation](https://github.com/mdx-js/mdx/blob/master/packages/mdx/index.js).\n\n#### `disableExports`\n\nIt is a **boolean** option whether or not stripping the `export statements` out from the MDX source.\n\nBy default it is **false**, meaningly the `export statements` work as expected.\n\n```typescript\nconst options: EvaluateOptions = {\n  disableExports: true;\n};\n```\n\nNow, the `export statements` will be stripped out from the MDX.\n\n#### `disableImports`\n\nIt is a **boolean** option whether or not stripping the `import statements` out from the MDX source.\n\nBy default it is **false**, meaningly the `import statements` work as expected.\n\n```typescript\nconst options: EvaluateOptions = {\n  disableImports: true;\n};\n```\n\nNow, the `import statements` will be stripped out from the MDX.\n\n#### `parseFrontmatter`\n\nIt is a **boolean** option whether or not the frontmatter should be parsed out of the MDX.\n\nBy default it is **false**, meaningly the `frontmatter` will not be parsed and extracted.\n\n```typescript\nconst options: EvaluateOptions = {\n  parseFrontmatter: true;\n};\n```\n\nNow, the `frontmatter` part of the MDX file is parsed and extracted from the MDX source; and will be supplied into the MDX file so as you to use it within the javascript statements.\n\n> [!NOTE]\n> Frontmatter is a way to identify metadata in Markdown files. Metadata can literally be anything you want it to be, but often it's used for data elements your page needs and you don't want to show directly.\n\n```mdx\n---\ntitle: \"My Article\"\nauthor: \"ipikuka\"\n---\n# {frontmatter.title}\n\nIt is written by {frontmatter.author}\n```\n\nThe package uses the `vfile-matter` internally to parse the frontmatter.\n\n#### `scope`\n\nIt is an **`Record<string, unknown>`** option which is an arbitrary object of data which will be supplied to the MDX. For example, in cases where you want to provide template variables to the MDX, like `my name is {name}`, you could provide scope as `{ name: \"ipikuka\" }`. \n\nHere is another example:\n\n```typescript\nconst options: EvaluateOptions = {\n  scope: {\n    readingTime: calculateSomeHow(source)\n  };\n};\n```\n\nNow, the `scope` will be supplied into the MDX file so as you to use it within the statements.\n\n```markdown\n# My article\n\nread in {readingTime} min.\n```\n\nThe variables within the expression in the MDX content should be valid javascript variable names. **Therefore, each key of the scope must be a valid variable name.**\n\n```markdown\nMy name is {name} valid expression.\nMy name is {my-name} is not valid expression, which will throw error\n```\n\nSo, we can say for the `scope`, here:\n```typescript\nconst options: EvaluateOptions = {\n  scope: {\n    name: \"ipikuka\", // valid usage\n    \"my-name\": \"ipikuka\", // is not valid and error prone for the MDX content !!!\n  };\n};\n```\n\n> [!TIP]\n> The scope variables can be consumed not only as a property of a component, but also within the texts.\n\n```mdx\nmy name is {name}\n\n<BarComponent name={name} />\n```\n\n#### `vfileDataIntoScope`\n\nIt is an **union** type option. It is for passing some fields of `vfile.data` into the `scope` by mutating the `scope`.\n\n> [!IMPORTANT]  \n> It provides referencial copy for objects and arrays. If the `scope` has the same key already, `vfile.data` overrides it.\n\nThe reason behind of this option is that `vfile.data` may hold some extra information added by some remark plugins. Some fields of the `vfile.data` may be needed to pass into the `scope` so as you to use in the MDX.\n\n```typescript\ntype VfileDataIntoScope =\n  | true // all fields from vfile.data\n  | string // one specific field\n  | { name: string; as: string } // one specific field but change the key as\n  | Array<string | { name: string; as: string }>; // more than one field\n```\n\n```typescript\nconst options: EvaluateOptions = {\n  // Let's assume you use \"remark-flexible-toc\" plugin which composes\n  // the table of content (TOC) within the 'vfile.data.toc'\n  vfileDataIntoScope: \"toc\"; // or fileDataIntoScope: [\"toc\"];\n};\n```\n\nNow, `vfile.data.toc` is copied into the scope as `scope[\"toc\"]`, and will be supplied to the MDX via `scope`.\n\n```mdx\n# My article\n\n<TableOfContentComponent toc={toc} />\n```\n\nIf you need to change the name of the field, specify it for example `{ name: \"toc\", as: \"headings\" }`.\n\n```typescript\nconst options: EvaluateOptions = {\n  vfileDataIntoScope: { name: \"toc\", as: \"headings\" };\n};\n```\n\n```mdx\n# My article\n\n<TableOfContentComponent headings={headings} />\n```\n\nIf you need to pass all the fields from `vfile.data`, specify it as `true`\n\n```typescript\nconst options: EvaluateOptions = {\n  vfileDataIntoScope: true;\n};\n```\n\n### The `MDXRemote` component\n\n_Go to the [evaluate](#the-evaluate-function) function_\n\nThe `MDXRemote` component is used for rendering the MDX content on the server side. It is a react server component.\n\n```typescript\nasync function MDXRemote(props: MDXRemoteProps): Promise<React.JSX.Element> {}\n```\n\nThe `MDXRemote` component takes `MDXRemoteProps` and returns `React.JSX.Element` as a promise.\n\n**Props of the `MDXRemote` component**\n\n```typescript\ntype MDXRemoteProps<TScope> = {\n  source: Compatible;\n  options?: MDXRemoteOptions<TScope>;\n  components?: MDXComponents;\n  onError?: React.ComponentType<{ error: Error }>\n};\n```\n\nThe `MDXRemote` has **internal error handling mechanism** as much as it can, in order to do so, it takes **`onError`** prop in addition to `evaluate` function.\n\n> [!CAUTION]\n> The eval of the compiled source returns a module `MDXModule`, and does not throw errors except syntax errors. Some errors throw during the render process which needs you to use an **ErrorBoundary**.\n\n```tsx\nimport { Suspense } from \"react\";\nimport { MDXRemote, type MDXRemoteOptions } from \"next-mdx-remote-client/rsc\";\n\nimport { ErrorComponent, LoadingComponent } from \"../components\";\nimport { components } from \"../mdxComponents\";\n\nexport default async function MDXComponent({ source }: {source?: string}) {\n  if (!source) {\n    return <ErrorComponent error=\"The source could not found !\" />;\n  }\n\n  const options: MDXRemoteOptions = {\n    /* */\n  };\n\n  return (\n    <Suspense fallback={<LoadingComponent />}>\n      <MDXRemote\n        source={source}\n        options={options}\n        components={components}\n        onError={ErrorComponent}\n      />\n    </Suspense>\n  );\n};\n```\n\n### The MDXRemote options (`MDXRemoteOptions`)\n\nAll options are optional.\n\n```typescript\ntype MDXRemoteOptions<TScope> = {\n  mdxOptions?: EvaluateMdxOptions;\n  disableExports?: boolean;\n  disableImports?: boolean;\n  parseFrontmatter?: boolean;\n  scope?: TScope;\n  vfileDataIntoScope?: VfileDataIntoScope;\n};\n```\n\nThe details are the same with the [EvaluateOptions](#the-evaluate-options-evaluateoptions).\n\n## The part associated with Next.js `pages` router\n\n_Go to [the part associated with Next.js app router](#the-part-associated-with-nextjs-app-router)_\n\n**`next-mdx-remote-client`** exposes **`serialize`**, **`hydrate`** functions and **`MDXClient`** component for **\"pages\" router**.\n\nThe `serialize` function is used on the server side in \"pages\" router, while as the `hydrate` and the `MDXClient` are used on the client side in \"pages\" router. That is why the \"serialize\" function is purposefully isolated considering it is intended to run on the server side.\n\nLet's give some examples how to use **`next-mdx-remote-client`** in \"pages\" router first, then explain the exposed functions and component.\n\n### Examples for `pages` router\n\nSee a **demo application** with **`pages` router**,  visit [source code](https://github.com/talatkuyuk/next-mdx-remote-client-in-pages-router) or [living web site](https://nmrc-in-pages-router.vercel.app/).\n\n#### An example with `javascript`\n\n```jsx\nimport { serialize } from 'next-mdx-remote-client/serialize';\nimport { MDXClient } from 'next-mdx-remote-client';\n\nimport ErrorComponent from '../components/ErrorComponent';\nimport Test from '../mdxComponents/Test';\n\nconst components = { \n  Test,\n  wrapper: ({children}) => <div className=\"mdx-wrapper\">{children}</div>,\n}\n\nexport default function Page({ mdxSource }) {\n  if (\"error\" in mdxSource) {\n    return <ErrorComponent error={mdxSource.error} />;\n  }\n\n  return <MDXClient {...mdxSource} components={components} />;\n}\n\nexport async function getStaticProps() {\n  const source = \"Some **bold text** in MDX, with a component <Test />\";\n\n  const mdxSource = await serialize({source});\n\n  return { props: { mdxSource } };\n}\n```\n\n#### An example with `typescript`, parsing frontmatter and providing custom data with scope\n\n```tsx\nimport { MDXClient, type MDXComponents } from 'next-mdx-remote-client';\nimport { serialize } from \"next-mdx-remote-client/serialize\";\nimport type { SerializeOptions, SerializeResult } from \"next-mdx-remote-client/serialize\";\n\nimport { calculateSomeHow, getSourceSomeHow } from \"../utils\";\nimport ErrorComponent from '../components/ErrorComponent';\nimport Test from '../mdxComponents/Test';\n\ntype Scope = {\n  readingTime: string;\n};\n\ntype Frontmatter = {\n  title: string;\n  author: string;\n};\n\nconst components: MDXComponents = { \n  Test,\n  wrapper: function ({ children }: React.ComponentPropsWithoutRef<\"div\">) {\n    return <div className=\"mdx-wrapper\">{children}</div>;\n  },\n}\n\ntype Props = {\n  mdxSource?: SerializeResult<Frontmatter, Scope>;\n}\n\nexport default function Page({ mdxSource }: Props) {\n  if (!mdxSource) {\n    return <ErrorComponent error=\"The source could not found !\" />;\n  }\n\n  if (\"error\" in mdxSource) {\n    return <ErrorComponent error={mdxSource.error} />;\n  }\n\n  return (\n    <>\n      <h1>{mdxSource.frontmatter.title}</h1>\n      <p>Written by {mdxSource.frontmatter.author}; read in {mdxSource.scope.readingTime}</p>\n      <MDXClient {...mdxSource} components={components} />\n    </>\n  );\n}\n\nexport async function getStaticProps() {\n  const source = await getSourceSomeHow();\n\n  if (!source) return { props: {} };\n\n  const options: SerializeOptions<Scope> = {\n    disableImports: true,\n    mdxOptions: {\n      // ...\n    },\n    parseFrontmatter: true,\n    scope: {\n      readingTime: calculateSomeHow(source),\n    },\n  };\n\n  const mdxSource = await serialize<Frontmatter, Scope>({source, options});\n\n  return { props: { mdxSource } };\n}\n```\n\n#### An example with creating a table of contents (TOC)\n\nI assume you have a MDX content having `<TableOfContentComponent />` inside; and you've provided it in MDX components.\n\n```markdown\n---\ntitle: My Article\n---\n# {frontmatter.title}\n\n<TableOfContentComponent toc={toc} />\n\nrest of the article...\n```\n\nYou can have a look at an example [TableOfContentComponent](https://github.com/talatkuyuk/next-mdx-remote-client-in-pages-router/blob/main/mdxComponents/Toc.tsx) in the demo application.\n\nIn order to create a table of contents (TOC) I use **`remark-flexible-toc`** in the remark plugins and pass the table of contents objects `vFile.data.toc` into the `scope` via the option `vfileDataIntoScope`.\n\nThat's it! So easy!\n\n```tsx\nimport { MDXClient, type MDXComponents } from 'next-mdx-remote-client';\nimport { serialize } from \"next-mdx-remote-client/serialize\";\nimport type { SerializeOptions, SerializeResult } from \"next-mdx-remote-client/serialize\";\nimport remarkFlexibleToc, {type TocItem} from \"remark-flexible-toc\"; // <---------\n\nimport { calculateSomeHow, getSourceSomeHow } from \"../utils\";\nimport { ErrorComponent, TableOfContentComponent } from '../components';\nimport { Test } from '../mdxComponents';\n\ntype Scope = {\n  readingTime: string;\n};\n\ntype Frontmatter = {\n  title: string;\n  author: string;\n};\n\nconst components: MDXComponents = { \n  Test,\n  wrapper: function ({ children }: React.ComponentPropsWithoutRef<\"div\">) {\n    return <div className=\"mdx-wrapper\">{children}</div>;\n  },\n}\n\ntype Props = {\n  mdxSource?: SerializeResult<Frontmatter, Scope & {toc: TocItem[]}>;\n}\n\nexport default function Page({ mdxSource }: Props) {\n  if (!mdxSource) {\n    return <ErrorComponent error=\"The source could not found !\" />;\n  }\n\n  if (\"error\" in mdxSource) {\n    return <ErrorComponent error={mdxSource.error} />;\n  }\n\n  return (\n    <>\n      <h1>{mdxSource.frontmatter.title}</h1>\n      <p>Written by {mdxSource.frontmatter.author}; read in {mdxSource.scope.readingTime}</p>\n      <TableOfContentComponent toc={mdxSource.scope.toc /* <----- here added TOC */} />\n      <MDXClient {...mdxSource} components={components} />\n    </>\n  );\n}\n\nexport async function getStaticProps() {\n  const source = await getSourceSomeHow();\n\n  if (!source) return { props: {} };\n\n  const options: SerializeOptions<Scope> = {\n    disableImports: true,\n    mdxOptions: {\n      remarkPlugins: [\n        // ...\n        remarkFlexibleToc, // <---------\n      ], \n    },\n    parseFrontmatter: true,\n    scope: {\n      readingTime: calculateSomeHow(source),\n    },\n    vfileDataIntoScope: \"toc\", // <---------\n  };\n\n  const mdxSource = await serialize<Frontmatter, Scope>({source, options});\n\n  return { props: { mdxSource } };\n}\n```\n\nActually, you may not need to access the \"frontmatter\" and \"scope\" in JSX, you can use them within MDX directly, and return just `<MDXClient />` only.\n\n```tsx\n// ...\nconst components: MDXComponents = { \n  TableOfContentComponent, // <---------\n  wrapper: function ({ children }: React.ComponentPropsWithoutRef<\"div\">) {\n    return <div className=\"mdx-wrapper\">{children}</div>;\n  },\n}\n// ...\nexport default function Page({ mdxSource }: Props) {\n  // ...\n  return (\n    <MDXClient {...mdxSource} components={components} />\n  );\n}\n```\n\n_article.mdx_\n```markdown\n# {frontmatter.title}\n\nWritten by {frontmatter.author}; read in {readingTime}\n\n<TableOfContentComponent toc={toc} />\n\nrest of the article...\n```\n\nAfter the examples given, let's dive into the exposed functions and component by **`next-mdx-remote-client`** for \"pages\" router.\n\n### The `serialize` function\n\n_Go to the [hydrate](#the-hydrate-function) function_\n_or the [MDXClient](#the-mdxclient-component) component_\n\n```typescript\nimport { serialize } from \"next-mdx-remote-client/serialize\";\n```\n\nThe `serialize` function is used for **compiling** MDX source, in other words **constructing compiled source** from MDX source, intended to run on server side at build time.\n\n> [!WARNING]\n> The `serialize` function is **asyncronous** and to be used within the `getStaticProps` or the `getServerSideProps` on the server side. (Off the record, it can be used within an `useEffect` as well, but this is not recommended because it is a heavy function as having more dependencies).\n\n```typescript\nasync function serialize(props: SerializeProps): Promise<SerializeResult> {}\n```\n\nThe `serialize` function takes `SerializeProps` and returns `SerializeResult` as a promise.\n\n**Props of the `serialize` function**\n\n```typescript\ntype SerializeProps<TScope> = {\n  source: Compatible;\n  options?: SerializeOptions<TScope>;\n};\n```\n\n**Result of the `serialize` function**\n\nEither the `compiledSource` or the `error` exists, in addition to `frontmatter` and `scope`.\n\n```typescript\ntype SerializeResult<TFrontmatter, TScope> = \n({ compiledSource: string } | { error: Error })\n& {\n  frontmatter: TFrontmatter;\n  scope: TScope;\n};\n```\n\nThe `serialize` function has **internal error handling mechanism** for the MDX syntax errors. The catched error is serialized via **`serialize-error`** and attached into the serialize results, further you can deserialize the error on the client, if necessary. **You don't need to implement error handling by yourself.**\n\n```tsx\nimport { serialize, type SerializeOptions } from \"next-mdx-remote-client/serialize\";\nimport type { Frontmatter, Scope } from \"./types\"\n\nexport async function getStaticProps() {\n  const source = await getSourceSomeHow();\n\n  if (!source) {\n    return { props: {} };\n  }\n\n  const options: SerializeOptions = {\n    /* */\n  };\n\n  const mdxSource = await serialize<Frontmatter, Scope>({\n    source,\n    options,\n  });\n\n  return {\n    props: {\n      mdxSource,\n    },\n  };\n}\n```\n\nIf you provide **the generic type parameters** like `await serialize<Frontmatter, Scope>(){}`, the `frontmatter` and the `scope` get the types, otherwise `Record<string, unknown>` by default for both.\n\n> [!WARNING]\n> Pay attention to the order of the generic type parameters.\\\n> \\\n> The type parameters `Frontmatter` and `Scope` should extend `Record<string, unknown>`. You should use **`type`** instead of **`interface`** for type parameters otherwise, you will receive an error saying `Type 'Xxxx' does not satisfy the constraint 'Record<string, unknown>'.` See this [issue](https://github.com/ipikuka/next-mdx-remote-client/issues/2) for more explanation.\n\nThe `nextjs` will send the `mdxSource` ((**`compiledSource`** or **`error`**) + **`frontmatter`** + **`scope`**) to client side.\n\n**On client side, you need first to narrow the `mdxSource` by checking `if (\"error\" in mdxSource) {}`.**\n\n```tsx\ntype Props = {\n  mdxSource?: SerializeResult<Frontmatter, Scope>;\n}\n\nexport default function Page({ mdxSource }: Props) {\n  // ...\n\n  if (\"error\" in mdxSource) {\n    return <ErrorComponent error={mdxSource.error} />;\n  }\n\n  // ...\n};\n```\n\n### The serialize options (`SerializeOptions`)\n\nAll options are optional.\n\n```typescript\ntype SerializeOptions<TScope> = {\n  mdxOptions?: SerializeMdxOptions;\n  disableExports?: boolean;\n  disableImports?: boolean;\n  parseFrontmatter?: boolean;\n  scope?: TScope;\n  vfileDataIntoScope?: VfileDataIntoScope;\n};\n```\n\nExcept the `mdxOptions`, the details are the same with the [EvaluateOptions](#the-evaluate-options-evaluateoptions).\n\n#### `mdxOptions`\n\nIt is a **`SerializeMdxOptions`** option to be passed to **`@mdx-js/mdx`** compiler.\n\n```typescript\nimport { type CompileOptions as OriginalCompileOptions } from \"@mdx-js/mdx\";\n\ntype SerializeMdxOptions = Omit<\n  OriginalCompileOptions,\n  \"outputFormat\" | \"providerImportSource\"\n>;\n```\n\nAs you see, some of the options are omitted and opinionated within the package. For example the `outputFormat` is always `function-body` by default. Visit https://mdxjs.com/packages/mdx/#compileoptions for available mdxOptions.\n\n```typescript\nconst options: SerializeOptions = {\n  // ...\n  mdxOptions: {\n    format: \"mdx\",\n    baseUrl: import.meta.url,\n    development: true,\n    remarkPlugins: [/* */],\n    rehypePlugins: [/* */],\n    recmaPlugins: [/* */],\n    remarkRehypeOptions: {handlers: {/* */}},\n    // ...\n  };\n};\n```\n\n> [!WARNING]\n> Here I need to mention about the `scope` option again for the `serialize`.\\\n> \\\n> **scope**\\\n> \\\n> Actually, the `serialize` doesn't do so much with the `scope` except you provide the option `vfileDataIntoScope` for passing data from `vfile.data` into the `scope`. Since the `scope` is passed from the server to the client by `nextjs`, the `scope` must be serializable. The `scope` can not hold **function**, **component** , **Date**, **undefined**, **Error object** etc.\\\n> \\\n> If the scope has to have **unserializable** information or if you don't need or don't want to pass the `scope` into the `serialize`, you can pass it into `hydrate` or `MDXClient` directly on the client side.\n\n### The `hydrate` function\n\n_Go to the [serialize](#the-serialize-function) function_\n_or the [MDXClient](#the-mdxclient-component) component_\n\n```typescript\nimport { hydrate } from \"next-mdx-remote-client/csr\";\n```\n\nThe `hydrate` function is used for **constructing compiled source**, getting exported information from MDX and returning MDX content to be rendered on the client side.\n\n```typescript\nfunction hydrate(props: HydrateProps): HydrateResult {}\n```\n\nThe `hydrate` function takes `HydrateProps` and returns `HydrateResult`. The `hydrate` has no \"options\" parameter.\n\n**Props of the `hydrate` function**\n\n```typescript\ntype HydrateProps = {\n  compiledSource: string;\n  frontmatter?: Record<string, unknown>;\n  scope?: Record<string, unknown>;\n  components?: MDXComponents;\n  disableParentContext?: boolean;\n};\n```\n\nThe option `disableParentContext` is a feature of **`@mdx-js/mdx`**. If it is `false`, the mdx components provided by parent `MDXProvider`s are going to be disregarded.\n\n**Result of the `hydrate` function**\n\n```typescript\ntype HydrateResult = {\n  content: React.JSX.Element;\n  mod: Record<string, unknown>;\n  error?: Error;\n};\n```\n\nThe **`mod`** object is for exported information from MDX source.\n\n> [!TIP]\n> If you need to get the **exports** from MDX --> use **`hydrate`**\\\n> If you don't need --> use **`MDXClient`**\n\nThe `hydrate` has **internal error handling mechanism** as much as it can, in order to do so, it returns an **`error`** object if it is catched.\n\n> [!CAUTION]\n> The eval of the compiled source returns a module `MDXModule`, and does not throw errors except syntax errors. Some errors throw during the render process which needs you to use an **ErrorBoundary**.\n\n```tsx\nimport { hydrate, type SerializeResult } from \"next-mdx-remote-client/csr\";\n\nimport { ErrorComponent, TableOfContentComponent } from \"../components\";\nimport { components } from \"../mdxComponents\";\nimport type { Frontmatter, Scope } from \"../types\"\n\ntype Props = {\n  mdxSource?: SerializeResult<Frontmatter, Scope>;\n}\n\nexport default function Page({ mdxSource }: Props) {\n  if (!mdxSource) {\n    return <ErrorComponent error=\"The source could not found !\" />;\n  }\n\n  if (\"error\" in mdxSource) {\n    return <ErrorComponent error={mdxSource.error} />;\n  }\n\n  // Now, mdxSource has {compiledSource, frontmatter, scope}\n\n  const { content, mod, error } = hydrate({ ...mdxSource, components });\n\n  if (error) {\n    return <ErrorComponent error={error} />;\n  }\n\n  // You can use the \"mod\" object for exported information from the MDX as you wish\n\n  return (\n    <>\n      <h1>{mdxSource.frontmatter.title}</h1>\n      <div><em>{mod.something}</em></div>\n      <TableOfContentComponent toc={mdxSource.scope.toc} />\n      {content}\n    </>\n  );\n};\n```\n\nIn the above example, I assume you use **`remark-flexible-toc`** remark plugin in order to collect the headings from MDX content, and you pass that information into the `scope` via `vfileDataIntoScope` option within the serialize on the server side.\n\n### The `MDXClient` component\n\n_Go to the [serialize](#the-serialize-function) function_\n_or the [hydrate](#the-hydrate-function) function_\n\n```typescript\nimport { MDXClient } from \"next-mdx-remote-client/csr\";\n```\n\nThe `MDXClient` component is used for rendering the MDX content on the client side.\n\n```typescript\nfunction MDXClient(props: MDXClientProps): React.JSX.Element {}\n```\n\nThe `MDXClient` component takes `MDXClientProps` and returns `React.JSX.Element`. The `MDXClient` has no \"options\" parameter like `hydrate`.\n\n**Props of the `MDXClient` component**\n\n```typescript\ntype MDXClientProps = {\n  compiledSource: string;\n  frontmatter?: Record<string, unknown>;\n  scope?: Record<string, unknown>;\n  components?: MDXComponents;\n  disableParentContext?: boolean;\n  onError?: React.ComponentType<{ error: Error }>\n};\n```\n\nThe option `disableParentContext` is a feature of **`@mdx-js/mdx`**. If it is `false`, the mdx components provided by parent `MDXProvider`s are going to be disregarded.\n\n> [!TIP]\n> If you need to get the **exports** from MDX --> use **`hydrate`**\\\n> If you don't need --> use **`MDXClient`**\n\nThe `MDXClient` has **internal error handling mechanism** as much as it can, in order to do so, it takes **`onError`** prop in addition to `hydrate` function.\n\n> [!CAUTION]\n> The eval of the compiled source returns a module `MDXModule`, and does not throw errors except syntax errors. Some errors throw during the render process which needs you to use an **ErrorBoundary**.\n\n```tsx\nimport { MDXClient, type SerializeResult } from \"next-mdx-remote-client/csr\";\n\nimport { ErrorComponent, TableOfContentComponent } from \"../components\";\nimport { components } from \"../mdxComponents\";\nimport type { Frontmatter, Scope } from \"../types\"\n\ntype Props = {\n  mdxSource?: SerializeResult<Frontmatter, Scope>;\n}\n\nexport default function Page({ mdxSource }: Props) {\n  if (!mdxSource) {\n    return <ErrorComponent error=\"The source could not found !\" />;\n  }\n\n  if (\"error\" in mdxSource) {\n    return <ErrorComponent error={mdxSource.error} />;\n  }\n\n  // Now, mdxSource has {compiledSource, frontmatter, scope}\n\n  return (\n    <>\n      <h1>{mdxSource.frontmatter.title}</h1>\n      <TableOfContentComponent toc={mdxSource.scope.toc} />\n      <MDXClient\n        {...mdxSource}\n        components={components}\n        onError={ErrorComponent}\n      />\n    </>\n  );\n};\n```\n\nIn the above example, I assume you use **`remark-flexible-toc`** remark plugin in order to collect the headings from MDX content, and you pass that information into the `scope` via `vfileDataIntoScope` option within the serialize on the server side.\n\n### The `hydrateLazy` function and the `MDXClientLazy` component\n\n**`next-mdx-remote-client`** exports additional versions, say, the `hydrateLazy` and the `MDXClientLazy`, which both **have the same _functionality_, _props_, _results_** with the `hydrate` and the `MDXClient`, correspondently.\n\n**The only difference is the hydration process takes place lazily** on the browser within a `window.requestIdleCallback` in a useEffect. You can use `hydrateLazy` or `MDXClientLazy` in order to defer hydration of the content and immediately serve the static markup.\n\n```typescript\nimport { hydrateLazy, MDXClientLazy } from \"next-mdx-remote-client/csr\";\n```\n\nWhen you use `hydrateLazy`, and want to get the exports from MDX via `mod` object, please be aware that the `mod` object is always empty `{}` at first render, then it will get actual exports at second render.\n\n> [!NOTE]\n> Lazy hydration defers hydration of the components on the client. This is an optimization technique to improve the initial load of the application, but may introduce unexpected delays in interactivity for any dynamic content within the MDX content.\\\n> \\\n> This will add an additional wrapping div around the rendered MDX, which is necessary to avoid hydration mismatches during render.\\\n> \\\n> _For further explanation about the lazy hydration see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote) notes._\n\n### The `hydrateAsync` function and the `MDXClientAsync` component\n\n**`next-mdx-remote-client`** exports additional versions, say, the `hydrateAsync` and the `MDXClientAsync`.\n\nThese have additional props and options, but here, I don't want to give the details since **I created them for experimental** to show the `import statements` on the client side don't work. You can have a look at the github repository for the code and the tests.\n\n**The main difference is that the eval of the compiled source takes place in a useEffect** on the browser, since the compile source has `await` keyword for `import statements`.\n\n```typescript\nimport { hydrateAsync, MDXClientAsync } from \"next-mdx-remote-client/csr\";\n```\n\n> [!NOTE]  \n> I believe, it is viable somehow using `dynamic` API if the `vercel` supports for a solution for the `pages` router via `import.meta` APIs. During the compilation of the MDX in the `serialize`, a remark/recma plugin can register the imported modules into the `import.meta.url` via a nextjs API (needs support of vercel) for them will be available to download/import on the client side via `dynamic` api. This is my imagination.\n\n### The `MDXProvider` component\n\nThe package exports the `MDXProvider` from **`@mdx-js/react`**, in order the developers don't need to install **`@mdx-js/react`**.\n\n```typescript\nimport { MDXProvider } from \"next-mdx-remote-client/csr\";\n```\n\nThe `<MDXProvider />` makes the mdx components available to any `<MDXClient />` or `hydrate's { content }`  being rendered in the application, as a child status of that provider. \n\nFor example, you can wrap the whole application so as **you do not need to supply the mdx components into any `<MDXClient />` or `hydrate's { content }`.**\n\n```tsx\nimport { MDXProvider } from 'next-mdx-remote-client';\n\nimport { components } from \"../mdxComponents\"; \n\nexport default function App({ Component, pageProps }) {\n  return (\n    <MDXProvider components={components}>\n      <Component {...pageProps} />\n    </MDXProvider>\n  )\n}\n```\n\n> [!NOTE]\n> How this happens, because **`next-mdx-remote-client`** injects the `useMdxComponents` context hook from **`@mdx-js/react`** during the function construction of the compiled source, internally. Pay attention that it is valid for only `MDXClient` and `hydrate` functions.\n\n> [!CAUTION]\n> Since `MDXRemote` as a react server component can not read the context, **`MDXProvider` is effectless when used within the nextjs `app` router** for `MDXRemote`, which is also for `evaluate`.\n\n## MDX Components\n\nYou can provide a map of custom MDX components, which is a feature of **`@mdx-js/mdx`**, in order to replace HTML tags (see [the list of markdown syntax and equivalent HTML tags](https://mdxjs.com/table-of-components)) with the custom components.\n\nTypescript users can use `MDXComponents` from `mdx/types`, which is exported by this package as well.\n\n`../mdxComponents/index.ts`\n```tsx\nimport { type MDXComponents } from \"next-mdx-remote-client\";\n\nimport dynamic from \"next/dynamic\";\nimport Image from \"next/image\";\nimport Link from \"next/link\";\n\nimport { Typography } from \"@material-ui/core\";\nimport { motion } from 'framer-motion'\n\nimport Hello from \"./Hello\";\nimport CountButton from \"./CountButton\";\nimport BlockQuote, { default as blockquote } from \"./BlockQuote\";\nimport pre from \"./pre\";\n\nexport const mdxComponents: MDXComponents = {\n  Hello,\n  CountButton,\n  Dynamic: dynamic(() => import(\"./dynamic\")),\n  Image,\n  Link,\n  motion: { div: () => <div>Hello world</div> },\n  h2: (props: React.ComponentPropsWithoutRef<\"h2\">) => (\n    <Typography variant=\"h2\" {...props} />\n  ),\n  strong: (props: React.ComponentPropsWithoutRef<\"strong\">) => (\n    <strong className=\"custom-strong\" {...props} />\n  ),\n  em: (props: React.ComponentPropsWithoutRef<\"em\">) => (\n    <em className=\"custom-em\" {...props} />\n  ),\n  pre,\n  blockquote,\n  BlockQuote,\n  wrapper: (props: { children: any }) => {\n    return <div id=\"mdx-layout\">{props.children}</div>;\n  }\n};\n```\n\n> [!NOTE]\n> The **`wrapper`** is a special key, if you want to wrap the MDX content with a HTML container element.\n\n`./data/my-article.mdx`\n```markdown\n---\ntitle: \"My Article\"\nauthor: \"ipikuka\"\n---\n_Read in {readingTime}, written by <Link href=\"#\">**{frontmatter.author}**</Link>_\n\n# {frontmatter.title}\n\n## Sub heading for custom components\n\n<Hello name={foo} />\n\n<CountButton />\n\n<Dynamic />\n\n<Image src=\"/images/cover.png\" alt=\"cover\" width={180} height={40} />\n\n<BlockQuote>\n  I am blackquote content\n</BlockQuote>\n\n<motion.div animate={{ x: 100 }} />\n\n## Sub heading for some markdown elements\n\n![cover](/images/cover.png)\n\nHere is _italic text_ and **strong text**\n\n> I am blackquote content\n```\n\n## Utility `getFrontmatter`\n\nThe package exports one utility **`getFrontmatter`** which is **for getting frontmatter without compiling the source**. You can get the fronmatter and the stripped source by using the `getFrontmatter` which employs the same frontmatter extractor **`vfile-matter`** used within the package.\n\n```typescript\nimport { getFrontmatter } from \"next-mdx-remote-client/utils\";\n\nconst { frontmatter, strippedSource } = getFrontmatter<TFrontmatter>(source);\n```\n\nIf you provide **the generic type parameter**, it ensures the `frontmatter` gets the type, otherwise `Record<string, unknown>` by default.\n\n**If there is no frontmatter** in the source, the `frontmatter` will be **empty object `{}`**.\n\n> [!IMPORTANT]\n> \\\n> If you use **`next-mdx-remote`** and want to get `frontmatter` without compiling the source !\n> \\\n> The subpath **`next-mdx-remote-client/utils`** is isolated from other features of the package and it does cost minimum. **So, anyone can use `next-mdx-remote-client/utils` while using `next-mdx-remote`.**\n\n## Types\n\n**`next-mdx-remote-client`** is fully typed with [TypeScript][url-typescript].\n\nThe package exports the types for server side (rsc):\n\n- `EvaluateProps`\n- `EvaluateOptions`\n- `EvaluateResult`\n- `MDXRemoteProps`\n- `MDXRemoteOptions`\n\nThe package exports the types for client side (csr):\n\n- `HydrateProps`\n- `HydrateResult`\n- `MDXClientProps`\n- `SerializeResult`\n\nThe package exports the types for the serialize function:\n\n- `SerializeProps`\n- `SerializeOptions`\n- `SerializeResult`\n\nIn addition, the package exports the types from `mdx/types` so that developers do not need to import `mdx/types`:\n\n- `MDXComponents`\n- `MDXContent`\n- `MDXProps`\n- `MDXModule`\n\n## Compatibility\n\n**`next-mdx-remote-client`** works with unified version 6+ ecosystem since it is compatible with MDX version 3.\n\n## Security\n\nThe security model of **`next-mdx-remote-client`** is fundamentally the same as other MDX integrations built on top of **`@mdx-js/mdx`**, including **`next-mdx-remote`**, **`@next/mdx`**, and similar solutions.\n\nMDX supports **JSX syntax**; **JavaScript expressions** (`{1 + 1}`, `{someVar}`, `{fn()}`); and **ESM blocks (`mdxjsEsm`)** such as `import` and `export`.\n\nBecause MDX compiles to executable JavaScript, rendering **untrusted MDX** can inherently introduce **Cross-Site Scripting (XSS)** and **Remote Code Execution (RCE)**.\n\nThis is not unique to **`next-mdx-remote-client`**; it is intrinsic to how MDX works and has long been documented across the MDX ecosystem.\n\n### Trust Model\n\nIf MDX content is **not fully trusted**, then **RCE** is inherently possible. If you completely block all JavaScript expressions, you effectively reduce MDX to *Markdown with JSX*. That may be acceptable for certain use cases, but it changes the expressive nature of MDX.\n\nA more balanced approach is to **block only dangerous expressions** rather than disabling all expressions. The remark plugin [**`remark-mdx-remove-expressions`**](https://github.com/ipikuka/remark-mdx-remove-expressions) can remove executable or dangerous MDX expressions at the syntax level:\n\n```ts\nimport remarkMdxRemoveExpressions from \"remark-mdx-remove-expressions\";\n\n{\n  mdxOptions: {\n    remarkPlugins: [\n      [remarkMdxRemoveExpressions, { onlyDangerousExpressions: true }]\n    ]\n  }\n}\n```\n\n### ESM (`import` / `export`) in MDX\n\nAllowing **`import` declarations** and **`export` declarations** inside MDX can introduce serious risks if the content is not strictly controlled. **`next-mdx-remote-client`** provides options to disable ESM blocks (`mdxjsEsm`) for this reason.\n\nBut *dynamic import expressions*, such as `await import(\"some-module\")` are JavaScript expressions and require a **custom recma plugin** to block or transform them. [**`remark-mdx-remove-expressions`**](https://github.com/ipikuka/remark-mdx-remove-expressions) can also remove import expressions, **`next-mdx-remote-client`** does not modify or restrict these automatically.\n\n### Runtime Evaluation (`eval` / `new Function`)\n\nLike most MDX runtimes, **`next-mdx-remote-client`** evaluates compiled JavaScript using runtime evaluation `Reflect.construct` similar with `eval` or `new Function()`.\n\nEvaluating JavaScript from a string can enable **XSS** attacks or **RCE** if the input is not trusted. You are responsible for ensuring either the MDX source is trusted, or the source is properly sanitized and restricted before evaluation. Please, take your own measures while passing the user input.\n\n### Content Security Policy (CSP)\n\nIf your site uses a strict **Content Security Policy (CSP)** that disallows dynamic code evaluation via `eval` or `new Function()`, you will need to loosen the `script-src` policy to include `unsafe-eval`. Otherwise, MDX runtime evaluation will fail.\n\nCarefully assess the security implications before enabling [`unsafe-eval`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#common_sources), especially in high-security environments.\n\n### Final Security Recommendations\n\n- Treat MDX as executable code.\n- Never evaluate/render untrusted MDX without applying proper restrictions or sanitization.\n- Prefer removing dangerous expressions at the **remark/recma stage**, not at the rendering layer.\n- Disable ESM blocks if the content is not fully controlled.\n- Understand your CSP implications before deploying to production.\n\n## Some Plugins\n\nI like to contribute the Unified / Remark / MDX ecosystem, so I recommend you to have a look my plugins.\n\n### My Remark Plugins\n\n- [`remark-flexible-code-titles`](https://www.npmjs.com/package/remark-flexible-code-titles)\n  – Remark plugin to add titles or/and containers for the code blocks with customizable properties\n- [`remark-flexible-containers`](https://www.npmjs.com/package/remark-flexible-containers)\n  – Remark plugin to add custom containers with customizable properties in markdown\n- [`remark-ins`](https://www.npmjs.com/package/remark-ins)\n  – Remark plugin to add `ins` element in markdown\n- [`remark-flexible-paragraphs`](https://www.npmjs.com/package/remark-flexible-paragraphs)\n  – Remark plugin to add custom paragraphs with customizable properties in markdown\n- [`remark-flexible-markers`](https://www.npmjs.com/package/remark-flexible-markers)\n  – Remark plugin to add custom `mark` element with customizable properties in markdown\n- [`remark-flexible-toc`](https://www.npmjs.com/package/remark-flexible-toc)\n  – Remark plugin to expose the table of contents via Vfile.data or via an option reference\n- [`remark-mdx-remove-esm`](https://www.npmjs.com/package/remark-mdx-remove-esm)\n  – Remark plugin to remove import and/or export statements (mdxjsEsm)\n- [`remark-mdx-remove-expressions`](https://www.npmjs.com/package/remark-mdx-remove-expressions)\n  – Remark plugin to remove MDX expressions within curlybraces {} in MDX content\n\n### My Rehype Plugins\n\n- [`rehype-pre-language`](https://www.npmjs.com/package/rehype-pre-language)\n  – Rehype plugin to add language information as a property to `pre` element\n- [`rehype-highlight-code-lines`](https://www.npmjs.com/package/rehype-highlight-code-lines)\n  – Rehype plugin to add line numbers to code blocks and allow highlighting of desired code lines\n- [`rehype-code-meta`](https://www.npmjs.com/package/rehype-code-meta)\n  – Rehype plugin to copy `code.data.meta` to `code.properties.metastring`\n- [`rehype-image-toolkit`](https://www.npmjs.com/package/rehype-image-toolkit)\n  – Rehype plugin to enhance Markdown image syntax `![]()` and Markdown/MDX media elements (`<img>`, `<audio>`, `<video>`) by auto-linking bracketed or parenthesized image URLs, wrapping them in `<figure>` with optional captions, unwrapping images/videos/audio from paragraph, parsing directives in title for styling and adding attributes, and dynamically converting images into `<video>` or `<audio>` elements based on file extension.\n\n### My Recma Plugins\n\n- [`recma-mdx-escape-missing-components`](https://www.npmjs.com/package/recma-mdx-escape-missing-components)\n  – Recma plugin to set the default value `() => null` for the Components in MDX in case of missing or not provided so as not to throw an error\n- [`recma-mdx-change-props`](https://www.npmjs.com/package/recma-mdx-change-props)\n  – Recma plugin to change the `props` parameter into the `_props` in the `function _createMdxContent(props) {/* */}` in the compiled source in order to be able to use `{props.foo}` like expressions. It is useful for the `next-mdx-remote` or `next-mdx-remote-client` users in `nextjs` applications.\n- [`recma-mdx-change-imports`](https://www.npmjs.com/package/recma-mdx-change-imports)\n  – Recma plugin to convert import declarations for assets and media with relative links into variable declarations with string URLs, enabling direct asset URL resolution in compiled MDX.\n- [`recma-mdx-import-media`](https://www.npmjs.com/package/recma-mdx-import-media)\n  – Recma plugin to turn media relative paths into import declarations for both markdown and html syntax in MDX.\n- [`recma-mdx-import-react`](https://www.npmjs.com/package/recma-mdx-import-react)\n  – Recma plugin to ensure getting `React` instance from the arguments and to make the runtime props `{React, jsx, jsxs, jsxDev, Fragment}` is available in the dynamically imported components in the compiled source of MDX.\n- [`recma-mdx-html-override`](https://www.npmjs.com/package/recma-mdx-html-override)\n  – Recma plugin to allow selected raw HTML elements to be overridden via MDX components.\n- [`recma-mdx-interpolate`](https://www.npmjs.com/package/recma-mdx-interpolate)\n  – Recma plugin to enable interpolation of identifiers wrapped in curly braces within the `alt`, `src`, `href`, and `title` attributes of markdown link and image syntax in MDX.\n\n### My Unist Utils and Unified Plugins\n\nI also build low-level utilities and plugins for the Unified ecosystem that can be used across Remark, Rehype, Recma, and other unist-based abstract syntax trees (ASTs).\n\n- [`unist-util-find-between`](https://www.npmjs.com/package/unist-util-find-between)\n  – Unist utility to find the nodes between two nodes.\n- [`unified-log-tree`](https://www.npmjs.com/package/unified-log-tree)\n  – Unified plugin to log abstract syntax trees (ASTs) for debugging without mutating.\n\n## License\n\n[MPL 2.0 License](./LICENSE) © ipikuka\n\n[MDX]: https://mdxjs.com/\n[mdx-js-mdx]: https://github.com/mdx-js/mdx\n[next-mdx-remote]: https://github.com/hashicorp/next-mdx-remote\n\n[badge-npm-version]: https://img.shields.io/npm/v/next-mdx-remote-client\n[badge-npm-download]:https://img.shields.io/npm/dt/next-mdx-remote-client\n[url-npm-package]: https://www.npmjs.com/package/next-mdx-remote-client\n[url-github-package]: https://github.com/ipikuka/next-mdx-remote-client\n\n[badge-license]: https://img.shields.io/github/license/ipikuka/next-mdx-remote-client\n[url-license]: https://github.com/ipikuka/next-mdx-remote-client/blob/main/LICENSE\n\n[badge-publish-to-npm]: https://github.com/ipikuka/next-mdx-remote-client/actions/workflows/publish.yml/badge.svg\n[url-publish-github-actions]: https://github.com/ipikuka/next-mdx-remote-client/actions/workflows/publish.yml\n\n[badge-typescript]: https://img.shields.io/npm/types/next-mdx-remote-client\n[url-typescript]: https://www.typescriptlang.org/\n\n[badge-codecov]: https://codecov.io/gh/ipikuka/next-mdx-remote-client/graph/badge.svg?token=N0BPBCI5CC\n[url-codecov]: https://codecov.io/gh/ipikuka/next-mdx-remote-client\n\n[badge-type-coverage]: https://img.shields.io/badge/dynamic/json.svg?label=type-coverage&prefix=%E2%89%A5&suffix=%&query=$.typeCoverage.atLeast&uri=https%3A%2F%2Fraw.githubusercontent.com%2Fipikuka%2Fnext-mdx-remote-client%2Fmaster%2Fpackage.json"
  },
  {
    "path": "codecov.yml",
    "content": "coverage:\n  status:\n    project:\n      default:\n        target: 100%\n"
  },
  {
    "path": "eslint.config.js",
    "content": "import { defineConfig } from \"eslint/config\";\nimport eslint from \"@eslint/js\";\nimport tseslint from \"typescript-eslint\";\nimport globals from \"globals\";\nimport react from \"eslint-plugin-react\";\nimport eslintPluginPrettier from \"eslint-plugin-prettier\";\nimport eslintConfigPrettier from \"eslint-config-prettier\";\n\nexport default defineConfig(\n  {\n    ignores: [\n      \"**/archive/**\",\n      \"**/coverage/**\",\n      \"**/dist/**\",\n      \"**/node_modules/**\",\n      \"**/package-lock.json\",\n      \"**/.DS_Store\",\n      \"**/.vscode\",\n    ],\n  },\n  eslint.configs.recommended,\n  {\n    name: \"TypeScript\",\n    files: [\"**/*.{ts,tsx}\"],\n    extends: [eslint.configs.recommended, tseslint.configs.recommended],\n    plugins: {\n      react,\n      prettier: eslintPluginPrettier,\n    },\n    rules: {\n      \"@typescript-eslint/no-non-null-assertion\": \"off\",\n      \"@typescript-eslint/ban-ts-comment\": \"off\",\n      \"@typescript-eslint/no-explicit-any\": \"off\",\n    },\n  },\n  {\n    name: \"JavaScript\",\n    files: [\"**/*.{js,jsx}\"],\n    extends: [tseslint.configs.disableTypeChecked],\n  },\n  {\n    name: \"React\",\n    files: [\"**/*.jsx\", \"tests/context/ExampleForm.mjs\"],\n    plugins: {\n      react,\n      prettier: eslintPluginPrettier,\n    },\n    languageOptions: {\n      parserOptions: {\n        ecmaFeatures: {\n          jsx: true,\n        },\n      },\n      globals: globals.browser,\n    },\n  },\n  {\n    name: \"Idle Callback Polyfill\",\n    files: [\"src/csr/idle-callback-polyfill.js\"],\n    languageOptions: {\n      sourceType: \"script\",\n      globals: globals.browser,\n    },\n  },\n  eslintConfigPrettier,\n);\n"
  },
  {
    "path": "migration_guide.md",
    "content": "# Migration guide from `next-mdx-remote`\n\n## Migration examples for \"pages\" router\n\nAll examples have been taken from **`next-mdx-remote`** to show exactly how to migrate the code.\n\n<details>\n  <summary>Main example in the github page headline</summary>\n\n```diff\n- import { serialize } from 'next-mdx-remote/serialize'\n- import { MDXRemote } from 'next-mdx-remote'\n\n+ import { serialize } from 'next-mdx-remote-client/serialize'\n+ import { MDXClient } from 'next-mdx-remote-client'\n\nimport { Test } from '../mdxComponents'\n+ import { ErrorComponent } from '../components'\n\nconst components = { Test }\n\nexport default function TestPage({ source }) {\n+ if (\"error\" in source) {\n+   return <ErrorComponent error={source.error} />;\n+ }\n\n  return (\n    <div className=\"wrapper\">\n-     <MDXRemote {...source} components={components} />\n+     <MDXClient {...source} components={components} />\n    </div>\n  )\n}\n\nexport async function getStaticProps() {\n  // MDX text - can be from a local file, database, anywhere\n  const source = 'Some **mdx** text, with a component <Test />'\n- const mdxSource = await serialize(source)\n+ const mdxSource = await serialize({source})\n  return { props: { source: mdxSource } }\n}\n```\n\n</details>\n\n<details>\n  <summary>Parsing frontmatter</summary>\n\n```diff\n- import { serialize } from 'next-mdx-remote/serialize'\n- import { MDXRemote } from 'next-mdx-remote'\n\n+ import { serialize } from 'next-mdx-remote-client/serialize'\n+ import { MDXClient } from 'next-mdx-remote-client'\n\nimport { Test } from '../mdxComponents'\n+ import { ErrorComponent } from '../components'\n\nconst components = { Test }\n\nexport default function TestPage({ mdxSource }) {\n+ if (\"error\" in mdxSource) {\n+   return <ErrorComponent error={mdxSource.error} />;\n+ }\n\n  return (\n    <div className=\"wrapper\">\n      <h1>{mdxSource.frontmatter.title}</h1>\n-     <MDXRemote {...mdxSource} components={components} />\n+     <MDXClient {...mdxSource} components={components} />\n    </div>\n  )\n}\n\nexport async function getStaticProps() {\n  // MDX text - can be from a local file, database, anywhere\n  const source = `---\ntitle: Test\n---\nSome **mdx** text, with a component <Test name={frontmatter.title}/>`\n\n- const mdxSource = await serialize(source, { parseFrontmatter: true })\n+ const mdxSource = await serialize({source, options: { parseFrontmatter: true }})\n  return { props: { mdxSource } }\n}\n```\n\n</details>\n\n<details>\n  <summary>Passing custom data to a component with `scope`</summary>\n\n```diff\n- import { serialize } from 'next-mdx-remote/serialize'\n- import { MDXRemote } from 'next-mdx-remote'\n\n+ import { serialize } from 'next-mdx-remote-client/serialize'\n+ import { MDXClient } from 'next-mdx-remote-client'\n\nimport { Test } from '../mdxComponents'\n+ import { ErrorComponent } from '../components'\n\nconst components = { Test }\nconst data = { product: 'next' }\n\nexport default function TestPage({ source }) {\n+ if (\"error\" in source) {\n+   return <ErrorComponent error={source.error} />;\n+ }\n\n  return (\n    <div className=\"wrapper\">\n-     <MDXRemote {...source} components={components} scope={data} />\n+     <MDXClient {...source} components={components} scope={data} />\n    </div>\n  )\n}\n\nexport async function getStaticProps() {\n  // MDX text - can be from a local file, database, anywhere\n  const source =\n    'Some **mdx** text, with a component using a scope variable <Test product={product} />'\n- const mdxSource = await serialize(source)\n+ const mdxSource = await serialize({source})\n  return { props: { source: mdxSource } }\n}\n```\n\n</details>\n\n<details>\n  <summary>Passing `scope` into the `serialize` function instead</summary>\n\n```diff\n- import { serialize } from 'next-mdx-remote/serialize'\n- import { MDXRemote } from 'next-mdx-remote'\n\n+ import { serialize } from 'next-mdx-remote-client/serialize'\n+ import { MDXClient } from 'next-mdx-remote-client'\n\nimport { Test } from '../mdxComponents'\n+ import { ErrorComponent } from '../components'\n\nconst components = { Test }\nconst data = { product: 'next' }\n\nexport default function TestPage({ source }) {\n+ if (\"error\" in source) {\n+   return <ErrorComponent error={source.error} />;\n+ }\n\n  return (\n    <div className=\"wrapper\">\n-     <MDXRemote {...source} components={components} />\n+     <MDXClient {...source} components={components} />\n    </div>\n  )\n}\n\nexport async function getStaticProps() {\n  // MDX text - can be from a local file, database, anywhere\n  const source =\n    'Some **mdx** text, with a component <Test product={product} />'\n- const mdxSource = await serialize(source, { scope: data })\n+ const mdxSource = await serialize({source, options: { scope: data }})\n  return { props: { source: mdxSource } }\n}\n```\n\n</details>\n\n<details>\n  <summary>\n    Custom components from <code>MDXProvider</code><a id=\"mdx-provider\"></a>\n  </summary>\n\n```diff\n// pages/_app.jsx\n- import { MDXProvider } from '@mdx-js/react'\n+ import { MDXProvider } from 'next-mdx-remote-client'\n\nimport Test from '../mdxComponents/Test'\n\nconst components = { Test }\n\nexport default function MyApp({ Component, pageProps }) {\n  return (\n    <MDXProvider components={components}>\n      <Component {...pageProps} />\n    </MDXProvider>\n  )\n}\n```\n\n```diff\n// pages/test.jsx\n- import { serialize } from 'next-mdx-remote/serialize'\n- import { MDXRemote } from 'next-mdx-remote'\n\n+ import { serialize } from 'next-mdx-remote-client/serialize'\n+ import { MDXClient } from 'next-mdx-remote-client'\n\n+ import { ErrorComponent } from '../components'\n\nexport default function TestPage({ source }) {\n+ if (\"error\" in source) {\n+   return <ErrorComponent error={source.error} />;\n+ }\n\n  return (\n    <div className=\"wrapper\">\n-     <MDXRemote {...source} />\n+     <MDXClient {...source} />\n    </div>\n  )\n}\n\nexport async function getStaticProps() {\n  // MDX text - can be from a local file, database, anywhere\n  const source = 'Some **mdx** text, with a component <Test />'\n- const mdxSource = await serialize(source)\n+ const mdxSource = await serialize({source})\n  return { props: { source: mdxSource } }\n}\n```\n\n</details>\n\n<details>\n  <summary>\n    Component names with dot (e.g. <code>motion.div</code>)\n  </summary>\n\n```diff\nimport { motion } from 'framer-motion'\n\n- import { MDXProvider } from '@mdx-js/react'\n- import { serialize } from 'next-mdx-remote/serialize'\n- import { MDXRemote } from 'next-mdx-remote'\n\n+ import { serialize } from 'next-mdx-remote-client/serialize'\n+ import { MDXClient, MDXProvider } from 'next-mdx-remote-client'\n\n+ import { ErrorComponent } from '../components'\n\nexport default function TestPage({ source }) {\n+ if (\"error\" in source) {\n+   return <ErrorComponent error={source.error} />;\n+ }\n\n  return (\n    <div className=\"wrapper\">\n-     <MDXRemote {...source} components={{ motion }} />\n+     <MDXClient {...source} components={{ motion }} />\n    </div>\n  )\n}\n\nexport async function getStaticProps() {\n  // MDX text - can be from a local file, database, anywhere\n  const source = `Some **mdx** text, with a component:\n\n<motion.div animate={{ x: 100 }} />`\n- const mdxSource = await serialize(source)\n+ const mdxSource = await serialize({source})\n  return { props: { source: mdxSource } }\n}\n```\n\n</details>\n\n<details>\n  <summary>Lazy hydration</summary>\n\n```diff\n- import { serialize } from 'next-mdx-remote/serialize'\n- import { MDXRemote } from 'next-mdx-remote'\n\n+ import { serialize } from 'next-mdx-remote-client/serialize'\n+ import { MDXClientLazy } from 'next-mdx-remote-client'\n\nimport { Test } from '../mdxComponents'\n+ import { ErrorComponent } from '../components'\n\nconst components = { Test }\n\nexport default function TestPage({ source }) {\n+ if (\"error\" in source) {\n+   return <ErrorComponent error={source.error} />;\n+ }\n\n  return (\n    <div className=\"wrapper\">\n-     <MDXRemote {...source} components={components} lazy />\n+     <MDXClientLazy {...source} components={components} />\n    </div>\n  )\n}\n\nexport async function getStaticProps() {\n  // MDX text - can be from a local file, database, anywhere\n  const source = 'Some **mdx** text, with a component <Test />'\n- const mdxSource = await serialize(source)\n+ const mdxSource = await serialize({source})\n  return { props: { source: mdxSource } }\n}\n```\n\n</details>\n\n<details>\n  <summary>With typescript</summary>\n\n```diff\nimport { type GetStaticProps } from 'next'\n\n- import { serialize } from 'next-mdx-remote/serialize'\n- import { MDXRemote, type MDXRemoteSerializeResult } from 'next-mdx-remote'\n\n+ import { serialize, type SerializeResult } from 'next-mdx-remote-client/serialize'\n+ import { MDXClient } from 'next-mdx-remote-client'\n\nimport { ExampleComponent } from './mdxComponents'\n+ import { ErrorComponent } from '../components'\n\nconst components = { ExampleComponent }\n\n- interface Props {\n-   mdxSource: MDXRemoteSerializeResult\n- }\n\n+ type Props = {\n+  mdxSource: SerializeResult\n+ }\n\nexport default function ExamplePage({ mdxSource }: Props) {\n+ if (\"error\" in mdxSource) {\n+   return <ErrorComponent error={mdxSource.error} />;\n+ }\n\n  return (\n    <div>\n+     <MDXRemote {...mdxSource} components={components} />\n-     <MDXClient {...mdxSource} components={components} />\n    </div>\n  )\n}\n\nexport const getStaticProps: GetStaticProps<{\n-  mdxSource: MDXRemoteSerializeResult\n+  mdxSource: SerializeResult\n}> = async () => {\n- const mdxSource = await serialize('some *mdx* content: <ExampleComponent />')\n+ const mdxSource = await serialize({ source: 'some *mdx* content: <ExampleComponent />'})\n  return { props: { mdxSource } }\n}\n```\n\n</details>\n\n## Migration examples for \"app\" router\n\nAll examples have been taken from **`next-mdx-remote`** to show exactly how to migrate the code.\n\n<details>\n  <summary>Basic example for React Server Components (RSC)</summary>\n\n```diff\n- import { MDXRemote } from 'next-mdx-remote/rsc'\n+ import { MDXRemote } from 'next-mdx-remote-client/rsc'\n\n+ import { ErrorComponent } from '../components'\n\n// app/page.js\nexport default function Home() {\n  return (\n    <MDXRemote\n      source={`# Hello from Server Components`}\n+     onEror={ErrorComponent}    \n    />\n  )\n}\n```\n\n</details>\n\n<details>\n  <summary>Loading state in \"app\" router</summary>\n\n```diff\nimport { Suspense } from 'react'\n- import { MDXRemote } from 'next-mdx-remote/rsc'\n+ import { MDXRemote } from 'next-mdx-remote-client/rsc'\n\n+ import { ErrorComponent } from '../components'\n\n// app/page.js\nexport default function Home() {\n  return (\n    // In Next.js you can also use `loading.js` instead of <Suspense />\n    <Suspense fallback={<>Loading...</>}>\n      <MDXRemote\n        source={`# Hello from Server Components`}\n+       onEror={ErrorComponent}  \n      />\n    </Suspense>\n  )\n}\n```\n\n</details>\n\n<details>\n  <summary>Custom components</summary>\n\n```diff\n// components/mdx-remote.js\n- import { MDXRemote } from 'next-mdx-remote/rsc'\n+ import { MDXRemote } from 'next-mdx-remote-client/rsc'\n\n+ import { ErrorComponent } from '../components'\n\nconst components = {\n  h1: (props) => (\n    <h1 {...props} className=\"large-text\">\n      {props.children}\n    </h1>\n  ),\n}\n\nexport function CustomMDX(props) {\n  return (\n    <MDXRemote\n      {...props}\n      components={{ ...components, ...(props.components || {}) }}\n+     onEror={ErrorComponent}  \n    />\n  )\n}\n```\n\n```diff\n// app/page.js\nimport { CustomMDX } from '../components/mdx-remote'\n\nexport default function Home() {\n  return (\n    <CustomMDX\n      // h1 now renders with `large-text` className\n      source={`# Hello from Server Components`}\n    />\n  )\n}\n```\n\n</details>\n\n<details>\n  <summary>Access `frontmatter` and `scope` outside of MDX</summary>\n\n```diff\n// app/page.js\n- import { compileMDX } from 'next-mdx-remote/rsc'\n+ import { evaluate } from 'next-mdx-remote-client/rsc'\n\n+ import { ErrorComponent } from '../components'\n\nexport default async function Home() {\n- const { content, frontmatter } = await compileMDX<{ title: string }>({\n+ const { content, frontmatter, scope, error } = await evaluate<{ title: string }>({\n    source: `---\ntitle: RSC Frontmatter Example\n---\n# Hello from {product}!`,\n    options: { \n      parseFrontmatter: true,\n      scope: {\n        product: 'Server Components'\n      },\n    },\n  })\n\n+ if (error) {\n+   return <ErrorComponent error={error} />;\n+ }\n\n  return (\n    <>\n      <h1>{frontmatter.title}</h1>\n+     <h2>{scope.product}</h2>\n      {content}\n    </>\n  )\n}\n```\n\n</details>\n\n## The differences between `next-mdx-remote` and `next-mdx-remote-client`\n\n### `next-mdx-remote-client` has additional exported subpaths\n\n**`🟥 next-mdx-remote`:**\n\n```typescript\nimport /* */ from \"next-mdx-remote\";\nimport /* */ from \"next-mdx-remote/serialize\";\nimport /* */ from \"next-mdx-remote/rsc\";\n```\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\nimport /* */ from \"next-mdx-remote-client\";\nimport /* */ from \"next-mdx-remote-client/serialize\";\nimport /* */ from \"next-mdx-remote-client/rsc\";\n\n// additional exported subpaths\nimport /* */ from \"next-mdx-remote-client/csr\";\nimport /* */ from \"next-mdx-remote-client/utils\";\n```\n\n> [!NOTE]\n> The `next-mdx-remote-client` and the `next-mdx-remote-client/csr` refer to the same.\n\n### Use `<MDXClient />` in the client side\n\n**`🟥 next-mdx-remote`:**\n\nIt exports the components with the same name `<MDXRemote />` for both \"app\" and \"pages\" router.\n\n```typescript\n// for \"pages\" router, it is a client component\nimport { MDXRemote } from \"next-mdx-remote\"; \n\n// for \"app\" router, it is a server component\nimport { MDXRemote } from \"next-mdx-remote/rsc\"; \n```\n\n**`🟩 next-mdx-remote-client`:**\n\nIt exports `<MDXClient />` for \"pages\" router, `<MDXRemote />` for \"app\" router. \n\n```typescript\n// for \"pages\" router, it is a client component\nimport { MDXClient } from \"next-mdx-remote-client/csr\"; \n\n// for \"app\" router, it is a server component\nimport { MDXRemote } from \"next-mdx-remote-client/rsc\"; \n```\n\n## The part associated with Next.js `app` router\n\n_Go to [the part associated with Next.js pages router](#the-part-associated-with-nextjs-pages-router)_\n\n### The differences in module exports\n\n**`🟥 next-mdx-remote`:**\n\n```typescript\nimport { MDXRemote, compileMDX } from \"next-mdx-remote/rsc\";\n```\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\nimport { MDXRemote, evaluate } from \"next-mdx-remote-client/rsc\";\n```\n\n### The differences in type exports\n\n**`🟥 next-mdx-remote`:**\n\n```typescript\nimport type { MDXRemoteProps, CompileMDXResult, MDXRemoteSerializeResult } from \"next-mdx-remote/rsc\";\n```\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\nimport type { MDXRemoteProps, MDXRemoteOptions } from \"next-mdx-remote-client/rsc\";\n\nimport type { EvaluateProps, EvaluateOptions, EvaluateResult } from \"next-mdx-remote-client/rsc\";\n```\n\n### The differences in props\n\n**`🟥 next-mdx-remote`:**\n\nThe `compileMDX` and `MDXRemote` take the same props `MDXRemoteProps`.\n\n```typescript\ntype MDXRemoteProps = {\n  source: VFileCompatible\n  options?: SerializeOptions\n  components?: React.ComponentProps<typeof MDXProvider>['components']\n}\n```\n\n**`🟩 next-mdx-remote-client`:**\n\nThe `evaluate` takes `EvaluateProps` which has a type argument, and **the same prop keys but different types**.\n\n```typescript\ntype EvaluateProps<TScope> = {\n  source: Compatible;\n  options?: EvaluateOptions<TScope>;\n  components?: MDXComponents;\n}\n```\n\nThe `MDXRemote` takes `MDXRemoteProps` which has `onError` prop in addition to `EvaluateProps`.\n\n```typescript\ntype MDXRemoteProps<TScope> = {\n  source: Compatible;\n  options?: EvaluateOptions<TScope>;\n  components?: MDXComponents;\n  onError?: React.ComponentType<{ error: Error }>;\n}\n```\n\n### Use `evaluate` instead of `compileMDX`\n\n**`🟥 next-mdx-remote`:**\n\nThe `compileMDX` takes `MDXRemoteProps` and returns `CompileMDXResult` as a promise.\n\n```typescript\nasync function compileMDX<Frontmatter>({source, options, components}): Promise<CompileMDXResult> {}\n```\n\nThe `compileMDX` takes one generic type parameter `<Frontmatter>`.\n\n**`🟩 next-mdx-remote-client`:**\n\nThe `evaluate` takes `EvaluateProps` and returns `EvaluateResult` as a promise.\n\n```typescript\nasync function evaluate<Frontmatter, Scope>({source, options, components}): Promise<EvaluateResult> {}\n```\n\nThe `evaluate` takes two generic type parameters `<Frontmatter, Scope>` _(the order matters)_.\n\n### The `evaluate` and the `compileMDX` have different results\n\n**`🟥 next-mdx-remote`:**\n\nThe `compileMDX` returns the MDX `content` and the `frontmatter`.\n\n```typescript\nconst { content, frontmatter } = await compileMDX<Frontmatter>({source, options, components});\n\ntype CompileMDXResult<TFrontmatter> = {\n  content: React.ReactElement\n  frontmatter: TFrontmatter\n}\n```\n\n**`🟩 next-mdx-remote-client`:**\n\nThe `evaluate` returns `mod` object for the exports, `scope`, and `error` objects additional to MDX `content` and the `frontmatter`.\n\n```typescript\nconst { content, mod, frontmatter, scope, error } = await evaluate<Frontmatter, Scope>({source, options, components});\n\ntype EvaluateResult<TFrontmatter, TScope> = {\n  content: React.JSX.Element;\n  mod: Record<string, unknown>;\n  frontmatter: TFrontmatter;\n  scope: TScope;\n  error?: Error;\n}\n```\n\n### The differences in options\n\nThe `next-mdx-remote-client` has more options.\n\nPlease, note that, the `mdxOptions` are more or less similar in both **but have differences in terms of opinionation for `@mdx-js/mdx` options**.\n\n**`🟥 next-mdx-remote`:**\n\nThe `compileMDX` and `MDXRemote` options:\n\n```typescript\n{\n  mdxOptions?: /* mdx options to be passed into @mdx-js/mdx */\n  parseFrontmatter?: boolean\n  scope?: Record<string, unknown>\n}\n```\n\n**`🟩 next-mdx-remote-client`:**\n\nThe `evaluate` and `MDXRemote` options:\n\n```typescript\n{\n  mdxOptions?: /* mdx options to be passed into @mdx-js/mdx */\n  disableExports?: boolean; // <---\n  disableImports?: boolean; // <---\n  parseFrontmatter?: boolean;\n  scope?: Record<string, unknown>;\n  vfileDataIntoScope?: VfileDataIntoScope; // <---\n}\n```\n\n## The part associated with Next.js `pages` router\n\n_Go to [the part associated with Next.js app router](#the-part-associated-with-nextjs-app-router)_\n\n### Serialize function takes named parameters and `rsc` parameter is removed\n\n**`🟥 next-mdx-remote`:**\n\n```typescript\nconst mdxSource = await serialize(source: VFileCompatible, options: SerializeOptions, rsc: boolean);\n```\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\nconst mdxSource = await serialize({ source: Compatible, options: SerializeOptions });\n```\n\n### Serialize function has additional options\n\n**`🟥 next-mdx-remote`:**\n\n```typescript\ntype SerializeOptions = {\n  mdxOptions?: SerializeMdxOptions;\n  parseFrontmatter?: boolean;\n  scope?: Record<string, unknown>;\n};\n```\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\ntype SerializeOptions<TScope> = {\n  mdxOptions?: SerializeMdxOptions;\n  disableExports?: boolean; // <---\n  disableImports?: boolean; // <---\n  parseFrontmatter?: boolean;\n  scope?: TScope;\n  vfileDataIntoScope?: VfileDataIntoScope; // <---\n};\n```\n\n### Serialize function accepts the generic type parameters in reverse\n\n**`🟥 next-mdx-remote`:**\n\n```typescript\nconst mdxSource = await serialize<Scope, Frontmatter>(/* */);\n```\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\nconst mdxSource = await serialize<Frontmatter, Scope>(/* */);\n```\n\n### SerializeResult takes the generic type parameters in reverse, as well\n\n**`🟥 next-mdx-remote`:**\n\n```typescript\ntype Props = {\n  mdxSource: MDXRemoteSerializeResult<Scope, Frontmatter>;\n};\n```\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\ntype Props = {\n  mdxSource: SerializeResult<Frontmatter, Scope>;\n};\n```\n\n### Serialize function returns \"error\" object\n\n**`🟥 next-mdx-remote`:**\n\nIt has no \"error\" object in return.\n\n```typescript\nconst { compiledSource, frontmatter, scope } = await serialize(/* */);\n```\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\nconst { compiledSource, frontmatter, scope, error } = await serialize(/* */);\n```\n\n### New function `hydrate`\n\n**`🟥 next-mdx-remote`:**\n\n_It doesn't have the function_\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\nconst { content, mod, error } = hydrate(props: HydrateProps): HydrateResult {}\n\ntype HydrateProps = {\n  compiledSource: string;\n  frontmatter?: Record<string, unknown>;\n  scope?: Record<string, unknown>;\n  components?: MDXComponents;\n  disableParentContext?: boolean;\n};\n\ntype HydrateResult = {\n  content: React.JSX.Element;\n  mod: Record<string, unknown>;\n  error?: Error;\n};\n```\n\n### Use `MDXClient` instead of `MDXRemote` in \"pages\" router\n\n**`🟥 next-mdx-remote`:**\n\n```typescript\n<MDXRemote\n  compiledSource={compiledSource}\n  frontmatter={frontmatter}\n  scope={scope}\n  components={components}\n  lazy={lazy} // boolean, optional\n/>\n```\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\n<MDXClient\n  compiledSource={compiledSource}\n  frontmatter={frontmatter}\n  scope={scope}\n  components={components}\n  onError={onError} // React.ComponentType<{ error: Error }>, optional\n/>\n```\n\n### For lazy hydration use `hydrateLazy` or `<MDXClientLazy />`\n\n**`🟥 next-mdx-remote`:**\n\n```typescript\n<MDXRemote\n  compiledSource={compiledSource}\n  // ..\n  lazy\n/>\n```\n\n**`🟩 next-mdx-remote-client`:**\n\n```typescript\nconst { content, mod, error } = hydrateLazy({compiledSource, /* */ })\n```\nor\n```typescript\n<MDXClientLazy\n  compiledSource={compiledSource}\n  // ..\n/>\n```"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"next-mdx-remote-client\",\n  \"description\": \"A wrapper of the `@mdx-js/mdx` for the `nextjs` applications in order to load MDX content. It is a fork of `next-mdx-remote`.\",\n  \"version\": \"2.1.10\",\n  \"type\": \"module\",\n  \"main\": \"./dist/csr/index.js\",\n  \"types\": \"./dist/csr/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/csr/index.d.ts\",\n      \"import\": \"./dist/csr/index.js\",\n      \"default\": \"./dist/csr/index.js\"\n    },\n    \"./csr\": {\n      \"types\": \"./dist/csr/index.d.ts\",\n      \"import\": \"./dist/csr/index.js\",\n      \"default\": \"./dist/csr/index.js\"\n    },\n    \"./serialize\": {\n      \"types\": \"./dist/csr/serialize.d.ts\",\n      \"import\": \"./dist/csr/serialize.js\",\n      \"default\": \"./dist/csr/serialize.js\"\n    },\n    \"./rsc\": {\n      \"types\": \"./dist/rsc/index.d.ts\",\n      \"import\": \"./dist/rsc/index.js\",\n      \"default\": \"./dist/rsc/index.js\"\n    },\n    \"./utils\": {\n      \"types\": \"./dist/utils/index.d.ts\",\n      \"import\": \"./dist/utils/index.js\",\n      \"default\": \"./dist/utils/index.js\"\n    }\n  },\n  \"scripts\": {\n    \"build\": \"rimraf dist && tsc --build && type-coverage\",\n    \"format\": \"npm run prettier && npm run lint\",\n    \"prettier\": \"prettier --write .\",\n    \"lint\": \"eslint .\",\n    \"pretest\": \"npm run build && npm pack --pack-destination ./dist\",\n    \"test:watch\": \"vitest --pool=vmThreads\",\n    \"test:file\": \"vitest --pool=vmThreads test.serialize-hydrate.spec.tsx\",\n    \"test\": \"npm run test:esm && npm run test:rest\",\n    \"test:esm\": \"vitest --pool=vmThreads run esm\",\n    \"test:rest\": \"vitest --pool=forks run --exclude 'tests/*esm*'\",\n    \"test-coverage\": \"vitest --pool=vmThreads run --coverage\",\n    \"prepublishOnly\": \"npm run format && npm run test-coverage\"\n  },\n  \"files\": [\n    \"dist/\",\n    \"LICENSE\",\n    \"README.md\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/ipikuka/next-mdx-remote-client.git\"\n  },\n  \"keywords\": [\n    \"markdown\",\n    \"MDX\",\n    \"@mdx-js/mdx\",\n    \"nextjs\",\n    \"next-mdx-remote\",\n    \"@next/mdx\"\n  ],\n  \"author\": \"ipikuka <talatkuyuk@gmail.com>\",\n  \"license\": \"MPL 2.0\",\n  \"homepage\": \"https://github.com/ipikuka/next-mdx-remote-client#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/ipikuka/next-mdx-remote-client/issues\"\n  },\n  \"dependencies\": {\n    \"@babel/code-frame\": \"^7.29.0\",\n    \"@mdx-js/mdx\": \"^3.1.1\",\n    \"@mdx-js/react\": \"^3.1.1\",\n    \"remark-mdx-remove-esm\": \"^1.3.1\",\n    \"serialize-error\": \"^13.0.1\",\n    \"vfile\": \"^6.0.3\",\n    \"vfile-matter\": \"^5.0.1\"\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"^9.39.3\",\n    \"@testing-library/dom\": \"^10.4.1\",\n    \"@testing-library/jest-dom\": \"^6.9.1\",\n    \"@testing-library/react\": \"^16.3.2\",\n    \"@types/babel__code-frame\": \"^7.27.0\",\n    \"@types/eslint-config-prettier\": \"^6.11.3\",\n    \"@types/mdx\": \"^2.0.13\",\n    \"@types/node\": \"^24.10.13\",\n    \"@types/react\": \"^19.2.14\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"@vitejs/plugin-react-swc\": \"^4.2.3\",\n    \"@vitest/coverage-v8\": \"^3.2.4\",\n    \"dedent\": \"^1.7.1\",\n    \"eslint\": \"^9.39.3\",\n    \"eslint-config-prettier\": \"^10.1.8\",\n    \"eslint-plugin-prettier\": \"^5.5.5\",\n    \"eslint-plugin-react\": \"^7.37.5\",\n    \"globals\": \"^17.3.0\",\n    \"jsdom\": \"^28.1.0\",\n    \"prettier\": \"^3.8.1\",\n    \"recma-mdx-change-props\": \"^1.2.4\",\n    \"recma-mdx-escape-missing-components\": \"^1.2.4\",\n    \"recma-mdx-import-react\": \"^1.2.4\",\n    \"remark-emoji\": \"^5.0.2\",\n    \"remark-flexible-markers\": \"^1.3.3\",\n    \"remark-flexible-paragraphs\": \"^1.3.3\",\n    \"rimraf\": \"^6.1.3\",\n    \"type-coverage\": \"^2.29.7\",\n    \"typescript\": \"^5.9.3\",\n    \"typescript-eslint\": \"^8.56.0\",\n    \"unified\": \"^11.0.5\",\n    \"vitest\": \"^3.2.4\"\n  },\n  \"peerDependencies\": {\n    \"react\": \">= 19.1.0\",\n    \"react-dom\": \">= 19.1.0\"\n  },\n  \"engines\": {\n    \"node\": \">=20.9.0\"\n  },\n  \"typeCoverage\": {\n    \"atLeast\": 100,\n    \"detail\": true,\n    \"ignoreAsAssertion\": true,\n    \"ignoreCatch\": true,\n    \"strict\": true\n  }\n}\n"
  },
  {
    "path": "src/csr/MDXClient.tsx",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport type { MDXClientProps } from \"./types.js\";\nimport { hydrate } from \"./hydrate.js\";\n\n/**\n * renders the content on the client side (csr), which is provided by the \"hydrate\" function.\n */\nexport function MDXClient(props: MDXClientProps): React.JSX.Element {\n  const { onError: ErrorComponent, ...rest } = props;\n\n  const { content, error } = hydrate(rest);\n\n  if (error && !ErrorComponent) throw error;\n\n  if (error && ErrorComponent) return <ErrorComponent error={error} />;\n\n  return content;\n}\n"
  },
  {
    "path": "src/csr/MDXClientAsync.tsx",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport type { MDXClientAsyncProps } from \"./types.js\";\nimport { hydrateAsync } from \"./hydrateAsync.js\";\n\n/**\n * it is experimental\n *\n * renders the content on the client side (csr), which is provided by the \"hydrateAsync\" function.\n *\n * the content is going to be hydrated \"asynchronously\" in a useEffect hook.\n */\nexport function MDXClientAsync(props: MDXClientAsyncProps): React.JSX.Element {\n  const { onError: ErrorComponent, ...rest } = props;\n\n  const { content, error } = hydrateAsync(rest);\n\n  /* v8 ignore next */\n  if (error && !ErrorComponent) throw error;\n\n  if (error && ErrorComponent) return <ErrorComponent error={error} />;\n\n  return content;\n}\n"
  },
  {
    "path": "src/csr/MDXClientLazy.tsx",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport type { MDXClientProps } from \"./types.js\";\nimport { hydrateLazy } from \"./hydrateLazy.js\";\n\n/**\n * renders the content on the client side (csr), which is provided by the \"hydrateLazy\" function.\n *\n * the content is going to be hydrated \"lazily\".\n */\nexport function MDXClientLazy(props: MDXClientProps): React.JSX.Element {\n  const { onError: ErrorComponent, ...rest } = props;\n\n  const { content, error } = hydrateLazy(rest);\n\n  /* v8 ignore next */\n  if (error && !ErrorComponent) throw error;\n\n  if (error && ErrorComponent) return <ErrorComponent error={error} />;\n\n  return content;\n}\n"
  },
  {
    "path": "src/csr/hydrate.tsx",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport { MDXProvider, useMDXComponents } from \"@mdx-js/react\";\n\nimport { runSync } from \"../lib/run.js\";\n\nimport type { HydrateResult, HydrateProps } from \"./types.js\";\n\n/**\n * \"run\"s the javascript code in the compiled source, and\n * returns the <Content /> component whether or not wrapped with the MDXProvider\n * in the domain of client side rendering (csr).\n */\nexport function hydrate({\n  compiledSource,\n  frontmatter = {},\n  scope = {},\n  components,\n  disableParentContext,\n}: HydrateProps): HydrateResult {\n  try {\n    const { Content, mod } = runSync(compiledSource, {\n      frontmatter,\n      scope,\n      mdxOptions: {\n        useMDXComponents,\n      },\n    });\n\n    const content = components ? (\n      // wrap the Content with the MDXProvider in order to customize the standard markdown components\n      <MDXProvider components={components} disableParentContext={disableParentContext}>\n        <Content />\n      </MDXProvider>\n    ) : (\n      // no need to wrap the Content with the MDXProvider since there is no custom component provided\n      <Content />\n    );\n\n    return { content, mod };\n  } catch (error: unknown) {\n    return {\n      content: <div className=\"mdx-empty\" />,\n      mod: {},\n      error: error as Error,\n    };\n  }\n}\n"
  },
  {
    "path": "src/csr/hydrateAsync.tsx",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport { useEffect, useState } from \"react\";\nimport { MDXProvider, useMDXComponents } from \"@mdx-js/react\";\n\nimport { runAsync } from \"../lib/run.js\";\nimport type { RunResult } from \"../lib/types.js\";\n\nimport type { HydrateAsyncProps, HydrateResult } from \"./types.js\";\n\n/**\n * This is experimental and proof for NOT WORKING in pages directory\n *\n * \"run\"s the javascript code in the compiled source, and\n * returns the <Content /> component whether or not wrapped with the MDXProvider\n * in the domain of client side rendering (csr).\n *\n * the hydration process occurs asynchronously in the useEffect so as to import modules in the compiled source.\n */\nexport function hydrateAsync({\n  compiledSource,\n  frontmatter = {},\n  scope = {},\n  components,\n  disableParentContext,\n  // two options below are for only hydrateAsync\n  options,\n  loading,\n}: HydrateAsyncProps): HydrateResult {\n  const { baseUrl } = options ?? {};\n\n  const [runResult, setRunResult] = useState<RunResult | { error: Error }>({\n    Content: loading ? loading : () => <div />,\n    mod: {},\n  });\n\n  useEffect(() => {\n    async function getContent() {\n      // to see loading state a bit\n      await new Promise((resolve) => setTimeout(resolve, 500));\n\n      try {\n        const runResult_ = await runAsync(compiledSource, {\n          mdxOptions: {\n            baseUrl,\n            useMDXComponents,\n          },\n          frontmatter,\n          scope,\n        });\n\n        setRunResult(runResult_);\n      } catch (error) {\n        setRunResult({\n          error: error as Error,\n        });\n      }\n    }\n\n    getContent();\n  }, []);\n\n  if (\"error\" in runResult) {\n    return {\n      content: <div className=\"mdx-empty\" />,\n      mod: {},\n      error: runResult.error,\n    };\n  }\n\n  const content = components ? (\n    // wrap the Content with the MDXProvider in order to customize the standard markdown components\n    <MDXProvider components={components} disableParentContext={disableParentContext}>\n      <runResult.Content />\n    </MDXProvider>\n  ) : (\n    // no need to wrap the Content with the MDXProvider since there is no custom component provided\n    <runResult.Content />\n  );\n\n  return { content, mod: runResult.mod };\n}\n"
  },
  {
    "path": "src/csr/hydrateLazy.tsx",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { MDXProvider, useMDXComponents } from \"@mdx-js/react\";\n\nimport \"./idle-callback-polyfill.js\";\nimport { runSync } from \"../lib/run.js\";\n\nimport type { HydrateResult, HydrateProps } from \"./types.js\";\n\n/**\n * \"run\"s the javascript code in the compiled source, and\n * returns the <Content /> component whether or not wrapped with the MDXProvider\n * in the domain of client side rendering (csr).\n *\n * the hydration process occurs lazily.\n */\nexport function hydrateLazy({\n  compiledSource,\n  frontmatter = {},\n  scope = {},\n  components,\n  disableParentContext,\n}: HydrateProps): HydrateResult {\n  const [isReadyToRender, setIsReadyToRender] = useState(typeof window === \"undefined\");\n\n  // console.log({ isReadyToRender });\n\n  // since lazy, the mdx content is hydrated inside requestIdleCallback,\n  // allowing the page to get to interactive quicker, but the mdx content to hydrate slower.\n  useEffect(() => {\n    const request = window.requestIdleCallback(() => {\n      setIsReadyToRender(true);\n    });\n    return () => window.cancelIdleCallback(request);\n  }, []);\n\n  const { Content, mod, error } = useMemo(() => {\n    try {\n      const result = runSync(compiledSource, {\n        frontmatter,\n        scope,\n        mdxOptions: {\n          useMDXComponents,\n        },\n      });\n\n      return { ...result };\n    } catch (error) {\n      return { Content: () => <div className=\"mdx-empty\" />, mod: {}, error: error as Error };\n    }\n  }, [compiledSource]);\n\n  if (!isReadyToRender) {\n    return {\n      // If not ready to render, return an empty div to preserve SSR'd markup\n      content: <div dangerouslySetInnerHTML={{ __html: \"\" }} suppressHydrationWarning />,\n      mod: {},\n    };\n  }\n\n  const content = components ? (\n    // wrap the Content with the MDXProvider in order to customize the standard markdown components\n    <MDXProvider components={components} disableParentContext={disableParentContext}>\n      <Content />\n    </MDXProvider>\n  ) : (\n    // no need to wrap the Content with the MDXProvider since there is no custom component provided\n    <Content />\n  );\n\n  // since lazy, need to wrap with a div to preserve the same markup structure that was SSR'd\n  return { content: <div>{content}</div>, mod, error };\n}\n"
  },
  {
    "path": "src/csr/idle-callback-polyfill.js",
    "content": "/**\n * Copyright (c) HashiCorp, Inc.\n * SPDX-License-Identifier: MPL-2.0\n *\n * reference to https://github.com/hashicorp/next-mdx-remote/blob/main/src/idle-callback-polyfill.js\n */\n\nif (typeof window !== \"undefined\") {\n  window.requestIdleCallback ||= function (cb) {\n    var start = Date.now();\n    return setTimeout(function () {\n      cb({\n        didTimeout: false,\n        timeRemaining: function () {\n          return Math.max(0, 50 - (Date.now() - start));\n        },\n      });\n    }, 1);\n  };\n\n  window.cancelIdleCallback ||= function (id) {\n    clearTimeout(id);\n  };\n}\n"
  },
  {
    "path": "src/csr/index.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nexport { hydrate } from \"./hydrate.js\";\nexport { hydrateLazy } from \"./hydrateLazy.js\";\nexport { hydrateAsync } from \"./hydrateAsync.js\";\nexport { MDXClient } from \"./MDXClient.js\";\nexport { MDXClientLazy } from \"./MDXClientLazy.js\";\nexport { MDXClientAsync } from \"./MDXClientAsync.js\";\n\nexport type {\n  HydrateProps,\n  HydrateResult,\n  MDXClientProps,\n  SerializeResult,\n  // below are experimantal\n  HydrateAsyncProps,\n  HydrateAsyncOptions,\n  MDXClientAsyncProps,\n  MDXClientAsyncOptions,\n} from \"./types.js\";\n\n// for who needs to use them without installing the \"@mdx-js/react\"\nexport { MDXProvider, useMDXComponents } from \"@mdx-js/react\";\n\n// for who needs to use them without installing the \"mdx/types\"\nexport type { MDXComponents, MDXContent, MDXProps, MDXModule } from \"mdx/types\";\n"
  },
  {
    "path": "src/csr/requestIdleCallback.d.ts",
    "content": "/**\n * Copyright (c) HashiCorp, Inc.\n * SPDX-License-Identifier: MPL-2.0\n *\n * reference to https://github.com/hashicorp/next-mdx-remote/blob/main/src/index.tsx\n * requestIdleCallback types found here: https://github.com/microsoft/TypeScript/issues/21309\n */\n\ntype RequestIdleCallbackHandle = number;\n\ntype RequestIdleCallbackOptions = {\n  timeout?: number;\n};\n\ntype RequestIdleCallbackDeadline = {\n  readonly didTimeout: boolean;\n  timeRemaining: () => number;\n};\n\ndeclare global {\n  interface Window {\n    requestIdleCallback: (\n      callback: (deadline: RequestIdleCallbackDeadline) => void,\n      opts?: RequestIdleCallbackOptions,\n    ) => RequestIdleCallbackHandle;\n    cancelIdleCallback: (handle: RequestIdleCallbackHandle) => void;\n  }\n}\n"
  },
  {
    "path": "src/csr/serialize.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport { serializeError } from \"serialize-error\";\n\nimport type { CompileMdxOptions } from \"../lib/types.js\";\nimport { passVfileDataIntoScope } from \"../lib/util.js\";\nimport { prepare } from \"../lib/prepare.js\";\nimport { compile } from \"../lib/compile.js\";\n\nimport type { SerializeResult, SerializeProps, SerializeOptions } from \"./types.js\";\n\nexport type { SerializeResult, SerializeProps, SerializeOptions };\n\n/**\n * compiles the MDX source.\n *\n * the compiled source can be passed into \"<MDXClient />\" or \"hydrate\" to be rendered on the client side (csr).\n *\n */\nexport async function serialize<\n  TFrontmatter extends Record<string, unknown> = Record<string, unknown>,\n  TScope extends Record<string, unknown> = Record<string, unknown>,\n>({\n  source,\n  options = {},\n}: SerializeProps<TScope>): Promise<SerializeResult<TFrontmatter, TScope>> {\n  const {\n    mdxOptions = {},\n    disableExports,\n    disableImports,\n    parseFrontmatter,\n    scope = {} as TScope,\n    vfileDataIntoScope,\n  } = options;\n\n  const { vfile, frontmatter } = prepare<TFrontmatter>(source, parseFrontmatter);\n\n  const compileMDXOptions: CompileMdxOptions = {\n    ...mdxOptions,\n    providerImportSource: \"#\", // important! doesn't matter \"@mdx-js/react\" since the outputFormat is \"function-body\"\n  };\n\n  try {\n    const { compiledSource } = await compile(vfile, {\n      mdxOptions: compileMDXOptions,\n      disableExports,\n      disableImports,\n    });\n\n    if (vfileDataIntoScope)\n      passVfileDataIntoScope(compiledSource.data, vfileDataIntoScope, scope);\n\n    return {\n      compiledSource: String(compiledSource),\n      frontmatter,\n      scope,\n    };\n  } catch (error: unknown) {\n    return {\n      error: serializeError(error) as Error,\n      frontmatter,\n      scope,\n    };\n  }\n}\n"
  },
  {
    "path": "src/csr/types.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport type {\n  CompileOptions as OriginalCompileOptions,\n  RunOptions as OriginalRunOptions,\n} from \"@mdx-js/mdx\";\nimport type { MDXComponents } from \"mdx/types\";\nimport type { Compatible } from \"vfile\";\n\nimport type { VfileDataIntoScope } from \"../lib/util.js\";\n\nexport type Prettify<T> = { [K in keyof T]: T[K] } & {};\n\nexport type SerializeProps<TScope extends Record<string, unknown> = Record<string, unknown>> = {\n  /**\n   * markdown or MDX source.\n   */\n  source: Compatible;\n  /**\n   * serialize options.\n   */\n  options?: SerializeOptions<TScope>;\n};\n\nexport type SerializeOptions<TScope extends Record<string, unknown> = Record<string, unknown>> =\n  {\n    /**\n     * These options are passed to the MDX compiler.\n     * See [the MDX docs.](https://github.com/mdx-js/mdx/blob/master/packages/mdx/index.js).\n     */\n    mdxOptions?: SerializeMdxOptions;\n    /**\n     * Whether or not strip out \"export\"s from MDX. Defaults to false, which means it does NOT strip out.\n     */\n    disableExports?: boolean;\n    /**\n     * Whether or not strip out \"import\"s from MDX. Defaults to false, which means it does NOT strip out.\n     */\n    disableImports?: boolean;\n    /**\n     * Indicates whether or not the frontmatter should be parsed out of the MDX. Defaults to false.\n     */\n    parseFrontmatter?: boolean;\n    /**\n     * An arbitrary object of data which will be supplied to the MDX.\n     *\n     * For example, in cases where you want to provide template variables to the MDX, like `my name is {name}`,\n     * you could provide scope as `{ name: \"Some name\" }`.\n     */\n    scope?: TScope;\n    /**\n     * Compiled source vfile.data may hold some extra information.\n     * Some field names in vfile.data may be needed to pass into the scope.\n     * If you need to change the name of the field, specify it { name: string; as: string } while passing.\n     * if the scope has the same key already, vfile.data overrides it.\n     */\n    vfileDataIntoScope?: VfileDataIntoScope;\n  };\n\ntype SerializeMdxOptions = Omit<\n  OriginalCompileOptions,\n  \"outputFormat\" | \"providerImportSource\"\n>;\n\nexport type SerializeResult<\n  TFrontmatter = Record<string, unknown>,\n  TScope = Record<string, unknown>,\n> = Prettify<\n  (\n    | {\n        /**\n         * The compiledSource, generated from the serialize function\n         */\n        compiledSource: string;\n      }\n    | {\n        /**\n         * The formatted MDX error object if compilation of the source is failed.\n         */\n        error: Error;\n      }\n  ) & {\n    /**\n     * If parseFrontmatter was set to true, contains any parsed frontmatter found in the MDX source.\n     */\n    frontmatter: TFrontmatter;\n    /**\n     * An arbitrary object of data which will be supplied to the MDX.\n     *\n     * For example, in cases where you want to provide template variables to the MDX, like `my name is {name}`,\n     * you could provide scope as `{ name: \"Some name\" }`.\n     */\n    scope: TScope;\n  }\n>;\n\nexport type HydrateProps = {\n  /**\n   * The compiledSource, generated from the serialize function\n   */\n  compiledSource: string;\n  /**\n   * If parseFrontmatter was set to true, contains any parsed frontmatter found in the MDX source.\n   */\n  frontmatter?: Record<string, unknown>;\n  /**\n   * Indicates whether or not the frontmatter should be parsed out of the MDX. Defaults to false.\n   */\n  scope?: Record<string, unknown>;\n  /**\n   * An object mapping names to React components.\n   * The key used will be the name accessible to MDX.\n   *\n   * For example: `{ ComponentName: Component }` will be accessible in the MDX as `<ComponentName/>`.\n   */\n  components?: MDXComponents;\n  /**\n   * Disable parent context\n   *\n   * @see https://github.com/mdx-js/mdx/blob/8f754f707207915bd34c3af8f9064e367c125a58/packages/react/lib/index.js#L70\n   */\n  disableParentContext?: boolean;\n};\n\nexport type HydrateResult = {\n  /**\n   * React element that renders the MDX compiled source using the component names mapping object.\n   */\n  content: React.JSX.Element;\n  /**\n   * An object which holds any value that is exported from the MDX file.\n   */\n  mod: Record<string, unknown> | { [key: string]: never };\n  /**\n   * The error object if construction of the compiled source is failed.\n   */\n  error?: Error;\n};\n\nexport type MDXClientProps = Prettify<\n  HydrateProps & {\n    onError?: React.ComponentType<{ error: Error }>;\n  }\n>;\n\nexport type HydrateAsyncProps = Prettify<\n  HydrateProps & {\n    /**\n     * hydrate options which is experimental for hydrateAsync only. It is INEFFECTIVE for hydrate and hydrateLazy.\n     */\n    options?: HydrateAsyncOptions;\n    /**\n     * fallback loading component\n     */\n    loading?: () => React.JSX.Element;\n  }\n>;\n\nexport type HydrateAsyncOptions = {\n  /**\n   * All RunOptions are pre-defined except the \"baseUrl\"\n   */\n  baseUrl?: OriginalRunOptions[\"baseUrl\"];\n};\n\nexport type MDXClientAsyncProps = Prettify<\n  HydrateAsyncProps & {\n    onError?: React.ComponentType<{ error: Error }>;\n  }\n>;\n\nexport type MDXClientAsyncOptions = HydrateAsyncOptions;\n"
  },
  {
    "path": "src/lib/compile.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport { compile as compileMDX, type CompileOptions as CompileMDXOptions } from \"@mdx-js/mdx\";\nimport type { VFile } from \"vfile\";\nimport type { PluggableList } from \"unified\";\nimport remarkMdxRemoveEsm from \"remark-mdx-remove-esm\";\n\nimport type { CompileOptions, CompileResult } from \"./types.js\";\nimport { createFormattedMDXError } from \"./util.js\";\n\n/**\n * composes an opinionated version of CompileOptions of the \"@mdx-js/mdx\"\n *\n * @param options CompileOptions\n * @returns CompileOptions of the \"@mdx-js/mdx\"\n */\nfunction composeCompileOptions(options: CompileOptions = {}): CompileMDXOptions {\n  const { mdxOptions = {}, disableImports, disableExports } = options;\n\n  const mdxRemoveEsmOptions = [disableExports && \"export\", disableImports && \"import\"];\n\n  const remarkPlugins: PluggableList = [\n    ...(mdxOptions.remarkPlugins || []),\n    [remarkMdxRemoveEsm, mdxRemoveEsmOptions],\n  ];\n\n  return {\n    ...mdxOptions,\n    remarkPlugins,\n    outputFormat: \"function-body\",\n  };\n}\n\n/**\n * compiles the vfile source via the compile of the \"@mdx-js/mdx\".\n *\n * returns the compiled source.\n */\nexport async function compile(vfile: VFile, options?: CompileOptions): Promise<CompileResult> {\n  try {\n    const compiledSource = await compileMDX(vfile, composeCompileOptions(options));\n\n    // for debugging\n    if (options?.debugCompiledSource) {\n      console.log(String(compiledSource));\n    }\n\n    // await new Promise((resolve) => setTimeout(resolve, 500));\n\n    return {\n      compiledSource,\n    };\n  } catch (error: any) {\n    throw createFormattedMDXError(error, String(vfile));\n  }\n}\n"
  },
  {
    "path": "src/lib/prepare.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport { type Compatible, VFile } from \"vfile\";\nimport { matter } from \"vfile-matter\";\n\nimport type { PrepareResult } from \"./types.js\";\n\n/**\n * turns the source into vfile, gets the fronmatter, strips it out from the vfile\n *\n * @param source markdown or MDX source\n * @param parseFrontmatter indicates whether or not the frontmatter should be parsed out of the source\n * @returns the frontmatter and stripped vfile\n */\nexport function prepare<TFrontmatter extends Record<string, unknown> = Record<string, unknown>>(\n  source: Compatible,\n  parseFrontmatter?: boolean,\n): PrepareResult<TFrontmatter> {\n  const vfile = looksLikeAVFile(source) ? source : new VFile(source);\n\n  // makes frontmatter available via vfile.data.matter\n  if (parseFrontmatter) matter(vfile, { strip: true });\n\n  const frontmatter = (vfile.data.matter ?? {}) as TFrontmatter;\n\n  return {\n    vfile,\n    frontmatter,\n  };\n}\n\n/**\n * taken from @mdx-js/mdx/lib/util/resolve-file-and-options.js\n */\nfunction looksLikeAVFile(value?: Compatible): value is VFile {\n  return Boolean(\n    value && typeof value === \"object\" && \"message\" in value && \"messages\" in value,\n  );\n}\n"
  },
  {
    "path": "src/lib/run.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport * as React from \"react\";\nimport * as jsxRuntime from \"react/jsx-runtime\";\nimport * as jsxDevRuntime from \"react/jsx-dev-runtime\";\nimport type { MDXModule } from \"mdx/types\";\nimport type { Fragment, Jsx, JsxDev } from \"@mdx-js/mdx\";\n\nimport type { RunOptions, RunResult } from \"./types.js\";\n\ntype JsxRuntime = {\n  Fragment: Fragment;\n  jsx: Jsx;\n  jsxs: Jsx;\n};\n\ntype JsxDevRuntime = {\n  Fragment: Fragment;\n  jsxDEV: JsxDev;\n};\n\n// TODO: use run and runSync function from \"@mdx-js/mdx\"\n\n/**\n * creates an object to be used for the function construction\n *\n * @param options RunOptions\n * @returns keys and values of the object\n */\nfunction prepareConstruction(options: RunOptions) {\n  const constructionScope = {\n    runMdxOptions: {\n      useMDXComponents: options.mdxOptions?.useMDXComponents,\n      baseUrl: options.mdxOptions?.baseUrl,\n      jsx: (jsxRuntime as JsxRuntime).jsx,\n      jsxs: (jsxRuntime as JsxRuntime).jsxs,\n      jsxDEV: (jsxDevRuntime as JsxDevRuntime).jsxDEV,\n      Fragment: (jsxRuntime as JsxRuntime).Fragment, // doesn't matter\n      React,\n    },\n    frontmatter: options.frontmatter,\n    ...options.scope,\n  };\n\n  return {\n    keys: Object.keys(constructionScope),\n    values: Object.values(constructionScope),\n  };\n}\n\n/**\n * parses and runs the javascript code syncronously in the compiled MDX source.\n */\nexport function runSync(compiledSource: string, options: RunOptions): RunResult {\n  const { keys, values } = prepareConstruction(options);\n\n  /* v8 ignore next */\n  const SyncFunction = function () {}.constructor;\n\n  // constructs the compiled source utilizing Reflect API with \"function constructor\"\n  const hydrateFn: typeof SyncFunction = Reflect.construct(\n    SyncFunction,\n    keys.concat(compiledSource),\n  );\n\n  const { default: Content, ...mod } = hydrateFn(...values) as MDXModule;\n\n  return { Content, mod };\n}\n\n/**\n * parses and runs the javascript code asyncronously in the compiled MDX source.\n */\nexport async function runAsync(\n  compiledSource: string,\n  options: RunOptions,\n): Promise<RunResult> {\n  const { keys, values } = prepareConstruction(options);\n\n  /* v8 ignore next */\n  const AsyncFunction = async function () {}.constructor;\n\n  // await new Promise((resolve) => setTimeout(resolve, 500));\n\n  // constructs the compiled source utilizing Reflect API with \"async function constructor\"\n  const hydrateFn: typeof AsyncFunction = Reflect.construct(\n    AsyncFunction,\n    keys.concat(compiledSource),\n  );\n\n  const { default: Content, ...mod } = await (hydrateFn(...values) as Promise<MDXModule>);\n\n  return { Content, mod };\n}\n"
  },
  {
    "path": "src/lib/types.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport type {\n  CompileOptions as OriginalCompileOptions,\n  RunOptions as OriginalRunOptions,\n} from \"@mdx-js/mdx\";\nimport type { MDXContent } from \"mdx/types\";\nimport type { Compatible, VFile } from \"vfile\";\n\nexport type PrepareProps = {\n  /**\n   * the markdown or mdx source.\n   */\n  source: Compatible;\n  /**\n   * Indicates whether or not the frontmatter should be parsed out of the MDX. Defaults to false.\n   */\n  parseFrontmatter?: boolean;\n};\n\nexport type PrepareResult<TFrontmatter = Record<string, unknown>> = {\n  /**\n   * the converted vFile of the source for compile function.\n   */\n  vfile: VFile;\n  /**\n   * the parsed frontmatter found in the MDX source if parseFrontmatter is set to true.\n   */\n  frontmatter: TFrontmatter;\n};\n\nexport type CompileOptions = {\n  /**\n   * These options are passed to the MDX compiler.\n   * See [the MDX docs.](https://github.com/mdx-js/mdx/blob/master/packages/mdx/index.js).\n   */\n  mdxOptions?: CompileMdxOptions;\n  /**\n   * Whether or not strip out \"export\"s from MDX. Defaults to false, which means it does NOT strip out.\n   */\n  disableExports?: boolean;\n  /**\n   * Whether or not strip out \"import\"s from MDX. Defaults to false, which means it does NOT strip out.\n   */\n  disableImports?: boolean;\n  /**\n   * for debugging\n   */\n  debugCompiledSource?: boolean;\n};\n\nexport type CompileMdxOptions = Omit<OriginalCompileOptions, \"outputFormat\">;\n\nexport type RunOptions = {\n  /**\n   * These options are passed to the MDX compiler.\n   * See [the MDX docs.](https://github.com/mdx-js/mdx/blob/master/packages/mdx/index.js).\n   */\n  mdxOptions?: RunMdxOptions;\n  /**\n   * the parsed frontmatter found in the MDX source if parseFrontmatter is set to true.\n   */\n  frontmatter: Record<string, unknown> | { [key: string]: never };\n  /**\n   * An arbitrary object of data which will be supplied to the MDX.\n   */\n  scope: Record<string, unknown> | { [key: string]: never };\n};\n\nexport type RunMdxOptions = Omit<OriginalRunOptions, \"Fragment\" | \"jsx\" | \"jsxDEV\" | \"jsxs\">;\n\nexport type CompileResult = {\n  /**\n   * compiled source produced by the serialize function, which contains js code in string format.\n   */\n  compiledSource: VFile;\n};\n\nexport type RunResult = {\n  /**\n   * A functional JSX component which renders the content of the MDX file.\n   */\n  Content: MDXContent;\n  /**\n   * An object which holds any value that is exported from the MDX file.\n   */\n  mod: {\n    [key: string]: unknown;\n  };\n};\n"
  },
  {
    "path": "src/lib/util.ts",
    "content": "/**\n * Copyright (c) HashiCorp, Inc.\n * SPDX-License-Identifier: MPL-2.0\n *\n * reference to https://github.com/hashicorp/next-mdx-remote/blob/main/src/format-mdx-error.ts\n *\n * improved the types\n */\n\nimport { codeFrameColumns, type SourceLocation } from \"@babel/code-frame\";\n\n/**\n * Attempt to parse position information from an error message originating from the MDX compiler.\n *\n * @param message error message\n * @returns the position of the error indicator\n */\nfunction parsePositionInformationFromErrorMessage(message: string): SourceLocation | undefined {\n  const positionInfoPattern = /\\d+:\\d+(-\\d+:\\d+)/g;\n\n  const match = message.match(positionInfoPattern);\n\n  if (!match) return;\n\n  // take the last match, that seems to be the most reliable source of the error.\n  const lastMatch = match.slice(-1)[0];\n\n  const [line, column] = lastMatch.split(\"-\")[0].split(\":\");\n\n  return {\n    start: {\n      line: Number.parseInt(line, 10),\n      column: Number.parseInt(column, 10),\n    },\n  };\n}\n\n/**\n * prints a nicely formatted error message from an error caught during MDX compilation.\n *\n * @param error Error caught from the mdx compiler\n * @param source Raw MDX string\n * @returns Error\n */\nexport function createFormattedMDXError(error: Error, source: string): Error {\n  const position =\n    \"position\" in error && Boolean(error.position)\n      ? (error.position as SourceLocation)\n      : parsePositionInformationFromErrorMessage(error.message);\n\n  const codeFrames =\n    position?.start?.line !== undefined\n      ? codeFrameColumns(source, position, { linesAbove: 2, linesBelow: 2 })\n      : \"\";\n\n  const formattedError = new Error(`[next-mdx-remote-client] error compiling MDX:\n${error.message}\n${codeFrames ? \"\\n\" + codeFrames + \"\\n\" : \"\"}\nMore information: https://mdxjs.com/docs/troubleshooting-mdx`);\n\n  // commented since React Flight throws an error if error stack is mutated\n  // when the error object is a prop in a rsc\n  // formattedError.stack = \"\";\n\n  return formattedError;\n}\n\n/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nexport type VfileDataIntoScope =\n  | true // all fields\n  | string // one specific field\n  | { name: string; as: string } // one specific field but change the key as\n  | Array<string | { name: string; as: string }>; // more than one field\n\n/**\n * copies some fields of vfile.data into scope by mutating the scope\n * pay attention that it provides reference copy for objects (including arrays)\n *\n * @param data vfile.data from copied\n * @param vfileDataIntoScope refers the fields of vfile.data, some or all (if true)\n * @param scope an object to copied in a mutable way\n */\nexport function passVfileDataIntoScope(\n  data: Record<string, unknown>,\n  vfileDataIntoScope: VfileDataIntoScope,\n  scope: Record<string, unknown>,\n): undefined {\n  if (typeof vfileDataIntoScope === \"boolean\") {\n    Object.entries(data).forEach(([key, value]) => {\n      scope[key] = value;\n    });\n  } else if (typeof vfileDataIntoScope === \"string\") {\n    scope[vfileDataIntoScope] = data[vfileDataIntoScope];\n  } else if (Array.isArray(vfileDataIntoScope)) {\n    vfileDataIntoScope.forEach((field) => {\n      if (typeof field === \"string\") {\n        scope[field] = data[field];\n      } else if (\n        // type-coverage:ignore-next-line\n        Object.prototype.hasOwnProperty.call(field, \"name\") &&\n        // type-coverage:ignore-next-line\n        Object.prototype.hasOwnProperty.call(field, \"as\")\n      ) {\n        scope[field.as] = data[field.name];\n      }\n    });\n  } else if (\n    // type-coverage:ignore-next-line\n    Object.prototype.hasOwnProperty.call(vfileDataIntoScope, \"name\") &&\n    // type-coverage:ignore-next-line\n    Object.prototype.hasOwnProperty.call(vfileDataIntoScope, \"as\")\n  ) {\n    scope[vfileDataIntoScope.as] = data[vfileDataIntoScope.name];\n  }\n}\n"
  },
  {
    "path": "src/rsc/MDXRemote.tsx",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport { evaluate } from \"./evaluate.js\";\nimport type { MDXRemoteProps } from \"./types.js\";\n\n/**\n * renders the content as a react server component (rsc), which is provided by the \"evaluate\" function\n */\nexport async function MDXRemote(props: MDXRemoteProps): Promise<React.JSX.Element> {\n  const { onError: ErrorComponent, ...rest } = props;\n\n  const { content, error } = await evaluate(rest);\n\n  if (error && !ErrorComponent) throw error;\n\n  if (error && ErrorComponent) return <ErrorComponent error={error} />;\n\n  return content;\n}\n"
  },
  {
    "path": "src/rsc/evaluate.tsx",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport { compile } from \"../lib/compile.js\";\nimport { prepare } from \"../lib/prepare.js\";\nimport { runSync, runAsync } from \"../lib/run.js\";\nimport { passVfileDataIntoScope } from \"../lib/util.js\";\n\nimport type { EvaluateProps, EvaluateResult } from \"./types.js\";\n\n/**\n * \"compiles\" the MDX source and \"runs\" the javascript code in the compiled source, so it basically \"evaluates\" the MDX.\n *\n * returns the frontmatter, exported object and the react server component to be rendered on the server.\n *\n */\nexport async function evaluate<\n  TFrontmatter extends Record<string, unknown> = Record<string, unknown>,\n  TScope extends Record<string, unknown> = Record<string, unknown>,\n>({\n  source,\n  options = {},\n  components = {},\n}: EvaluateProps<TScope>): Promise<EvaluateResult<TFrontmatter, TScope>> {\n  const {\n    mdxOptions = {},\n    disableExports,\n    disableImports,\n    scope = {} as TScope,\n    parseFrontmatter,\n    vfileDataIntoScope,\n    debug,\n  } = options;\n\n  const { vfile, frontmatter } = prepare<TFrontmatter>(source, parseFrontmatter);\n\n  const { baseUrl, ...compileMDXOptions } = mdxOptions;\n\n  try {\n    const { compiledSource } = await compile(vfile, {\n      mdxOptions: compileMDXOptions,\n      disableExports,\n      disableImports,\n      debugCompiledSource: debug?.compiledSource,\n    });\n\n    if (vfileDataIntoScope)\n      passVfileDataIntoScope(compiledSource.data, vfileDataIntoScope, scope);\n\n    // This check is necessary otherwise \"await\" expression in the compiledSource throws a syntax error\n    const { Content, mod } = disableImports\n      ? runSync(String(compiledSource), {\n          frontmatter,\n          scope,\n        })\n      : await runAsync(String(compiledSource), {\n          mdxOptions: { baseUrl },\n          frontmatter,\n          scope,\n        });\n\n    return {\n      content: <Content components={components} />,\n      mod,\n      frontmatter,\n      scope,\n    };\n  } catch (error: unknown) {\n    return {\n      content: <div className=\"mdx-empty\" />,\n      mod: {},\n      frontmatter: frontmatter as TFrontmatter,\n      scope,\n      error: error as Error,\n    };\n  }\n}\n"
  },
  {
    "path": "src/rsc/index.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nexport { MDXRemote } from \"./MDXRemote.js\";\nexport { evaluate } from \"./evaluate.js\";\n\nexport type {\n  MDXRemoteProps,\n  MDXRemoteOptions,\n  EvaluateProps,\n  EvaluateOptions,\n  EvaluateResult,\n} from \"./types.js\";\n\n// for who needs to use them without installing the \"mdx/types\"\nexport type { MDXComponents, MDXContent, MDXProps, MDXModule } from \"mdx/types\";\n"
  },
  {
    "path": "src/rsc/types.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport type { EvaluateOptions as OriginalEvaluateOptions } from \"@mdx-js/mdx\";\nimport type { MDXComponents } from \"mdx/types\";\nimport type { Compatible } from \"vfile\";\n\nimport type { VfileDataIntoScope } from \"../lib/util.js\";\n\nexport type Prettify<T> = { [K in keyof T]: T[K] } & {};\n\nexport type EvaluateProps<TScope extends Record<string, unknown> = Record<string, unknown>> = {\n  /**\n   * markdown or MDX source.\n   */\n  source: Compatible;\n  /**\n   * evaluate options.\n   */\n  options?: EvaluateOptions<TScope>;\n  /**\n   * An object mapping names to React components.\n   * The key used will be the name accessible to MDX.\n   *\n   * For example: `{ ComponentName: Component }` will be accessible in the MDX as `<ComponentName/>`.\n   */\n  components?: MDXComponents;\n};\n\nexport type EvaluateOptions<TScope extends Record<string, unknown> = Record<string, unknown>> =\n  {\n    /**\n     * These options are passed to the MDX compiler.\n     * See [the MDX docs.](https://github.com/mdx-js/mdx/blob/master/packages/mdx/index.js).\n     */\n    mdxOptions?: EvaluateMdxOptions;\n    /**\n     * Whether or not strip out \"export\"s from MDX. Defaults to false, which means it does NOT strip out.\n     */\n    disableExports?: boolean;\n    /**\n     * Whether or not strip out \"import\"s from MDX. Defaults to false, which means it does NOT strip out.\n     */\n    disableImports?: boolean;\n    /**\n     * Indicates whether or not the frontmatter should be parsed out of the MDX. Defaults to false.\n     */\n    parseFrontmatter?: boolean;\n    /**\n     * An arbitrary object of data which will be supplied to the MDX.\n     *\n     * For example, in cases where you want to provide template variables to the MDX, like `my name is {name}`,\n     * you could provide scope as `{ name: \"Some name\" }`.\n     */\n    scope?: TScope;\n    /**\n     * Compiled source vfile.data may hold some extra information.\n     * Some field names in vfile.data may be needed to pass into the scope.\n     * If you need to change the name of the field, specify it { name: string; as: string } while passing.\n     * if the scope has the same key already, vfile.data overrides it.\n     */\n    vfileDataIntoScope?: VfileDataIntoScope;\n    /**\n     * for debugging\n     */\n    debug?: {\n      compiledSource?: boolean;\n    };\n  };\n\ntype EvaluateMdxOptions = Omit<\n  OriginalEvaluateOptions,\n  | \"Fragment\"\n  | \"jsx\"\n  | \"jsxs\"\n  | \"jsxDEV\"\n  | \"useMDXComponents\"\n  | \"providerImportSource\"\n  | \"outputFormat\"\n>;\n\nexport type EvaluateResult<\n  TFrontmatter = Record<string, unknown>,\n  TScope = Record<string, unknown>,\n> = {\n  /**\n   * React element that renders the MDX source using the component names mapping object.\n   */\n  content: React.JSX.Element;\n  /**\n   * An object which holds any value that is exported from the MDX file.\n   */\n  mod: Record<string, unknown> | { [key: string]: never };\n  /**\n   * the parsed frontmatter found in the MDX source if parseFrontmatter is set to true.\n   */\n  frontmatter: TFrontmatter;\n  /**\n   * The scope can be mutated during the compile process, and you may want to get it back.\n   *\n   */\n  scope: TScope;\n  /**\n   * The error object if construction of the compiled source is failed, or\n   * compilation of the source is failed due to MDX syntax error.\n   */\n  error?: Error;\n};\n\nexport type MDXRemoteProps = Prettify<\n  EvaluateProps & {\n    onError?: React.ComponentType<{ error: Error }>;\n  }\n>;\n\nexport type MDXRemoteOptions = EvaluateOptions;\n"
  },
  {
    "path": "src/utils/getFrontmatter.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport { type Compatible, VFile } from \"vfile\";\nimport { matter } from \"vfile-matter\";\n\n/**\n * gets the fronmatter and the stripped source\n *\n * @param source markdown or MDX source\n * @returns fronmatter and stripped source. If no matter is found, the frontmatter is an empty object.\n */\nexport function getFrontmatter<TFrontmatter extends Record<string, unknown>>(\n  source: Compatible,\n): { frontmatter: TFrontmatter; strippedSource: string } {\n  const vfile = new VFile(source);\n\n  matter(vfile, { strip: true });\n\n  const frontmatter = vfile.data.matter as TFrontmatter;\n\n  // If no matter is found, the file.data.matter is an empty object ({}).\n  return { frontmatter, strippedSource: String(vfile) };\n}\n"
  },
  {
    "path": "src/utils/index.ts",
    "content": "/**\n * Copyright (c) @talatkuyuk AKA @ipikuka\n * SPDX-License-Identifier: MPL-2.0\n */\n\n// for who needs to parse and get the fronmatter and stripped source\nexport { getFrontmatter } from \"./getFrontmatter.js\";\n"
  },
  {
    "path": "tests/ErrorBoundaryClassic.jsx",
    "content": "import React from \"react\";\n\nclass ErrorBoundary extends React.Component {\n  constructor(props) {\n    super(props);\n\n    // Define a state variable to track whether is an error or not\n    this.state = { hasError: false };\n  }\n\n  // eslint-disable-next-line no-unused-vars\n  static getDerivedStateFromError(error) {\n    // Update state so the next render will show the fallback UI\n\n    return { hasError: true };\n  }\n\n  componentDidCatch(error, errorInfo) {\n    console.log({ error, errorInfo });\n  }\n\n  render() {\n    // Check if the error is thrown\n    if (this.state.hasError) {\n      // You can render any custom fallback UI\n      return (\n        <div>\n          <h2>Oops, there is an error!</h2>\n          <button type=\"button\" onClick={() => this.setState({ hasError: false })}>\n            Try again?\n          </button>\n        </div>\n      );\n    }\n\n    // Return children components in case of no error\n\n    return this.props.children;\n  }\n}\n\nexport default ErrorBoundary;\n"
  },
  {
    "path": "tests/ErrorBoundaryForTests.tsx",
    "content": "import React from \"react\";\n\ninterface ErrorBoundaryProps {\n  fallback: React.ReactNode;\n  onError?: (error: Error, info: React.ErrorInfo) => void;\n  children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n  hasError: boolean;\n  error: Error | null;\n}\n\n/**\n * a TypeScript-based ErrorBoundary that gives a reliable runtime error\n * since React will stop propagating those “uncatchable” render errors once they’re caught by boundary\n */\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n  constructor(props: ErrorBoundaryProps) {\n    super(props);\n    this.state = { hasError: false, error: null };\n  }\n\n  static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n    return { hasError: true, error };\n  }\n\n  componentDidCatch(error: Error, info: React.ErrorInfo) {\n    this.props.onError?.(error, info);\n  }\n\n  render() {\n    if (this.state.hasError) {\n      return this.props.fallback;\n    }\n    return this.props.children;\n  }\n}\n"
  },
  {
    "path": "tests/context/ExampleForm.mjs",
    "content": "import { useId, useState } from \"react\";\n\nfunction ExampleForm() {\n  const id = useId(); // Generates a unique ID\n  const [name, setName] = useState(\"\");\n\n  return (\n    <div>\n      <label htmlFor={`${id}-name`}>Enter your name:</label>\n      <input\n        id={`${id}-name`}\n        type=\"text\"\n        value={name}\n        onChange={(e) => setName(e.target.value)}\n      />\n      <p>Hello, {name || \"stranger\"}!</p>\n    </div>\n  );\n}\n\nexport default ExampleForm;\n"
  },
  {
    "path": "tests/context/ExampleFormTransformedAutomatic.mjs",
    "content": "import { useId, useState } from \"react\";\nimport { jsx as _jsx, jsxs as _jsxs } from \"react/jsx-runtime\";\nfunction ExampleForm() {\n  const id = useId(); // Generates a unique ID\n  const [name, setName] = useState(\"\");\n  return /*#__PURE__*/ _jsxs(\"div\", {\n    children: [\n      /*#__PURE__*/ _jsx(\"label\", {\n        htmlFor: `${id}-name`,\n        children: \"Enter your name:\",\n      }),\n      /*#__PURE__*/ _jsx(\"input\", {\n        id: `${id}-name`,\n        type: \"text\",\n        value: name,\n        onChange: (e) => setName(e.target.value),\n      }),\n      /*#__PURE__*/ _jsxs(\"p\", {\n        children: [\"Hello, \", name || \"stranger\", \"!\"],\n      }),\n    ],\n  });\n}\nexport default ExampleForm;\n"
  },
  {
    "path": "tests/context/ExampleFormTransformedClassic.mjs",
    "content": "import React, { useId, useState } from \"react\";\nfunction ExampleForm() {\n  const id = useId(); // Generates a unique ID\n  const [name, setName] = useState(\"\");\n  return /*#__PURE__*/ React.createElement(\n    \"div\",\n    null,\n    /*#__PURE__*/ React.createElement(\n      \"label\",\n      {\n        htmlFor: `${id}-name`,\n      },\n      \"Enter your name:\",\n    ),\n    /*#__PURE__*/ React.createElement(\"input\", {\n      id: `${id}-name`,\n      type: \"text\",\n      value: name,\n      onChange: (e) => setName(e.target.value),\n    }),\n    /*#__PURE__*/ React.createElement(\"p\", null, \"Hello, \", name || \"stranger\", \"!\"),\n  );\n}\nexport default ExampleForm;\n"
  },
  {
    "path": "tests/context/HelloDave.mjs",
    "content": "import * as ReactModule from \"react\";\n\nexport default function HelloDave({ runtimeProps, ...props }) {\n  const { React = ReactModule } = runtimeProps;\n\n  if (!React) return \"<HelloDave /> component doesn't work due to missing `React` instance !\";\n\n  const id = React.useId();\n\n  return React.createElement(\"div\", props, `Hello, Dave! Your id is ${id}`);\n}\n"
  },
  {
    "path": "tests/context/components.js",
    "content": "// the same test file taken from @mdx-js/mdx test files iot be inline with\n\nimport React from \"react\";\n\n/**\n * @param {Readonly<React.JSX.IntrinsicElements['span']>} props\n *   Props\n * @returns\n *   `span` element.\n */\nexport function Pill(props) {\n  return React.createElement(\"span\", { ...props, style: { color: \"blue\" } });\n}\n\n/**\n * @param {Readonly<React.JSX.IntrinsicElements['div']>} props\n *   Props\n * @returns\n *   `div` element.\n */\nexport function Layout(props) {\n  return React.createElement(\"div\", { ...props, style: { color: \"red\" } });\n}\n\nexport default Layout;\n"
  },
  {
    "path": "tests/context/data.js",
    "content": "// the same test file taken from @mdx-js/mdx test files iot be inline with\n\n/**\n * Number.\n */\nexport const number = 3.14;\n\n/**\n * Object.\n */\nexport const object = { a: 1, b: 2 };\n\n/**\n * Array.\n */\nexport const array = [1, 2];\n\n/**\n * Number.\n */\nexport default 2 * number;\n"
  },
  {
    "path": "tests/test.MDXClient.spec.tsx",
    "content": "import { describe, expect, test } from \"vitest\";\n\nimport ReactDOMServer from \"react-dom/server\";\n\nimport { MDXClient } from \"../src/csr\";\nimport { serialize } from \"../src/csr/serialize.js\";\n\nimport { ErrorBoundary } from \"./ErrorBoundaryForTests.js\";\n\ndescribe(\"MDXClient\", () => {\n  test(\"works\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi <Test name={bar} />\",\n      options: {\n        scope: {\n          bar: \"ipikuka\",\n        },\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    const components = {\n      Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n    };\n\n    expect(\n      ReactDOMServer.renderToStaticMarkup(<MDXClient components={components} {...mdxSource} />),\n    ).toMatchInlineSnapshot(`\"<p>hi <strong>ipikuka</strong></p>\"`);\n  });\n\n  test(\"works with catchable errors\", async () => {\n    const mdxSource = await serialize({\n      source: \"import x from 'y'\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    const onError = ({ error }: { error: Error }) => {\n      return <div>{error.message}</div>;\n    };\n\n    expect(() =>\n      ReactDOMServer.renderToStaticMarkup(<MDXClient {...mdxSource} />),\n    ).toThrowErrorMatchingInlineSnapshot(\n      `[SyntaxError: await is only valid in async functions and the top level bodies of modules]`,\n    );\n\n    expect(\n      ReactDOMServer.renderToStaticMarkup(<MDXClient {...mdxSource} onError={onError} />),\n    ).toMatchInlineSnapshot(\n      `\"<div>await is only valid in async functions and the top level bodies of modules</div>\"`,\n    );\n  });\n\n  test(\"has problem working with uncatchable errors\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi {bar}\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    const onError = ({ error }: { error: Error }) => {\n      return <div>{error.message}</div>;\n    };\n\n    // throws error only during render\n    expect(() =>\n      ReactDOMServer.renderToStaticMarkup(<MDXClient {...mdxSource} />),\n    ).toThrowErrorMatchingInlineSnapshot(`[ReferenceError: bar is not defined]`);\n\n    // even the ErrorBoundary couldn't catch the error, don't know why?\n    expect(() =>\n      ReactDOMServer.renderToStaticMarkup(\n        <ErrorBoundary\n          fallback={<div data-testid=\"mdx-error\">Something went wrong</div>}\n          onError={(error) => {\n            console.log(error);\n          }}\n        >\n          <MDXClient {...mdxSource} onError={onError} />\n        </ErrorBoundary>,\n      ),\n    ).toThrowErrorMatchingInlineSnapshot(`[ReferenceError: bar is not defined]`);\n  });\n});\n"
  },
  {
    "path": "tests/test.MDXClientAsync.esm.spec.tsx",
    "content": "import { vi, describe, expect, test } from \"vitest\";\n\nimport type { ComponentProps } from \"react\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\n\nimport { MDXClientAsync, type MDXComponents } from \"../src/csr\";\nimport { serialize } from \"../src/csr/serialize.js\";\n\nimport { ErrorBoundary } from \"./ErrorBoundaryForTests.js\";\n\ndescribe(\"MDXClientAsync\", () => {\n  const LoadingComponent = () => {\n    return <div data-testid=\"mdx-loading\">loading</div>;\n  };\n\n  const ErrorComponent = ({ error }: { error: Error }) => {\n    return <div data-testid=\"mdx-error\">{error.message}</div>;\n  };\n\n  const mdxComponents = {\n    Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n    wrapper: (props: ComponentProps<\"div\"> & { components: MDXComponents }) => {\n      const { components, children, ...rest } = props; // eslint-disable-line @typescript-eslint/no-unused-vars\n      return (\n        <div data-testid=\"mdx-layout\" {...rest}>\n          {children}\n        </div>\n      );\n    },\n  };\n\n  test(\"works as expected\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi <Test name={bar} />\",\n      options: {\n        scope: {\n          bar: \"ipikuka\",\n        },\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    render(\n      <MDXClientAsync\n        components={mdxComponents}\n        {...mdxSource}\n        loading={LoadingComponent}\n        onError={ErrorComponent}\n      />,\n    );\n\n    const loadingDiv = screen.queryByTestId(\"mdx-loading\");\n    expect(loadingDiv?.innerHTML).toEqual(\"loading\");\n\n    await waitFor(() => {\n      const layoutDiv = screen.queryByTestId(\"mdx-layout\");\n      expect(layoutDiv?.innerHTML).toContain(\"<p>hi <strong>ipikuka</strong></p>\");\n    });\n  });\n\n  test(\"works with catchable errors 1\", async () => {\n    const mdxSource = await serialize({\n      source: \"import x from 'y'\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    render(\n      <MDXClientAsync\n        components={mdxComponents}\n        {...mdxSource}\n        loading={LoadingComponent}\n        onError={ErrorComponent}\n      />,\n    );\n\n    const loadingDiv = screen.queryByTestId(\"mdx-loading\");\n    expect(loadingDiv?.innerHTML).toEqual(\"loading\");\n\n    await screen.findByTestId(\"mdx-error\", {}, { timeout: 2000 });\n    expect(screen.queryByTestId(\"mdx-error\")).toMatchInlineSnapshot(`\n      <div\n        data-testid=\"mdx-error\"\n      >\n        Unexpected missing \\`options.baseUrl\\` needed to support \\`export … from\\`, \\`import\\`, or \\`import.meta.url\\` when generating \\`function-body\\`\n      </div>\n    `);\n  });\n\n  test(\"works with catchable errors 2\", async () => {\n    const mdxSource = await serialize({\n      source: \"import x from 'y'\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    render(\n      <MDXClientAsync\n        components={mdxComponents}\n        {...mdxSource}\n        loading={LoadingComponent}\n        onError={ErrorComponent}\n        options={{ baseUrl: \"https://gist.githubusercontent.com/Bar.mjs\" }}\n      />,\n    );\n\n    const loadingDiv = screen.queryByTestId(\"mdx-loading\");\n    expect(loadingDiv?.innerHTML).toEqual(\"loading\");\n\n    await screen.findByTestId(\"mdx-error\", {}, { timeout: 2000 });\n    expect(screen.queryByTestId(\"mdx-error\")?.innerHTML).toContain(\n      \"Cannot find package 'y' imported from\",\n    );\n  });\n\n  test(\"uncatchable runtime error\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi {bar}\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    const consoleErrorSpy = vi.spyOn(console, \"error\").mockImplementation(() => {});\n\n    const onError = vi.fn();\n\n    render(\n      <ErrorBoundary\n        fallback={<div data-testid=\"mdx-error\">Something went wrong</div>}\n        onError={onError}\n      >\n        <MDXClientAsync\n          components={mdxComponents}\n          {...mdxSource}\n          loading={LoadingComponent}\n          onError={ErrorComponent}\n        />\n      </ErrorBoundary>,\n    );\n\n    const loadingDiv = screen.queryByTestId(\"mdx-loading\");\n    expect(loadingDiv).toHaveTextContent(\"loading\");\n    expect(loadingDiv?.innerHTML).toEqual(\"loading\");\n\n    await waitFor(() =>\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          name: \"ReferenceError\",\n          message: expect.stringContaining(\"bar is not defined\"),\n        }),\n        expect.objectContaining({\n          componentStack: expect.stringContaining(\"_createMdxContent\"),\n        }),\n      ),\n    );\n\n    const errorDiv = await screen.findByTestId(\"mdx-error\", {}, { timeout: 2000 });\n    expect(errorDiv).toHaveTextContent(\"Something went wrong\");\n    expect(errorDiv.innerHTML).toEqual(\"Something went wrong\");\n\n    expect(consoleErrorSpy).toHaveBeenCalled();\n    consoleErrorSpy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "tests/test.MDXClientLazy.spec.tsx",
    "content": "import { vi, describe, expect, test } from \"vitest\";\n\nimport type { ComponentProps } from \"react\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\n\nimport { MDXClientLazy, type MDXComponents } from \"../src/csr\";\nimport { serialize } from \"../src/csr/serialize.js\";\n\nimport { ErrorBoundary } from \"./ErrorBoundaryForTests.js\";\n\ndescribe(\"MDXClientLazy\", () => {\n  const ErrorComponent = ({ error }: { error: Error }) => {\n    return <div data-testid=\"mdx-error\">{error.message}</div>;\n  };\n\n  const mdxComponents = {\n    Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n    wrapper: (props: ComponentProps<\"div\"> & { components: MDXComponents }) => {\n      const { components, children, ...rest } = props; // eslint-disable-line @typescript-eslint/no-unused-vars\n      return (\n        <div data-testid=\"mdx-layout\" {...rest}>\n          {children}\n        </div>\n      );\n    },\n  };\n\n  test(\"works as expected\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi <Test name={bar} />\",\n      options: {\n        scope: {\n          bar: \"ipikuka\",\n        },\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    render(\n      <MDXClientLazy components={mdxComponents} {...mdxSource} onError={ErrorComponent} />,\n    );\n\n    await waitFor(() => {\n      const layoutDiv = screen.queryByTestId(\"mdx-layout\");\n      expect(layoutDiv?.innerHTML).toContain(\"<p>hi <strong>ipikuka</strong></p>\");\n    });\n  });\n\n  test(\"works with catchable errors\", async () => {\n    const mdxSource = await serialize({\n      source: \"import x from 'y'\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    render(\n      <MDXClientLazy components={mdxComponents} {...mdxSource} onError={ErrorComponent} />,\n    );\n\n    const errorDiv = await screen.findByTestId(\"mdx-error\", {}, { timeout: 2000 });\n\n    expect(errorDiv).toMatchInlineSnapshot(`\n      <div\n        data-testid=\"mdx-error\"\n      >\n        await is only valid in async functions and the top level bodies of modules\n      </div>\n    `);\n  });\n\n  test(\"uncatchable runtime error\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi {bar}\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    const consoleErrorSpy = vi.spyOn(console, \"error\").mockImplementation(() => {});\n\n    const onError = vi.fn();\n\n    render(\n      <ErrorBoundary\n        fallback={<div data-testid=\"mdx-error\">Something went wrong</div>}\n        onError={onError}\n      >\n        <MDXClientLazy components={mdxComponents} {...mdxSource} onError={ErrorComponent} />\n      </ErrorBoundary>,\n    );\n\n    await waitFor(() =>\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          name: \"ReferenceError\",\n          message: expect.stringContaining(\"bar is not defined\"),\n        }),\n        expect.objectContaining({\n          componentStack: expect.stringContaining(\"_createMdxContent\"),\n        }),\n      ),\n    );\n\n    const errorDiv = await screen.findByTestId(\"mdx-error\");\n    expect(errorDiv).toHaveTextContent(\"Something went wrong\");\n\n    expect(consoleErrorSpy).toHaveBeenCalled();\n    consoleErrorSpy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "tests/test.MDXProvider.spec.tsx",
    "content": "import { describe, expect, test } from \"vitest\";\n\nimport React from \"react\";\nimport ReactDOMServer from \"react-dom/server\";\n\nimport { serialize } from \"../src/csr/serialize.js\";\nimport { MDXClient, MDXProvider, type MDXComponents } from \"../src/csr/index.js\";\n\n// the test cases are taken from `@mdx-js/react`for reference\ndescribe(\"MDXProvider\", () => {\n  test(\"should support `components` with `MDXProvider`\", async () => {\n    const mdxSource = await serialize({\n      source: \"# hi\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(\n      ReactDOMServer.renderToStaticMarkup(\n        <MDXProvider\n          components={{\n            h1(properties) {\n              return <h1 style={{ color: \"tomato\" }} {...properties} />;\n            },\n          }}\n        >\n          <MDXClient {...mdxSource} />\n        </MDXProvider>,\n      ),\n      '<h1 style=\"color:tomato\">hi</h1>',\n    );\n  });\n\n  test(\"should support `wrapper` in `components`\", async () => {\n    const mdxSource = await serialize({\n      source: \"# hi\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    const CustomWrapper = (\n      props: React.JSX.IntrinsicElements[\"div\"] & { components: MDXComponents },\n    ) => {\n      const { components, ...rest } = props; // eslint-disable-line @typescript-eslint/no-unused-vars\n      return <div id=\"layout\" {...rest} />;\n    };\n\n    expect(\n      ReactDOMServer.renderToStaticMarkup(\n        <MDXProvider\n          components={{\n            wrapper: CustomWrapper,\n          }}\n        >\n          <MDXClient {...mdxSource} />\n        </MDXProvider>,\n      ),\n      '<div id=\"layout\"><h1>hi</h1></div>',\n    );\n  });\n\n  test(\"should combine components in nested `MDXProvider`s\", async () => {\n    const mdxSource = await serialize({\n      source: \"# hi\\n## hello\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(\n      ReactDOMServer.renderToStaticMarkup(\n        <MDXProvider\n          components={{\n            h1(properties) {\n              return <h1 style={{ color: \"tomato\" }} {...properties} />;\n            },\n            h2(properties) {\n              return <h2 style={{ color: \"rebeccapurple\" }} {...properties} />;\n            },\n          }}\n        >\n          <MDXProvider\n            components={{\n              h2(properties) {\n                return <h2 style={{ color: \"papayawhip\" }} {...properties} />;\n              },\n            }}\n          >\n            <MDXClient {...mdxSource} />\n          </MDXProvider>\n        </MDXProvider>,\n      ),\n      '<h1 style=\"color:tomato\">hi</h1>\\n<h2 style=\"color:papayawhip\">hello</h2>',\n    );\n  });\n\n  test(\"should support components as a function\", async () => {\n    const mdxSource = await serialize({\n      source: \"# hi\\n## hello\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(\n      ReactDOMServer.renderToStaticMarkup(\n        <MDXProvider\n          components={{\n            h1(properties) {\n              return <h1 style={{ color: \"tomato\" }} {...properties} />;\n            },\n            h2(properties) {\n              return <h2 style={{ color: \"rebeccapurple\" }} {...properties} />;\n            },\n          }}\n        >\n          <MDXProvider\n            components={function () {\n              return {\n                h2(properties) {\n                  return <h2 style={{ color: \"papayawhip\" }} {...properties} />;\n                },\n              };\n            }}\n          >\n            <MDXClient {...mdxSource} />\n          </MDXProvider>\n        </MDXProvider>,\n      ),\n      '<h1>hi</h1>\\n<h2 style=\"color:papayawhip\">hello</h2>',\n    );\n  });\n\n  test(\"should support a `disableParentContext` prop (sandbox)\", async () => {\n    const mdxSource = await serialize({\n      source: \"# hi\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(\n      ReactDOMServer.renderToStaticMarkup(\n        <MDXProvider\n          components={{\n            h1(properties) {\n              return <h1 style={{ color: \"tomato\" }} {...properties} />;\n            },\n          }}\n        >\n          <MDXClient {...mdxSource} disableParentContext />\n        </MDXProvider>,\n      ),\n      \"<h1>hi</h1>\",\n    );\n  });\n\n  test(\"should support a `disableParentContext` *and* `components` as a function\", async () => {\n    const mdxSource = await serialize({\n      source: \"# hi\\n## hello\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(\n      ReactDOMServer.renderToStaticMarkup(\n        <MDXProvider\n          components={{\n            h1(properties) {\n              return <h1 style={{ color: \"tomato\" }} {...properties} />;\n            },\n          }}\n        >\n          <MDXProvider\n            disableParentContext\n            components={function () {\n              return {\n                h2(properties) {\n                  return <h2 style={{ color: \"papayawhip\" }} {...properties} />;\n                },\n              };\n            }}\n          >\n            <MDXClient {...mdxSource} />\n          </MDXProvider>\n        </MDXProvider>,\n      ),\n      '<h1>hi</h1>\\n<h2 style=\"color:papayawhip\">hello</h2>',\n    );\n  });\n});\n"
  },
  {
    "path": "tests/test.MDXRemote.esm.spec.tsx",
    "content": "import { describe, expect, test } from \"vitest\";\n\nimport React from \"react\";\nimport ReactDOMServer from \"react-dom/server\";\nimport { render, screen } from \"@testing-library/react\";\n\nimport { MDXRemote, type MDXRemoteOptions, type MDXComponents } from \"../src/rsc\";\n\nimport { renderToStringFromStream } from \"./utils\";\n\ndescribe(\"MDXRemote\", () => {\n  // const LoadingComponent = () => {\n  //   return <div data-testid=\"mdx-loading\">loading</div>;\n  // };\n\n  const ErrorComponent = ({ error }: { error: Error }) => {\n    return <div data-testid=\"mdx-error\">{error.message}</div>;\n  };\n\n  const mdxComponents = {\n    Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n    wrapper: (props: React.ComponentProps<\"div\"> & { components: MDXComponents }) => {\n      const { components, children, ...rest } = props; // eslint-disable-line @typescript-eslint/no-unused-vars\n      return (\n        <div data-testid=\"mdx-layout\" {...rest}>\n          {children}\n        </div>\n      );\n    },\n  };\n\n  test(\"works (as func)\", async () => {\n    const source = \"hi <Test name={bar} />\";\n\n    const options: MDXRemoteOptions = {\n      scope: {\n        bar: \"ipikuka\",\n      },\n    };\n\n    const content = await MDXRemote({\n      source,\n      options,\n      components: mdxComponents,\n      onError: ErrorComponent,\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div data-testid=\"mdx-layout\"><p>hi <strong>ipikuka</strong></p></div>\"`,\n    );\n  });\n\n  test(\"works (as jsx)\", async () => {\n    const source = \"hi <Test name={bar} />\";\n\n    const options: MDXRemoteOptions = {\n      scope: {\n        bar: \"ipikuka\",\n      },\n    };\n\n    const element = (\n      <MDXRemote\n        source={source}\n        options={options}\n        components={mdxComponents}\n        onError={ErrorComponent}\n      />\n    );\n\n    expect(await renderToStringFromStream(element)).toMatchInlineSnapshot(\n      `\"<div data-testid=\"mdx-layout\"><p>hi <strong>ipikuka</strong></p></div>\"`,\n    );\n  });\n\n  test(\"works with catchable error but no Error Component (as func)\", async () => {\n    const source = \"import x from 'y'\";\n\n    try {\n      await MDXRemote({\n        source,\n        components: mdxComponents,\n      });\n    } catch (error) {\n      expect(error).toMatchInlineSnapshot(\n        `[Error: Unexpected missing \\`options.baseUrl\\` needed to support \\`export … from\\`, \\`import\\`, or \\`import.meta.url\\` when generating \\`function-body\\`]`,\n      );\n    }\n\n    // second way\n\n    await expect(\n      MDXRemote({\n        source,\n        components: mdxComponents,\n      }),\n    ).rejects.toThrowErrorMatchingInlineSnapshot(\n      `[Error: Unexpected missing \\`options.baseUrl\\` needed to support \\`export … from\\`, \\`import\\`, or \\`import.meta.url\\` when generating \\`function-body\\`]`,\n    );\n  });\n\n  test(\"works with catchable error but no Error Component (as jsx)\", async () => {\n    const source = \"import x from 'y'\";\n\n    const element = <MDXRemote source={source} components={mdxComponents} />;\n\n    try {\n      await renderToStringFromStream(element);\n    } catch (error) {\n      expect(error).toMatchInlineSnapshot(\n        `[Error: Unexpected missing \\`options.baseUrl\\` needed to support \\`export … from\\`, \\`import\\`, or \\`import.meta.url\\` when generating \\`function-body\\`]`,\n      );\n    }\n\n    // second way\n\n    await expect(renderToStringFromStream(element)).rejects.toThrowErrorMatchingInlineSnapshot(\n      `[Error: Unexpected missing \\`options.baseUrl\\` needed to support \\`export … from\\`, \\`import\\`, or \\`import.meta.url\\` when generating \\`function-body\\`]`,\n    );\n  });\n\n  test(\"works with catchable error, with Error component (as func)\", async () => {\n    const source = \"import x from 'y'\";\n\n    const content = await MDXRemote({\n      source,\n      components: mdxComponents,\n      onError: ErrorComponent,\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div data-testid=\"mdx-error\">Unexpected missing \\`options.baseUrl\\` needed to support \\`export … from\\`, \\`import\\`, or \\`import.meta.url\\` when generating \\`function-body\\`</div>\"`,\n    );\n  });\n\n  test(\"works with catchable error, with Error component (as jsx)\", async () => {\n    const source = \"import x from 'y'\";\n\n    const element = (\n      <MDXRemote source={source} components={mdxComponents} onError={ErrorComponent} />\n    );\n\n    expect(await renderToStringFromStream(element)).toMatchInlineSnapshot(\n      `\"<div data-testid=\"mdx-error\">Unexpected missing \\`options.baseUrl\\` needed to support \\`export … from\\`, \\`import\\`, or \\`import.meta.url\\` when generating \\`function-body\\`</div>\"`,\n    );\n  });\n\n  test(\"catchable error (as func)\", async () => {\n    const source = \"import x from 'y'\";\n\n    const options: MDXRemoteOptions = {\n      mdxOptions: {\n        baseUrl: import.meta.url,\n      },\n    };\n\n    const content = await MDXRemote({\n      source,\n      options,\n      components: mdxComponents,\n      onError: ErrorComponent,\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toContain(\"Cannot find package\");\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatch(/Cannot find package/);\n\n    // just for testing it with @testing-library\n    render(content);\n    expect(screen.getByTestId(\"mdx-error\")).toHaveTextContent(\"Cannot find package 'y'\");\n  });\n\n  test(\"catchable error (as jsx)\", async () => {\n    const source = \"import x from 'y'\";\n\n    const options: MDXRemoteOptions = {\n      mdxOptions: {\n        baseUrl: import.meta.url,\n      },\n    };\n\n    const element = (\n      <MDXRemote\n        source={source}\n        options={options}\n        components={mdxComponents}\n        onError={ErrorComponent}\n      />\n    );\n\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toContain(\"Cannot find package\");\n    expect(content).toMatch(/Cannot find package/);\n\n    // just for testing it with @testing-library\n    render(<div dangerouslySetInnerHTML={{ __html: content }} />);\n    expect(screen.getByTestId(\"mdx-error\")).toBeInTheDocument();\n    expect(screen.getByTestId(\"mdx-error\")).toHaveTextContent(\"Cannot find package 'y'\");\n  });\n\n  test(\"uncatchable error (as func)\", async () => {\n    const source = \"hi {bar}\";\n\n    const content = await MDXRemote({\n      source,\n      components: mdxComponents,\n      onError: ErrorComponent,\n    });\n\n    expect(() =>\n      ReactDOMServer.renderToStaticMarkup(content),\n    ).toThrowErrorMatchingInlineSnapshot(`[ReferenceError: bar is not defined]`);\n  });\n\n  test(\"uncatchable error (as jsx)\", async () => {\n    const source = \"hi {bar}\";\n\n    const element = (\n      <MDXRemote source={source} components={mdxComponents} onError={ErrorComponent} />\n    );\n\n    await expect(renderToStringFromStream(element)).rejects.toThrowErrorMatchingInlineSnapshot(\n      `[ReferenceError: bar is not defined]`,\n    );\n  });\n});\n"
  },
  {
    "path": "tests/test.MDXRemote.spec.tsx",
    "content": "import { vi, describe, test, expect } from \"vitest\";\n\nimport type { Plugin } from \"unified\";\nimport { VFile } from \"vfile\";\nimport dedent from \"dedent\";\nimport remarkEmoji from \"remark-emoji\";\nimport remarkFlexibleMarkers from \"remark-flexible-markers\";\nimport recmaMdxChangeProps from \"recma-mdx-change-props\";\nimport recmaMdxEscapeMissingComponents from \"recma-mdx-escape-missing-components\";\n\nimport { MDXRemote, type MDXRemoteOptions, type MDXComponents } from \"../src/rsc\";\nimport { compile } from \"../src/lib/compile\";\n\nimport { renderToStringFromStream } from \"./utils\";\n\ndescribe(\"MDXRemote\", () => {\n  test(\"simple\", async () => {\n    const source = \"foo **bar**\";\n\n    const element = <MDXRemote source={source} />;\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toMatchInlineSnapshot(`\"<p>foo <strong>bar</strong></p>\"`);\n  });\n\n  test(\"with component 1\", async () => {\n    const source = 'foo <Test name=\"test\" />';\n\n    const element = (\n      <MDXRemote\n        source={source}\n        components={{\n          Test: ({ name }: { name: string }) => <span>hello {name}</span>,\n        }}\n      />\n    );\n\n    // React inserts a <!-- --> comment in streaming SSR to separate adjacent text nodes.\n    const content = await renderToStringFromStream(element);\n    expect(content).toMatchInlineSnapshot(`\"<p>foo <span>hello <!-- -->test</span></p>\"`);\n\n    const contentStrippedComments = await renderToStringFromStream(element, {\n      stripReactSSRComments: true,\n    });\n\n    expect(contentStrippedComments).toMatchInlineSnapshot(\n      `\"<p>foo <span>hello test</span></p>\"`,\n    );\n  });\n\n  test(\"with component 2\", async () => {\n    const source = 'foo <Test name=\"test\" />';\n\n    const element = (\n      <MDXRemote\n        source={source}\n        components={{\n          Test: ({ name }: { name: string }) => <span>{`hello ${name}`}</span>,\n        }}\n      />\n    );\n\n    // strpping comment is NOT needed because the text is concatenated into a single node.\n    const content = await renderToStringFromStream(element);\n    expect(content).toMatchInlineSnapshot(`\"<p>foo <span>hello test</span></p>\"`);\n  });\n\n  test(\"with some remarkPlugins in mdxOptions\", async () => {\n    const source = \"==hello :tada: Talat Kuyuk==\";\n\n    const options: MDXRemoteOptions = {\n      mdxOptions: {\n        remarkPlugins: [remarkFlexibleMarkers, remarkEmoji],\n      },\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n    const content = await renderToStringFromStream(element, { stripReactSSRComments: true });\n\n    expect(content).toMatchInlineSnapshot(\n      `\"<p><mark class=\"flexible-marker flexible-marker-default\">hello 🎉 Talat Kuyuk</mark></p>\"`,\n    );\n  });\n\n  test(\"with scope\", async () => {\n    const source = \"hi {bar}\";\n\n    const options: MDXRemoteOptions = {\n      scope: {\n        bar: \"ipikuka\",\n      },\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n    const content = await renderToStringFromStream(element, { stripReactSSRComments: true });\n\n    expect(content).toMatchInlineSnapshot(`\"<p>hi ipikuka</p>\"`);\n  });\n\n  test(\"with scope and component\", async () => {\n    const source = \"hi <Test name={bar} />\";\n\n    const options: MDXRemoteOptions = {\n      scope: {\n        bar: \"ipikuka\",\n      },\n    };\n\n    const components = {\n      Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n    };\n\n    const element = <MDXRemote source={source} options={options} components={components} />;\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toMatchInlineSnapshot(`\"<p>hi <strong>ipikuka</strong></p>\"`);\n  });\n\n  test(\"with scope in which consists props key escaped with no reason\", async () => {\n    const source = dedent`\n      Hi {props.bar}\n      <Test name={props.foo} />\n    `;\n\n    const options: MDXRemoteOptions = {\n      scope: {\n        props: {\n          bar: \"barbar\",\n          foo: \"foofoo\",\n        },\n      },\n    };\n\n    const components = {\n      Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n    };\n\n    const element = <MDXRemote source={source} options={options} components={components} />;\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toMatchInlineSnapshot(`\n      \"<p>Hi </p>\n      <strong></strong>\"\n    `);\n  });\n\n  test(\"with scope in which consists props key works as expected using a recma plugin\", async () => {\n    const source = dedent`\n      Hi {props.bar}\n      <Test name={props.foo} />\n    `;\n\n    const options: MDXRemoteOptions = {\n      scope: {\n        props: {\n          bar: \"barbar\",\n          foo: \"foofoo\",\n        },\n      },\n      mdxOptions: {\n        recmaPlugins: [recmaMdxChangeProps],\n      },\n    };\n\n    const components = {\n      Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n    };\n\n    const element = <MDXRemote source={source} options={options} components={components} />;\n    const content = await renderToStringFromStream(element, { stripReactSSRComments: true });\n\n    expect(content).toMatchInlineSnapshot(`\n      \"<p>Hi barbar</p>\n      <strong>foofoo</strong>\"\n    `);\n  });\n\n  test(\"with frontmatter supplying frontmatter's type argument\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      ## {frontmatter.title}\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toMatchInlineSnapshot(`\n      \"<h2>My Article</h2>\"\n    `);\n  });\n\n  test(\"with frontmatter and scope\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      # {frontmatter.title}\n      Hi *{name}*\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n      scope: { name: \"Talat Kuyuk\" },\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toMatchInlineSnapshot(`\n      \"<h1>My Article</h1>\n      <p>Hi <em>Talat Kuyuk</em></p>\"\n    `);\n  });\n\n  test(\"strips any undefined frontmatters without giving an error\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      The title is {frontmatter.title} and {frontmatter.subtitle}.\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n    const content = await renderToStringFromStream(element, { stripReactSSRComments: true });\n\n    expect(content).toMatchInlineSnapshot(`\n      \"<p>The title is My Article and .</p>\"\n    `);\n  });\n\n  test(\"supports component names with a dot(.)\", async () => {\n    const source = \"<motion.p />\";\n\n    const components: MDXComponents = {\n      // @ts-ignore no match for the signature\n      motion: { p: () => <p>Hello world</p> },\n    };\n\n    const element = <MDXRemote source={source} components={components} />;\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toMatchInlineSnapshot(`\n      \"<p>Hello world</p>\"\n    `);\n  });\n\n  test(\"renders fragments\", async () => {\n    const source = \"<Test content={<>Renders fragments</>} />\";\n\n    const components = {\n      Test: ({ content }: { content: string }) => <>{content}</>,\n    };\n\n    const element = <MDXRemote source={source} components={components} />;\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toMatchInlineSnapshot(`\n      \"Renders fragments\"\n    `);\n  });\n\n  test(\"supports VFile\", async () => {\n    const source = new VFile(\"foo **bar**\");\n\n    const element = <MDXRemote source={source} />;\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toMatchInlineSnapshot(`\n      \"<p>foo <strong>bar</strong></p>\"\n    `);\n  });\n\n  test(\"supports Buffer\", async () => {\n    const source = Buffer.from(\"foo **bar**\");\n\n    const element = <MDXRemote source={source} />;\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toMatchInlineSnapshot(`\n      \"<p>foo <strong>bar</strong></p>\"\n    `);\n  });\n\n  test(\"debug compiled source\", async () => {\n    const logSpy = vi.spyOn(console, \"log\").mockImplementation(() => {});\n\n    const result = await compile(new VFile(\"Hi\"));\n\n    await renderToStringFromStream(\n      <MDXRemote source=\"Hi\" options={{ debug: { compiledSource: true } }} />,\n    );\n\n    expect(logSpy).toHaveBeenCalledTimes(1);\n    expect(logSpy).toHaveBeenCalledWith(String(result.compiledSource));\n\n    logSpy.mockRestore(); // Restore original console.log behavior\n  });\n});\n\ndescribe(\"vfileDataIntoScope in MDXRemote function, no scope but vfileDataIntoScope injects data into scope\", () => {\n  const remarkAddBarFoo: Plugin = () => (_, file) => {\n    file.data[\"bar\"] = \"barbar\";\n    file.data[\"foo\"] = \"foofoo\";\n  };\n\n  test(\"Throw error for missing expression in scope, no 'vfileDataIntoScope'\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      # {frontmatter.title} {bar} {foo}\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n      mdxOptions: {\n        remarkPlugins: [remarkAddBarFoo],\n      },\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n\n    try {\n      await renderToStringFromStream(element);\n    } catch (error) {\n      // Because the first non-exist expression in scope is bar in the content\n      expect(error).toMatchInlineSnapshot(`[ReferenceError: bar is not defined]`);\n    }\n  });\n\n  test(\"Throw error for missing expression in scope, no cover 'vfileDataIntoScope' - string\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      # {frontmatter.title} {bar} {foo}\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n      vfileDataIntoScope: \"bar\",\n      mdxOptions: {\n        remarkPlugins: [remarkAddBarFoo],\n      },\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n\n    try {\n      await renderToStringFromStream(element);\n    } catch (error) {\n      // Because, bar is in scope (thanks to vfileDataIntoScope), but foo\n      expect(error).toMatchInlineSnapshot(`[ReferenceError: foo is not defined]`);\n    }\n  });\n\n  test(\"works with the option 'vfileDataIntoScope' - string array\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      # {frontmatter.title} {bar} {foo}\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n      vfileDataIntoScope: [\"bar\", \"foo\"],\n      mdxOptions: {\n        remarkPlugins: [remarkAddBarFoo],\n      },\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n    const content = await renderToStringFromStream(element, { stripReactSSRComments: true });\n\n    expect(content).toMatchInlineSnapshot(`\"<h1>My Article barbar foofoo</h1>\"`);\n  });\n\n  test(\"works with the option 'vfileDataIntoScope' - boolean true\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      # {frontmatter.title} {bar} {foo}\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n      vfileDataIntoScope: true,\n      mdxOptions: {\n        remarkPlugins: [remarkAddBarFoo],\n      },\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n    const content = await renderToStringFromStream(element, { stripReactSSRComments: true });\n\n    expect(content).toMatchInlineSnapshot(`\"<h1>My Article barbar foofoo</h1>\"`);\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - object\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      # {mymatter.title}\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n      vfileDataIntoScope: { name: \"matter\", as: \"mymatter\" },\n    };\n\n    // file.matter is created by `parseFrontmatter: true`\n    // vfileDataIntoScope injects it as `mymatter` into scope\n\n    const element = <MDXRemote source={source} options={options} />;\n    const content = await renderToStringFromStream(element, { stripReactSSRComments: true });\n\n    expect(content).toMatchInlineSnapshot(`\"<h1>My Article</h1>\"`);\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - object array\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      # {frontmatter.title} {newbar} {newfoo}\n    `;\n\n    const options: MDXRemoteOptions = {\n      scope: {},\n      parseFrontmatter: true,\n      vfileDataIntoScope: [\n        { name: \"bar\", as: \"newbar\" },\n        { name: \"foo\", as: \"newfoo\" },\n      ],\n      mdxOptions: {\n        remarkPlugins: [remarkAddBarFoo],\n      },\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n    const content = await renderToStringFromStream(element, { stripReactSSRComments: true });\n\n    expect(content).toMatchInlineSnapshot(`\"<h1>My Article barbar foofoo</h1>\"`);\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - mixed array\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      # {frontmatter.title} {bar} {newfoo}\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n      vfileDataIntoScope: [\"bar\", { name: \"foo\", as: \"newfoo\" }],\n      mdxOptions: {\n        remarkPlugins: [remarkAddBarFoo],\n      },\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n    const content = await renderToStringFromStream(element, { stripReactSSRComments: true });\n\n    expect(content).toMatchInlineSnapshot(`\"<h1>My Article barbar foofoo</h1>\"`);\n  });\n});\n\ndescribe(\"error handling in MDXRemote\", () => {\n  const ErrorComponent = ({ error }: { error: Error }) => {\n    return <div data-testid=\"mdx-error\">{error.message}</div>;\n  };\n\n  test(\"prints helpful message from compile MDX error, no Error component\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      This is very bad syntax <GITHUB_USER>\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n    };\n\n    const element = <MDXRemote source={source} options={options} />;\n\n    try {\n      const content = await renderToStringFromStream(element);\n      expect(content).toMatchInlineSnapshot(); // above render throwed error, so no content\n    } catch (error) {\n      // The error is thrown as a raw Error object (not rendered to HTML)\n      expect(error).toMatchInlineSnapshot(`\n        [Error: [next-mdx-remote-client] error compiling MDX:\n        Expected a closing tag for \\`<GITHUB_USER>\\` (1:25-1:38) before the end of \\`paragraph\\`\n\n        > 1 | This is very bad syntax <GITHUB_USER>\n            |                         ^\n\n        More information: https://mdxjs.com/docs/troubleshooting-mdx]\n      `);\n    }\n\n    // the second way of testing\n    await expect(renderToStringFromStream(element)).rejects.toMatchInlineSnapshot(`\n      [Error: [next-mdx-remote-client] error compiling MDX:\n      Expected a closing tag for \\`<GITHUB_USER>\\` (1:25-1:38) before the end of \\`paragraph\\`\n\n      > 1 | This is very bad syntax <GITHUB_USER>\n          |                         ^\n\n      More information: https://mdxjs.com/docs/troubleshooting-mdx]\n    `);\n  });\n\n  test(\"prints helpful message from compile MDX error, with Error component\", async () => {\n    // This test shows that MDX syntax errors are catched by `next-mdx-remote-client`\n\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      This is very bad syntax <GITHUB_USER>\n    `;\n\n    const options: MDXRemoteOptions = {\n      parseFrontmatter: true,\n    };\n\n    const element = <MDXRemote source={source} options={options} onError={ErrorComponent} />;\n    const content = await renderToStringFromStream(element);\n\n    // The error is rendered inside a React component (ErrorComponent) and thus HTML-escaped by React\n    expect(content).toMatchInlineSnapshot(`\n      \"<div data-testid=\"mdx-error\">[next-mdx-remote-client] error compiling MDX:\n      Expected a closing tag for \\`&lt;GITHUB_USER&gt;\\` (1:25-1:38) before the end of \\`paragraph\\`\n\n      &gt; 1 | This is very bad syntax &lt;GITHUB_USER&gt;\n          |                         ^\n\n      More information: https://mdxjs.com/docs/troubleshooting-mdx</div>\"\n    `);\n  });\n\n  test(\"missing a scope value causes runtime error during render, no Error component\", async () => {\n    const source = \"hi {bar}\";\n    const element = <MDXRemote source={source} />;\n\n    try {\n      const content = await renderToStringFromStream(element); // the render throws an error\n      expect(content).toMatchInlineSnapshot(); // so no content\n    } catch (error) {\n      expect(error).toMatchInlineSnapshot(`[ReferenceError: bar is not defined]`);\n    }\n\n    // the second way of testing\n    await expect(renderToStringFromStream(element)).rejects.toThrowErrorMatchingInlineSnapshot(\n      `[ReferenceError: bar is not defined]`,\n    );\n  });\n\n  test(\"missing a scope value causes runtime error during render, with Error component\", async () => {\n    // This test shows that a runtime error can not be catched by `next-mdx-remote-client`\n\n    const source = \"hi {bar}\";\n    const element = <MDXRemote source={source} onError={ErrorComponent} />;\n\n    try {\n      const content = await renderToStringFromStream(element); // the render throws an error\n      expect(content).toMatchInlineSnapshot(); // so no content\n    } catch (error) {\n      expect(error).toMatchInlineSnapshot(`[ReferenceError: bar is not defined]`);\n    }\n\n    // the second way of testing\n    await expect(renderToStringFromStream(element)).rejects.toThrowErrorMatchingInlineSnapshot(\n      `[ReferenceError: bar is not defined]`,\n    );\n  });\n\n  test(\"missing a component causes runtime error during render, no Error component\", async () => {\n    const source = \"hi <Test />\";\n    const element = <MDXRemote source={source} />;\n\n    try {\n      const content = await renderToStringFromStream(element); // the render throws an error\n      expect(content).toMatchInlineSnapshot(); // so no content\n    } catch (error) {\n      expect(error).toMatchInlineSnapshot(\n        `[Error: Expected component \\`Test\\` to be defined: you likely forgot to import, pass, or provide it.]`,\n      );\n    }\n\n    // the second way of testing\n    await expect(renderToStringFromStream(element)).rejects.toThrowErrorMatchingInlineSnapshot(\n      `[Error: Expected component \\`Test\\` to be defined: you likely forgot to import, pass, or provide it.]`,\n    );\n  });\n\n  test(\"missing a component causes runtime error during render, with Error component\", async () => {\n    // This test shows that a runtime error can not be catched by `next-mdx-remote-client`\n\n    const source = \"hi <Test />\";\n    const element = <MDXRemote source={source} onError={ErrorComponent} />;\n\n    try {\n      const content = await renderToStringFromStream(element); // the render throws an error\n      expect(content).toMatchInlineSnapshot(); // so no content\n    } catch (error) {\n      expect(error).toMatchInlineSnapshot(\n        `[Error: Expected component \\`Test\\` to be defined: you likely forgot to import, pass, or provide it.]`,\n      );\n    }\n\n    // the second way of testing\n    await expect(renderToStringFromStream(element)).rejects.toThrowErrorMatchingInlineSnapshot(\n      `[Error: Expected component \\`Test\\` to be defined: you likely forgot to import, pass, or provide it.]`,\n    );\n  });\n\n  test(\"missing components can be escaped via a recma plugin without giving runtime error\", async () => {\n    const source = \"hi <Test />\";\n\n    const element = (\n      <MDXRemote\n        source={source}\n        options={{\n          mdxOptions: {\n            recmaPlugins: [recmaMdxEscapeMissingComponents],\n          },\n        }}\n      />\n    );\n    const content = await renderToStringFromStream(element);\n\n    expect(content).toMatchInlineSnapshot(`\"<p>hi </p>\"`);\n  });\n});\n"
  },
  {
    "path": "tests/test.compile.spec.tsx",
    "content": "import { describe, test, expect } from \"vitest\";\n\nimport dedent from \"dedent\";\n\nimport { compile } from \"../src/lib/compile\";\nimport { prepare } from \"../src/lib/prepare\";\n\ntype Frontmatter = { title: string };\n\ndescribe(\"the result of the compile function\", () => {\n  test(\"has import statement but without enableImports option\", async () => {\n    const source = dedent`\n      ---\n      title: 'Hello World'\n      ---\n      import abc from \"./xxx.js\"\n      \n      # Hi {name}\n    `;\n\n    const { vfile, frontmatter } = prepare<Frontmatter>(source, true);\n\n    const result = await compile(vfile, {\n      disableImports: true,\n    });\n\n    // test the frontmatter *******************************\n\n    expect(frontmatter.title).toEqual(\"Hello World\");\n\n    // @ts-expect-error\n    expect(frontmatter.blah).toBeUndefined();\n\n    // test the compiledSource ****************************\n\n    const compiledSource = dedent`\n      \"use strict\";\n      const {jsx: _jsx, jsxs: _jsxs} = arguments[0];\n      function _createMdxContent(props) {\n        const _components = {\n          h1: \"h1\",\n          ...props.components\n        };\n        return _jsxs(_components.h1, {\n          children: [\"Hi \", name]\n        });\n      }\n      function MDXContent(props = {}) {\n        const {wrapper: MDXLayout} = props.components || ({});\n        return MDXLayout ? _jsx(MDXLayout, {\n          ...props,\n          children: _jsx(_createMdxContent, {\n            ...props\n          })\n        }) : _createMdxContent(props);\n      }\n      return {\n        default: MDXContent\n      };\n    `;\n\n    expect(String(result.compiledSource)).toContain(compiledSource);\n  });\n\n  test(\"has import statement, but baseURL is not defined\", async () => {\n    const source = dedent`\n      ---\n      title: 'Hello World'\n      ---\n      import abc from \"./xxx.js\"\n      \n      # Hi {name}\n    `;\n\n    const { vfile, frontmatter } = prepare<Frontmatter>(source, true);\n\n    const result = await compile(vfile, {\n      mdxOptions: {\n        // baseUrl: import.meta.url, // <---- disabling this makes happen to add const _importMetaUrl = arguments[0].baseUrl;\n      },\n    });\n\n    // test the frontmatter *******************************\n\n    expect(frontmatter.title).toEqual(\"Hello World\");\n\n    // @ts-expect-error\n    expect(frontmatter.blah).toBeUndefined();\n\n    // test the compiledSource ****************************\n\n    const compiledSource = dedent`\n      \"use strict\";\n      const {jsx: _jsx, jsxs: _jsxs} = arguments[0];\n      const _importMetaUrl = arguments[0].baseUrl;\n      if (!_importMetaUrl) throw new Error(\"Unexpected missing \\`options.baseUrl\\` needed to support \\`export … from\\`, \\`import\\`, or \\`import.meta.url\\` when generating \\`function-body\\`\");\n      const {default: abc} = await import(_resolveDynamicMdxSpecifier(\"./xxx.js\"));\n      function _createMdxContent(props) {\n        const _components = {\n          h1: \"h1\",\n          ...props.components\n        };\n        return _jsxs(_components.h1, {\n          children: [\"Hi \", name]\n        });\n      }\n      function MDXContent(props = {}) {\n        const {wrapper: MDXLayout} = props.components || ({});\n        return MDXLayout ? _jsx(MDXLayout, {\n          ...props,\n          children: _jsx(_createMdxContent, {\n            ...props\n          })\n        }) : _createMdxContent(props);\n      }\n      return {\n        default: MDXContent\n      };\n      function _resolveDynamicMdxSpecifier(d) {\n        if (typeof d !== \"string\") return d;\n        try {\n          new URL(d);\n          return d;\n        } catch {}\n        if (d.startsWith(\"/\") || d.startsWith(\"./\") || d.startsWith(\"../\")) return new URL(d, _importMetaUrl).href;\n        return d;\n      }\n    `;\n\n    expect(String(result.compiledSource)).toContain(compiledSource);\n  });\n\n  test(\"has import statement, and baseURL is defined\", async () => {\n    const source = dedent`\n      ---\n      title: 'Hello World'\n      ---\n      import abc from \"./xxx.js\"\n      \n      # Hi {name}\n    `;\n\n    const { vfile, frontmatter } = prepare<Frontmatter>(source, true);\n\n    const result = await compile(vfile, {\n      mdxOptions: {\n        baseUrl: import.meta.url,\n      },\n    });\n\n    // test the frontmatter *******************************\n\n    expect(frontmatter.title).toEqual(\"Hello World\");\n\n    // @ts-expect-error\n    expect(frontmatter.blah).toBeUndefined();\n\n    // test the compiledSource ****************************\n\n    const compiledSource = dedent`\n      \"use strict\";\n      const {jsx: _jsx, jsxs: _jsxs} = arguments[0];\n      const {default: abc} = await import(_resolveDynamicMdxSpecifier(\"./xxx.js\"));\n      function _createMdxContent(props) {\n        const _components = {\n          h1: \"h1\",\n          ...props.components\n        };\n        return _jsxs(_components.h1, {\n          children: [\"Hi \", name]\n        });\n      }\n      function MDXContent(props = {}) {\n        const {wrapper: MDXLayout} = props.components || ({});\n        return MDXLayout ? _jsx(MDXLayout, {\n          ...props,\n          children: _jsx(_createMdxContent, {\n            ...props\n          })\n        }) : _createMdxContent(props);\n      }\n      return {\n        default: MDXContent\n      };\n      function _resolveDynamicMdxSpecifier(d) {\n        if (typeof d !== \"string\") return d;\n        try {\n          new URL(d);\n          return d;\n        } catch {}\n        if (d.startsWith(\"/\") || d.startsWith(\"./\") || d.startsWith(\"../\")) return new URL(d, \"file:`;\n\n    expect(String(result.compiledSource)).toContain(compiledSource);\n  });\n\n  test(\"has NO import statement, baseURL is not defined\", async () => {\n    const source = dedent`\n      ---\n      title: 'Hello World'\n      ---\n      # Hi {name}\n    `;\n\n    const { vfile } = prepare<Frontmatter>(source, true);\n\n    const result = await compile(vfile);\n\n    // test the compiledSource ****************************\n\n    const compiledSource = dedent`\n      \"use strict\";\n      const {jsx: _jsx, jsxs: _jsxs} = arguments[0];\n      function _createMdxContent(props) {\n        const _components = {\n          h1: \"h1\",\n          ...props.components\n        };\n        return _jsxs(_components.h1, {\n          children: [\"Hi \", name]\n        });\n      }\n      function MDXContent(props = {}) {\n        const {wrapper: MDXLayout} = props.components || ({});\n        return MDXLayout ? _jsx(MDXLayout, {\n          ...props,\n          children: _jsx(_createMdxContent, {\n            ...props\n          })\n        }) : _createMdxContent(props);\n      }\n      return {\n        default: MDXContent\n      };\n    `;\n\n    expect(String(result.compiledSource)).toContain(compiledSource);\n  });\n\n  test(\"has NO import statement, baseURL definition does not lead to change\", async () => {\n    const source = dedent`\n      ---\n      title: 'Hello World'\n      ---\n      # Hi {name}\n    `;\n\n    const { vfile } = prepare<Frontmatter>(source, true);\n\n    const result = await compile(vfile, {\n      mdxOptions: {\n        baseUrl: import.meta.url,\n      },\n    });\n\n    // test the compiledSource ****************************\n\n    const compiledSource = dedent`\n      \"use strict\";\n      const {jsx: _jsx, jsxs: _jsxs} = arguments[0];\n      function _createMdxContent(props) {\n        const _components = {\n          h1: \"h1\",\n          ...props.components\n        };\n        return _jsxs(_components.h1, {\n          children: [\"Hi \", name]\n        });\n      }\n      function MDXContent(props = {}) {\n        const {wrapper: MDXLayout} = props.components || ({});\n        return MDXLayout ? _jsx(MDXLayout, {\n          ...props,\n          children: _jsx(_createMdxContent, {\n            ...props\n          })\n        }) : _createMdxContent(props);\n      }\n      return {\n        default: MDXContent\n      };\n    `;\n\n    expect(String(result.compiledSource)).toContain(compiledSource);\n  });\n\n  test(\"more paragraph needs Fragment\", async () => {\n    const source = dedent`\n      ---\n      title: 'Hello World'\n      ---\n      # Hi {name}\n\n      More paragraph\n    `;\n\n    const { vfile } = prepare<Frontmatter>(source, true);\n\n    const result = await compile(vfile);\n\n    // test the compiledSource ****************************\n\n    const compiledSourceInitialPart = dedent`\n      \"use strict\";\n      const {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\n    `;\n\n    expect(String(result.compiledSource)).toContain(compiledSourceInitialPart);\n  });\n\n  test(\"providerImportSource option is defined\", async () => {\n    const source = dedent`\n      ---\n      title: 'Hello World'\n      ---\n      import abc from \"./xxx.js\"\n      \n      # Hi {name}\n    `;\n\n    const { vfile, frontmatter } = prepare<Frontmatter>(source, true);\n\n    const result = await compile(vfile, {\n      mdxOptions: {\n        baseUrl: import.meta.url,\n        providerImportSource: \"#\", // <--- here, this makes happen to add \"useMDXComponents\" into the code\n      },\n    });\n\n    // test the frontmatter *******************************\n\n    expect(frontmatter.title).toEqual(\"Hello World\");\n\n    // @ts-expect-error\n    expect(frontmatter.blah).toBeUndefined();\n\n    // test the compiledSource ****************************\n\n    const compiledSource = dedent`\n      \"use strict\";\n      const {jsx: _jsx, jsxs: _jsxs} = arguments[0];\n      const {useMDXComponents: _provideComponents} = arguments[0];\n      const {default: abc} = await import(_resolveDynamicMdxSpecifier(\"./xxx.js\"));\n      function _createMdxContent(props) {\n        const _components = {\n          h1: \"h1\",\n          ..._provideComponents(),\n          ...props.components\n        };\n        return _jsxs(_components.h1, {\n          children: [\"Hi \", name]\n        });\n      }\n      function MDXContent(props = {}) {\n        const {wrapper: MDXLayout} = {\n          ..._provideComponents(),\n          ...props.components\n        };\n        return MDXLayout ? _jsx(MDXLayout, {\n          ...props,\n          children: _jsx(_createMdxContent, {\n            ...props\n          })\n        }) : _createMdxContent(props);\n      }\n      return {\n        default: MDXContent\n      };\n      function _resolveDynamicMdxSpecifier(d) {\n        if (typeof d !== \"string\") return d;\n        try {\n          new URL(d);\n          return d;\n        } catch {}\n        if (d.startsWith(\"/\") || d.startsWith(\"./\") || d.startsWith(\"../\")) return new URL(d, \"file:`;\n\n    expect(String(result.compiledSource)).toContain(compiledSource);\n  });\n\n  test(\"development option is true\", async () => {\n    const source = dedent`\n      ---\n      title: 'Hello World'\n      ---\n      # Hi {name}\n    `;\n\n    const { vfile } = prepare<Frontmatter>(source, true);\n\n    const result = await compile(vfile, {\n      mdxOptions: {\n        development: true,\n      },\n    });\n\n    // test the compiledSource ****************************\n\n    const compiledSource = dedent`\n      \"use strict\";\n      const {jsxDEV: _jsxDEV} = arguments[0];\n      function _createMdxContent(props) {\n        const _components = {\n          h1: \"h1\",\n          ...props.components\n        };\n        return _jsxDEV(_components.h1, {\n          children: [\"Hi \", name]\n        }, undefined, true, {\n          fileName: \"<source.js>\",\n          lineNumber: 1,\n          columnNumber: 1\n        }, this);\n      }\n      function MDXContent(props = {}) {\n        const {wrapper: MDXLayout} = props.components || ({});\n        return MDXLayout ? _jsxDEV(MDXLayout, {\n          ...props,\n          children: _jsxDEV(_createMdxContent, {\n            ...props\n          }, undefined, false, {\n            fileName: \"<source.js>\"\n          }, this)\n        }, undefined, false, {\n          fileName: \"<source.js>\"\n        }, this) : _createMdxContent(props);\n      }\n      return {\n        default: MDXContent\n      };\n    `;\n\n    expect(String(result.compiledSource)).toContain(compiledSource);\n  });\n\n  test(\"has import statement, development option is true\", async () => {\n    const source = dedent`\n      ---\n      title: 'Hello World'\n      ---\n      import abc from \"./xxx.js\"\n\n      # Hi {name}\n\n      More paragraph\n    `;\n\n    const { vfile } = prepare<Frontmatter>(source, true);\n\n    const result = await compile(vfile, {\n      mdxOptions: {\n        development: true,\n      },\n    });\n\n    // test the compiledSource ****************************\n\n    const compiledSourceInitialPart = dedent`\n      \"use strict\";\n      const {Fragment: _Fragment, jsxDEV: _jsxDEV} = arguments[0];\n    `;\n\n    expect(String(result.compiledSource)).toContain(compiledSourceInitialPart);\n  });\n\n  test(\"use {scope: {props}}\", async () => {\n    const source = dedent`\n      # Hi {props.baz}\n\n      <Test name={props.foo} />\n    `;\n\n    const { vfile } = prepare(source);\n\n    const result = await compile(vfile);\n\n    expect(String(result.compiledSource)).toMatchInlineSnapshot(`\n      \"\"use strict\";\n      const {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\n      function _createMdxContent(props) {\n        const _components = {\n          h1: \"h1\",\n          ...props.components\n        }, {Test} = _components;\n        if (!Test) _missingMdxReference(\"Test\", true);\n        return _jsxs(_Fragment, {\n          children: [_jsxs(_components.h1, {\n            children: [\"Hi \", props.baz]\n          }), \"\\\\n\", _jsx(Test, {\n            name: props.foo\n          })]\n        });\n      }\n      function MDXContent(props = {}) {\n        const {wrapper: MDXLayout} = props.components || ({});\n        return MDXLayout ? _jsx(MDXLayout, {\n          ...props,\n          children: _jsx(_createMdxContent, {\n            ...props\n          })\n        }) : _createMdxContent(props);\n      }\n      return {\n        default: MDXContent\n      };\n      function _missingMdxReference(id, component) {\n        throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" \\`\" + id + \"\\` to be defined: you likely forgot to import, pass, or provide it.\");\n      }\n      \"\n    `);\n  });\n});\n"
  },
  {
    "path": "tests/test.core.spec.ts",
    "content": "import { test } from \"vitest\";\n\nimport assert from \"node:assert/strict\";\n\ntest(\"should expose the public apis\", async function () {\n  assert.deepEqual(Object.keys(await import(\"../src/csr\")).sort(), [\n    \"MDXClient\",\n    \"MDXClientAsync\",\n    \"MDXClientLazy\",\n    \"MDXProvider\",\n    \"hydrate\",\n    \"hydrateAsync\",\n    \"hydrateLazy\",\n    \"useMDXComponents\",\n  ]);\n\n  assert.deepEqual(Object.keys(await import(\"../src/csr/serialize.js\")).sort(), [\"serialize\"]);\n\n  assert.deepEqual(Object.keys(await import(\"../src/rsc\")).sort(), [\"MDXRemote\", \"evaluate\"]);\n\n  assert.deepEqual(Object.keys(await import(\"../src/utils\")).sort(), [\"getFrontmatter\"]);\n});\n"
  },
  {
    "path": "tests/test.evaluate.esm.spec.tsx",
    "content": "import { describe, test, expect } from \"vitest\";\n\nimport ReactDOMServer from \"react-dom/server\";\nimport recmaMdxImportReact from \"recma-mdx-import-react\";\nimport dedent from \"dedent\";\n\nimport { evaluate } from \"../src/rsc\";\n\ntype Frontmatter = { title: string };\n\ndescribe(\"evaluate function with ESM imports\", () => {\n  test(\"removes imports, if there is 'disableImports: true'\", async () => {\n    const source = dedent`\n      import {Pill} from \"./context/components.js\"\n      \n      Hi {name}\n    `;\n\n    const { content } = await evaluate({\n      source,\n      options: {\n        disableImports: true,\n        scope: {\n          name: \"foo\",\n        },\n      },\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>Hi foo</p>\"`,\n    );\n  });\n\n  test(\"works with imported modules\", async () => {\n    const source = dedent`\n      import {Pill} from \"./context/components.js\"\n      \n      Hi {name}\n\n      <Pill>!</Pill>\n    `;\n    const { content } = await evaluate({\n      source,\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url, // should be provided, finds the 'components.js' in relative path\n        },\n        scope: {\n          name: \"foo\",\n        },\n      },\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\n      \"<p>Hi foo</p>\n      <span style=\"color:blue\">!</span>\"\n    `);\n  });\n\n  test(\"should support importing data w/ ESM\", async () => {\n    const source = dedent`\n      import {number} from \"./context/data.js\"\n      \n      {number}\n    `;\n\n    const { content } = await evaluate({\n      source,\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\"3.14\"`);\n  });\n\n  test(\"should support exporting w/ ESM\", async () => {\n    const source = dedent`\n      export const number = Math.PI\n    `;\n\n    const { content, mod } = await evaluate({ source });\n\n    expect(mod.number).toBe(Math.PI);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toBe(\"\");\n  });\n\n  test(\"disabling exports is lead to 'mod' is empty object\", async () => {\n    const source = dedent`\n      export const number = Math.PI\n    `;\n\n    const { content, mod } = await evaluate({ source, options: { disableExports: true } });\n\n    expect(mod).toStrictEqual({});\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toBe(\"\");\n  });\n\n  test(\"should support exporting an identifier w/o a value\", async () => {\n    const source = dedent`\n      export var a\n    `;\n\n    const { content, mod } = await evaluate({ source });\n\n    expect(mod).toHaveProperty(\"a\");\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toBe(\"\");\n  });\n\n  test(\"should support exporting an object pattern\", async () => {\n    const source = dedent`\n      import {object} from \"./context/data.js\"\n      export var {a} = object\n    `;\n\n    const { content, mod } = await evaluate({\n      source,\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(mod.a).toBe(1);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toBe(\"\");\n  });\n\n  test(\"should support exporting a rest element in an object pattern\", async () => {\n    const source = dedent`\n      import {object} from \"./context/data.js\"\n      export var {a, ...rest} = object\n    `;\n\n    const { content, mod } = await evaluate({\n      source,\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(mod.a).toBe(1);\n    expect(mod.rest).toStrictEqual({ b: 2 });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toBe(\"\");\n  });\n\n  test(\"should support exporting an assignment pattern in an object pattern\", async () => {\n    const source = dedent`\n      import {object} from \"./context/data.js\"\n      export var {c = 3} = object\n    `;\n\n    const { content, mod } = await evaluate({\n      source,\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(mod.c).toBe(3);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toBe(\"\");\n  });\n\n  test(\"should support exporting an array pattern\", async () => {\n    const source = dedent`\n      import {array} from \"./context/data.js\"\n      export var [a] = array\n    `;\n\n    const { content, mod } = await evaluate({\n      source,\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(mod.a).toBe(1);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toBe(\"\");\n  });\n\n  test(\"should support `export as` w/ ESM\", async () => {\n    const source = dedent`\n      export const number = Math.PI\n      export {number as pi}\n    `;\n\n    const { content, mod } = await evaluate({\n      source,\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(mod.pi).toBe(Math.PI);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toBe(\"\");\n  });\n\n  test(\"should support default export to define a layout\", async () => {\n    const source = dedent`\n      export default function Layout(props) { return <div {...props} /> }\n\n      Hi\n    `;\n\n    const { content } = await evaluate({ source });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div components=\"[object Object]\"><p>Hi</p></div>\"`,\n    );\n  });\n\n  test(\"should support default export from a source\", async () => {\n    const source = dedent`\n      export {Layout as default} from \"./context/components.js\"\n\n      Hi\n    `;\n\n    const { content } = await evaluate({\n      source,\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div components=\"[object Object]\" style=\"color:red\"><p>Hi</p></div>\"`,\n    );\n  });\n\n  test(\"should support rexporting something as a default export from a source\", async () => {\n    const source = dedent`\n      export {default} from \"./context/components.js\"\n\n      Hi\n    `;\n\n    const { content } = await evaluate({\n      source,\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div components=\"[object Object]\" style=\"color:red\"><p>Hi</p></div>\"`,\n    );\n  });\n\n  test(\"should support rexporting the default export, and other things, from a source\", async () => {\n    const source = dedent`\n      export {default, Pill} from \"./context/components.js\"\n\n      <Pill>!</Pill>\n    `;\n\n    const { content } = await evaluate({\n      source,\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div components=\"[object Object]\" style=\"color:red\"><span style=\"color:blue\">!</span></div>\"`,\n    );\n  });\n});\n\ndescribe(\"evaluate function with ESM exports\", () => {\n  test(\"works with `export` statements\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      export const num = 1\n      export let str = 'foo';\n      export var bool = true\n      export function Component() {\n        return 'from component'\n      }\n\n      # {num} {str} {String(bool)} <Component />\n\n      export function Thing() {\n        return 'hello'\n      }\n      \n      <p><Thing /></p>\n    `;\n\n    const { content, mod } = await evaluate<Frontmatter>({\n      source,\n      options: {\n        parseFrontmatter: true,\n      },\n    });\n\n    expect(mod).toMatchObject({\n      Component: expect.any(Function),\n      Thing: expect.any(Function),\n      bool: true,\n      num: 1,\n      str: \"foo\",\n    });\n\n    const expected = dedent`\n      <h1>1 foo true from component</h1>\n\n      <p>hello</p>\n    `;\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toEqual(expected);\n  });\n\n  test(\"remove all `export` statements\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      export const num = 1\n      export let str = 'foo';\n      export var bool = true\n\n      # Hi\n\n      export function Component() {\n        return 'from component'\n      }\n    `;\n\n    const { content, mod } = await evaluate<Frontmatter>({\n      source,\n      options: {\n        disableExports: true,\n        parseFrontmatter: true,\n      },\n    });\n\n    expect(mod).toStrictEqual({});\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\"<h1>Hi</h1>\"`);\n  });\n});\n\ndescribe(\"error handling in evaluate related with ESM\", () => {\n  test(\"throws an error if the imported module is used after removing imports\", async () => {\n    const source = dedent`\n      import {Pill} from \"./context/components.js\"\n      \n      Hi {name}\n\n      <Pill>!</Pill>\n    `;\n\n    const { content, error } = await evaluate({\n      source,\n      options: {\n        disableImports: true,\n        scope: {\n          name: \"foo\",\n        },\n      },\n    });\n\n    // The \"evaluate\" can't catch the error, because the missing component is not syntax error in the compiled source\n    expect(error).toBeUndefined();\n\n    expect(content).toMatchInlineSnapshot(`\n      <MDXContent\n        components={{}}\n      />\n    `);\n\n    // But throws error during render\n    expect(() =>\n      ReactDOMServer.renderToStaticMarkup(content),\n    ).toThrowErrorMatchingInlineSnapshot(\n      `[Error: Expected component \\`Pill\\` to be defined: you likely forgot to import, pass, or provide it.]`,\n    );\n  });\n\n  test(\"throws an error if the option 'baseURL' is not provided for imports\", async () => {\n    const source = dedent`\n      import {Pill} from \"./context/components.js\"\n      \n      Hi {name}\n\n      <Pill>!</Pill>\n    `;\n\n    const { content, error } = await evaluate({\n      source,\n      options: {\n        scope: {\n          name: \"foo\",\n        },\n      },\n    });\n\n    expect(error).toMatchInlineSnapshot(\n      `[Error: Unexpected missing \\`options.baseUrl\\` needed to support \\`export … from\\`, \\`import\\`, or \\`import.meta.url\\` when generating \\`function-body\\`]`,\n    );\n\n    expect(content).toMatchInlineSnapshot(`\n      <div\n        className=\"mdx-empty\"\n      />\n    `);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div class=\"mdx-empty\"></div>\"`,\n    );\n  });\n\n  test(\"syntax error in compiled source can be catched in evaluate\", async () => {\n    const { content, error } = await evaluate({\n      source: \"import x from 'y'\",\n    });\n\n    expect(error).toMatchInlineSnapshot(\n      `[Error: Unexpected missing \\`options.baseUrl\\` needed to support \\`export … from\\`, \\`import\\`, or \\`import.meta.url\\` when generating \\`function-body\\`]`,\n    );\n\n    expect(content).toMatchInlineSnapshot(`\n      <div\n        className=\"mdx-empty\"\n      />\n    `);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div class=\"mdx-empty\"></div>\"`,\n    );\n  });\n\n  // don't know why this test causes an segmentation error in coverage but not in normal test\n  test(\"syntax error in compiled source can be catched in evaluate\", async () => {\n    const { content, error } = await evaluate({\n      source: \"import x from 'y'\",\n      options: {\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(error?.message).toContain(`Cannot find package 'y' imported from`);\n\n    expect(content).toMatchInlineSnapshot(`\n      <div\n        className=\"mdx-empty\"\n      /> \n    `);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div class=\"mdx-empty\"></div>\"`,\n    );\n  });\n\n  test(\"import .mjs React component with jsx syntax\", async () => {\n    const source = dedent`\n      import ExampleForm from \"./context/ExampleForm.mjs\"\n      \n      Hi {name}\n\n      <ExampleForm />\n    `;\n\n    const { content, error } = await evaluate({\n      source,\n      options: {\n        scope: {\n          name: \"ipikuka\",\n        },\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(error).toMatchInlineSnapshot(`[SyntaxError: Unexpected token '<']`);\n\n    expect(content).toMatchInlineSnapshot(`\n      <div\n        className=\"mdx-empty\"\n      />\n    `);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div class=\"mdx-empty\"></div>\"`,\n    );\n  });\n\n  test(\"import .mjs React component transformed to classic runtime\", async () => {\n    const source = dedent`\n      import ExampleForm from \"./context/ExampleFormTransformedClassic.mjs\"\n      \n      Hi {name}\n\n      <ExampleForm />\n    `;\n\n    const { content, error } = await evaluate({\n      source,\n      options: {\n        scope: {\n          name: \"ipikuka\",\n        },\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(error).toBeUndefined();\n\n    expect(content).toMatchInlineSnapshot(`\n      <MDXContent\n        components={{}}\n      />\n    `);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\n      \"<p>Hi ipikuka</p>\n      <div><label for=\"_R_3_-name\">Enter your name:</label><input id=\"_R_3_-name\" type=\"text\" value=\"\"/><p>Hello, stranger!</p></div>\"\n    `);\n  });\n\n  test(\"import .mjs React component transformed to automatic runtime\", async () => {\n    const source = dedent`\n      import ExampleForm from \"./context/ExampleFormTransformedAutomatic.mjs\"\n      \n      Hi {name}\n\n      <ExampleForm />\n    `;\n\n    const { content, error } = await evaluate({\n      source,\n      options: {\n        scope: {\n          name: \"ipikuka\",\n        },\n        mdxOptions: {\n          baseUrl: import.meta.url,\n        },\n      },\n    });\n\n    expect(error).toBeUndefined();\n\n    expect(content).toMatchInlineSnapshot(`\n      <MDXContent\n        components={{}}\n      />\n    `);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\n      \"<p>Hi ipikuka</p>\n      <div><label for=\"_R_3_-name\">Enter your name:</label><input id=\"_R_3_-name\" type=\"text\" value=\"\"/><p>Hello, stranger!</p></div>\"\n    `);\n  });\n\n  test(\"import .mjs React component in which the React instance injected\", async () => {\n    const source = dedent`\n      import HelloDave from \"./context/HelloDave.mjs\"\n\n      <HelloDave />\n    `;\n\n    const { content, error } = await evaluate({\n      source,\n      options: {\n        scope: {\n          name: \"ipikuka\",\n        },\n        mdxOptions: {\n          baseUrl: import.meta.url,\n          // without recma plugin, it throws an error\n          // TypeError: Cannot read properties of undefined (reading 'useId')\n          recmaPlugins: [recmaMdxImportReact],\n        },\n      },\n    });\n\n    expect(error).toBeUndefined();\n\n    expect(content).toMatchInlineSnapshot(`\n      <MDXContent\n        components={{}}\n      />\n    `);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toBe(\n      \"<div>Hello, Dave! Your id is _R_0_</div>\",\n    );\n  });\n});\n"
  },
  {
    "path": "tests/test.evaluate.spec.tsx",
    "content": "import { vi, describe, test, expect } from \"vitest\";\n\nimport ReactDOMServer from \"react-dom/server\";\nimport { VFile } from \"vfile\";\nimport dedent from \"dedent\";\nimport remarkEmoji from \"remark-emoji\";\nimport remarkFlexibleMarkers from \"remark-flexible-markers\";\nimport recmaMdxChangeProps from \"recma-mdx-change-props\";\nimport recmaMdxEscapeMissingComponents from \"recma-mdx-escape-missing-components\";\n\nimport { evaluate, type EvaluateOptions } from \"../src/rsc\";\nimport { compile } from \"../src/lib/compile\";\n\ntype Frontmatter = { title: string };\n\ndescribe(\"evaluate\", () => {\n  test(\"simple\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: \"foo **bar**\",\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>foo <strong>bar</strong></p>\"`,\n    );\n  });\n\n  test(\"with component\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: 'foo <Test name=\"test\" />',\n      components: {\n        Test: ({ name }: { name: string }) => <span>hello {name}</span>,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>foo <span>hello test</span></p>\"`,\n    );\n  });\n\n  test(\"with some remarkPlugins in mdxOptions\", async () => {\n    const options: EvaluateOptions = {\n      mdxOptions: {\n        remarkPlugins: [remarkFlexibleMarkers, remarkEmoji],\n      },\n    };\n\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: \"==hello :tada: Talat Kuyuk==\",\n      options,\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p><mark class=\"flexible-marker flexible-marker-default\">hello 🎉 Talat Kuyuk</mark></p>\"`,\n    );\n\n    expect(options.mdxOptions?.remarkPlugins?.length).toBe(2);\n  });\n\n  test(\"with scope\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: \"hi {bar}\",\n      options: {\n        scope: {\n          bar: \"ipikuka\",\n        },\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope.bar).toBe(\"ipikuka\");\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>hi ipikuka</p>\"`,\n    );\n  });\n\n  test(\"with scope and component\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: \"hi <Test name={bar} />\",\n      options: {\n        scope: {\n          bar: \"ipikuka\",\n        },\n      },\n      components: {\n        Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope.bar).toBe(\"ipikuka\");\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>hi <strong>ipikuka</strong></p>\"`,\n    );\n  });\n\n  test(\"with scope in which consists props key escaped with no reason\", async () => {\n    const source = dedent`\n      Hi {props.bar}\n      <Test name={props.foo} />\n    `;\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source,\n      options: {\n        scope: {\n          props: {\n            bar: \"barbar\",\n            foo: \"foofoo\",\n          },\n        },\n      },\n      components: {\n        Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope.props.bar).toBe(\"barbar\");\n    expect(scope.props.foo).toBe(\"foofoo\");\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\n      \"<p>Hi </p>\n      <strong></strong>\"\n    `);\n  });\n\n  test(\"with scope in which consists props key works as expected using a recma plugin\", async () => {\n    const source = dedent`\n      Hi {props.bar}\n      <Test name={props.foo} />\n    `;\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source,\n      options: {\n        scope: {\n          props: {\n            bar: \"barbar\",\n            foo: \"foofoo\",\n          },\n        },\n        mdxOptions: {\n          recmaPlugins: [recmaMdxChangeProps],\n        },\n      },\n      components: {\n        Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope.props.bar).toBe(\"barbar\");\n    expect(scope.props.foo).toBe(\"foofoo\");\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\n      \"<p>Hi barbar</p>\n      <strong>foofoo</strong>\"\n    `);\n  });\n\n  test(\"with frontmatter supplying frontmatter's type argument\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      ## {frontmatter.title}\n    `;\n\n    // there is a type argument for evaluate\n    const { content, mod, frontmatter, scope, error } = await evaluate<Frontmatter>({\n      source,\n      options: {\n        parseFrontmatter: true,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter.title).toEqual(\"My Article\");\n    expect(scope).toEqual({});\n    expect(error).toBeUndefined();\n\n    // @ts-expect-error Property 'blah' does not exist on type 'Frontmatter'.\n    expect(frontmatter.blah).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<h2>My Article</h2>\"`,\n    );\n  });\n\n  test(\"with frontmatter without supplying frontmatter's type argument\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      ## {frontmatter.title}\n    `;\n\n    // there is no type argument for evaluate\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source,\n      options: {\n        parseFrontmatter: true,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter.title).toEqual(\"My Article\");\n    expect(scope).toEqual({});\n    expect(error).toBeUndefined();\n\n    // it doesn't give any Typescript error\n    expect(frontmatter.blah).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<h2>My Article</h2>\"`,\n    );\n  });\n\n  test(\"with frontmatter and scope\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      # {frontmatter.title}\n      Hi *{name}*\n    `;\n\n    const { content, mod, frontmatter, scope, error } = await evaluate<Frontmatter>({\n      source,\n      options: {\n        parseFrontmatter: true,\n        scope: { name: \"Talat Kuyuk\" },\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter.title).toEqual(\"My Article\");\n    expect(scope.name).toBe(\"Talat Kuyuk\");\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\n      \"<h1>My Article</h1>\n      <p>Hi <em>Talat Kuyuk</em></p>\"\n    `);\n  });\n\n  test(\"strips any undefined frontmatters without giving an error\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      The title is {frontmatter.title} and {frontmatter.subtitle}.\n    `;\n\n    const { content, mod, frontmatter, scope, error } = await evaluate<Frontmatter>({\n      source,\n      options: {\n        parseFrontmatter: true,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter.title).toEqual(\"My Article\");\n    expect(scope).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>The title is My Article and .</p>\"`,\n    );\n  });\n\n  test(\"supports component names with a dot(.)\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: \"<motion.p />\",\n      components: {\n        // @ts-expect-error (2322) -- Issue caused by React 19 removing global JSX types,\n        // no match for the signature which affects the type inference for nested components in this case.\n        // Define your global JSX (for JSX.IntrinsicElements) in your project if need to use nested components.\n        motion: { p: () => <p>Hello world</p> },\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>Hello world</p>\"`,\n    );\n  });\n\n  test(\"renders fragments\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: \"<Test content={<>Renders fragments</>} />\",\n      components: {\n        Test: ({ content }: { content: string }) => <>{content}</>,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"Renders fragments\"`,\n    );\n  });\n\n  test(\"supports VFile\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: new VFile(\"foo **bar**\"),\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>foo <strong>bar</strong></p>\"`,\n    );\n  });\n\n  test(\"supports Buffer\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: Buffer.from(\"foo **bar**\"),\n    });\n\n    expect(mod).toEqual({});\n    expect(frontmatter).toEqual({});\n    expect(scope).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>foo <strong>bar</strong></p>\"`,\n    );\n  });\n\n  test(\"debug compiled source\", async () => {\n    const logSpy = vi.spyOn(console, \"log\").mockImplementation(() => {});\n\n    const result = await compile(new VFile(\"Hi\"));\n\n    await evaluate({\n      source: \"Hi\",\n      options: { debug: { compiledSource: true } },\n    });\n\n    expect(logSpy).toHaveBeenCalledTimes(1);\n    expect(logSpy).toHaveBeenCalledWith(String(result.compiledSource));\n\n    logSpy.mockRestore(); // Restore original console.log behavior\n  });\n});\n\ndescribe(\"vfileDataIntoScope in evaluate function\", () => {\n  test(\"works with no option 'vfileDataIntoScope'\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await evaluate({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toStrictEqual({});\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - true\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await evaluate({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        vfileDataIntoScope: true,\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toEqual({\n      matter: { title: \"My Article\" },\n      foo: \"foofoo\",\n      bar: \"barbar\",\n    });\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - string\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await evaluate({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        vfileDataIntoScope: \"foo\",\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toEqual({ foo: \"foofoo\" });\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - object\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await evaluate({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        vfileDataIntoScope: { name: \"bar\", as: \"zig\" },\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toEqual({ zig: \"barbar\" });\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - array\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await evaluate({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        vfileDataIntoScope: [\"foo\", { name: \"bar\", as: \"zig\" }],\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toEqual({ foo: \"foofoo\", zig: \"barbar\" });\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - frontmatter hack\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await evaluate({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        vfileDataIntoScope: { name: \"matter\", as: \"fronmatter\" },\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toEqual({ fronmatter: { title: \"My Article\" } });\n  });\n});\n\ndescribe(\"error handling in evaluate\", () => {\n  test(\"prints helpful message from compile MDX error\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      This is very bad syntax <GITHUB_USER>\n    `;\n\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source,\n      options: {\n        parseFrontmatter: true,\n        scope: { foo: \"foofoo\" },\n      },\n    });\n\n    if (!error) throw new Error(\"should have an error !\");\n\n    expect(frontmatter).toStrictEqual({ title: \"My Article\" });\n    expect(scope).toStrictEqual({ foo: \"foofoo\" });\n    expect(mod).toStrictEqual({});\n\n    expect(error).toMatchInlineSnapshot(`\n      [Error: [next-mdx-remote-client] error compiling MDX:\n      Expected a closing tag for \\`<GITHUB_USER>\\` (1:25-1:38) before the end of \\`paragraph\\`\n\n      > 1 | This is very bad syntax <GITHUB_USER>\n          |                         ^\n\n      More information: https://mdxjs.com/docs/troubleshooting-mdx]\n    `);\n\n    expect(content).toMatchInlineSnapshot(`\n      <div\n        className=\"mdx-empty\"\n      />\n    `);\n  });\n\n  test(\"missing a scope value causes runtime error during render\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: \"hi {bar}\",\n    });\n\n    expect(frontmatter).toStrictEqual({});\n    expect(scope).toStrictEqual({});\n    expect(mod).toStrictEqual({});\n    expect(error).toBeUndefined();\n\n    expect(() => {\n      ReactDOMServer.renderToStaticMarkup(content);\n    }).toThrow(\"bar is not defined\");\n  });\n\n  test(\"invalid identifier in scope causes syntax error during compile\", async () => {\n    const myScope = { [\"bar-baz\"]: \"ipikuka\" };\n\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: \"hi {bar-baz}\",\n      options: {\n        scope: myScope,\n      },\n    });\n\n    expect(frontmatter).toStrictEqual({});\n    expect(scope).toStrictEqual(myScope);\n    expect(mod).toStrictEqual({});\n    expect(error).toMatchInlineSnapshot(\n      `[SyntaxError: Arg string terminates parameters early]`,\n    );\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\n      \"<div class=\"mdx-empty\"></div>\"\n    `);\n  });\n\n  test(\"missing a component causes runtime error during render\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: \"hi <Test />\",\n    });\n\n    expect(frontmatter).toStrictEqual({});\n    expect(scope).toStrictEqual({});\n    expect(mod).toStrictEqual({});\n    expect(error).toBeUndefined();\n\n    expect(() => {\n      ReactDOMServer.renderToStaticMarkup(content);\n    }).toThrow(\n      \"Expected component `Test` to be defined: you likely forgot to import, pass, or provide it.\",\n    );\n  });\n\n  test(\"missing components can be escaped via a recma plugin without giving runtime error\", async () => {\n    const { content, mod, frontmatter, scope, error } = await evaluate({\n      source: \"hi <Test />\",\n      options: {\n        mdxOptions: {\n          recmaPlugins: [[recmaMdxEscapeMissingComponents, \"Test\"]],\n        },\n      },\n    });\n\n    expect(frontmatter).toStrictEqual({});\n    expect(scope).toStrictEqual({});\n    expect(mod).toStrictEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\"<p>hi </p>\"`);\n  });\n});\n"
  },
  {
    "path": "tests/test.original.compile.spec.tsx",
    "content": "import { test, expect } from \"vitest\";\n\nimport { compile } from \"@mdx-js/mdx\";\nimport dedent from \"dedent\";\n\ntest(\"provides understanding about differences of the compiled sources\", async () => {\n  const input = dedent`\n    # Hi\n\n    <Test />\n  `;\n\n  expect(\n    String(\n      await compile(input, {\n        providerImportSource: undefined,\n        outputFormat: \"function-body\",\n      }),\n    ),\n  ).toMatchInlineSnapshot(`\n    \"\"use strict\";\n    const {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\n    function _createMdxContent(props) {\n      const _components = {\n        h1: \"h1\",\n        ...props.components\n      }, {Test} = _components;\n      if (!Test) _missingMdxReference(\"Test\", true);\n      return _jsxs(_Fragment, {\n        children: [_jsx(_components.h1, {\n          children: \"Hi\"\n        }), \"\\\\n\", _jsx(Test, {})]\n      });\n    }\n    function MDXContent(props = {}) {\n      const {wrapper: MDXLayout} = props.components || ({});\n      return MDXLayout ? _jsx(MDXLayout, {\n        ...props,\n        children: _jsx(_createMdxContent, {\n          ...props\n        })\n      }) : _createMdxContent(props);\n    }\n    return {\n      default: MDXContent\n    };\n    function _missingMdxReference(id, component) {\n      throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" \\`\" + id + \"\\` to be defined: you likely forgot to import, pass, or provide it.\");\n    }\n    \"\n  `);\n\n  expect(\n    String(\n      await compile(input, {\n        providerImportSource: \"#\",\n        outputFormat: \"function-body\",\n      }),\n    ),\n  ).toMatchInlineSnapshot(`\n    \"\"use strict\";\n    const {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\n    const {useMDXComponents: _provideComponents} = arguments[0];\n    function _createMdxContent(props) {\n      const _components = {\n        h1: \"h1\",\n        ..._provideComponents(),\n        ...props.components\n      }, {Test} = _components;\n      if (!Test) _missingMdxReference(\"Test\", true);\n      return _jsxs(_Fragment, {\n        children: [_jsx(_components.h1, {\n          children: \"Hi\"\n        }), \"\\\\n\", _jsx(Test, {})]\n      });\n    }\n    function MDXContent(props = {}) {\n      const {wrapper: MDXLayout} = {\n        ..._provideComponents(),\n        ...props.components\n      };\n      return MDXLayout ? _jsx(MDXLayout, {\n        ...props,\n        children: _jsx(_createMdxContent, {\n          ...props\n        })\n      }) : _createMdxContent(props);\n    }\n    return {\n      default: MDXContent\n    };\n    function _missingMdxReference(id, component) {\n      throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" \\`\" + id + \"\\` to be defined: you likely forgot to import, pass, or provide it.\");\n    }\n    \"\n  `);\n\n  expect(\n    String(\n      await compile(input, {\n        providerImportSource: \"@mdx-js/react\",\n        outputFormat: \"function-body\",\n      }),\n    ),\n  ).toMatchInlineSnapshot(`\n    \"\"use strict\";\n    const {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\n    const {useMDXComponents: _provideComponents} = arguments[0];\n    function _createMdxContent(props) {\n      const _components = {\n        h1: \"h1\",\n        ..._provideComponents(),\n        ...props.components\n      }, {Test} = _components;\n      if (!Test) _missingMdxReference(\"Test\", true);\n      return _jsxs(_Fragment, {\n        children: [_jsx(_components.h1, {\n          children: \"Hi\"\n        }), \"\\\\n\", _jsx(Test, {})]\n      });\n    }\n    function MDXContent(props = {}) {\n      const {wrapper: MDXLayout} = {\n        ..._provideComponents(),\n        ...props.components\n      };\n      return MDXLayout ? _jsx(MDXLayout, {\n        ...props,\n        children: _jsx(_createMdxContent, {\n          ...props\n        })\n      }) : _createMdxContent(props);\n    }\n    return {\n      default: MDXContent\n    };\n    function _missingMdxReference(id, component) {\n      throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" \\`\" + id + \"\\` to be defined: you likely forgot to import, pass, or provide it.\");\n    }\n    \"\n  `);\n\n  expect(\n    String(\n      await compile(input, {\n        providerImportSource: \"@mdx-js/react\",\n        outputFormat: \"program\",\n      }),\n    ),\n  ).toMatchInlineSnapshot(`\n    \"import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from \"react/jsx-runtime\";\n    import {useMDXComponents as _provideComponents} from \"@mdx-js/react\";\n    function _createMdxContent(props) {\n      const _components = {\n        h1: \"h1\",\n        ..._provideComponents(),\n        ...props.components\n      }, {Test} = _components;\n      if (!Test) _missingMdxReference(\"Test\", true);\n      return _jsxs(_Fragment, {\n        children: [_jsx(_components.h1, {\n          children: \"Hi\"\n        }), \"\\\\n\", _jsx(Test, {})]\n      });\n    }\n    export default function MDXContent(props = {}) {\n      const {wrapper: MDXLayout} = {\n        ..._provideComponents(),\n        ...props.components\n      };\n      return MDXLayout ? _jsx(MDXLayout, {\n        ...props,\n        children: _jsx(_createMdxContent, {\n          ...props\n        })\n      }) : _createMdxContent(props);\n    }\n    function _missingMdxReference(id, component) {\n      throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" \\`\" + id + \"\\` to be defined: you likely forgot to import, pass, or provide it.\");\n    }\n    \"\n  `);\n});\n"
  },
  {
    "path": "tests/test.run.spec.tsx",
    "content": "import { describe, test, expect } from \"vitest\";\n\nimport { VFile } from \"vfile\";\nimport dedent from \"dedent\";\n\nimport { runSync } from \"../src/lib/run.js\";\nimport { compile } from \"../src/lib/compile.js\";\n\n/**\n * a rehearsal of runSync without actual jsxRuntime\n */\nfunction runSync_(\n  compiledSource: string,\n  options?: { scope?: Record<string, unknown>; frontmatter?: Record<string, unknown> },\n) {\n  const constructionScope = {\n    mdxOptions: { jsx: () => null }, // do nothing\n    frontmatter: options?.frontmatter,\n    ...options?.scope,\n  };\n\n  const keys = Object.keys(constructionScope);\n  const values = Object.values(constructionScope);\n\n  const SyncFunction = function () {}.constructor;\n\n  const hydrateFn = Reflect.construct(SyncFunction, keys.concat(compiledSource));\n  return hydrateFn(...values).default ?? hydrateFn(...values);\n}\n\ndescribe(\"runSync_\", () => {\n  test(\"function construction\", async () => {\n    const compiledSource = dedent`\n      const Test = foo;\n      if (!Test) _missingMdxReference();\n      function _missingMdxReference() {\n        throw new Error(\"Expected Error\");\n      }\n      return Test;\n    `;\n\n    const SyncFunction = function () {}.constructor;\n\n    const hydrateFn = Reflect.construct(SyncFunction, [\"foo\", compiledSource]);\n    const hydrateFn2 = Reflect.construct(SyncFunction, [\"bar\", compiledSource]);\n\n    expect(hydrateFn(\"foofoo\")).toEqual(\"foofoo\");\n\n    try {\n      hydrateFn();\n    } catch (error) {\n      expect((error as Error).message).toBe(\"Expected Error\");\n    }\n\n    try {\n      const foo = undefined;\n      hydrateFn(foo);\n    } catch (error) {\n      expect((error as Error).message).toBe(\"Expected Error\");\n    }\n\n    try {\n      const bar = \"bar\";\n      hydrateFn2(bar);\n    } catch (error) {\n      expect((error as Error).message).toBe(\"foo is not defined\");\n    }\n  });\n\n  test(\"throws error when return a value\", async () => {\n    const compiledSource = dedent`\n      const Test = foo;\n      if (!Test) _missingMdxReference();\n      function _missingMdxReference() {\n        throw new Error(\"Expected Error\");\n      }\n      return Test;\n    `;\n\n    expect(runSync_(compiledSource, { scope: { foo: \"foofoo\" } })).toEqual(\"foofoo\");\n\n    try {\n      runSync_(compiledSource);\n    } catch (error) {\n      expect((error as Error).message).toBe(\"foo is not defined\");\n    }\n\n    try {\n      runSync_(compiledSource, { scope: { foo: undefined } });\n    } catch (error) {\n      expect((error as Error).message).toBe(\"Expected Error\");\n    }\n  });\n\n  test(\"doesn't throw error when return default export with a module\", async () => {\n    const compiledSource = dedent`\n      \"use strict\";\n      const {jsx: _jsx} = arguments[0];\n      function _createMdxContent(props) {\n        const _components = {}, {Test} = _components;\n        if (!Test) _missingMdxReference();\n        return _jsx(Test);\n      }\n      function _missingMdxReference() {\n        throw new Error(\"Error: missing component\");\n      }\n      return {\n        default: _createMdxContent\n      }\n    `;\n\n    expect(runSync_(compiledSource)).toMatchInlineSnapshot(`[Function]`);\n\n    try {\n      runSync_(compiledSource);\n    } catch (error) {\n      // doesn't throw an error, the snapshot is empty !\n      expect((error as Error).message).toMatchInlineSnapshot();\n    }\n  });\n\n  test(\"throws error when return default export with a value\", async () => {\n    const compiledSource = dedent`\n      \"use strict\";\n      const {jsx: _jsx} = arguments[0];\n      const _components = {}, {Test} = _components;\n      if (!Test) _missingMdxReference();\n      function _missingMdxReference() {\n        throw new Error(\"Error: missing component\");\n      }\n      return {\n        default: Test\n      }\n    `;\n\n    try {\n      runSync_(compiledSource);\n    } catch (error) {\n      expect((error as Error).message).toBe(\"Error: missing component\");\n    }\n  });\n});\n\ndescribe(\"runSync\", () => {\n  test(\"errors in runSync can't be catched\", async () => {\n    const result = await compile(new VFile(\"hi <Test bar={bar} />\"));\n    const compiledSource = String(result.compiledSource);\n\n    try {\n      // it doesn't throw error, sinse runSync returns a module to be rendered\n      runSync(compiledSource, { frontmatter: {}, scope: {} });\n    } catch (error) {\n      // Actually, <Test /> compenent is missing and \"bar\" is not defined but the snapshot is empty !\n      expect((error as Error).message).toMatchInlineSnapshot();\n    }\n  });\n\n  test(\"some errors (syntax error in compiled source) in runSync can be catched\", async () => {\n    const result = await compile(new VFile(\"import x from 'y'\"));\n    const compiledSource = String(result.compiledSource);\n\n    try {\n      runSync(compiledSource, { frontmatter: {}, scope: {} });\n    } catch (error) {\n      expect((error as Error).message).toMatchInlineSnapshot(\n        `\"await is only valid in async functions and the top level bodies of modules\"`,\n      );\n    }\n  });\n});\n"
  },
  {
    "path": "tests/test.serialize-hydrate.spec.tsx",
    "content": "import { describe, test, expect } from \"vitest\";\n\nimport ReactDOMServer from \"react-dom/server\";\nimport { VFile } from \"vfile\";\nimport dedent from \"dedent\";\nimport remarkEmoji from \"remark-emoji\";\nimport remarkFlexibleMarkers from \"remark-flexible-markers\";\nimport recmaMdxChangeProps from \"recma-mdx-change-props\";\nimport recmaMdxEscapeMissingComponents from \"recma-mdx-escape-missing-components\";\n\nimport { hydrate } from \"../src/csr\";\nimport { serialize, type SerializeOptions } from \"../src/csr/serialize.js\";\n\ntype Frontmatter = { title: string };\n\ndescribe(\"serialize & hydrate\", () => {\n  test(\"simple\", async () => {\n    const mdxSource = await serialize({\n      source: \"foo **bar**\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>foo <strong>bar</strong></p>\"`,\n    );\n  });\n\n  test(\"with component\", async () => {\n    const mdxSource = await serialize({\n      source: 'foo <Test name=\"test\" />',\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate({\n      ...mdxSource,\n      components: {\n        Test: ({ name }: { name: string }) => <span>hello {name}</span>,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>foo <span>hello test</span></p>\"`,\n    );\n  });\n\n  test(\"with some remarkPlugins in mdxOptions\", async () => {\n    const serializeOptions: SerializeOptions = {\n      mdxOptions: {\n        remarkPlugins: [remarkFlexibleMarkers, remarkEmoji],\n      },\n    };\n\n    const mdxSource = await serialize({\n      source: \"==hello :tada: Talat Kuyuk==\",\n      options: serializeOptions,\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p><mark class=\"flexible-marker flexible-marker-default\">hello 🎉 Talat Kuyuk</mark></p>\"`,\n    );\n  });\n\n  test(\"with scope\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi {bar}\",\n      options: {\n        scope: {\n          bar: \"ipikuka\",\n        },\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({ bar: \"ipikuka\" });\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>hi ipikuka</p>\"`,\n    );\n  });\n\n  test(\"with scope and component\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi <Test name={bar} />\",\n      options: {\n        scope: {\n          bar: \"ipikuka\",\n        },\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({ bar: \"ipikuka\" });\n\n    const { content, mod, error } = hydrate({\n      ...mdxSource,\n      components: {\n        Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>hi <strong>ipikuka</strong></p>\"`,\n    );\n  });\n\n  test(\"with scope in which consists props key escaped with no reason\", async () => {\n    const source = dedent`\n      Hi {props.bar}\n      <Test name={props.foo} />\n    `;\n    const mdxSource = await serialize({\n      source,\n      options: {\n        scope: {\n          props: {\n            bar: \"barbar\",\n            foo: \"foofoo\",\n          },\n        },\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope.props.bar).toEqual(\"barbar\");\n    expect(mdxSource.scope.props.foo).toEqual(\"foofoo\");\n\n    const { content, mod, error } = hydrate({\n      ...mdxSource,\n      components: {\n        Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\n      \"<p>Hi </p>\n      <strong></strong>\"\n    `);\n  });\n\n  test(\"with scope in which consists props key works as expected using a recma plugin\", async () => {\n    const source = dedent`\n      Hi {props.bar}\n      <Test name={props.foo} />\n    `;\n    const mdxSource = await serialize({\n      source,\n      options: {\n        scope: {\n          props: {\n            bar: \"barbar\",\n            foo: \"foofoo\",\n          },\n        },\n        mdxOptions: {\n          recmaPlugins: [recmaMdxChangeProps],\n        },\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope.props.bar).toEqual(\"barbar\");\n    expect(mdxSource.scope.props.foo).toEqual(\"foofoo\");\n\n    const { content, mod, error } = hydrate({\n      ...mdxSource,\n      components: {\n        Test: ({ name }: { name: string }) => <strong>{name}</strong>,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\n      \"<p>Hi barbar</p>\n      <strong>foofoo</strong>\"\n    `);\n  });\n\n  test(\"with frontmatter supplying frontmatter's type argument\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      ## {frontmatter.title}\n    `;\n\n    // there is a type argument for serialize\n    const mdxSource = await serialize<Frontmatter>({\n      source,\n      options: {\n        parseFrontmatter: true,\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter.title).toEqual(\"My Article\");\n    expect(mdxSource.scope).toEqual({});\n\n    // @ts-expect-error\n    expect(mdxSource.frontmatter.blah).toBeUndefined();\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<h2>My Article</h2>\"`,\n    );\n  });\n\n  test(\"with frontmatter without supplying frontmatter's type argument\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      ## {frontmatter.title}\n    `;\n\n    // there is no type argument for serialize\n    const mdxSource = await serialize({\n      source,\n      options: {\n        parseFrontmatter: true,\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter.title).toEqual(\"My Article\");\n    expect(mdxSource.scope).toEqual({});\n\n    // it doesn't give any Typescript error\n    expect(mdxSource.frontmatter.blah).toBeUndefined();\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<h2>My Article</h2>\"`,\n    );\n  });\n\n  test(\"with frontmatter and scope\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      # {frontmatter.title}\n      Hi *{name}*\n    `;\n\n    const mdxSource = await serialize<Frontmatter>({\n      source,\n      options: {\n        parseFrontmatter: true,\n        scope: { name: \"Talat Kuyuk\" },\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter.title).toEqual(\"My Article\");\n    expect(mdxSource.scope).toEqual({ name: \"Talat Kuyuk\" });\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\n      \"<h1>My Article</h1>\n      <p>Hi <em>Talat Kuyuk</em></p>\"\n    `);\n  });\n\n  test(\"strips any undefined frontmatters without giving an error\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      The title is {frontmatter.title} and {frontmatter.subtitle}.\n    `;\n\n    const mdxSource = await serialize<Frontmatter>({\n      source,\n      options: {\n        parseFrontmatter: true,\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter.title).toEqual(\"My Article\");\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>The title is My Article and .</p>\"`,\n    );\n  });\n\n  test(\"parsed frontmatter should be supplied on the client side\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      The title is {frontmatter.title}\n    `;\n\n    const mdxSource = await serialize<Frontmatter>({\n      source,\n      options: {\n        parseFrontmatter: true,\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter.title).toEqual(\"My Article\");\n    expect(mdxSource.scope).toEqual({});\n\n    const {\n      content: content,\n      mod,\n      error,\n    } = hydrate({\n      compiledSource: mdxSource.compiledSource,\n      frontmatter: mdxSource.frontmatter,\n    });\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>The title is My Article</p>\"`,\n    );\n\n    const {\n      content: content_,\n      mod: mod_,\n      error: error_,\n    } = hydrate({\n      compiledSource: mdxSource.compiledSource,\n    });\n\n    expect(mod_).toEqual({});\n    expect(error_).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content_)).toMatchInlineSnapshot(\n      `\"<p>The title is </p>\"`,\n    );\n  });\n\n  test(\"supports component names with a dot(.)\", async () => {\n    const mdxSource = await serialize({\n      source: \"<motion.p />\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate({\n      ...mdxSource,\n      components: {\n        // @ts-expect-error (2322) -- Issue caused by React 19 removing global JSX types,\n        // no match for the signature which affects the type inference for nested components in this case.\n        // Define your global JSX (for JSX.IntrinsicElements) in your project if need to use nested components.\n        motion: { p: () => <p>Hello world</p> },\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>Hello world</p>\"`,\n    );\n  });\n\n  test(\"renders fragments\", async () => {\n    const mdxSource = await serialize({\n      source: \"<Test content={<>Renders fragments</>} />\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate({\n      ...mdxSource,\n      components: {\n        Test: ({ content }: { content: string }) => <>{content}</>,\n      },\n    });\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"Renders fragments\"`,\n    );\n  });\n\n  test(\"supports VFile\", async () => {\n    const mdxSource = await serialize({\n      source: new VFile(\"foo **bar**\"),\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>foo <strong>bar</strong></p>\"`,\n    );\n  });\n\n  test(\"supports Buffer\", async () => {\n    const mdxSource = await serialize({\n      source: Buffer.from(\"foo **bar**\"),\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<p>foo <strong>bar</strong></p>\"`,\n    );\n  });\n});\n\ndescribe(\"serialize & hydrate function with ESM exports\", () => {\n  test(\"works with `export` statements 1\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      export const name = 'world'\n      \n      # Hello {name.toUpperCase()}\n    `;\n\n    const mdxSource = await serialize<Frontmatter>({\n      source,\n      options: {\n        parseFrontmatter: true,\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({ title: \"My Article\" });\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(error).toBeUndefined();\n\n    expect(mod).toMatchObject({\n      name: \"world\",\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<h1>Hello WORLD</h1>\"`,\n    );\n  });\n\n  test(\"works with `export` statements 2\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      export const num = 1\n      export let str = 'foo';\n      export var bool = true\n      export function Component() {\n        return 'from component'\n      }\n\n      # {num} {str} {String(bool)} <Component />\n    `;\n\n    const mdxSource = await serialize<Frontmatter>({\n      source,\n      options: {\n        parseFrontmatter: true,\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({ title: \"My Article\" });\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(error).toBeUndefined();\n\n    expect(mod).toMatchObject({\n      Component: expect.any(Function),\n      bool: true,\n      num: 1,\n      str: \"foo\",\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<h1>1 foo true from component</h1>\"`,\n    );\n  });\n\n  test(\"remove all `export` statements\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      export const num = 1\n      export let str = 'foo';\n      export var bool = true\n\n      # Hi\n\n      export function Component() {\n        return 'from component'\n      }\n    `;\n\n    const mdxSource = await serialize<Frontmatter>({\n      source,\n      options: {\n        disableExports: true,\n        parseFrontmatter: true,\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({ title: \"My Article\" });\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\"<h1>Hi</h1>\"`);\n  });\n});\n\ndescribe(\"vfileDataIntoScope in serialize function\", () => {\n  test(\"works with no option 'vfileDataIntoScope'\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await serialize<Frontmatter>({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toStrictEqual({});\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - true\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await serialize<Frontmatter>({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        vfileDataIntoScope: true,\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toEqual({\n      matter: { title: \"My Article\" },\n      foo: \"foofoo\",\n      bar: \"barbar\",\n    });\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - string\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await serialize<Frontmatter>({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        vfileDataIntoScope: \"foo\",\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toEqual({ foo: \"foofoo\" });\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - object\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await serialize<Frontmatter>({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        vfileDataIntoScope: { name: \"bar\", as: \"zig\" },\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toEqual({ zig: \"barbar\" });\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - array\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await serialize<Frontmatter>({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        vfileDataIntoScope: [\"foo\", { name: \"bar\", as: \"zig\" }],\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toEqual({ foo: \"foofoo\", zig: \"barbar\" });\n  });\n\n  test(\"works the option 'vfileDataIntoScope' - frontmatter hack\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      Hello\n    `;\n\n    const { scope } = await serialize<Frontmatter>({\n      source,\n      options: {\n        scope: {},\n        parseFrontmatter: true,\n        vfileDataIntoScope: { name: \"matter\", as: \"fronmatter\" },\n        mdxOptions: {\n          remarkPlugins: [\n            () => (_, file) => {\n              file.data[\"foo\"] = \"foofoo\";\n              file.data[\"bar\"] = \"barbar\";\n            },\n          ],\n        },\n      },\n    });\n\n    expect(scope).toEqual({ fronmatter: { title: \"My Article\" } });\n  });\n});\n\ndescribe(\"error handling in serialize & hydrate\", () => {\n  test(\"prints helpful message from compile error\", async () => {\n    const source = dedent`\n      ---\n      title: 'My Article'\n      ---\n      This is very bad <GITHUB_USER>\n    `;\n\n    const mdxSource = await serialize({\n      source,\n      options: {\n        parseFrontmatter: true,\n        scope: { foo: \"foofoo\" },\n      },\n    });\n\n    if (\"compiledSource\" in mdxSource) throw new Error(\"should have an error !\");\n\n    expect(mdxSource.frontmatter).toStrictEqual({ title: \"My Article\" });\n    expect(mdxSource.scope).toStrictEqual({ foo: \"foofoo\" });\n\n    expect(mdxSource.error.message).toMatchInlineSnapshot(`\n      \"[next-mdx-remote-client] error compiling MDX:\n      Expected a closing tag for \\`<GITHUB_USER>\\` (1:18-1:31) before the end of \\`paragraph\\`\n\n      > 1 | This is very bad <GITHUB_USER>\n          |                  ^\n\n      More information: https://mdxjs.com/docs/troubleshooting-mdx\"\n    `);\n  });\n\n  test(\"missing a scope value causes runtime error during render\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi {bar}\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(content).toMatchInlineSnapshot(`<MDXContent />`);\n\n    expect(() => {\n      ReactDOMServer.renderToStaticMarkup(content);\n    }).toThrow(\"bar is not defined\");\n  });\n\n  test(\"invalid identifier in scope causes syntax error during compile\", async () => {\n    const myScope = { [\"bar-baz\"]: \"ipikuka\" };\n\n    const mdxSource = await serialize({\n      source: \"hi {bar-baz}\",\n      options: {\n        scope: myScope,\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual(myScope);\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toMatchInlineSnapshot(\n      `[SyntaxError: Arg string terminates parameters early]`,\n    );\n\n    expect(content).toMatchInlineSnapshot(`\n      <div\n        className=\"mdx-empty\"\n      />\n    `);\n  });\n\n  test(\"missing a component causes runtime error during render\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi <Test />\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(content).toMatchInlineSnapshot(`<MDXContent />`);\n\n    expect(() => {\n      ReactDOMServer.renderToStaticMarkup(content);\n    }).toThrow(\n      \"Expected component `Test` to be defined: you likely forgot to import, pass, or provide it.\",\n    );\n  });\n\n  test(\"missing components can be escaped via a recma plugin without giving runtime error\", async () => {\n    const mdxSource = await serialize({\n      source: \"hi <Test />\",\n      options: {\n        mdxOptions: {\n          recmaPlugins: [[recmaMdxEscapeMissingComponents, \"Test\"]],\n        },\n      },\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n    expect(error).toBeUndefined();\n\n    expect(content).toMatchInlineSnapshot(`<MDXContent />`);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(`\"<p>hi </p>\"`);\n  });\n\n  test(\"syntax error in compiled source can be catched in hydrate\", async () => {\n    const mdxSource = await serialize({\n      source: \"import x from 'y'\",\n    });\n\n    if (\"error\" in mdxSource) throw new Error(\"shouldn't have any MDX syntax error\");\n\n    expect(mdxSource.frontmatter).toEqual({});\n    expect(mdxSource.scope).toEqual({});\n\n    const { content, mod, error } = hydrate(mdxSource);\n\n    expect(mod).toEqual({});\n\n    expect(error).toMatchInlineSnapshot(\n      `[SyntaxError: await is only valid in async functions and the top level bodies of modules]`,\n    );\n\n    expect(content).toMatchInlineSnapshot(`\n      <div\n        className=\"mdx-empty\"\n      />\n    `);\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div class=\"mdx-empty\"></div>\"`,\n    );\n  });\n});\n"
  },
  {
    "path": "tests/test.utils.spec.ts",
    "content": "import { describe, test, expect } from \"vitest\";\n\nimport type { SourceLocation } from \"@babel/code-frame\";\nimport dedent from \"dedent\";\n\nimport { getFrontmatter } from \"../src/utils\";\nimport { createFormattedMDXError, passVfileDataIntoScope } from \"../src/lib/util\";\n\ndescribe(\"getFrontmatter\", () => {\n  type Frontmatter = { title: string };\n\n  test(\"works as expected without generic type\", async () => {\n    const source = dedent`\n      ---\n\t    title: 'my title'\n\t    ---\n\t    Hi\n    `;\n\n    const { frontmatter, strippedSource } = getFrontmatter(source);\n\n    expect(frontmatter.title).toEqual(\"my title\");\n\n    // don't need to put @ts-expect-error since it is Record<string, unknown>\n    expect(frontmatter.blah).toBeUndefined();\n\n    expect(strippedSource).toEqual(\"Hi\");\n  });\n\n  test(\"works as expected with generic type\", async () => {\n    const source = dedent`\n      ---\n      title: 'my title'\n      ---\n      Hi\n    `;\n\n    const { frontmatter } = getFrontmatter<Frontmatter>(source);\n\n    // @ts-expect-error\n    expect(frontmatter.blah).toBeUndefined();\n  });\n\n  test(\"returns empty object if no frontmatter\", async () => {\n    const source = \"Hi\";\n\n    const { frontmatter } = getFrontmatter<Frontmatter>(source);\n\n    expect(frontmatter).toStrictEqual({});\n  });\n});\n\ndescribe(\"passVfileDataIntoScope\", () => {\n  test(\"works as expected via 'true'\", () => {\n    const data = {\n      toc: [1, 2, 3],\n      mog: \"mogmog\",\n    };\n\n    const scope: Record<string, unknown> = {};\n\n    passVfileDataIntoScope(data, true, scope);\n\n    expect(scope).toHaveProperty(\"toc\");\n    expect(scope[\"toc\"]).toEqual([1, 2, 3]);\n    expect(scope).toHaveProperty(\"mog\");\n    expect(scope[\"mog\"]).toEqual(\"mogmog\");\n\n    (scope.toc as Array<number>).push(4);\n    expect(data.toc).toEqual([1, 2, 3, 4]);\n  });\n\n  test(\"works as expected via 'string'\", () => {\n    const data = {\n      toc: [1, 2, 3],\n      mog: \"mogmog\",\n    };\n\n    const scope: Record<string, unknown> = {};\n\n    passVfileDataIntoScope(data, \"toc\", scope);\n\n    expect(scope).toHaveProperty(\"toc\");\n    expect(scope[\"toc\"]).toEqual([1, 2, 3]);\n    expect(scope).not.toHaveProperty(\"mog\");\n\n    (scope.toc as Array<number>).push(4);\n    expect(data.toc).toEqual([1, 2, 3, 4]);\n  });\n\n  test(\"works as expected via 'name' and 'as'\", () => {\n    const data = {\n      toc: [1, 2, 3],\n      mog: \"mogmog\",\n    };\n\n    const scope: Record<string, unknown> = {};\n\n    passVfileDataIntoScope(data, { name: \"toc\", as: \"heading\" }, scope);\n\n    expect(scope).not.haveOwnProperty(\"toc\");\n    expect(scope).toHaveProperty(\"heading\");\n    expect(scope[\"heading\"]).toEqual([1, 2, 3]);\n    expect(scope).not.toHaveProperty(\"mog\");\n\n    (scope.heading as Array<number>).push(4);\n    expect(data.toc).toEqual([1, 2, 3, 4]);\n  });\n\n  test(\"works as expected via 'array'\", () => {\n    const data = {\n      toc: [1, 2, 3],\n      mog: \"mogmog\",\n    };\n\n    const scope: Record<string, unknown> = {};\n\n    passVfileDataIntoScope(data, [\"mog\", { name: \"toc\", as: \"heading\" }], scope);\n\n    expect(scope).not.haveOwnProperty(\"toc\");\n    expect(scope).toHaveProperty(\"heading\");\n    expect(scope[\"heading\"]).toEqual([1, 2, 3]);\n    expect(scope).toHaveProperty(\"mog\");\n    expect(scope[\"mog\"]).toEqual(\"mogmog\");\n\n    (scope.heading as Array<number>).push(4);\n    expect(data.toc).toEqual([1, 2, 3, 4]);\n  });\n});\n\ndescribe(\"createFormattedMDXError\", () => {\n  test(\"with standart error\", async () => {\n    const source = dedent`\n      ---\n      title: 'my title'\n      ---\n      Hi <GITHUB_USER>\n    `;\n\n    const myError = new Error(\"something went wrong\");\n    const formattedError = createFormattedMDXError(myError, source);\n\n    expect(formattedError.message).toMatchInlineSnapshot(`\n      \"[next-mdx-remote-client] error compiling MDX:\n      something went wrong\n\n      More information: https://mdxjs.com/docs/troubleshooting-mdx\"\n    `);\n  });\n\n  test(\"with implicitly positioned error\", async () => {\n    const source = dedent`\n      ---\n      title: 'my title'\n      ---\n      Hi <GITHUB_USER>\n    `;\n\n    const positionedError = new Error(\n      \"Expected a closing tag for `<GITHUB_USER>` (1:4-1:17) before the end of `paragraph`\",\n    );\n\n    const strippedSource = getFrontmatter(source).strippedSource;\n\n    const formattedError = createFormattedMDXError(positionedError, strippedSource);\n\n    /*\n\t[1:1-1:17: Expected a closing tag for `<GITHUB_USER>` (1:4-1:17) before the end of `paragraph`] {\n\t\tancestors: undefined,\n\t\tcause: undefined,\n\t\tcolumn: 1,\n\t\tfatal: undefined,\n\t\tline: 1,\n\t\tplace: {\n\t\t\tstart: { line: 1, column: 1, offset: 0, _index: 0, _bufferIndex: 0 },\n\t\t\tend: { line: 1, column: 17, offset: 16, _index: 1, _bufferIndex: -1 }\n\t\t},\n\t\treason: 'Expected a closing tag for `<GITHUB_USER>` (1:4-1:17) before the end of `paragraph`',\n\t\truleId: 'end-tag-mismatch',\n\t\tsource: 'mdast-util-mdx-jsx'\n\t}  \n\t*/\n\n    expect(formattedError.message).toMatchInlineSnapshot(`\n      \"[next-mdx-remote-client] error compiling MDX:\n      Expected a closing tag for \\`<GITHUB_USER>\\` (1:4-1:17) before the end of \\`paragraph\\`\n\n      > 1 | Hi <GITHUB_USER>\n          |    ^\n\n      More information: https://mdxjs.com/docs/troubleshooting-mdx\"\n    `);\n  });\n\n  test(\"with explicitly positioned error\", async () => {\n    const source = dedent`\n      target x as error\n    `;\n\n    const positionedError: Error & { position?: SourceLocation } = new Error(\n      \"The char x is targetted as error\",\n    );\n\n    positionedError[\"position\"] = { start: { line: 1, column: 8 } };\n\n    const formattedError = createFormattedMDXError(positionedError, source);\n\n    expect(formattedError.message).toMatchInlineSnapshot(`\n      \"[next-mdx-remote-client] error compiling MDX:\n      The char x is targetted as error\n\n      > 1 | target x as error\n          |        ^\n\n      More information: https://mdxjs.com/docs/troubleshooting-mdx\"\n    `);\n  });\n});\n"
  },
  {
    "path": "tests/test.wrapper.spec.tsx",
    "content": "import { describe, test, expect } from \"vitest\";\n\nimport React from \"react\";\nimport ReactDOMServer from \"react-dom/server\";\n\nimport { evaluate, type MDXComponents } from \"../src/rsc\";\n\ndescribe(\"evaluate function with wrapper\", () => {\n  test(\"wrapper component - 1\", async () => {\n    const { content } = await evaluate({\n      source: \"foo **bar**\",\n      components: {\n        wrapper: \"div\",\n      },\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div components=\"[object Object]\"><p>foo <strong>bar</strong></p></div>\"`,\n    );\n  });\n\n  test(\"wrapper component - 2\", async () => {\n    const { content } = await evaluate({\n      source: \"foo **bar**\",\n      components: {\n        wrapper(props: React.ComponentProps<\"div\"> & { components: MDXComponents }) {\n          const { components, ...rest } = props; // eslint-disable-line @typescript-eslint/no-unused-vars\n          return <div id=\"layout\" {...rest} />;\n        },\n      },\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div id=\"layout\"><p>foo <strong>bar</strong></p></div>\"`,\n    );\n  });\n\n  test(\"wrapper component - 3 - extract the prop 'components'\", async () => {\n    const { content } = await evaluate({\n      source: \"foo **bar**\",\n      components: {\n        wrapper(props: React.ComponentProps<\"div\"> & { components: MDXComponents }) {\n          const { components, ...rest } = props; // eslint-disable-line @typescript-eslint/no-unused-vars\n          return React.createElement(\"article\", { id: \"custom-article\", ...rest });\n        },\n      },\n    });\n\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<article id=\"custom-article\"><p>foo <strong>bar</strong></p></article>\"`,\n    );\n  });\n\n  test(\"wrapper component without supplying props\", async () => {\n    const { content } = await evaluate({\n      source: \"foo **bar**\",\n      components: {\n        wrapper() {\n          return <div id=\"layout\" />;\n        },\n      },\n    });\n\n    // it didn't render the mdx\n    expect(ReactDOMServer.renderToStaticMarkup(content)).toMatchInlineSnapshot(\n      `\"<div id=\"layout\"></div>\"`,\n    );\n  });\n});\n"
  },
  {
    "path": "tests/utils/index.ts",
    "content": "import { act, type ReactElement } from \"react\";\nimport reactDom from \"react-dom/server\";\nimport { PassThrough } from \"stream\";\n\ntype RenderOptions = {\n  stripReactSSRComments?: boolean;\n};\n\n/**\n * Render a React element to a string using streaming SSR.\n * @param element React element to render\n * @param options If stripReactSSRComments is true, removes <!-- --> or <!--$--> inserted by React streaming SSR\n */\nexport async function renderToStringFromStream(\n  element: ReactElement,\n  options: RenderOptions = {},\n) {\n  const { stripReactSSRComments } = options;\n\n  return new Promise<string>((resolve, reject) => {\n    const stream = new PassThrough();\n    let html = \"\";\n\n    stream.on(\"data\", (chunk) => (html += chunk));\n    stream.on(\"end\", () => {\n      if (stripReactSSRComments) {\n        // Remove internal markers <!-- --> and streaming root markers <!--$--> / <!--/$-->\n        html = html\n          .replace(/<!--\\$-->/g, \"\")\n          .replace(/<!--\\/\\$-->/g, \"\")\n          .replace(/<!--\\s*-->/g, \"\");\n      }\n      resolve(html);\n    });\n    stream.on(\"error\", reject);\n\n    act(() => {\n      const { pipe } = reactDom.renderToPipeableStream(element, {\n        onAllReady() {\n          pipe(stream);\n        },\n        onError(error) {\n          reject(error);\n        },\n      });\n    });\n  });\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"ESNext\", \"DOM\"],\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Node\",\n    \"jsx\": \"react-jsx\",\n    \"strict\": true,\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"sourceMap\": true,\n    \"inlineSources\": true,\n    \"outDir\": \"dist\",\n    \"noImplicitReturns\": true,\n    \"noImplicitThis\": false\n  },\n  \"include\": [\"./src\"]\n}\n"
  },
  {
    "path": "vite.config.js",
    "content": "import { defineConfig } from \"vite\";\nimport { coverageConfigDefaults } from \"vitest/config\";\nimport react from \"@vitejs/plugin-react-swc\";\n\n/// <reference types=\"vitest\" />\nexport default defineConfig({\n  plugins: [react()],\n  test: {\n    environment: \"jsdom\",\n    setupFiles: [\"./vitest-setup-tests.js\"],\n    include: [\"tests/**/*.spec.ts?(x)\"],\n    poolOptions: {\n      vmThreads: {\n        memoryLimit: \"1 MB\",\n      },\n    },\n    coverage: {\n      provider: \"v8\",\n      reporter: [\n        [\"lcov\", { projectRoot: \"./src\" }],\n        [\"json\", { file: \"coverage.json\" }],\n        \"text\",\n      ],\n      thresholds: {\n        lines: 100,\n        functions: 100,\n        branches: 100,\n        statements: 100,\n      },\n      exclude: [\n        \"archive\",\n        \"tests\",\n        \"**/types.ts\",\n        \"**/*.d.ts\",\n        \"src/csr/idle-callback-polyfill.js\",\n        ...coverageConfigDefaults.exclude,\n      ],\n    },\n  },\n});\n"
  },
  {
    "path": "vitest-setup-tests.js",
    "content": "import \"@testing-library/jest-dom/vitest\";\n\nimport { afterEach } from \"vitest\";\nimport { cleanup } from \"@testing-library/react\";\n\nafterEach(() => {\n  cleanup();\n});\n"
  }
]