diff --git a/.changeset/shaggy-games-retire.md b/.changeset/shaggy-games-retire.md new file mode 100644 index 00000000000..a3980e8bdb3 --- /dev/null +++ b/.changeset/shaggy-games-retire.md @@ -0,0 +1,43 @@ +--- +'@astrojs/starlight': minor +--- + +Removes Shiki `css-variables` theme fallback. + +⚠️ **Breaking change:** + +Previously, Starlight used to automatically provide a fallback theme for Shiki, the default syntax highlighter built into Astro if the configured Shiki theme was not `github-dark`. + +This fallback was only relevant when the default Starlight code block renderer, Expressive Code, was disabled and Shiki was used. Starlight no longer provides this fallback. + +If you were relying on this behavior, you now manually need to update your Astro configuration to use the Shiki `css-variables` theme to match the previous behavior. + +```diff +import { defineConfig } from 'astro/config'; + +export default defineConfig({ ++ markdown: { ++ shikiConfig: { ++ theme: 'css-variables', ++ }, ++ }, +}); +``` + +Additionally, you can use [custom CSS](https://starlight.astro.build/guides/css-and-tailwind/#custom-css-styles) to control the appearance of the code blocks. Here is the previously used CSS variables for the fallback theme: + +```css +:root { + --astro-code-foreground: var(--sl-color-white); + --astro-code-background: var(--sl-color-gray-6); + --astro-code-token-constant: var(--sl-color-blue-high); + --astro-code-token-string: var(--sl-color-green-high); + --astro-code-token-comment: var(--sl-color-gray-2); + --astro-code-token-keyword: var(--sl-color-purple-high); + --astro-code-token-parameter: var(--sl-color-red-high); + --astro-code-token-function: var(--sl-color-red-high); + --astro-code-token-string-expression: var(--sl-color-green-high); + --astro-code-token-punctuation: var(--sl-color-gray-2); + --astro-code-token-link: var(--sl-color-blue-high); +} +``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2d98b28efef..792dd47caa2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -275,7 +275,7 @@ To add a language, you will need its BCP-47 tag and a label. See [“Adding a ne - Components that require client-side JavaScript or CSS should use JavaScript/CSS features that are well-supported by browsers. - You can find a list of supported browsers and their versions using this [browserslist query](https://browsersl.ist/#q=%3E+0.5%25%2C+not+dead%2C+Chrome+%3E%3D+88%2C+Edge+%3E%3D+88%2C+Firefox+%3E%3D+98%2C+Safari+%3E%3D+15.4%2C+iOS+%3E%3D+15.4%2C+not+op_mini+all). To check whether or not a feature is supported, you can visit the [Can I use](https://caniuse.com) website and search for the feature. + You can find a list of supported browsers and their versions using this [browserslist query](https://browsersl.ist/#q=%3E+0.5%25%2C+not+dead%2C+Chrome+%3E%3D+99%2C+Edge+%3E%3D+99%2C+Firefox+%3E%3D+98%2C+Safari+%3E%3D+15.4%2C+iOS+%3E%3D+15.4%2C+not+op_mini+all). To check whether or not a feature is supported, you can visit the [Can I use](https://caniuse.com) website and search for the feature. [discord]: https://astro.build/chat [issues]: https://github.com/withastro/starlight/issues diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 9906df38447..9b1b16c35f9 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -31,6 +31,8 @@ const ogUrl = new URL('og.jpg?v=1', site).href; const ogImageAlt = 'Make your docs shine with Starlight'; export default defineConfig({ + // TODO(HiDeoo) Remove this, only used to avoid screenshoting the dev toolbar. + devToolbar: { enabled: false }, site, trailingSlash: 'always', integrations: [ diff --git a/docs/src/components/theme-designer.astro b/docs/src/components/theme-designer.astro index 286b2075b46..b706121860c 100644 --- a/docs/src/components/theme-designer.astro +++ b/docs/src/components/theme-designer.astro @@ -115,22 +115,28 @@ const { } #updateTailwindConfig({ dark, light }: ReturnType) { - const config = `import starlightPlugin from '@astrojs/starlight-tailwind'; - -// Generated color palettes -const accent = { 200: '${dark['accent-high']}', 600: '${light.accent}', 900: '${light['accent-high']}', 950: '${dark['accent-low']}' }; -const gray = { 100: '${light['gray-7']}', 200: '${light['gray-6']}', 300: '${light['gray-5']}', 400: '${light['gray-4']}', 500: '${light['gray-3']}', 700: '${light['gray-2']}', 800: '${light['gray-1']}', 900: '${light.white}' }; - -/** @type {import('tailwindcss').Config} */ -export default { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { accent, gray }, - }, - }, - plugins: [starlightPlugin()], -};`; + const config = `@layer starlight.base, starlight.reset, starlight.components, starlight.content, starlight.user-components, starlight.asides, starlight.expressive-code, starlight.utils, theme, base, components, utilities; + +@import '@astrojs/starlight-tailwind'; +@import 'tailwindcss/theme.css' layer(theme); +@import 'tailwindcss/utilities.css' layer(utilities); + +@theme { + /* Generated accent color palettes. */ + --color-accent-200: ${dark['accent-high']}; + --color-accent-600: ${light.accent}; + --color-accent-900: ${light['accent-high']}; + --color-accent-950: ${dark['accent-low']}; + /* Generated gray color palettes. */ + --color-gray-100: ${light['gray-7']}; + --color-gray-200: ${light['gray-6']}; + --color-gray-300: ${light['gray-5']}; + --color-gray-400: ${light['gray-4']}; + --color-gray-500: ${light['gray-3']}; + --color-gray-700: ${light['gray-2']}; + --color-gray-800: ${light['gray-1']}; + --color-gray-900: ${light.white}; +}`; const codePreview = this.querySelector('[data-theme-tailwind]'); if (codePreview) codePreview.innerHTML = config; } diff --git a/docs/src/content/docs/guides/css-and-tailwind.mdx b/docs/src/content/docs/guides/css-and-tailwind.mdx index 405b8e27c34..bb71a620647 100644 --- a/docs/src/content/docs/guides/css-and-tailwind.mdx +++ b/docs/src/content/docs/guides/css-and-tailwind.mdx @@ -48,16 +48,32 @@ Customize the styles applied to your Starlight site by providing additional CSS You can see all the CSS custom properties used by Starlight that you can set to customize your site in the [`props.css` file on GitHub](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css). +Starlight uses [cascade layers](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers) internally so that any custom unlayered CSS will override the default styles. +If you are using cascade layers in your custom CSS, you can use the [`@layer`](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) CSS at-rule to define the order of precedence for different layers including the ones used by Starlight: + +```css /(my-(?:reset|layer))/ +@layer starlight.base, + my-reset, + starlight.reset, + starlight.components, + starlight.content, + starlight.user-components, + starlight.asides, + starlight.expressive-code, + starlight.utils, + my-layer; +``` + ## Tailwind CSS -Tailwind CSS support in Astro projects is provided by the [Astro Tailwind integration](https://docs.astro.build/en/guides/integrations-guide/tailwind/). -Starlight provides a complementary Tailwind plugin to help configure Tailwind for compatibility with Starlight’s styles. +Tailwind CSS support in Astro projects is provided by the [Tailwind Vite plugin](https://tailwindcss.com/docs/installation/using-vite). +Starlight provides complementary CSS to help configure Tailwind for compatibility with Starlight’s styles. -The Starlight Tailwind plugin applies the following configuration: +The Starlight Tailwind CSS applies the following configuration: - Configures Tailwind’s `dark:` variants to work with Starlight’s dark mode. - Uses Tailwind [theme colors and fonts](#styling-starlight-with-tailwind) in Starlight’s UI. -- Disables Tailwind’s [Preflight](https://tailwindcss.com/docs/preflight) reset styles while selectively restoring essential parts of Preflight required for Tailwind’s border utility classes. +- Restore essential parts of Preflight. ### Create a new project with Tailwind @@ -93,7 +109,7 @@ If you already have a Starlight site and want to add Tailwind CSS, follow these -1. Add Astro’s Tailwind integration: +1. Add Tailwind Vite plugin: @@ -123,7 +139,7 @@ If you already have a Starlight site and want to add Tailwind CSS, follow these -2. Install the Starlight Tailwind plugin: +2. Install the Starlight Tailwind CSS: @@ -153,22 +169,51 @@ If you already have a Starlight site and want to add Tailwind CSS, follow these -3. Create a CSS file for Tailwind’s base styles, for example at `src/tailwind.css`: +3. Create a CSS file for Tailwind’s base styles, for example at `src/tailwind.css`, including Starlight Tailwind CSS: - ```css + ```css {4} /* src/tailwind.css */ - @tailwind base; - @tailwind components; - @tailwind utilities; + @layer starlight.base, starlight.reset, starlight.components, starlight.content, starlight.user-components, starlight.asides, starlight.expressive-code, starlight.utils, theme, base, components, utilities; + + @import '@astrojs/starlight-tailwind'; + @import 'tailwindcss/theme.css' layer(theme); + @import 'tailwindcss/utilities.css' layer(utilities); + + @theme { + /* Your preferred accent color. Indigo is closest to Starlight’s defaults. */ + --color-accent-50: var(--color-indigo-50); + --color-accent-100: var(--color-indigo-100); + --color-accent-200: var(--color-indigo-200); + --color-accent-300: var(--color-indigo-300); + --color-accent-400: var(--color-indigo-400); + --color-accent-500: var(--color-indigo-500); + --color-accent-600: var(--color-indigo-600); + --color-accent-700: var(--color-indigo-700); + --color-accent-800: var(--color-indigo-800); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + /* Your preferred gray scale. Zinc is closest to Starlight’s defaults. */ + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); + } ``` 4. Update your Astro config file to use your Tailwind base styles and disable the default base styles: - ```js {11-12,16-17} + ```js {11-12} // astro.config.mjs import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; - import tailwind from '@astrojs/tailwind'; + import tailwindcss from '@tailwindcss/vite'; export default defineConfig({ integrations: [ @@ -179,66 +224,62 @@ If you already have a Starlight site and want to add Tailwind CSS, follow these './src/tailwind.css', ], }), - tailwind({ - // Disable the default base styles: - applyBaseStyles: false, - }), ], + vite: { plugins: [tailwindcss()] }, }); ``` -5. Add the Starlight Tailwind plugin to `tailwind.config.mjs`: - - ```js ins={2,7} - // tailwind.config.mjs - import starlightPlugin from '@astrojs/starlight-tailwind'; - - /** @type {import('tailwindcss').Config} */ - export default { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - plugins: [starlightPlugin()], - }; - ``` - ### Styling Starlight with Tailwind Starlight will use values from your [Tailwind theme config](https://tailwindcss.com/docs/theme) in its UI. -If set, the following options will override Starlight’s default styles: - -- `colors.accent` — used for links and current item highlighting -- `colors.gray` — used for background colors and borders -- `fontFamily.sans` — used for UI and content text -- `fontFamily.mono` — used for code examples - -```js {12,14,18,20} -// tailwind.config.mjs -import starlightPlugin from '@astrojs/starlight-tailwind'; -import colors from 'tailwindcss/colors'; - -/** @type {import('tailwindcss').Config} */ -export default { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { - // Your preferred accent color. Indigo is closest to Starlight’s defaults. - accent: colors.indigo, - // Your preferred gray scale. Zinc is closest to Starlight’s defaults. - gray: colors.zinc, - }, - fontFamily: { - // Your preferred text font. Starlight uses a system font stack by default. - sans: ['"Atkinson Hyperlegible"'], - // Your preferred code font. Starlight uses system monospace fonts by default. - mono: ['"IBM Plex Mono"'], - }, - }, - }, - plugins: [starlightPlugin()], -}; +If set, the following CSS custom properties will override Starlight’s default styles: + +- `--color-accent-*` — used for links and current item highlighting +- `--color-gray-*` — used for background colors and borders +- `--sl-font` — used for UI and content text +- `--sl-font-mono` — used for code examples + +```css {10-20,22-32,34,36} +/* src/tailwind.css */ +@layer starlight.base, starlight.reset, starlight.components, starlight.content, starlight.user-components, starlight.asides, starlight.expressive-code, starlight.utils, theme, base, components, utilities; + +@import '@astrojs/starlight-tailwind'; +@import 'tailwindcss/theme.css' layer(theme); +@import 'tailwindcss/utilities.css' layer(utilities); + +@theme { + /* Your preferred accent color. Indigo is closest to Starlight’s defaults. */ + --color-accent-50: var(--color-indigo-50); + --color-accent-100: var(--color-indigo-100); + --color-accent-200: var(--color-indigo-200); + --color-accent-300: var(--color-indigo-300); + --color-accent-400: var(--color-indigo-400); + --color-accent-500: var(--color-indigo-500); + --color-accent-600: var(--color-indigo-600); + --color-accent-700: var(--color-indigo-700); + --color-accent-800: var(--color-indigo-800); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + /* Your preferred gray scale. Zinc is closest to Starlight’s defaults. */ + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); + /* Your preferred text font. Starlight uses a system font stack by default. */ + --sl-font: 'Atkinson Hyperlegible'; + /* Your preferred code font. Starlight uses system monospace fonts by default. */ + --sl-font-mono: 'IBM Plex Mono'; +} ``` ## Theming @@ -294,8 +335,8 @@ import ThemeDesigner from '~/components/theme-designer.astro'; file](#custom-css-styles) to apply this theme to your site. - The example [Tailwind config file](#styling-starlight-with-tailwind) below - includes generated `accent` and `gray` color palettes to use in the - `theme.extend.colors` configuration object. + The example [Tailwind theme config](#styling-starlight-with-tailwind) below + includes generated `accent` and `gray` color palettes to use in the `@theme` + configuration directive. diff --git a/examples/tailwind/astro.config.mjs b/examples/tailwind/astro.config.mjs index a3a3ba5ee08..d7f39746501 100644 --- a/examples/tailwind/astro.config.mjs +++ b/examples/tailwind/astro.config.mjs @@ -1,7 +1,7 @@ // @ts-check import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; -import tailwind from '@astrojs/tailwind'; +import tailwindcss from '@tailwindcss/vite'; // https://astro.build/config export default defineConfig({ @@ -26,6 +26,8 @@ export default defineConfig({ ], customCss: ['./src/tailwind.css'], }), - tailwind({ applyBaseStyles: false }), ], + vite: { + plugins: [tailwindcss()], + }, }); diff --git a/examples/tailwind/package.json b/examples/tailwind/package.json index 1f483462d9b..d9498ca1bca 100644 --- a/examples/tailwind/package.json +++ b/examples/tailwind/package.json @@ -13,9 +13,9 @@ "dependencies": { "@astrojs/starlight": "^0.32.0", "@astrojs/starlight-tailwind": "^3.0.0", - "@astrojs/tailwind": "^5.1.4", + "@tailwindcss/vite": "^4.0.7", "astro": "^5.1.5", "sharp": "^0.32.5", - "tailwindcss": "^3.4.4" + "tailwindcss": "^4.0.7" } } diff --git a/examples/tailwind/src/tailwind.css b/examples/tailwind/src/tailwind.css index 26664bc8816..583f05f12a6 100644 --- a/examples/tailwind/src/tailwind.css +++ b/examples/tailwind/src/tailwind.css @@ -1,8 +1,37 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@layer starlight.base, starlight.reset, starlight.components, starlight.content, starlight.user-components, starlight.asides, starlight.expressive-code, starlight.utils, theme, base, components, utilities; + +@import '@astrojs/starlight-tailwind'; +@import 'tailwindcss/theme.css' layer(theme); +@import 'tailwindcss/utilities.css' layer(utilities); + +@theme { + /* Your preferred accent color. Indigo is closest to Starlight’s defaults. */ + --color-accent-50: var(--color-indigo-50); + --color-accent-100: var(--color-indigo-100); + --color-accent-200: var(--color-indigo-200); + --color-accent-300: var(--color-indigo-300); + --color-accent-400: var(--color-indigo-400); + --color-accent-500: var(--color-indigo-500); + --color-accent-600: var(--color-indigo-600); + --color-accent-700: var(--color-indigo-700); + --color-accent-800: var(--color-indigo-800); + --color-accent-900: var(--color-indigo-900); + --color-accent-950: var(--color-indigo-950); + /* Your preferred gray scale. Zinc is closest to Starlight’s defaults. */ + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); +} /* -Add additional Tailwind styles to this file, for example with @layer: -https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer +Add additional Tailwind styles to this file: +https://tailwindcss.com/docs/adding-custom-styles#using-custom-css */ diff --git a/examples/tailwind/tailwind.config.mjs b/examples/tailwind/tailwind.config.mjs deleted file mode 100644 index 623ce3a9247..00000000000 --- a/examples/tailwind/tailwind.config.mjs +++ /dev/null @@ -1,18 +0,0 @@ -import colors from 'tailwindcss/colors'; -import starlightPlugin from '@astrojs/starlight-tailwind'; - -/** @type {import('tailwindcss').Config} */ -export default { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: { - colors: { - // Your preferred accent color. Indigo is closest to Starlight’s defaults. - accent: colors.indigo, - // Your preferred gray scale. Zinc is closest to Starlight’s defaults. - gray: colors.zinc, - }, - }, - }, - plugins: [starlightPlugin()], -}; diff --git a/packages/local-prod-visual-diff/.gitignore b/packages/local-prod-visual-diff/.gitignore new file mode 100644 index 00000000000..750e145aa20 --- /dev/null +++ b/packages/local-prod-visual-diff/.gitignore @@ -0,0 +1 @@ +screenshots/ diff --git a/packages/local-prod-visual-diff/diff.setup.ts b/packages/local-prod-visual-diff/diff.setup.ts new file mode 100644 index 00000000000..2d57c072c2c --- /dev/null +++ b/packages/local-prod-visual-diff/diff.setup.ts @@ -0,0 +1,9 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; + +// Delete the dev and diff screenshots directories before running the tests. +await fs.rm(path.join('screenshots', 'dev'), { force: true, recursive: true }); +await fs.rm(path.join('screenshots', 'diff'), { force: true, recursive: true }); + +// Ensure the diff screenshots directory exists. +await fs.mkdir(path.join('screenshots', 'diff'), { recursive: true }); diff --git a/packages/local-prod-visual-diff/diff.test.ts b/packages/local-prod-visual-diff/diff.test.ts new file mode 100644 index 00000000000..171e9b432c9 --- /dev/null +++ b/packages/local-prod-visual-diff/diff.test.ts @@ -0,0 +1,167 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { expect, test, type Page } from '@playwright/test'; +import pixelmatch from 'pixelmatch'; +import { PNG } from 'pngjs'; + +const prodUrl = new URL('https://starlight.astro.build'); + +// A list of all the routes to visually compare between the production and development environments. +// This could be based on the sitemap but it was not worth the effort for this PR. +const routePaths = [ + '/', + '/getting-started/', + '/manual-setup/', + '/environmental-impact/', + '/guides/pages/', + '/guides/authoring-content/', + // Temporarily disabled as this page is edited to add content in this PR. + // '/guides/css-and-tailwind/', + '/guides/customization/', + '/guides/i18n/', + '/guides/overriding-components/', + '/guides/sidebar/', + '/guides/site-search/', + '/components/using-components/', + '/components/cards/', + '/components/link-cards/', + '/components/card-grids/', + '/components/asides/', + '/components/badges/', + '/components/code/', + '/components/file-tree/', + '/components/icons/', + '/components/link-buttons/', + '/components/steps/', + '/components/tabs/', + '/reference/configuration/', + '/resources/plugins/', + '/resources/community-content/', + '/resources/showcase/', +]; + +// The maximum number of mismatched pixels between the production and development screenshots. +const maxDiffPixels = 10; + +for (const routePath of routePaths) { + test.only(`CSS Layers: ${routePath}`, async ({ page }) => { + const prodScreenshotPath = getScreenshotPath(routePath, 'prod'); + + // Take a screenshot of the production route if it doesn't exist. + if (!(await exists(prodScreenshotPath))) { + await page.goto(new URL(routePath, prodUrl).toString()); + await takeScreenshot(page, prodScreenshotPath); + } + + const devScreenshotPath = getScreenshotPath(routePath, 'dev'); + + // Take a screenshot of the development route. + await page.goto(routePath); + await takeScreenshot(page, devScreenshotPath); + + // Compare the screenshots between the production and development routes. + const { diffPixels, diffImage } = await compareScreenshots( + prodScreenshotPath, + devScreenshotPath + ); + + // Save the diff image if the number of mismatched pixels is greater than the maximum allowed. + if (diffPixels >= maxDiffPixels) { + // @ts-expect-error - let me write my file, I don't want to update `@types/node` for this. + await fs.writeFile(getScreenshotPath(routePath, 'diff'), PNG.sync.write(diffImage)); + } + + // Assert the number of mismatched pixels is less than the maximum allowed. + expect(diffPixels).toBeLessThan(maxDiffPixels); + }); +} + +async function compareScreenshots(screenshotPath1: string, screenshotPath2: string) { + let screenshot1: PNG = await getScreenshot(screenshotPath1); + let screenshot2: PNG = await getScreenshot(screenshotPath2); + + let diffSize: ScreenshotSize; + + // If the screenshots have different dimensions, resize them to the largest dimensions so we can + // see where the differences start to appear. + if (screenshot1.width !== screenshot2.width || screenshot1.height !== screenshot2.height) { + diffSize = { + width: Math.max(screenshot1.width, screenshot2.width), + height: Math.max(screenshot1.height, screenshot2.height), + }; + + screenshot1 = resizeScreenshot(screenshot1, diffSize); + screenshot2 = resizeScreenshot(screenshot2, diffSize); + } else { + diffSize = { width: screenshot1.width, height: screenshot1.height }; + } + + const diffImage = new PNG(diffSize); + + const diffPixels = pixelmatch( + screenshot1.data, + screenshot2.data, + diffImage.data, + diffSize.width, + diffSize.height, + { threshold: 0.2 } + ); + + return { diffPixels, diffImage }; +} + +function resizeScreenshot(screenshot: PNG, size: ScreenshotSize) { + const resized = new PNG(size); + PNG.bitblt(screenshot, resized, 0, 0, screenshot.width, screenshot.height); + return resized; +} + +async function getScreenshot(screenshotPath: string) { + const data = await fs.readFile(screenshotPath); + return PNG.sync.read(data); +} + +async function takeScreenshot(page: Page, screenshotPath: string) { + // Ensure all images are loaded before taking the screenshot. + for (const lazyImage of await page.locator('img[loading="lazy"]:visible').all()) { + await lazyImage.scrollIntoViewIfNeeded(); + } + + const overviewLink = page.getByRole('link', { name: 'Overview', exact: true }); + + // Scroll to the top of the page to ensure the screenshot is consistent. + if (await overviewLink.isVisible()) { + // Use the Overview link when possible to avoid mismatched pixels due to ToC highlighting. + overviewLink.click(); + } else { + await page.evaluate(() => window.scrollTo(0, 0)); + } + await page.waitForTimeout(500); + + await page.screenshot({ path: screenshotPath, fullPage: true }); +} + +function getScreenshotPath(routePath: string, type: ScreenshotType) { + return path.join( + 'screenshots', + type, + routePath.replace(/\//g, '-').replace(/^-/, '').replace(/-$/, '').replace(/^$/, 'index') + + '.png' + ); +} + +async function exists(filePath: string) { + try { + await fs.access(filePath, fs.constants.F_OK); + return true; + } catch { + return false; + } +} + +type ScreenshotType = 'dev' | 'prod' | 'diff'; + +interface ScreenshotSize { + width: number; + height: number; +} diff --git a/packages/local-prod-visual-diff/package.json b/packages/local-prod-visual-diff/package.json new file mode 100644 index 00000000000..cdaa53bc2bd --- /dev/null +++ b/packages/local-prod-visual-diff/package.json @@ -0,0 +1,18 @@ +{ + "name": "starlight-local-prod-visual-diff", + "version": "0.1.0", + "description": "Visual diffing between local and production builds of Starlight", + "private": true, + "scripts": { + "test": "playwright install --with-deps chromium && playwright test" + }, + "license": "MIT", + "dependencies": { + "@playwright/test": "^1.45.0", + "@types/pixelmatch": "^5.2.6", + "@types/pngjs": "^6.0.5", + "pixelmatch": "^6.0.0", + "pngjs": "^7.0.0" + }, + "type": "module" +} diff --git a/packages/local-prod-visual-diff/playwright.config.ts b/packages/local-prod-visual-diff/playwright.config.ts new file mode 100644 index 00000000000..27fb0e622d7 --- /dev/null +++ b/packages/local-prod-visual-diff/playwright.config.ts @@ -0,0 +1,34 @@ +import { defineConfig, devices } from '@playwright/test'; + +const baseURL = 'http://localhost:4321'; + +export default defineConfig({ + forbidOnly: !!process.env['CI'], + projects: [ + { + name: 'setup diff', + testMatch: /diff\.setup\.ts/, + }, + { + name: 'Chrome Stable', + use: { + ...devices['Desktop Chrome'], + headless: true, + }, + dependencies: ['setup diff'], + }, + ], + testMatch: '*.test.ts', + use: { + baseURL, + }, + webServer: [ + { + command: 'pnpm run dev', + // command: 'pnpm run build && pnpm run preview', + cwd: '../../docs', + reuseExistingServer: !process.env['CI'], + url: baseURL, + }, + ], +}); diff --git a/packages/starlight/components/Banner.astro b/packages/starlight/components/Banner.astro index 40c2122e0f5..244c672bdbf 100644 --- a/packages/starlight/components/Banner.astro +++ b/packages/starlight/components/Banner.astro @@ -5,17 +5,19 @@ const { banner } = Astro.locals.starlightRoute.entry.data; {banner &&
} diff --git a/packages/starlight/components/ContentNotice.astro b/packages/starlight/components/ContentNotice.astro index fcf4ac3dbcc..c6a599b63b5 100644 --- a/packages/starlight/components/ContentNotice.astro +++ b/packages/starlight/components/ContentNotice.astro @@ -16,16 +16,18 @@ const { icon, label } = Astro.props;

diff --git a/packages/starlight/components/ContentPanel.astro b/packages/starlight/components/ContentPanel.astro index d4089408f55..70ff87408f7 100644 --- a/packages/starlight/components/ContentPanel.astro +++ b/packages/starlight/components/ContentPanel.astro @@ -3,23 +3,25 @@
diff --git a/packages/starlight/components/EditLink.astro b/packages/starlight/components/EditLink.astro index 024f38b7665..9fe6b93bfd2 100644 --- a/packages/starlight/components/EditLink.astro +++ b/packages/starlight/components/EditLink.astro @@ -14,13 +14,15 @@ const { editUrl } = Astro.locals.starlightRoute; } diff --git a/packages/starlight/components/Footer.astro b/packages/starlight/components/Footer.astro index 4c88eae552f..dd4080c625e 100644 --- a/packages/starlight/components/Footer.astro +++ b/packages/starlight/components/Footer.astro @@ -23,34 +23,36 @@ import { Icon } from '../components'; diff --git a/packages/starlight/components/Header.astro b/packages/starlight/components/Header.astro index cb7f6501614..e5f39e5d43f 100644 --- a/packages/starlight/components/Header.astro +++ b/packages/starlight/components/Header.astro @@ -14,7 +14,7 @@ const shouldRenderSearch = config.pagefind || config.components.Search !== '@astrojs/starlight/components/Search.astro'; --- -
+
@@ -31,61 +31,64 @@ const shouldRenderSearch =
diff --git a/packages/starlight/components/Hero.astro b/packages/starlight/components/Hero.astro index 4e3d42d98cd..e11ee53ef94 100644 --- a/packages/starlight/components/Hero.astro +++ b/packages/starlight/components/Hero.astro @@ -64,78 +64,80 @@ if (image) {
diff --git a/packages/starlight/components/MobileMenuFooter.astro b/packages/starlight/components/MobileMenuFooter.astro index d74b71e7219..3d4d0a67e20 100644 --- a/packages/starlight/components/MobileMenuFooter.astro +++ b/packages/starlight/components/MobileMenuFooter.astro @@ -5,7 +5,7 @@ import ThemeSelect from 'virtual:starlight/components/ThemeSelect'; ---
- diff --git a/packages/starlight/components/MobileMenuToggle.astro b/packages/starlight/components/MobileMenuToggle.astro index 6e65710b424..fed3ec6ce0d 100644 --- a/packages/starlight/components/MobileMenuToggle.astro +++ b/packages/starlight/components/MobileMenuToggle.astro @@ -50,45 +50,49 @@ import Icon from '../user-components/Icon.astro'; diff --git a/packages/starlight/components/MobileTableOfContents.astro b/packages/starlight/components/MobileTableOfContents.astro index d724eaf8c3b..67bf53b4b3d 100644 --- a/packages/starlight/components/MobileTableOfContents.astro +++ b/packages/starlight/components/MobileTableOfContents.astro @@ -27,82 +27,84 @@ const { toc } = Astro.locals.starlightRoute; } diff --git a/packages/starlight/components/Page.astro b/packages/starlight/components/Page.astro index caebe091c56..0076e4b8a40 100644 --- a/packages/starlight/components/Page.astro +++ b/packages/starlight/components/Page.astro @@ -1,11 +1,16 @@ --- +// Important that this is the first import so it can override cascade layers order. +import 'virtual:starlight/user-css'; + +// Starlight nested cascade layers definitions which specify the default order of internal layers. +import '../style/layers.css'; + // Built-in CSS styles. import '../style/props.css'; import '../style/reset.css'; -import '../style/shiki.css'; +import '../style/asides.css'; import '../style/util.css'; -// Components — can override built-in CSS, but not user CSS. import Banner from 'virtual:starlight/components/Banner'; import ContentPanel from 'virtual:starlight/components/ContentPanel'; import FallbackContentNotice from 'virtual:starlight/components/FallbackContentNotice'; @@ -23,12 +28,6 @@ import SkipLink from 'virtual:starlight/components/SkipLink'; import ThemeProvider from 'virtual:starlight/components/ThemeProvider'; import TwoColumnContent from 'virtual:starlight/components/TwoColumnContent'; -// Remark component CSS (needs to override `MarkdownContent.astro`) -import '../style/asides.css'; - -// Important that this is the last import so it can override built-in styles. -import 'virtual:starlight/user-css'; - import printHref from '../style/print.css?url&no-inline'; const { starlightRoute } = Astro.locals; diff --git a/packages/starlight/components/PageFrame.astro b/packages/starlight/components/PageFrame.astro index 7c76228ad54..585acc2dd67 100644 --- a/packages/starlight/components/PageFrame.astro +++ b/packages/starlight/components/PageFrame.astro @@ -22,72 +22,76 @@ const { hasSidebar } = Astro.locals.starlightRoute;
diff --git a/packages/starlight/components/PageSidebar.astro b/packages/starlight/components/PageSidebar.astro index b87e470295e..60a53548f7f 100644 --- a/packages/starlight/components/PageSidebar.astro +++ b/packages/starlight/components/PageSidebar.astro @@ -19,39 +19,41 @@ import TableOfContents from 'virtual:starlight/components/TableOfContents'; } diff --git a/packages/starlight/components/PageTitle.astro b/packages/starlight/components/PageTitle.astro index 8d9da54a90d..4f1ee9604a6 100644 --- a/packages/starlight/components/PageTitle.astro +++ b/packages/starlight/components/PageTitle.astro @@ -5,11 +5,13 @@ import { PAGE_TITLE_ID } from '../constants';

{Astro.locals.starlightRoute.entry.data.title}

diff --git a/packages/starlight/components/Pagination.astro b/packages/starlight/components/Pagination.astro index d5723ab4134..7c2b4212e67 100644 --- a/packages/starlight/components/Pagination.astro +++ b/packages/starlight/components/Pagination.astro @@ -34,44 +34,46 @@ const isRtl = dir === 'rtl'; diff --git a/packages/starlight/components/Search.astro b/packages/starlight/components/Search.astro index 6ce176bbe27..9412dcf2109 100644 --- a/packages/starlight/components/Search.astro +++ b/packages/starlight/components/Search.astro @@ -163,321 +163,325 @@ if (project.trailingSlash === 'never') dataAttributes['data-strip-trailing-slash diff --git a/packages/starlight/components/Select.astro b/packages/starlight/components/Select.astro index 50925b1a9cd..7866c15213c 100644 --- a/packages/starlight/components/Select.astro +++ b/packages/starlight/components/Select.astro @@ -37,60 +37,64 @@ interface Props { diff --git a/packages/starlight/components/SidebarPersister.astro b/packages/starlight/components/SidebarPersister.astro index d83b02c0cdd..512da17399c 100644 --- a/packages/starlight/components/SidebarPersister.astro +++ b/packages/starlight/components/SidebarPersister.astro @@ -70,7 +70,9 @@ declare global { diff --git a/packages/starlight/components/SidebarSublist.astro b/packages/starlight/components/SidebarSublist.astro index a11898c71cc..c51300549cb 100644 --- a/packages/starlight/components/SidebarSublist.astro +++ b/packages/starlight/components/SidebarSublist.astro @@ -60,93 +60,95 @@ const { sublist, nested } = Astro.props; diff --git a/packages/starlight/components/SiteTitle.astro b/packages/starlight/components/SiteTitle.astro index fd2fa0311b1..9ce869b5069 100644 --- a/packages/starlight/components/SiteTitle.astro +++ b/packages/starlight/components/SiteTitle.astro @@ -34,20 +34,22 @@ const { siteTitle, siteTitleHref } = Astro.locals.starlightRoute; diff --git a/packages/starlight/components/SkipLink.astro b/packages/starlight/components/SkipLink.astro index 213c7bf2f84..569d3411b8d 100644 --- a/packages/starlight/components/SkipLink.astro +++ b/packages/starlight/components/SkipLink.astro @@ -5,20 +5,22 @@ import { PAGE_TITLE_ID } from '../constants'; {Astro.locals.t('skipLink.label')} diff --git a/packages/starlight/components/SocialIcons.astro b/packages/starlight/components/SocialIcons.astro index ad9056ff05c..33c5e3978eb 100644 --- a/packages/starlight/components/SocialIcons.astro +++ b/packages/starlight/components/SocialIcons.astro @@ -21,12 +21,14 @@ const links = Object.entries(config.social || {}) as [Platform, SocialConfig][]; } diff --git a/packages/starlight/components/TableOfContents/TableOfContentsList.astro b/packages/starlight/components/TableOfContents/TableOfContentsList.astro index 8ea9eb84280..21f37c9e689 100644 --- a/packages/starlight/components/TableOfContents/TableOfContentsList.astro +++ b/packages/starlight/components/TableOfContents/TableOfContentsList.astro @@ -26,52 +26,54 @@ const { toc, isMobile = false, depth = 0 } = Astro.props; diff --git a/packages/starlight/components/TwoColumnContent.astro b/packages/starlight/components/TwoColumnContent.astro index 2b229a50d9e..8c57d39e145 100644 --- a/packages/starlight/components/TwoColumnContent.astro +++ b/packages/starlight/components/TwoColumnContent.astro @@ -12,41 +12,43 @@ diff --git a/packages/starlight/index.ts b/packages/starlight/index.ts index 9e463bdf648..fb80b2a5528 100644 --- a/packages/starlight/index.ts +++ b/packages/starlight/index.ts @@ -128,9 +128,6 @@ export default function StarlightIntegration( }), ], rehypePlugins: [rehypeRtlCodeSupport()], - shikiConfig: - // Configure Shiki theme if the user is using the default github-dark theme. - config.markdown.shikiConfig.theme !== 'github-dark' ? {} : { theme: 'css-variables' }, }, scopedStyleStrategy: 'where', // If not already configured, default to prefetching all links on hover. diff --git a/packages/starlight/integrations/expressive-code/index.ts b/packages/starlight/integrations/expressive-code/index.ts index 146d315b5fd..b087f2f887d 100644 --- a/packages/starlight/integrations/expressive-code/index.ts +++ b/packages/starlight/integrations/expressive-code/index.ts @@ -81,6 +81,7 @@ export function getStarlightEcConfigPreprocessor({ const { themes: themesInput, + cascadeLayer, customizeTheme, styleOverrides: { textMarkers: textMarkersStyleOverrides, ...otherStyleOverrides } = {}, useStarlightDarkModeSwitch, @@ -136,6 +137,7 @@ export function getStarlightEcConfigPreprocessor({ // Return the default selector return `[data-theme='${theme.name}']`; }, + cascadeLayer: cascadeLayer ?? 'starlight.expressive-code', styleOverrides: { borderRadius: '0px', borderWidth: '1px', diff --git a/packages/starlight/style/asides.css b/packages/starlight/style/asides.css index adbb0558f48..10459cf46ee 100644 --- a/packages/starlight/style/asides.css +++ b/packages/starlight/style/asides.css @@ -1,49 +1,51 @@ -.starlight-aside { - padding: 1rem; - border-inline-start: 0.25rem solid var(--sl-color-asides-border); - color: var(--sl-color-white); -} -.starlight-aside--note { - --sl-color-asides-text-accent: var(--sl-color-blue-high); - --sl-color-asides-border: var(--sl-color-blue); - background-color: var(--sl-color-blue-low); -} -.starlight-aside--tip { - --sl-color-asides-text-accent: var(--sl-color-purple-high); - --sl-color-asides-border: var(--sl-color-purple); - background-color: var(--sl-color-purple-low); -} -.starlight-aside--caution { - --sl-color-asides-text-accent: var(--sl-color-orange-high); - --sl-color-asides-border: var(--sl-color-orange); - background-color: var(--sl-color-orange-low); -} -.starlight-aside--danger { - --sl-color-asides-text-accent: var(--sl-color-red-high); - --sl-color-asides-border: var(--sl-color-red); - background-color: var(--sl-color-red-low); -} +@layer starlight.asides { + .starlight-aside { + padding: 1rem; + border-inline-start: 0.25rem solid var(--sl-color-asides-border); + color: var(--sl-color-white); + } + .starlight-aside--note { + --sl-color-asides-text-accent: var(--sl-color-blue-high); + --sl-color-asides-border: var(--sl-color-blue); + background-color: var(--sl-color-blue-low); + } + .starlight-aside--tip { + --sl-color-asides-text-accent: var(--sl-color-purple-high); + --sl-color-asides-border: var(--sl-color-purple); + background-color: var(--sl-color-purple-low); + } + .starlight-aside--caution { + --sl-color-asides-text-accent: var(--sl-color-orange-high); + --sl-color-asides-border: var(--sl-color-orange); + background-color: var(--sl-color-orange-low); + } + .starlight-aside--danger { + --sl-color-asides-text-accent: var(--sl-color-red-high); + --sl-color-asides-border: var(--sl-color-red); + background-color: var(--sl-color-red-low); + } -.starlight-aside__title { - display: flex; - gap: 0.5rem; - align-items: center; - font-size: var(--sl-text-h5); - font-weight: 600; - line-height: var(--sl-line-height-headings); - color: var(--sl-color-asides-text-accent); -} + .starlight-aside__title { + display: flex; + gap: 0.5rem; + align-items: center; + font-size: var(--sl-text-h5); + font-weight: 600; + line-height: var(--sl-line-height-headings); + color: var(--sl-color-asides-text-accent); + } -.starlight-aside__icon { - font-size: 1.333em; - width: 1em; - height: 1em; -} + .starlight-aside__icon { + font-size: 1.333em; + width: 1em; + height: 1em; + } -.starlight-aside__title + .starlight-aside__content { - margin-top: 0.5rem; -} + .starlight-aside__title + .starlight-aside__content { + margin-top: 0.5rem; + } -.starlight-aside__content a { - color: var(--sl-color-asides-text-accent); + .starlight-aside__content a { + color: var(--sl-color-asides-text-accent); + } } diff --git a/packages/starlight/style/layers.css b/packages/starlight/style/layers.css new file mode 100644 index 00000000000..b4bbf7d037d --- /dev/null +++ b/packages/starlight/style/layers.css @@ -0,0 +1 @@ +@layer starlight.base, starlight.reset, starlight.components, starlight.content, starlight.user-components, starlight.asides, starlight.expressive-code, starlight.utils; diff --git a/packages/starlight/style/markdown.css b/packages/starlight/style/markdown.css index 2fe23920bb5..b6084a0d164 100644 --- a/packages/starlight/style/markdown.css +++ b/packages/starlight/style/markdown.css @@ -1,217 +1,236 @@ -.sl-markdown-content - :not(a, strong, em, del, span, input, code, br) - + :not(a, strong, em, del, span, input, code, br, :where(.not-content *)) { - margin-top: 1rem; -} +@layer starlight.content { + .sl-markdown-content + :not(a, strong, em, del, span, input, code, br) + + :not(a, strong, em, del, span, input, code, br, :where(.not-content *)) { + margin-top: 1rem; + } -/* Headings after non-headings have more spacing. */ -.sl-markdown-content - :not(h1, h2, h3, h4, h5, h6) - + :is(h1, h2, h3, h4, h5, h6):not(:where(.not-content *)) { - margin-top: 1.5em; -} + /* Headings after non-headings have more spacing. */ + .sl-markdown-content + :not(h1, h2, h3, h4, h5, h6) + + :is(h1, h2, h3, h4, h5, h6):not(:where(.not-content *)) { + margin-top: 1.5em; + } -.sl-markdown-content li + li:not(:where(.not-content *)), -.sl-markdown-content dt + dt:not(:where(.not-content *)), -.sl-markdown-content dt + dd:not(:where(.not-content *)), -.sl-markdown-content dd + dd:not(:where(.not-content *)) { - margin-top: 0.25rem; -} + .sl-markdown-content li + li:not(:where(.not-content *)), + .sl-markdown-content dt + dt:not(:where(.not-content *)), + .sl-markdown-content dt + dd:not(:where(.not-content *)), + .sl-markdown-content dd + dd:not(:where(.not-content *)) { + margin-top: 0.25rem; + } -.sl-markdown-content li:not(:where(.not-content *)) { - overflow-wrap: anywhere; -} + .sl-markdown-content li:not(:where(.not-content *)) { + overflow-wrap: anywhere; + } -.sl-markdown-content - li - > :last-child:not(li, ul, ol, a, strong, em, del, span, input, code, br, :where(.not-content *)) { - margin-bottom: 1.25rem; -} + .sl-markdown-content + li + > :last-child:not( + li, + ul, + ol, + a, + strong, + em, + del, + span, + input, + code, + br, + :where(.not-content *) + ) { + margin-bottom: 1.25rem; + } -.sl-markdown-content dt:not(:where(.not-content *)) { - font-weight: 700; -} -.sl-markdown-content dd:not(:where(.not-content *)) { - padding-inline-start: 1rem; -} + .sl-markdown-content dt:not(:where(.not-content *)) { + font-weight: 700; + } + .sl-markdown-content dd:not(:where(.not-content *)) { + padding-inline-start: 1rem; + } -.sl-markdown-content :is(h1, h2, h3, h4, h5, h6):not(:where(.not-content *)) { - color: var(--sl-color-white); - line-height: var(--sl-line-height-headings); - font-weight: 600; -} + .sl-markdown-content :is(h1, h2, h3, h4, h5, h6):not(:where(.not-content *)) { + color: var(--sl-color-white); + line-height: var(--sl-line-height-headings); + font-weight: 600; + } -.sl-markdown-content :is(img, picture, video, canvas, svg, iframe):not(:where(.not-content *)) { - display: block; - max-width: 100%; - height: auto; -} + .sl-markdown-content :is(img, picture, video, canvas, svg, iframe):not(:where(.not-content *)) { + display: block; + max-width: 100%; + height: auto; + } -.sl-markdown-content h1:not(:where(.not-content *)) { - font-size: var(--sl-text-h1); -} -.sl-markdown-content h2:not(:where(.not-content *)) { - font-size: var(--sl-text-h2); -} -.sl-markdown-content h3:not(:where(.not-content *)) { - font-size: var(--sl-text-h3); -} -.sl-markdown-content h4:not(:where(.not-content *)) { - font-size: var(--sl-text-h4); -} -.sl-markdown-content h5:not(:where(.not-content *)) { - font-size: var(--sl-text-h5); -} -.sl-markdown-content h6:not(:where(.not-content *)) { - font-size: var(--sl-text-h6); -} + .sl-markdown-content h1:not(:where(.not-content *)) { + font-size: var(--sl-text-h1); + } + .sl-markdown-content h2:not(:where(.not-content *)) { + font-size: var(--sl-text-h2); + } + .sl-markdown-content h3:not(:where(.not-content *)) { + font-size: var(--sl-text-h3); + } + .sl-markdown-content h4:not(:where(.not-content *)) { + font-size: var(--sl-text-h4); + } + .sl-markdown-content h5:not(:where(.not-content *)) { + font-size: var(--sl-text-h5); + } + .sl-markdown-content h6:not(:where(.not-content *)) { + font-size: var(--sl-text-h6); + } -.sl-markdown-content a:not(:where(.not-content *)) { - color: var(--sl-color-text-accent); -} -.sl-markdown-content a:hover:not(:where(.not-content *)) { - color: var(--sl-color-white); -} + .sl-markdown-content a:not(:where(.not-content *)) { + color: var(--sl-color-text-accent); + } + .sl-markdown-content a:hover:not(:where(.not-content *)) { + color: var(--sl-color-white); + } -.sl-markdown-content code:not(:where(.not-content *)) { - background-color: var(--sl-color-bg-inline-code); - margin-block: -0.125rem; - padding: 0.125rem 0.375rem; - font-size: var(--sl-text-code-sm); -} -.sl-markdown-content :is(h1, h2, h3, h4, h5, h6) code { - font-size: inherit; -} + .sl-markdown-content code:not(:where(.not-content *)) { + background-color: var(--sl-color-bg-inline-code); + margin-block: -0.125rem; + padding: 0.125rem 0.375rem; + font-size: var(--sl-text-code-sm); + } + .sl-markdown-content :is(h1, h2, h3, h4, h5, h6) code { + font-size: inherit; + } -.sl-markdown-content pre:not(:where(.not-content *)) { - border: 1px solid var(--sl-color-gray-5); - padding: 0.75rem 1rem; - font-size: var(--sl-text-code); - tab-size: 2; -} + .sl-markdown-content pre:not(:where(.not-content *)) { + border: 1px solid var(--sl-color-gray-5); + padding: 0.75rem 1rem; + font-size: var(--sl-text-code); + tab-size: 2; + } -.sl-markdown-content pre code:not(:where(.not-content *)) { - all: unset; - font-family: var(--__sl-font-mono); -} + .sl-markdown-content pre code:not(:where(.not-content *)) { + all: unset; + font-family: var(--__sl-font-mono); + } -.sl-markdown-content blockquote:not(:where(.not-content *)) { - border-inline-start: 1px solid var(--sl-color-gray-5); - padding-inline-start: 1rem; -} + .sl-markdown-content blockquote:not(:where(.not-content *)) { + border-inline-start: 1px solid var(--sl-color-gray-5); + padding-inline-start: 1rem; + } -/* Table styling */ -.sl-markdown-content table:not(:where(.not-content *)) { - display: block; - overflow: auto; - border-spacing: 0; -} -.sl-markdown-content :is(th, td):not(:where(.not-content *)) { - border-bottom: 1px solid var(--sl-color-gray-5); - padding: 0.5rem 1rem; - /* Align text to the top of the row in multiline tables. */ - vertical-align: baseline; -} -.sl-markdown-content :is(th:first-child, td:first-child):not(:where(.not-content *)) { - padding-inline-start: 0; -} -.sl-markdown-content :is(th:last-child, td:last-child):not(:where(.not-content *)) { - padding-inline-end: 0; -} -.sl-markdown-content th:not(:where(.not-content *)) { - color: var(--sl-color-white); - font-weight: 600; -} -/* Align headings to the start of the line unless set by the `align` attribute. */ -.sl-markdown-content th:not([align]):not(:where(.not-content *)) { - text-align: start; -} -/* s,
s, and
s inside asides */ -.sl-markdown-content .starlight-aside :is(th, td, hr, blockquote):not(:where(.not-content *)) { - border-color: var(--sl-color-gray-4); -} -@supports (border-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 30%, transparent)) { + /* Table styling */ + .sl-markdown-content table:not(:where(.not-content *)) { + display: block; + overflow: auto; + border-spacing: 0; + } + .sl-markdown-content :is(th, td):not(:where(.not-content *)) { + border-bottom: 1px solid var(--sl-color-gray-5); + padding: 0.5rem 1rem; + /* Align text to the top of the row in multiline tables. */ + vertical-align: baseline; + } + .sl-markdown-content :is(th:first-child, td:first-child):not(:where(.not-content *)) { + padding-inline-start: 0; + } + .sl-markdown-content :is(th:last-child, td:last-child):not(:where(.not-content *)) { + padding-inline-end: 0; + } + .sl-markdown-content th:not(:where(.not-content *)) { + color: var(--sl-color-white); + font-weight: 600; + } + /* Align headings to the start of the line unless set by the `align` attribute. */ + .sl-markdown-content th:not([align]):not(:where(.not-content *)) { + text-align: start; + } + /*
s,
s, and
s inside asides */ .sl-markdown-content .starlight-aside :is(th, td, hr, blockquote):not(:where(.not-content *)) { - border-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 30%, transparent); + border-color: var(--sl-color-gray-4); + } + @supports ( + border-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 30%, transparent) + ) { + .sl-markdown-content .starlight-aside :is(th, td, hr, blockquote):not(:where(.not-content *)) { + border-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 30%, transparent); + } } -} -/* inside asides */ -@supports (border-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 12%, transparent)) { - .sl-markdown-content .starlight-aside code:not(:where(.not-content *)) { - background-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 12%, transparent); + /* inside asides */ + @supports ( + border-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 12%, transparent) + ) { + .sl-markdown-content .starlight-aside code:not(:where(.not-content *)) { + background-color: color-mix(in srgb, var(--sl-color-asides-text-accent) 12%, transparent); + } } -} -.sl-markdown-content hr:not(:where(.not-content *)) { - border: 0; - border-bottom: 1px solid var(--sl-color-hairline); -} + .sl-markdown-content hr:not(:where(.not-content *)) { + border: 0; + border-bottom: 1px solid var(--sl-color-hairline); + } -/*
and styles */ -.sl-markdown-content details:not(:where(.not-content *)) { - --sl-details-border-color: var(--sl-color-gray-5); - --sl-details-border-color--hover: var(--sl-color-text-accent); + /*
and styles */ + .sl-markdown-content details:not(:where(.not-content *)) { + --sl-details-border-color: var(--sl-color-gray-5); + --sl-details-border-color--hover: var(--sl-color-text-accent); - border-inline-start: 2px solid var(--sl-details-border-color); - padding-inline-start: 1rem; -} -.sl-markdown-content details:not([open]):hover:not(:where(.not-content *)), -.sl-markdown-content details:has(> summary:hover):not(:where(.not-content *)) { - border-color: var(--sl-details-border-color--hover); -} -.sl-markdown-content summary:not(:where(.not-content *)) { - color: var(--sl-color-white); - cursor: pointer; - display: block; /* Needed to hide the default marker in some browsers. */ - font-weight: 600; - /* Expand the outline so that the marker cannot distort it. */ - margin-inline-start: -0.5rem; - padding-inline-start: 0.5rem; -} -.sl-markdown-content details[open] > summary:not(:where(.not-content *)) { - margin-bottom: 1rem; -} + border-inline-start: 2px solid var(--sl-details-border-color); + padding-inline-start: 1rem; + } + .sl-markdown-content details:not([open]):hover:not(:where(.not-content *)), + .sl-markdown-content details:has(> summary:hover):not(:where(.not-content *)) { + border-color: var(--sl-details-border-color--hover); + } + .sl-markdown-content summary:not(:where(.not-content *)) { + color: var(--sl-color-white); + cursor: pointer; + display: block; /* Needed to hide the default marker in some browsers. */ + font-weight: 600; + /* Expand the outline so that the marker cannot distort it. */ + margin-inline-start: -0.5rem; + padding-inline-start: 0.5rem; + } + .sl-markdown-content details[open] > summary:not(:where(.not-content *)) { + margin-bottom: 1rem; + } -/* marker styles */ -.sl-markdown-content summary:not(:where(.not-content *))::marker, -.sl-markdown-content summary:not(:where(.not-content *))::-webkit-details-marker { - display: none; -} -.sl-markdown-content summary:not(:where(.not-content *))::before { - --sl-details-marker-size: 1.25rem; - - background-color: currentColor; - content: ''; - display: inline-block; - height: var(--sl-details-marker-size); - width: var(--sl-details-marker-size); - margin-inline: calc((var(--sl-details-marker-size) / 4) * -1) 0.25rem; - vertical-align: middle; - -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M14.8 11.3 10.6 7a1 1 0 1 0-1.4 1.5l3.5 3.5-3.5 3.5a1 1 0 0 0 0 1.4 1 1 0 0 0 .7.3 1 1 0 0 0 .7-.3l4.2-4.2a1 1 0 0 0 0-1.4Z'/%3E%3C/svg%3E%0A"); - mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M14.8 11.3 10.6 7a1 1 0 1 0-1.4 1.5l3.5 3.5-3.5 3.5a1 1 0 0 0 0 1.4 1 1 0 0 0 .7.3 1 1 0 0 0 .7-.3l4.2-4.2a1 1 0 0 0 0-1.4Z'/%3E%3C/svg%3E%0A"); - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; -} -@media (prefers-reduced-motion: no-preference) { + /* marker styles */ + .sl-markdown-content summary:not(:where(.not-content *))::marker, + .sl-markdown-content summary:not(:where(.not-content *))::-webkit-details-marker { + display: none; + } .sl-markdown-content summary:not(:where(.not-content *))::before { - transition: transform 0.2s ease-in-out; + --sl-details-marker-size: 1.25rem; + + background-color: currentColor; + content: ''; + display: inline-block; + height: var(--sl-details-marker-size); + width: var(--sl-details-marker-size); + margin-inline: calc((var(--sl-details-marker-size) / 4) * -1) 0.25rem; + vertical-align: middle; + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M14.8 11.3 10.6 7a1 1 0 1 0-1.4 1.5l3.5 3.5-3.5 3.5a1 1 0 0 0 0 1.4 1 1 0 0 0 .7.3 1 1 0 0 0 .7-.3l4.2-4.2a1 1 0 0 0 0-1.4Z'/%3E%3C/svg%3E%0A"); + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M14.8 11.3 10.6 7a1 1 0 1 0-1.4 1.5l3.5 3.5-3.5 3.5a1 1 0 0 0 0 1.4 1 1 0 0 0 .7.3 1 1 0 0 0 .7-.3l4.2-4.2a1 1 0 0 0 0-1.4Z'/%3E%3C/svg%3E%0A"); + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + } + @media (prefers-reduced-motion: no-preference) { + .sl-markdown-content summary:not(:where(.not-content *))::before { + transition: transform 0.2s ease-in-out; + } + } + .sl-markdown-content details[open] > summary:not(:where(.not-content *))::before { + transform: rotateZ(90deg); + } + [dir='rtl'] .sl-markdown-content summary:not(:where(.not-content *))::before, + .sl-markdown-content [dir='rtl'] summary:not(:where(.not-content *))::before { + transform: rotateZ(180deg); + } + /* with only a paragraph automatically added when using MDX */ + .sl-markdown-content summary:not(:where(.not-content *)) p:only-child { + display: inline; } -} -.sl-markdown-content details[open] > summary:not(:where(.not-content *))::before { - transform: rotateZ(90deg); -} -[dir='rtl'] .sl-markdown-content summary:not(:where(.not-content *))::before, -.sl-markdown-content [dir='rtl'] summary:not(:where(.not-content *))::before { - transform: rotateZ(180deg); -} -/* with only a paragraph automatically added when using MDX */ -.sl-markdown-content summary:not(:where(.not-content *)) p:only-child { - display: inline; -} -/*
styles inside asides */ -.sl-markdown-content .starlight-aside details:not(:where(.not-content *)) { - --sl-details-border-color: var(--sl-color-asides-border); - --sl-details-border-color--hover: var(--sl-color-asides-text-accent); + /*
styles inside asides */ + .sl-markdown-content .starlight-aside details:not(:where(.not-content *)) { + --sl-details-border-color: var(--sl-color-asides-border); + --sl-details-border-color--hover: var(--sl-color-asides-text-accent); + } } diff --git a/packages/starlight/style/props.css b/packages/starlight/style/props.css index 09c0305d110..83eafa9b0e4 100644 --- a/packages/starlight/style/props.css +++ b/packages/starlight/style/props.css @@ -1,184 +1,186 @@ -:root, -::backdrop { - /* Colors (dark mode) */ - --sl-color-white: hsl(0, 0%, 100%); /* “white” */ - --sl-color-gray-1: hsl(224, 20%, 94%); - --sl-color-gray-2: hsl(224, 6%, 77%); - --sl-color-gray-3: hsl(224, 6%, 56%); - --sl-color-gray-4: hsl(224, 7%, 36%); - --sl-color-gray-5: hsl(224, 10%, 23%); - --sl-color-gray-6: hsl(224, 14%, 16%); - --sl-color-black: hsl(224, 10%, 10%); - - --sl-hue-orange: 41; - --sl-color-orange-low: hsl(var(--sl-hue-orange), 39%, 22%); - --sl-color-orange: hsl(var(--sl-hue-orange), 82%, 63%); - --sl-color-orange-high: hsl(var(--sl-hue-orange), 82%, 87%); - --sl-hue-green: 101; - --sl-color-green-low: hsl(var(--sl-hue-green), 39%, 22%); - --sl-color-green: hsl(var(--sl-hue-green), 82%, 63%); - --sl-color-green-high: hsl(var(--sl-hue-green), 82%, 80%); - --sl-hue-blue: 234; - --sl-color-blue-low: hsl(var(--sl-hue-blue), 54%, 20%); - --sl-color-blue: hsl(var(--sl-hue-blue), 100%, 60%); - --sl-color-blue-high: hsl(var(--sl-hue-blue), 100%, 87%); - --sl-hue-purple: 281; - --sl-color-purple-low: hsl(var(--sl-hue-purple), 39%, 22%); - --sl-color-purple: hsl(var(--sl-hue-purple), 82%, 63%); - --sl-color-purple-high: hsl(var(--sl-hue-purple), 82%, 89%); - --sl-hue-red: 339; - --sl-color-red-low: hsl(var(--sl-hue-red), 39%, 22%); - --sl-color-red: hsl(var(--sl-hue-red), 82%, 63%); - --sl-color-red-high: hsl(var(--sl-hue-red), 82%, 87%); - - --sl-color-accent-low: hsl(224, 54%, 20%); - --sl-color-accent: hsl(224, 100%, 60%); - --sl-color-accent-high: hsl(224, 100%, 85%); - - --sl-color-text: var(--sl-color-gray-2); - --sl-color-text-accent: var(--sl-color-accent-high); - --sl-color-text-invert: var(--sl-color-accent-low); - --sl-color-bg: var(--sl-color-black); - --sl-color-bg-nav: var(--sl-color-gray-6); - --sl-color-bg-sidebar: var(--sl-color-gray-6); - --sl-color-bg-inline-code: var(--sl-color-gray-5); - --sl-color-bg-accent: var(--sl-color-accent-high); - --sl-color-hairline-light: var(--sl-color-gray-5); - --sl-color-hairline: var(--sl-color-gray-6); - --sl-color-hairline-shade: var(--sl-color-black); - - --sl-color-backdrop-overlay: hsla(223, 13%, 10%, 0.66); - - /* Shadows (dark mode) */ - --sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.12), 0px 2px 1px hsla(0, 0%, 0%, 0.24); - --sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.08), 0px 5px 2px hsla(0, 0%, 0%, 0.08), - 0px 3px 2px hsla(0, 0%, 0%, 0.12), 0px 1px 1px hsla(0, 0%, 0%, 0.15); - --sl-shadow-lg: 0px 25px 7px hsla(0, 0%, 0%, 0.03), 0px 16px 6px hsla(0, 0%, 0%, 0.1), - 0px 9px 5px hsla(223, 13%, 10%, 0.33), 0px 4px 4px hsla(0, 0%, 0%, 0.75), - 0px 4px 2px hsla(0, 0%, 0%, 0.25); - - /* Text size and line height */ - --sl-text-2xs: 0.75rem; /* 12px */ - --sl-text-xs: 0.8125rem; /* 13px */ - --sl-text-sm: 0.875rem; /* 14px */ - --sl-text-base: 1rem; /* 16px */ - --sl-text-lg: 1.125rem; /* 18px */ - --sl-text-xl: 1.25rem; /* 20px */ - --sl-text-2xl: 1.5rem; /* 24px */ - --sl-text-3xl: 1.8125rem; /* 29px */ - --sl-text-4xl: 2.1875rem; /* 35px */ - --sl-text-5xl: 2.625rem; /* 42px */ - --sl-text-6xl: 4rem; /* 64px */ - - --sl-text-body: var(--sl-text-base); - --sl-text-body-sm: var(--sl-text-xs); - --sl-text-code: var(--sl-text-sm); - --sl-text-code-sm: var(--sl-text-xs); - --sl-text-h1: var(--sl-text-4xl); - --sl-text-h2: var(--sl-text-3xl); - --sl-text-h3: var(--sl-text-2xl); - --sl-text-h4: var(--sl-text-xl); - --sl-text-h5: var(--sl-text-lg); - - --sl-line-height: 1.75; - --sl-line-height-headings: 1.2; - - --sl-font-system: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', - 'Segoe UI Symbol', 'Noto Color Emoji'; - --sl-font-system-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', - 'Courier New', monospace; - --__sl-font: var(--sl-font, var(--sl-font-system)), var(--sl-font-system); - --__sl-font-mono: var(--sl-font-mono, var(--sl-font-system-mono)), var(--sl-font-system-mono); - - /** Key layout values */ - --sl-nav-height: 3.5rem; - --sl-nav-pad-x: 1rem; - --sl-nav-pad-y: 0.75rem; - --sl-mobile-toc-height: 3rem; - --sl-sidebar-width: 18.75rem; - --sl-sidebar-pad-x: 1rem; - --sl-content-width: 45rem; - --sl-content-pad-x: 1rem; - --sl-menu-button-size: 2rem; - --sl-nav-gap: var(--sl-content-pad-x); - /* Offset required to show outline inside an element instead of round the outside */ - --sl-outline-offset-inside: -0.1875rem; - - /* Global z-index values */ - --sl-z-index-toc: 4; - --sl-z-index-menu: 5; - --sl-z-index-navbar: 10; - --sl-z-index-skiplink: 20; -} +@layer starlight.base { + :root, + ::backdrop { + /* Colors (dark mode) */ + --sl-color-white: hsl(0, 0%, 100%); /* “white” */ + --sl-color-gray-1: hsl(224, 20%, 94%); + --sl-color-gray-2: hsl(224, 6%, 77%); + --sl-color-gray-3: hsl(224, 6%, 56%); + --sl-color-gray-4: hsl(224, 7%, 36%); + --sl-color-gray-5: hsl(224, 10%, 23%); + --sl-color-gray-6: hsl(224, 14%, 16%); + --sl-color-black: hsl(224, 10%, 10%); + + --sl-hue-orange: 41; + --sl-color-orange-low: hsl(var(--sl-hue-orange), 39%, 22%); + --sl-color-orange: hsl(var(--sl-hue-orange), 82%, 63%); + --sl-color-orange-high: hsl(var(--sl-hue-orange), 82%, 87%); + --sl-hue-green: 101; + --sl-color-green-low: hsl(var(--sl-hue-green), 39%, 22%); + --sl-color-green: hsl(var(--sl-hue-green), 82%, 63%); + --sl-color-green-high: hsl(var(--sl-hue-green), 82%, 80%); + --sl-hue-blue: 234; + --sl-color-blue-low: hsl(var(--sl-hue-blue), 54%, 20%); + --sl-color-blue: hsl(var(--sl-hue-blue), 100%, 60%); + --sl-color-blue-high: hsl(var(--sl-hue-blue), 100%, 87%); + --sl-hue-purple: 281; + --sl-color-purple-low: hsl(var(--sl-hue-purple), 39%, 22%); + --sl-color-purple: hsl(var(--sl-hue-purple), 82%, 63%); + --sl-color-purple-high: hsl(var(--sl-hue-purple), 82%, 89%); + --sl-hue-red: 339; + --sl-color-red-low: hsl(var(--sl-hue-red), 39%, 22%); + --sl-color-red: hsl(var(--sl-hue-red), 82%, 63%); + --sl-color-red-high: hsl(var(--sl-hue-red), 82%, 87%); + + --sl-color-accent-low: hsl(224, 54%, 20%); + --sl-color-accent: hsl(224, 100%, 60%); + --sl-color-accent-high: hsl(224, 100%, 85%); + + --sl-color-text: var(--sl-color-gray-2); + --sl-color-text-accent: var(--sl-color-accent-high); + --sl-color-text-invert: var(--sl-color-accent-low); + --sl-color-bg: var(--sl-color-black); + --sl-color-bg-nav: var(--sl-color-gray-6); + --sl-color-bg-sidebar: var(--sl-color-gray-6); + --sl-color-bg-inline-code: var(--sl-color-gray-5); + --sl-color-bg-accent: var(--sl-color-accent-high); + --sl-color-hairline-light: var(--sl-color-gray-5); + --sl-color-hairline: var(--sl-color-gray-6); + --sl-color-hairline-shade: var(--sl-color-black); + + --sl-color-backdrop-overlay: hsla(223, 13%, 10%, 0.66); + + /* Shadows (dark mode) */ + --sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.12), 0px 2px 1px hsla(0, 0%, 0%, 0.24); + --sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.08), 0px 5px 2px hsla(0, 0%, 0%, 0.08), + 0px 3px 2px hsla(0, 0%, 0%, 0.12), 0px 1px 1px hsla(0, 0%, 0%, 0.15); + --sl-shadow-lg: 0px 25px 7px hsla(0, 0%, 0%, 0.03), 0px 16px 6px hsla(0, 0%, 0%, 0.1), + 0px 9px 5px hsla(223, 13%, 10%, 0.33), 0px 4px 4px hsla(0, 0%, 0%, 0.75), + 0px 4px 2px hsla(0, 0%, 0%, 0.25); + + /* Text size and line height */ + --sl-text-2xs: 0.75rem; /* 12px */ + --sl-text-xs: 0.8125rem; /* 13px */ + --sl-text-sm: 0.875rem; /* 14px */ + --sl-text-base: 1rem; /* 16px */ + --sl-text-lg: 1.125rem; /* 18px */ + --sl-text-xl: 1.25rem; /* 20px */ + --sl-text-2xl: 1.5rem; /* 24px */ + --sl-text-3xl: 1.8125rem; /* 29px */ + --sl-text-4xl: 2.1875rem; /* 35px */ + --sl-text-5xl: 2.625rem; /* 42px */ + --sl-text-6xl: 4rem; /* 64px */ + + --sl-text-body: var(--sl-text-base); + --sl-text-body-sm: var(--sl-text-xs); + --sl-text-code: var(--sl-text-sm); + --sl-text-code-sm: var(--sl-text-xs); + --sl-text-h1: var(--sl-text-4xl); + --sl-text-h2: var(--sl-text-3xl); + --sl-text-h3: var(--sl-text-2xl); + --sl-text-h4: var(--sl-text-xl); + --sl-text-h5: var(--sl-text-lg); + + --sl-line-height: 1.75; + --sl-line-height-headings: 1.2; + + --sl-font-system: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', + Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + --sl-font-system-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', + 'Courier New', monospace; + --__sl-font: var(--sl-font, var(--sl-font-system)), var(--sl-font-system); + --__sl-font-mono: var(--sl-font-mono, var(--sl-font-system-mono)), var(--sl-font-system-mono); + + /** Key layout values */ + --sl-nav-height: 3.5rem; + --sl-nav-pad-x: 1rem; + --sl-nav-pad-y: 0.75rem; + --sl-mobile-toc-height: 3rem; + --sl-sidebar-width: 18.75rem; + --sl-sidebar-pad-x: 1rem; + --sl-content-width: 45rem; + --sl-content-pad-x: 1rem; + --sl-menu-button-size: 2rem; + --sl-nav-gap: var(--sl-content-pad-x); + /* Offset required to show outline inside an element instead of round the outside */ + --sl-outline-offset-inside: -0.1875rem; + + /* Global z-index values */ + --sl-z-index-toc: 4; + --sl-z-index-menu: 5; + --sl-z-index-navbar: 10; + --sl-z-index-skiplink: 20; + } -:root[data-theme='light'], -[data-theme='light'] ::backdrop { - /* Colours (light mode) */ - --sl-color-white: hsl(224, 10%, 10%); - --sl-color-gray-1: hsl(224, 14%, 16%); - --sl-color-gray-2: hsl(224, 10%, 23%); - --sl-color-gray-3: hsl(224, 7%, 36%); - --sl-color-gray-4: hsl(224, 6%, 56%); - --sl-color-gray-5: hsl(224, 6%, 77%); - --sl-color-gray-6: hsl(224, 20%, 94%); - --sl-color-gray-7: hsl(224, 19%, 97%); - --sl-color-black: hsl(0, 0%, 100%); - - --sl-color-orange-high: hsl(var(--sl-hue-orange), 80%, 25%); - --sl-color-orange: hsl(var(--sl-hue-orange), 90%, 60%); - --sl-color-orange-low: hsl(var(--sl-hue-orange), 90%, 88%); - --sl-color-green-high: hsl(var(--sl-hue-green), 80%, 22%); - --sl-color-green: hsl(var(--sl-hue-green), 90%, 46%); - --sl-color-green-low: hsl(var(--sl-hue-green), 85%, 90%); - --sl-color-blue-high: hsl(var(--sl-hue-blue), 80%, 30%); - --sl-color-blue: hsl(var(--sl-hue-blue), 90%, 60%); - --sl-color-blue-low: hsl(var(--sl-hue-blue), 88%, 90%); - --sl-color-purple-high: hsl(var(--sl-hue-purple), 90%, 30%); - --sl-color-purple: hsl(var(--sl-hue-purple), 90%, 60%); - --sl-color-purple-low: hsl(var(--sl-hue-purple), 80%, 90%); - --sl-color-red-high: hsl(var(--sl-hue-red), 80%, 30%); - --sl-color-red: hsl(var(--sl-hue-red), 90%, 60%); - --sl-color-red-low: hsl(var(--sl-hue-red), 80%, 90%); - - --sl-color-accent-high: hsl(234, 80%, 30%); - --sl-color-accent: hsl(234, 90%, 60%); - --sl-color-accent-low: hsl(234, 88%, 90%); - - --sl-color-text-accent: var(--sl-color-accent); - --sl-color-text-invert: var(--sl-color-black); - --sl-color-bg-nav: var(--sl-color-gray-7); - --sl-color-bg-sidebar: var(--sl-color-bg); - --sl-color-bg-inline-code: var(--sl-color-gray-6); - --sl-color-bg-accent: var(--sl-color-accent); - --sl-color-hairline-light: var(--sl-color-gray-6); - --sl-color-hairline-shade: var(--sl-color-gray-6); - - --sl-color-backdrop-overlay: hsla(225, 9%, 36%, 0.66); - - /* Shadows (light mode) */ - --sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.06), 0px 2px 1px hsla(0, 0%, 0%, 0.06); - --sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.03), 0px 5px 2px hsla(0, 0%, 0%, 0.03), - 0px 3px 2px hsla(0, 0%, 0%, 0.06), 0px 1px 1px hsla(0, 0%, 0%, 0.06); - --sl-shadow-lg: 0px 25px 7px rgba(0, 0, 0, 0.01), 0px 16px 6px hsla(0, 0%, 0%, 0.03), - 0px 9px 5px hsla(223, 13%, 10%, 0.08), 0px 4px 4px hsla(0, 0%, 0%, 0.16), - 0px 4px 2px hsla(0, 0%, 0%, 0.04); -} + :root[data-theme='light'], + [data-theme='light'] ::backdrop { + /* Colours (light mode) */ + --sl-color-white: hsl(224, 10%, 10%); + --sl-color-gray-1: hsl(224, 14%, 16%); + --sl-color-gray-2: hsl(224, 10%, 23%); + --sl-color-gray-3: hsl(224, 7%, 36%); + --sl-color-gray-4: hsl(224, 6%, 56%); + --sl-color-gray-5: hsl(224, 6%, 77%); + --sl-color-gray-6: hsl(224, 20%, 94%); + --sl-color-gray-7: hsl(224, 19%, 97%); + --sl-color-black: hsl(0, 0%, 100%); + + --sl-color-orange-high: hsl(var(--sl-hue-orange), 80%, 25%); + --sl-color-orange: hsl(var(--sl-hue-orange), 90%, 60%); + --sl-color-orange-low: hsl(var(--sl-hue-orange), 90%, 88%); + --sl-color-green-high: hsl(var(--sl-hue-green), 80%, 22%); + --sl-color-green: hsl(var(--sl-hue-green), 90%, 46%); + --sl-color-green-low: hsl(var(--sl-hue-green), 85%, 90%); + --sl-color-blue-high: hsl(var(--sl-hue-blue), 80%, 30%); + --sl-color-blue: hsl(var(--sl-hue-blue), 90%, 60%); + --sl-color-blue-low: hsl(var(--sl-hue-blue), 88%, 90%); + --sl-color-purple-high: hsl(var(--sl-hue-purple), 90%, 30%); + --sl-color-purple: hsl(var(--sl-hue-purple), 90%, 60%); + --sl-color-purple-low: hsl(var(--sl-hue-purple), 80%, 90%); + --sl-color-red-high: hsl(var(--sl-hue-red), 80%, 30%); + --sl-color-red: hsl(var(--sl-hue-red), 90%, 60%); + --sl-color-red-low: hsl(var(--sl-hue-red), 80%, 90%); + + --sl-color-accent-high: hsl(234, 80%, 30%); + --sl-color-accent: hsl(234, 90%, 60%); + --sl-color-accent-low: hsl(234, 88%, 90%); + + --sl-color-text-accent: var(--sl-color-accent); + --sl-color-text-invert: var(--sl-color-black); + --sl-color-bg-nav: var(--sl-color-gray-7); + --sl-color-bg-sidebar: var(--sl-color-bg); + --sl-color-bg-inline-code: var(--sl-color-gray-6); + --sl-color-bg-accent: var(--sl-color-accent); + --sl-color-hairline-light: var(--sl-color-gray-6); + --sl-color-hairline-shade: var(--sl-color-gray-6); + + --sl-color-backdrop-overlay: hsla(225, 9%, 36%, 0.66); + + /* Shadows (light mode) */ + --sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.06), 0px 2px 1px hsla(0, 0%, 0%, 0.06); + --sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.03), 0px 5px 2px hsla(0, 0%, 0%, 0.03), + 0px 3px 2px hsla(0, 0%, 0%, 0.06), 0px 1px 1px hsla(0, 0%, 0%, 0.06); + --sl-shadow-lg: 0px 25px 7px rgba(0, 0, 0, 0.01), 0px 16px 6px hsla(0, 0%, 0%, 0.03), + 0px 9px 5px hsla(223, 13%, 10%, 0.08), 0px 4px 4px hsla(0, 0%, 0%, 0.16), + 0px 4px 2px hsla(0, 0%, 0%, 0.04); + } -@media (min-width: 50em) { - :root { - --sl-nav-height: 4rem; - --sl-nav-pad-x: 1.5rem; - --sl-text-h1: var(--sl-text-5xl); - --sl-text-h2: var(--sl-text-4xl); - --sl-text-h3: var(--sl-text-3xl); - --sl-text-h4: var(--sl-text-2xl); + @media (min-width: 50em) { + :root { + --sl-nav-height: 4rem; + --sl-nav-pad-x: 1.5rem; + --sl-text-h1: var(--sl-text-5xl); + --sl-text-h2: var(--sl-text-4xl); + --sl-text-h3: var(--sl-text-3xl); + --sl-text-h4: var(--sl-text-2xl); + } } -} -@media (min-width: 72rem) { - :root { - --sl-content-pad-x: 1.5rem; - --sl-mobile-toc-height: 0rem; + @media (min-width: 72rem) { + :root { + --sl-content-pad-x: 1.5rem; + --sl-mobile-toc-height: 0rem; + } } } diff --git a/packages/starlight/style/reset.css b/packages/starlight/style/reset.css index 0867542a8c4..f2855a468e7 100644 --- a/packages/starlight/style/reset.css +++ b/packages/starlight/style/reset.css @@ -1,48 +1,50 @@ -*, -*::before, -*::after { - box-sizing: border-box; -} +@layer starlight.reset { + *, + *::before, + *::after { + box-sizing: border-box; + } -* { - margin: 0; -} + * { + margin: 0; + } -html { - color-scheme: dark; - accent-color: var(--sl-color-accent); -} + html { + color-scheme: dark; + accent-color: var(--sl-color-accent); + } -html[data-theme='light'] { - color-scheme: light; -} + html[data-theme='light'] { + color-scheme: light; + } -body { - font-family: var(--__sl-font); - line-height: var(--sl-line-height); - -webkit-font-smoothing: antialiased; - color: var(--sl-color-text); - background-color: var(--sl-color-bg); -} + body { + font-family: var(--__sl-font); + line-height: var(--sl-line-height); + -webkit-font-smoothing: antialiased; + color: var(--sl-color-text); + background-color: var(--sl-color-bg); + } -input, -button, -textarea, -select { - font: inherit; -} + input, + button, + textarea, + select { + font: inherit; + } -p, -h1, -h2, -h3, -h4, -h5, -h6, -code { - overflow-wrap: anywhere; -} + p, + h1, + h2, + h3, + h4, + h5, + h6, + code { + overflow-wrap: anywhere; + } -code { - font-family: var(--__sl-font-mono); + code { + font-family: var(--__sl-font-mono); + } } diff --git a/packages/starlight/style/shiki.css b/packages/starlight/style/shiki.css deleted file mode 100644 index c9197d1c32e..00000000000 --- a/packages/starlight/style/shiki.css +++ /dev/null @@ -1,13 +0,0 @@ -:root { - --astro-code-foreground: var(--sl-color-white); - --astro-code-background: var(--sl-color-gray-6); - --astro-code-token-constant: var(--sl-color-blue-high); - --astro-code-token-string: var(--sl-color-green-high); - --astro-code-token-comment: var(--sl-color-gray-2); - --astro-code-token-keyword: var(--sl-color-purple-high); - --astro-code-token-parameter: var(--sl-color-red-high); - --astro-code-token-function: var(--sl-color-red-high); - --astro-code-token-string-expression: var(--sl-color-green-high); - --astro-code-token-punctuation: var(--sl-color-gray-2); - --astro-code-token-link: var(--sl-color-blue-high); -} diff --git a/packages/starlight/style/util.css b/packages/starlight/style/util.css index 74868532205..bb839538b33 100644 --- a/packages/starlight/style/util.css +++ b/packages/starlight/style/util.css @@ -1,61 +1,63 @@ -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; -} +@layer starlight.utils { + .sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; + } -.sl-hidden { - display: none; -} -.sl-flex { - display: flex; -} -.sl-block { - display: block; -} -@media (min-width: 50rem) { - .md\:sl-hidden { + .sl-hidden { display: none; } - .md\:sl-flex { + .sl-flex { display: flex; } - .md\:sl-block { + .sl-block { display: block; } -} -@media (min-width: 72rem) { - .lg\:sl-hidden { - display: none; + @media (min-width: 50rem) { + .md\:sl-hidden { + display: none; + } + .md\:sl-flex { + display: flex; + } + .md\:sl-block { + display: block; + } } - .lg\:sl-flex { - display: flex; + @media (min-width: 72rem) { + .lg\:sl-hidden { + display: none; + } + .lg\:sl-flex { + display: flex; + } + .lg\:sl-block { + display: block; + } } - .lg\:sl-block { - display: block; + [data-theme='light'] .light\:sl-hidden { + display: none; + } + [data-theme='dark'] .dark\:sl-hidden { + display: none; } -} -[data-theme='light'] .light\:sl-hidden { - display: none; -} -[data-theme='dark'] .dark\:sl-hidden { - display: none; -} - -/* -Flip an element around the y-axis when in an RTL context. -Primarily useful for things where we can’t rely on writing direction like icons. - - -In a LTR context: → In a RTL context: ← -*/ -[dir='rtl'] .rtl\:flip:not(:where([dir='rtl'] [dir='ltr'] *)) { - transform: matrix(-1, 0, 0, 1, 0, 0); + /** + * Flip an element around the y-axis when in an RTL context. + * Primarily useful for things where we can’t rely on writing direction like icons. + * + * + * + * In a LTR context: → In a RTL context: ← + */ + [dir='rtl'] .rtl\:flip:not(:where([dir='rtl'] [dir='ltr'] *)) { + transform: matrix(-1, 0, 0, 1, 0, 0); + } } diff --git a/packages/starlight/user-components/Badge.astro b/packages/starlight/user-components/Badge.astro index 821cd0a32e3..2a0fa991ded 100644 --- a/packages/starlight/user-components/Badge.astro +++ b/packages/starlight/user-components/Badge.astro @@ -21,121 +21,123 @@ const { {text} diff --git a/packages/starlight/user-components/Card.astro b/packages/starlight/user-components/Card.astro index d7ead9c97bf..ee24e84cc28 100644 --- a/packages/starlight/user-components/Card.astro +++ b/packages/starlight/user-components/Card.astro @@ -19,47 +19,49 @@ const { icon, title } = Astro.props; diff --git a/packages/starlight/user-components/CardGrid.astro b/packages/starlight/user-components/CardGrid.astro index 399f18c1cad..65de96f875b 100644 --- a/packages/starlight/user-components/CardGrid.astro +++ b/packages/starlight/user-components/CardGrid.astro @@ -9,28 +9,30 @@ const { stagger = false } = Astro.props;
diff --git a/packages/starlight/user-components/FileTree.astro b/packages/starlight/user-components/FileTree.astro index 2dcb101b34d..353bcb5c535 100644 --- a/packages/starlight/user-components/FileTree.astro +++ b/packages/starlight/user-components/FileTree.astro @@ -8,127 +8,129 @@ const html = processFileTree(fileTreeHtml, Astro.locals.t('fileTree.directory')) diff --git a/packages/starlight/user-components/Icon.astro b/packages/starlight/user-components/Icon.astro index ee7c443d578..61ba21a9aae 100644 --- a/packages/starlight/user-components/Icon.astro +++ b/packages/starlight/user-components/Icon.astro @@ -24,10 +24,12 @@ const a11yAttrs = label ? ({ 'aria-label': label } as const) : ({ 'aria-hidden': /> diff --git a/packages/starlight/user-components/LinkButton.astro b/packages/starlight/user-components/LinkButton.astro index 3afa2bb65b0..2aed3567183 100644 --- a/packages/starlight/user-components/LinkButton.astro +++ b/packages/starlight/user-components/LinkButton.astro @@ -26,51 +26,53 @@ const { diff --git a/packages/starlight/user-components/LinkCard.astro b/packages/starlight/user-components/LinkCard.astro index 8cf6fbd90fd..d78d0e5ca68 100644 --- a/packages/starlight/user-components/LinkCard.astro +++ b/packages/starlight/user-components/LinkCard.astro @@ -21,56 +21,58 @@ const { title, description, ...attributes } = Astro.props; diff --git a/packages/starlight/user-components/Steps.astro b/packages/starlight/user-components/Steps.astro index c66dffb1f43..99c0815a375 100644 --- a/packages/starlight/user-components/Steps.astro +++ b/packages/starlight/user-components/Steps.astro @@ -8,79 +8,83 @@ const { html } = processSteps(content); diff --git a/packages/starlight/user-components/Tabs.astro b/packages/starlight/user-components/Tabs.astro index 257174e1dbe..c11e483c5b2 100644 --- a/packages/starlight/user-components/Tabs.astro +++ b/packages/starlight/user-components/Tabs.astro @@ -98,43 +98,45 @@ if (isSynced) { diff --git a/packages/tailwind/__tests__/tailwind.test.ts b/packages/tailwind/__tests__/tailwind.test.ts index fecfa0f0980..764a7cb1ba0 100644 --- a/packages/tailwind/__tests__/tailwind.test.ts +++ b/packages/tailwind/__tests__/tailwind.test.ts @@ -1,284 +1,119 @@ -import tailwindcss, { type Config } from 'tailwindcss'; -import colors from 'tailwindcss/colors'; -import postcss from 'postcss'; -import { test, expect, describe, vi } from 'vitest'; -import StarlightTailwindPlugin from '..'; +import { compile } from 'tailwindcss'; +import { transform } from 'lightningcss'; +import { test, expect, describe } from 'vitest'; +import starlightTailwindCss from '../tailwind.css?raw'; -/** Generate a CSS string based on the passed CSS and HTML content. */ -const generatePluginCss = async ({ - css = '@tailwind base;', - html = '', - config = {}, -}: { css?: string; html?: string; config?: Partial } = {}): Promise => { - const result = await postcss( - tailwindcss({ - // Enable Starlight plugin. - plugins: [StarlightTailwindPlugin()], - // Provide content for Tailwind to scan for class names. - content: [{ raw: html, extension: 'html' }], - // Spread in any custom Tailwind config. - ...config, - }) - ).process(css, { from: '' }); - return result.css; -}; +const css = String.raw; -describe('@tailwind base;', async () => { - // Generate base CSS with no core Tailwind plugins running to see just Starlight’s output. - const base = await generatePluginCss({ config: { corePlugins: [] } }); +describe('@layer base', async () => { + const output = await render(); + const baseLayer = output.match(/@layer base {(.*?)}[\s\n]*@layer/s)?.[1]; - test('generates Starlight base CSS', async () => { - expect(base).toMatchInlineSnapshot(` - "*, ::before, ::after { - border-width: 0; - border-style: solid; - border-color: #e5e7eb; - } - ::before, ::after { - --tw-content: ; - } - html, :host { - font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - } - code, kbd, samp, pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - } - :root { - --sl-font: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --sl-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - --sl-color-white: #fff; - --sl-color-gray-1: #e5e7eb; - --sl-color-gray-2: #d1d5db; - --sl-color-gray-3: #9ca3af; - --sl-color-gray-4: #4b5563; - --sl-color-gray-5: #374151; - --sl-color-gray-6: #1f2937; - --sl-color-black: #111827; - --sl-color-accent-low: #1e1b4b; - --sl-color-accent: #4f46e5; - --sl-color-accent-high: #c7d2fe; + test('generates base layer CSS', () => { + // The first line includes Tailwind version so we skip it. + const outputWithoutVersion = output.split('\n').slice(1).join('\n'); + expect(outputWithoutVersion).toMatchInlineSnapshot(` + "@layer theme; + + @layer base { + html, :host { + font-family: var(--font-sans); + } + + code, kbd, samp, pre { + font-family: var(--font-mono); + } + + :root { + --sl-font: var(--font-sans); + --sl-font-mono: var(--font-mono); + --sl-color-white: var(--color-white); + --sl-color-gray-1: var(--color-gray-200); + --sl-color-gray-2: var(--color-gray-300); + --sl-color-gray-3: var(--color-gray-400); + --sl-color-gray-4: var(--color-gray-600); + --sl-color-gray-5: var(--color-gray-700); + --sl-color-gray-6: var(--color-gray-800); + --sl-color-black: var(--color-gray-900); + --sl-color-accent-low: var(--color-accent-950, var(--color-accent-900, #1e1b4b)); + --sl-color-accent: var(--color-accent-600, #4f46e5); + --sl-color-accent-high: var(--color-accent-200, #c7d2fe); + + &[data-theme="light"] { + --sl-color-white: var(--color-gray-900); + --sl-color-gray-1: var(--color-gray-800); + --sl-color-gray-2: var(--color-gray-700); + --sl-color-gray-3: var(--color-gray-500); + --sl-color-gray-4: var(--color-gray-400); + --sl-color-gray-5: var(--color-gray-300); + --sl-color-gray-6: var(--color-gray-200); + --sl-color-gray-7: var(--color-gray-100); + --sl-color-black: var(--color-white); + --sl-color-accent-low: var(--color-accent-200, #c7d2fe); + --sl-color-accent: var(--color-accent-600, #4f46e5); + --sl-color-accent-high: var(--color-accent-900, #312e81); + } + } } - :root[data-theme="light"] { - --sl-color-white: #111827; - --sl-color-gray-1: #1f2937; - --sl-color-gray-2: #374151; - --sl-color-gray-3: #6b7280; - --sl-color-gray-4: #9ca3af; - --sl-color-gray-5: #d1d5db; - --sl-color-gray-6: #e5e7eb; - --sl-color-gray-7: #f3f4f6; - --sl-color-black: #fff; - --sl-color-accent-low: #c7d2fe; - --sl-color-accent: #4f46e5; - --sl-color-accent-high: #312e81; - }" + + @layer components, utilities; + " `); }); - test('configures `--sl-color-*` variables', () => { - expect(base).includes('--sl-color-gray-1: #e5e7eb;'); - expect(base).includes('--sl-color-accent: #4f46e5;'); + test('restores some styles from Tailwind Preflight in the base layer', () => { + expect(baseLayer).toMatch(/html, :host {[\s\n]+font-family: var\(--font-sans\);[\s\n]+}/); + expect(baseLayer).toMatch( + /code, kbd, samp, pre {[\s\n]+font-family: var\(--font-mono\);[\s\n]+}/ + ); }); - describe('with user theme config', async () => { - const baseWithConfig = await generatePluginCss({ - config: { - corePlugins: [], - theme: { extend: { colors: { accent: colors.amber, gray: colors.slate } } }, - }, - }); - - test('generates different CSS from base without user config', () => { - expect(baseWithConfig).not.toEqual(base); - }); - - test('uses theme values for Starlight colours', () => { - expect(baseWithConfig).includes('--sl-color-gray-1: #e2e8f0;'); - expect(baseWithConfig).includes('--sl-color-accent: #d97706;'); - }); + test('configures `--sl-color-*` variables', () => { + expect(baseLayer).includes('--sl-color-gray-1: var(--color-gray-200);'); + expect(baseLayer).includes('--sl-color-accent: var(--color-accent-600, #4f46e5);'); }); +}); - test('disables Tailwind preflight', async () => { - const baseWithDefaultPlugins = await generatePluginCss(); - expect(baseWithDefaultPlugins).not.includes('line-height: 1.5;'); - expect(baseWithDefaultPlugins).includes('--tw-'); - expect(baseWithDefaultPlugins).toMatchInlineSnapshot(` - "*, ::before, ::after { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; +describe('@layer utilities', async () => { + const output = await render( + ['dark:bg-black'], + css` + @theme { + --color-black: #000; } - ::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; - } - *, ::before, ::after { - border-width: 0; - border-style: solid; - border-color: #e5e7eb; - } - ::before, ::after { - --tw-content: ; - } - html, :host { - font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - } - code, kbd, samp, pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - } - :root { - --sl-font: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --sl-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - --sl-color-white: #fff; - --sl-color-gray-1: #e5e7eb; - --sl-color-gray-2: #d1d5db; - --sl-color-gray-3: #9ca3af; - --sl-color-gray-4: #4b5563; - --sl-color-gray-5: #374151; - --sl-color-gray-6: #1f2937; - --sl-color-black: #111827; - --sl-color-accent-low: #1e1b4b; - --sl-color-accent: #4f46e5; - --sl-color-accent-high: #c7d2fe; - } - :root[data-theme="light"] { - --sl-color-white: #111827; - --sl-color-gray-1: #1f2937; - --sl-color-gray-2: #374151; - --sl-color-gray-3: #6b7280; - --sl-color-gray-4: #9ca3af; - --sl-color-gray-5: #d1d5db; - --sl-color-gray-6: #e5e7eb; - --sl-color-gray-7: #f3f4f6; - --sl-color-black: #fff; - --sl-color-accent-low: #c7d2fe; - --sl-color-accent: #4f46e5; - --sl-color-accent-high: #312e81; - }" - `); - }); -}); + ` + ); + const utilitiesLayer = output.match(/@layer utilities {(.*?)}\n*$/s)?.[1]; -describe('@tailwind utilities;', () => { test('uses [data-theme="dark"] for dark: utility classes', async () => { - const utils = await generatePluginCss({ - css: '@tailwind utilities;', - html: '
', - }); - expect(utils).includes('.dark\\:text-red-50:is([data-theme="dark"] *)'); - expect(utils).toMatchInlineSnapshot(` - ".dark\\:text-red-50:is([data-theme="dark"] *) { - --tw-text-opacity: 1; - color: rgb(254 242 242 / var(--tw-text-opacity)) - }" + expect(utilitiesLayer).toMatchInlineSnapshot(` + " + .dark\\:bg-black { + &:where([data-theme="dark"], [data-theme="dark"] *) { + background-color: var(--color-black); + } + } + " `); }); }); -test('warns when a prefix of "sl-" is set', async () => { - const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}); - await generatePluginCss({ config: { prefix: 'sl-' } }); - expect(warn).toBeCalledTimes(1); - expect(warn.mock.lastCall?.[0]).toMatchInlineSnapshot(` - "A Tailwind prefix of "sl-" will clash with Starlight’s built-in styles. - Please set a different prefix in your Tailwind config file." +// https://github.com/tailwindlabs/tailwindcss/blob/61af484ff4f34464b317895598c49966c132b410/packages/tailwindcss/src/test-utils/run.ts +async function render(candidates: string[] = [], theme: string = '') { + let { build } = await compile(css` + ${theme} + + @layer theme, base, components, utilities; + + @layer utilities { + @tailwind utilities; + } + + ${starlightTailwindCss} `); - warn.mockRestore(); -}); + + return transform({ + code: Uint8Array.from(Buffer.from(build(candidates))), + filename: 'test.css', + }).code.toString(); +} diff --git a/packages/tailwind/index.ts b/packages/tailwind/index.ts deleted file mode 100644 index 8253e70a9d7..00000000000 --- a/packages/tailwind/index.ts +++ /dev/null @@ -1,120 +0,0 @@ -import plugin from 'tailwindcss/plugin'; - -/** - * Starlight Tailwind Plugin - * - * - Disables Tailwind Preflight. - * - Configures `dark:` variants for Starlight dark mode. - * - Links Starlight’s colors to `gray` and `accent` in Tailwind theme settings. - * - Links Starlight’s fonts to `sans` and `mono` in Tailwind theme settings. - * - * @example - * // tailwind.config.mjs - * import colors from 'tailwindcss/colors'; - * import starlightPlugin from '@astrojs/starlight-tailwind'; - * - * export default { - * plugins: [ - * // Add Starlight’s Tailwind plugin - * starlightPlugin(), - * ], - * theme: { - * extend: { - * colors: { - * // Set an accent color for Astro to use. Indigo is closest to Astro’s defaults. - * accent: colors.yellow, - * // Configure your preferred gray scale. Zinc is closest to Astro’s defaults. - * gray: colors.zinc, - * }, - * }, - * }, - * } - */ -const StarlightTailwindPlugin = () => - plugin( - ({ addBase, theme, config }) => { - if (config('prefix') === 'sl-') { - console.warn( - 'A Tailwind prefix of "sl-" will clash with Starlight’s built-in styles.\n' + - 'Please set a different prefix in your Tailwind config file.' - ); - } - - /** Utility to apply accent colors based on a user’s theme config. */ - const themeAccent = ( - shade: 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950, - fallback: string - ) => - shade === 950 - ? theme(`colors.accent.${shade}`, theme(`colors.accent.900`, fallback)) - : theme(`colors.accent.${shade}`, fallback); - - let white: string = theme('colors.white'); - if (typeof white !== 'string') { - console.warn( - `Expected \`colors.white\` in Tailwind theme to be a string, received ${typeof white}.\n` + - `Try setting a single value, for example \`white: '#fafaf9'\` or \`white: colors.stone[50]\`.` - ); - // Ensure a usable value for white if the user-configured one is wrong. - white = '#fff'; - } - - addBase({ - // Restore crucial styles from Tailwind Preflight: https://tailwindcss.com/docs/preflight - // Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) - '*, ::before, ::after': { - borderWidth: '0', - borderStyle: 'solid', - borderColor: theme('borderColor.DEFAULT', 'currentColor'), - }, - '::before, ::after': { '--tw-content': '' }, - // Keep base font-family styles even in non-Starlight pages. - 'html, :host': { 'font-family': theme('fontFamily.sans') }, - 'code, kbd, samp, pre': { 'font-family': theme('fontFamily.mono') }, - - // Wire up Starlight theme to use Tailwind config. - ':root': { - // Use Tailwind-configured font families. - '--sl-font': theme('fontFamily.sans'), - '--sl-font-mono': theme('fontFamily.mono'), - // Dark mode Starlight theme variables. - '--sl-color-white': white, - '--sl-color-gray-1': theme('colors.gray.200'), - '--sl-color-gray-2': theme('colors.gray.300'), - '--sl-color-gray-3': theme('colors.gray.400'), - '--sl-color-gray-4': theme('colors.gray.600'), - '--sl-color-gray-5': theme('colors.gray.700'), - '--sl-color-gray-6': theme('colors.gray.800'), - '--sl-color-black': theme('colors.gray.900'), - '--sl-color-accent-low': themeAccent(950, '#1e1b4b'), - '--sl-color-accent': themeAccent(600, '#4f46e5'), - '--sl-color-accent-high': themeAccent(200, '#c7d2fe'), - // Light mode Starlight theme variables - '&[data-theme="light"]': { - '--sl-color-white': theme('colors.gray.900'), - '--sl-color-gray-1': theme('colors.gray.800'), - '--sl-color-gray-2': theme('colors.gray.700'), - '--sl-color-gray-3': theme('colors.gray.500'), - '--sl-color-gray-4': theme('colors.gray.400'), - '--sl-color-gray-5': theme('colors.gray.300'), - '--sl-color-gray-6': theme('colors.gray.200'), - '--sl-color-gray-7': theme('colors.gray.100'), - '--sl-color-black': white, - '--sl-color-accent-low': themeAccent(200, '#c7d2fe'), - '--sl-color-accent': themeAccent(600, '#4f46e5'), - '--sl-color-accent-high': themeAccent(900, '#312e81'), - }, - }, - }); - }, - { - // Starlight uses a `data-theme` attribute to power its dark mode. - darkMode: ['class', '[data-theme="dark"]'], - corePlugins: { - // Disable Tailwind’s default reset styles which conflict with Starlight. - preflight: false, - }, - } - ); - -export default StarlightTailwindPlugin; diff --git a/packages/tailwind/package.json b/packages/tailwind/package.json index 502bfe86db3..ea4e9793e8a 100644 --- a/packages/tailwind/package.json +++ b/packages/tailwind/package.json @@ -16,22 +16,20 @@ "index.ts" ], "exports": { - ".": "./index.ts" + ".": "./tailwind.css" }, "scripts": { "test": "vitest", - "test:coverage": "vitest run --coverage" + "test:coverage": "pnpm test" }, "devDependencies": { - "@vitest/coverage-v8": "^3.0.5", - "postcss": "^8.4.47", - "tailwindcss": "^3.4.14", + "lightningcss": "^1.29.1", + "tailwindcss": "^4.0.7", "vitest": "^3.0.5" }, "peerDependencies": { - "@astrojs/starlight": ">=0.30.0", - "@astrojs/tailwind": "^5.1.3", - "tailwindcss": "^3.3.3" + "@astrojs/starlight": ">=0.33.0", + "tailwindcss": "^4.0.0" }, "publishConfig": { "provenance": true diff --git a/packages/tailwind/tailwind.css b/packages/tailwind/tailwind.css new file mode 100644 index 00000000000..29c0bb949cf --- /dev/null +++ b/packages/tailwind/tailwind.css @@ -0,0 +1,50 @@ +@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *)); + +@layer base { + /* Restore crucial styles from Tailwind Preflight: https://tailwindcss.com/docs/preflight */ + /* Keep base font-family styles even in non-Starlight pages. */ + html, + :host { + font-family: var(--font-sans); + } + code, + kbd, + samp, + pre { + font-family: var(--font-mono); + } + + /* Wire up Starlight theme to use Tailwind config. */ + :root { + /* Use Tailwind-configured font families. */ + --sl-font: var(--font-sans); + --sl-font-mono: var(--font-mono); + /* Dark mode Starlight theme variables. */ + --sl-color-white: var(--color-white); + --sl-color-gray-1: var(--color-gray-200); + --sl-color-gray-2: var(--color-gray-300); + --sl-color-gray-3: var(--color-gray-400); + --sl-color-gray-4: var(--color-gray-600); + --sl-color-gray-5: var(--color-gray-700); + --sl-color-gray-6: var(--color-gray-800); + --sl-color-black: var(--color-gray-900); + --sl-color-accent-low: var(--color-accent-950, var(--color-accent-900, #1e1b4b)); + --sl-color-accent: var(--color-accent-600, #4f46e5); + --sl-color-accent-high: var(--color-accent-200, #c7d2fe); + /* Light mode Starlight theme variables. */ + &[data-theme='light'] { + --sl-color-white: var(--color-gray-900); + --sl-color-gray-1: var(--color-gray-800); + --sl-color-gray-2: var(--color-gray-700); + --sl-color-gray-3: var(--color-gray-500); + --sl-color-gray-4: var(--color-gray-400); + --sl-color-gray-5: var(--color-gray-300); + --sl-color-gray-6: var(--color-gray-200); + --sl-color-gray-7: var(--color-gray-100); + --sl-color-black: var(--color-white); + --sl-color-accent-low: var(--color-accent-200, #c7d2fe); + --sl-color-accent: var(--color-accent-600, #4f46e5); + --sl-color-accent-high: var(--color-accent-900, #312e81); + } + } +} diff --git a/packages/tailwind/vitest.config.ts b/packages/tailwind/vitest.config.ts index 045a00292dd..e32dbf9ae85 100644 --- a/packages/tailwind/vitest.config.ts +++ b/packages/tailwind/vitest.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { + css: true, coverage: { reportsDirectory: './__coverage__', thresholds: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e18443bc237..e19093ce9bd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,7 +22,7 @@ importers: version: 11.1.6(size-limit@11.1.6) astro: specifier: ^5.1.5 - version: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + version: 5.1.5(typescript@5.6.3) prettier: specifier: ^3.3.3 version: 3.3.3 @@ -52,7 +52,7 @@ importers: version: 2.1.1 astro: specifier: ^5.1.5 - version: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + version: 5.1.5(typescript@5.6.3) culori: specifier: ^4.0.1 version: 4.0.1 @@ -80,7 +80,7 @@ importers: version: link:../../packages/starlight astro: specifier: ^5.1.5 - version: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + version: 5.1.5(typescript@5.6.3) sharp: specifier: ^0.32.5 version: 0.32.6 @@ -98,7 +98,7 @@ importers: version: link:../../packages/markdoc astro: specifier: ^5.1.5 - version: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + version: 5.1.5(typescript@5.6.3) sharp: specifier: ^0.32.5 version: 0.32.6 @@ -111,18 +111,18 @@ importers: '@astrojs/starlight-tailwind': specifier: ^3.0.0 version: link:../../packages/tailwind - '@astrojs/tailwind': - specifier: ^5.1.4 - version: 5.1.4(astro@5.1.5)(tailwindcss@3.4.14) + '@tailwindcss/vite': + specifier: ^4.0.7 + version: 4.0.7 astro: specifier: ^5.1.5 - version: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + version: 5.1.5(typescript@5.6.3) sharp: specifier: ^0.32.5 version: 0.32.6 tailwindcss: - specifier: ^3.4.4 - version: 3.4.14 + specifier: ^4.0.7 + version: 4.0.7 packages/docsearch: dependencies: @@ -150,6 +150,24 @@ importers: specifier: ^1.3.8 version: 1.3.8 + packages/local-prod-visual-diff: + dependencies: + '@playwright/test': + specifier: ^1.45.0 + version: 1.45.0 + '@types/pixelmatch': + specifier: ^5.2.6 + version: 5.2.6 + '@types/pngjs': + specifier: ^6.0.5 + version: 6.0.5 + pixelmatch: + specifier: ^6.0.0 + version: 6.0.0 + pngjs: + specifier: ^7.0.0 + version: 7.0.0 + packages/markdoc: devDependencies: '@astrojs/markdoc': @@ -160,7 +178,7 @@ importers: version: link:../starlight vitest: specifier: ^3.0.5 - version: 3.0.5(@types/node@18.16.19) + version: 3.0.5 packages/starlight: dependencies: @@ -269,7 +287,7 @@ importers: version: link:../../.. astro: specifier: ^5.1.5 - version: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + version: 5.1.5(typescript@5.6.3) packages/starlight/__e2e__/fixtures/custom src-dir: dependencies: @@ -278,7 +296,7 @@ importers: version: link:../../.. astro: specifier: ^5.1.5 - version: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + version: 5.1.5(typescript@5.6.3) packages/starlight/__e2e__/fixtures/git: dependencies: @@ -287,7 +305,7 @@ importers: version: link:../../.. astro: specifier: ^5.1.5 - version: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + version: 5.1.5(typescript@5.6.3) packages/starlight/__e2e__/fixtures/legacy-collection-config-file: dependencies: @@ -296,7 +314,7 @@ importers: version: link:../../.. astro: specifier: ^5.1.5 - version: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + version: 5.1.5(typescript@5.6.3) packages/starlight/__e2e__/fixtures/ssr: dependencies: @@ -308,22 +326,19 @@ importers: version: link:../../.. astro: specifier: ^5.1.5 - version: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + version: 5.1.5(typescript@5.6.3) packages/tailwind: devDependencies: - '@vitest/coverage-v8': - specifier: ^3.0.5 - version: 3.0.5(vitest@3.0.5) - postcss: - specifier: ^8.4.47 - version: 8.4.49 + lightningcss: + specifier: ^1.29.1 + version: 1.29.1 tailwindcss: - specifier: ^3.4.14 - version: 3.4.14 + specifier: ^4.0.7 + version: 4.0.7 vitest: specifier: ^3.0.5 - version: 3.0.5(@types/node@18.16.19) + version: 3.0.5(lightningcss@1.29.1) packages: @@ -467,10 +482,6 @@ packages: '@algolia/requester-common': 4.20.0 dev: false - /@alloc/quick-lru@5.2.0: - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - /@ampproject/remapping@2.3.0: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -484,7 +495,7 @@ packages: peerDependencies: astro: ^2.0.0 || ^3.0.0-beta || ^4.0.0-beta || ^5.0.0-beta dependencies: - astro: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + astro: 5.1.5(typescript@5.6.3) lite-youtube-embed: 0.3.3 dev: false @@ -556,7 +567,7 @@ packages: '@astrojs/markdown-remark': 6.0.1 '@astrojs/prism': 3.2.0 '@markdoc/markdoc': 0.4.0 - astro: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + astro: 5.1.5(typescript@5.6.3) esbuild: 0.21.5 github-slugger: 2.0.0 htmlparser2: 10.0.0 @@ -619,7 +630,7 @@ packages: peerDependencies: astro: ^5.0.0 dependencies: - astro: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) + astro: 5.1.5(typescript@5.6.3) send: 1.1.0 server-destroy: 1.0.1 transitivePeerDependencies: @@ -640,21 +651,6 @@ packages: zod: 3.23.8 dev: false - /@astrojs/tailwind@5.1.4(astro@5.1.5)(tailwindcss@3.4.14): - resolution: {integrity: sha512-EJ3uoTZZr0RYwTrVS2HgYN0+VbXvg7h87AtwpD5OzqS3GyMwRmzfOwHfORTxoWGQRrY9k/Fi+Awk60kwpvRL5Q==} - peerDependencies: - astro: ^3.0.0 || ^4.0.0 || ^5.0.0 - tailwindcss: ^3.0.24 - dependencies: - astro: 5.1.5(@types/node@18.16.19)(typescript@5.6.3) - autoprefixer: 10.4.20(postcss@8.4.49) - postcss: 8.4.49 - postcss-load-config: 4.0.2(postcss@8.4.49) - tailwindcss: 3.4.14 - transitivePeerDependencies: - - ts-node - dev: false - /@astrojs/telemetry@3.2.0: resolution: {integrity: sha512-wxhSKRfKugLwLlr4OFfcqovk+LIFtKwLyGPqMsv+9/ibqqnW3Gv7tBhtKEb0gAyUAC4G9BTVQeQahqnQAhd6IQ==} engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} @@ -1614,14 +1610,17 @@ packages: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 + dev: true /@jridgewell/resolve-uri@3.1.1: resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} + dev: true /@jridgewell/set-array@1.2.1: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} + dev: true /@jridgewell/sourcemap-codec@1.5.0: resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} @@ -1631,6 +1630,7 @@ packages: dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.5.0 + dev: true /@kwsites/file-exists@1.1.1: resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==} @@ -1807,7 +1807,6 @@ packages: hasBin: true dependencies: playwright: 1.45.0 - dev: true /@rollup/pluginutils@5.1.3: resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} @@ -2011,6 +2010,141 @@ packages: defer-to-connect: 2.0.1 dev: true + /@tailwindcss/node@4.0.7: + resolution: {integrity: sha512-dkFXufkbRB2mu3FPsW5xLAUWJyexpJA+/VtQj18k3SUiJVLdpgzBd1v1gRRcIpEJj7K5KpxBKfOXlZxT3ZZRuA==} + dependencies: + enhanced-resolve: 5.18.1 + jiti: 2.4.2 + tailwindcss: 4.0.7 + dev: false + + /@tailwindcss/oxide-android-arm64@4.0.7: + resolution: {integrity: sha512-5iQXXcAeOHBZy8ASfHFm1k0O/9wR2E3tKh6+P+ilZZbQiMgu+qrnfpBWYPc3FPuQdWiWb73069WT5D+CAfx/tg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide-darwin-arm64@4.0.7: + resolution: {integrity: sha512-7yGZtEc5IgVYylqK/2B0yVqoofk4UAbkn1ygNpIJZyrOhbymsfr8uUFCueTu2fUxmAYIfMZ8waWo2dLg/NgLgg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide-darwin-x64@4.0.7: + resolution: {integrity: sha512-tPQDV20fBjb26yWbPqT1ZSoDChomMCiXTKn4jupMSoMCFyU7+OJvIY1ryjqBuY622dEBJ8LnCDDWsnj1lX9nNQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide-freebsd-x64@4.0.7: + resolution: {integrity: sha512-sZqJpTyTZiknU9LLHuByg5GKTW+u3FqM7q7myequAXxKOpAFiOfXpY710FuMY+gjzSapyRbDXJlsTQtCyiTo5w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide-linux-arm-gnueabihf@4.0.7: + resolution: {integrity: sha512-PBgvULgeSswjd8cbZ91gdIcIDMdc3TUHV5XemEpxlqt9M8KoydJzkuB/Dt910jYdofOIaTWRL6adG9nJICvU4A==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide-linux-arm64-gnu@4.0.7: + resolution: {integrity: sha512-By/a2yeh+e9b+C67F88ndSwVJl2A3tcUDb29FbedDi+DZ4Mr07Oqw9Y1DrDrtHIDhIZ3bmmiL1dkH2YxrtV+zw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide-linux-arm64-musl@4.0.7: + resolution: {integrity: sha512-WHYs3cpPEJb/ccyT20NOzopYQkl7JKncNBUbb77YFlwlXMVJLLV3nrXQKhr7DmZxz2ZXqjyUwsj2rdzd9stYdw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide-linux-x64-gnu@4.0.7: + resolution: {integrity: sha512-7bP1UyuX9kFxbOwkeIJhBZNevKYPXB6xZI37v09fqi6rqRJR8elybwjMUHm54GVP+UTtJ14ueB1K54Dy1tIO6w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide-linux-x64-musl@4.0.7: + resolution: {integrity: sha512-gBQIV8nL/LuhARNGeroqzXymMzzW5wQzqlteVqOVoqwEfpHOP3GMird5pGFbnpY+NP0fOlsZGrxxOPQ4W/84bQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide-win32-arm64-msvc@4.0.7: + resolution: {integrity: sha512-aH530NFfx0kpQpvYMfWoeG03zGnRCMVlQG8do/5XeahYydz+6SIBxA1tl/cyITSJyWZHyVt6GVNkXeAD30v0Xg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide-win32-x64-msvc@4.0.7: + resolution: {integrity: sha512-8Cva6bbJN7ZJx320k7vxGGdU0ewmpfS5A4PudyzUuofdi8MgeINuiiWiPQ0VZCda/GX88K6qp+6UpDZNVr8HMQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@tailwindcss/oxide@4.0.7: + resolution: {integrity: sha512-yr6w5YMgjy+B+zkJiJtIYGXW+HNYOPfRPtSs+aqLnKwdEzNrGv4ZuJh9hYJ3mcA+HMq/K1rtFV+KsEr65S558g==} + engines: {node: '>= 10'} + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.0.7 + '@tailwindcss/oxide-darwin-arm64': 4.0.7 + '@tailwindcss/oxide-darwin-x64': 4.0.7 + '@tailwindcss/oxide-freebsd-x64': 4.0.7 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.7 + '@tailwindcss/oxide-linux-arm64-gnu': 4.0.7 + '@tailwindcss/oxide-linux-arm64-musl': 4.0.7 + '@tailwindcss/oxide-linux-x64-gnu': 4.0.7 + '@tailwindcss/oxide-linux-x64-musl': 4.0.7 + '@tailwindcss/oxide-win32-arm64-msvc': 4.0.7 + '@tailwindcss/oxide-win32-x64-msvc': 4.0.7 + dev: false + + /@tailwindcss/vite@4.0.7: + resolution: {integrity: sha512-GYx5sxArfIMtdZCsxfya3S/efMmf4RvfqdiLUozkhmSFBNUFnYVodatpoO/en4/BsOIGvq/RB6HwcTLn9prFnQ==} + peerDependencies: + vite: ^5.2.0 || ^6 + dependencies: + '@tailwindcss/node': 4.0.7 + '@tailwindcss/oxide': 4.0.7 + lightningcss: 1.29.1 + tailwindcss: 4.0.7 + dev: false + /@types/acorn@4.0.6: resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} dependencies: @@ -2125,6 +2259,18 @@ packages: resolution: {integrity: sha512-1MRgzpzY0hOp9pW/kLRxeQhUWwil6gnrUYd3oEpeYBqp/FexhaCPv3F8LsYr47gtUU45fO2cm1dbwkSrHEo8Uw==} dev: true + /@types/pixelmatch@5.2.6: + resolution: {integrity: sha512-wC83uexE5KGuUODn6zkm9gMzTwdY5L0chiK+VrKcDfEjzxh1uadlWTvOmAbCpnM9zx/Ww3f8uKlYQVnO/TrqVg==} + dependencies: + '@types/node': 18.16.19 + dev: false + + /@types/pngjs@6.0.5: + resolution: {integrity: sha512-0k5eKfrA83JOZPppLtS2C7OUtyNAl2wKNxfyYl9Q5g9lPkgBl/9hNyAu6HuEH2J4XmIv2znEpkDd0SaZVxW6iQ==} + dependencies: + '@types/node': 18.16.19 + dev: false + /@types/responselike@1.0.3: resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} dependencies: @@ -2196,7 +2342,7 @@ packages: '@vitest/spy': 3.0.5 estree-walker: 3.0.3 magic-string: 0.30.17 - vite: 6.0.7(@types/node@18.16.19) + vite: 6.0.7 dev: true /@vitest/pretty-format@3.0.5: @@ -2372,9 +2518,6 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - /any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - /anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -2384,6 +2527,7 @@ packages: /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: false /argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -2524,21 +2668,105 @@ packages: - uploadthing - yaml - /autoprefixer@10.4.20(postcss@8.4.49): - resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} - engines: {node: ^10 || ^12 || >=14} + /astro@5.1.5(typescript@5.6.3): + resolution: {integrity: sha512-Q9TE4aNlczxVoPDoXR3UcjLezL+70z0KbTRXovE4ybpx0mgNL1jsmSWtF3UFXB5+GTf9JK7om5fbIaaMReKcUg==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} hasBin: true - peerDependencies: - postcss: ^8.1.0 dependencies: - browserslist: 4.24.2 - caniuse-lite: 1.0.30001679 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.1.1 - postcss: 8.4.49 - postcss-value-parser: 4.2.0 - dev: false + '@astrojs/compiler': 2.10.3 + '@astrojs/internal-helpers': 0.4.2 + '@astrojs/markdown-remark': 6.0.1 + '@astrojs/telemetry': 3.2.0 + '@oslojs/encoding': 1.1.0 + '@rollup/pluginutils': 5.1.3 + '@types/cookie': 0.6.0 + acorn: 8.14.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + boxen: 8.0.1 + ci-info: 4.1.0 + clsx: 2.1.1 + common-ancestor-path: 1.0.1 + cookie: 0.7.2 + cssesc: 3.0.0 + debug: 4.4.0 + deterministic-object-hash: 2.0.2 + devalue: 5.1.1 + diff: 5.2.0 + dlv: 1.1.3 + dset: 3.1.4 + es-module-lexer: 1.6.0 + esbuild: 0.21.5 + estree-walker: 3.0.3 + fast-glob: 3.3.2 + flattie: 1.1.1 + github-slugger: 2.0.0 + html-escaper: 3.0.3 + http-cache-semantics: 4.1.1 + js-yaml: 4.1.0 + kleur: 4.1.5 + magic-string: 0.30.17 + magicast: 0.3.5 + micromatch: 4.0.8 + mrmime: 2.0.0 + neotraverse: 0.6.18 + p-limit: 6.1.0 + p-queue: 8.0.1 + preferred-pm: 4.0.0 + prompts: 2.4.2 + rehype: 13.0.2 + semver: 7.6.3 + shiki: 1.26.1 + tinyexec: 0.3.2 + tsconfck: 3.1.4(typescript@5.6.3) + ultrahtml: 1.5.3 + unist-util-visit: 5.0.0 + unstorage: 1.14.4 + vfile: 6.0.3 + vite: 6.0.7 + vitefu: 1.0.4(vite@6.0.7) + which-pm: 3.0.0 + xxhash-wasm: 1.1.0 + yargs-parser: 21.1.1 + yocto-spinner: 0.1.1 + zod: 3.23.8 + zod-to-json-schema: 3.23.5(zod@3.23.8) + zod-to-ts: 1.2.0(typescript@5.6.3)(zod@3.23.8) + optionalDependencies: + sharp: 0.33.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@types/node' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - db0 + - idb-keyval + - ioredis + - jiti + - less + - lightningcss + - rollup + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - uploadthing + - yaml /axe-core@4.10.1: resolution: {integrity: sha512-qPC9o+kD8Tir0lzNGLeghbOrWMr3ZJpaRlCIb6Uobt/7N4FiEDvqUMnxzCHRHmg8vOg14kr5gVNyScRmbMaJ9g==} @@ -2583,6 +2811,7 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true /base-64@1.0.0: resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} @@ -2638,12 +2867,6 @@ packages: widest-line: 5.0.0 wrap-ansi: 9.0.0 - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - /brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} dependencies: @@ -2656,17 +2879,6 @@ packages: dependencies: fill-range: 7.1.1 - /browserslist@4.24.2: - resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001679 - electron-to-chromium: 1.5.55 - node-releases: 2.0.18 - update-browserslist-db: 1.1.1(browserslist@4.24.2) - dev: false - /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: @@ -2702,18 +2914,10 @@ packages: responselike: 2.0.1 dev: true - /camelcase-css@2.0.1: - resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} - engines: {node: '>= 6'} - /camelcase@8.0.0: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} - /caniuse-lite@1.0.30001679: - resolution: {integrity: sha512-j2YqID/YwpLnKzCmBOS4tlZdWprXm3ZmQLBH9ZBXFOhoxLA46fwyBvx6toCBWBmnuwUY/qB3kEU6gFx8qgCroA==} - dev: false - /ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -2840,16 +3044,9 @@ packages: /comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - /commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - /common-ancestor-path@1.0.1: resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - /consola@3.3.3: resolution: {integrity: sha512-Qil5KwghMzlqd51UXM0b6fyaGHtOC22scxrwrz4A2882LyUMwQjnvaedN1HAeXzphspQ6CpHkzMAWxBTUruDLg==} engines: {node: ^14.18.0 || >=16.10.0} @@ -2982,6 +3179,11 @@ packages: engines: {node: '>=8'} dev: true + /detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + /detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} @@ -3001,9 +3203,6 @@ packages: dependencies: dequal: 2.0.3 - /didyoumean@1.2.2: - resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - /diff@5.2.0: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} @@ -3063,10 +3262,6 @@ packages: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: false - /electron-to-chromium@1.5.55: - resolution: {integrity: sha512-6maZ2ASDOTBtjt9FhqYPRnbvKU5tjG0IN9SztUOWYw2AzNDNpKJYLJmlK0/En4Hs/aiWnB+JZ+gW19PIGszgKg==} - dev: false - /emmet@2.4.7: resolution: {integrity: sha512-O5O5QNqtdlnQM2bmKHtJgyChcrFMgQuulI+WdiOw2NArzprUqqxUW6bgYtKvzKgrsYpuLWalOkdhNP+1jluhCA==} dependencies: @@ -3097,7 +3292,15 @@ packages: dependencies: once: 1.4.0 - /enquirer@2.3.6: + /enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.10 + tapable: 2.2.1 + dev: false + + /enquirer@2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} engines: {node: '>=8.6'} dependencies: @@ -3198,6 +3401,7 @@ packages: /escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} + dev: true /escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -3377,10 +3581,6 @@ packages: signal-exit: 4.1.0 dev: true - /fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - dev: false - /fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} @@ -3408,15 +3608,11 @@ packages: universalify: 0.1.2 dev: true - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - /fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: true optional: true /fsevents@2.3.3: @@ -3426,9 +3622,6 @@ packages: requiresBuild: true optional: true - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -3469,12 +3662,6 @@ packages: dependencies: is-glob: 4.0.3 - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - /glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true @@ -3487,17 +3674,6 @@ packages: path-scurry: 1.11.1 dev: true - /glob@7.1.6: - resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} - deprecated: Glob versions prior to v9 are no longer supported - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -3549,12 +3725,6 @@ packages: engines: {node: '>=8'} dev: true - /hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - /hast-util-embedded@3.0.0: resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==} dependencies: @@ -3844,15 +4014,9 @@ packages: /import-meta-resolve@4.1.0: resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false /ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} @@ -3894,11 +4058,6 @@ packages: dependencies: binary-extensions: 2.2.0 - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.0 - /is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} dev: false @@ -4012,12 +4171,18 @@ packages: /jiti@1.21.0: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true + dev: false /jiti@2.4.0: resolution: {integrity: sha512-H5UpaUI+aHOqZXlYOaFP/8AzKsg+guWu+Pr3Y8i7+Y3zr1aXAvCvTAQ1RxSc6oVD8R8c7brgNtTVP91E7upH/g==} hasBin: true dev: true + /jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + dev: false + /js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true @@ -4081,16 +4246,107 @@ packages: engines: {node: '>= 8'} dev: false - /lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} + /lightningcss-darwin-arm64@1.29.1: + resolution: {integrity: sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /lightningcss-darwin-x64@1.29.1: + resolution: {integrity: sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /lightningcss-freebsd-x64@1.29.1: + resolution: {integrity: sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + /lightningcss-linux-arm-gnueabihf@1.29.1: + resolution: {integrity: sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /lightningcss-linux-arm64-gnu@1.29.1: + resolution: {integrity: sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /lightningcss-linux-arm64-musl@1.29.1: + resolution: {integrity: sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /lightningcss-linux-x64-gnu@1.29.1: + resolution: {integrity: sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /lightningcss-linux-x64-musl@1.29.1: + resolution: {integrity: sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /lightningcss-win32-arm64-msvc@1.29.1: + resolution: {integrity: sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + /lightningcss-win32-x64-msvc@1.29.1: + resolution: {integrity: sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + /lightningcss@1.29.1: + resolution: {integrity: sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==} + engines: {node: '>= 12.0.0'} + dependencies: + detect-libc: 1.0.3 + optionalDependencies: + lightningcss-darwin-arm64: 1.29.1 + lightningcss-darwin-x64: 1.29.1 + lightningcss-freebsd-x64: 1.29.1 + lightningcss-linux-arm-gnueabihf: 1.29.1 + lightningcss-linux-arm64-gnu: 1.29.1 + lightningcss-linux-arm64-musl: 1.29.1 + lightningcss-linux-x64-gnu: 1.29.1 + lightningcss-linux-x64-musl: 1.29.1 + lightningcss-win32-arm64-msvc: 1.29.1 + lightningcss-win32-x64-msvc: 1.29.1 /lilconfig@3.1.2: resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} engines: {node: '>=14'} - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true /linkedom@0.18.4: resolution: {integrity: sha512-JhLErxMIEOKByMi3fURXgI1fYOzR87L1Cn0+MI9GlMckFrqFZpV1SUGox1jcKtsKN3y6JgclcQf0FzZT//BuGw==} @@ -4745,11 +5001,6 @@ packages: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - /minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -4791,13 +5042,6 @@ packages: hasBin: true dev: true - /mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - /nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -4848,19 +5092,10 @@ packages: whatwg-url: 5.0.0 dev: true - /node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} - dev: false - /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - /normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - dev: false - /normalize-url@6.1.0: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} @@ -4875,14 +5110,6 @@ packages: dependencies: boolbase: 1.0.0 - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - /object-hash@3.0.0: - resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} - engines: {node: '>= 6'} - /ofetch@1.4.1: resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} dependencies: @@ -5042,18 +5269,11 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} dev: true - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - /path-scurry@1.11.1: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} @@ -5094,17 +5314,16 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} - /pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - /pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} - /pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} + /pixelmatch@6.0.0: + resolution: {integrity: sha512-FYpL4XiIWakTnIqLqvt3uN4L9B3TsuHIvhLILzTiJZMJUsGvmKNeL4H3b6I99LRyerK9W4IuOXw+N28AtRgK2g==} + hasBin: true + dependencies: + pngjs: 7.0.0 + dev: false /pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} @@ -5116,7 +5335,6 @@ packages: resolution: {integrity: sha512-lZmHlFQ0VYSpAs43dRq1/nJ9G/6SiTI7VPqidld9TDefL9tX87bTKExWZZUF5PeRyqtXqd8fQi2qmfIedkwsNQ==} engines: {node: '>=18'} hasBin: true - dev: true /playwright@1.45.0: resolution: {integrity: sha512-4z3ac3plDfYzGB6r0Q3LF8POPR20Z8D0aXcxbJvmfMgSSq1hkcgvFRXJk9rUq5H/MJ0Ktal869hhOdI/zUTeLA==} @@ -5126,43 +5344,11 @@ packages: playwright-core: 1.45.0 optionalDependencies: fsevents: 2.3.2 - dev: true - - /postcss-import@15.1.0(postcss@8.4.49): - resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} - engines: {node: '>=14.0.0'} - peerDependencies: - postcss: ^8.0.0 - dependencies: - postcss: 8.4.49 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.8 - /postcss-js@4.0.1(postcss@8.4.49): - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} - engines: {node: ^12 || ^14 || >= 16} - peerDependencies: - postcss: ^8.4.21 - dependencies: - camelcase-css: 2.0.1 - postcss: 8.4.49 - - /postcss-load-config@4.0.2(postcss@8.4.49): - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - dependencies: - lilconfig: 3.1.2 - postcss: 8.4.49 - yaml: 2.6.1 + /pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} + engines: {node: '>=14.19.0'} + dev: false /postcss-nested@6.0.1(postcss@8.4.49): resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} @@ -5172,6 +5358,7 @@ packages: dependencies: postcss: 8.4.49 postcss-selector-parser: 6.0.13 + dev: false /postcss-selector-parser@6.0.13: resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} @@ -5179,9 +5366,7 @@ packages: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: false /postcss@8.4.49: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} @@ -5305,11 +5490,6 @@ packages: strip-json-comments: 2.0.1 dev: false - /read-cache@1.0.0: - resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - dependencies: - pify: 2.3.0 - /read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} @@ -5561,14 +5741,6 @@ packages: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} dev: false - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - /responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} dependencies: @@ -6001,19 +6173,6 @@ packages: inline-style-parser: 0.2.4 dev: false - /sucrase@3.34.0: - resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} - engines: {node: '>=8'} - hasBin: true - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - commander: 4.1.1 - glob: 7.1.6 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.6 - ts-interface-checker: 0.1.13 - /suf-log@2.5.3: resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==} dependencies: @@ -6027,39 +6186,13 @@ packages: has-flag: 4.0.0 dev: true - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} + /tailwindcss@4.0.7: + resolution: {integrity: sha512-yH5bPPyapavo7L+547h3c4jcBXcrKwybQRjwdEIVAd9iXRvy/3T1CC6XSQEgZtRySjKfqvo3Cc0ZF1DTheuIdA==} - /tailwindcss@3.4.14: - resolution: {integrity: sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==} - engines: {node: '>=14.0.0'} - hasBin: true - dependencies: - '@alloc/quick-lru': 5.2.0 - arg: 5.0.2 - chokidar: 3.6.0 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.2 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.21.0 - lilconfig: 2.1.0 - micromatch: 4.0.8 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.1.1 - postcss: 8.4.49 - postcss-import: 15.1.0(postcss@8.4.49) - postcss-js: 4.0.1(postcss@8.4.49) - postcss-load-config: 4.0.2(postcss@8.4.49) - postcss-nested: 6.0.1(postcss@8.4.49) - postcss-selector-parser: 6.0.13 - resolve: 1.22.8 - sucrase: 3.34.0 - transitivePeerDependencies: - - ts-node + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: false /tar-fs@2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} @@ -6111,17 +6244,6 @@ packages: minimatch: 9.0.5 dev: true - /thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - dependencies: - thenify: 3.3.1 - - /thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - dependencies: - any-promise: 1.3.0 - /tiny-inflate@1.0.3: resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} dev: false @@ -6184,9 +6306,6 @@ packages: /trough@2.1.0: resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} - /ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - /tsconfck@3.1.4(typescript@5.6.3): resolution: {integrity: sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==} engines: {node: ^18 || >=20} @@ -6407,19 +6526,9 @@ packages: ofetch: 1.4.1 ufo: 1.5.4 - /update-browserslist-db@1.1.1(browserslist@4.24.2): - resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.24.2 - escalade: 3.2.0 - picocolors: 1.1.1 - dev: false - /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false /vfile-location@5.0.2: resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} @@ -6439,6 +6548,31 @@ packages: '@types/unist': 3.0.0 vfile-message: 4.0.2 + /vite-node@3.0.5: + resolution: {integrity: sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.6.0 + pathe: 2.0.2 + vite: 6.0.7 + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + dev: true + /vite-node@3.0.5(@types/node@18.16.19): resolution: {integrity: sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -6464,6 +6598,77 @@ packages: - yaml dev: true + /vite-node@3.0.5(lightningcss@1.29.1): + resolution: {integrity: sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.6.0 + pathe: 2.0.2 + vite: 6.0.7(lightningcss@1.29.1) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + dev: true + + /vite@6.0.7: + resolution: {integrity: sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + dependencies: + esbuild: 0.24.2 + postcss: 8.4.49 + rollup: 4.25.0 + optionalDependencies: + fsevents: 2.3.3 + /vite@6.0.7(@types/node@18.16.19): resolution: {integrity: sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -6511,6 +6716,54 @@ packages: optionalDependencies: fsevents: 2.3.3 + /vite@6.0.7(lightningcss@1.29.1): + resolution: {integrity: sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + dependencies: + esbuild: 0.24.2 + lightningcss: 1.29.1 + postcss: 8.4.49 + rollup: 4.25.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /vitefu@1.0.4(vite@6.0.7): resolution: {integrity: sha512-y6zEE3PQf6uu/Mt6DTJ9ih+kyJLr4XcSgHR2zUkM8SWDhuixEJxfJ6CZGMHh1Ec3vPLoEA0IHU5oWzVqw8ulow==} peerDependencies: @@ -6519,7 +6772,70 @@ packages: vite: optional: true dependencies: - vite: 6.0.7(@types/node@18.16.19) + vite: 6.0.7 + + /vitest@3.0.5: + resolution: {integrity: sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.0.5 + '@vitest/ui': 3.0.5 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@vitest/expect': 3.0.5 + '@vitest/mocker': 3.0.5(vite@6.0.7) + '@vitest/pretty-format': 3.0.5 + '@vitest/runner': 3.0.5 + '@vitest/snapshot': 3.0.5 + '@vitest/spy': 3.0.5 + '@vitest/utils': 3.0.5 + chai: 5.1.2 + debug: 4.4.0 + expect-type: 1.1.0 + magic-string: 0.30.17 + pathe: 2.0.2 + std-env: 3.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.0.7 + vite-node: 3.0.5 + why-is-node-running: 2.3.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + dev: true /vitest@3.0.5(@types/node@18.16.19): resolution: {integrity: sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==} @@ -6585,6 +6901,69 @@ packages: - yaml dev: true + /vitest@3.0.5(lightningcss@1.29.1): + resolution: {integrity: sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.0.5 + '@vitest/ui': 3.0.5 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@vitest/expect': 3.0.5 + '@vitest/mocker': 3.0.5(vite@6.0.7) + '@vitest/pretty-format': 3.0.5 + '@vitest/runner': 3.0.5 + '@vitest/snapshot': 3.0.5 + '@vitest/spy': 3.0.5 + '@vitest/utils': 3.0.5 + chai: 5.1.2 + debug: 4.4.0 + expect-type: 1.1.0 + magic-string: 0.30.17 + pathe: 2.0.2 + std-env: 3.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.0.7(lightningcss@1.29.1) + vite-node: 3.0.5(lightningcss@1.29.1) + why-is-node-running: 2.3.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + dev: true + /volar-service-css@0.0.62(@volar/language-service@2.4.10): resolution: {integrity: sha512-JwNyKsH3F8PuzZYuqPf+2e+4CTU8YoyUHEHVnoXNlrLe7wy9U3biomZ56llN69Ris7TTy/+DEX41yVxQpM4qvg==} peerDependencies: @@ -6917,6 +7296,7 @@ packages: resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} engines: {node: '>= 14'} hasBin: true + dev: true /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}