fmt = {
function bareInspector(value) {
const el = DOM.element("div");
new Inspector.Inspector(el).fulfilled(value);
const inspectSpan = el.querySelector(".observablehq--inspect");
if (inspectSpan) {
inspectSpan.parentElement.removeChild(inspectSpan);
}
return inspectSpan;
}
function constructOutput(format, strings) {
const id = `inspector-${Math.floor(1e9 * Math.random())}`;
let assignment = "";
const lhs = [];
const rhs = [];
let valueIdx = Infinity;
for (let i = 2; i < arguments.length; i++) {
if (!isElement(arguments[i])) {
valueIdx = i;
break;
}
}
if (valueIdx === Infinity) {
for (let i = 2; i < arguments.length; i++) {
if (arguments[i].value !== undefined) {
valueIdx = i;
break;
}
}
}
// Otherwise just take the first html element
if (valueIdx === Infinity) {
valueIdx = 2;
}
let dst, klass, color;
const value = arguments[valueIdx];
let isNumber = format && typeof value === "number";
for (var i = 0; i < strings.length; i++) {
dst = i < valueIdx - 1 ? lhs : rhs;
klass = i < valueIdx - 1 ? "cellname" : "number";
// Swap for alternate coloring...
color = "";
//color = klass === 'number' ? 'style="color:#767676"' : '';
// Push the string, wrapped in cellname (lhs) or number (rhs)
dst.push(
html`<span class="observablehq--${klass}" ${color}>${strings[i]}</span>`
);
// Process expression arguments
// Is this expression the value?
if (i === valueIdx - 2 && i < arguments.length - 2) {
if (isNumber) {
const str = format
? (typeof format === "string" ? d3format(format) : format)(value)
: value;
dst.push(html`<span class="observablehq--number">${str}</span>`);
} else {
const inspector = bareInspector(value);
if (inspector) {
inspector.setAttribute("id", id);
inspector.style.display = "inline";
dst.push(inspector);
} else if (isElement(value)) {
const wrapper = document.createElement("div");
wrapper.className = "observablehq--number";
wrapper.style.display = "inline-block";
wrapper.appendChild(value);
dst.push(wrapper);
} else {
dst.push(value);
}
}
} else if (i < arguments.length - 2) {
// If it's not the value, it's just a stray rhs expression
dst.push(
html`<span class="observablehq--${klass}" ${color}>${
arguments[i + 2]
}</span>`
);
}
}
// Force this inspector to remain inline ?!?!
const css = html`<style>#${id} > .observablehq--inspect { display: inline !important }</style>`;
// Build the final output!
const el = html`<span class="observablehq--inspect fmt-inspector" id="${id}">${lhs}${rhs}</span>${css}`;
if (isElement(value)) {
value.addEventListener("input", (event) => {
el.value = value.value;
el.dispatchEvent(new CustomEvent("input"));
});
el.value = value.value;
} else {
el.value = value;
}
return el;
}
// Return a function that is either a tagged template *or* receives
// format and returns a tagged template.
const returnValue = function fmt(format = null) {
if (Array.isArray(arguments[0])) {
// In this case, strings were provided, proceed to templating
const args = [null];
for (let i = 0; i < arguments.length; i++) args.push(arguments[i]);
return constructOutput.apply(null, args);
} else {
// In this case, the first argument is a format
return function () {
// So that you may back up and override the formatting after the fact.
// This is useful for creating a helper which provides an overridable
// default.
if (!Array.isArray(arguments[0])) return fmt(arguments[0]);
// Otherwise, use the default and evaluate
const args = [format];
for (let i = 0; i < arguments.length; i++) args.push(arguments[i]);
return constructOutput.apply(null, args);
};
}
};
returnValue.sci = sci;
return returnValue;
}