Completely fixes head/doctype stuff
This commit is contained in:
parent
b2075cc137
commit
5e568571f0
7 changed files with 74 additions and 48 deletions
|
@ -146,8 +146,8 @@ async function __render(props, ...children) {
|
||||||
value: props,
|
value: props,
|
||||||
enumerable: true
|
enumerable: true
|
||||||
},
|
},
|
||||||
css: {
|
pageCSS: {
|
||||||
value: (props[__astroInternal] && props[__astroInternal].css) || [],
|
value: (props[__astroContext] && props[__astroContext].pageCSS) || [],
|
||||||
enumerable: true
|
enumerable: true
|
||||||
},
|
},
|
||||||
isPage: {
|
isPage: {
|
||||||
|
@ -177,6 +177,7 @@ export async function __renderPage({request, children, props, css}) {
|
||||||
|
|
||||||
Object.defineProperty(props, __astroContext, {
|
Object.defineProperty(props, __astroContext, {
|
||||||
value: {
|
value: {
|
||||||
|
pageCSS: css,
|
||||||
request
|
request
|
||||||
},
|
},
|
||||||
writable: false,
|
writable: false,
|
||||||
|
@ -185,7 +186,6 @@ export async function __renderPage({request, children, props, css}) {
|
||||||
|
|
||||||
Object.defineProperty(props, __astroInternal, {
|
Object.defineProperty(props, __astroInternal, {
|
||||||
value: {
|
value: {
|
||||||
css,
|
|
||||||
isPage: true
|
isPage: true
|
||||||
},
|
},
|
||||||
writable: false,
|
writable: false,
|
||||||
|
|
|
@ -73,7 +73,7 @@ export default function (opts: TransformOptions): Transformer {
|
||||||
start: 0,
|
start: 0,
|
||||||
end: 0,
|
end: 0,
|
||||||
type: 'Expression',
|
type: 'Expression',
|
||||||
codeChunks: ['Astro.css.map(css => (', '))'],
|
codeChunks: ['Astro.pageCSS.map(css => (', '))'],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
type: 'Element',
|
type: 'Element',
|
||||||
|
@ -162,22 +162,15 @@ export default function (opts: TransformOptions): Transformer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const conditionalNode = {
|
if(eoh.foundHeadOrHtmlElement) {
|
||||||
start: 0,
|
const topLevelFragment = {
|
||||||
end: 0,
|
start: 0,
|
||||||
type: 'Expression',
|
end: 0,
|
||||||
codeChunks: ['Astro.isPage ? (', ') : null'],
|
type: 'Fragment',
|
||||||
children: [
|
children,
|
||||||
{
|
};
|
||||||
start: 0,
|
eoh.append(topLevelFragment);
|
||||||
end: 0,
|
}
|
||||||
type: 'Fragment',
|
|
||||||
children,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
eoh.append(conditionalNode);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
import type { TemplateNode } from '@astrojs/parser';
|
import type { TemplateNode } from '@astrojs/parser';
|
||||||
|
|
||||||
|
const beforeHeadElements = new Set(['!doctype', 'html']);
|
||||||
const validHeadElements = new Set(['!doctype', 'title', 'meta', 'link', 'style', 'script', 'noscript', 'base']);
|
const validHeadElements = new Set(['!doctype', 'title', 'meta', 'link', 'style', 'script', 'noscript', 'base']);
|
||||||
|
|
||||||
export class EndOfHead {
|
export class EndOfHead {
|
||||||
|
private html: TemplateNode | null = null;
|
||||||
private head: TemplateNode | null = null;
|
private head: TemplateNode | null = null;
|
||||||
private firstNonHead: TemplateNode | null = null;
|
private firstNonHead: TemplateNode | null = null;
|
||||||
private parent: TemplateNode | null = null;
|
private parent: TemplateNode | null = null;
|
||||||
private stack: TemplateNode[] = [];
|
private stack: TemplateNode[] = [];
|
||||||
|
private foundHeadElements: boolean = false;
|
||||||
|
|
||||||
public append: (...node: TemplateNode[]) => void = () => void 0;
|
public append: (...node: TemplateNode[]) => void = () => void 0;
|
||||||
|
|
||||||
|
@ -14,6 +17,14 @@ export class EndOfHead {
|
||||||
return !!(this.head || this.firstNonHead);
|
return !!(this.head || this.firstNonHead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get foundHeadContent(): boolean {
|
||||||
|
return !!this.head || this.foundHeadElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
get foundHeadOrHtmlElement(): boolean {
|
||||||
|
return !!(this.html || this.head);
|
||||||
|
}
|
||||||
|
|
||||||
enter(node: TemplateNode) {
|
enter(node: TemplateNode) {
|
||||||
if (this.found) {
|
if (this.found) {
|
||||||
return;
|
return;
|
||||||
|
@ -35,6 +46,14 @@ export class EndOfHead {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip !doctype and html elements
|
||||||
|
if(beforeHeadElements.has(name)) {
|
||||||
|
if(name === 'html') {
|
||||||
|
this.html = node;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!validHeadElements.has(name)) {
|
if (!validHeadElements.has(name)) {
|
||||||
this.firstNonHead = node;
|
this.firstNonHead = node;
|
||||||
this.parent = this.stack[this.stack.length - 2];
|
this.parent = this.stack[this.stack.length - 2];
|
||||||
|
|
|
@ -1,36 +1,11 @@
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import { suite } from 'uvu';
|
import { suite } from 'uvu';
|
||||||
import * as assert from 'uvu/assert';
|
import * as assert from 'uvu/assert';
|
||||||
import { loadConfig } from '#astro/config';
|
import { doc } from './test-utils.js';
|
||||||
import { createRuntime } from '#astro/runtime';
|
import { setup } from './helpers.js';
|
||||||
|
|
||||||
const DType = suite('doctype');
|
const DType = suite('doctype');
|
||||||
|
|
||||||
let runtime, setupError;
|
setup(DType, './fixtures/astro-doctype');
|
||||||
|
|
||||||
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 () => {
|
DType('Automatically prepends the standards mode doctype', async () => {
|
||||||
const result = await runtime.load('/prepend');
|
const result = await runtime.load('/prepend');
|
||||||
|
@ -65,4 +40,23 @@ DType('User provided doctype is case insensitive', async () => {
|
||||||
assert.not.ok(html.includes('</!DOCTYPE>'), 'There should not be a closing tag');
|
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();
|
DType.run();
|
||||||
|
|
5
packages/astro/test/fixtures/astro-doctype/src/components/Meta.astro
vendored
Normal file
5
packages/astro/test/fixtures/astro-doctype/src/components/Meta.astro
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
import SubMeta from './SubMeta.astro';
|
||||||
|
---
|
||||||
|
<meta name="author" content="Astro Fan">
|
||||||
|
<SubMeta />
|
1
packages/astro/test/fixtures/astro-doctype/src/components/SubMeta.astro
vendored
Normal file
1
packages/astro/test/fixtures/astro-doctype/src/components/SubMeta.astro
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<meta name="keywords" content="JavaScript,Astro">
|
14
packages/astro/test/fixtures/astro-doctype/src/layouts/WithDoctype.astro
vendored
Normal file
14
packages/astro/test/fixtures/astro-doctype/src/layouts/WithDoctype.astro
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
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>
|
Loading…
Reference in a new issue