diff --git a/.changeset/strong-stingrays-compete.md b/.changeset/strong-stingrays-compete.md new file mode 100644 index 000000000000..f01d4cc8c4a2 --- /dev/null +++ b/.changeset/strong-stingrays-compete.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Add support for `.html` components and pages diff --git a/packages/astro/env.d.ts b/packages/astro/env.d.ts index aa649c896fdd..619a4422bc54 100644 --- a/packages/astro/env.d.ts +++ b/packages/astro/env.d.ts @@ -26,3 +26,8 @@ declare module '*.md' { const load: MD['default']; export default load; } + +declare module "*.html" { + const Component: { render(opts: { slots: Record }): string }; + export default Component; +} diff --git a/packages/astro/package.json b/packages/astro/package.json index ee82786b3478..b02f29011930 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -125,6 +125,7 @@ "prismjs": "^1.28.0", "prompts": "^2.4.2", "recast": "^0.20.5", + "rehype": "^12.0.1", "resolve": "^1.22.0", "rollup": "^2.75.6", "semver": "^7.3.7", @@ -136,6 +137,8 @@ "strip-ansi": "^7.0.1", "supports-esm": "^1.0.0", "tsconfig-resolver": "^3.0.1", + "unist-util-visit": "^4.1.0", + "vfile": "^5.3.2", "vite": "3.0.2", "yargs-parser": "^21.0.1", "zod": "^3.17.3" diff --git a/packages/astro/src/core/config.ts b/packages/astro/src/core/config.ts index 75fabdc89857..bbfad04396a9 100644 --- a/packages/astro/src/core/config.ts +++ b/packages/astro/src/core/config.ts @@ -325,7 +325,7 @@ export async function validateConfig( const result = { ...(await AstroConfigRelativeSchema.parseAsync(userConfig)), _ctx: { - pageExtensions: ['.astro', '.md'], + pageExtensions: ['.astro', '.md', '.html'], scripts: [], renderers: [], injectedRoutes: [], diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts index c853b29c78a6..72e357470633 100644 --- a/packages/astro/src/core/create-vite.ts +++ b/packages/astro/src/core/create-vite.ts @@ -11,6 +11,7 @@ import configAliasVitePlugin from '../vite-plugin-config-alias/index.js'; import envVitePlugin from '../vite-plugin-env/index.js'; import astroIntegrationsContainerPlugin from '../vite-plugin-integrations-container/index.js'; import jsxVitePlugin from '../vite-plugin-jsx/index.js'; +import htmlVitePlugin from '../vite-plugin-html/index.js'; import markdownVitePlugin from '../vite-plugin-markdown/index.js'; import astroScriptsPlugin from '../vite-plugin-scripts/index.js'; import { createCustomViteLogger } from './errors.js'; @@ -73,6 +74,7 @@ export async function createVite( mode === 'dev' && astroViteServerPlugin({ config: astroConfig, logging }), envVitePlugin({ config: astroConfig }), markdownVitePlugin({ config: astroConfig }), + htmlVitePlugin(), jsxVitePlugin({ config: astroConfig, logging }), astroPostprocessVitePlugin({ config: astroConfig }), astroIntegrationsContainerPlugin({ config: astroConfig }), diff --git a/packages/astro/src/core/dev/index.ts b/packages/astro/src/core/dev/index.ts index df26858e5e26..eff09c5a4e58 100644 --- a/packages/astro/src/core/dev/index.ts +++ b/packages/astro/src/core/dev/index.ts @@ -45,14 +45,7 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro mode: 'development', server: { host }, optimizeDeps: { - include: [ - 'astro/client/idle.js', - 'astro/client/load.js', - 'astro/client/visible.js', - 'astro/client/media.js', - 'astro/client/only.js', - ...rendererClientEntries, - ], + include: rendererClientEntries, }, }, { astroConfig: config, logging: options.logging, mode: 'dev' } diff --git a/packages/astro/src/core/errors.ts b/packages/astro/src/core/errors.ts index 49bf4b6f2fab..13eec5cb8739 100644 --- a/packages/astro/src/core/errors.ts +++ b/packages/astro/src/core/errors.ts @@ -58,7 +58,8 @@ export function fixViteErrorMessage(_err: unknown, server: ViteDevServer, filePa const content = fs.readFileSync(fileURLToPath(filePath)).toString(); const lns = content.split('\n'); const line = lns.findIndex((ln) => ln.includes(importName)); - const column = lns[line].indexOf(importName); + if (line == -1) return err; + const column = lns[line]?.indexOf(importName); if (!(err as any).id) { (err as any).id = `${fileURLToPath(filePath)}:${line + 1}:${column + 1}`; } diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index 59473798d05e..77673e953c21 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -210,6 +210,21 @@ export async function renderComponent( return markHTMLString(children); } + if (Component && typeof Component === 'object' && (Component as any)['astro:html']) { + const children: Record = {}; + if (slots) { + await Promise.all( + Object.entries(slots).map(([key, value]) => + renderSlot(result, value as string).then((output) => { + children[key] = output; + }) + ) + ); + } + const html = (Component as any).render({ slots: children }); + return markHTMLString(html); + } + if (Component && (Component as any).isAstroComponentFactory) { async function* renderAstroComponentInline(): AsyncGenerator { let iterable = await renderToIterable(result, Component as any, _props, slots); @@ -279,6 +294,7 @@ Did you mean to add ${formatList(probableRendererNames.map((r) => '`' + r + '`') ) ); } + // Call the renderers `check` hook to see if any claim this component. let renderer: SSRLoadedRenderer | undefined; if (metadata.hydrate !== 'only') { diff --git a/packages/astro/src/vite-plugin-html/index.ts b/packages/astro/src/vite-plugin-html/index.ts new file mode 100644 index 000000000000..c593bc2015c9 --- /dev/null +++ b/packages/astro/src/vite-plugin-html/index.ts @@ -0,0 +1,14 @@ +import { transform } from './transform/index.js'; + +export default function html() { + return { + name: 'astro:html', + options(options: any) { + options.plugins = options.plugins?.filter((p: any) => p.name !== 'vite:build-html'); + }, + async transform(source: string, id: string) { + if (!id.endsWith('.html')) return; + return await transform(source, id); + } + } +} diff --git a/packages/astro/src/vite-plugin-html/transform/escape.ts b/packages/astro/src/vite-plugin-html/transform/escape.ts new file mode 100644 index 000000000000..8b58056141ee --- /dev/null +++ b/packages/astro/src/vite-plugin-html/transform/escape.ts @@ -0,0 +1,27 @@ +import type { Plugin } from 'unified'; +import type { Root, RootContent } from 'hast'; +import type MagicString from 'magic-string'; +import { visit } from 'unist-util-visit'; + +import { replaceAttribute, needsEscape, escape } from './utils.js'; + +const rehypeEscape: Plugin<[{ s: MagicString }], Root> = ({ s }) => { + return (tree, file) => { + visit(tree, (node: Root | RootContent, index, parent) => { + if (node.type === 'text' || node.type === 'comment') { + if (needsEscape(node.value)) { + s.overwrite(node.position!.start.offset!, node.position!.end.offset!, escape(node.value)); + } + } else if (node.type === 'element') { + for (const [key, value] of Object.entries(node.properties ?? {})) { + const newKey = needsEscape(key) ? escape(key) : key; + const newValue = needsEscape(value) ? escape(value) : value; + if (newKey === key && newValue === value) continue; + replaceAttribute(s, node, key, (value === '') ? newKey : `${newKey}="${newValue}"`); + } + } + }); + }; +}; + +export default rehypeEscape; diff --git a/packages/astro/src/vite-plugin-html/transform/index.ts b/packages/astro/src/vite-plugin-html/transform/index.ts new file mode 100644 index 000000000000..de6431ea7649 --- /dev/null +++ b/packages/astro/src/vite-plugin-html/transform/index.ts @@ -0,0 +1,32 @@ +import MagicString from 'magic-string'; +import { rehype } from 'rehype'; +import { VFile } from 'vfile'; +import escape from './escape.js'; +import slots, { SLOT_PREFIX } from './slots.js'; + +export async function transform(code: string, id: string) { + const s = new MagicString(code, { filename: id }); + const imports = new Map(); + const parser = rehype() + .data('settings', { fragment: true }) + .use(escape, { s }) + .use(slots, { s }); + + const vfile = new VFile({ value: code, path: id }) + await parser.process(vfile) + s.prepend(`export default {\n\t"astro:html": true,\n\trender({ slots: ${SLOT_PREFIX} }) {\n\t\treturn \``); + s.append('`\n\t}\n}'); + + if (imports.size > 0) { + let importText = '' + for (const [path, importName] of imports.entries()) { + importText += `import ${importName} from "${path}";\n` + } + s.prepend(importText); + } + + return { + code: s.toString(), + map: s.generateMap() + } +} diff --git a/packages/astro/src/vite-plugin-html/transform/slots.ts b/packages/astro/src/vite-plugin-html/transform/slots.ts new file mode 100644 index 000000000000..c8cb32f13a97 --- /dev/null +++ b/packages/astro/src/vite-plugin-html/transform/slots.ts @@ -0,0 +1,27 @@ +import type { Plugin } from 'unified'; +import type { Root, RootContent } from 'hast'; + +import { visit } from 'unist-util-visit'; +import MagicString from 'magic-string'; +import { escape } from './utils.js'; + +const rehypeSlots: Plugin<[{ s: MagicString }], Root> = ({ s }) => { + return (tree, file) => { + visit(tree, (node: Root | RootContent, index, parent) => { + if (node.type === 'element' && node.tagName === 'slot') { + if (typeof node.properties?.['is:inline'] !== 'undefined') return; + const name = node.properties?.['name'] ?? 'default'; + const start = node.position?.start.offset ?? 0; + const end = node.position?.end.offset ?? 0; + const first = node.children.at(0) ?? node; + const last = node.children.at(-1) ?? node; + const text = file.value.slice(first.position?.start.offset ?? 0, last.position?.end.offset ?? 0).toString(); + s.overwrite(start, end, `\${${SLOT_PREFIX}["${name}"] ?? \`${escape(text).trim()}\`}`) + } + }); + } +} + +export default rehypeSlots; + +export const SLOT_PREFIX = `___SLOTS___`; diff --git a/packages/astro/src/vite-plugin-html/transform/utils.ts b/packages/astro/src/vite-plugin-html/transform/utils.ts new file mode 100644 index 000000000000..313bfe662c62 --- /dev/null +++ b/packages/astro/src/vite-plugin-html/transform/utils.ts @@ -0,0 +1,27 @@ +import type { Element } from 'hast'; +import MagicString from 'magic-string'; + +const splitAttrsTokenizer = /([\$\{\}\@a-z0-9_\:\-]*)\s*?=\s*?(['"]?)(.*?)\2\s+/gim; + +export function replaceAttribute(s: MagicString, node: Element, key: string, newValue: string) { + splitAttrsTokenizer.lastIndex = 0; + const text = s.original.slice(node.position?.start.offset ?? 0, node.position?.end.offset ?? 0).toString(); + const offset = text.indexOf(key); + if (offset === -1) return; + const start = node.position!.start.offset! + offset; + const tokens = text.slice(offset).split(splitAttrsTokenizer); + const token = tokens[0].replace(/([^>])(\>[\s\S]*$)/gmi, '$1'); + if (token.trim() === key) { + const end = start + key.length; + s.overwrite(start, end, newValue) + } else { + const end = start + `${key}=${tokens[2]}${tokens[3]}${tokens[2]}`.length; + s.overwrite(start, end, newValue) + } +} +export function needsEscape(value: any): value is string { + return typeof value === 'string' && (value.includes('`') || value.includes('${')); +} +export function escape(value: string) { + return value.replace(/`/g, '\\`').replace(/\$\{/g, '\\${'); +} diff --git a/packages/astro/test/fixtures/html-component/package.json b/packages/astro/test/fixtures/html-component/package.json new file mode 100644 index 000000000000..548f0bc7b591 --- /dev/null +++ b/packages/astro/test/fixtures/html-component/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/html-component", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/html-component/src/components/Test.html b/packages/astro/test/fixtures/html-component/src/components/Test.html new file mode 100644 index 000000000000..ec16bf314cf1 --- /dev/null +++ b/packages/astro/test/fixtures/html-component/src/components/Test.html @@ -0,0 +1,3 @@ +

Hello component!

+ +
bar
diff --git a/packages/astro/test/fixtures/html-component/src/pages/index.astro b/packages/astro/test/fixtures/html-component/src/pages/index.astro new file mode 100644 index 000000000000..821d12538b9a --- /dev/null +++ b/packages/astro/test/fixtures/html-component/src/pages/index.astro @@ -0,0 +1,5 @@ +--- +import Test from '../components/Test.html'; +--- + + diff --git a/packages/astro/test/fixtures/html-escape/package.json b/packages/astro/test/fixtures/html-escape/package.json new file mode 100644 index 000000000000..b6eb747659fb --- /dev/null +++ b/packages/astro/test/fixtures/html-escape/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/html-escape", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/html-escape/src/components/Test.html b/packages/astro/test/fixtures/html-escape/src/components/Test.html new file mode 100644 index 000000000000..6ee4b52000dd --- /dev/null +++ b/packages/astro/test/fixtures/html-escape/src/components/Test.html @@ -0,0 +1,4 @@ +
${foo}
+ + + diff --git a/packages/astro/test/fixtures/html-escape/src/pages/index.astro b/packages/astro/test/fixtures/html-escape/src/pages/index.astro new file mode 100644 index 000000000000..821d12538b9a --- /dev/null +++ b/packages/astro/test/fixtures/html-escape/src/pages/index.astro @@ -0,0 +1,5 @@ +--- +import Test from '../components/Test.html'; +--- + + diff --git a/packages/astro/test/fixtures/html-page/package.json b/packages/astro/test/fixtures/html-page/package.json new file mode 100644 index 000000000000..070024b1e14d --- /dev/null +++ b/packages/astro/test/fixtures/html-page/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/html-page", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/html-page/src/pages/index.html b/packages/astro/test/fixtures/html-page/src/pages/index.html new file mode 100644 index 000000000000..5d4d2282712e --- /dev/null +++ b/packages/astro/test/fixtures/html-page/src/pages/index.html @@ -0,0 +1 @@ +

Hello page!

diff --git a/packages/astro/test/fixtures/html-slots/package.json b/packages/astro/test/fixtures/html-slots/package.json new file mode 100644 index 000000000000..10b04cfd4f22 --- /dev/null +++ b/packages/astro/test/fixtures/html-slots/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/html-slots", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/html-slots/src/components/Default.html b/packages/astro/test/fixtures/html-slots/src/components/Default.html new file mode 100644 index 000000000000..9f012095fbf0 --- /dev/null +++ b/packages/astro/test/fixtures/html-slots/src/components/Default.html @@ -0,0 +1 @@ +
diff --git a/packages/astro/test/fixtures/html-slots/src/components/Inline.html b/packages/astro/test/fixtures/html-slots/src/components/Inline.html new file mode 100644 index 000000000000..121164e380e4 --- /dev/null +++ b/packages/astro/test/fixtures/html-slots/src/components/Inline.html @@ -0,0 +1 @@ +
diff --git a/packages/astro/test/fixtures/html-slots/src/components/Named.html b/packages/astro/test/fixtures/html-slots/src/components/Named.html new file mode 100644 index 000000000000..0993cfb27263 --- /dev/null +++ b/packages/astro/test/fixtures/html-slots/src/components/Named.html @@ -0,0 +1,3 @@ +
+
+
diff --git a/packages/astro/test/fixtures/html-slots/src/pages/index.astro b/packages/astro/test/fixtures/html-slots/src/pages/index.astro new file mode 100644 index 000000000000..aa4a3bd2587a --- /dev/null +++ b/packages/astro/test/fixtures/html-slots/src/pages/index.astro @@ -0,0 +1,13 @@ +--- +import Default from '../components/Default.html'; +import Named from '../components/Named.html'; +import Inline from '../components/Inline.html'; +--- + +Default + + A + B + C + + diff --git a/packages/astro/test/html-component.test.js b/packages/astro/test/html-component.test.js new file mode 100644 index 000000000000..0145a22aa395 --- /dev/null +++ b/packages/astro/test/html-component.test.js @@ -0,0 +1,57 @@ +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('HTML Component', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/html-component/', + }); + }); + + describe('build', () => { + before(async () => { + await fixture.build(); + }); + + it('works', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + const h1 = $('h1'); + const foo = $('#foo'); + + expect(h1.text()).to.equal('Hello component!'); + expect(foo.text()).to.equal('bar'); + }); + }); + + describe('dev', () => { + let devServer; + + before(async () => { + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('works', async () => { + const res = await fixture.fetch('/'); + + expect(res.status).to.equal(200); + + const html = await res.text(); + const $ = cheerio.load(html); + + const h1 = $('h1'); + const foo = $('#foo'); + + expect(h1.text()).to.equal('Hello component!'); + expect(foo.text()).to.equal('bar'); + }); + }); +}); diff --git a/packages/astro/test/html-escape.test.js b/packages/astro/test/html-escape.test.js new file mode 100644 index 000000000000..ed19105c6567 --- /dev/null +++ b/packages/astro/test/html-escape.test.js @@ -0,0 +1,69 @@ +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('HTML Escape', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/html-escape/', + }); + }); + + describe('build', () => { + before(async () => { + await fixture.build(); + }); + + it('works', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + const div = $('div'); + expect(div.text()).to.equal('${foo}'); + + const span = $('span'); + expect(span.attr('${attr}')).to.equal(""); + + const ce = $('custom-element'); + expect(ce.attr('x-data')).to.equal("`${test}`"); + + const script = $('script'); + expect(script.text()).to.equal('console.log(`hello ${"world"}!`)'); + }); + }); + + describe('dev', () => { + let devServer; + + before(async () => { + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('works', async () => { + const res = await fixture.fetch('/'); + + expect(res.status).to.equal(200); + + const html = await res.text(); + const $ = cheerio.load(html); + + const div = $('div'); + expect(div.text()).to.equal('${foo}'); + + const span = $('span'); + expect(span.attr('${attr}')).to.equal(""); + + const ce = $('custom-element'); + expect(ce.attr('x-data')).to.equal("`${test}`"); + + const script = $('script'); + expect(script.text()).to.equal('console.log(`hello ${"world"}!`)'); + }); + }); +}); diff --git a/packages/astro/test/html-page.test.js b/packages/astro/test/html-page.test.js new file mode 100644 index 000000000000..fe4c01f68050 --- /dev/null +++ b/packages/astro/test/html-page.test.js @@ -0,0 +1,53 @@ +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('HTML Page', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/html-page/', + }); + }); + + describe('build', () => { + before(async () => { + await fixture.build(); + }); + + it('works', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html) + + const h1 = $('h1'); + + expect(h1.text()).to.equal('Hello page!'); + }); + }); + + describe('dev', () => { + let devServer; + + before(async () => { + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('works', async () => { + const res = await fixture.fetch('/'); + + expect(res.status).to.equal(200); + + const html = await res.text(); + const $ = cheerio.load(html) + + const h1 = $('h1'); + + expect(h1.text()).to.equal('Hello page!'); + }); + }); +}); diff --git a/packages/astro/test/html-slots.test.js b/packages/astro/test/html-slots.test.js new file mode 100644 index 000000000000..af1a05a83327 --- /dev/null +++ b/packages/astro/test/html-slots.test.js @@ -0,0 +1,75 @@ +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('HTML Slots', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/html-slots/', + }); + }); + + describe('build', () => { + before(async () => { + await fixture.build(); + }); + + it('works', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + const slotDefault = $('#default'); + expect(slotDefault.text()).to.equal('Default'); + + const a = $('#a'); + expect(a.text().trim()).to.equal('A'); + + const b = $('#b'); + expect(b.text().trim()).to.equal('B'); + + const c = $('#c'); + expect(c.text().trim()).to.equal('C'); + + const inline = $('#inline'); + expect(inline.html()).to.equal(''); + }); + }); + + describe('dev', () => { + let devServer; + + before(async () => { + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('works', async () => { + const res = await fixture.fetch('/'); + + expect(res.status).to.equal(200); + + const html = await res.text(); + const $ = cheerio.load(html); + + const slotDefault = $('#default'); + expect(slotDefault.text()).to.equal('Default'); + + const a = $('#a'); + expect(a.text().trim()).to.equal('A'); + + const b = $('#b'); + expect(b.text().trim()).to.equal('B'); + + const c = $('#c'); + expect(c.text().trim()).to.equal('C'); + + const inline = $('#inline'); + expect(inline.html()).to.equal(''); + }); + }); +}); diff --git a/packages/webapi/mod.d.ts b/packages/webapi/mod.d.ts index a3c49dc5c406..7150edbe716e 100644 --- a/packages/webapi/mod.d.ts +++ b/packages/webapi/mod.d.ts @@ -9,4 +9,4 @@ interface PolyfillOptions { override?: Record; -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a0c342494d12..738882324952 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -506,6 +506,7 @@ importers: prismjs: ^1.28.0 prompts: ^2.4.2 recast: ^0.20.5 + rehype: ^12.0.1 resolve: ^1.22.0 rollup: ^2.75.6 sass: ^1.52.2 @@ -519,6 +520,8 @@ importers: strip-ansi: ^7.0.1 supports-esm: ^1.0.0 tsconfig-resolver: ^3.0.1 + unist-util-visit: ^4.1.0 + vfile: ^5.3.2 vite: 3.0.2 yargs-parser: ^21.0.1 zod: ^3.17.3 @@ -566,6 +569,7 @@ importers: prismjs: 1.28.0 prompts: 2.4.2 recast: 0.20.5 + rehype: 12.0.1 resolve: 1.22.1 rollup: 2.76.0 semver: 7.3.7 @@ -577,6 +581,8 @@ importers: strip-ansi: 7.0.1 supports-esm: 1.0.0 tsconfig-resolver: 3.0.1 + unist-util-visit: 4.1.0 + vfile: 5.3.4 vite: 3.0.2_sass@1.53.0 yargs-parser: 21.0.1 zod: 3.17.3 @@ -1518,6 +1524,30 @@ importers: dependencies: astro: link:../../.. + packages/astro/test/fixtures/html-component: + specifiers: + astro: workspace:* + dependencies: + astro: link:../../.. + + packages/astro/test/fixtures/html-escape: + specifiers: + astro: workspace:* + dependencies: + astro: link:../../.. + + packages/astro/test/fixtures/html-page: + specifiers: + astro: workspace:* + dependencies: + astro: link:../../.. + + packages/astro/test/fixtures/html-slots: + specifiers: + astro: workspace:* + dependencies: + astro: link:../../.. + packages/astro/test/fixtures/import-ts-with-js: specifiers: astro: workspace:* @@ -9499,7 +9529,7 @@ packages: dev: true /concat-map/0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} /concurrently/7.2.2: resolution: {integrity: sha512-DcQkI0ruil5BA/g7Xy3EWySGrFJovF5RYAYxwGvv9Jf9q9B1v3jPFP2tl6axExNf1qgF30kjoNYrangZ0ey4Aw==} @@ -14159,6 +14189,15 @@ packages: unist-util-visit: 4.1.0 dev: true + /rehype-parse/8.0.4: + resolution: {integrity: sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==} + dependencies: + '@types/hast': 2.3.4 + hast-util-from-parse5: 7.1.0 + parse5: 6.0.1 + unified: 10.1.2 + dev: false + /rehype-raw/6.1.1: resolution: {integrity: sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==} dependencies: @@ -14193,6 +14232,15 @@ packages: '@jsdevtools/rehype-toc': 3.0.2 dev: true + /rehype/12.0.1: + resolution: {integrity: sha512-ey6kAqwLM3X6QnMDILJthGvG1m1ULROS9NT4uG9IDCuv08SFyLlreSuvOa//DgEvbXx62DS6elGVqusWhRUbgw==} + dependencies: + '@types/hast': 2.3.4 + rehype-parse: 8.0.4 + rehype-stringify: 9.0.3 + unified: 10.1.2 + dev: false + /remark-code-titles/0.1.2: resolution: {integrity: sha512-KsHQbaI4FX8Ozxqk7YErxwmBiveUqloKuVqyPG2YPLHojpgomodWgRfG4B+bOtmn/5bfJ8khw4rR0lvgVFl2Uw==} dependencies: