mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
Fix set:html
behavior with null
(#2790)
* feat: improve set:html behavior for null/undefined * chore: add changeset * refactor: improve set:html and set:text documentation * test: improve set:html tests * refactor: better types for server API
This commit is contained in:
parent
de2b246237
commit
6b34840d3d
5 changed files with 57 additions and 6 deletions
5
.changeset/serious-guests-matter.md
Normal file
5
.changeset/serious-guests-matter.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Improve `set:html` behavior for `null` and `undefined` values
|
|
@ -1,6 +1,7 @@
|
|||
const entities = { '"': 'quot', '&': 'amp', "'": 'apos', '<': 'lt', '>': 'gt' } as const;
|
||||
|
||||
export const escapeHTML = (string: any) => string.replace(/["'&<>]/g, (char: keyof typeof entities) => '&' + entities[char] + ';');
|
||||
// This util is only ever run on expression values that we already know are of type `string`
|
||||
export const escapeHTML = (str: string) => str.replace(/["'&<>]/g, (char: string) => '&' + entities[char as keyof typeof entities] + ';');
|
||||
|
||||
/**
|
||||
* RawString is a "blessed" version of String
|
||||
|
@ -11,7 +12,14 @@ export class UnescapedString extends String {}
|
|||
/**
|
||||
* unescapeHTML marks a string as raw, unescaped HTML.
|
||||
* This should only be generated internally, not a public API.
|
||||
*
|
||||
* Need to cast the return value `as unknown as string` so TS doesn't yell at us.
|
||||
*/
|
||||
export const unescapeHTML = (str: any) => new UnescapedString(str) as unknown as string;
|
||||
export const unescapeHTML = (value: any) => {
|
||||
// Cast any `string` values to `UnescapedString` to mark them as ignored
|
||||
// The `as unknown as string` is necessary for TypeScript to treat this as `string`
|
||||
if (typeof value === 'string') {
|
||||
return new UnescapedString(value) as unknown as string;
|
||||
}
|
||||
// Just return values that are `number`, `null`, `undefined` etc
|
||||
// The compiler will recursively stringify these correctly
|
||||
return value
|
||||
}
|
||||
|
|
|
@ -418,7 +418,7 @@ export async function renderEndpoint(mod: EndpointHandler, params: any) {
|
|||
}
|
||||
|
||||
// Calls a component and renders it into a string of HTML
|
||||
export async function renderToString(result: SSRResult, componentFactory: AstroComponentFactory, props: any, children: any) {
|
||||
export async function renderToString(result: SSRResult, componentFactory: AstroComponentFactory, props: any, children: any): Promise<string> {
|
||||
const Component = await componentFactory(result, props, children);
|
||||
let template = await renderAstroComponent(Component);
|
||||
|
||||
|
@ -439,7 +439,7 @@ const uniqueElements = (item: any, index: number, all: any[]) => {
|
|||
|
||||
// Renders a page to completion by first calling the factory callback, waiting for its result, and then appending
|
||||
// styles and scripts into the head.
|
||||
export async function renderHead(result: SSRResult) {
|
||||
export async function renderHead(result: SSRResult): Promise<string> {
|
||||
const styles = Array.from(result.styles)
|
||||
.filter(uniqueElements)
|
||||
.map((style) => {
|
||||
|
|
|
@ -17,4 +17,30 @@ describe('Directives', async () => {
|
|||
expect($('script#inline')).to.have.lengthOf(1);
|
||||
expect($('script#inline').toString()).to.include('let foo = "bar"');
|
||||
});
|
||||
|
||||
it('set:html', async () => {
|
||||
const html = await fixture.readFile('/set-html/index.html');
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
expect($('#text')).to.have.lengthOf(1);
|
||||
expect($('#text').text()).to.equal('a');
|
||||
|
||||
expect($('#zero')).to.have.lengthOf(1);
|
||||
expect($('#zero').text()).to.equal('0');
|
||||
|
||||
expect($('#number')).to.have.lengthOf(1);
|
||||
expect($('#number').text()).to.equal('1');
|
||||
|
||||
expect($('#undefined')).to.have.lengthOf(1);
|
||||
expect($('#undefined').text()).to.equal('');
|
||||
|
||||
expect($('#null')).to.have.lengthOf(1);
|
||||
expect($('#null').text()).to.equal('');
|
||||
|
||||
expect($('#false')).to.have.lengthOf(1);
|
||||
expect($('#false').text()).to.equal('');
|
||||
|
||||
expect($('#true')).to.have.lengthOf(1);
|
||||
expect($('#true').text()).to.equal('true');
|
||||
});
|
||||
});
|
||||
|
|
12
packages/astro/test/fixtures/astro-directives/src/pages/set-html.astro
vendored
Normal file
12
packages/astro/test/fixtures/astro-directives/src/pages/set-html.astro
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<div id="text" set:html={"a"} />
|
||||
<div id="zero" set:html={0} />
|
||||
<div id="number" set:html={1} />
|
||||
<div id="false" set:html={false} />
|
||||
<div id="true" set:html={true} />
|
||||
<div id="undefined" set:html={undefined} />
|
||||
<div id="null" set:html={null} />
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue