Remove legacy.astroFlavoredMarkdown (#5771)
* Remove legacy.astroFlavoredMarkdown * update vue mdx test * Add a changeset
This commit is contained in:
parent
9ef0c50427
commit
259a539d7d
109 changed files with 15 additions and 1870 deletions
9
.changeset/grumpy-days-yell.md
Normal file
9
.changeset/grumpy-days-yell.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
'astro': major
|
||||||
|
---
|
||||||
|
|
||||||
|
Removes support for astroFlavoredMarkdown
|
||||||
|
|
||||||
|
In 1.0 Astro moved the old Astro Flavored Markdown (also sometimes called Components in Markdown) to a legacy feature. This change removes the `legacy.astroFlavoredMarkdown` option completely.
|
||||||
|
|
||||||
|
In 2.0 this feature will not be available in Astro at all. We recommend migration to MDX for those were still using this feature in 1.x.
|
|
@ -3,8 +3,5 @@ import preact from '@astrojs/preact';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [preact({ compat: true })],
|
integrations: [preact({ compat: true })],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
layout: ../components/Layout.astro
|
|
||||||
setup: |
|
|
||||||
import Counter from '../components/Counter.jsx';
|
|
||||||
import PreactComponent from '../components/JSXComponent.jsx';
|
|
||||||
|
|
||||||
const someProps = {
|
|
||||||
count: 0,
|
|
||||||
};
|
|
||||||
---
|
|
||||||
|
|
||||||
<Counter id="server-only" {...someProps}>
|
|
||||||
# Hello, server!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-idle" {...someProps} client:idle>
|
|
||||||
# Hello, client:idle!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-load" {...someProps} client:load>
|
|
||||||
# Hello, client:load!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-visible" {...someProps} client:visible>
|
|
||||||
# Hello, client:visible!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-media" {...someProps} client:media="(max-width: 50em)">
|
|
||||||
# Hello, client:media!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<PreactComponent id="client-only" client:only="preact" />
|
|
|
@ -4,8 +4,5 @@ import mdx from '@astrojs/mdx';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [preact(), mdx()],
|
integrations: [preact(), mdx()],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
layout: ../components/Layout.astro
|
|
||||||
setup: |
|
|
||||||
import Counter from '../components/Counter.jsx';
|
|
||||||
import PreactComponent from '../components/JSXComponent.jsx';
|
|
||||||
|
|
||||||
const someProps = {
|
|
||||||
count: 0,
|
|
||||||
};
|
|
||||||
---
|
|
||||||
|
|
||||||
<Counter id="server-only" {...someProps}>
|
|
||||||
# Hello, server!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-idle" {...someProps} client:idle>
|
|
||||||
# Hello, client:idle!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-load" {...someProps} client:load>
|
|
||||||
# Hello, client:load!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-visible" {...someProps} client:visible>
|
|
||||||
# Hello, client:visible!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-media" {...someProps} client:media="(max-width: 50em)">
|
|
||||||
# Hello, client:media!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<PreactComponent id="client-only" client:only="preact" />
|
|
|
@ -4,8 +4,5 @@ import mdx from '@astrojs/mdx';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [react(), mdx()],
|
integrations: [react(), mdx()],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
layout: ../components/Layout.astro
|
|
||||||
setup: |
|
|
||||||
import Counter from '../components/Counter.jsx';
|
|
||||||
import ReactComponent from '../components/JSXComponent.jsx';
|
|
||||||
|
|
||||||
const someProps = {
|
|
||||||
count: 0,
|
|
||||||
};
|
|
||||||
---
|
|
||||||
|
|
||||||
<Counter id="server-only" {...someProps}>
|
|
||||||
# Hello, server!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-idle" {...someProps} client:idle>
|
|
||||||
# Hello, client:idle!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-load" {...someProps} client:load>
|
|
||||||
# Hello, client:load!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-visible" {...someProps} client:visible>
|
|
||||||
# Hello, client:visible!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-media" {...someProps} client:media="(max-width: 50em)">
|
|
||||||
# Hello, client:media!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<ReactComponent id="client-only" client:only="react" />
|
|
|
@ -4,8 +4,5 @@ import solid from '@astrojs/solid-js';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [solid(), mdx()],
|
integrations: [solid(), mdx()],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
layout: ../components/Layout.astro
|
|
||||||
setup: |
|
|
||||||
import Counter from '../components/Counter.jsx';
|
|
||||||
import SolidComponent from '../components/SolidComponent.jsx';
|
|
||||||
|
|
||||||
const someProps = {
|
|
||||||
count: 0,
|
|
||||||
};
|
|
||||||
---
|
|
||||||
|
|
||||||
<Counter id="server-only" {...someProps}>
|
|
||||||
# Hello, server!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-idle" {...someProps} client:idle>
|
|
||||||
# Hello, client:idle!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-load" {...someProps} client:load>
|
|
||||||
# Hello, client:load!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-visible" {...someProps} client:visible>
|
|
||||||
# Hello, client:visible!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-media" {...someProps} client:media="(max-width: 50em)">
|
|
||||||
# Hello, client:media!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<SolidComponent id="client-only" client:only="solid" />
|
|
|
@ -4,8 +4,5 @@ import mdx from '@astrojs/mdx';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [svelte(), mdx()],
|
integrations: [svelte(), mdx()],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
layout: ../components/Layout.astro
|
|
||||||
setup: |
|
|
||||||
import Counter from '../components/Counter.svelte';
|
|
||||||
import SvelteComponent from '../components/SvelteComponent.svelte';
|
|
||||||
|
|
||||||
const someProps = {
|
|
||||||
count: 0,
|
|
||||||
};
|
|
||||||
---
|
|
||||||
|
|
||||||
<Counter id="server-only" {...someProps}>
|
|
||||||
# Hello, server!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-idle" {...someProps} client:idle>
|
|
||||||
# Hello, client:idle!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-load" {...someProps} client:load>
|
|
||||||
# Hello, client:load!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-visible" {...someProps} client:visible>
|
|
||||||
# Hello, client:visible!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-media" {...someProps} client:media="(max-width: 50em)">
|
|
||||||
# Hello, client:media!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<SvelteComponent id="client-only" client:only="svelte" />
|
|
|
@ -4,9 +4,6 @@ import mdx from '@astrojs/mdx';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [
|
integrations: [
|
||||||
mdx(),
|
mdx(),
|
||||||
vue({
|
vue({
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
layout: ../components/Layout.astro
|
|
||||||
setup: |
|
|
||||||
import Counter from '../components/Counter.vue';
|
|
||||||
import VueComponent from '../components/VueComponent.vue';
|
|
||||||
|
|
||||||
const someProps = {
|
|
||||||
count: 0,
|
|
||||||
};
|
|
||||||
---
|
|
||||||
|
|
||||||
<Counter id="server-only" {...someProps}>
|
|
||||||
# Hello, server!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-idle" {...someProps} client:idle>
|
|
||||||
# Hello, client:idle!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-load" {...someProps} client:load>
|
|
||||||
# Hello, client:load!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-visible" {...someProps} client:visible>
|
|
||||||
# Hello, client:visible!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<Counter id="client-media" {...someProps} client:media="(max-width: 50em)">
|
|
||||||
# Hello, client:media!
|
|
||||||
</Counter>
|
|
||||||
|
|
||||||
<VueComponent id="client-only" client:only="vue" />
|
|
|
@ -14,11 +14,3 @@ test.describe('preact/compat components in Astro files', () => {
|
||||||
pageSourceFilePath: './src/pages/index.astro',
|
pageSourceFilePath: './src/pages/index.astro',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('preact/compat components in Markdown files', () => {
|
|
||||||
createTests({
|
|
||||||
...config,
|
|
||||||
pageUrl: '/markdown/',
|
|
||||||
pageSourceFilePath: './src/pages/markdown.md',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
|
@ -15,14 +15,6 @@ test.describe('Preact components in Astro files', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('Preact components in Markdown files', () => {
|
|
||||||
createTests({
|
|
||||||
...config,
|
|
||||||
pageUrl: '/markdown/',
|
|
||||||
pageSourceFilePath: './src/pages/markdown.md',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('Preact components in MDX files', () => {
|
test.describe('Preact components in MDX files', () => {
|
||||||
createTests({
|
createTests({
|
||||||
...config,
|
...config,
|
||||||
|
|
|
@ -16,14 +16,6 @@ test.describe('React components in Astro files', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('React components in Markdown files', () => {
|
|
||||||
createTests({
|
|
||||||
...config,
|
|
||||||
pageUrl: '/markdown/',
|
|
||||||
pageSourceFilePath: './src/pages/markdown.md',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('React components in MDX files', () => {
|
test.describe('React components in MDX files', () => {
|
||||||
createTests({
|
createTests({
|
||||||
...config,
|
...config,
|
||||||
|
|
|
@ -15,14 +15,6 @@ test.describe('Solid components in Astro files', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('Solid components in Markdown files', () => {
|
|
||||||
createTests({
|
|
||||||
...config,
|
|
||||||
pageUrl: '/markdown/',
|
|
||||||
pageSourceFilePath: './src/pages/markdown.md',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('Solid components in MDX files', () => {
|
test.describe('Solid components in MDX files', () => {
|
||||||
createTests({
|
createTests({
|
||||||
...config,
|
...config,
|
||||||
|
|
|
@ -16,14 +16,6 @@ test.describe('Svelte components in Astro files', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('Svelte components in Markdown files', () => {
|
|
||||||
createTests({
|
|
||||||
...config,
|
|
||||||
pageUrl: '/markdown/',
|
|
||||||
pageSourceFilePath: './src/pages/markdown.md',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('Svelte components in MDX files', () => {
|
test.describe('Svelte components in MDX files', () => {
|
||||||
createTests({
|
createTests({
|
||||||
...config,
|
...config,
|
||||||
|
|
|
@ -16,14 +16,6 @@ test.describe('Vue components in Astro files', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('Vue components in Markdown files', () => {
|
|
||||||
createTests({
|
|
||||||
...config,
|
|
||||||
pageUrl: '/markdown/',
|
|
||||||
pageSourceFilePath: './src/pages/markdown.md',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('Vue components in MDX files', () => {
|
test.describe('Vue components in MDX files', () => {
|
||||||
createTests({
|
createTests({
|
||||||
...config,
|
...config,
|
||||||
|
|
|
@ -870,30 +870,7 @@ export interface AstroUserConfig {
|
||||||
* These flags allow you to opt in to some deprecated or otherwise outdated behavior of Astro
|
* These flags allow you to opt in to some deprecated or otherwise outdated behavior of Astro
|
||||||
* in the latest version, so that you can continue to upgrade and take advantage of new Astro releases.
|
* in the latest version, so that you can continue to upgrade and take advantage of new Astro releases.
|
||||||
*/
|
*/
|
||||||
legacy?: {
|
legacy?: object;
|
||||||
/**
|
|
||||||
* @docs
|
|
||||||
* @name legacy.astroFlavoredMarkdown
|
|
||||||
* @type {boolean}
|
|
||||||
* @default `false`
|
|
||||||
* @version 1.0.0-rc.1
|
|
||||||
* @description
|
|
||||||
* Enable Astro's pre-v1.0 support for components and JSX expressions in `.md` (and alternative extensions for markdown files like ".markdown") Markdown files.
|
|
||||||
* In Astro `1.0.0-rc`, this original behavior was removed as the default, in favor of our new [MDX integration](https://docs.astro.build/en/guides/integrations-guide/mdx/).
|
|
||||||
*
|
|
||||||
* To enable this behavior, set `legacy.astroFlavoredMarkdown` to `true` in your [`astro.config.mjs` configuration file](https://docs.astro.build/en/guides/configuring-astro/#the-astro-config-file).
|
|
||||||
*
|
|
||||||
* ```js
|
|
||||||
* {
|
|
||||||
* legacy: {
|
|
||||||
* // Example: Add support for legacy Markdown features
|
|
||||||
* astroFlavoredMarkdown: true,
|
|
||||||
* },
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
astroFlavoredMarkdown?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @docs
|
* @docs
|
||||||
|
|
|
@ -349,7 +349,6 @@ async function generatePath(
|
||||||
logging,
|
logging,
|
||||||
markdown: {
|
markdown: {
|
||||||
...settings.config.markdown,
|
...settings.config.markdown,
|
||||||
isAstroFlavoredMd: settings.config.legacy.astroFlavoredMarkdown,
|
|
||||||
isExperimentalContentCollections: settings.config.experimental.contentCollections,
|
isExperimentalContentCollections: settings.config.experimental.contentCollections,
|
||||||
contentDir: getContentPaths(settings.config).contentDir,
|
contentDir: getContentPaths(settings.config).contentDir,
|
||||||
},
|
},
|
||||||
|
|
|
@ -210,7 +210,6 @@ function buildManifest(
|
||||||
base: settings.config.base,
|
base: settings.config.base,
|
||||||
markdown: {
|
markdown: {
|
||||||
...settings.config.markdown,
|
...settings.config.markdown,
|
||||||
isAstroFlavoredMd: settings.config.legacy.astroFlavoredMarkdown,
|
|
||||||
isExperimentalContentCollections: settings.config.experimental.contentCollections,
|
isExperimentalContentCollections: settings.config.experimental.contentCollections,
|
||||||
contentDir: getContentPaths(settings.config).contentDir,
|
contentDir: getContentPaths(settings.config).contentDir,
|
||||||
},
|
},
|
||||||
|
|
|
@ -36,9 +36,7 @@ const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = {
|
||||||
...markdownConfigDefaults,
|
...markdownConfigDefaults,
|
||||||
},
|
},
|
||||||
vite: {},
|
vite: {},
|
||||||
legacy: {
|
legacy: {},
|
||||||
astroFlavoredMarkdown: false,
|
|
||||||
},
|
|
||||||
experimental: {
|
experimental: {
|
||||||
contentCollections: false,
|
contentCollections: false,
|
||||||
},
|
},
|
||||||
|
@ -180,12 +178,7 @@ export const AstroConfigSchema = z.object({
|
||||||
.optional()
|
.optional()
|
||||||
.default({}),
|
.default({}),
|
||||||
legacy: z
|
legacy: z
|
||||||
.object({
|
.object({})
|
||||||
astroFlavoredMarkdown: z
|
|
||||||
.boolean()
|
|
||||||
.optional()
|
|
||||||
.default(ASTRO_CONFIG_DEFAULTS.legacy.astroFlavoredMarkdown),
|
|
||||||
})
|
|
||||||
.optional()
|
.optional()
|
||||||
.default({}),
|
.default({}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,7 +20,6 @@ import htmlVitePlugin from '../vite-plugin-html/index.js';
|
||||||
import astroIntegrationsContainerPlugin from '../vite-plugin-integrations-container/index.js';
|
import astroIntegrationsContainerPlugin from '../vite-plugin-integrations-container/index.js';
|
||||||
import jsxVitePlugin from '../vite-plugin-jsx/index.js';
|
import jsxVitePlugin from '../vite-plugin-jsx/index.js';
|
||||||
import astroLoadFallbackPlugin from '../vite-plugin-load-fallback/index.js';
|
import astroLoadFallbackPlugin from '../vite-plugin-load-fallback/index.js';
|
||||||
import legacyMarkdownVitePlugin from '../vite-plugin-markdown-legacy/index.js';
|
|
||||||
import markdownVitePlugin from '../vite-plugin-markdown/index.js';
|
import markdownVitePlugin from '../vite-plugin-markdown/index.js';
|
||||||
import astroScannerPlugin from '../vite-plugin-scanner/index.js';
|
import astroScannerPlugin from '../vite-plugin-scanner/index.js';
|
||||||
import astroScriptsPlugin from '../vite-plugin-scripts/index.js';
|
import astroScriptsPlugin from '../vite-plugin-scripts/index.js';
|
||||||
|
@ -110,9 +109,7 @@ export async function createVite(
|
||||||
// the build to run very slow as the filewatcher is triggered often.
|
// the build to run very slow as the filewatcher is triggered often.
|
||||||
mode !== 'build' && vitePluginAstroServer({ settings, logging, fs }),
|
mode !== 'build' && vitePluginAstroServer({ settings, logging, fs }),
|
||||||
envVitePlugin({ settings }),
|
envVitePlugin({ settings }),
|
||||||
settings.config.legacy.astroFlavoredMarkdown
|
markdownVitePlugin({ settings, logging }),
|
||||||
? legacyMarkdownVitePlugin({ settings, logging })
|
|
||||||
: markdownVitePlugin({ settings, logging }),
|
|
||||||
htmlVitePlugin(),
|
htmlVitePlugin(),
|
||||||
jsxVitePlugin({ settings, logging }),
|
jsxVitePlugin({ settings, logging }),
|
||||||
astroPostprocessVitePlugin({ settings }),
|
astroPostprocessVitePlugin({ settings }),
|
||||||
|
|
|
@ -24,7 +24,6 @@ export function createDevelopmentEnvironment(
|
||||||
logging,
|
logging,
|
||||||
markdown: {
|
markdown: {
|
||||||
...settings.config.markdown,
|
...settings.config.markdown,
|
||||||
isAstroFlavoredMd: settings.config.legacy.astroFlavoredMarkdown,
|
|
||||||
isExperimentalContentCollections: settings.config.experimental.contentCollections,
|
isExperimentalContentCollections: settings.config.experimental.contentCollections,
|
||||||
contentDir: getContentPaths(settings.config).contentDir,
|
contentDir: getContentPaths(settings.config).contentDir,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
# vite-plugin-markdown-legacy
|
|
||||||
|
|
||||||
Adds Markdown support to Vite, both at the top level as well as within `.astro` files.
|
|
|
@ -1,265 +0,0 @@
|
||||||
import { renderMarkdown } from '@astrojs/markdown-remark';
|
|
||||||
import fs from 'fs';
|
|
||||||
import matter from 'gray-matter';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import { Plugin, ResolvedConfig, transformWithEsbuild } from 'vite';
|
|
||||||
import type { AstroSettings } from '../@types/astro';
|
|
||||||
import { getContentPaths } from '../content/index.js';
|
|
||||||
import { pagesVirtualModuleId } from '../core/app/index.js';
|
|
||||||
import { cachedCompilation, CompileProps } from '../core/compile/index.js';
|
|
||||||
import { AstroErrorData, MarkdownError } from '../core/errors/index.js';
|
|
||||||
import type { LogOptions } from '../core/logger/core.js';
|
|
||||||
import { isMarkdownFile } from '../core/util.js';
|
|
||||||
import type { PluginMetadata as AstroPluginMetadata } from '../vite-plugin-astro/types';
|
|
||||||
import { getFileInfo, normalizeFilename } from '../vite-plugin-utils/index.js';
|
|
||||||
|
|
||||||
interface AstroPluginOptions {
|
|
||||||
settings: AstroSettings;
|
|
||||||
logging: LogOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MARKDOWN_IMPORT_FLAG = '?mdImport';
|
|
||||||
const MARKDOWN_CONTENT_FLAG = '?content';
|
|
||||||
|
|
||||||
function safeMatter(source: string, id: string) {
|
|
||||||
try {
|
|
||||||
return matter(source);
|
|
||||||
} catch (err: any) {
|
|
||||||
const markdownError = new MarkdownError({
|
|
||||||
code: AstroErrorData.UnknownMarkdownError.code,
|
|
||||||
message: err.message,
|
|
||||||
stack: err.stack,
|
|
||||||
location: {
|
|
||||||
file: id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (err.name === 'YAMLException') {
|
|
||||||
markdownError.setErrorCode(AstroErrorData.MarkdownFrontmatterParseError.code);
|
|
||||||
markdownError.setLocation({
|
|
||||||
file: id,
|
|
||||||
line: err.mark.line,
|
|
||||||
column: err.mark.column,
|
|
||||||
});
|
|
||||||
|
|
||||||
markdownError.setMessage(err.reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw markdownError;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Both end up connecting a `load()` hook to the Astro compiler, and share some copy-paste
|
|
||||||
// logic in how that is done.
|
|
||||||
export default function markdown({ settings }: AstroPluginOptions): Plugin {
|
|
||||||
const { config } = settings;
|
|
||||||
|
|
||||||
// Weird Vite behavior: Vite seems to use a fake "index.html" importer when you
|
|
||||||
// have `enforce: pre`. This can probably be removed once the vite issue is fixed.
|
|
||||||
// see: https://github.com/vitejs/vite/issues/5981
|
|
||||||
const fakeRootImporter = fileURLToPath(new URL('index.html', config.root));
|
|
||||||
function isRootImport(importer: string | undefined) {
|
|
||||||
if (!importer) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (importer === fakeRootImporter) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (importer === '\0' + pagesVirtualModuleId) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let resolvedConfig: ResolvedConfig;
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: 'astro:markdown',
|
|
||||||
enforce: 'pre',
|
|
||||||
async resolveId(id, importer, options) {
|
|
||||||
// Resolve any .md (or alternative extensions of markdown files like .markdown) files with the `?content` cache buster. This should only come from
|
|
||||||
// an already-resolved JS module wrapper. Needed to prevent infinite loops in Vite.
|
|
||||||
// Unclear if this is expected or if cache busting is just working around a Vite bug.
|
|
||||||
if (isMarkdownFile(id, { suffix: MARKDOWN_CONTENT_FLAG })) {
|
|
||||||
const resolvedId = await this.resolve(id, importer, { skipSelf: true, ...options });
|
|
||||||
return resolvedId?.id.replace(MARKDOWN_CONTENT_FLAG, '');
|
|
||||||
}
|
|
||||||
// If the markdown file is imported from another file via ESM, resolve a JS representation
|
|
||||||
// that defers the markdown -> HTML rendering until it is needed. This is especially useful
|
|
||||||
// when fetching and then filtering many markdown files, like with import.meta.glob() or Astro.glob().
|
|
||||||
// Otherwise, resolve directly to the actual component.
|
|
||||||
if (isMarkdownFile(id) && !isRootImport(importer)) {
|
|
||||||
const resolvedId = await this.resolve(id, importer, { skipSelf: true, ...options });
|
|
||||||
if (resolvedId) {
|
|
||||||
return resolvedId.id + MARKDOWN_IMPORT_FLAG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// In all other cases, we do nothing and rely on normal Vite resolution.
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
async load(id, opts) {
|
|
||||||
// A markdown file has been imported via ESM!
|
|
||||||
// Return the file's JS representation, including all Markdown
|
|
||||||
// frontmatter and a deferred `import() of the compiled markdown content.
|
|
||||||
if (isMarkdownFile(id, { suffix: MARKDOWN_IMPORT_FLAG })) {
|
|
||||||
const { fileId, fileUrl } = getFileInfo(id, config);
|
|
||||||
|
|
||||||
const source = await fs.promises.readFile(fileId, 'utf8');
|
|
||||||
const { data: frontmatter, content: rawContent } = safeMatter(source, fileId);
|
|
||||||
return {
|
|
||||||
code: `
|
|
||||||
// Static
|
|
||||||
export const frontmatter = ${escapeViteEnvReferences(JSON.stringify(frontmatter))};
|
|
||||||
export const file = ${JSON.stringify(fileId)};
|
|
||||||
export const url = ${JSON.stringify(fileUrl)};
|
|
||||||
export function rawContent() {
|
|
||||||
return ${escapeViteEnvReferences(JSON.stringify(rawContent))};
|
|
||||||
}
|
|
||||||
export async function compiledContent() {
|
|
||||||
return load().then((m) => m.compiledContent());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deferred
|
|
||||||
export default async function load() {
|
|
||||||
return (await import(${JSON.stringify(fileId + MARKDOWN_CONTENT_FLAG)}));
|
|
||||||
}
|
|
||||||
export function Content(...args) {
|
|
||||||
return load().then((m) => m.default(...args));
|
|
||||||
}
|
|
||||||
Content.isAstroComponentFactory = true;
|
|
||||||
export function getHeadings() {
|
|
||||||
return load().then((m) => m.metadata.headings);
|
|
||||||
}
|
|
||||||
export function getHeaders() {
|
|
||||||
console.warn('getHeaders() have been deprecated. Use getHeadings() function instead.');
|
|
||||||
return load().then((m) => m.metadata.headings);
|
|
||||||
};`,
|
|
||||||
map: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// A markdown file is being rendered! This markdown file was either imported
|
|
||||||
// directly as a page in Vite, or it was a deferred render from a JS module.
|
|
||||||
// This returns the compiled markdown -> astro component that renders to HTML.
|
|
||||||
if (isMarkdownFile(id)) {
|
|
||||||
const filename = normalizeFilename(id, config);
|
|
||||||
const source = await fs.promises.readFile(filename, 'utf8');
|
|
||||||
const renderOpts = config.markdown;
|
|
||||||
|
|
||||||
const fileUrl = new URL(`file://${filename}`);
|
|
||||||
|
|
||||||
// Extract special frontmatter keys
|
|
||||||
let { data: frontmatter, content: markdownContent } = safeMatter(source, filename);
|
|
||||||
|
|
||||||
// Turn HTML comments into JS comments while preventing nested `*/` sequences
|
|
||||||
// from ending the JS comment by injecting a zero-width space
|
|
||||||
// Inside code blocks, this is removed during renderMarkdown by the remark-escape plugin.
|
|
||||||
markdownContent = markdownContent.replace(
|
|
||||||
/<\s*!--([^-->]*)(.*?)-->/gs,
|
|
||||||
(whole) => `{/*${whole.replace(/\*\//g, '*\u200b/')}*/}`
|
|
||||||
);
|
|
||||||
|
|
||||||
let renderResult = await renderMarkdown(markdownContent, {
|
|
||||||
...renderOpts,
|
|
||||||
fileURL: fileUrl,
|
|
||||||
isAstroFlavoredMd: true,
|
|
||||||
isExperimentalContentCollections: settings.config.experimental.contentCollections,
|
|
||||||
contentDir: getContentPaths(settings.config).contentDir,
|
|
||||||
} as any);
|
|
||||||
let { code: astroResult, metadata } = renderResult;
|
|
||||||
const { layout = '', components = '', setup = '', ...content } = frontmatter;
|
|
||||||
content.astro = metadata;
|
|
||||||
content.url = getFileInfo(id, config).fileUrl;
|
|
||||||
content.file = filename;
|
|
||||||
|
|
||||||
const prelude = `---
|
|
||||||
import Slugger from 'github-slugger';
|
|
||||||
${layout ? `import Layout from ${JSON.stringify(layout)};` : ''}
|
|
||||||
${components ? `import * from ${JSON.stringify(components)};` : ''}
|
|
||||||
${setup}
|
|
||||||
|
|
||||||
const slugger = new Slugger();
|
|
||||||
function $$slug(value) {
|
|
||||||
return slugger.slug(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const $$content = ${JSON.stringify(content)};
|
|
||||||
|
|
||||||
Object.defineProperty($$content.astro, 'headers', {
|
|
||||||
get() {
|
|
||||||
console.warn('[${JSON.stringify(id)}] content.astro.headers is now content.astro.headings.');
|
|
||||||
return this.headings;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
---`;
|
|
||||||
|
|
||||||
const imports = `${layout ? `import Layout from ${JSON.stringify(layout)};` : ''}
|
|
||||||
${setup}`.trim();
|
|
||||||
|
|
||||||
// If the user imported "Layout", wrap the content in a Layout
|
|
||||||
if (/\bLayout\b/.test(imports)) {
|
|
||||||
astroResult = `${prelude}\n<Layout content={$$content}>\n\n${astroResult}\n\n</Layout>`;
|
|
||||||
} else {
|
|
||||||
// Note: without a Layout, we need to inject `head` manually so `maybeRenderHead` runs
|
|
||||||
astroResult = `${prelude}\n<head></head>${astroResult}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform from `.astro` to valid `.ts`
|
|
||||||
const compileProps: CompileProps = {
|
|
||||||
astroConfig: config,
|
|
||||||
viteConfig: resolvedConfig,
|
|
||||||
filename,
|
|
||||||
source: astroResult,
|
|
||||||
id,
|
|
||||||
};
|
|
||||||
|
|
||||||
let transformResult = await cachedCompilation(compileProps);
|
|
||||||
let { code: tsResult } = transformResult;
|
|
||||||
|
|
||||||
tsResult = `\nexport const metadata = ${JSON.stringify(metadata)};
|
|
||||||
export const frontmatter = ${JSON.stringify(content)};
|
|
||||||
export function rawContent() {
|
|
||||||
return ${JSON.stringify(markdownContent)};
|
|
||||||
}
|
|
||||||
export function compiledContent() {
|
|
||||||
return ${JSON.stringify(renderResult.metadata.html)};
|
|
||||||
}
|
|
||||||
${tsResult}`;
|
|
||||||
|
|
||||||
// Compile from `.ts` to `.js`
|
|
||||||
const { code } = await transformWithEsbuild(tsResult, id, {
|
|
||||||
loader: 'ts',
|
|
||||||
sourcemap: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const astroMetadata: AstroPluginMetadata['astro'] = {
|
|
||||||
clientOnlyComponents: transformResult.clientOnlyComponents,
|
|
||||||
hydratedComponents: transformResult.hydratedComponents,
|
|
||||||
scripts: transformResult.scripts,
|
|
||||||
propagation: 'none',
|
|
||||||
pageOptions: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
code: escapeViteEnvReferences(code),
|
|
||||||
map: null,
|
|
||||||
meta: {
|
|
||||||
astro: astroMetadata,
|
|
||||||
vite: {
|
|
||||||
lang: 'ts',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts the first dot in `import.meta.env` to its Unicode escape sequence,
|
|
||||||
// which prevents Vite from replacing strings like `import.meta.env.SITE`
|
|
||||||
// in our JS representation of loaded Markdown files
|
|
||||||
function escapeViteEnvReferences(code: string) {
|
|
||||||
return code.replace(/import\.meta\.env/g, 'import\\u002Emeta.env');
|
|
||||||
}
|
|
|
@ -91,7 +91,7 @@ export default function markdown({ settings, logging }: AstroPluginOptions): Plu
|
||||||
warn(
|
warn(
|
||||||
logging,
|
logging,
|
||||||
'markdown',
|
'markdown',
|
||||||
`[${id}] Astro now supports MDX! Support for components in ".md" (or alternative extensions like ".markdown") files using the "setup" frontmatter is no longer enabled by default. Migrate this file to MDX or add the "legacy.astroFlavoredMarkdown" config flag to re-enable support.`
|
`[${id}] Astro now supports MDX! Support for components in ".md" (or alternative extensions like ".markdown") files using the "setup" frontmatter is no longer enabled by default. Migrate this file to MDX.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
import { expect } from 'chai';
|
|
||||||
import * as cheerio from 'cheerio';
|
|
||||||
import { loadFixture } from './test-utils.js';
|
|
||||||
|
|
||||||
let fixture;
|
|
||||||
const IMPORTED_ASTRO_COMPONENT_ID = 'imported-astro-component';
|
|
||||||
|
|
||||||
describe('Imported markdown CSS', function () {
|
|
||||||
before(async () => {
|
|
||||||
fixture = await loadFixture({ root: './fixtures/astro-markdown-css/' });
|
|
||||||
});
|
|
||||||
describe('build', () => {
|
|
||||||
let $;
|
|
||||||
let bundledCSS;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
this.timeout(45000); // test needs a little more time in CI
|
|
||||||
await fixture.build();
|
|
||||||
|
|
||||||
// get bundled CSS (will be hashed, hence DOM query)
|
|
||||||
const html = await fixture.readFile('/index.html');
|
|
||||||
$ = cheerio.load(html);
|
|
||||||
const bundledCSSHREF = $('link[rel=stylesheet][href^=/assets/]').attr('href');
|
|
||||||
bundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Compiles styles for Astro components within imported markdown', () => {
|
|
||||||
const importedAstroComponent = $(`#${IMPORTED_ASTRO_COMPONENT_ID}`)?.[0];
|
|
||||||
expect(importedAstroComponent?.name).to.equal('h2');
|
|
||||||
const cssClass = $(importedAstroComponent).attr('class')?.split(/\s+/)?.[0];
|
|
||||||
|
|
||||||
expect(bundledCSS).to.include(`h2:where(.${cssClass}){color:#00f}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('dev', () => {
|
|
||||||
let devServer;
|
|
||||||
let html;
|
|
||||||
let $;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
devServer = await fixture.startDevServer();
|
|
||||||
html = await fixture.fetch('/').then((res) => res.text());
|
|
||||||
$ = cheerio.load(html);
|
|
||||||
});
|
|
||||||
|
|
||||||
after(async () => {
|
|
||||||
await devServer.stop();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Compiles styles for Astro components within imported markdown', async () => {
|
|
||||||
const importedAstroComponent = $(`#${IMPORTED_ASTRO_COMPONENT_ID}`)?.[0];
|
|
||||||
expect(importedAstroComponent?.name).to.equal('h2');
|
|
||||||
const cssClass = $(importedAstroComponent).attr('class')?.split(/\s+/)?.[0];
|
|
||||||
|
|
||||||
const allInjectedStyles = $('style').text().replace(/\s*/g, '');
|
|
||||||
expect(allInjectedStyles).to.include(`h2:where(.${cssClass}){color:#00f}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -14,19 +14,6 @@ describe('Astro Markdown', () => {
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Leaves JSX expressions unprocessed', async () => {
|
|
||||||
const html = await fixture.readFile('/jsx-expressions/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h2').html()).to.equal('{frontmatter.title}');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Leaves JSX components un-transformed', async () => {
|
|
||||||
const html = await fixture.readFile('/components/index.html');
|
|
||||||
|
|
||||||
expect(html).to.include('<counter client:load="" count="{0}">');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Exposes raw markdown content', async () => {
|
it('Exposes raw markdown content', async () => {
|
||||||
const { raw } = JSON.parse(await fixture.readFile('/raw-content.json'));
|
const { raw } = JSON.parse(await fixture.readFile('/raw-content.json'));
|
||||||
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
import { defineConfig } from 'astro/config';
|
|
||||||
|
|
||||||
// https://astro.build/config
|
|
||||||
export default defineConfig({
|
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: []
|
|
||||||
});
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@test/astro-markdown-css",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"build": "astro build",
|
|
||||||
"dev": "astro dev"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"astro": "workspace:*"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
<h2 id="imported-astro-component">I'm a visual!</h2>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
h2 {
|
|
||||||
color: #00f;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
setup: import Visual from '../components/Visual.astro'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Example markdown document, with a Visual
|
|
||||||
|
|
||||||
<Visual />
|
|
||||||
<Visual />
|
|
||||||
<Visual />
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
setup: import Visual from '../components/Visual.astro'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Example markdown document, with a more Visuals
|
|
||||||
|
|
||||||
<Visual />
|
|
||||||
<Visual />
|
|
||||||
<Visual />
|
|
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
const markdownDocs = await Astro.glob('../markdown/*.md')
|
|
||||||
const article2 = await import('../markdown/article2.md')
|
|
||||||
---
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width" />
|
|
||||||
<title>Astro</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{markdownDocs.map(markdownDoc => <><h2>{markdownDoc.url}</h2><markdownDoc.Content /></>)}
|
|
||||||
<article2.Content />
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,5 +0,0 @@
|
||||||
---
|
|
||||||
setup: import Counter from '../components/Counter.svelte'
|
|
||||||
---
|
|
||||||
|
|
||||||
<Counter client:load count={0}></Counter>
|
|
|
@ -1,13 +0,0 @@
|
||||||
---
|
|
||||||
title: Blog Post with JSX expressions
|
|
||||||
paragraph: JSX at the start of the line!
|
|
||||||
list: ['test-1', 'test-2', 'test-3']
|
|
||||||
---
|
|
||||||
|
|
||||||
## {frontmatter.title}
|
|
||||||
|
|
||||||
{frontmatter.paragraph}
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
{frontmatter.list.map(item => <li id={item}>{item}</li>)}
|
|
||||||
</ul>
|
|
|
@ -2,8 +2,5 @@ import { defineConfig } from 'astro/config';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: []
|
integrations: []
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
setup: |
|
|
||||||
import foo from '../foo.js'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Testing
|
|
||||||
|
|
||||||
## { foo() }
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { defineConfig } from 'astro/config';
|
|
||||||
import preact from '@astrojs/preact';
|
|
||||||
import svelte from "@astrojs/svelte";
|
|
||||||
|
|
||||||
// https://astro.build/config
|
|
||||||
export default defineConfig({
|
|
||||||
integrations: [preact(), svelte()],
|
|
||||||
site: 'https://astro.build/',
|
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@test/astro-markdown",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@astrojs/preact": "workspace:*",
|
|
||||||
"@astrojs/svelte": "workspace:*",
|
|
||||||
"astro": "workspace:*",
|
|
||||||
"preact": "^10.11.0",
|
|
||||||
"svelte": "^3.48.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
import { h } from 'preact';
|
|
||||||
import { useState } from 'preact/hooks';
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
const [count, setCount] = useState(0);
|
|
||||||
return <button onClick={() => setCount(count + 1)}>{count}</button>;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { h } from 'preact';
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
return <div id="test">Testing</div>;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { h } from 'preact';
|
|
||||||
|
|
||||||
export default function ({ name }) {
|
|
||||||
return <div id="test">Hello {name}</div>;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
<article>
|
|
||||||
<section class="fragmentSlot">
|
|
||||||
<slot name="fragmentSlot">❌ Missing content for slot "fragmentSlot"</slot>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="pSlot">
|
|
||||||
<slot name="pSlot">❌ Missing content for slot "pSlot"</slot>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="defaultSlot">
|
|
||||||
<slot>❌ Missing content for default slot</slot>
|
|
||||||
</section>
|
|
||||||
</article>
|
|
|
@ -1,11 +0,0 @@
|
||||||
<script>
|
|
||||||
let cool = false
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<button on:click={() => cool = true}>This is cool right? {cool}</button>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
button {
|
|
||||||
background: green;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { h } from 'preact';
|
|
||||||
|
|
||||||
const TextBlock = ({
|
|
||||||
title,
|
|
||||||
children,
|
|
||||||
noPadding = false,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`${
|
|
||||||
noPadding ? "" : "md:px-2 lg:px-4"
|
|
||||||
} flex-1 prose prose-headings:font-grotesk`}
|
|
||||||
>
|
|
||||||
<h3>{title}</h3>
|
|
||||||
<p>{children}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TextBlock;
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Counter from './Counter';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
Counter
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
This should have `nospace` around it.
|
|
||||||
|
|
||||||
This should have <code class="custom-class">nospace</code> around it.
|
|
|
@ -1,6 +0,0 @@
|
||||||
---
|
|
||||||
---
|
|
||||||
|
|
||||||
## Plain jane
|
|
||||||
|
|
||||||
I am plain markdown!
|
|
|
@ -1,17 +0,0 @@
|
||||||
---
|
|
||||||
setup: |
|
|
||||||
import Counter from '../components/Counter.jsx'
|
|
||||||
import Hello from '../components/Hello.jsx'
|
|
||||||
import SvelteButton from '../components/SvelteButton.svelte'
|
|
||||||
---
|
|
||||||
|
|
||||||
## With components
|
|
||||||
|
|
||||||
### Non-hydrated
|
|
||||||
|
|
||||||
<Hello name="Astro Naut" />
|
|
||||||
|
|
||||||
### Hydrated
|
|
||||||
|
|
||||||
<Counter client:load />
|
|
||||||
<SvelteButton client:load />
|
|
|
@ -1,10 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Head Stuff -->
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,17 +0,0 @@
|
||||||
---
|
|
||||||
interface Props {
|
|
||||||
url: string;
|
|
||||||
file: string;
|
|
||||||
title: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { title, url, file } = Astro.props.content as Props;
|
|
||||||
---
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<div id="title">{title}</div>
|
|
||||||
<div id="url">{url}</div>
|
|
||||||
<div id="file">{file}</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,12 +0,0 @@
|
||||||
---
|
|
||||||
setup: import TextBlock from '../components/TextBlock'
|
|
||||||
---
|
|
||||||
{/* https://github.com/withastro/astro/issues/3319 */}
|
|
||||||
|
|
||||||
<TextBlock title="Hello world!" noPadding>
|
|
||||||
<ul class="not-prose">
|
|
||||||
<li>A</li>
|
|
||||||
<li>B</li>
|
|
||||||
<li>C</li>
|
|
||||||
</ul>
|
|
||||||
</TextBlock>
|
|
|
@ -1,7 +0,0 @@
|
||||||
---
|
|
||||||
const content = await Astro.glob('../content/*.md');
|
|
||||||
---
|
|
||||||
|
|
||||||
<div>
|
|
||||||
{content.map(({ Content }) => <Content />)}
|
|
||||||
</div>
|
|
|
@ -1,16 +0,0 @@
|
||||||
# Inline code blocks
|
|
||||||
|
|
||||||
`<script>` tags in **Astro** components are now built,
|
|
||||||
bundled and optimized by default.
|
|
||||||
|
|
||||||
> Markdown formatting still works between tags in inline code blocks.
|
|
||||||
|
|
||||||
We can also use closing `</script>` tags without any problems.
|
|
||||||
|
|
||||||
# Fenced code blocks
|
|
||||||
|
|
||||||
```html
|
|
||||||
<body>
|
|
||||||
<div>This should also work without any problems.</div>
|
|
||||||
</body>
|
|
||||||
```
|
|
|
@ -1,23 +0,0 @@
|
||||||
<!--
|
|
||||||
HTML comments with */ inside!
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
```js
|
|
||||||
/**
|
|
||||||
* It even works inside nested fenced code blocks!
|
|
||||||
*/
|
|
||||||
function test() {
|
|
||||||
/* Yay */
|
|
||||||
return 'Nice!';
|
|
||||||
}
|
|
||||||
```
|
|
||||||
-->
|
|
||||||
|
|
||||||
```
|
|
||||||
<!-- HTML comments in code fence -->
|
|
||||||
```
|
|
||||||
|
|
||||||
`<!-- HTML comments in code -->`
|
|
||||||
|
|
||||||
# It still works!
|
|
|
@ -1,2 +0,0 @@
|
||||||
<!-- HTML comments! -->
|
|
||||||
# It works!
|
|
|
@ -1,14 +0,0 @@
|
||||||
---
|
|
||||||
title: My Blog Post
|
|
||||||
layout: ../layouts/content.astro
|
|
||||||
---
|
|
||||||
|
|
||||||
## Title
|
|
||||||
|
|
||||||
Hello world
|
|
||||||
|
|
||||||
With this in the body ---
|
|
||||||
|
|
||||||
## Another
|
|
||||||
|
|
||||||
more content
|
|
|
@ -1,20 +0,0 @@
|
||||||
---
|
|
||||||
title: My Blog Post
|
|
||||||
layout: ../layouts/content.astro
|
|
||||||
---
|
|
||||||
|
|
||||||
## Title
|
|
||||||
|
|
||||||
Hello world
|
|
||||||
|
|
||||||
With this in the body ---
|
|
||||||
|
|
||||||
## Another
|
|
||||||
|
|
||||||
more content
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
<pre></pre>
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
import Layout from '../../layouts/content.astro'
|
|
||||||
|
|
||||||
const posts = await Astro.glob('../../imported-md/*.md')
|
|
||||||
---
|
|
||||||
|
|
||||||
<Layout>
|
|
||||||
{posts.map(({ Content }) => <Content />)}
|
|
||||||
</Layout>
|
|
|
@ -1,13 +0,0 @@
|
||||||
---
|
|
||||||
title: Blog Post with JSX expressions
|
|
||||||
paragraph: JSX at the start of the line!
|
|
||||||
list: ['test-1', 'test-2', 'test-3']
|
|
||||||
---
|
|
||||||
|
|
||||||
## {frontmatter.title}
|
|
||||||
|
|
||||||
{frontmatter.paragraph}
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
{frontmatter.list.map(item => <li id={item}>{item}</li>)}
|
|
||||||
</ul>
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: 'Hello world!'
|
|
||||||
layout: '../layouts/layout-props.astro'
|
|
||||||
---
|
|
|
@ -1,7 +0,0 @@
|
||||||
---
|
|
||||||
setup: import ns from '../components/index.js';
|
|
||||||
---
|
|
||||||
|
|
||||||
# Hello Namespace!
|
|
||||||
|
|
||||||
<ns.Counter>Click me!</ns.Counter>
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { rawContent, compiledContent } from '../imported-md/with-components.md';
|
|
||||||
|
|
||||||
export async function get() {
|
|
||||||
return {
|
|
||||||
body: JSON.stringify({
|
|
||||||
raw: rawContent(),
|
|
||||||
compiled: await compiledContent(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
# Test
|
|
||||||
|
|
||||||
## Let's try a script...
|
|
||||||
|
|
||||||
This should work!
|
|
||||||
|
|
||||||
<script src="/src/scripts/test.js" />
|
|
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
layout: ../layouts/content.astro
|
|
||||||
setup: import SlotComponent from '../components/SlotComponent.astro';
|
|
||||||
---
|
|
||||||
|
|
||||||
# Component with slot contents in children
|
|
||||||
|
|
||||||
<SlotComponent>
|
|
||||||
<div>4: Div in default slot</div>
|
|
||||||
<Fragment slot="fragmentSlot">
|
|
||||||
<div>1: Div in fragmentSlot</div>
|
|
||||||
<p>2: Paragraph in fragmentSlot</p>
|
|
||||||
</Fragment>
|
|
||||||
<Fragment><p>5: Paragraph in fragment in default slot</p></Fragment>
|
|
||||||
6: Regular text in default slot
|
|
||||||
<p slot="pSlot" title="hello">3: p with title as pSlot</p>
|
|
||||||
</SlotComponent>
|
|
||||||
|
|
||||||
# Component with nested component in children
|
|
||||||
|
|
||||||
<SlotComponent>
|
|
||||||
<p slot="pSlot">2: pSlot</p>
|
|
||||||
<SlotComponent>
|
|
||||||
<p slot="pSlot">4: nested pSlot</p>
|
|
||||||
5: nested text in default slot
|
|
||||||
<Fragment slot="fragmentSlot">3: nested fragmentSlot</Fragment>
|
|
||||||
</SlotComponent>
|
|
||||||
<Fragment slot="fragmentSlot">1: fragmentSlot</Fragment>
|
|
||||||
</SlotComponent>
|
|
||||||
|
|
||||||
# Missing content due to empty children
|
|
||||||
|
|
||||||
<SlotComponent>
|
|
||||||
</SlotComponent>
|
|
||||||
|
|
||||||
# Missing content due to self-closing tag
|
|
||||||
|
|
||||||
<SlotComponent/>
|
|
|
@ -1,7 +0,0 @@
|
||||||
---
|
|
||||||
title: My Blog Post
|
|
||||||
---
|
|
||||||
|
|
||||||
# {frontmatter.title}
|
|
||||||
|
|
||||||
Hello world
|
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
title: Referencing Vite Env Vars like import.meta.env.SITE, import.meta.env.TITLE and import.meta.env
|
|
||||||
layout: ../layouts/content.astro
|
|
||||||
---
|
|
||||||
|
|
||||||
## Referencing the full name of Vite env vars
|
|
||||||
|
|
||||||
You can get the configured site URL with `import.meta.env.SITE`.
|
|
||||||
|
|
||||||
The variable `import.meta.env.TITLE` is not configured.
|
|
||||||
|
|
||||||
You can reference all env vars through `import.meta.env`.
|
|
||||||
|
|
||||||
This should also work outside of code blocks:
|
|
||||||
- import.meta.env.SITE
|
|
||||||
- import.meta.env.TITLE
|
|
||||||
- import.meta.env
|
|
||||||
|
|
||||||
## Usage in fenced code blocks with syntax highlighting
|
|
||||||
|
|
||||||
```js
|
|
||||||
// src/pages/rss.xml.js
|
|
||||||
import rss from '@astrojs/rss';
|
|
||||||
|
|
||||||
export const get = () => rss({
|
|
||||||
// Use Vite env vars with import.meta.env
|
|
||||||
site: import.meta.env.SITE,
|
|
||||||
title: import.meta.env.TITLE,
|
|
||||||
items: import.meta.glob('./**/*.md'),
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage in frontmatter
|
|
||||||
|
|
||||||
> frontmatter.title: {frontmatter.title}
|
|
|
@ -1 +0,0 @@
|
||||||
console.log("Hello world");
|
|
|
@ -1,7 +0,0 @@
|
||||||
import { defineConfig } from 'astro/config';
|
|
||||||
import vue from '@astrojs/vue';
|
|
||||||
|
|
||||||
// https://astro.build/config
|
|
||||||
export default defineConfig({
|
|
||||||
integrations: [vue()],
|
|
||||||
});
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@test/legacy-build",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@astrojs/vue": "workspace:*",
|
|
||||||
"astro": "workspace:*",
|
|
||||||
"preact": "~10.6.6"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
<template>
|
|
||||||
<div id="vue" class="counter">
|
|
||||||
<button @click="subtract()">-</button>
|
|
||||||
<pre>{{ count }}</pre>
|
|
||||||
<button @click="add()">+</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
export default {
|
|
||||||
setup() {
|
|
||||||
const count = ref(0);
|
|
||||||
const add = () => (count.value = count.value + 1);
|
|
||||||
const subtract = () => (count.value = count.value - 1);
|
|
||||||
|
|
||||||
return {
|
|
||||||
count,
|
|
||||||
add,
|
|
||||||
subtract,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
|
@ -1,20 +0,0 @@
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
greeting: 'Hello World!',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<p class="greeting">{{ greeting }}</p>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.greeting {
|
|
||||||
color: red;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,13 +0,0 @@
|
||||||
<script type="module" hoist>
|
|
||||||
import { h, render } from 'preact';
|
|
||||||
|
|
||||||
|
|
||||||
const mount = document.querySelector('#inline-hoist');
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return h('strong', null, 'Hello again');
|
|
||||||
}
|
|
||||||
|
|
||||||
render(h(App), mount);
|
|
||||||
</script>
|
|
||||||
<div id="inline-hoist"></div>
|
|
|
@ -1,18 +0,0 @@
|
||||||
---
|
|
||||||
import Greeting from '../components/Greeting.vue';
|
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
|
||||||
const allPokemon = [{name: 'Charmander'}, {name: 'Charmander'}, {name: 'Charizard'}];
|
|
||||||
return allPokemon.map(pokemon => ({params: {pokemon: pokemon.name}, props: {pokemon}}));
|
|
||||||
}
|
|
||||||
---
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Hello</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1>{Astro.props.pokemon.name}</h1>
|
|
||||||
<Greeting client:load />
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,60 +0,0 @@
|
||||||
---
|
|
||||||
import Greeting from '../components/Greeting.vue';
|
|
||||||
import Counter from '../components/Counter.vue';
|
|
||||||
import InlineHoisted from '../components/InlineHoisted.astro';
|
|
||||||
---
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Demo app</title>
|
|
||||||
<style>
|
|
||||||
h1 {
|
|
||||||
color: salmon;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<style lang="scss">
|
|
||||||
@import "../styles/_global.scss";
|
|
||||||
h2 {
|
|
||||||
color: $color;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<style define:vars={{ color: 'blue' }}>
|
|
||||||
.define-vars h1 {
|
|
||||||
color: var(--color);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h1>Component CSS</h1>
|
|
||||||
<Greeting />
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h1>ImageTools</h1>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h1>Astro components</h1>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h1>Hydrated component</h1>
|
|
||||||
<Counter client:idle />
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h1>Hoisted scripts</h1>
|
|
||||||
<InlineHoisted />
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="define-vars">
|
|
||||||
<h1>define:vars</h1>
|
|
||||||
<h2></h2>
|
|
||||||
<script define:vars={{ color: 'blue' }}>
|
|
||||||
document.querySelector('.define-vars h2').textContent = `Color: ${color}`;
|
|
||||||
</script>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,2 +0,0 @@
|
||||||
const el = document.querySelector('#external-hoist');
|
|
||||||
el.textContent = `This was loaded externally`;
|
|
|
@ -1 +0,0 @@
|
||||||
$color: tan;
|
|
|
@ -1,3 +0,0 @@
|
||||||
body {
|
|
||||||
background: lightcoral;
|
|
||||||
}
|
|
|
@ -4,8 +4,5 @@ import preact from '@astrojs/preact';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [preact(), mdx()],
|
integrations: [preact(), mdx()],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
setup: import Counter from '../components/Counter.jsx'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Slots: Preact
|
|
||||||
|
|
||||||
<Counter case="content" client:visible><h1 id="slotted">Hello world!</h1></Counter>
|
|
||||||
<Counter case="named" client:visible><h1 slot="named"> / Named</h1></Counter>
|
|
||||||
<Counter case="dash-case" client:visible><h1 slot="dash-case"> / Dash Case</h1></Counter>
|
|
|
@ -4,8 +4,5 @@ import react from '@astrojs/react';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [react(), mdx()],
|
integrations: [react(), mdx()],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
setup: import Counter from '../components/Counter.jsx'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Slots: React
|
|
||||||
|
|
||||||
<Counter case="content" client:visible><h1 id="slotted">Hello world!</h1></Counter>
|
|
||||||
<Counter case="named" client:visible><h1 slot="named"> / Named</h1></Counter>
|
|
||||||
<Counter case="dash-case" client:visible><h1 slot="dash-case"> / Dash Case</h1></Counter>
|
|
|
@ -4,8 +4,5 @@ import solid from '@astrojs/solid-js';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [solid(), mdx()],
|
integrations: [solid(), mdx()],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
setup: import Counter from '../components/Counter.jsx'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Slots: Solid
|
|
||||||
|
|
||||||
<Counter case="content" client:visible><h1 id="slotted">Hello world!</h1></Counter>
|
|
||||||
<Counter case="named" client:visible><h1 slot="named"> / Named</h1></Counter>
|
|
||||||
<Counter case="dash-case" client:visible><h1 slot="dash-case"> / Dash Case</h1></Counter>
|
|
|
@ -4,8 +4,5 @@ import svelte from '@astrojs/svelte';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [svelte(), mdx()],
|
integrations: [svelte(), mdx()],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
setup: import Counter from '../components/Counter.svelte'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Slots: Svelte
|
|
||||||
|
|
||||||
<Counter id="content" client:visible><h1 id="slotted">Hello world!</h1></Counter>
|
|
||||||
<Counter id="named" client:visible><h1 slot="named"> / Named</h1></Counter>
|
|
||||||
<Counter id="dash-case" client:visible><h1 slot="dash-case"> / Dash Case</h1></Counter>
|
|
|
@ -4,8 +4,5 @@ import vue from '@astrojs/vue';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [vue(), mdx()],
|
integrations: [vue(), mdx()],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
setup: import Counter from '../components/Counter.vue'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Slots: Vue
|
|
||||||
|
|
||||||
<Counter case="content" client:visible><h1 id="slotted">Hello world!</h1></Counter>
|
|
||||||
<Counter case="named" client:visible><h1 slot="named"> / Named</h1></Counter>
|
|
||||||
<Counter case="dash-case" client:visible><h1 slot="dash-case"> / Dash Case</h1></Counter>
|
|
|
@ -4,9 +4,6 @@ import mdx from '@astrojs/mdx';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
legacy: {
|
|
||||||
astroFlavoredMarkdown: true,
|
|
||||||
},
|
|
||||||
integrations: [tailwind(), mdx()],
|
integrations: [tailwind(), mdx()],
|
||||||
vite: {
|
vite: {
|
||||||
build: {
|
build: {
|
||||||
|
|
|
@ -16,10 +16,4 @@ describe('Using .js extension on .ts file', () => {
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
expect($('h1').text()).to.equal('bar');
|
expect($('h1').text()).to.equal('bar');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works in .md files', async () => {
|
|
||||||
const html = await fixture.readFile('/post/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('h2').text()).to.equal('bar');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,200 +0,0 @@
|
||||||
import { expect } from 'chai';
|
|
||||||
import * as cheerio from 'cheerio';
|
|
||||||
import { loadFixture, fixLineEndings } from './test-utils.js';
|
|
||||||
|
|
||||||
describe('Legacy Astro-flavored Markdown', () => {
|
|
||||||
let fixture;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
fixture = await loadFixture({
|
|
||||||
root: './fixtures/legacy-astro-flavored-markdown/',
|
|
||||||
});
|
|
||||||
await fixture.build();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can parse JSX expressions in markdown pages', async () => {
|
|
||||||
const html = await fixture.readFile('/jsx-expressions/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h2').html()).to.equal('Blog Post with JSX expressions');
|
|
||||||
|
|
||||||
expect(html).to.contain('JSX at the start of the line!');
|
|
||||||
for (let listItem of ['test-1', 'test-2', 'test-3']) {
|
|
||||||
expect($(`#${listItem}`).html()).to.equal(`${listItem}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can handle slugs with JSX expressions in markdown pages', async () => {
|
|
||||||
const html = await fixture.readFile('/slug/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h1').attr('id')).to.equal('my-blog-post');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can handle code elements without extra spacing', async () => {
|
|
||||||
const html = await fixture.readFile('/code-element/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
$('code').each((_, el) => {
|
|
||||||
expect($(el).html()).to.equal($(el).html().trim());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can handle namespaced components in markdown', async () => {
|
|
||||||
const html = await fixture.readFile('/namespace/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h1').text()).to.equal('Hello Namespace!');
|
|
||||||
expect($('button').length).to.equal(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Correctly handles component children in markdown pages (#3319)', async () => {
|
|
||||||
const html = await fixture.readFile('/children/index.html');
|
|
||||||
|
|
||||||
expect(html).not.to.contain('<p></p>');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can handle HTML comments in markdown pages', async () => {
|
|
||||||
const html = await fixture.readFile('/comment/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h1').text()).to.equal('It works!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Prevents `*/` sequences from breaking HTML comments (#3476)', async () => {
|
|
||||||
const html = await fixture.readFile('/comment-with-js/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h1').text()).to.equal('It still works!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can handle HTML comments in inline code', async () => {
|
|
||||||
const html = await fixture.readFile('/comment-with-js/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('p code').text()).to.equal('<!-- HTML comments in code -->');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can handle HTML comments in code fences', async () => {
|
|
||||||
const html = await fixture.readFile('/comment-with-js/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('pre > code').text()).to.equal('<!-- HTML comments in code fence -->');
|
|
||||||
});
|
|
||||||
|
|
||||||
// https://github.com/withastro/astro/issues/3254
|
|
||||||
it('Can handle scripts in markdown pages', async () => {
|
|
||||||
const html = await fixture.readFile('/script/index.html');
|
|
||||||
expect(html).not.to.match(new RegExp('/src/scripts/test.js'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Empty code blocks do not fail', async () => {
|
|
||||||
const html = await fixture.readFile('/empty-code/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
// test 1: There is not a `<code>` in the codeblock
|
|
||||||
expect($('pre')[0].children).to.have.lengthOf(1);
|
|
||||||
|
|
||||||
// test 2: The empty `<pre>` failed to render
|
|
||||||
expect($('pre')[1].children).to.have.lengthOf(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can render markdown with --- for horizontal rule', async () => {
|
|
||||||
const html = await fixture.readFile('/dash/index.html');
|
|
||||||
expect(!!html).to.equal(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Exposes raw markdown content', async () => {
|
|
||||||
const { raw } = JSON.parse(await fixture.readFile('/raw-content.json'));
|
|
||||||
|
|
||||||
expect(fixLineEndings(raw)).to.equal(
|
|
||||||
`\n## With components\n\n### Non-hydrated\n\n<Hello name="Astro Naut" />\n\n### Hydrated\n\n<Counter client:load />\n<SvelteButton client:load />\n`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Exposes compiled HTML content', async () => {
|
|
||||||
const { compiled } = JSON.parse(await fixture.readFile('/raw-content.json'));
|
|
||||||
|
|
||||||
expect(fixLineEndings(compiled)).to.equal(
|
|
||||||
`<h2 id="with-components">With components</h2>\n<h3 id="non-hydrated">Non-hydrated</h3>\n<Hello name="Astro Naut" />\n<h3 id="hydrated">Hydrated</h3>\n<Counter client:load />\n<SvelteButton client:load />`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Allows referencing Vite env var names in markdown (#3412)', async () => {
|
|
||||||
const html = await fixture.readFile('/vite-env-vars/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
// test 1: referencing an existing var name
|
|
||||||
expect($('code').eq(0).text()).to.equal('import.meta.env.SITE');
|
|
||||||
expect($('li').eq(0).text()).to.equal('import.meta.env.SITE');
|
|
||||||
expect($('code').eq(3).text()).to.contain('site: import.meta.env.SITE');
|
|
||||||
expect($('blockquote').text()).to.contain('import.meta.env.SITE');
|
|
||||||
|
|
||||||
// test 2: referencing a non-existing var name
|
|
||||||
expect($('code').eq(1).text()).to.equal('import.meta.env.TITLE');
|
|
||||||
expect($('li').eq(1).text()).to.equal('import.meta.env.TITLE');
|
|
||||||
expect($('code').eq(3).text()).to.contain('title: import.meta.env.TITLE');
|
|
||||||
expect($('blockquote').text()).to.contain('import.meta.env.TITLE');
|
|
||||||
|
|
||||||
// test 3: referencing `import.meta.env` itself (without any var name)
|
|
||||||
expect($('code').eq(2).text()).to.equal('import.meta.env');
|
|
||||||
expect($('li').eq(2).text()).to.equal('import.meta.env');
|
|
||||||
expect($('code').eq(3).text()).to.contain('// Use Vite env vars with import.meta.env');
|
|
||||||
expect($('blockquote').text()).to.match(/import\.meta\.env\s*$/);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Escapes HTML tags in code blocks', async () => {
|
|
||||||
const html = await fixture.readFile('/code-in-md/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('code').eq(0).html()).to.equal('<script>');
|
|
||||||
expect($('blockquote').length).to.equal(1);
|
|
||||||
expect($('code').eq(1).html()).to.equal('</script>');
|
|
||||||
expect($('pre').html()).to.contain('>This should also work without any problems.<');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Allows defining slot contents in component children', async () => {
|
|
||||||
const html = await fixture.readFile('/slots/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
const slots = $('article').eq(0);
|
|
||||||
expect(slots.find('> .fragmentSlot > div').text()).to.contain('1:');
|
|
||||||
expect(slots.find('> .fragmentSlot > div + p').text()).to.contain('2:');
|
|
||||||
expect(slots.find('> .pSlot > p[title="hello"]').text()).to.contain('3:');
|
|
||||||
expect(slots.find('> .defaultSlot').html()).to.match(
|
|
||||||
new RegExp(
|
|
||||||
`<div>4: Div in default slot</div>` +
|
|
||||||
// Optional extra paragraph due to the line breaks between components
|
|
||||||
`(<p></p>)?` +
|
|
||||||
`<p>5: Paragraph in fragment in default slot</p>` +
|
|
||||||
// Optional whitespace due to the line breaks between components
|
|
||||||
`[\s\n]*` +
|
|
||||||
`6: Regular text in default slot`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const nestedSlots = $('article').eq(1);
|
|
||||||
expect(nestedSlots.find('> .fragmentSlot').html()).to.contain('1:');
|
|
||||||
expect(nestedSlots.find('> .pSlot > p').text()).to.contain('2:');
|
|
||||||
expect(nestedSlots.find('> .defaultSlot > article').text().replace(/\s+/g, ' ')).to.equal(
|
|
||||||
`
|
|
||||||
3: nested fragmentSlot
|
|
||||||
4: nested pSlot
|
|
||||||
5: nested text in default slot
|
|
||||||
`.replace(/\s+/g, ' ')
|
|
||||||
);
|
|
||||||
|
|
||||||
expect($('article').eq(3).text().replace(/[^❌]/g, '')).to.equal('❌❌❌');
|
|
||||||
|
|
||||||
expect($('article').eq(4).text().replace(/[^❌]/g, '')).to.equal('❌❌❌');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Generate the right props for the layout', async () => {
|
|
||||||
const html = await fixture.readFile('/layout-props/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('#title').text()).to.equal('Hello world!');
|
|
||||||
expect($('#url').text()).to.equal('/layout-props');
|
|
||||||
expect($('#file').text()).to.match(/.*\/layout-props.md$/);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -34,26 +34,6 @@ describe('Slots: Preact', () => {
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('For Markdown Pages', () => {
|
|
||||||
it('Renders default slot', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#content').text().trim()).to.equal('Hello world!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Renders named slot', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#named').text().trim()).to.equal('Fallback / Named');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Converts dash-case slot to camelCase', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('For MDX Pages', () => {
|
describe('For MDX Pages', () => {
|
||||||
it('Renders default slot', async () => {
|
it('Renders default slot', async () => {
|
||||||
const html = await fixture.readFile('/mdx/index.html');
|
const html = await fixture.readFile('/mdx/index.html');
|
||||||
|
|
|
@ -34,26 +34,6 @@ describe('Slots: React', () => {
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('For Markdown Pages', () => {
|
|
||||||
it('Renders default slot', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#content').text().trim()).to.equal('Hello world!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Renders named slot', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#named').text().trim()).to.equal('Fallback / Named');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Converts dash-case slot to camelCase', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('For MDX Pages', () => {
|
describe('For MDX Pages', () => {
|
||||||
it('Renders default slot', async () => {
|
it('Renders default slot', async () => {
|
||||||
const html = await fixture.readFile('/mdx/index.html');
|
const html = await fixture.readFile('/mdx/index.html');
|
||||||
|
|
|
@ -34,26 +34,6 @@ describe('Slots: Solid', () => {
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('For Markdown Pages', () => {
|
|
||||||
it('Renders default slot', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#content').text().trim()).to.equal('Hello world!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Renders named slot', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#named').text().trim()).to.equal('Fallback / Named');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Converts dash-case slot to camelCase', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('For MDX Pages', () => {
|
describe('For MDX Pages', () => {
|
||||||
it('Renders default slot', async () => {
|
it('Renders default slot', async () => {
|
||||||
const html = await fixture.readFile('/mdx/index.html');
|
const html = await fixture.readFile('/mdx/index.html');
|
||||||
|
|
|
@ -34,26 +34,6 @@ describe('Slots: Svelte', () => {
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('For Markdown Pages', () => {
|
|
||||||
it('Renders default slot', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#content').text().trim()).to.equal('Hello world!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Renders named slot', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#named').text().trim()).to.equal('Fallback / Named');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Converts dash-case slot to camelCase', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('For MDX Pages', () => {
|
describe('For MDX Pages', () => {
|
||||||
it('Renders default slot', async () => {
|
it('Renders default slot', async () => {
|
||||||
const html = await fixture.readFile('/mdx/index.html');
|
const html = await fixture.readFile('/mdx/index.html');
|
||||||
|
|
|
@ -34,26 +34,6 @@ describe('Slots: Vue', () => {
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('For Markdown Pages', () => {
|
|
||||||
it('Renders default slot', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#content').text().trim()).to.equal('Hello world!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Renders named slot', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#named').text().trim()).to.equal('Fallback / Named');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Converts dash-case slot to camelCase', async () => {
|
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('For MDX Pages', () => {
|
describe('For MDX Pages', () => {
|
||||||
it('Renders default slot', async () => {
|
it('Renders default slot', async () => {
|
||||||
const html = await fixture.readFile('/mdx/index.html');
|
const html = await fixture.readFile('/mdx/index.html');
|
||||||
|
@ -68,7 +48,7 @@ describe('Slots: Vue', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Converts dash-case slot to camelCase', async () => {
|
it('Converts dash-case slot to camelCase', async () => {
|
||||||
const html = await fixture.readFile('/markdown/index.html');
|
const html = await fixture.readFile('/mdx/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,25 +25,6 @@ describe('Astro Markdown', () => {
|
||||||
expect($('#test').length).to.be.ok;
|
expect($('#test').length).to.be.ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Can parse JSX expressions in markdown pages', async () => {
|
|
||||||
const html = await fixture.readFile('/jsx-expressions/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h2').html()).to.equal('Blog Post with JSX expressions');
|
|
||||||
|
|
||||||
expect(html).to.contain('JSX at the start of the line!');
|
|
||||||
for (let listItem of ['test-1', 'test-2', 'test-3']) {
|
|
||||||
expect($(`#${listItem}`).html()).to.equal(`${listItem}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can handle slugs with JSX expressions in markdown pages', async () => {
|
|
||||||
const html = await fixture.readFile('/slug/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h1').attr('id')).to.equal('my-blog-post');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can handle code elements without extra spacing', async () => {
|
it('Can handle code elements without extra spacing', async () => {
|
||||||
const html = await fixture.readFile('/code-element/index.html');
|
const html = await fixture.readFile('/code-element/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
|
@ -53,14 +34,6 @@ describe('Astro Markdown', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Can handle namespaced components in markdown', async () => {
|
|
||||||
const html = await fixture.readFile('/namespace/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h1').text()).to.equal('Hello Namespace!');
|
|
||||||
expect($('button').length).to.equal(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Correctly handles component children in markdown pages (#3319)', async () => {
|
it('Correctly handles component children in markdown pages (#3319)', async () => {
|
||||||
const html = await fixture.readFile('/children/index.html');
|
const html = await fixture.readFile('/children/index.html');
|
||||||
|
|
||||||
|
@ -95,12 +68,6 @@ describe('Astro Markdown', () => {
|
||||||
expect($('pre > code').text()).to.equal('<!-- HTML comments in code fence -->');
|
expect($('pre > code').text()).to.equal('<!-- HTML comments in code fence -->');
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/withastro/astro/issues/3254
|
|
||||||
it('Can handle scripts in markdown pages', async () => {
|
|
||||||
const html = await fixture.readFile('/script/index.html');
|
|
||||||
expect(html).not.to.match(new RegExp('/src/scripts/test.js'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can load more complex jsxy stuff', async () => {
|
it('Can load more complex jsxy stuff', async () => {
|
||||||
const html = await fixture.readFile('/complex/index.html');
|
const html = await fixture.readFile('/complex/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
|
@ -256,45 +223,6 @@ describe('Astro Markdown', () => {
|
||||||
expect($('#target > ol > li > ol > li').text()).to.equal('nested hello');
|
expect($('#target > ol > li > ol > li').text()).to.equal('nested hello');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Exposes raw markdown content', async () => {
|
|
||||||
const { raw } = JSON.parse(await fixture.readFile('/raw-content.json'));
|
|
||||||
|
|
||||||
expect(fixLineEndings(raw)).to.equal(
|
|
||||||
`\n## With components\n\n### Non-hydrated\n\n<Hello name="Astro Naut" />\n\n### Hydrated\n\n<Counter client:load />\n<SvelteButton client:load />\n`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Exposes HTML parser for raw markdown content', async () => {
|
|
||||||
const { compiled } = JSON.parse(await fixture.readFile('/raw-content.json'));
|
|
||||||
|
|
||||||
expect(fixLineEndings(compiled)).to.equal(
|
|
||||||
`<h2 id="with-components">With components</h2>\n<h3 id="non-hydrated">Non-hydrated</h3>\n<Hello name="Astro Naut" />\n<h3 id="hydrated">Hydrated</h3>\n<Counter client:load />\n<SvelteButton client:load />`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Allows referencing Vite env var names in markdown (#3412)', async () => {
|
|
||||||
const html = await fixture.readFile('/vite-env-vars/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
// test 1: referencing an existing var name
|
|
||||||
expect($('code').eq(0).text()).to.equal('import.meta.env.SITE');
|
|
||||||
expect($('li').eq(0).text()).to.equal('import.meta.env.SITE');
|
|
||||||
expect($('code').eq(3).text()).to.contain('site: import.meta.env.SITE');
|
|
||||||
expect($('blockquote').text()).to.contain('import.meta.env.SITE');
|
|
||||||
|
|
||||||
// test 2: referencing a non-existing var name
|
|
||||||
expect($('code').eq(1).text()).to.equal('import.meta.env.TITLE');
|
|
||||||
expect($('li').eq(1).text()).to.equal('import.meta.env.TITLE');
|
|
||||||
expect($('code').eq(3).text()).to.contain('title: import.meta.env.TITLE');
|
|
||||||
expect($('blockquote').text()).to.contain('import.meta.env.TITLE');
|
|
||||||
|
|
||||||
// test 3: referencing `import.meta.env` itself (without any var name)
|
|
||||||
expect($('code').eq(2).text()).to.equal('import.meta.env');
|
|
||||||
expect($('li').eq(2).text()).to.equal('import.meta.env');
|
|
||||||
expect($('code').eq(3).text()).to.contain('// Use Vite env vars with import.meta.env');
|
|
||||||
expect($('blockquote').text()).to.match(/import\.meta\.env\s*$/);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Escapes HTML tags in code blocks', async () => {
|
it('Escapes HTML tags in code blocks', async () => {
|
||||||
const html = await fixture.readFile('/code-in-md/index.html');
|
const html = await fixture.readFile('/code-in-md/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
|
@ -305,42 +233,6 @@ describe('Astro Markdown', () => {
|
||||||
expect($('pre').html()).to.contain('>This should also work without any problems.<');
|
expect($('pre').html()).to.contain('>This should also work without any problems.<');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Allows defining slot contents in component children', async () => {
|
|
||||||
const html = await fixture.readFile('/slots/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
const slots = $('article').eq(0);
|
|
||||||
expect(slots.find('> .fragmentSlot > div').text()).to.contain('1:');
|
|
||||||
expect(slots.find('> .fragmentSlot > div + p').text()).to.contain('2:');
|
|
||||||
expect(slots.find('> .pSlot > p[title="hello"]').text()).to.contain('3:');
|
|
||||||
expect(slots.find('> .defaultSlot').html()).to.match(
|
|
||||||
new RegExp(
|
|
||||||
`<div>4: Div in default slot</div>` +
|
|
||||||
// Optional extra paragraph due to the line breaks between components
|
|
||||||
`(<p></p>)?` +
|
|
||||||
`<p>5: Paragraph in fragment in default slot</p>` +
|
|
||||||
// Optional whitespace due to the line breaks between components
|
|
||||||
`[\s\n]*` +
|
|
||||||
`6: Regular text in default slot`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const nestedSlots = $('article').eq(1);
|
|
||||||
expect(nestedSlots.find('> .fragmentSlot').html()).to.contain('1:');
|
|
||||||
expect(nestedSlots.find('> .pSlot > p').text()).to.contain('2:');
|
|
||||||
expect(nestedSlots.find('> .defaultSlot > article').text().replace(/\s+/g, ' ')).to.equal(
|
|
||||||
`
|
|
||||||
3: nested fragmentSlot
|
|
||||||
4: nested pSlot
|
|
||||||
5: nested text in default slot
|
|
||||||
`.replace(/\s+/g, ' ')
|
|
||||||
);
|
|
||||||
|
|
||||||
expect($('article').eq(3).text().replace(/[^❌]/g, '')).to.equal('❌❌❌');
|
|
||||||
|
|
||||||
expect($('article').eq(4).text().replace(/[^❌]/g, '')).to.equal('❌❌❌');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Generate the right props for the layout', async () => {
|
it('Generate the right props for the layout', async () => {
|
||||||
const html = await fixture.readFile('/layout-props/index.html');
|
const html = await fixture.readFile('/layout-props/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue