Serialize boolean attributes without a value (#422)
* Serialize boolean attributes without a value Fixes #307 * Update the attrs test * Adds a changeset * Adds test that components receive booleans
This commit is contained in:
parent
42dee7978d
commit
2d854092a4
7 changed files with 41 additions and 4 deletions
5
.changeset/sour-squids-trade.md
Normal file
5
.changeset/sour-squids-trade.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes serialization of boolean attributes
|
|
@ -1,4 +1,4 @@
|
||||||
export type HProps = Record<string, string> | null | undefined;
|
export type HProps = Record<string, string | boolean> | null | undefined;
|
||||||
export type HChild = string | undefined | (() => string);
|
export type HChild = string | undefined | (() => string);
|
||||||
export type AstroComponent = (props: HProps, ...children: Array<HChild>) => string;
|
export type AstroComponent = (props: HProps, ...children: Array<HChild>) => string;
|
||||||
export type HTag = string | AstroComponent;
|
export type HTag = string | AstroComponent;
|
||||||
|
@ -20,7 +20,8 @@ function* _h(tag: string, attrs: HProps, children: Array<HChild>) {
|
||||||
if (attrs) {
|
if (attrs) {
|
||||||
for (let [key, value] of Object.entries(attrs)) {
|
for (let [key, value] of Object.entries(attrs)) {
|
||||||
if (value === '') yield ` ${key}=""`;
|
if (value === '') yield ` ${key}=""`;
|
||||||
else if (value == null) yield '';
|
else if (value == null || value === false) yield '';
|
||||||
|
else if (value === true) yield ` ${key}`;
|
||||||
else yield ` ${key}="${value}"`;
|
else yield ` ${key}="${value}"`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ Attributes('Passes attributes to elements as expected', async ({ runtime }) => {
|
||||||
const $ = doc(result.contents);
|
const $ = doc(result.contents);
|
||||||
|
|
||||||
const ids = ['false-str', 'true-str', 'false', 'true', 'empty', 'null', 'undefined'];
|
const ids = ['false-str', 'true-str', 'false', 'true', 'empty', 'null', 'undefined'];
|
||||||
const specs = ['false', 'true', 'false', 'true', '', undefined, undefined];
|
const specs = ['false', 'true', undefined, '', '', undefined, undefined];
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (const id of ids) {
|
for (const id of ids) {
|
||||||
|
@ -25,4 +25,15 @@ Attributes('Passes attributes to elements as expected', async ({ runtime }) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Attributes('Passes boolean attributes to components as expected', async ({ runtime }) => {
|
||||||
|
const result = await runtime.load('/component');
|
||||||
|
if (result.error) throw new Error(result.error);
|
||||||
|
|
||||||
|
const $ = doc(result.contents);
|
||||||
|
assert.equal($('#true').attr('attr'), 'attr-true');
|
||||||
|
assert.equal($('#true').attr('type'), 'boolean');
|
||||||
|
assert.equal($('#false').attr('attr'), 'attr-false');
|
||||||
|
assert.equal($('#false').attr('type'), 'boolean');
|
||||||
|
});
|
||||||
|
|
||||||
Attributes.run();
|
Attributes.run();
|
||||||
|
|
|
@ -32,4 +32,12 @@ Basics('Does not set the HMR port when no dynamic component used', async ({ runt
|
||||||
assert.ok(!/HMR_WEBSOCKET_URL/.test(html), 'Does not set the websocket port');
|
assert.ok(!/HMR_WEBSOCKET_URL/.test(html), 'Does not set the websocket port');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Basics('Correctly serializes boolean attributes', async ({ runtime }) => {
|
||||||
|
const result = await runtime.load('/');
|
||||||
|
const html = result.contents;
|
||||||
|
const $ = doc(html);
|
||||||
|
assert.equal($('h1').attr('data-something'), '');
|
||||||
|
assert.equal($('h2').attr('not-data-ok'), '');
|
||||||
|
});
|
||||||
|
|
||||||
Basics.run();
|
Basics.run();
|
||||||
|
|
5
packages/astro/test/fixtures/astro-attrs/src/components/Span.jsx
vendored
Normal file
5
packages/astro/test/fixtures/astro-attrs/src/components/Span.jsx
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function({ id, attr }) {
|
||||||
|
return <span id={id} attr={`attr-${attr}`} type={typeof attr}></span>
|
||||||
|
}
|
6
packages/astro/test/fixtures/astro-attrs/src/pages/component.astro
vendored
Normal file
6
packages/astro/test/fixtures/astro-attrs/src/pages/component.astro
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
import Span from '../components/Span.jsx';
|
||||||
|
---
|
||||||
|
|
||||||
|
<Span id="true" attr={true} />
|
||||||
|
<Span id="false" attr={false} />
|
|
@ -7,6 +7,7 @@ let title = 'My App'
|
||||||
<!-- Head Stuff -->
|
<!-- Head Stuff -->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Hello world!</h1>
|
<h1 data-something>Hello world!</h1>
|
||||||
|
<h2 not-data-ok>Subtitle here</h2>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue