* Revert "Fixes duplicate head content (#995)"
This reverts commit 268a36f399
.
* Changeset
This commit is contained in:
parent
57b736211a
commit
b1959f0fed
16 changed files with 78 additions and 121 deletions
5
.changeset/eighty-walls-count.md
Normal file
5
.changeset/eighty-walls-count.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Reverts a change to head content that was breaking docs site
|
|
@ -662,7 +662,7 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile
|
|||
buffers[curr] += `h(__astro_slot_content, { name: ${attributes.slot} },`;
|
||||
paren++;
|
||||
}
|
||||
buffers[curr] += `h("${name}", ${generateAttributes(attributes)},`;
|
||||
buffers[curr] += `h("${name}", ${generateAttributes(attributes)}`;
|
||||
paren++;
|
||||
return;
|
||||
}
|
||||
|
@ -692,7 +692,7 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile
|
|||
buffers[curr] += `h(__astro_slot_content, { name: ${attributes.slot} },`;
|
||||
paren++;
|
||||
}
|
||||
buffers[curr] += `h(${componentName}, ${generateAttributes(attributes)},`;
|
||||
buffers[curr] += `h(${componentName}, ${generateAttributes(attributes)}`;
|
||||
paren++;
|
||||
return;
|
||||
} else if (!componentInfo && !isCustomElementTag(componentName)) {
|
||||
|
|
|
@ -150,8 +150,8 @@ async function __render(props, ...children) {
|
|||
value: props,
|
||||
enumerable: true
|
||||
},
|
||||
pageCSS: {
|
||||
value: (props[__astroContext] && props[__astroContext].pageCSS) || [],
|
||||
css: {
|
||||
value: (props[__astroInternal] && props[__astroInternal].css) || [],
|
||||
enumerable: true
|
||||
},
|
||||
isPage: {
|
||||
|
@ -181,7 +181,6 @@ export async function __renderPage({request, children, props, css}) {
|
|||
|
||||
Object.defineProperty(props, __astroContext, {
|
||||
value: {
|
||||
pageCSS: css,
|
||||
request
|
||||
},
|
||||
writable: false,
|
||||
|
@ -190,6 +189,7 @@ export async function __renderPage({request, children, props, css}) {
|
|||
|
||||
Object.defineProperty(props, __astroInternal, {
|
||||
value: {
|
||||
css,
|
||||
isPage: true
|
||||
},
|
||||
writable: false,
|
||||
|
|
|
@ -73,7 +73,7 @@ export default function (opts: TransformOptions): Transformer {
|
|||
start: 0,
|
||||
end: 0,
|
||||
type: 'Expression',
|
||||
codeChunks: ['Astro.pageCSS.map(css => (', '))'],
|
||||
codeChunks: ['Astro.css.map(css => (', '))'],
|
||||
children: [
|
||||
{
|
||||
type: 'Element',
|
||||
|
@ -162,15 +162,22 @@ export default function (opts: TransformOptions): Transformer {
|
|||
);
|
||||
}
|
||||
|
||||
if (eoh.foundHeadOrHtmlElement || eoh.foundHeadAndBodyContent) {
|
||||
const topLevelFragment = {
|
||||
const conditionalNode = {
|
||||
start: 0,
|
||||
end: 0,
|
||||
type: 'Expression',
|
||||
codeChunks: ['Astro.isPage ? (', ') : null'],
|
||||
children: [
|
||||
{
|
||||
start: 0,
|
||||
end: 0,
|
||||
type: 'Fragment',
|
||||
children,
|
||||
},
|
||||
],
|
||||
};
|
||||
eoh.append(topLevelFragment);
|
||||
}
|
||||
|
||||
eoh.append(conditionalNode);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,44 +1,21 @@
|
|||
import type { TemplateNode } from '@astrojs/parser';
|
||||
|
||||
const beforeHeadElements = new Set(['!doctype', 'html']);
|
||||
const validHeadElements = new Set(['title', 'meta', 'link', 'style', 'script', 'noscript', 'base']);
|
||||
const validHeadElements = new Set(['!doctype', 'title', 'meta', 'link', 'style', 'script', 'noscript', 'base']);
|
||||
|
||||
export class EndOfHead {
|
||||
private html: TemplateNode | null = null;
|
||||
private head: TemplateNode | null = null;
|
||||
private firstNonHead: TemplateNode | null = null;
|
||||
private parent: TemplateNode | null = null;
|
||||
private stack: TemplateNode[] = [];
|
||||
|
||||
public foundHeadElements = false;
|
||||
public foundBodyElements = false;
|
||||
public append: (...node: TemplateNode[]) => void = () => void 0;
|
||||
|
||||
get found(): boolean {
|
||||
return !!(this.head || this.firstNonHead);
|
||||
}
|
||||
|
||||
get foundHeadContent(): boolean {
|
||||
return !!this.head || this.foundHeadElements;
|
||||
}
|
||||
|
||||
get foundHeadAndBodyContent(): boolean {
|
||||
return this.foundHeadContent && this.foundBodyElements;
|
||||
}
|
||||
|
||||
get foundHeadOrHtmlElement(): boolean {
|
||||
return !!(this.html || this.head);
|
||||
}
|
||||
|
||||
enter(node: TemplateNode) {
|
||||
const name = node.name ? node.name.toLowerCase() : null;
|
||||
|
||||
if (this.found) {
|
||||
if (!validHeadElements.has(name)) {
|
||||
if (node.type === 'Element') {
|
||||
this.foundBodyElements = true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -49,6 +26,8 @@ export class EndOfHead {
|
|||
return;
|
||||
}
|
||||
|
||||
const name = node.name.toLowerCase();
|
||||
|
||||
if (name === 'head') {
|
||||
this.head = node;
|
||||
this.parent = this.stack[this.stack.length - 2];
|
||||
|
@ -56,24 +35,11 @@ export class EndOfHead {
|
|||
return;
|
||||
}
|
||||
|
||||
// Skip !doctype and html elements
|
||||
if (beforeHeadElements.has(name)) {
|
||||
if (name === 'html') {
|
||||
this.html = node;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!validHeadElements.has(name)) {
|
||||
if (node.type === 'Element') {
|
||||
this.foundBodyElements = true;
|
||||
}
|
||||
this.firstNonHead = node;
|
||||
this.parent = this.stack[this.stack.length - 2];
|
||||
this.append = this.prependToFirstNonHead;
|
||||
return;
|
||||
} else {
|
||||
this.foundHeadElements = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,38 @@
|
|||
import { fileURLToPath } from 'url';
|
||||
import { suite } from 'uvu';
|
||||
import * as assert from 'uvu/assert';
|
||||
import { doc } from './test-utils.js';
|
||||
import { setup } from './helpers.js';
|
||||
import { loadConfig } from '#astro/config';
|
||||
import { createRuntime } from '#astro/runtime';
|
||||
|
||||
const DType = suite('doctype');
|
||||
|
||||
setup(DType, './fixtures/astro-doctype');
|
||||
let runtime, setupError;
|
||||
|
||||
DType('Automatically prepends the standards mode doctype', async ({ runtime }) => {
|
||||
DType.before(async () => {
|
||||
try {
|
||||
const astroConfig = await loadConfig(fileURLToPath(new URL('./fixtures/astro-doctype', import.meta.url)));
|
||||
|
||||
const logging = {
|
||||
level: 'error',
|
||||
dest: process.stderr,
|
||||
};
|
||||
|
||||
runtime = await createRuntime(astroConfig, { logging });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
setupError = err;
|
||||
}
|
||||
});
|
||||
|
||||
DType.after(async () => {
|
||||
(await runtime) && runtime.shutdown();
|
||||
});
|
||||
|
||||
DType('No errors creating a runtime', () => {
|
||||
assert.equal(setupError, undefined);
|
||||
});
|
||||
|
||||
DType('Automatically prepends the standards mode doctype', async () => {
|
||||
const result = await runtime.load('/prepend');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
|
@ -15,7 +40,7 @@ DType('Automatically prepends the standards mode doctype', async ({ runtime }) =
|
|||
assert.ok(html.startsWith('<!doctype html>'), 'Doctype always included');
|
||||
});
|
||||
|
||||
DType('No attributes added when doctype is provided by user', async ({ runtime }) => {
|
||||
DType('No attributes added when doctype is provided by user', async () => {
|
||||
const result = await runtime.load('/provided');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
|
@ -23,7 +48,7 @@ DType('No attributes added when doctype is provided by user', async ({ runtime }
|
|||
assert.ok(html.startsWith('<!doctype html>'), 'Doctype always included');
|
||||
});
|
||||
|
||||
DType.skip('Preserves user provided doctype', async ({ runtime }) => {
|
||||
DType.skip('Preserves user provided doctype', async () => {
|
||||
const result = await runtime.load('/preserve');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
|
@ -31,7 +56,7 @@ DType.skip('Preserves user provided doctype', async ({ runtime }) => {
|
|||
assert.ok(html.startsWith('<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'), 'Doctype included was preserved');
|
||||
});
|
||||
|
||||
DType('User provided doctype is case insensitive', async ({ runtime }) => {
|
||||
DType('User provided doctype is case insensitive', async () => {
|
||||
const result = await runtime.load('/capital');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
|
@ -40,23 +65,4 @@ DType('User provided doctype is case insensitive', async ({ runtime }) => {
|
|||
assert.not.ok(html.includes('</!DOCTYPE>'), 'There should not be a closing tag');
|
||||
});
|
||||
|
||||
DType('Doctype can be provided in a layout', async ({ runtime }) => {
|
||||
const result = await runtime.load('/in-layout');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
const html = result.contents.toString('utf-8');
|
||||
assert.ok(html.startsWith('<!doctype html>'), 'doctype is at the front');
|
||||
|
||||
const $ = doc(html);
|
||||
assert.equal($('head link').length, 1, 'A link inside of the head');
|
||||
});
|
||||
|
||||
DType('Doctype is added in a layout without one', async ({ runtime }) => {
|
||||
const result = await runtime.load('/in-layout-no-doctype');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
const html = result.contents.toString('utf-8');
|
||||
assert.ok(html.startsWith('<!doctype html>'), 'doctype is at the front');
|
||||
});
|
||||
|
||||
DType.run();
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
import SubMeta from './SubMeta.astro';
|
||||
---
|
||||
<meta name="author" content="Astro Fan">
|
||||
<SubMeta />
|
|
@ -1 +0,0 @@
|
|||
<meta name="keywords" content="JavaScript,Astro">
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
import '../styles/global.css';
|
||||
import Meta from '../components/Meta.astro';
|
||||
---
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>My App</title>
|
||||
<Meta />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
import '../styles/global.css'
|
||||
---
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>My App</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
import WithoutDoctype from '../layouts/WithoutDoctype.astro';
|
||||
---
|
||||
<WithoutDoctype />
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
import WithDoctype from '../layouts/WithDoctype.astro';
|
||||
---
|
||||
<WithDoctype />
|
|
@ -1,3 +0,0 @@
|
|||
body {
|
||||
background: green;
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
import Something from '../components/Something.jsx';
|
||||
import Child from '../components/Child.astro';
|
||||
---
|
||||
|
||||
<title>My page</title>
|
||||
<style>
|
||||
.h1 {
|
||||
|
|
6
packages/astro/test/fixtures/no-head-el/src/pages/no-elements.astro
vendored
Normal file
6
packages/astro/test/fixtures/no-head-el/src/pages/no-elements.astro
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
import Something from '../components/Something.jsx';
|
||||
import Child from '../components/Child.astro';
|
||||
---
|
||||
<Something client:load />
|
||||
<Child />
|
|
@ -25,4 +25,14 @@ NoHeadEl('Places style and scripts before the first non-head element', async ({
|
|||
assert.equal($('script[src="/_snowpack/hmr-client.js"]').length, 1, 'Only the hmr client for the page');
|
||||
});
|
||||
|
||||
NoHeadEl('Injects HMR script even when there are no elements on the page', async ({ runtime }) => {
|
||||
const result = await runtime.load('/no-elements');
|
||||
assert.ok(!result.error, `build error: ${result.error}`);
|
||||
|
||||
const html = result.contents;
|
||||
const $ = doc(html);
|
||||
|
||||
assert.equal($('script[src="/_snowpack/hmr-client.js"]').length, 1, 'Only the hmr client for the page');
|
||||
});
|
||||
|
||||
NoHeadEl.run();
|
||||
|
|
Loading…
Reference in a new issue