Skip to content

Commit

Permalink
better string coercion (observablehq#179)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock authored Sep 24, 2021
1 parent ae1f0d2 commit 424dd32
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/css.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export function length(x) {
return x == null ? null : typeof x === "number" ? `${x}px` : x + "";
return x == null ? null : typeof x === "number" ? `${x}px` : `${x}`;
}

export function maybeWidth(width) {
Expand Down
30 changes: 16 additions & 14 deletions src/format.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// Note: use formatAuto (or any other localized format) to present values to the
// user; stringify is only intended for machine values.
export function stringify(x) {
return x == null ? "" : x + "";
return x == null ? "" : `${x}`;
}

export const formatLocaleAuto = localize(locale => {
const formatNumber = formatLocaleNumber(locale);
return value => value == null ? ""
: typeof value === "number" ? formatNumber(value)
: value instanceof Date ? formatDate(value)
: value + "";
: `${value}`;
});

export const formatLocaleNumber = localize(locale => {
Expand All @@ -35,24 +35,26 @@ export function formatTrim(value) {
}

export function formatDate(date) {
var hours = date.getUTCHours(),
minutes = date.getUTCMinutes(),
seconds = date.getUTCSeconds(),
milliseconds = date.getUTCMilliseconds();
return isNaN(date) ? "Invalid Date"
: formatYear(date.getUTCFullYear(), 4) + "-" + pad(date.getUTCMonth() + 1, 2) + "-" + pad(date.getUTCDate(), 2)
+ (milliseconds ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + "." + pad(milliseconds, 3) + "Z"
: seconds ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + "Z"
: minutes || hours ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + "Z"
: "");
if (isNaN(date)) return "Invalid Date";
const hours = date.getUTCHours();
const minutes = date.getUTCMinutes();
const seconds = date.getUTCSeconds();
const milliseconds = date.getUTCMilliseconds();
return `${formatYear(date.getUTCFullYear(), 4)}-${pad(date.getUTCMonth() + 1, 2)}-${pad(date.getUTCDate(), 2)}${
hours || minutes || seconds || milliseconds ? `T${pad(hours, 2)}:${pad(minutes, 2)}${
seconds || milliseconds ? `:${pad(seconds, 2)}${
milliseconds ? `.${pad(milliseconds, 3)}` : ``
}` : ``
}Z` : ``
}`;
}

function formatYear(year) {
return year < 0 ? "-" + pad(-year, 6) : year > 9999 ? "+" + pad(year, 6) : pad(year, 4);
return year < 0 ? `-${pad(-year, 6)}` : year > 9999 ? `+${pad(year, 6)}` : pad(year, 4);
}

function pad(value, width) {
return (value + "").padStart(width, "0");
return `${value}`.padStart(width, "0");
}

// Memoize the last-returned locale.
Expand Down
6 changes: 3 additions & 3 deletions src/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function search(data, {
data = arrayify(data);
required = !!required;
const [list, listId] = maybeDatalist(datalist);
const input = html`<input name=input type=search list=${listId} disabled=${disabled} spellcheck=${spellcheck === undefined ? false : spellcheck === null ? null : spellcheck + ""} placeholder=${placeholder} value=${query} oninput=${oninput}>`;
const input = html`<input name=input type=search list=${listId} disabled=${disabled} spellcheck=${spellcheck === undefined ? false : spellcheck === null ? null : `${spellcheck}`} placeholder=${placeholder} value=${query} oninput=${oninput}>`;
const output = html`<output name=output>`;
const form = html`<form class=__ns__ onsubmit=${preventDefault} style=${maybeWidth(width)}>
${maybeLabel(label, input)}<div class=__ns__-input>
Expand Down Expand Up @@ -56,7 +56,7 @@ export function search(data, {
}

export function searchFilter(query) {
const filters = (query + "").split(/\s+/g).filter(t => t).map(termFilter);
const filters = `${query}`.split(/\s+/g).filter(t => t).map(termFilter);
return d => {
if (d == null) return false;
if (typeof d === "object") {
Expand All @@ -81,7 +81,7 @@ export function searchFilter(query) {

function columnFilter(columns) {
return query => {
const filters = (query + "").split(/\s+/g).filter(t => t).map(termFilter);
const filters = `${query}`.split(/\s+/g).filter(t => t).map(termFilter);
return d => {
out: for (const filter of filters) {
for (const column of columns) {
Expand Down
2 changes: 1 addition & 1 deletion src/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export function text({
...options
} = {}) {
const [list, listId] = maybeDatalist(datalist);
const input = html`<input type=${type} name=text list=${listId} readonly=${readonly} disabled=${disabled} required=${required} min=${min} max=${max} minlength=${minlength} maxlength=${maxlength} pattern=${pattern} spellcheck=${spellcheck === undefined ? false : spellcheck === null ? null : spellcheck + ""} placeholder=${placeholder}>`;
const input = html`<input type=${type} name=text list=${listId} readonly=${readonly} disabled=${disabled} required=${required} min=${min} max=${max} minlength=${minlength} maxlength=${maxlength} pattern=${pattern} spellcheck=${spellcheck === undefined ? false : spellcheck === null ? null : `${spellcheck}`} placeholder=${placeholder}>`;
const form = html`<form class=__ns__ style=${maybeWidth(width)}>
${maybeLabel(label, input)}<div class=__ns__-input>
${input}
Expand Down
2 changes: 1 addition & 1 deletion src/textarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function textarea({
width,
...options
} = {}) {
const input = html`<textarea name=text readonly=${readonly} disabled=${disabled} required=${required} rows=${rows} minlength=${minlength} maxlength=${maxlength} spellcheck=${spellcheck === undefined ? false : spellcheck === null ? null : spellcheck + ""} placeholder=${placeholder} onkeydown=${onkeydown} style=${{width, fontFamily: monospace ? "var(--monospace, monospace)" : null, resize: resize ? null : "none"}}>`;
const input = html`<textarea name=text readonly=${readonly} disabled=${disabled} required=${required} rows=${rows} minlength=${minlength} maxlength=${maxlength} spellcheck=${spellcheck === undefined ? false : spellcheck === null ? null : `${spellcheck}`} placeholder=${placeholder} onkeydown=${onkeydown} style=${{width, fontFamily: monospace ? "var(--monospace, monospace)" : null, resize: resize ? null : "none"}}>`;
const form = html`<form class="__ns__ __ns__-textarea" style=${maybeWidth(width)}>
${maybeLabel(label, input)}<div>
${input}
Expand Down

0 comments on commit 424dd32

Please sign in to comment.