[ci] format

This commit is contained in:
matthewp 2022-12-06 21:28:24 +00:00 committed by fredkbot
parent 05915fec01
commit 1cfbd5923f
22 changed files with 172 additions and 159 deletions

View file

@ -10,6 +10,7 @@ import { vitePluginAstroServer } from '../vite-plugin-astro-server/index.js';
import astroVitePlugin from '../vite-plugin-astro/index.js'; import astroVitePlugin from '../vite-plugin-astro/index.js';
import configAliasVitePlugin from '../vite-plugin-config-alias/index.js'; import configAliasVitePlugin from '../vite-plugin-config-alias/index.js';
import envVitePlugin from '../vite-plugin-env/index.js'; import envVitePlugin from '../vite-plugin-env/index.js';
import astroHeadPropagationPlugin from '../vite-plugin-head-propagation/index.js';
import htmlVitePlugin from '../vite-plugin-html/index.js'; 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';
@ -18,7 +19,6 @@ 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 astroScriptsPlugin from '../vite-plugin-scripts/index.js'; import astroScriptsPlugin from '../vite-plugin-scripts/index.js';
import astroScriptsPageSSRPlugin from '../vite-plugin-scripts/page-ssr.js'; import astroScriptsPageSSRPlugin from '../vite-plugin-scripts/page-ssr.js';
import astroHeadPropagationPlugin from '../vite-plugin-head-propagation/index.js';
import { createCustomViteLogger } from './errors/dev/index.js'; import { createCustomViteLogger } from './errors/dev/index.js';
import { resolveDependency } from './util.js'; import { resolveDependency } from './util.js';

View file

@ -2,8 +2,8 @@ import type { SSRResult } from '../../../@types/astro';
import type { ModuleInfo, ModuleLoader } from '../../module-loader/index'; import type { ModuleInfo, ModuleLoader } from '../../module-loader/index';
import { viteID } from '../../util.js';
import { getAstroMetadata } from '../../../vite-plugin-astro/index.js'; import { getAstroMetadata } from '../../../vite-plugin-astro/index.js';
import { viteID } from '../../util.js';
import { crawlGraph } from './vite.js'; import { crawlGraph } from './vite.js';
export async function getPropagationMap( export async function getPropagationMap(
@ -13,7 +13,7 @@ export async function getPropagationMap(
const map: SSRResult['propagation'] = new Map(); const map: SSRResult['propagation'] = new Map();
const rootID = viteID(filePath); const rootID = viteID(filePath);
addInjection(map, loader.getModuleInfo(rootID)) addInjection(map, loader.getModuleInfo(rootID));
for await (const moduleNode of crawlGraph(loader, rootID, true)) { for await (const moduleNode of crawlGraph(loader, rootID, true)) {
const id = moduleNode.id; const id = moduleNode.id;
if (id) { if (id) {
@ -25,10 +25,10 @@ export async function getPropagationMap(
} }
function addInjection(map: SSRResult['propagation'], modInfo: ModuleInfo | null) { function addInjection(map: SSRResult['propagation'], modInfo: ModuleInfo | null) {
if(modInfo) { if (modInfo) {
const astro = getAstroMetadata(modInfo); const astro = getAstroMetadata(modInfo);
if(astro && astro.propagation) { if (astro && astro.propagation) {
map.set(modInfo.id, astro.propagation) map.set(modInfo.id, astro.propagation);
} }
} }
} }

View file

@ -15,8 +15,8 @@ import { createRenderContext, renderPage as coreRenderPage } from '../index.js';
import { filterFoundRenderers, loadRenderer } from '../renderer.js'; import { filterFoundRenderers, loadRenderer } from '../renderer.js';
import { getStylesForURL } from './css.js'; import { getStylesForURL } from './css.js';
import type { DevelopmentEnvironment } from './environment'; import type { DevelopmentEnvironment } from './environment';
import { getScriptsForURL } from './scripts.js';
import { getPropagationMap } from './head.js'; import { getPropagationMap } from './head.js';
import { getScriptsForURL } from './scripts.js';
export { createDevelopmentEnvironment } from './environment.js'; export { createDevelopmentEnvironment } from './environment.js';
export type { DevelopmentEnvironment }; export type { DevelopmentEnvironment };

View file

@ -21,7 +21,7 @@ function createComponentWithOptions(opts: CreateComponentOptions) {
} }
// Used in creating the component. aka the main export. // Used in creating the component. aka the main export.
export function createComponent(arg1: AstroComponentFactory, moduleId: string) { export function createComponent(arg1: AstroComponentFactory, moduleId: string) {
if(typeof arg1 === 'function') { if (typeof arg1 === 'function') {
return baseCreateComponent(arg1, moduleId); return baseCreateComponent(arg1, moduleId);
} else { } else {
return createComponentWithOptions(arg1); return createComponentWithOptions(arg1);

View file

@ -1,3 +1,4 @@
export { createComponent } from './astro-component.js';
export { createAstro } from './astro-global.js'; export { createAstro } from './astro-global.js';
export { renderEndpoint } from './endpoint.js'; export { renderEndpoint } from './endpoint.js';
export { escapeHTML, HTMLBytes, HTMLString, markHTMLString, unescapeHTML } from './escape.js'; export { escapeHTML, HTMLBytes, HTMLString, markHTMLString, unescapeHTML } from './escape.js';
@ -18,17 +19,19 @@ export {
renderSlot, renderSlot,
renderTemplate as render, renderTemplate as render,
renderTemplate, renderTemplate,
renderUniqueStylesheet,
renderToString, renderToString,
renderUniqueStylesheet,
stringifyChunk, stringifyChunk,
voidElementNames, voidElementNames,
} from './render/index.js'; } from './render/index.js';
export { createComponent } from './astro-component.js'; export type {
export type { AstroComponentFactory, AstroComponentInstance, RenderInstruction } from './render/index.js'; AstroComponentFactory,
AstroComponentInstance,
RenderInstruction,
} from './render/index.js';
import { markHTMLString } from './escape.js'; import { markHTMLString } from './escape.js';
import { Renderer } from './render/index.js'; import { addAttribute, Renderer } from './render/index.js';
import { addAttribute } from './render/index.js';
export function mergeSlots(...slotted: unknown[]) { export function mergeSlots(...slotted: unknown[]) {
const slots: Record<string, () => any> = {}; const slots: Record<string, () => any> = {};

View file

@ -1,6 +1,9 @@
import { escapeHTML, isHTMLString, markHTMLString } from '../escape.js'; import { escapeHTML, isHTMLString, markHTMLString } from '../escape.js';
import { isRenderTemplateResult, renderAstroTemplateResult } from './astro/index.js'; import {
import { isAstroComponentInstance } from './astro/index.js'; isAstroComponentInstance,
isRenderTemplateResult,
renderAstroTemplateResult,
} from './astro/index.js';
import { SlotString } from './slot.js'; import { SlotString } from './slot.js';
export async function* renderChild(child: any): AsyncIterable<any> { export async function* renderChild(child: any): AsyncIterable<any> {
@ -25,10 +28,9 @@ export async function* renderChild(child: any): AsyncIterable<any> {
yield markHTMLString(escapeHTML(child)); yield markHTMLString(escapeHTML(child));
} else if (!child && child !== 0) { } else if (!child && child !== 0) {
// do nothing, safe to ignore falsey values. // do nothing, safe to ignore falsey values.
} } else if (isRenderTemplateResult(child)) {
else if(isRenderTemplateResult(child)) {
yield* renderAstroTemplateResult(child); yield* renderAstroTemplateResult(child);
} else if(isAstroComponentInstance(child)) { } else if (isAstroComponentInstance(child)) {
yield* child.render(); yield* child.render();
} else if (ArrayBuffer.isView(child)) { } else if (ArrayBuffer.isView(child)) {
yield child; yield child;

View file

@ -1,10 +1,10 @@
import type { SSRResult, PropagationHint } from '../../../../@types/astro'; import type { PropagationHint, SSRResult } from '../../../../@types/astro';
import type { HeadAndContent } from './head-and-content'; import type { HeadAndContent } from './head-and-content';
import type { RenderTemplateResult } from './render-template'; import type { RenderTemplateResult } from './render-template';
import { renderAstroTemplateResult } from './render-template.js';
import { isHeadAndContent } from './head-and-content.js';
import { HTMLParts } from '../common.js'; import { HTMLParts } from '../common.js';
import { isHeadAndContent } from './head-and-content.js';
import { renderAstroTemplateResult } from './render-template.js';
export type AstroFactoryReturnValue = RenderTemplateResult | Response | HeadAndContent; export type AstroFactoryReturnValue = RenderTemplateResult | Response | HeadAndContent;
@ -40,13 +40,15 @@ export async function renderToString(
parts.append(chunk, result); parts.append(chunk, result);
} }
return parts.toString(); return parts.toString();
} }
export function isAPropagatingComponent(result: SSRResult, factory: AstroComponentFactory): boolean { export function isAPropagatingComponent(
result: SSRResult,
factory: AstroComponentFactory
): boolean {
let hint: PropagationHint = factory.propagation || 'none'; let hint: PropagationHint = factory.propagation || 'none';
if(factory.moduleId && result.propagation.has(factory.moduleId) && hint === 'none') { if (factory.moduleId && result.propagation.has(factory.moduleId) && hint === 'none') {
hint = result.propagation.get(factory.moduleId)!; hint = result.propagation.get(factory.moduleId)!;
} }
return hint === 'in-tree' || hint === 'self'; return hint === 'in-tree' || hint === 'self';

View file

@ -6,10 +6,10 @@ export type HeadAndContent = {
[headAndContentSym]: true; [headAndContentSym]: true;
head: string | RenderTemplateResult; head: string | RenderTemplateResult;
content: RenderTemplateResult; content: RenderTemplateResult;
} };
export function isHeadAndContent(obj: unknown): obj is HeadAndContent { export function isHeadAndContent(obj: unknown): obj is HeadAndContent {
return typeof obj === 'object' && !!((obj as any)[headAndContentSym]); return typeof obj === 'object' && !!(obj as any)[headAndContentSym];
} }
export function createHeadAndContent( export function createHeadAndContent(
@ -19,6 +19,6 @@ export function createHeadAndContent(
return { return {
[headAndContentSym]: true, [headAndContentSym]: true,
head, head,
content content,
} };
} }

View file

@ -1,25 +1,10 @@
export type { AstroComponentFactory } from './factory';
export { export { isAstroComponentFactory, renderToString } from './factory.js';
createAstroComponentInstance, export { createHeadAndContent, isHeadAndContent } from './head-and-content.js';
isAstroComponentInstance export type { AstroComponentInstance } from './instance';
} from './instance.js'; export { createAstroComponentInstance, isAstroComponentInstance } from './instance.js';
export {
isAstroComponentFactory,
renderToString
} from './factory.js';
export { export {
isRenderTemplateResult, isRenderTemplateResult,
renderAstroTemplateResult, renderAstroTemplateResult,
renderTemplate renderTemplate,
} from './render-template.js'; } from './render-template.js';
export {
isHeadAndContent,
createHeadAndContent
} from './head-and-content.js';
export type {
AstroComponentFactory
} from './factory';
export type {
AstroComponentInstance
} from './instance';

View file

@ -2,10 +2,10 @@ import type { SSRResult } from '../../../../@types/astro';
import type { AstroComponentFactory, AstroFactoryReturnValue } from './factory.js'; import type { AstroComponentFactory, AstroFactoryReturnValue } from './factory.js';
import { HydrationDirectiveProps } from '../../hydration.js'; import { HydrationDirectiveProps } from '../../hydration.js';
import { renderChild } from '../any.js';
import { isHeadAndContent } from './head-and-content.js';
import { isAPropagatingComponent } from './factory.js';
import { isPromise } from '../../util.js'; import { isPromise } from '../../util.js';
import { renderChild } from '../any.js';
import { isAPropagatingComponent } from './factory.js';
import { isHeadAndContent } from './head-and-content.js';
type ComponentProps = Record<string | number, any>; type ComponentProps = Record<string | number, any>;
@ -19,7 +19,12 @@ export class AstroComponentInstance {
private readonly slots: any; private readonly slots: any;
private readonly factory: AstroComponentFactory; private readonly factory: AstroComponentFactory;
private returnValue: ReturnType<AstroComponentFactory> | undefined; private returnValue: ReturnType<AstroComponentFactory> | undefined;
constructor(result: SSRResult, props: ComponentProps, slots: any, factory: AstroComponentFactory) { constructor(
result: SSRResult,
props: ComponentProps,
slots: any,
factory: AstroComponentFactory
) {
this.result = result; this.result = result;
this.props = props; this.props = props;
this.slots = slots; this.slots = slots;
@ -32,18 +37,18 @@ export class AstroComponentInstance {
} }
async *render() { async *render() {
if(this.returnValue === undefined) { if (this.returnValue === undefined) {
await this.init(); await this.init();
} }
let value: AstroFactoryReturnValue | undefined = this.returnValue; let value: AstroFactoryReturnValue | undefined = this.returnValue;
if(isPromise(value)) { if (isPromise(value)) {
value = await value; value = await value;
} }
if(isHeadAndContent(value)) { if (isHeadAndContent(value)) {
yield * value.content; yield* value.content;
} else { } else {
yield * renderChild(value); yield* renderChild(value);
} }
} }
} }
@ -71,12 +76,12 @@ export function createAstroComponentInstance(
) { ) {
validateComponentProps(props, displayName); validateComponentProps(props, displayName);
const instance = new AstroComponentInstance(result, props, slots, factory); const instance = new AstroComponentInstance(result, props, slots, factory);
if(isAPropagatingComponent(result, factory) && !result.propagators.has(factory)) { if (isAPropagatingComponent(result, factory) && !result.propagators.has(factory)) {
result.propagators.set(factory, instance); result.propagators.set(factory, instance);
} }
return instance; return instance;
} }
export function isAstroComponentInstance(obj: unknown): obj is AstroComponentInstance { export function isAstroComponentInstance(obj: unknown): obj is AstroComponentInstance {
return typeof obj === 'object' && !!((obj as any)[astroComponentInstanceSym]); return typeof obj === 'object' && !!(obj as any)[astroComponentInstanceSym];
} }

View file

@ -52,9 +52,7 @@ export class RenderTemplateResult {
// Determines if a component is an .astro component // Determines if a component is an .astro component
export function isRenderTemplateResult(obj: unknown): obj is RenderTemplateResult { export function isRenderTemplateResult(obj: unknown): obj is RenderTemplateResult {
return ( return typeof obj === 'object' && !!(obj as any)[renderTemplateResultSym];
typeof obj === 'object' && !!((obj as any)[renderTemplateResultSym])
);
} }
export async function* renderAstroTemplateResult( export async function* renderAstroTemplateResult(

View file

@ -1,9 +1,4 @@
import type { import type { AstroComponentMetadata, SSRLoadedRenderer, SSRResult } from '../../../@types/astro';
AstroComponentMetadata,
RouteData,
SSRLoadedRenderer,
SSRResult,
} from '../../../@types/astro';
import type { RenderInstruction } from './types.js'; import type { RenderInstruction } from './types.js';
import { AstroError, AstroErrorData } from '../../../core/errors/index.js'; import { AstroError, AstroErrorData } from '../../../core/errors/index.js';
@ -11,19 +6,19 @@ import { HTMLBytes, markHTMLString } from '../escape.js';
import { extractDirectives, generateHydrateScript } from '../hydration.js'; import { extractDirectives, generateHydrateScript } from '../hydration.js';
import { serializeProps } from '../serialize.js'; import { serializeProps } from '../serialize.js';
import { shorthash } from '../shorthash.js'; import { shorthash } from '../shorthash.js';
import { isPromise } from '../util.js';
import { import {
createAstroComponentInstance, createAstroComponentInstance,
isAstroComponentFactory, isAstroComponentFactory,
isAstroComponentInstance, isAstroComponentInstance,
renderAstroTemplateResult, renderAstroTemplateResult,
renderTemplate, renderTemplate,
type AstroComponentInstance type AstroComponentInstance,
} from './astro/index.js'; } from './astro/index.js';
import { Fragment, Renderer, stringifyChunk } from './common.js'; import { Fragment, Renderer, stringifyChunk } from './common.js';
import { componentIsHTMLElement, renderHTMLElement } from './dom.js'; import { componentIsHTMLElement, renderHTMLElement } from './dom.js';
import { renderSlot, renderSlots } from './slot.js'; import { renderSlot, renderSlots } from './slot.js';
import { formatList, internalSpreadAttributes, renderElement, voidElementNames } from './util.js'; import { formatList, internalSpreadAttributes, renderElement, voidElementNames } from './util.js';
import { isPromise } from '../util.js';
const rendererAliases = new Map([['solid', 'solid-js']]); const rendererAliases = new Map([['solid', 'solid-js']]);
@ -55,9 +50,7 @@ function isFragmentComponent(Component: unknown) {
} }
function isHTMLComponent(Component: unknown) { function isHTMLComponent(Component: unknown) {
return ( return Component && typeof Component === 'object' && (Component as any)['astro:html'];
Component && typeof Component === 'object' && (Component as any)['astro:html']
);
} }
async function renderFrameworkComponent( async function renderFrameworkComponent(
@ -65,7 +58,7 @@ async function renderFrameworkComponent(
displayName: string, displayName: string,
Component: unknown, Component: unknown,
_props: Record<string | number, any>, _props: Record<string | number, any>,
slots: any = {}, slots: any = {}
): Promise<ComponentIterable> { ): Promise<ComponentIterable> {
if (!Component && !_props['client:only']) { if (!Component && !_props['client:only']) {
throw new Error( throw new Error(
@ -358,22 +351,22 @@ export function renderComponent(
props: Record<string | number, any>, props: Record<string | number, any>,
slots: any = {} slots: any = {}
): Promise<ComponentIterable> | ComponentIterable | AstroComponentInstance { ): Promise<ComponentIterable> | ComponentIterable | AstroComponentInstance {
if(isPromise(Component)) { if (isPromise(Component)) {
return Promise.resolve(Component).then(Unwrapped => { return Promise.resolve(Component).then((Unwrapped) => {
return renderComponent(result, displayName, Unwrapped, props, slots) as any; return renderComponent(result, displayName, Unwrapped, props, slots) as any;
}); });
} }
if(isFragmentComponent(Component)) { if (isFragmentComponent(Component)) {
return renderFragmentComponent(result, slots); return renderFragmentComponent(result, slots);
} }
// .html components // .html components
if(isHTMLComponent(Component)) { if (isHTMLComponent(Component)) {
return renderHTMLComponent(result, Component, props, slots); return renderHTMLComponent(result, Component, props, slots);
} }
if(isAstroComponentFactory(Component)) { if (isAstroComponentFactory(Component)) {
return createAstroComponentInstance(result, displayName, Component, props, slots); return createAstroComponentInstance(result, displayName, Component, props, slots);
} }
@ -388,7 +381,7 @@ export function renderComponentToIterable(
slots: any = {} slots: any = {}
): Promise<ComponentIterable> | ComponentIterable { ): Promise<ComponentIterable> | ComponentIterable {
const renderResult = renderComponent(result, displayName, Component, props, slots); const renderResult = renderComponent(result, displayName, Component, props, slots);
if(isAstroComponentInstance(renderResult)) { if (isAstroComponentInstance(renderResult)) {
return renderResult.render(); return renderResult.render();
} }
return renderResult; return renderResult;

View file

@ -1,8 +1,8 @@
import type { SSRResult } from '../../../@types/astro'; import type { SSRResult } from '../../../@types/astro';
import { markHTMLString } from '../escape.js'; import { markHTMLString } from '../escape.js';
import { renderElement } from './util.js';
import { renderChild } from './any.js'; import { renderChild } from './any.js';
import { renderElement } from './util.js';
// Filter out duplicate elements in our set // Filter out duplicate elements in our set
const uniqueElements = (item: any, index: number, all: any[]) => { const uniqueElements = (item: any, index: number, all: any[]) => {
@ -13,10 +13,10 @@ const uniqueElements = (item: any, index: number, all: any[]) => {
); );
}; };
async function * renderExtraHead(result: SSRResult, base: string) { async function* renderExtraHead(result: SSRResult, base: string) {
yield base; yield base;
for(const part of result.extraHead) { for (const part of result.extraHead) {
yield * renderChild(part); yield* renderChild(part);
} }
} }
@ -35,9 +35,9 @@ function renderAllHeadContent(result: SSRResult) {
.filter(uniqueElements) .filter(uniqueElements)
.map((link) => renderElement('link', link, false)); .map((link) => renderElement('link', link, false));
const baseHeadContent = markHTMLString(links.join('\n') + styles.join('\n') + scripts.join('\n')) const baseHeadContent = markHTMLString(links.join('\n') + styles.join('\n') + scripts.join('\n'));
if(result.extraHead.length > 0) { if (result.extraHead.length > 0) {
return renderExtraHead(result, baseHeadContent); return renderExtraHead(result, baseHeadContent);
} else { } else {
return baseHeadContent; return baseHeadContent;

View file

@ -1,12 +1,16 @@
export type { RenderInstruction } from './types';
export type { AstroComponentFactory, AstroComponentInstance } from './astro/index'; export type { AstroComponentFactory, AstroComponentInstance } from './astro/index';
export {
export { createHeadAndContent, renderAstroTemplateResult, renderToString, renderTemplate } from './astro/index.js'; createHeadAndContent,
renderAstroTemplateResult,
renderTemplate,
renderToString,
} from './astro/index.js';
export { Fragment, Renderer, stringifyChunk } from './common.js'; export { Fragment, Renderer, stringifyChunk } from './common.js';
export { renderComponent, renderComponentToIterable } from './component.js'; export { renderComponent, renderComponentToIterable } from './component.js';
export { renderHTMLElement } from './dom.js'; export { renderHTMLElement } from './dom.js';
export { maybeRenderHead, renderHead } from './head.js'; export { maybeRenderHead, renderHead } from './head.js';
export { renderPage } from './page.js'; export { renderPage } from './page.js';
export { renderSlot } from './slot.js'; export { renderSlot } from './slot.js';
export { addAttribute, defineScriptVars, voidElementNames } from './util.js';
export { renderUniqueStylesheet } from './stylesheet.js'; export { renderUniqueStylesheet } from './stylesheet.js';
export type { RenderInstruction } from './types';
export { addAttribute, defineScriptVars, voidElementNames } from './util.js';

View file

@ -8,9 +8,9 @@ import { createResponse } from '../response.js';
import { import {
isAstroComponentFactory, isAstroComponentFactory,
isAstroComponentInstance, isAstroComponentInstance,
isRenderTemplateResult,
isHeadAndContent, isHeadAndContent,
renderAstroTemplateResult isRenderTemplateResult,
renderAstroTemplateResult,
} from './astro/index.js'; } from './astro/index.js';
import { chunkToByteArray, encoder, HTMLParts } from './common.js'; import { chunkToByteArray, encoder, HTMLParts } from './common.js';
import { renderComponent } from './component.js'; import { renderComponent } from './component.js';
@ -55,13 +55,13 @@ async function iterableToHTMLBytes(
// to be propagated up. // to be propagated up.
async function bufferHeadContent(result: SSRResult) { async function bufferHeadContent(result: SSRResult) {
const iterator = result.propagators.values(); const iterator = result.propagators.values();
while(true) { while (true) {
const { value, done } = iterator.next(); const { value, done } = iterator.next();
if(done) { if (done) {
break; break;
} }
const returnValue = await value.init(); const returnValue = await value.init();
if(isHeadAndContent(returnValue)) { if (isHeadAndContent(returnValue)) {
result.extraHead.push(returnValue.head); result.extraHead.push(returnValue.head);
} }
} }
@ -85,9 +85,9 @@ export async function renderPage(
componentFactory.name, componentFactory.name,
componentFactory, componentFactory,
pageProps, pageProps,
null, null
); );
if(isAstroComponentInstance(renderResult)) { if (isAstroComponentInstance(renderResult)) {
output = renderResult.render(); output = renderResult.render();
} else { } else {
output = renderResult; output = renderResult;
@ -123,7 +123,9 @@ export async function renderPage(
if (isRenderTemplateResult(factoryReturnValue) || factoryIsHeadAndContent) { if (isRenderTemplateResult(factoryReturnValue) || factoryIsHeadAndContent) {
// Wait for head content to be buffered up // Wait for head content to be buffered up
await bufferHeadContent(result); await bufferHeadContent(result);
const templateResult = factoryIsHeadAndContent ? factoryReturnValue.content : factoryReturnValue; const templateResult = factoryIsHeadAndContent
? factoryReturnValue.content
: factoryReturnValue;
let iterable = renderAstroTemplateResult(templateResult); let iterable = renderAstroTemplateResult(templateResult);
let init = result.response; let init = result.response;

View file

@ -1,22 +1,28 @@
import { SSRResult } from '../../../@types/astro'; import { SSRResult } from '../../../@types/astro';
import { renderElement } from './util.js';
import { markHTMLString } from '../escape.js'; import { markHTMLString } from '../escape.js';
import { renderElement } from './util.js';
const stylesheetRel = 'stylesheet'; const stylesheetRel = 'stylesheet';
export function renderStylesheet({ href }: { href: string }) { export function renderStylesheet({ href }: { href: string }) {
return markHTMLString(renderElement('link', { return markHTMLString(
props: { renderElement(
rel: stylesheetRel, 'link',
href {
}, props: {
children: '' rel: stylesheetRel,
}, false)); href,
},
children: '',
},
false
)
);
} }
export function renderUniqueStylesheet(result: SSRResult, link: { href: string }) { export function renderUniqueStylesheet(result: SSRResult, link: { href: string }) {
for (const existingLink of result.links) { for (const existingLink of result.links) {
if(existingLink.props.rel === stylesheetRel && existingLink.props.href === link.href) { if (existingLink.props.rel === stylesheetRel && existingLink.props.href === link.href) {
return ''; return '';
} }
} }

View file

@ -18,8 +18,8 @@ import { normalizeFilename } from '../vite-plugin-utils/index.js';
import { cachedFullCompilation } from './compile.js'; import { cachedFullCompilation } from './compile.js';
import { handleHotUpdate } from './hmr.js'; import { handleHotUpdate } from './hmr.js';
import { parseAstroRequest, ParsedRequestResult } from './query.js'; import { parseAstroRequest, ParsedRequestResult } from './query.js';
export type { AstroPluginMetadata };
export { getAstroMetadata } from './metadata.js'; export { getAstroMetadata } from './metadata.js';
export type { AstroPluginMetadata };
interface AstroPluginOptions { interface AstroPluginOptions {
settings: AstroSettings; settings: AstroSettings;

View file

@ -1,8 +1,8 @@
import type { PluginMetadata } from './types';
import type { ModuleInfo } from '../core/module-loader'; import type { ModuleInfo } from '../core/module-loader';
import type { PluginMetadata } from './types';
export function getAstroMetadata(modInfo: ModuleInfo): PluginMetadata['astro'] | undefined { export function getAstroMetadata(modInfo: ModuleInfo): PluginMetadata['astro'] | undefined {
if(modInfo.meta?.astro) { if (modInfo.meta?.astro) {
return modInfo.meta.astro as PluginMetadata['astro']; return modInfo.meta.astro as PluginMetadata['astro'];
} }
return undefined; return undefined;

View file

@ -1,5 +1,5 @@
import type { AstroSettings } from '../@types/astro';
import type { ModuleInfo } from 'rollup'; import type { ModuleInfo } from 'rollup';
import type { AstroSettings } from '../@types/astro';
import * as vite from 'vite'; import * as vite from 'vite';
import { getAstroMetadata } from '../vite-plugin-astro/index.js'; import { getAstroMetadata } from '../vite-plugin-astro/index.js';
@ -16,17 +16,22 @@ export default function configHeadPropagationVitePlugin({
}: { }: {
settings: AstroSettings; settings: AstroSettings;
}): vite.Plugin { }): vite.Plugin {
function addHeadInjectionInTree(graph: vite.ModuleGraph, id: string, getInfo: (id: string) => ModuleInfo | null, seen: Set<string> = new Set()) { function addHeadInjectionInTree(
graph: vite.ModuleGraph,
id: string,
getInfo: (id: string) => ModuleInfo | null,
seen: Set<string> = new Set()
) {
const mod = server.moduleGraph.getModuleById(id); const mod = server.moduleGraph.getModuleById(id);
for(const parent of mod?.importers || []) { for (const parent of mod?.importers || []) {
if(parent.id) { if (parent.id) {
if(seen.has(parent.id)) { if (seen.has(parent.id)) {
continue; continue;
} }
const info = getInfo(parent.id); const info = getInfo(parent.id);
if(info?.meta.astro) { if (info?.meta.astro) {
const astroMetadata = getAstroMetadata(info); const astroMetadata = getAstroMetadata(info);
if(astroMetadata) { if (astroMetadata) {
astroMetadata.propagation = 'in-tree'; astroMetadata.propagation = 'in-tree';
} }
} }
@ -42,13 +47,13 @@ export default function configHeadPropagationVitePlugin({
server = _server; server = _server;
}, },
transform(source, id) { transform(source, id) {
if(!server) { if (!server) {
return; return;
} }
if(injectExp.test(source)) { if (injectExp.test(source)) {
addHeadInjectionInTree(server.moduleGraph, id, (child) => this.getModuleInfo(child)); addHeadInjectionInTree(server.moduleGraph, id, (child) => this.getModuleInfo(child));
} }
} },
}; };
} }

View file

@ -233,7 +233,7 @@ ${tsResult}`;
clientOnlyComponents: transformResult.clientOnlyComponents, clientOnlyComponents: transformResult.clientOnlyComponents,
hydratedComponents: transformResult.hydratedComponents, hydratedComponents: transformResult.hydratedComponents,
scripts: transformResult.scripts, scripts: transformResult.scripts,
propagation: 'none' propagation: 'none',
}; };
return { return {

View file

@ -55,24 +55,28 @@ describe('head injection', () => {
root root
); );
await runInContainer({ await runInContainer(
fs, root, {
userConfig: { fs,
vite: { server: { middlewareMode: true } } root,
} userConfig: {
}, async (container) => { vite: { server: { middlewareMode: true } },
const { req, res, done, text } = createRequestAndResponse({ },
method: 'GET', },
url: '/', async (container) => {
}); const { req, res, done, text } = createRequestAndResponse({
container.handle(req, res); method: 'GET',
await done; url: '/',
const html = await text(); });
const $ = cheerio.load(html); container.handle(req, res);
await done;
const html = await text();
const $ = cheerio.load(html);
expect($('link[rel=stylesheet][href="/some/fake/styles.css"]')).to.have.a.lengthOf(1); expect($('link[rel=stylesheet][href="/some/fake/styles.css"]')).to.have.a.lengthOf(1);
expect($('#other')).to.have.a.lengthOf(1); expect($('#other')).to.have.a.lengthOf(1);
}); }
);
}); });
it('Dynamic injection from a layout component', async () => { it('Dynamic injection from a layout component', async () => {
@ -138,23 +142,27 @@ describe('head injection', () => {
root root
); );
await runInContainer({ await runInContainer(
fs, root, {
userConfig: { fs,
vite: { server: { middlewareMode: true } } root,
} userConfig: {
}, async (container) => { vite: { server: { middlewareMode: true } },
const { req, res, done, text } = createRequestAndResponse({ },
method: 'GET', },
url: '/', async (container) => {
}); const { req, res, done, text } = createRequestAndResponse({
container.handle(req, res); method: 'GET',
await done; url: '/',
const html = await text(); });
const $ = cheerio.load(html); container.handle(req, res);
await done;
const html = await text();
const $ = cheerio.load(html);
expect($('link[rel=stylesheet][href="/some/fake/styles.css"]')).to.have.a.lengthOf(1); expect($('link[rel=stylesheet][href="/some/fake/styles.css"]')).to.have.a.lengthOf(1);
expect($('#other')).to.have.a.lengthOf(1); expect($('#other')).to.have.a.lengthOf(1);
}); }
);
}); });
}); });