Correctly serialize falsey values at top-level of components (#834)
* Correctly serialize falsey values at top-level of components * Adding a changeset
This commit is contained in:
parent
0c729f248d
commit
164489fbb2
5 changed files with 61 additions and 16 deletions
5
.changeset/healthy-pants-rule.md
Normal file
5
.changeset/healthy-pants-rule.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix for `false` being rendered in conditionals
|
|
@ -5,6 +5,23 @@ export type HTag = string | AstroComponent;
|
|||
|
||||
const voidTags = new Set(['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']);
|
||||
|
||||
function* _children(children: Array<HChild>) {
|
||||
for (let child of children) {
|
||||
// Special: If a child is a function, call it automatically.
|
||||
// This lets you do {() => ...} without the extra boilerplate
|
||||
// of wrapping it in a function and calling it.
|
||||
if (typeof child === 'function') {
|
||||
yield child();
|
||||
} else if (typeof child === 'string') {
|
||||
yield child;
|
||||
} else if (!child && child !== 0) {
|
||||
// do nothing, safe to ignore falsey values.
|
||||
} else {
|
||||
yield child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Generator for primary h() function */
|
||||
function* _h(tag: string, attrs: HProps, children: Array<HChild>) {
|
||||
if (tag.toLowerCase() === '!doctype') {
|
||||
|
@ -32,20 +49,7 @@ function* _h(tag: string, attrs: HProps, children: Array<HChild>) {
|
|||
return;
|
||||
}
|
||||
|
||||
for (let child of children) {
|
||||
// Special: If a child is a function, call it automatically.
|
||||
// This lets you do {() => ...} without the extra boilerplate
|
||||
// of wrapping it in a function and calling it.
|
||||
if (typeof child === 'function') {
|
||||
yield child();
|
||||
} else if (typeof child === 'string') {
|
||||
yield child;
|
||||
} else if (!child && child !== 0) {
|
||||
// do nothing, safe to ignore falsey values.
|
||||
} else {
|
||||
yield child;
|
||||
}
|
||||
}
|
||||
yield * _children(children);
|
||||
|
||||
yield `</${tag}>`;
|
||||
}
|
||||
|
@ -62,6 +66,6 @@ export async function h(tag: HTag, attrs: HProps, ...pChildren: Array<Promise<HC
|
|||
}
|
||||
|
||||
/** Fragment helper, similar to React.Fragment */
|
||||
export function Fragment(_: HProps, ...children: Array<string>) {
|
||||
return children.join('');
|
||||
export function Fragment(_: HProps, ...children: Array<HChild>) {
|
||||
return Array.from(_children(children)).join('');
|
||||
}
|
||||
|
|
|
@ -80,6 +80,12 @@ Expressions('Does not render falsy values using &&', async ({ runtime }) => {
|
|||
assert.equal($('#false').length, 0, `Expected {false && <span id="false" />} not to render`);
|
||||
assert.equal($('#null').length, 0, `Expected {null && <span id="null" />} not to render`);
|
||||
assert.equal($('#undefined').length, 0, `Expected {undefined && <span id="undefined" />} not to render`);
|
||||
|
||||
// Inside of a component
|
||||
assert.equal($('#frag-true').length, 1, `Expected {true && <span id="true" />} to render`);
|
||||
assert.equal($('#frag-false').length, 0, `Expected {false && <span id="false" />} not to render`);
|
||||
assert.equal($('#frag-null').length, 0, `Expected {null && <span id="null" />} not to render`);
|
||||
assert.equal($('#frag-undefined').length, 0, `Expected {undefined && <span id="undefined" />} not to render`);
|
||||
});
|
||||
|
||||
Expressions.run();
|
||||
|
|
23
packages/astro/test/fixtures/astro-expr/src/components/falsy.astro
vendored
Normal file
23
packages/astro/test/fixtures/astro-expr/src/components/falsy.astro
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
const { items, emptyItems } = Astro.props;
|
||||
|
||||
const internal = [];
|
||||
---
|
||||
|
||||
<!-- False -->
|
||||
{false && (
|
||||
<span id="frag-false" />
|
||||
)}
|
||||
|
||||
<!-- Null -->
|
||||
{null && (
|
||||
<span id="frag-null" />
|
||||
)}
|
||||
|
||||
<!-- True -->
|
||||
{true && (
|
||||
<span id="frag-true" />
|
||||
)}
|
||||
|
||||
<!-- Undefined -->
|
||||
{false && (<span id="frag-undefined" />)}
|
|
@ -1,3 +1,6 @@
|
|||
---
|
||||
import Falsey from '../components/falsy.astro';
|
||||
---
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>My site</title>
|
||||
|
@ -8,5 +11,9 @@
|
|||
{undefined && <span id="undefined" />}
|
||||
{true && <span id="true" />}
|
||||
<span id="zero">{0 && "VALUE"}</span>
|
||||
|
||||
<section id="fragment-container">
|
||||
<Falsey />
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue