diff options
Diffstat (limited to 'packages/integrations')
75 files changed, 643 insertions, 1154 deletions
diff --git a/packages/integrations/alpinejs/package.json b/packages/integrations/alpinejs/package.json index 50662b3b6..8c61fdaf5 100644 --- a/packages/integrations/alpinejs/package.json +++ b/packages/integrations/alpinejs/package.json @@ -41,7 +41,7 @@ "@playwright/test": "1.49.0", "astro": "workspace:*", "astro-scripts": "workspace:*", - "vite": "^5.4.11" + "vite": "^6.0.1" }, "publishConfig": { "provenance": true diff --git a/packages/integrations/lit/.gitignore b/packages/integrations/lit/.gitignore deleted file mode 100644 index 40b878db5..000000000 --- a/packages/integrations/lit/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules/
\ No newline at end of file diff --git a/packages/integrations/lit/CHANGELOG.md b/packages/integrations/lit/CHANGELOG.md deleted file mode 100644 index 0aa8f4f71..000000000 --- a/packages/integrations/lit/CHANGELOG.md +++ /dev/null @@ -1,306 +0,0 @@ -# @astrojs/lit - -## 4.3.0 - -### Minor Changes - -- [#11234](https://github.com/withastro/astro/pull/11234) [`4385bf7`](https://github.com/withastro/astro/commit/4385bf7a4dc9c65bff53a30c660f7a909fcabfc9) Thanks [@ematipico](https://github.com/ematipico)! - Adds a new function called `addServerRenderer` to the Container API. Use this function to manually store renderers inside the instance of your container. - - This new function should be preferred when using the Container API in environments like on-demand pages: - - ```ts - import type { APIRoute } from 'astro'; - import { experimental_AstroContainer } from 'astro/container'; - import reactRenderer from '@astrojs/react/server.js'; - import vueRenderer from '@astrojs/vue/server.js'; - import ReactComponent from '../components/button.jsx'; - import VueComponent from '../components/button.vue'; - - // MDX runtime is contained inside the Astro core - import mdxRenderer from 'astro/jsx/server.js'; - - // In case you need to import a custom renderer - import customRenderer from '../renderers/customRenderer.js'; - - export const GET: APIRoute = async (ctx) => { - const container = await experimental_AstroContainer.create(); - container.addServerRenderer({ renderer: reactRenderer }); - container.addServerRenderer({ renderer: vueRenderer }); - container.addServerRenderer({ renderer: customRenderer }); - // You can pass a custom name too - container.addServerRenderer({ - name: 'customRenderer', - renderer: customRenderer, - }); - const vueComponent = await container.renderToString(VueComponent); - return await container.renderToResponse(Component); - }; - ``` - -## 4.2.0 - -### Minor Changes - -- [#11144](https://github.com/withastro/astro/pull/11144) [`803dd80`](https://github.com/withastro/astro/commit/803dd8061df02138b4928442bcb76e77dcf6f5e7) Thanks [@ematipico](https://github.com/ematipico)! - The integration now exposes a function called `getContainerRenderer`, that can be used inside the Container APIs to load the relative renderer. - - ```js - import { experimental_AstroContainer as AstroContainer } from 'astro/container'; - import ReactWrapper from '../src/components/ReactWrapper.astro'; - import { loadRenderers } from 'astro:container'; - import { getContainerRenderer } from '@astrojs/react'; - - test('ReactWrapper with react renderer', async () => { - const renderers = await loadRenderers([getContainerRenderer()]); - const container = await AstroContainer.create({ - renderers, - }); - const result = await container.renderToString(ReactWrapper); - - expect(result).toContain('Counter'); - expect(result).toContain('Count: <!-- -->5'); - }); - ``` - -## 4.1.0 - -### Minor Changes - -- [#11164](https://github.com/withastro/astro/pull/11164) [`cf9b2ff`](https://github.com/withastro/astro/commit/cf9b2ff7967c4287ab26ec65fc4bb2eed525a235) Thanks [@scottnath](https://github.com/scottnath)! - Removes deprecated `template` attribute and replaces deprecated domparser function - -## 4.0.1 - -### Patch Changes - -- [#9479](https://github.com/withastro/astro/pull/9479) [`1baf0b0d3cbd0564954c2366a7278794fad6726e`](https://github.com/withastro/astro/commit/1baf0b0d3cbd0564954c2366a7278794fad6726e) Thanks [@sarah11918](https://github.com/sarah11918)! - Updates README - -## 4.0.0 - -### Major Changes - -- [#8822](https://github.com/withastro/astro/pull/8822) [`b0a71946f`](https://github.com/withastro/astro/commit/b0a71946f4320d4e76f31e990fe5821f823f0e12) Thanks [@Geoffrey-Pliez](https://github.com/Geoffrey-Pliez)! - Upgrade to Lit 3.0 - -## 3.0.3 - -### Patch Changes - -- [#9018](https://github.com/withastro/astro/pull/9018) [`23c9a30ad`](https://github.com/withastro/astro/commit/23c9a30ad859398d62a013d639b5b2716b583331) Thanks [@augustjk](https://github.com/augustjk)! - Fix hydration ordering of nested custom elements. Child components will now wait for their parents to hydrate before hydrating themselves. - -## 3.0.2 - -### Patch Changes - -- [#8826](https://github.com/withastro/astro/pull/8826) [`754c40f6e`](https://github.com/withastro/astro/commit/754c40f6ed941a61362d221915568c04ae85d6ad) Thanks [@lilnasy](https://github.com/lilnasy)! - Fixed an issue where an incompatible version of lit was installed. - -## 3.0.1 - -### Patch Changes - -- [#8737](https://github.com/withastro/astro/pull/8737) [`6f60da805`](https://github.com/withastro/astro/commit/6f60da805e0014bc50dd07bef972e91c73560c3c) Thanks [@ematipico](https://github.com/ematipico)! - Add provenance statement when publishing the library from CI - -## 3.0.0 - -### Major Changes - -- [#8188](https://github.com/withastro/astro/pull/8188) [`d0679a666`](https://github.com/withastro/astro/commit/d0679a666f37da0fca396d42b9b32bbb25d29312) Thanks [@ematipico](https://github.com/ematipico)! - Remove support for Node 16. The lowest supported version by Astro and all integrations is now v18.14.1. As a reminder, Node 16 will be deprecated on the 11th September 2023. - -- [#8179](https://github.com/withastro/astro/pull/8179) [`6011d52d3`](https://github.com/withastro/astro/commit/6011d52d38e43c3e3d52bc3bc41a60e36061b7b7) Thanks [@matthewp](https://github.com/matthewp)! - Astro 3.0 Release Candidate - -## 3.0.0-rc.1 - -### Major Changes - -- [#8179](https://github.com/withastro/astro/pull/8179) [`6011d52d3`](https://github.com/withastro/astro/commit/6011d52d38e43c3e3d52bc3bc41a60e36061b7b7) Thanks [@matthewp](https://github.com/matthewp)! - Astro 3.0 Release Candidate - -## 3.0.0-beta.0 - -### Major Changes - -- [`1eae2e3f7`](https://github.com/withastro/astro/commit/1eae2e3f7d693c9dfe91c8ccfbe606d32bf2fb81) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Remove support for Node 16. The lowest supported version by Astro and all integrations is now v18.14.1. As a reminder, Node 16 will be deprecated on the 11th September 2023. - -## 2.1.1 - -### Patch Changes - -- [#7985](https://github.com/withastro/astro/pull/7985) [`ec06dd9bb`](https://github.com/withastro/astro/commit/ec06dd9bbb29cc38e891517fbf884cb7083b3240) Thanks [@delucis](https://github.com/delucis)! - Fix formatting in Lit README - -## 2.1.0 - -### Minor Changes - -- [#7373](https://github.com/withastro/astro/pull/7373) [`0986a44dd`](https://github.com/withastro/astro/commit/0986a44ddd2b48edbe318f6fceb7f4ce4670ce05) Thanks [@matthewp](https://github.com/matthewp)! - Upgrade lit dependencies - -## 2.0.2 - -### Patch Changes - -- [#7104](https://github.com/withastro/astro/pull/7104) [`826e02890`](https://github.com/withastro/astro/commit/826e0289005f645b902375b98d5549c6a95ccafa) Thanks [@bluwy](https://github.com/bluwy)! - Specify `"files"` field to only publish necessary files - -## 2.0.1 - -### Patch Changes - -- [#6752](https://github.com/withastro/astro/pull/6752) [`c7eb0d431`](https://github.com/withastro/astro/commit/c7eb0d431032edc5d4af72726d84e1c52ef36575) Thanks [@augustjk](https://github.com/augustjk)! - Provide `renderInfo` when rendering Lit components. Fixes issue with rendering nested components. - -## 2.0.0 - -### Major Changes - -- [#6681](https://github.com/withastro/astro/pull/6681) [`4b077318f`](https://github.com/withastro/astro/commit/4b077318fbc21c4350cc21c380d96b54d302759c) Thanks [@e111077](https://github.com/e111077)! - Update to use `@lit-labs/ssr@^3` - **[BREAKING]** DOM shim required for Lit SSR has been greatly reduced. `window`, `document`, and other objects are no longer available in global. Most SSR-ready component code should not be affected but, if so, they can be fixed with optional chaining or by using the `isServer` environment checker from the `lit` package. See [lit.dev docs on authoring components for SSR].(https://lit.dev/docs/ssr/authoring/#browser-only-code) - **[BREAKING]** Adds compatibility with `lit@2.7.0` hydration behavior. Do not update if you're using `lit@2.6.1` or lower. - Includes support for template[shadowrootmode] support. - -## 1.3.0 - -### Minor Changes - -- [#6213](https://github.com/withastro/astro/pull/6213) [`afbbc4d5b`](https://github.com/withastro/astro/commit/afbbc4d5bfafc1779bac00b41c2a1cb1c90f2808) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updated compilation settings to disable downlevelling for Node 14 - -## 1.2.1 - -### Patch Changes - -- [#6351](https://github.com/withastro/astro/pull/6351) [`26bf12ef3`](https://github.com/withastro/astro/commit/26bf12ef3c7ab874a23ac753f841f7bb329c9361) Thanks [@hrmcdonald](https://github.com/hrmcdonald)! - Render DSD attributes based on `shadowRootOptions` - -## 1.2.0 - -### Minor Changes - -- [#6111](https://github.com/withastro/astro/pull/6111) [`ec38a8921`](https://github.com/withastro/astro/commit/ec38a8921f02a275949abcababe1b8afdf8184a2) Thanks [@e111077](https://github.com/e111077)! - Implement client:only functionality in Lit and add lit to the client:only warning - -## 1.1.2 - -### Patch Changes - -- [#6080](https://github.com/withastro/astro/pull/6080) [`0db220415`](https://github.com/withastro/astro/commit/0db22041531d981a813a07f4c4e00cfb7ebddd51) Thanks [@e111077](https://github.com/e111077)! - Fixes Lit hydration not having the same reactive values as server (losing state upon hydration) - -- [#6055](https://github.com/withastro/astro/pull/6055) [`2567aa48b`](https://github.com/withastro/astro/commit/2567aa48bba8751cf7e10429555f1e85830c9169) Thanks [@e111077](https://github.com/e111077)! - Add forwards compatibility for streaming Declarative Shadow DOM - -## 1.1.1 - -### Patch Changes - -- [#5478](https://github.com/withastro/astro/pull/5478) [`1c7eef308`](https://github.com/withastro/astro/commit/1c7eef308e808aa5ed4662b53e67ec8d1b814d1f) Thanks [@nemo0](https://github.com/nemo0)! - Update READMEs for consistency - -## 1.1.0 - -### Minor Changes - -- [#5782](https://github.com/withastro/astro/pull/5782) [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Only shim fetch if not already present - -- [#5791](https://github.com/withastro/astro/pull/5791) [`f7aa1ec25`](https://github.com/withastro/astro/commit/f7aa1ec25d1584f7abd421903fbef66b1c050e2a) Thanks [@ba55ie](https://github.com/ba55ie)! - Fix Lit slotted content - -## 1.0.2 - -### Patch Changes - -- [#5782](https://github.com/withastro/astro/pull/5782) [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Only shim fetch if not already present - -- [#5776](https://github.com/withastro/astro/pull/5776) [`6a31433ed`](https://github.com/withastro/astro/commit/6a31433ed79c7f84fd3ce602005b42ad95007d84) & [#5791](https://github.com/withastro/astro/pull/5791) [`f7aa1ec25`](https://github.com/withastro/astro/commit/f7aa1ec25d1584f7abd421903fbef66b1c050e2a) Thanks [@ba55ie](https://github.com/ba55ie)! - Fix Lit slotted content - -## 1.0.2-beta.0 - -<details> -<summary>See changes in 1.0.2-beta.0</summary> - -### Patch Changes - -- [#5782](https://github.com/withastro/astro/pull/5782) [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Only shim fetch if not already present - -- [#5791](https://github.com/withastro/astro/pull/5791) [`f7aa1ec25`](https://github.com/withastro/astro/commit/f7aa1ec25d1584f7abd421903fbef66b1c050e2a) Thanks [@ba55ie](https://github.com/ba55ie)! - Fix Lit slotted content - -</details> - -## 1.0.1 - -### Patch Changes - -- [#4503](https://github.com/withastro/astro/pull/4503) [`1222ab954`](https://github.com/withastro/astro/commit/1222ab9540d17e4e7e811240b8a2a039acc333cb) Thanks [@matthewp](https://github.com/matthewp)! - Allow using Lit's decorators - -## 1.0.0 - -### Major Changes - -- [`04ad44563`](https://github.com/withastro/astro/commit/04ad445632c67bdd60c1704e1e0dcbcaa27b9308) - > Astro v1.0 is out! Read the [official announcement post](https://astro.build/blog/astro-1/). - - **No breaking changes**. This package is now officially stable and compatible with `astro@1.0.0`! - -## 0.3.2 - -### Patch Changes - -- [#4009](https://github.com/withastro/astro/pull/4009) [`01ba07d8f`](https://github.com/withastro/astro/commit/01ba07d8fa7eb67530b47b8530d65906f1aebf6e) Thanks [@matthewp](https://github.com/matthewp)! - Fixes Lit compat with Vite 3.0.1 - -## 0.3.1 - -### Patch Changes - -- [#3854](https://github.com/withastro/astro/pull/3854) [`b012ee55`](https://github.com/withastro/astro/commit/b012ee55b107dea0730286263b27d83e530fad5d) Thanks [@bholmesdev](https://github.com/bholmesdev)! - [astro add] Support adapters and third party packages - -## 0.3.0 - -### Minor Changes - -- [#3652](https://github.com/withastro/astro/pull/3652) [`7373d61c`](https://github.com/withastro/astro/commit/7373d61cdcaedd64bf5fd60521b157cfa4343558) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Adds support for passing named slots from `.astro` => Lit components. - - All slots are treated as Light DOM content. - -## 0.2.0 - -### Minor Changes - -- [#3625](https://github.com/withastro/astro/pull/3625) [`f5afaf24`](https://github.com/withastro/astro/commit/f5afaf24984ee7d4d6e908a7eeed17f5ca18c61e) Thanks [@matthewp](https://github.com/matthewp)! - Conform to Constructor based rendering - - This changes `@astrojs/lit` to conform to the way rendering happens in all other frameworks. Instead of using the tag name `<my-element client:load>` you use the imported constructor function, `<MyElement client:load>` like you would do with any other framework. - - Support for `tag-name` syntax had to be removed due to the fact that it was a runtime feature that was not statically analyzable. To improve build performance, we have removed all runtime based component discovery. Using the imported Constructor name allows Astro to discover what components need to be built and bundled for production without ever running your file. - -## 0.1.5 - -### Patch Changes - -- [#3511](https://github.com/withastro/astro/pull/3511) [`2fedb974`](https://github.com/withastro/astro/commit/2fedb974899b37a8d9ddabc476764a6d35d1e446) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Patch Lit's server shim to allow for `sass` compatibility - -## 0.1.4 - -### Patch Changes - -- [#3484](https://github.com/withastro/astro/pull/3484) [`55820fa7`](https://github.com/withastro/astro/commit/55820fa784d6d4f66a45092321a47c8ce9de5546) Thanks [@matthewp](https://github.com/matthewp)! - Wait for DOMCOntentLoaded to polyfill in Lit - -## 0.1.3 - -### Patch Changes - -- [#3375](https://github.com/withastro/astro/pull/3375) [`fe61e469`](https://github.com/withastro/astro/commit/fe61e469b243c27781112499f151782baf9004a4) Thanks [@jdvivar](https://github.com/jdvivar)! - Added tests and fix a small edge case for when you call render with no props/attrs - -## 0.1.2 - -### Patch Changes - -- [#3164](https://github.com/withastro/astro/pull/3164) [`e85b16e2`](https://github.com/withastro/astro/commit/e85b16e2b3d846333f542139c82640de19bfd2f5) Thanks [@matthewp](https://github.com/matthewp)! - Fixes lit when running in SSR - -## 0.1.1 - -### Patch Changes - -- [`815d62f1`](https://github.com/withastro/astro/commit/815d62f151a36fef7d09590d4962ca71bda61b32) Thanks [@FredKSchott](https://github.com/FredKSchott)! - no changes. - -## 0.1.0 - -### Minor Changes - -- [#2979](https://github.com/withastro/astro/pull/2979) [`9d7a4b59`](https://github.com/withastro/astro/commit/9d7a4b59b53f8cb274266f5036d1cef841750252) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Welcome to the Astro v1.0.0 Beta! Read the [official announcement](https://astro.build/blog/astro-1-beta-release/) for more details. - -## 0.0.2 - -### Patch Changes - -- [#2885](https://github.com/withastro/astro/pull/2885) [`6b004363`](https://github.com/withastro/astro/commit/6b004363f99f27e581d1e2d53a2ebff39d7afb8a) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add README across Astro built-in integrations - -* [#2847](https://github.com/withastro/astro/pull/2847) [`3b621f7a`](https://github.com/withastro/astro/commit/3b621f7a613b45983b090794fa7c015f23ed6140) Thanks [@tony-sull](https://github.com/tony-sull)! - Adds keywords to the official integrations to support discoverability on Astro's Integrations site - -## 0.0.2-next.0 - -### Patch Changes - -- [#2847](https://github.com/withastro/astro/pull/2847) [`3b621f7a`](https://github.com/withastro/astro/commit/3b621f7a613b45983b090794fa7c015f23ed6140) Thanks [@tony-sull](https://github.com/tony-sull)! - Adds keywords to the official integrations to support discoverability on Astro's Integrations site diff --git a/packages/integrations/lit/README.md b/packages/integrations/lit/README.md deleted file mode 100644 index 5d0acb5ed..000000000 --- a/packages/integrations/lit/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# @astrojs/lit 🔥 - -This **[Astro integration][astro-integration]** enables server-side rendering and client-side hydration for your [Lit](https://lit.dev/) custom elements. - -## Documentation - -Read the [`@astrojs/lit` docs][docs] - -## Support - -- Get help in the [Astro Discord][discord]. Post questions in our `#support` forum, or visit our dedicated `#dev` channel to discuss current development and more! - -- Check our [Astro Integration Documentation][astro-integration] for more on integrations. - -- Submit bug reports and feature requests as [GitHub issues][issues]. - -## Contributing - -This package is maintained by Astro's Core team. You're welcome to submit an issue or PR! These links will help you get started: - -- [Contributor Manual][contributing] -- [Code of Conduct][coc] -- [Community Guide][community] - -## License - -MIT - -Copyright (c) 2023–present [Astro][astro] - -[astro]: https://astro.build/ -[docs]: https://docs.astro.build/en/guides/integrations-guide/lit/ -[contributing]: https://github.com/withastro/astro/blob/main/CONTRIBUTING.md -[coc]: https://github.com/withastro/.github/blob/main/CODE_OF_CONDUCT.md -[community]: https://github.com/withastro/.github/blob/main/COMMUNITY_GUIDE.md -[discord]: https://astro.build/chat/ -[issues]: https://github.com/withastro/astro/issues -[astro-integration]: https://docs.astro.build/en/guides/integrations-guide/ diff --git a/packages/integrations/lit/client-shim.js b/packages/integrations/lit/client-shim.js deleted file mode 100644 index c28ee5edf..000000000 --- a/packages/integrations/lit/client-shim.js +++ /dev/null @@ -1,16 +0,0 @@ -async function polyfill() { - const { hydrateShadowRoots } = await import( - '@webcomponents/template-shadowroot/template-shadowroot.js' - ); - window.addEventListener('DOMContentLoaded', () => hydrateShadowRoots(document.body), { - once: true, - }); -} - -const polyfillCheckEl = Document.parseHTMLUnsafe( - `<p><template shadowrootmode="open"></template></p>`, -).querySelector('p'); - -if (!polyfillCheckEl?.shadowRoot) { - polyfill(); -} diff --git a/packages/integrations/lit/client-shim.min.js b/packages/integrations/lit/client-shim.min.js deleted file mode 100644 index 0ec44c3fa..000000000 --- a/packages/integrations/lit/client-shim.min.js +++ /dev/null @@ -1,85 +0,0 @@ -/** @license Copyright 2020 Google LLC (BSD-3-Clause) */ -/** Bundled JS generated from "@astrojs/lit/client-shim.js" */ -var N = Object.defineProperty; -var i = (t, n) => () => (t && (n = t((t = 0))), n); -var b = (t, n) => { - for (var a in n) N(t, a, { get: n[a], enumerable: !0 }); -}; -function s() { - if (d === void 0) { - let t = document.createElement('div'); - (t.innerHTML = '<div><template shadowrootmode="open"></template></div>'), - (d = !!t.firstElementChild.shadowRoot); - } - return d; -} -var d, - m = i(() => {}); -var p, - c, - f, - u = i(() => { - (p = (t) => t.parentElement === null), - (c = (t) => t.tagName === 'TEMPLATE'), - (f = (t) => t.nodeType === Node.ELEMENT_NODE); - }); -var h, - E = i(() => { - m(); - u(); - h = (t) => { - var n; - if (s()) return; - let a = [], - e = t.firstElementChild; - for (; e !== t && e !== null; ) - if (c(e)) a.push(e), (e = e.content); - else if (e.firstElementChild !== null) e = e.firstElementChild; - else if (f(e) && e.nextElementSibling !== null) e = e.nextElementSibling; - else { - let o; - for (; e !== t && e !== null; ) - if (p(e)) { - o = a.pop(); - let r = o.parentElement, - l = o.getAttribute('shadowroot'); - if (((e = o), l === 'open' || l === 'closed')) { - let y = o.hasAttribute('shadowrootdelegatesfocus'); - try { - r.attachShadow({ mode: l, delegatesFocus: y }).append(o.content); - } catch {} - } else o = void 0; - } else { - let r = e.nextElementSibling; - if (r != null) { - (e = r), o !== void 0 && o.parentElement.removeChild(o); - break; - } - let l = - (n = e.parentElement) === null || n === void 0 ? void 0 : n.nextElementSibling; - if (l != null) { - (e = l), o !== void 0 && o.parentElement.removeChild(o); - break; - } - (e = e.parentElement), o !== void 0 && (o.parentElement.removeChild(o), (o = void 0)); - } - } - }; - }); -var w = i(() => { - E(); -}); -var v = {}; -b(v, { hasNativeDeclarativeShadowRoots: () => s, hydrateShadowRoots: () => h }); -var S = i(() => { - m(); - w(); -}); -async function g() { - let { hydrateShadowRoots: t } = await Promise.resolve().then(() => (S(), v)); - window.addEventListener('DOMContentLoaded', () => t(document.body), { once: true }); -} -var x = Document.parseHTMLUnsafe( - '<p><template shadowrootmode="open"></template></p>', -).querySelector('p'); -(!x || !x.shadowRoot) && g(); diff --git a/packages/integrations/lit/hydration-support.js b/packages/integrations/lit/hydration-support.js deleted file mode 100644 index 0f367ae0b..000000000 --- a/packages/integrations/lit/hydration-support.js +++ /dev/null @@ -1,2 +0,0 @@ -// @ts-check -import '@lit-labs/ssr-client/lit-element-hydrate-support.js'; diff --git a/packages/integrations/lit/package.json b/packages/integrations/lit/package.json deleted file mode 100644 index d3b55e182..000000000 --- a/packages/integrations/lit/package.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "name": "@astrojs/lit", - "version": "4.3.0", - "description": "Use Lit components within Astro", - "type": "module", - "types": "./dist/index.d.ts", - "author": "withastro", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/withastro/astro.git", - "directory": "packages/integrations/lit" - }, - "keywords": [ - "astro-integration", - "astro-component", - "renderer", - "lit" - ], - "bugs": "https://github.com/withastro/astro/issues", - "homepage": "https://docs.astro.build/en/guides/integrations-guide/lit/", - "exports": { - ".": "./dist/index.js", - "./server.js": "./server.js", - "./client-shim.js": "./client-shim.js", - "./dist/client.js": "./dist/client.js", - "./hydration-support.js": "./hydration-support.js", - "./package.json": "./package.json" - }, - "files": [ - "dist", - "client-shim.js", - "client-shim.min.js", - "hydration-support.js", - "server.js", - "server.d.ts", - "server-shim.js" - ], - "scripts": { - "build": "astro-scripts build \"src/**/*.ts\" && tsc", - "build:ci": "astro-scripts build \"src/**/*.ts\"", - "dev": "astro-scripts dev \"src/**/*.ts\"", - "test": "astro-scripts test \"test/**/*.test.js\"" - }, - "dependencies": { - "@lit-labs/ssr": "^3.2.2", - "@lit-labs/ssr-client": "^1.1.7", - "@lit-labs/ssr-dom-shim": "^1.2.1", - "parse5": "^7.2.1" - }, - "overrides": { - "@lit-labs/ssr": { - "@lit-labs/ssr-client": "1.1.7" - } - }, - "devDependencies": { - "astro": "workspace:*", - "astro-scripts": "workspace:*", - "cheerio": "1.0.0", - "lit": "^3.2.1", - "sass": "^1.81.0" - }, - "peerDependencies": { - "@webcomponents/template-shadowroot": "^0.2.1", - "lit": "^3.1.0" - }, - "publishConfig": { - "provenance": true - } -} diff --git a/packages/integrations/lit/server-shim.js b/packages/integrations/lit/server-shim.js deleted file mode 100644 index d777382f2..000000000 --- a/packages/integrations/lit/server-shim.js +++ /dev/null @@ -1,35 +0,0 @@ -import { customElements as litCE, HTMLElement as litShimHTMLElement } from '@lit-labs/ssr-dom-shim'; - -// Something at build time injects document.currentScript = undefined instead of -// document.currentScript = null. This causes Sass build to fail because it -// seems to be expecting `=== null`. This set to `undefined` doesn't seem to be -// caused by Lit and only happens at build / test time, but not in dev or -// preview time. -if (globalThis.document) { - document.currentScript = null; -} - -if (globalThis.HTMLElement) { - // Seems Astro's Element shim does nothing when `.setAttribute` is called - // and subsequently `.getAttribute` is called. Causes Lit to not SSR attrs - globalThis.HTMLElement = litShimHTMLElement; -} - -// Astro seems to have a DOM shim and the only real difference that we need out -// of the Lit DOM shim is that the Lit DOM shim reads -// `HTMLElement.observedAttributes` which is meant to trigger -// `ReactiveElement.finalize()`. So this is the only thing we will re-shim since -// Lit will try to respect other global DOM shims. -globalThis.customElements = litCE; - -const litCeDefine = customElements.define; - -// We need to patch customElements.define to keep track of the tagName on the -// class itself so that we can transform JSX custom element class definition to -// a DSD string on the server, because there is no way to get the tagName from a -// CE class otherwise. Not an issue on client:only because the browser supports -// appending a class instance directly to the DOM. -customElements.define = function (tagName, Ctr) { - Ctr[Symbol.for('tagName')] = tagName; - return litCeDefine.call(this, tagName, Ctr); -}; diff --git a/packages/integrations/lit/server.d.ts b/packages/integrations/lit/server.d.ts deleted file mode 100644 index bb2f29556..000000000 --- a/packages/integrations/lit/server.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import type { NamedSSRLoadedRendererValue } from 'astro'; -export default NamedSSRLoadedRendererValue; diff --git a/packages/integrations/lit/server.js b/packages/integrations/lit/server.js deleted file mode 100644 index d1da3c6c9..000000000 --- a/packages/integrations/lit/server.js +++ /dev/null @@ -1,118 +0,0 @@ -// Separate import from the rest so it doesn't get re-organized after other imports -import './server-shim.js'; - -import { LitElementRenderer } from '@lit-labs/ssr/lib/lit-element-renderer.js'; -import * as parse5 from 'parse5'; - -function isCustomElementTag(name) { - return typeof name === 'string' && name.includes('-'); -} - -function getCustomElementConstructor(name) { - if (typeof customElements !== 'undefined' && isCustomElementTag(name)) { - return customElements.get(name) || null; - } else if (typeof name === 'function') { - return name; - } - return null; -} - -async function isLitElement(Component) { - const Ctr = getCustomElementConstructor(Component); - return !!Ctr?._$litElement$; -} - -async function check(Component) { - // Lit doesn't support getting a tagName from a Constructor at this time. - // So this must be a string at the moment. - return !!(await isLitElement(Component)); -} - -function* render(Component, attrs, slots) { - let tagName = Component; - if (typeof tagName !== 'string') { - tagName = Component[Symbol.for('tagName')]; - } - const instance = new LitElementRenderer(tagName); - - // LitElementRenderer creates a new element instance, so copy over. - const Ctr = getCustomElementConstructor(tagName); - let shouldDeferHydration = false; - - if (attrs) { - for (let [name, value] of Object.entries(attrs)) { - const isReactiveProperty = name in Ctr.prototype; - const isReflectedReactiveProperty = Ctr.elementProperties.get(name)?.reflect; - - // Only defer hydration if we are setting a reactive property that cannot - // be reflected / serialized as a property. - shouldDeferHydration ||= isReactiveProperty && !isReflectedReactiveProperty; - - if (isReactiveProperty) { - instance.setProperty(name, value); - } else { - instance.setAttribute(name, value); - } - } - } - - instance.connectedCallback(); - - yield `<${tagName}${shouldDeferHydration ? ' defer-hydration' : ''}`; - yield* instance.renderAttributes(); - yield `>`; - const shadowContents = instance.renderShadow({ - elementRenderers: [LitElementRenderer], - customElementInstanceStack: [instance], - customElementHostStack: [instance], - deferHydration: false, - }); - if (shadowContents !== undefined) { - const { mode = 'open', delegatesFocus } = instance.shadowRootOptions ?? {}; - // `delegatesFocus` is intentionally allowed to coerce to boolean to - // match web platform behavior. - const delegatesfocusAttr = delegatesFocus ? ' shadowrootdelegatesfocus' : ''; - yield `<template shadowroot="${mode}" shadowrootmode="${mode}"${delegatesfocusAttr}>`; - yield* shadowContents; - yield '</template>'; - } - if (slots) { - for (let [slot, value = ''] of Object.entries(slots)) { - if (slot !== 'default' && value) { - // Parse the value as a concatenated string - const fragment = parse5.parseFragment(`${value}`); - - // Add the missing slot attribute to child Element nodes - for (const node of fragment.childNodes) { - if (node.tagName && !node.attrs.some(({ name }) => name === 'slot')) { - node.attrs.push({ name: 'slot', value: slot }); - } - } - - value = parse5.serialize(fragment); - } - - yield value; - } - } - yield `</${tagName}>`; -} - -async function renderToStaticMarkup(Component, props, slots) { - let tagName = Component; - - let out = ''; - for (let chunk of render(tagName, props, slots)) { - out += chunk; - } - - return { - html: out, - }; -} - -export default { - name: '@astrojs/lit', - check, - renderToStaticMarkup, -}; diff --git a/packages/integrations/lit/src/client.ts b/packages/integrations/lit/src/client.ts deleted file mode 100644 index 9a573d8ee..000000000 --- a/packages/integrations/lit/src/client.ts +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Adds the appropriate slot attribute to each top-level node in the given HTML - * string. - * - * @example - * addSlotAttrsToHtmlString('foo', '<div>bar</div><div>baz</div>'); - * // '<div slot="foo">bar</div><div slot="foo">baz</div>' - * - * @param slotName Name of slot to apply to HTML string. - * @param html Stringified HTML that should be projected into the given slotname. - * @returns A stringified HTML string with the slot attribute applied to each top-level node. - */ -const addSlotAttrsToHtmlString = (slotName: string, html: string) => { - const templ = document.createElement('template'); - templ.innerHTML = html; - Array.from(templ.content.children).forEach((node) => { - node.setAttribute('slot', slotName); - }); - return templ.innerHTML; -}; - -export default (element: HTMLElement) => - async ( - Component: any, - props: Record<string, any>, - { default: defaultChildren, ...slotted }: { default: string; [slotName: string]: string }, - ) => { - // Get the LitElement element instance. - let component = element.children[0]; - // Check if hydration model is client:only - const isClientOnly = element.getAttribute('client') === 'only'; - - // We need to attach the element and it's children to the DOM since it's not - // SSR'd. - if (isClientOnly) { - component = new Component(); - - const otherSlottedChildren = Object.entries(slotted) - .map(([slotName, htmlStr]) => addSlotAttrsToHtmlString(slotName, htmlStr)) - .join(''); - - // defaultChildren can actually be undefined, but TS will complain if we - // type it as so, make sure we don't render undefined. - component.innerHTML = `${defaultChildren ?? ''}${otherSlottedChildren}`; - element.appendChild(component); - - // Set props bound to non-reactive properties as attributes. - for (let [name, value] of Object.entries(props)) { - if (!(name in Component.prototype)) { - component.setAttribute(name, value); - } - } - } - - // If there is no deferral of hydration, then all reactive properties are - // already serialized as reflected attributes, or no reactive props were set - // Alternatively, if hydration is client:only proceed to set props. - if (!component || !(component.hasAttribute('defer-hydration') || isClientOnly)) { - return; - } - - // Set properties on the LitElement instance for resuming hydration. - for (let [name, value] of Object.entries(props)) { - // Check if reactive property or class property. - if (name in Component.prototype) { - (component as any)[name] = value; - } - } - - // Tell LitElement to resume hydration. - component.removeAttribute('defer-hydration'); - }; diff --git a/packages/integrations/lit/src/index.ts b/packages/integrations/lit/src/index.ts deleted file mode 100644 index 94a6d683a..000000000 --- a/packages/integrations/lit/src/index.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { readFileSync } from 'node:fs'; -import type { AstroIntegration, ContainerRenderer } from 'astro'; - -function getViteConfiguration() { - return { - optimizeDeps: { - include: [ - '@astrojs/lit/dist/client.js', - '@astrojs/lit/client-shim.js', - '@astrojs/lit/hydration-support.js', - '@webcomponents/template-shadowroot/template-shadowroot.js', - '@lit-labs/ssr-client/lit-element-hydrate-support.js', - ], - exclude: ['@astrojs/lit/server.js'], - }, - ssr: { - external: ['lit-element', '@lit-labs/ssr', '@astrojs/lit', 'lit/decorators.js'], - }, - }; -} - -export function getContainerRenderer(): ContainerRenderer { - return { - name: '@astrojs/lit', - serverEntrypoint: '@astrojs/lit/server.js', - }; -} - -export default function (): AstroIntegration { - return { - name: '@astrojs/lit', - hooks: { - 'astro:config:setup': ({ updateConfig, addRenderer, injectScript }) => { - // Inject the necessary polyfills on every page (inlined for speed). - injectScript( - 'head-inline', - readFileSync(new URL('../client-shim.min.js', import.meta.url), { encoding: 'utf-8' }), - ); - // Inject the hydration code, before a component is hydrated. - injectScript('before-hydration', `import '@astrojs/lit/hydration-support.js';`); - // Add the lit renderer so that Astro can understand lit components. - addRenderer({ - name: '@astrojs/lit', - serverEntrypoint: '@astrojs/lit/server.js', - clientEntrypoint: '@astrojs/lit/dist/client.js', - }); - // Update the vite configuration. - updateConfig({ - vite: getViteConfiguration(), - }); - }, - 'astro:build:setup': ({ vite, target }) => { - if (target === 'server') { - if (!vite.ssr) { - vite.ssr = {}; - } - if (!vite.ssr.noExternal) { - vite.ssr.noExternal = []; - } - if (Array.isArray(vite.ssr.noExternal)) { - vite.ssr.noExternal.push('lit'); - } - } - }, - }, - }; -} diff --git a/packages/integrations/lit/test/sass.test.js b/packages/integrations/lit/test/sass.test.js deleted file mode 100644 index a6cbfae8b..000000000 --- a/packages/integrations/lit/test/sass.test.js +++ /dev/null @@ -1,15 +0,0 @@ -import * as assert from 'node:assert/strict'; -import { describe, it } from 'node:test'; - -describe('check', () => { - it('should be able to load sass', async () => { - let error = null; - try { - await import(new URL('../server-shim.js', import.meta.url)); - await import('sass'); - } catch (e) { - error = e; - } - assert.equal(error, null); - }); -}); diff --git a/packages/integrations/lit/test/server.test.js b/packages/integrations/lit/test/server.test.js deleted file mode 100644 index bcecef2f6..000000000 --- a/packages/integrations/lit/test/server.test.js +++ /dev/null @@ -1,134 +0,0 @@ -import * as assert from 'node:assert/strict'; -import { describe, it } from 'node:test'; -import * as cheerio from 'cheerio'; -import { LitElement, html } from 'lit'; -// Must come after lit import because @lit/reactive-element defines -// globalThis.customElements which the server shim expects to be defined. -import server from '../server.js'; - -const { check, renderToStaticMarkup } = server; - -describe('check', () => { - it('should be false with no component', async () => { - assert.equal(await check(), false); - }); - - it('should be false with a registered non-lit component', async () => { - const tagName = 'non-lit-component'; - // Lit no longer shims HTMLElement globally, so we need to do it ourselves. - if (!globalThis.HTMLElement) { - globalThis.HTMLElement = class {}; - } - customElements.define(tagName, class TestComponent extends HTMLElement {}); - assert.equal(await check(tagName), false); - }); - - it('should be true with a registered lit component', async () => { - const tagName = 'lit-component'; - customElements.define(tagName, class extends LitElement {}); - assert.equal(await check(tagName), true); - }); -}); - -describe('renderToStaticMarkup', () => { - it('should throw error if trying to render an unregistered component', async () => { - const tagName = 'non-registrered-component'; - try { - await renderToStaticMarkup(tagName); - } catch (e) { - assert.equal(e instanceof TypeError, true); - } - }); - - it('should render empty component with default markup', async () => { - const tagName = 'nothing-component'; - customElements.define(tagName, class extends LitElement {}); - const render = await renderToStaticMarkup(tagName); - assert.deepEqual(render, { - html: `<${tagName}><template shadowroot="open" shadowrootmode="open"><!--lit-part--><!--/lit-part--></template></${tagName}>`, - }); - }); - - it('should render component with default markup', async () => { - const tagName = 'simple-component'; - customElements.define( - tagName, - class extends LitElement { - render() { - return html`<p>hola</p>`; - } - }, - ); - const render = await renderToStaticMarkup(tagName); - const $ = cheerio.load(render.html); - assert.equal($(`${tagName} template`).html().includes('<p>hola</p>'), true); - }); - - it('should render component with properties and attributes', async () => { - const tagName = 'props-and-attrs-component'; - const attr1 = 'test'; - const prop1 = 'Daniel'; - customElements.define( - tagName, - class extends LitElement { - static properties = { - prop1: { type: String }, - }; - - constructor() { - super(); - this.prop1 = 'someone'; - } - - render() { - return html`<p>Hello ${this.prop1}</p>`; - } - }, - ); - const render = await renderToStaticMarkup(tagName, { prop1, attr1 }); - const $ = cheerio.load(render.html); - assert.equal($(tagName).attr('attr1'), attr1); - assert.equal($(`${tagName} template`).text().includes(`Hello ${prop1}`), true); - }); - - it('should render nested components', async () => { - const tagName = 'parent-component'; - const childTagName = 'child-component'; - customElements.define( - childTagName, - class extends LitElement { - render() { - return html`<p>child</p>`; - } - }, - ); - customElements.define( - tagName, - class extends LitElement { - render() { - return html`<child-component></child-component>`; - } - }, - ); - const render = await renderToStaticMarkup(tagName); - const $ = cheerio.load(render.html); - assert.equal($(`${tagName} template`).text().includes('child'), true); - // Child component should have `defer-hydration` attribute so it'll only - // hydrate after the parent hydrates - assert.equal($(childTagName).attr('defer-hydration'), ''); - }); - - it('should render DSD attributes based on shadowRootOptions', async () => { - const tagName = 'shadow-root-options-component'; - customElements.define( - tagName, - class extends LitElement { - static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }; - }, - ); - const render = await renderToStaticMarkup(tagName); - assert.deepEqual(render, { - html: `<${tagName}><template shadowroot=\"open\" shadowrootmode=\"open\" shadowrootdelegatesfocus><!--lit-part--><!--/lit-part--></template></${tagName}>`, - }); - }); -}); diff --git a/packages/integrations/lit/tsconfig.json b/packages/integrations/lit/tsconfig.json deleted file mode 100644 index 1504b4b6d..000000000 --- a/packages/integrations/lit/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "include": ["src"], - "compilerOptions": { - "outDir": "./dist" - } -} diff --git a/packages/integrations/markdoc/CHANGELOG.md b/packages/integrations/markdoc/CHANGELOG.md index 0929ce6e0..978f2ba91 100644 --- a/packages/integrations/markdoc/CHANGELOG.md +++ b/packages/integrations/markdoc/CHANGELOG.md @@ -1,5 +1,38 @@ # @astrojs/markdoc +## 0.11.5-beta.1 + +### Patch Changes + +- [#12075](https://github.com/withastro/astro/pull/12075) [`a19530e`](https://github.com/withastro/astro/commit/a19530e377b7d7afad58a33b23c0a5df1c376819) Thanks [@bluwy](https://github.com/bluwy)! - Parses frontmatter ourselves + +- Updated dependencies [[`a19530e`](https://github.com/withastro/astro/commit/a19530e377b7d7afad58a33b23c0a5df1c376819)]: + - @astrojs/markdown-remark@6.0.0-beta.2 + +## 0.11.5-beta.0 + +### Patch Changes + +- Updated dependencies [[`5608338`](https://github.com/withastro/astro/commit/560833843c6d3ce2b6c6c473ec4ae70e744bf255)]: + - @astrojs/markdown-remark@6.0.0-beta.1 + +## 1.0.0-alpha.1 + +### Patch Changes + +- [#11825](https://github.com/withastro/astro/pull/11825) [`560ef15`](https://github.com/withastro/astro/commit/560ef15ad23bd137b56ef1048eb2df548b99fdce) Thanks [@bluwy](https://github.com/bluwy)! - Uses latest version of `@astrojs/markdown-remark` with updated Shiki APIs + +- Updated dependencies [[`3ab3b4e`](https://github.com/withastro/astro/commit/3ab3b4efbcdd2aabea5f949deedf51a5acefae59), [`560ef15`](https://github.com/withastro/astro/commit/560ef15ad23bd137b56ef1048eb2df548b99fdce), [`3ab3b4e`](https://github.com/withastro/astro/commit/3ab3b4efbcdd2aabea5f949deedf51a5acefae59)]: + - @astrojs/markdown-remark@6.0.0-alpha.1 + +## 1.0.0-alpha.0 + +### Patch Changes + +- Updated dependencies [[`b6fbdaa`](https://github.com/withastro/astro/commit/b6fbdaa94a9ecec706a99e1938fbf5cd028c72e0), [`89bab1e`](https://github.com/withastro/astro/commit/89bab1e70786123fbe933a9d7a1b80c9334dcc5f), [`d74617c`](https://github.com/withastro/astro/commit/d74617cbd3278feba05909ec83db2d73d57a153e), [`83a2a64`](https://github.com/withastro/astro/commit/83a2a648418ad30f4eb781d1c1b5f2d8a8ac846e), [`e90f559`](https://github.com/withastro/astro/commit/e90f5593d23043579611452a84b9e18ad2407ef9), [`2df49a6`](https://github.com/withastro/astro/commit/2df49a6fb4f6d92fe45f7429430abe63defeacd6), [`8a53517`](https://github.com/withastro/astro/commit/8a5351737d6a14fc55f1dafad8f3b04079e81af6)]: + - astro@5.0.0-alpha.0 + - @astrojs/markdown-remark@6.0.0-alpha.0 + ## 0.11.5 ### Patch Changes diff --git a/packages/integrations/markdoc/package.json b/packages/integrations/markdoc/package.json index 282a1e9e4..80c4e7771 100644 --- a/packages/integrations/markdoc/package.json +++ b/packages/integrations/markdoc/package.json @@ -1,7 +1,7 @@ { "name": "@astrojs/markdoc", "description": "Add support for Markdoc in your Astro site", - "version": "0.11.5", + "version": "0.12.0-beta.0", "type": "module", "types": "./dist/index.d.ts", "author": "withastro", @@ -68,11 +68,10 @@ "@markdoc/markdoc": "^0.4.0", "esbuild": "^0.21.5", "github-slugger": "^2.0.0", - "gray-matter": "^4.0.3", "htmlparser2": "^9.1.0" }, "peerDependencies": { - "astro": "^3.0.0 || ^4.0.0" + "astro": "^5.0.0-alpha.0" }, "devDependencies": { "@types/markdown-it": "^14.1.2", @@ -80,10 +79,10 @@ "astro-scripts": "workspace:*", "devalue": "^5.1.1", "linkedom": "^0.18.5", - "vite": "^5.4.11" + "vite": "^6.0.1" }, "engines": { - "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + "node": "^18.17.1 || ^20.3.0 || >=22.0.0" }, "publishConfig": { "provenance": true diff --git a/packages/integrations/markdoc/src/content-entry-type.ts b/packages/integrations/markdoc/src/content-entry-type.ts index 303251d66..67a8be531 100644 --- a/packages/integrations/markdoc/src/content-entry-type.ts +++ b/packages/integrations/markdoc/src/content-entry-type.ts @@ -1,11 +1,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; +import { parseFrontmatter } from '@astrojs/markdown-remark'; import type { Config as MarkdocConfig, Node } from '@markdoc/markdoc'; import Markdoc from '@markdoc/markdoc'; import type { AstroConfig, ContentEntryType } from 'astro'; import { emitESMImage } from 'astro/assets/utils'; -import matter from 'gray-matter'; import type { Rollup, ErrorPayload as ViteErrorPayload } from 'vite'; import type { ComponentConfig } from './config.js'; import { htmlTokenTransform } from './html/transform/html-token-transform.js'; @@ -26,12 +26,20 @@ export async function getContentEntryType({ }): Promise<ContentEntryType> { return { extensions: ['.mdoc'], - getEntryInfo, + getEntryInfo({ fileUrl, contents }) { + const parsed = safeParseFrontmatter(contents, fileURLToPath(fileUrl)); + return { + data: parsed.frontmatter, + body: parsed.content.trim(), + slug: parsed.frontmatter.slug, + rawData: parsed.rawFrontmatter, + }; + }, handlePropagation: true, async getRenderModule({ contents, fileUrl, viteId }) { - const entry = getEntryInfo({ contents, fileUrl }); + const parsed = safeParseFrontmatter(contents, fileURLToPath(fileUrl)); const tokenizer = getMarkdocTokenizer(options); - let tokens = tokenizer.tokenize(entry.body); + let tokens = tokenizer.tokenize(parsed.content); if (options?.allowHTML) { tokens = htmlTokenTransform(tokenizer, tokens); @@ -47,7 +55,6 @@ export async function getContentEntryType({ ast, /* Raised generics issue with Markdoc core https://github.com/markdoc/markdoc/discussions/400 */ markdocConfig: markdocConfig as MarkdocConfig, - entry, viteId, astroConfig, filePath, @@ -64,7 +71,6 @@ export async function getContentEntryType({ raiseValidationErrors({ ast: partialAst, markdocConfig: markdocConfig as MarkdocConfig, - entry, viteId, astroConfig, filePath: partialPath, @@ -224,14 +230,12 @@ async function resolvePartials({ function raiseValidationErrors({ ast, markdocConfig, - entry, viteId, astroConfig, filePath, }: { ast: Node; markdocConfig: MarkdocConfig; - entry: ReturnType<typeof getEntryInfo>; viteId: string; astroConfig: AstroConfig; filePath: string; @@ -250,8 +254,6 @@ function raiseValidationErrors({ }); if (validationErrors.length) { - // Heuristic: take number of newlines for `rawData` and add 2 for the `---` fences - const frontmatterBlockOffset = entry.rawData.split('\n').length + 2; const rootRelativePath = path.relative(fileURLToPath(astroConfig.root), filePath); throw new MarkdocError({ message: [ @@ -261,7 +263,7 @@ function raiseValidationErrors({ location: { // Error overlay does not support multi-line or ranges. // Just point to the first line. - line: frontmatterBlockOffset + validationErrors[0].lines[0], + line: validationErrors[0].lines[0], file: viteId, }, }); @@ -282,16 +284,6 @@ function getUsedTags(markdocAst: Node) { return tags; } -function getEntryInfo({ fileUrl, contents }: { fileUrl: URL; contents: string }) { - const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl)); - return { - data: parsed.data, - body: parsed.content, - slug: parsed.data.slug, - rawData: parsed.matter, - }; -} - /** * Emits optimized images, and appends the generated `src` to each AST node * via the `__optimizedSrc` attribute. @@ -410,12 +402,11 @@ function getStringifiedMap( * Match YAML exception handling from Astro core errors * @see 'astro/src/core/errors.ts' */ -function parseFrontmatter(fileContents: string, filePath: string) { +function safeParseFrontmatter(fileContents: string, filePath: string) { try { - // `matter` is empty string on cache results - // clear cache to prevent this - (matter as any).clearCache(); - return matter(fileContents); + // empty with lines to preserve sourcemap location, but not `empty-with-spaces` + // because markdoc struggles with spaces + return parseFrontmatter(fileContents, { frontmatter: 'empty-with-lines' }); } catch (e: any) { if (e.name === 'YAMLException') { const err: Error & ViteErrorPayload['err'] = e; diff --git a/packages/integrations/markdoc/src/extensions/shiki.ts b/packages/integrations/markdoc/src/extensions/shiki.ts index 04fc8e867..1102242fd 100644 --- a/packages/integrations/markdoc/src/extensions/shiki.ts +++ b/packages/integrations/markdoc/src/extensions/shiki.ts @@ -5,7 +5,11 @@ import { unescapeHTML } from 'astro/runtime/server/index.js'; import type { AstroMarkdocConfig } from '../config.js'; export default async function shiki(config?: ShikiConfig): Promise<AstroMarkdocConfig> { - const highlighter = await createShikiHighlighter(config); + const highlighter = await createShikiHighlighter({ + langs: config?.langs, + theme: config?.theme, + themes: config?.themes, + }); return { nodes: { @@ -16,7 +20,11 @@ export default async function shiki(config?: ShikiConfig): Promise<AstroMarkdocC // Only the `js` part is parsed as `attributes.language` and the rest is ignored. This means // some Shiki transformers may not work correctly as it relies on the `meta`. const lang = typeof attributes.language === 'string' ? attributes.language : 'plaintext'; - const html = await highlighter.highlight(attributes.content, lang); + const html = await highlighter.codeToHtml(attributes.content, lang, { + wrap: config?.wrap, + defaultColor: config?.defaultColor, + transformers: config?.transformers, + }); // Use `unescapeHTML` to return `HTMLString` for Astro renderer to inline as HTML return unescapeHTML(html) as any; diff --git a/packages/integrations/markdoc/test/content-collections.test.js b/packages/integrations/markdoc/test/content-collections.test.js index 5417f297d..48e97d45d 100644 --- a/packages/integrations/markdoc/test/content-collections.test.js +++ b/packages/integrations/markdoc/test/content-collections.test.js @@ -13,6 +13,8 @@ function formatPost(post) { const root = new URL('./fixtures/content-collections/', import.meta.url); +const sortById = (a, b) => a.id.localeCompare(b.id); + describe('Markdoc - Content Collections', () => { let baseFixture; @@ -46,7 +48,7 @@ describe('Markdoc - Content Collections', () => { assert.notEqual(posts, null); assert.deepEqual( - posts.sort().map((post) => formatPost(post)), + posts.sort(sortById).map((post) => formatPost(post)), [post1Entry, post2Entry, post3Entry], ); }); @@ -68,7 +70,7 @@ describe('Markdoc - Content Collections', () => { const posts = parseDevalue(res); assert.notEqual(posts, null); assert.deepEqual( - posts.sort().map((post) => formatPost(post)), + posts.sort(sortById).map((post) => formatPost(post)), [post1Entry, post2Entry, post3Entry], ); }); @@ -83,7 +85,10 @@ const post1Entry = { schemaWorks: true, title: 'Post 1', }, - body: '\n## Post 1\n\nThis is the contents of post 1.\n', + body: '## Post 1\n\nThis is the contents of post 1.', + deferredRender: true, + filePath: 'src/content/blog/post-1.mdoc', + digest: '5d5bd98d949e2b9a', }; const post2Entry = { @@ -94,7 +99,10 @@ const post2Entry = { schemaWorks: true, title: 'Post 2', }, - body: '\n## Post 2\n\nThis is the contents of post 2.\n', + body: '## Post 2\n\nThis is the contents of post 2.', + deferredRender: true, + filePath: 'src/content/blog/post-2.mdoc', + digest: '595af4b93a4af072', }; const post3Entry = { @@ -105,5 +113,8 @@ const post3Entry = { schemaWorks: true, title: 'Post 3', }, - body: '\n## Post 3\n\nThis is the contents of post 3.\n', + body: '## Post 3\n\nThis is the contents of post 3.', + deferredRender: true, + filePath: 'src/content/blog/post-3.mdoc', + digest: 'ef589606e542247e', }; diff --git a/packages/integrations/markdoc/test/fixtures/headings-custom/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/headings-custom/src/content/config.ts new file mode 100644 index 000000000..a142ace11 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/headings-custom/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const docs = defineCollection({}); + +export const collections = { + docs, +}; diff --git a/packages/integrations/markdoc/test/fixtures/headings/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/headings/src/content/config.ts new file mode 100644 index 000000000..a142ace11 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/headings/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const docs = defineCollection({}); + +export const collections = { + docs, +}; diff --git a/packages/integrations/markdoc/test/fixtures/image-assets/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/image-assets/src/content/config.ts new file mode 100644 index 000000000..a142ace11 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/image-assets/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const docs = defineCollection({}); + +export const collections = { + docs, +}; diff --git a/packages/integrations/markdoc/test/fixtures/image-assets/tsconfig.json b/packages/integrations/markdoc/test/fixtures/image-assets/tsconfig.json index b5bf6a715..c193287fc 100644 --- a/packages/integrations/markdoc/test/fixtures/image-assets/tsconfig.json +++ b/packages/integrations/markdoc/test/fixtures/image-assets/tsconfig.json @@ -5,5 +5,7 @@ "paths": { "~/assets/*": ["src/assets/*"] }, - } + }, + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] } diff --git a/packages/integrations/markdoc/test/fixtures/render with-space/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render with-space/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render with-space/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-html/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-html/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-html/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-null/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-null/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-null/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-partials/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-partials/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-partials/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-simple/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-simple/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-simple/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-typographer/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-typographer/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-typographer/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-with-components/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-with-components/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-with-components/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-with-components/tsconfig.json b/packages/integrations/markdoc/test/fixtures/render-with-components/tsconfig.json index 99df2e61a..f993eddf6 100644 --- a/packages/integrations/markdoc/test/fixtures/render-with-components/tsconfig.json +++ b/packages/integrations/markdoc/test/fixtures/render-with-components/tsconfig.json @@ -3,5 +3,7 @@ "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "preact" - } + }, + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] }
\ No newline at end of file diff --git a/packages/integrations/markdoc/test/fixtures/render-with-config/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-with-config/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-with-config/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-with-extends-components/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-with-extends-components/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-with-extends-components/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/image-assets.test.js b/packages/integrations/markdoc/test/image-assets.test.js index 0f98af4f1..793bf1be6 100644 --- a/packages/integrations/markdoc/test/image-assets.test.js +++ b/packages/integrations/markdoc/test/image-assets.test.js @@ -38,7 +38,7 @@ describe('Markdoc - Image assets', () => { const { document } = parseHTML(html); assert.match( document.querySelector('#relative > img')?.src, - /\/_image\?href=.*%2Fsrc%2Fassets%2Frelative%2Foar.jpg%3ForigWidth%3D420%26origHeight%3D630%26origFormat%3Djpg&f=webp/, + /\/_image\?href=.*%2Fsrc%2Fassets%2Frelative%2Foar.jpg%3ForigWidth%3D420%26origHeight%3D630%26origFormat%3Djpg&w=420&h=630&f=webp/, ); }); @@ -48,7 +48,7 @@ describe('Markdoc - Image assets', () => { const { document } = parseHTML(html); assert.match( document.querySelector('#alias > img')?.src, - /\/_image\?href=.*%2Fsrc%2Fassets%2Falias%2Fcityscape.jpg%3ForigWidth%3D420%26origHeight%3D280%26origFormat%3Djpg&f=webp/, + /\/_image\?href=.*%2Fsrc%2Fassets%2Falias%2Fcityscape.jpg%3ForigWidth%3D420%26origHeight%3D280%26origFormat%3Djpg&w=420&h=280&f=webp/, ); }); diff --git a/packages/integrations/markdoc/test/propagated-assets.test.js b/packages/integrations/markdoc/test/propagated-assets.test.js index a0768448f..5fe7369ce 100644 --- a/packages/integrations/markdoc/test/propagated-assets.test.js +++ b/packages/integrations/markdoc/test/propagated-assets.test.js @@ -45,12 +45,12 @@ describe('Markdoc - propagated assets', () => { let styleContents; if (mode === 'dev') { const styles = stylesDocument.querySelectorAll('style'); - assert.equal(styles.length, 1); - styleContents = styles[0].textContent; + assert.equal(styles.length, 2); + styleContents = styles[1].textContent; } else { const links = stylesDocument.querySelectorAll('link[rel="stylesheet"]'); - assert.equal(links.length, 1); - styleContents = await fixture.readFile(links[0].href); + assert.equal(links.length, 2); + styleContents = await fixture.readFile(links[1].href); } assert.equal(styleContents.includes('--color-base-purple: 269, 79%;'), true); }); @@ -58,10 +58,10 @@ describe('Markdoc - propagated assets', () => { it('[fails] Does not bleed styles to other page', async () => { if (mode === 'dev') { const styles = scriptsDocument.querySelectorAll('style'); - assert.equal(styles.length, 0); + assert.equal(styles.length, 1); } else { const links = scriptsDocument.querySelectorAll('link[rel="stylesheet"]'); - assert.equal(links.length, 0); + assert.equal(links.length, 1); } }); }); diff --git a/packages/integrations/mdx/CHANGELOG.md b/packages/integrations/mdx/CHANGELOG.md index e4742f9ea..00d4816d2 100644 --- a/packages/integrations/mdx/CHANGELOG.md +++ b/packages/integrations/mdx/CHANGELOG.md @@ -1,5 +1,44 @@ # @astrojs/mdx +## 4.0.0-beta.4 + +### Patch Changes + +- [#12533](https://github.com/withastro/astro/pull/12533) [`1b61fdf`](https://github.com/withastro/astro/commit/1b61fdf038d2627c6dad1a7f1426f60a4616ad93) Thanks [@ematipico](https://github.com/ematipico)! - Fixes a case where the MDX renderer couldn't be loaded when used as a direct dependency of an Astro integration. + +## 4.0.0-beta.3 + +### Major Changes + +- [#12231](https://github.com/withastro/astro/pull/12231) [`90ae100`](https://github.com/withastro/astro/commit/90ae100cf482529828febed591172433309bc12e) Thanks [@bluwy](https://github.com/bluwy)! - Handles the breaking change in Astro where content pages (including `.mdx` pages located within `src/pages/`) no longer respond with `charset=utf-8` in the `Content-Type` header. + + For MDX pages without layouts, `@astrojs/mdx` will automatically add the `<meta charset="utf-8">` tag to the page by default. This reduces the boilerplate needed to write with non-ASCII characters. If your MDX pages have a layout, the layout component should include the `<meta charset="utf-8">` tag. + + If you require `charset=utf-8` to render your page correctly, make sure that your layout components have the `<meta charset="utf-8">` tag added. + +## 4.0.0-alpha.2 + +### Patch Changes + +- [#11861](https://github.com/withastro/astro/pull/11861) [`3ab3b4e`](https://github.com/withastro/astro/commit/3ab3b4efbcdd2aabea5f949deedf51a5acefae59) Thanks [@bluwy](https://github.com/bluwy)! - Updates `@astrojs/markdown-remark` and handle its breaking changes + +- Updated dependencies [[`3ab3b4e`](https://github.com/withastro/astro/commit/3ab3b4efbcdd2aabea5f949deedf51a5acefae59), [`560ef15`](https://github.com/withastro/astro/commit/560ef15ad23bd137b56ef1048eb2df548b99fdce), [`3ab3b4e`](https://github.com/withastro/astro/commit/3ab3b4efbcdd2aabea5f949deedf51a5acefae59)]: + - @astrojs/markdown-remark@6.0.0-alpha.1 + +## 4.0.0-alpha.1 + +### Minor Changes + +- [#11741](https://github.com/withastro/astro/pull/11741) [`6617491`](https://github.com/withastro/astro/commit/6617491c3bc2bde87f7867d7dec2580781852cfc) Thanks [@bluwy](https://github.com/bluwy)! - Updates adapter server entrypoint to use `@astrojs/mdx/server.js` + + This is an internal change. Handling JSX in your `.mdx` files has been moved from Astro internals and is now the responsibility of this integration. You should not notice a change in your project, and no update to your code is required. + +## 4.0.0-alpha.0 + +- Updated dependencies [[`b6fbdaa`](https://github.com/withastro/astro/commit/b6fbdaa94a9ecec706a99e1938fbf5cd028c72e0), [`89bab1e`](https://github.com/withastro/astro/commit/89bab1e70786123fbe933a9d7a1b80c9334dcc5f), [`d74617c`](https://github.com/withastro/astro/commit/d74617cbd3278feba05909ec83db2d73d57a153e), [`83a2a64`](https://github.com/withastro/astro/commit/83a2a648418ad30f4eb781d1c1b5f2d8a8ac846e), [`e90f559`](https://github.com/withastro/astro/commit/e90f5593d23043579611452a84b9e18ad2407ef9), [`2df49a6`](https://github.com/withastro/astro/commit/2df49a6fb4f6d92fe45f7429430abe63defeacd6), [`8a53517`](https://github.com/withastro/astro/commit/8a5351737d6a14fc55f1dafad8f3b04079e81af6)]: + - astro@5.0.0-alpha.0 + - @astrojs/markdown-remark@6.0.0-alpha.0 + ## 3.1.9 ### Patch Changes diff --git a/packages/integrations/mdx/package.json b/packages/integrations/mdx/package.json index 3cdb1eb7b..4223431da 100644 --- a/packages/integrations/mdx/package.json +++ b/packages/integrations/mdx/package.json @@ -1,7 +1,7 @@ { "name": "@astrojs/mdx", "description": "Add support for MDX pages in your Astro site", - "version": "3.1.9", + "version": "4.0.0-beta.4", "type": "module", "types": "./dist/index.d.ts", "author": "withastro", @@ -20,6 +20,7 @@ "homepage": "https://docs.astro.build/en/guides/integrations-guide/mdx/", "exports": { ".": "./dist/index.js", + "./server.js": "./dist/server.js", "./package.json": "./package.json" }, "files": [ @@ -38,7 +39,6 @@ "acorn": "^8.14.0", "es-module-lexer": "^1.5.4", "estree-util-visit": "^2.0.0", - "gray-matter": "^4.0.3", "hast-util-to-html": "^9.0.3", "kleur": "^4.1.5", "rehype-raw": "^7.0.0", @@ -49,7 +49,7 @@ "vfile": "^6.0.3" }, "peerDependencies": { - "astro": "^4.8.0" + "astro": "^5.0.0-alpha.0" }, "devDependencies": { "@types/estree": "^1.0.6", @@ -70,10 +70,10 @@ "remark-toc": "^9.0.0", "shiki": "^1.23.1", "unified": "^11.0.5", - "vite": "^5.4.11" + "vite": "^6.0.1" }, "engines": { - "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + "node": "^18.17.1 || ^20.3.0 || >=22.0.0" }, "publishConfig": { "provenance": true diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts index de29003ff..fd2fab8c8 100644 --- a/packages/integrations/mdx/src/index.ts +++ b/packages/integrations/mdx/src/index.ts @@ -8,13 +8,12 @@ import type { ContentEntryType, HookParameters, } from 'astro'; -import astroJSXRenderer from 'astro/jsx/renderer.js'; import type { Options as RemarkRehypeOptions } from 'remark-rehype'; import type { PluggableList } from 'unified'; import type { OptimizeOptions } from './rehype-optimize-static.js'; -import { ignoreStringPlugins, parseFrontmatter } from './utils.js'; +import { ignoreStringPlugins, safeParseFrontmatter } from './utils.js'; import { vitePluginMdxPostprocess } from './vite-plugin-mdx-postprocess.js'; -import { vitePluginMdx } from './vite-plugin-mdx.js'; +import { type VitePluginMdxOptions, vitePluginMdx } from './vite-plugin-mdx.js'; export type MdxOptions = Omit<typeof markdownConfigDefaults, 'remarkPlugins' | 'rehypePlugins'> & { extendMarkdownConfig: boolean; @@ -37,14 +36,14 @@ type SetupHookParams = HookParameters<'astro:config:setup'> & { export function getContainerRenderer(): ContainerRenderer { return { name: 'astro:jsx', - serverEntrypoint: 'astro/jsx/server.js', + serverEntrypoint: '@astrojs/mdx/server.js', }; } export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroIntegration { // @ts-expect-error Temporarily assign an empty object here, which will be re-assigned by the // `astro:config:done` hook later. This is so that `vitePluginMdx` can get hold of a reference earlier. - let mdxOptions: MdxOptions = {}; + let vitePluginMdxOptions: VitePluginMdxOptions = {}; return { name: '@astrojs/mdx', @@ -53,17 +52,20 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI const { updateConfig, config, addPageExtension, addContentEntryType, addRenderer } = params as SetupHookParams; - addRenderer(astroJSXRenderer); + addRenderer({ + name: 'astro:jsx', + serverEntrypoint: new URL('../dist/server.js', import.meta.url), + }); addPageExtension('.mdx'); addContentEntryType({ extensions: ['.mdx'], async getEntryInfo({ fileUrl, contents }: { fileUrl: URL; contents: string }) { - const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl)); + const parsed = safeParseFrontmatter(contents, fileURLToPath(fileUrl)); return { - data: parsed.data, - body: parsed.content, - slug: parsed.data.slug, - rawData: parsed.matter, + data: parsed.frontmatter, + body: parsed.content.trim(), + slug: parsed.frontmatter.slug, + rawData: parsed.rawFrontmatter, }; }, contentModuleTypes: await fs.readFile( @@ -77,7 +79,7 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI updateConfig({ vite: { - plugins: [vitePluginMdx(mdxOptions), vitePluginMdxPostprocess(config)], + plugins: [vitePluginMdx(vitePluginMdxOptions), vitePluginMdxPostprocess(config)], }, }); }, @@ -96,10 +98,13 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI }); // Mutate `mdxOptions` so that `vitePluginMdx` can reference the actual options - Object.assign(mdxOptions, resolvedMdxOptions); + Object.assign(vitePluginMdxOptions, { + mdxOptions: resolvedMdxOptions, + srcDir: config.srcDir, + }); // @ts-expect-error After we assign, we don't need to reference `mdxOptions` in this context anymore. // Re-assign it so that the garbage can be collected later. - mdxOptions = {}; + vitePluginMdxOptions = {}; }, }, }; diff --git a/packages/integrations/mdx/src/plugins.ts b/packages/integrations/mdx/src/plugins.ts index 082e8f6fd..77c76243c 100644 --- a/packages/integrations/mdx/src/plugins.ts +++ b/packages/integrations/mdx/src/plugins.ts @@ -83,7 +83,7 @@ function getRehypePlugins(mdxOptions: MdxOptions): PluggableList { } rehypePlugins.push( - // Render info from `vfile.data.astro.data.frontmatter` as JS + // Render info from `vfile.data.astro.frontmatter` as JS rehypeApplyFrontmatterExport, // Analyze MDX nodes and attach to `vfile.data.__astroMetadata` rehypeAnalyzeAstroMetadata, diff --git a/packages/integrations/mdx/src/rehype-apply-frontmatter-export.ts b/packages/integrations/mdx/src/rehype-apply-frontmatter-export.ts index 1b981a68e..5880c30b3 100644 --- a/packages/integrations/mdx/src/rehype-apply-frontmatter-export.ts +++ b/packages/integrations/mdx/src/rehype-apply-frontmatter-export.ts @@ -1,23 +1,35 @@ -import { InvalidAstroDataError } from '@astrojs/markdown-remark'; -import { safelyGetAstroData } from '@astrojs/markdown-remark/dist/internal.js'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { isFrontmatterValid } from '@astrojs/markdown-remark'; +import type { Root, RootContent } from 'hast'; import type { VFile } from 'vfile'; import { jsToTreeNode } from './utils.js'; +// Passed metadata to help determine adding charset utf8 by default +declare module 'vfile' { + interface DataMap { + applyFrontmatterExport?: { + srcDir?: URL; + }; + } +} + +const exportConstPartialTrueRe = /export\s+const\s+partial\s*=\s*true/; + export function rehypeApplyFrontmatterExport() { - return function (tree: any, vfile: VFile) { - const astroData = safelyGetAstroData(vfile.data); - if (astroData instanceof InvalidAstroDataError) + return function (tree: Root, vfile: VFile) { + const frontmatter = vfile.data.astro?.frontmatter; + if (!frontmatter || !isFrontmatterValid(frontmatter)) throw new Error( // Copied from Astro core `errors-data` // TODO: find way to import error data from core '[MDX] A remark or rehype plugin attempted to inject invalid frontmatter. Ensure "astro.frontmatter" is set to a valid JSON object that is not `null` or `undefined`.', ); - const { frontmatter } = astroData; - const exportNodes = [ + const extraChildren: RootContent[] = [ jsToTreeNode(`export const frontmatter = ${JSON.stringify(frontmatter)};`), ]; if (frontmatter.layout) { - exportNodes.unshift( + extraChildren.unshift( jsToTreeNode( // NOTE: Use `__astro_*` import names to prevent conflicts with user code /** @see 'vite-plugin-markdown' for layout props reference */ @@ -41,7 +53,61 @@ export default function ({ children }) { };`, ), ); + } else if (shouldAddCharset(tree, vfile)) { + extraChildren.unshift({ + type: 'mdxJsxFlowElement', + name: 'meta', + attributes: [ + { + type: 'mdxJsxAttribute', + name: 'charset', + value: 'utf-8', + }, + ], + children: [], + }); } - tree.children = exportNodes.concat(tree.children); + tree.children = extraChildren.concat(tree.children); }; } + +/** + * If this is a page (e.g. in src/pages), has no layout frontmatter (handled before calling this function), + * has no leading component that looks like a wrapping layout, and `partial` isn't set to true, we default to + * adding charset=utf-8 like markdown so that users don't have to worry about it for MDX pages without layouts. + */ +function shouldAddCharset(tree: Root, vfile: VFile) { + const srcDirUrl = vfile.data.applyFrontmatterExport?.srcDir; + if (!srcDirUrl) return false; + + const hasConstPartialTrue = tree.children.some( + (node) => node.type === 'mdxjsEsm' && exportConstPartialTrueRe.test(node.value), + ); + if (hasConstPartialTrue) return false; + + // NOTE: the pages directory is a non-configurable Astro behaviour + const pagesDir = path.join(fileURLToPath(srcDirUrl), 'pages').replace(/\\/g, '/'); + // `vfile.path` comes from Vite, which is a normalized path (no backslashes) + const filePath = vfile.path; + if (!filePath.startsWith(pagesDir)) return false; + + const hasLeadingUnderscoreInPath = filePath + .slice(pagesDir.length) + .replace(/\\/g, '/') + .split('/') + .some((part) => part.startsWith('_')); + if (hasLeadingUnderscoreInPath) return false; + + // Bail if the first content found is a wrapping layout component + for (const child of tree.children) { + if (child.type === 'element') break; + if (child.type === 'mdxJsxFlowElement') { + // If is fragment or lowercase tag name (html tags), skip and assume there's no layout + if (child.name == null) break; + if (child.name[0] === child.name[0].toLowerCase()) break; + return false; + } + } + + return true; +} diff --git a/packages/integrations/mdx/src/rehype-collect-headings.ts b/packages/integrations/mdx/src/rehype-collect-headings.ts index fafc59721..a51e8e9f0 100644 --- a/packages/integrations/mdx/src/rehype-collect-headings.ts +++ b/packages/integrations/mdx/src/rehype-collect-headings.ts @@ -1,9 +1,9 @@ -import type { MarkdownHeading, MarkdownVFile } from '@astrojs/markdown-remark'; +import type { VFile } from 'vfile'; import { jsToTreeNode } from './utils.js'; export function rehypeInjectHeadingsExport() { - return function (tree: any, file: MarkdownVFile) { - const headings: MarkdownHeading[] = file.data.__astroHeadings || []; + return function (tree: any, file: VFile) { + const headings = file.data.astro?.headings ?? []; tree.children.unshift( jsToTreeNode(`export function getHeadings() { return ${JSON.stringify(headings)} }`), ); diff --git a/packages/integrations/mdx/src/rehype-images-to-component.ts b/packages/integrations/mdx/src/rehype-images-to-component.ts index 95b500784..da2f25ee5 100644 --- a/packages/integrations/mdx/src/rehype-images-to-component.ts +++ b/packages/integrations/mdx/src/rehype-images-to-component.ts @@ -1,8 +1,8 @@ -import type { MarkdownVFile } from '@astrojs/markdown-remark'; import type { Properties, Root } from 'hast'; import type { MdxJsxAttribute, MdxjsEsm } from 'mdast-util-mdx'; import type { MdxJsxFlowElementHast } from 'mdast-util-mdx-jsx'; import { visit } from 'unist-util-visit'; +import type { VFile } from 'vfile'; import { jsToTreeNode } from './utils.js'; export const ASTRO_IMAGE_ELEMENT = 'astro-image'; @@ -72,18 +72,18 @@ function getImageComponentAttributes(props: Properties): MdxJsxAttribute[] { } export function rehypeImageToComponent() { - return function (tree: Root, file: MarkdownVFile) { - if (!file.data.imagePaths) return; + return function (tree: Root, file: VFile) { + if (!file.data.astro?.imagePaths) return; const importsStatements: MdxjsEsm[] = []; const importedImages = new Map<string, string>(); visit(tree, 'element', (node, index, parent) => { - if (!file.data.imagePaths || node.tagName !== 'img' || !node.properties.src) return; + if (!file.data.astro?.imagePaths || node.tagName !== 'img' || !node.properties.src) return; const src = decodeURI(String(node.properties.src)); - if (!file.data.imagePaths.has(src)) return; + if (!file.data.astro.imagePaths?.includes(src)) return; let importName = importedImages.get(src); diff --git a/packages/integrations/mdx/src/server.ts b/packages/integrations/mdx/src/server.ts new file mode 100644 index 000000000..79934eb32 --- /dev/null +++ b/packages/integrations/mdx/src/server.ts @@ -0,0 +1,73 @@ +import type { NamedSSRLoadedRendererValue } from 'astro'; +import { AstroError } from 'astro/errors'; +import { AstroJSX, jsx } from 'astro/jsx-runtime'; +import { renderJSX } from 'astro/runtime/server/index.js'; + +const slotName = (str: string) => str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase()); + +// NOTE: In practice, MDX components are always tagged with `__astro_tag_component__`, so the right renderer +// is used directly, and this check is not often used to return true. +export async function check( + Component: any, + props: any, + { default: children = null, ...slotted } = {}, +) { + if (typeof Component !== 'function') return false; + const slots: Record<string, any> = {}; + for (const [key, value] of Object.entries(slotted)) { + const name = slotName(key); + slots[name] = value; + } + try { + const result = await Component({ ...props, ...slots, children }); + return result[AstroJSX]; + } catch (e) { + throwEnhancedErrorIfMdxComponent(e as Error, Component); + } + return false; +} + +export async function renderToStaticMarkup( + this: any, + Component: any, + props = {}, + { default: children = null, ...slotted } = {}, +) { + const slots: Record<string, any> = {}; + for (const [key, value] of Object.entries(slotted)) { + const name = slotName(key); + slots[name] = value; + } + + const { result } = this; + try { + const html = await renderJSX(result, jsx(Component, { ...props, ...slots, children })); + return { html }; + } catch (e) { + throwEnhancedErrorIfMdxComponent(e as Error, Component); + throw e; + } +} + +function throwEnhancedErrorIfMdxComponent(error: Error, Component: any) { + // if the exception is from an mdx component + // throw an error + if (Component[Symbol.for('mdx-component')]) { + // if it's an existing AstroError, we don't need to re-throw, keep the original hint + if (AstroError.is(error)) return; + // Mimic the fields of the internal `AstroError` class (not from `astro/errors`) to + // provide better title and hint for the error overlay + (error as any).title = error.name; + (error as any).hint = + `This issue often occurs when your MDX component encounters runtime errors.`; + throw error; + } +} + +const renderer: NamedSSRLoadedRendererValue = { + name: 'astro:jsx', + check, + renderToStaticMarkup, +}; + +export default renderer; diff --git a/packages/integrations/mdx/src/utils.ts b/packages/integrations/mdx/src/utils.ts index ad98abb9e..7dcd4a14c 100644 --- a/packages/integrations/mdx/src/utils.ts +++ b/packages/integrations/mdx/src/utils.ts @@ -1,7 +1,7 @@ +import { parseFrontmatter } from '@astrojs/markdown-remark'; import type { Options as AcornOpts } from 'acorn'; import { parse } from 'acorn'; import type { AstroConfig, AstroIntegrationLogger, SSRError } from 'astro'; -import matter from 'gray-matter'; import { bold } from 'kleur/colors'; import type { MdxjsEsm } from 'mdast-util-mdx'; import type { PluggableList } from 'unified'; @@ -48,9 +48,9 @@ export function getFileInfo(id: string, config: AstroConfig): FileInfo { * Match YAML exception handling from Astro core errors * @see 'astro/src/core/errors.ts' */ -export function parseFrontmatter(code: string, id: string) { +export function safeParseFrontmatter(code: string, id: string) { try { - return matter(code); + return parseFrontmatter(code, { frontmatter: 'empty-with-spaces' }); } catch (e: any) { if (e.name === 'YAMLException') { const err: SSRError = e; diff --git a/packages/integrations/mdx/src/vite-plugin-mdx.ts b/packages/integrations/mdx/src/vite-plugin-mdx.ts index 5a409d40d..869c65d26 100644 --- a/packages/integrations/mdx/src/vite-plugin-mdx.ts +++ b/packages/integrations/mdx/src/vite-plugin-mdx.ts @@ -1,13 +1,18 @@ -import { setVfileFrontmatter } from '@astrojs/markdown-remark'; import type { SSRError } from 'astro'; import { getAstroMetadata } from 'astro/jsx/rehype.js'; import { VFile } from 'vfile'; import type { Plugin } from 'vite'; import type { MdxOptions } from './index.js'; import { createMdxProcessor } from './plugins.js'; -import { parseFrontmatter } from './utils.js'; +import { safeParseFrontmatter } from './utils.js'; -export function vitePluginMdx(mdxOptions: MdxOptions): Plugin { +export interface VitePluginMdxOptions { + mdxOptions: MdxOptions; + srcDir: URL; +} + +// NOTE: Do not destructure `opts` as we're assigning a reference that will be mutated later +export function vitePluginMdx(opts: VitePluginMdxOptions): Plugin { let processor: ReturnType<typeof createMdxProcessor> | undefined; let sourcemapEnabled: boolean; @@ -39,16 +44,24 @@ export function vitePluginMdx(mdxOptions: MdxOptions): Plugin { async transform(code, id) { if (!id.endsWith('.mdx')) return; - const { data: frontmatter, content: pageContent, matter } = parseFrontmatter(code, id); - const frontmatterLines = matter ? matter.match(/\n/g)?.join('') + '\n\n' : ''; + const { frontmatter, content } = safeParseFrontmatter(code, id); - const vfile = new VFile({ value: frontmatterLines + pageContent, path: id }); - // Ensure `data.astro` is available to all remark plugins - setVfileFrontmatter(vfile, frontmatter); + const vfile = new VFile({ + value: content, + path: id, + data: { + astro: { + frontmatter, + }, + applyFrontmatterExport: { + srcDir: opts.srcDir, + }, + }, + }); // Lazily initialize the MDX processor if (!processor) { - processor = createMdxProcessor(mdxOptions, { sourcemap: sourcemapEnabled }); + processor = createMdxProcessor(opts.mdxOptions, { sourcemap: sourcemapEnabled }); } try { diff --git a/packages/integrations/mdx/test/css-head-mdx.test.js b/packages/integrations/mdx/test/css-head-mdx.test.js index 4d4df5cec..d55e2f52a 100644 --- a/packages/integrations/mdx/test/css-head-mdx.test.js +++ b/packages/integrations/mdx/test/css-head-mdx.test.js @@ -15,7 +15,6 @@ describe('Head injection w/ MDX', () => { integrations: [mdx()], // test suite was authored when inlineStylesheets defaulted to never build: { inlineStylesheets: 'never' }, - experimental: { contentLayer: true }, }); }); @@ -24,14 +23,14 @@ describe('Head injection w/ MDX', () => { await fixture.build(); }); - it('only injects contents into head', async () => { + it('injects content styles into head', async () => { const html = await fixture.readFile('/indexThree/index.html'); const { document } = parseHTML(html); const links = document.querySelectorAll('head link[rel=stylesheet]'); - assert.equal(links.length, 1); + assert.equal(links.length, 2); - const scripts = document.querySelectorAll('head script[type=module]'); + const scripts = document.querySelectorAll('script[type=module]'); assert.equal(scripts.length, 1); }); @@ -40,7 +39,7 @@ describe('Head injection w/ MDX', () => { const { document } = parseHTML(html); const links = document.querySelectorAll('head link[rel=stylesheet]'); - assert.equal(links.length, 1); + assert.equal(links.length, 2); }); it('injects content from a component using Content#render()', async () => { @@ -48,9 +47,9 @@ describe('Head injection w/ MDX', () => { const { document } = parseHTML(html); const links = document.querySelectorAll('head link[rel=stylesheet]'); - assert.equal(links.length, 1); + assert.equal(links.length, 2); - const scripts = document.querySelectorAll('head script[type=module]'); + const scripts = document.querySelectorAll('script[type=module]'); assert.equal(scripts.length, 1); }); @@ -68,7 +67,7 @@ describe('Head injection w/ MDX', () => { const $ = cheerio.load(html); const headLinks = $('head link[rel=stylesheet]'); - assert.equal(headLinks.length, 1); + assert.equal(headLinks.length, 2); const bodyLinks = $('body link[rel=stylesheet]'); assert.equal(bodyLinks.length, 0); @@ -80,7 +79,7 @@ describe('Head injection w/ MDX', () => { const $ = cheerio.load(html); const headLinks = $('head link[rel=stylesheet]'); - assert.equal(headLinks.length, 1); + assert.equal(headLinks.length, 2); const bodyLinks = $('body link[rel=stylesheet]'); assert.equal(bodyLinks.length, 0); @@ -93,7 +92,7 @@ describe('Head injection w/ MDX', () => { const $ = cheerio.load(html); const headLinks = $('head link[rel=stylesheet]'); - assert.equal(headLinks.length, 1); + assert.equal(headLinks.length, 2); const bodyLinks = $('body link[rel=stylesheet]'); assert.equal(bodyLinks.length, 0); diff --git a/packages/integrations/mdx/test/fixtures/mdx-images/src/content/config.ts b/packages/integrations/mdx/test/fixtures/mdx-images/src/content/config.ts new file mode 100644 index 000000000..14443e78d --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/mdx-images/src/content/config.ts @@ -0,0 +1,5 @@ +import { defineCollection, z } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { blog }; diff --git a/packages/integrations/mdx/test/fixtures/mdx-images/tsconfig.json b/packages/integrations/mdx/test/fixtures/mdx-images/tsconfig.json index b5bf6a715..c193287fc 100644 --- a/packages/integrations/mdx/test/fixtures/mdx-images/tsconfig.json +++ b/packages/integrations/mdx/test/fixtures/mdx-images/tsconfig.json @@ -5,5 +5,7 @@ "paths": { "~/assets/*": ["src/assets/*"] }, - } + }, + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] } diff --git a/packages/integrations/mdx/test/fixtures/mdx-page/src/layouts/EncodingLayout.astro b/packages/integrations/mdx/test/fixtures/mdx-page/src/layouts/EncodingLayout.astro new file mode 100644 index 000000000..13e0e91ed --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/mdx-page/src/layouts/EncodingLayout.astro @@ -0,0 +1 @@ +<slot></slot> diff --git a/packages/integrations/mdx/test/fixtures/mdx-page/src/pages/chinese-encoding-layout-frontmatter.mdx b/packages/integrations/mdx/test/fixtures/mdx-page/src/pages/chinese-encoding-layout-frontmatter.mdx new file mode 100644 index 000000000..471827de0 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/mdx-page/src/pages/chinese-encoding-layout-frontmatter.mdx @@ -0,0 +1,7 @@ +--- +layout: ../layouts/EncodingLayout.astro +--- + +# 我的第一篇博客文章 + +发表于:2022-07-01 diff --git a/packages/integrations/mdx/test/fixtures/mdx-page/src/pages/chinese-encoding-layout-manual.mdx b/packages/integrations/mdx/test/fixtures/mdx-page/src/pages/chinese-encoding-layout-manual.mdx new file mode 100644 index 000000000..1c8c78630 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/mdx-page/src/pages/chinese-encoding-layout-manual.mdx @@ -0,0 +1,12 @@ +import EncodingLayout from '../layouts/EncodingLayout.astro' + +{/* Ensure random stuff preceding the wrapper layout is ignored when detecting a wrapper layout */} +export const foo = {} + +<EncodingLayout> + +# 我的第一篇博客文章 + +发表于:2022-07-01 + +</EncodingLayout> diff --git a/packages/integrations/mdx/test/fixtures/mdx-page/src/pages/chinese-encoding.mdx b/packages/integrations/mdx/test/fixtures/mdx-page/src/pages/chinese-encoding.mdx new file mode 100644 index 000000000..572b3c370 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/mdx-page/src/pages/chinese-encoding.mdx @@ -0,0 +1,3 @@ +# 我的第一篇博客文章 + +发表于:2022-07-01 diff --git a/packages/integrations/mdx/test/mdx-math.test.js b/packages/integrations/mdx/test/mdx-math.test.js index 5352eca68..a68c5cbe7 100644 --- a/packages/integrations/mdx/test/mdx-math.test.js +++ b/packages/integrations/mdx/test/mdx-math.test.js @@ -28,7 +28,7 @@ describe('MDX math', () => { const mjxContainer = document.querySelector('mjx-container[jax="SVG"]'); assert.notEqual(mjxContainer, null); - const mjxStyle = document.querySelector('style').innerHTML; + const mjxStyle = document.querySelectorAll('style')[1].innerHTML; assert.equal( mjxStyle.includes('mjx-container[jax="SVG"]'), true, @@ -62,7 +62,7 @@ describe('MDX math', () => { const mjxContainer = document.querySelector('mjx-container[jax="CHTML"]'); assert.notEqual(mjxContainer, null); - const mjxStyle = document.querySelector('style').innerHTML; + const mjxStyle = document.querySelectorAll('style')[1].innerHTML; assert.equal( mjxStyle.includes('mjx-container[jax="CHTML"]'), true, diff --git a/packages/integrations/mdx/test/mdx-page.test.js b/packages/integrations/mdx/test/mdx-page.test.js index 7948de653..b58781efc 100644 --- a/packages/integrations/mdx/test/mdx-page.test.js +++ b/packages/integrations/mdx/test/mdx-page.test.js @@ -1,5 +1,6 @@ import * as assert from 'node:assert/strict'; import { after, before, describe, it } from 'node:test'; +import * as cheerio from 'cheerio'; import { parseHTML } from 'linkedom'; import { loadFixture } from '../../../astro/test/test-utils.js'; @@ -36,6 +37,23 @@ describe('MDX Page', () => { assert.notEqual(stylesheet, null); }); + + it('Renders MDX in utf-8 by default', async () => { + const html = await fixture.readFile('/chinese-encoding/index.html'); + const $ = cheerio.load(html); + assert.equal($('h1').text(), '我的第一篇博客文章'); + assert.match(html, /<meta charset="utf-8"/); + }); + + it('Renders MDX with layout frontmatter without utf-8 by default', async () => { + const html = await fixture.readFile('/chinese-encoding-layout-frontmatter/index.html'); + assert.doesNotMatch(html, /<meta charset="utf-8"/); + }); + + it('Renders MDX with layout manual import without utf-8 by default', async () => { + const html = await fixture.readFile('/chinese-encoding-layout-manual/index.html'); + assert.doesNotMatch(html, /<meta charset="utf-8"/); + }); }); describe('dev', () => { @@ -61,5 +79,31 @@ describe('MDX Page', () => { assert.equal(h1.textContent, 'Hello page!'); }); + + it('Renders MDX in utf-8 by default', async () => { + const res = await fixture.fetch('/chinese-encoding/'); + assert.equal(res.status, 200); + const html = await res.text(); + const $ = cheerio.load(html); + assert.equal($('h1').text(), '我的第一篇博客文章'); + assert.doesNotMatch(res.headers.get('content-type'), /charset=utf-8/); + assert.match(html, /<meta charset="utf-8"/); + }); + + it('Renders MDX with layout frontmatter without utf-8 by default', async () => { + const res = await fixture.fetch('/chinese-encoding-layout-frontmatter/'); + assert.equal(res.status, 200); + const html = await res.text(); + assert.doesNotMatch(res.headers.get('content-type'), /charset=utf-8/); + assert.doesNotMatch(html, /<meta charset="utf-8"/); + }); + + it('Renders MDX with layout manual import without utf-8 by default', async () => { + const res = await fixture.fetch('/chinese-encoding-layout-manual/'); + assert.equal(res.status, 200); + const html = await res.text(); + assert.doesNotMatch(res.headers.get('content-type'), /charset=utf-8/); + assert.doesNotMatch(html, /<meta charset="utf-8"/); + }); }); }); diff --git a/packages/integrations/mdx/test/mdx-vite-env-vars.test.js b/packages/integrations/mdx/test/mdx-vite-env-vars.test.js index 80a9b1cec..213386ceb 100644 --- a/packages/integrations/mdx/test/mdx-vite-env-vars.test.js +++ b/packages/integrations/mdx/test/mdx-vite-env-vars.test.js @@ -57,8 +57,8 @@ describe('MDX - Vite env vars', () => { const dataAttrDump = document.querySelector('[data-env-dump]'); assert.notEqual(dataAttrDump, null); - assert.notEqual(dataAttrDump.getAttribute('data-env-prod'), null); - assert.equal(dataAttrDump.getAttribute('data-env-dev'), null); + assert.equal(dataAttrDump.getAttribute('data-env-prod'), 'true'); + assert.equal(dataAttrDump.getAttribute('data-env-dev'), 'false'); assert.equal(dataAttrDump.getAttribute('data-env-base-url'), '/'); assert.equal(dataAttrDump.getAttribute('data-env-mode'), 'production'); }); diff --git a/packages/integrations/preact/package.json b/packages/integrations/preact/package.json index d32dca053..0cd20421a 100644 --- a/packages/integrations/preact/package.json +++ b/packages/integrations/preact/package.json @@ -1,7 +1,7 @@ { "name": "@astrojs/preact", "description": "Use Preact components within Astro", - "version": "3.5.4", + "version": "3.5.4-beta.0", "type": "module", "types": "./dist/index.d.ts", "author": "withastro", @@ -41,7 +41,7 @@ "@preact/signals": "^1.3.0", "babel-plugin-transform-hook-names": "^1.0.2", "preact-render-to-string": "^6.5.11", - "vite": "^5.4.11" + "vite": "^6.0.1" }, "devDependencies": { "astro": "workspace:*", @@ -52,7 +52,7 @@ "preact": "^10.6.5" }, "engines": { - "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + "node": "^18.17.1 || ^20.3.0 || >=22.0.0" }, "publishConfig": { "provenance": true diff --git a/packages/integrations/react/CHANGELOG.md b/packages/integrations/react/CHANGELOG.md index 45f9ffaeb..31c9066ca 100644 --- a/packages/integrations/react/CHANGELOG.md +++ b/packages/integrations/react/CHANGELOG.md @@ -1,5 +1,11 @@ # @astrojs/react +## 3.7.0-beta.1 + +### Minor Changes + +- [#12510](https://github.com/withastro/astro/pull/12510) [`14feaf3`](https://github.com/withastro/astro/commit/14feaf30e1a4266b8422865722a4478d39202404) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Changes the generated URL query param from `_astroAction` to `_action` when submitting a form using Actions. This avoids leaking the framework name into the URL bar, which may be considered a security issue. + ## 3.6.3 ### Patch Changes diff --git a/packages/integrations/react/package.json b/packages/integrations/react/package.json index e4662b820..4a0c7262b 100644 --- a/packages/integrations/react/package.json +++ b/packages/integrations/react/package.json @@ -1,7 +1,7 @@ { "name": "@astrojs/react", "description": "Use React components within Astro", - "version": "3.6.3", + "version": "3.7.0-beta.1", "type": "module", "types": "./dist/index.d.ts", "author": "withastro", @@ -51,7 +51,7 @@ "dependencies": { "@vitejs/plugin-react": "^4.3.4", "ultrahtml": "^1.5.3", - "vite": "^5.4.11" + "vite": "^6.0.1" }, "devDependencies": { "@types/react": "^18.3.12", @@ -69,7 +69,7 @@ "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0-beta" }, "engines": { - "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + "node": "^18.17.1 || ^20.3.0 || >=22.0.0" }, "publishConfig": { "provenance": true diff --git a/packages/integrations/react/server.js b/packages/integrations/react/server.js index 69b0a8e12..9c3c309cc 100644 --- a/packages/integrations/react/server.js +++ b/packages/integrations/react/server.js @@ -126,11 +126,7 @@ async function getFormState({ result }) { * This matches the endpoint path. * @example "/_actions/blog.like" */ - const actionName = - searchParams.get('_astroAction') ?? - /* Legacy. TODO: remove for stable */ formData - .get('_astroAction') - ?.toString(); + const actionName = searchParams.get('_action'); if (!actionKey || !actionName) return undefined; diff --git a/packages/integrations/react/src/actions.ts b/packages/integrations/react/src/actions.ts index a5ccb2f9a..06ecd4148 100644 --- a/packages/integrations/react/src/actions.ts +++ b/packages/integrations/react/src/actions.ts @@ -26,7 +26,7 @@ export function experimental_withState<T>(action: FormFn<T>) { // Called by React when form state is passed from the server. // If the action names match, React returns this state from `useActionState()`. callback.$$IS_SIGNATURE_EQUAL = (incomingActionName: string) => { - const actionName = new URLSearchParams(action.toString()).get('_astroAction'); + const actionName = new URLSearchParams(action.toString()).get('_action'); return actionName === incomingActionName; }; @@ -46,7 +46,9 @@ export function experimental_withState<T>(action: FormFn<T>) { */ export async function experimental_getActionState<T>({ request, -}: { request: Request }): Promise<T> { +}: { + request: Request; +}): Promise<T> { const contentType = request.headers.get('Content-Type'); if (!contentType || !isFormRequest(contentType)) { throw new AstroError( diff --git a/packages/integrations/solid/package.json b/packages/integrations/solid/package.json index e6622296d..dd76b0618 100644 --- a/packages/integrations/solid/package.json +++ b/packages/integrations/solid/package.json @@ -1,6 +1,6 @@ { "name": "@astrojs/solid-js", - "version": "4.4.4", + "version": "4.4.4-beta.0", "description": "Use Solid components within Astro", "type": "module", "types": "./dist/index.d.ts", @@ -36,7 +36,7 @@ }, "dependencies": { "vite-plugin-solid": "^2.11.0", - "vite": "^5.4.11" + "vite": "^6.0.1" }, "devDependencies": { "astro": "workspace:*", @@ -53,7 +53,7 @@ } }, "engines": { - "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + "node": "^18.17.1 || ^20.3.0 || >=22.0.0" }, "publishConfig": { "provenance": true diff --git a/packages/integrations/solid/src/index.ts b/packages/integrations/solid/src/index.ts index 001f3d6ab..60680ff9c 100644 --- a/packages/integrations/solid/src/index.ts +++ b/packages/integrations/solid/src/index.ts @@ -45,43 +45,15 @@ async function getDevtoolsPlugin(logger: AstroIntegrationLogger, retrieve: boole } } -async function getViteConfiguration( - isDev: boolean, +function getViteConfiguration( { include, exclude }: Options, devtoolsPlugin: DevtoolsPlugin | null, ) { - // https://github.com/solidjs/vite-plugin-solid - // We inject the dev mode only if the user explicitly wants it or if we are in dev (serve) mode - const nestedDeps = ['solid-js', 'solid-js/web', 'solid-js/store', 'solid-js/html', 'solid-js/h']; const config: UserConfig = { - resolve: { - conditions: ['solid', ...(isDev ? ['development'] : [])], - dedupe: nestedDeps, - alias: [{ find: /^solid-refresh$/, replacement: '/@solid-refresh' }], - }, optimizeDeps: { - include: [...nestedDeps], exclude: ['@astrojs/solid-js/server.js'], }, - plugins: [ - solid({ include, exclude, dev: isDev, ssr: true }), - { - name: '@astrojs/solid:config-overrides', - enforce: 'post', - config() { - return { - esbuild: { - // To support using alongside other JSX frameworks, still let - // esbuild compile stuff. Solid goes first anyways. - include: /\.(m?ts|[jt]sx)$/, - }, - }; - }, - }, - ], - ssr: { - external: ['babel-preset-solid'], - }, + plugins: [solid({ include, exclude, ssr: true })], }; if (devtoolsPlugin) { @@ -128,7 +100,7 @@ export default function (options: Options = {}): AstroIntegration { addRenderer(getRenderer()); updateConfig({ - vite: await getViteConfiguration(command === 'dev', options, devtoolsPlugin), + vite: getViteConfiguration(options, devtoolsPlugin), }); if (devtoolsPlugin) { diff --git a/packages/integrations/svelte/CHANGELOG.md b/packages/integrations/svelte/CHANGELOG.md index 36da20e51..76b1bbff5 100644 --- a/packages/integrations/svelte/CHANGELOG.md +++ b/packages/integrations/svelte/CHANGELOG.md @@ -6,6 +6,9 @@ - [#12481](https://github.com/withastro/astro/pull/12481) [`8a46e80`](https://github.com/withastro/astro/commit/8a46e8074d6afb4a23badbd59ed239d526294e8c) Thanks [@marbrex](https://github.com/marbrex)! - Resolve `vite` peer dependency problem for strict package managers like **Yarn in PnP mode**. +- Updated dependencies [[`c48916c`](https://github.com/withastro/astro/commit/c48916cc4e6f7c31e3563d04b68a8698d8775b65), [`4364bff`](https://github.com/withastro/astro/commit/4364bff27332e52f92da72392620a36110daee42), [`c8f877c`](https://github.com/withastro/astro/commit/c8f877cad2d8f1780f70045413872d5b9d32ebed), [`8309c61`](https://github.com/withastro/astro/commit/8309c61f0dfa5991d3f6c5c5fca4403794d6fda2), [`af867f3`](https://github.com/withastro/astro/commit/af867f3910ecd8fc04a5337f591d84f03192e3fa), [`3f02d5f`](https://github.com/withastro/astro/commit/3f02d5f12b167514fff6eb9693b4e25c668e7a31)]: + - astro@5.0.0-beta.9 + ## 6.0.1 ### Patch Changes @@ -33,6 +36,31 @@ Refer to the [Svelte 5 migration guide](https://svelte.dev/docs/svelte/v5-migration-guide) and [`@sveltejs/vite-plugin-svelte` changelog](https://github.com/sveltejs/vite-plugin-svelte/blob/main/packages/vite-plugin-svelte/CHANGELOG.md#400) for details of their respective breaking changes. +## 6.0.0-beta.2 + +### Patch Changes + +- [`b21a075`](https://github.com/withastro/astro/commit/b21a07500284a3621be4d509f5aa67c0a8fcbf07) Thanks [@bluwy](https://github.com/bluwy)! - New release to include changes from 5.7.3 + +## 6.0.0-beta.1 + +### Patch Changes + +- [#12102](https://github.com/withastro/astro/pull/12102) [`dcc1e89`](https://github.com/withastro/astro/commit/dcc1e895abbad1311719803363c933541c0ad984) Thanks [@hermit99](https://github.com/hermit99)! - Fixes an Reference Error that occurred during client transitions + +## 6.0.0-beta.0 + +### Major Changes + +- [#12060](https://github.com/withastro/astro/pull/12060) [`cb5d3ae`](https://github.com/withastro/astro/commit/cb5d3ae6ee6af646c9d7d46a9d8f551edac3092e) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updates peer dependency range to support Astro 5 + +## 6.0.0-alpha.0 + +### Patch Changes + +- Updated dependencies [[`b6fbdaa`](https://github.com/withastro/astro/commit/b6fbdaa94a9ecec706a99e1938fbf5cd028c72e0), [`89bab1e`](https://github.com/withastro/astro/commit/89bab1e70786123fbe933a9d7a1b80c9334dcc5f), [`d74617c`](https://github.com/withastro/astro/commit/d74617cbd3278feba05909ec83db2d73d57a153e), [`e90f559`](https://github.com/withastro/astro/commit/e90f5593d23043579611452a84b9e18ad2407ef9), [`2df49a6`](https://github.com/withastro/astro/commit/2df49a6fb4f6d92fe45f7429430abe63defeacd6), [`8a53517`](https://github.com/withastro/astro/commit/8a5351737d6a14fc55f1dafad8f3b04079e81af6)]: + - astro@5.0.0-alpha.0 + ## 5.7.3 ### Patch Changes diff --git a/packages/integrations/svelte/package.json b/packages/integrations/svelte/package.json index 053f5ebb6..8113af063 100644 --- a/packages/integrations/svelte/package.json +++ b/packages/integrations/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@astrojs/svelte", - "version": "6.0.2", + "version": "6.0.2-beta.0", "description": "Use Svelte components within Astro", "type": "module", "types": "./dist/index.d.ts", @@ -39,9 +39,9 @@ "dev": "astro-scripts dev \"src/**/*.ts\"" }, "dependencies": { - "@sveltejs/vite-plugin-svelte": "^4.0.2", - "svelte2tsx": "^0.7.28", - "vite": "^5.4.11" + "@sveltejs/vite-plugin-svelte": "^5.0.1", + "svelte2tsx": "^0.7.22", + "vite": "^6.0.1" }, "devDependencies": { "astro": "workspace:*", @@ -49,12 +49,12 @@ "svelte": "^5.2.9" }, "peerDependencies": { - "astro": "^4.0.0", + "astro": "^5.0.0-beta.9", "svelte": "^5.1.16", "typescript": "^5.3.3" }, "engines": { - "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + "node": "^18.17.1 || ^20.3.0 || >=22.0.0" }, "publishConfig": { "provenance": true diff --git a/packages/integrations/tailwind/CHANGELOG.md b/packages/integrations/tailwind/CHANGELOG.md index 4179807df..0fe76096e 100644 --- a/packages/integrations/tailwind/CHANGELOG.md +++ b/packages/integrations/tailwind/CHANGELOG.md @@ -1,11 +1,25 @@ # @astrojs/tailwind +## 6.0.0-alpha.0 + +### Patch Changes + +- Updated dependencies [[`b6fbdaa`](https://github.com/withastro/astro/commit/b6fbdaa94a9ecec706a99e1938fbf5cd028c72e0), [`89bab1e`](https://github.com/withastro/astro/commit/89bab1e70786123fbe933a9d7a1b80c9334dcc5f), [`d74617c`](https://github.com/withastro/astro/commit/d74617cbd3278feba05909ec83db2d73d57a153e), [`e90f559`](https://github.com/withastro/astro/commit/e90f5593d23043579611452a84b9e18ad2407ef9), [`2df49a6`](https://github.com/withastro/astro/commit/2df49a6fb4f6d92fe45f7429430abe63defeacd6), [`8a53517`](https://github.com/withastro/astro/commit/8a5351737d6a14fc55f1dafad8f3b04079e81af6)]: + - astro@5.0.0-alpha.0 + ## 5.1.2 ### Patch Changes - [#12161](https://github.com/withastro/astro/pull/12161) [`8e500f2`](https://github.com/withastro/astro/commit/8e500f2f9656a98e4a14ef567f9bf072459f62c4) Thanks [@delucis](https://github.com/delucis)! - Adds keywords to `package.json` to improve categorization in the Astro integrations catalog +## 6.0.0-alpha.0 + +### Patch Changes + +- Updated dependencies [[`b6fbdaa`](https://github.com/withastro/astro/commit/b6fbdaa94a9ecec706a99e1938fbf5cd028c72e0), [`89bab1e`](https://github.com/withastro/astro/commit/89bab1e70786123fbe933a9d7a1b80c9334dcc5f), [`d74617c`](https://github.com/withastro/astro/commit/d74617cbd3278feba05909ec83db2d73d57a153e), [`e90f559`](https://github.com/withastro/astro/commit/e90f5593d23043579611452a84b9e18ad2407ef9), [`2df49a6`](https://github.com/withastro/astro/commit/2df49a6fb4f6d92fe45f7429430abe63defeacd6), [`8a53517`](https://github.com/withastro/astro/commit/8a5351737d6a14fc55f1dafad8f3b04079e81af6)]: + - astro@5.0.0-alpha.0 + ## 5.1.1 ### Patch Changes diff --git a/packages/integrations/tailwind/package.json b/packages/integrations/tailwind/package.json index 28ad75fc3..c2d033b08 100644 --- a/packages/integrations/tailwind/package.json +++ b/packages/integrations/tailwind/package.json @@ -42,8 +42,8 @@ "devDependencies": { "astro": "workspace:*", "astro-scripts": "workspace:*", - "tailwindcss": "^3.4.15", - "vite": "^5.4.11" + "tailwindcss": "^3.4.14", + "vite": "^6.0.1" }, "peerDependencies": { "astro": "^3.0.0 || ^4.0.0 || ^5.0.0-beta.0", diff --git a/packages/integrations/vue/CHANGELOG.md b/packages/integrations/vue/CHANGELOG.md index daad7f51b..71f28ed6c 100644 --- a/packages/integrations/vue/CHANGELOG.md +++ b/packages/integrations/vue/CHANGELOG.md @@ -1,5 +1,24 @@ # @astrojs/vue +## 5.0.0-beta.1 + +### Patch Changes + +- [`81b0bf5`](https://github.com/withastro/astro/commit/81b0bf5734735a0633bfc1089151e174ba9fbc83) Thanks [@bluwy](https://github.com/bluwy)! - New release to include changes from 4.5.2 + +## 5.0.0-beta.0 + +### Major Changes + +- [#12060](https://github.com/withastro/astro/pull/12060) [`cb5d3ae`](https://github.com/withastro/astro/commit/cb5d3ae6ee6af646c9d7d46a9d8f551edac3092e) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updates peer dependency range to support Astro 5 + +## 5.0.0-alpha.0 + +### Patch Changes + +- Updated dependencies [[`b6fbdaa`](https://github.com/withastro/astro/commit/b6fbdaa94a9ecec706a99e1938fbf5cd028c72e0), [`89bab1e`](https://github.com/withastro/astro/commit/89bab1e70786123fbe933a9d7a1b80c9334dcc5f), [`d74617c`](https://github.com/withastro/astro/commit/d74617cbd3278feba05909ec83db2d73d57a153e), [`e90f559`](https://github.com/withastro/astro/commit/e90f5593d23043579611452a84b9e18ad2407ef9), [`2df49a6`](https://github.com/withastro/astro/commit/2df49a6fb4f6d92fe45f7429430abe63defeacd6), [`8a53517`](https://github.com/withastro/astro/commit/8a5351737d6a14fc55f1dafad8f3b04079e81af6)]: + - astro@5.0.0-alpha.0 + ## 4.5.3 ### Patch Changes diff --git a/packages/integrations/vue/package.json b/packages/integrations/vue/package.json index aec6d3eaf..b99400b34 100644 --- a/packages/integrations/vue/package.json +++ b/packages/integrations/vue/package.json @@ -1,6 +1,6 @@ { "name": "@astrojs/vue", - "version": "4.5.3", + "version": "5.0.0-beta.2", "description": "Use Vue components within Astro", "type": "module", "types": "./dist/index.d.ts", @@ -43,10 +43,10 @@ }, "dependencies": { "@vitejs/plugin-vue": "^5.2.1", - "@vitejs/plugin-vue-jsx": "^4.1.1", - "@vue/compiler-sfc": "^3.5.13", - "vite-plugin-vue-devtools": "^7.6.4", - "vite": "^5.4.11" + "@vitejs/plugin-vue-jsx": "^4.0.1", + "@vue/compiler-sfc": "^3.5.12", + "vite": "^6.0.1", + "vite-plugin-vue-devtools": "^7.6.3" }, "devDependencies": { "astro": "workspace:*", @@ -56,11 +56,11 @@ "vue": "^3.5.13" }, "peerDependencies": { - "astro": "^4.0.0", + "astro": "^5.0.0-alpha.0", "vue": "^3.2.30" }, "engines": { - "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + "node": "^18.17.1 || ^20.3.0 || >=22.0.0" }, "publishConfig": { "provenance": true diff --git a/packages/integrations/web-vitals/CHANGELOG.md b/packages/integrations/web-vitals/CHANGELOG.md index 8e350c74e..dede426c6 100644 --- a/packages/integrations/web-vitals/CHANGELOG.md +++ b/packages/integrations/web-vitals/CHANGELOG.md @@ -1,5 +1,27 @@ # @astrojs/web-vitals +## 3.0.0-beta.1 + +### Major Changes + +- [#12008](https://github.com/withastro/astro/pull/12008) [`5608338`](https://github.com/withastro/astro/commit/560833843c6d3ce2b6c6c473ec4ae70e744bf255) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Welcome to the Astro 5 beta! This release has no changes from the latest alpha of this package, but it does bring us one step closer to the final, stable release. + + Starting from this release, no breaking changes will be introduced unless absolutely necessary. + + To learn how to upgrade, check out the [Astro v5.0 upgrade guide in our beta docs site](https://5-0-0-beta.docs.astro.build/en/guides/upgrade-to/v5/). + +### Patch Changes + +- Updated dependencies [[`5608338`](https://github.com/withastro/astro/commit/560833843c6d3ce2b6c6c473ec4ae70e744bf255)]: + - @astrojs/db@0.14.0-beta.1 + +## 2.0.1-alpha.0 + +### Patch Changes + +- Updated dependencies [[`b677429`](https://github.com/withastro/astro/commit/b67742961a384c10e5cd04cf5b02d0f014ea7362)]: + - @astrojs/db@0.13.2-alpha.0 + ## 3.0.0 ### Patch Changes diff --git a/packages/integrations/web-vitals/package.json b/packages/integrations/web-vitals/package.json index 3aa0616fc..d06582b15 100644 --- a/packages/integrations/web-vitals/package.json +++ b/packages/integrations/web-vitals/package.json @@ -1,7 +1,7 @@ { "name": "@astrojs/web-vitals", "description": "Track your website’s performance with Astro DB", - "version": "3.0.0", + "version": "3.0.0-beta.1", "type": "module", "author": "withastro", "license": "MIT", @@ -35,7 +35,7 @@ "web-vitals": "^4.2.4" }, "peerDependencies": { - "@astrojs/db": "^0.14.0" + "@astrojs/db": "^0.14.0-beta.1" }, "devDependencies": { "@astrojs/db": "workspace:*", diff --git a/packages/integrations/web-vitals/src/index.ts b/packages/integrations/web-vitals/src/index.ts index 02293ac6f..c74ab3261 100644 --- a/packages/integrations/web-vitals/src/index.ts +++ b/packages/integrations/web-vitals/src/index.ts @@ -19,14 +19,6 @@ export default function webVitals({ deprecated }: { deprecated?: boolean } = {}) ); } - if (config.output !== 'hybrid' && config.output !== 'server') { - throw new AstroError( - 'No SSR adapter found.', - '`@astrojs/web-vitals` requires your site to be built with `hybrid` or `server` output.\n' + - 'Please add an SSR adapter: https://docs.astro.build/en/guides/server-side-rendering/', - ); - } - // Middleware that adds a `<meta>` tag to each page. addMiddleware({ entrypoint: '@astrojs/web-vitals/middleware', order: 'post' }); // Endpoint that collects metrics and inserts them in Astro DB. diff --git a/packages/integrations/web-vitals/test/fixtures/basics/astro.config.mjs b/packages/integrations/web-vitals/test/fixtures/basics/astro.config.mjs index 42bfa6f66..4dae98ae0 100644 --- a/packages/integrations/web-vitals/test/fixtures/basics/astro.config.mjs +++ b/packages/integrations/web-vitals/test/fixtures/basics/astro.config.mjs @@ -6,7 +6,7 @@ import { defineConfig } from 'astro/config'; // https://astro.build/config export default defineConfig({ integrations: [db(), webVitals()], - output: 'hybrid', + output: 'static', adapter: node({ mode: 'standalone' }), devToolbar: { enabled: false, |