// @quarto/quarto-ojs-runtime v0.0.7 Copyright 2022 undefined var EOL = {}, EOF = {}, QUOTE = 34, NEWLINE = 10, RETURN = 13; function objectConverter(columns) { return new Function("d", "return {" + columns.map(function(name, i) { return JSON.stringify(name) + ": d[" + i + "] || \"\""; }).join(",") + "}"); } function customConverter(columns, f) { var object = objectConverter(columns); return function(row, i) { return f(object(row), i, columns); }; } // Compute unique columns in order of discovery. function inferColumns(rows) { var columnSet = Object.create(null), columns = []; rows.forEach(function(row) { for (var column in row) { if (!(column in columnSet)) { columns.push(columnSet[column] = column); } } }); return columns; } function pad$1(value, width) { var s = value + "", length = s.length; return length < width ? new Array(width - length + 1).join(0) + s : s; } function formatYear$1(year) { return year < 0 ? "-" + pad$1(-year, 6) : year > 9999 ? "+" + pad$1(year, 6) : pad$1(year, 4); } function formatDate$2(date) { var hours = date.getUTCHours(), minutes = date.getUTCMinutes(), seconds = date.getUTCSeconds(), milliseconds = date.getUTCMilliseconds(); return isNaN(date) ? "Invalid Date" : formatYear$1(date.getUTCFullYear()) + "-" + pad$1(date.getUTCMonth() + 1, 2) + "-" + pad$1(date.getUTCDate(), 2) + (milliseconds ? "T" + pad$1(hours, 2) + ":" + pad$1(minutes, 2) + ":" + pad$1(seconds, 2) + "." + pad$1(milliseconds, 3) + "Z" : seconds ? "T" + pad$1(hours, 2) + ":" + pad$1(minutes, 2) + ":" + pad$1(seconds, 2) + "Z" : minutes || hours ? "T" + pad$1(hours, 2) + ":" + pad$1(minutes, 2) + "Z" : ""); } function dsv$1(delimiter) { var reFormat = new RegExp("[\"" + delimiter + "\n\r]"), DELIMITER = delimiter.charCodeAt(0); function parse(text, f) { var convert, columns, rows = parseRows(text, function(row, i) { if (convert) return convert(row, i - 1); columns = row, convert = f ? customConverter(row, f) : objectConverter(row); }); rows.columns = columns || []; return rows; } function parseRows(text, f) { var rows = [], // output rows N = text.length, I = 0, // current character index n = 0, // current line number t, // current token eof = N <= 0, // current token followed by EOF? eol = false; // current token followed by EOL? // Strip the trailing newline. if (text.charCodeAt(N - 1) === NEWLINE) --N; if (text.charCodeAt(N - 1) === RETURN) --N; function token() { if (eof) return EOF; if (eol) return eol = false, EOL; // Unescape quotes. var i, j = I, c; if (text.charCodeAt(j) === QUOTE) { while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE); if ((i = I) >= N) eof = true; else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true; else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; } return text.slice(j + 1, i - 1).replace(/""/g, "\""); } // Find next delimiter or newline. while (I < N) { if ((c = text.charCodeAt(i = I++)) === NEWLINE) eol = true; else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; } else if (c !== DELIMITER) continue; return text.slice(j, i); } // Return last token before EOF. return eof = true, text.slice(j, N); } while ((t = token()) !== EOF) { var row = []; while (t !== EOL && t !== EOF) row.push(t), t = token(); if (f && (row = f(row, n++)) == null) continue; rows.push(row); } return rows; } function preformatBody(rows, columns) { return rows.map(function(row) { return columns.map(function(column) { return formatValue(row[column]); }).join(delimiter); }); } function format(rows, columns) { if (columns == null) columns = inferColumns(rows); return [columns.map(formatValue).join(delimiter)].concat(preformatBody(rows, columns)).join("\n"); } function formatBody(rows, columns) { if (columns == null) columns = inferColumns(rows); return preformatBody(rows, columns).join("\n"); } function formatRows(rows) { return rows.map(formatRow).join("\n"); } function formatRow(row) { return row.map(formatValue).join(delimiter); } function formatValue(value) { return value == null ? "" : value instanceof Date ? formatDate$2(value) : reFormat.test(value += "") ? "\"" + value.replace(/"/g, "\"\"") + "\"" : value; } return { parse: parse, parseRows: parseRows, format: format, formatBody: formatBody, formatRows: formatRows, formatRow: formatRow, formatValue: formatValue }; } var csv = dsv$1(","); var csvParse = csv.parse; var csvParseRows = csv.parseRows; var tsv = dsv$1("\t"); var tsvParse = tsv.parse; var tsvParseRows = tsv.parseRows; function autoType(object) { for (var key in object) { var value = object[key].trim(), number, m; if (!value) value = null; else if (value === "true") value = true; else if (value === "false") value = false; else if (value === "NaN") value = NaN; else if (!isNaN(number = +value)) value = number; else if (m = value.match(/^([-+]\d{2})?\d{4}(-\d{2}(-\d{2})?)?(T\d{2}:\d{2}(:\d{2}(\.\d{3})?)?(Z|[-+]\d{2}:\d{2})?)?$/)) { if (fixtz && !!m[4] && !m[7]) value = value.replace(/-/g, "/").replace(/T/, " "); value = new Date(value); } else continue; object[key] = value; } return object; } // https://github.com/d3/d3-dsv/issues/45 const fixtz = new Date("2019-01-01T00:00").getHours() || new Date("2019-07-01T00:00").getHours(); const metas = new Map; const queue$1 = []; const map$2 = queue$1.map; const some = queue$1.some; const hasOwnProperty$2 = queue$1.hasOwnProperty; const origin = "https://cdn.jsdelivr.net/npm/"; const identifierRe = /^((?:@[^/@]+\/)?[^/@]+)(?:@([^/]+))?(?:\/(.*))?$/; const versionRe = /^\d+\.\d+\.\d+(-[\w-.+]+)?$/; const extensionRe = /\.[^/]*$/; const mains = ["unpkg", "jsdelivr", "browser", "main"]; class RequireError extends Error { constructor(message) { super(message); } } RequireError.prototype.name = RequireError.name; function main(meta) { for (const key of mains) { const value = meta[key]; if (typeof value === "string") { return extensionRe.test(value) ? value : `${value}.js`; } } } function parseIdentifier(identifier) { const match = identifierRe.exec(identifier); return match && { name: match[1], version: match[2], path: match[3] }; } function resolveMeta(target) { const url = `${origin}${target.name}${target.version ? `@${target.version}` : ""}/package.json`; let meta = metas.get(url); if (!meta) metas.set(url, meta = fetch(url).then(response => { if (!response.ok) throw new RequireError("unable to load package.json"); if (response.redirected && !metas.has(response.url)) metas.set(response.url, meta); return response.json(); })); return meta; } async function resolve$1(name, base) { if (name.startsWith(origin)) name = name.substring(origin.length); if (/^(\w+:)|\/\//i.test(name)) return name; if (/^[.]{0,2}\//i.test(name)) return new URL(name, base == null ? location : base).href; if (!name.length || /^[\s._]/.test(name) || /\s$/.test(name)) throw new RequireError("illegal name"); const target = parseIdentifier(name); if (!target) return `${origin}${name}`; if (!target.version && base != null && base.startsWith(origin)) { const meta = await resolveMeta(parseIdentifier(base.substring(origin.length))); target.version = meta.dependencies && meta.dependencies[target.name] || meta.peerDependencies && meta.peerDependencies[target.name]; } if (target.path && !extensionRe.test(target.path)) target.path += ".js"; if (target.path && target.version && versionRe.test(target.version)) return `${origin}${target.name}@${target.version}/${target.path}`; const meta = await resolveMeta(target); return `${origin}${meta.name}@${meta.version}/${target.path || main(meta) || "index.js"}`; } var require = requireFrom(resolve$1); let requestsInFlight = 0; let prevDefine = undefined; function requireFrom(resolver) { const cache = new Map; const requireBase = requireRelative(null); function requireAbsolute(url) { if (typeof url !== "string") return url; let module = cache.get(url); if (!module) cache.set(url, module = new Promise((resolve, reject) => { const script = document.createElement("script"); script.onload = () => { try { resolve(queue$1.pop()(requireRelative(url))); } catch (error) { reject(new RequireError("invalid module")); } script.remove(); requestsInFlight--; if (requestsInFlight === 0) { window.define = prevDefine; } }; script.onerror = () => { reject(new RequireError("unable to load module")); script.remove(); requestsInFlight--; if (requestsInFlight === 0) { window.define = prevDefine; } }; script.async = true; script.src = url; if (requestsInFlight === 0) { prevDefine = window.define; window.define = define; } requestsInFlight++; document.head.appendChild(script); })); return module; } function requireRelative(base) { return name => Promise.resolve(resolver(name, base)).then(requireAbsolute); } function requireAlias(aliases) { return requireFrom((name, base) => { if (name in aliases) { name = aliases[name], base = null; if (typeof name !== "string") return name; } return resolver(name, base); }); } function require(name) { return arguments.length > 1 ? Promise.all(map$2.call(arguments, requireBase)).then(merge) : requireBase(name); } require.alias = requireAlias; require.resolve = resolver; return require; } function merge(modules) { const o = {}; for (const m of modules) { for (const k in m) { if (hasOwnProperty$2.call(m, k)) { if (m[k] == null) Object.defineProperty(o, k, {get: getter(m, k)}); else o[k] = m[k]; } } } return o; } function getter(object, name) { return () => object[name]; } function isbuiltin(name) { name = name + ""; return name === "exports" || name === "module"; } function define(name, dependencies, factory) { const n = arguments.length; if (n < 2) factory = name, dependencies = []; else if (n < 3) factory = dependencies, dependencies = typeof name === "string" ? [] : name; queue$1.push(some.call(dependencies, isbuiltin) ? require => { const exports = {}; const module = {exports}; return Promise.all(map$2.call(dependencies, name => { name = name + ""; return name === "exports" ? exports : name === "module" ? module : require(name); })).then(dependencies => { factory.apply(null, dependencies); return module.exports; }); } : require => { return Promise.all(map$2.call(dependencies, require)).then(dependencies => { return typeof factory === "function" ? factory.apply(null, dependencies) : factory; }); }); } define.amd = {}; function dependency(name, version, main) { return { resolve(path = main) { return `https://cdn.jsdelivr.net/npm/${name}@${version}/${path}`; } }; } const d3 = dependency("d3", "7.4.4", "dist/d3.min.js"); const inputs = dependency("@observablehq/inputs", "0.10.4", "dist/inputs.min.js"); const plot = dependency("@observablehq/plot", "0.4.3", "dist/plot.umd.min.js"); const graphviz = dependency("@observablehq/graphviz", "0.2.1", "dist/graphviz.min.js"); const highlight = dependency("@observablehq/highlight.js", "2.0.0", "highlight.min.js"); const katex = dependency("@observablehq/katex", "0.11.1", "dist/katex.min.js"); const lodash = dependency("lodash", "4.17.21", "lodash.min.js"); const htl = dependency("htl", "0.3.1", "dist/htl.min.js"); const jszip = dependency("jszip", "3.9.1", "dist/jszip.min.js"); const marked = dependency("marked", "0.3.12", "marked.min.js"); const sql = dependency("sql.js", "1.6.2", "dist/sql-wasm.js"); const vega = dependency("vega", "5.22.1", "build/vega.min.js"); const vegalite = dependency("vega-lite", "5.2.0", "build/vega-lite.min.js"); const vegaliteApi = dependency("vega-lite-api", "5.0.0", "build/vega-lite-api.min.js"); const arrow = dependency("apache-arrow", "4.0.1", "Arrow.es2015.min.js"); const arquero = dependency("arquero", "4.8.8", "dist/arquero.min.js"); const topojson = dependency("topojson-client", "3.1.0", "dist/topojson-client.min.js"); const exceljs = dependency("exceljs", "4.3.0", "dist/exceljs.min.js"); const mermaid$1 = dependency("mermaid", "9.0.0", "dist/mermaid.min.js"); function fromEntries(obj) { const result = {}; for (const [key, value] of obj) { result[key] = value; } return result; } async function sqlite(require) { const init = await require(sql.resolve()); return init({locateFile: file => sql.resolve(`dist/${file}`)}); } class SQLiteDatabaseClient { constructor(db) { Object.defineProperties(this, { _db: {value: db} }); } static async open(source) { const [SQL, buffer] = await Promise.all([sqlite(require), Promise.resolve(source).then(load$1)]); return new SQLiteDatabaseClient(new SQL.Database(buffer)); } async query(query, params) { return await exec(this._db, query, params); } async queryRow(query, params) { return (await this.query(query, params))[0] || null; } async explain(query, params) { const rows = await this.query(`EXPLAIN QUERY PLAN ${query}`, params); return element$1("pre", {className: "observablehq--inspect"}, [ text$2(rows.map(row => row.detail).join("\n")) ]); } async describe(object) { const rows = await (object === undefined ? this.query(`SELECT name FROM sqlite_master WHERE type = 'table'`) : this.query(`SELECT * FROM pragma_table_info(?)`, [object])); if (!rows.length) throw new Error("Not found"); const {columns} = rows; return element$1("table", {value: rows}, [ element$1("thead", [element$1("tr", columns.map(c => element$1("th", [text$2(c)])))]), element$1("tbody", rows.map(r => element$1("tr", columns.map(c => element$1("td", [text$2(r[c])]))))) ]); } async sql(strings, ...args) { return this.query(strings.join("?"), args); } } Object.defineProperty(SQLiteDatabaseClient.prototype, "dialect", { value: "sqlite" }); function load$1(source) { return typeof source === "string" ? fetch(source).then(load$1) : source instanceof Response || source instanceof Blob ? source.arrayBuffer().then(load$1) : source instanceof ArrayBuffer ? new Uint8Array(source) : source; } async function exec(db, query, params) { const [result] = await db.exec(query, params); if (!result) return []; const {columns, values} = result; const rows = values.map(row => fromEntries(row.map((value, i) => [columns[i], value]))); rows.columns = columns; return rows; } function element$1(name, props, children) { if (arguments.length === 2) children = props, props = undefined; const element = document.createElement(name); if (props !== undefined) for (const p in props) element[p] = props[p]; if (children !== undefined) for (const c of children) element.appendChild(c); return element; } function text$2(value) { return document.createTextNode(value); } class Workbook { constructor(workbook) { Object.defineProperties(this, { _: {value: workbook}, sheetNames: { value: workbook.worksheets.map((s) => s.name), enumerable: true, }, }); } sheet(name, options) { const sname = typeof name === "number" ? this.sheetNames[name] : this.sheetNames.includes((name += "")) ? name : null; if (sname == null) throw new Error(`Sheet not found: ${name}`); const sheet = this._.getWorksheet(sname); return extract(sheet, options); } } function extract(sheet, {range, headers} = {}) { let [[c0, r0], [c1, r1]] = parseRange(range, sheet); const headerRow = headers ? sheet._rows[r0++] : null; let names = new Set(["#"]); for (let n = c0; n <= c1; n++) { const value = headerRow ? valueOf(headerRow.findCell(n + 1)) : null; let name = (value && value + "") || toColumn(n); while (names.has(name)) name += "_"; names.add(name); } names = new Array(c0).concat(Array.from(names)); const output = new Array(r1 - r0 + 1); for (let r = r0; r <= r1; r++) { const row = (output[r - r0] = Object.create(null, {"#": {value: r + 1}})); const _row = sheet.getRow(r + 1); if (_row.hasValues) for (let c = c0; c <= c1; c++) { const value = valueOf(_row.findCell(c + 1)); if (value != null) row[names[c + 1]] = value; } } output.columns = names.filter(() => true); // Filter sparse columns return output; } function valueOf(cell) { if (!cell) return; const {value} = cell; if (value && typeof value === "object" && !(value instanceof Date)) { if (value.formula || value.sharedFormula) { return value.result && value.result.error ? NaN : value.result; } if (value.richText) { return richText(value); } if (value.text) { let {text} = value; if (text.richText) text = richText(text); return value.hyperlink && value.hyperlink !== text ? `${value.hyperlink} ${text}` : text; } return value; } return value; } function richText(value) { return value.richText.map((d) => d.text).join(""); } function parseRange(specifier = ":", {columnCount, rowCount}) { specifier += ""; if (!specifier.match(/^[A-Z]*\d*:[A-Z]*\d*$/)) throw new Error("Malformed range specifier"); const [[c0 = 0, r0 = 0], [c1 = columnCount - 1, r1 = rowCount - 1]] = specifier.split(":").map(fromCellReference); return [ [c0, r0], [c1, r1], ]; } // Returns the default column name for a zero-based column index. // For example: 0 -> "A", 1 -> "B", 25 -> "Z", 26 -> "AA", 27 -> "AB". function toColumn(c) { let sc = ""; c++; do { sc = String.fromCharCode(64 + (c % 26 || 26)) + sc; } while ((c = Math.floor((c - 1) / 26))); return sc; } // Returns the zero-based indexes from a cell reference. // For example: "A1" -> [0, 0], "B2" -> [1, 1], "AA10" -> [26, 9]. function fromCellReference(s) { const [, sc, sr] = s.match(/^([A-Z]*)(\d*)$/); let c = 0; if (sc) for (let i = 0; i < sc.length; i++) c += Math.pow(26, sc.length - i - 1) * (sc.charCodeAt(i) - 64); return [c ? c - 1 : undefined, sr ? +sr - 1 : undefined]; } async function remote_fetch(file) { const response = await fetch(await file.url()); if (!response.ok) throw new Error(`Unable to load file: ${file.name}`); return response; } async function dsv(file, delimiter, {array = false, typed = false} = {}) { const text = await file.text(); return (delimiter === "\t" ? (array ? tsvParseRows : tsvParse) : (array ? csvParseRows : csvParse))(text, typed && autoType); } class AbstractFile { constructor(name, mimeType) { Object.defineProperty(this, "name", {value: name, enumerable: true}); if (mimeType !== undefined) Object.defineProperty(this, "mimeType", {value: mimeType + "", enumerable: true}); } async blob() { return (await remote_fetch(this)).blob(); } async arrayBuffer() { return (await remote_fetch(this)).arrayBuffer(); } async text() { return (await remote_fetch(this)).text(); } async json() { return (await remote_fetch(this)).json(); } async stream() { return (await remote_fetch(this)).body; } async csv(options) { return dsv(this, ",", options); } async tsv(options) { return dsv(this, "\t", options); } async image(props) { const url = await this.url(); return new Promise((resolve, reject) => { const i = new Image(); if (new URL(url, document.baseURI).origin !== new URL(location).origin) { i.crossOrigin = "anonymous"; } Object.assign(i, props); i.onload = () => resolve(i); i.onerror = () => reject(new Error(`Unable to load file: ${this.name}`)); i.src = url; }); } async arrow() { const [Arrow, response] = await Promise.all([require(arrow.resolve()), remote_fetch(this)]); return Arrow.Table.from(response); } async sqlite() { return SQLiteDatabaseClient.open(remote_fetch(this)); } async zip() { const [JSZip, buffer] = await Promise.all([require(jszip.resolve()), this.arrayBuffer()]); return new ZipArchive(await JSZip.loadAsync(buffer)); } async xml(mimeType = "application/xml") { return (new DOMParser).parseFromString(await this.text(), mimeType); } async html() { return this.xml("text/html"); } async xlsx() { const [ExcelJS, buffer] = await Promise.all([require(exceljs.resolve()), this.arrayBuffer()]); return new Workbook(await new ExcelJS.Workbook().xlsx.load(buffer)); } } class FileAttachment extends AbstractFile { constructor(url, name, mimeType) { super(name, mimeType); Object.defineProperty(this, "_url", {value: url}); } async url() { return (await this._url) + ""; } } function NoFileAttachments(name) { throw new Error(`File not found: ${name}`); } function FileAttachments(resolve) { return Object.assign( name => { const result = resolve(name += ""); if (result == null) throw new Error(`File not found: ${name}`); if (typeof result === "object" && "url" in result) { const {url, mimeType} = result; return new FileAttachment(url, name, mimeType); } return new FileAttachment(result, name); }, {prototype: FileAttachment.prototype} // instanceof ); } class ZipArchive { constructor(archive) { Object.defineProperty(this, "_", {value: archive}); this.filenames = Object.keys(archive.files).filter(name => !archive.files[name].dir); } file(path) { const object = this._.file(path += ""); if (!object || object.dir) throw new Error(`file not found: ${path}`); return new ZipArchiveEntry(object); } } class ZipArchiveEntry extends AbstractFile { constructor(object) { super(object.name); Object.defineProperty(this, "_", {value: object}); Object.defineProperty(this, "_url", {writable: true}); } async url() { return this._url || (this._url = this.blob().then(URL.createObjectURL)); } async blob() { return this._.async("blob"); } async arrayBuffer() { return this._.async("arraybuffer"); } async text() { return this._.async("text"); } async json() { return JSON.parse(await this.text()); } } function canvas(width, height) { var canvas = document.createElement("canvas"); canvas.width = width; canvas.height = height; return canvas; } function context2d(width, height, dpi) { if (dpi == null) dpi = devicePixelRatio; var canvas = document.createElement("canvas"); canvas.width = width * dpi; canvas.height = height * dpi; canvas.style.width = width + "px"; var context = canvas.getContext("2d"); context.scale(dpi, dpi); return context; } function download(value, name = "untitled", label = "Save") { const a = document.createElement("a"); const b = a.appendChild(document.createElement("button")); b.textContent = label; a.download = name; async function reset() { await new Promise(requestAnimationFrame); URL.revokeObjectURL(a.href); a.removeAttribute("href"); b.textContent = label; b.disabled = false; } a.onclick = async event => { b.disabled = true; if (a.href) return reset(); // Already saved. b.textContent = "Saving…"; try { const object = await (typeof value === "function" ? value() : value); b.textContent = "Download"; a.href = URL.createObjectURL(object); // eslint-disable-line require-atomic-updates } catch (ignore) { b.textContent = label; } if (event.eventPhase) return reset(); // Already downloaded. b.disabled = false; }; return a; } var namespaces = { math: "http://www.w3.org/1998/Math/MathML", svg: "http://www.w3.org/2000/svg", xhtml: "http://www.w3.org/1999/xhtml", xlink: "http://www.w3.org/1999/xlink", xml: "http://www.w3.org/XML/1998/namespace", xmlns: "http://www.w3.org/2000/xmlns/" }; function element(name, attributes) { var prefix = name += "", i = prefix.indexOf(":"), value; if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); var element = namespaces.hasOwnProperty(prefix) // eslint-disable-line no-prototype-builtins ? document.createElementNS(namespaces[prefix], name) : document.createElement(name); if (attributes) for (var key in attributes) { prefix = key, i = prefix.indexOf(":"), value = attributes[key]; if (i >= 0 && (prefix = key.slice(0, i)) !== "xmlns") key = key.slice(i + 1); if (namespaces.hasOwnProperty(prefix)) element.setAttributeNS(namespaces[prefix], key, value); // eslint-disable-line no-prototype-builtins else element.setAttribute(key, value); } return element; } function input$1(type) { var input = document.createElement("input"); if (type != null) input.type = type; return input; } function range$1(min, max, step) { if (arguments.length === 1) max = min, min = null; var input = document.createElement("input"); input.min = min = min == null ? 0 : +min; input.max = max = max == null ? 1 : +max; input.step = step == null ? "any" : step = +step; input.type = "range"; return input; } function select(values) { var select = document.createElement("select"); Array.prototype.forEach.call(values, function(value) { var option = document.createElement("option"); option.value = option.textContent = value; select.appendChild(option); }); return select; } function svg$1(width, height) { var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("viewBox", [0, 0, width, height]); svg.setAttribute("width", width); svg.setAttribute("height", height); return svg; } function text$1(value) { return document.createTextNode(value); } var count$1 = 0; function uid(name) { return new Id("O-" + (name == null ? "" : name + "-") + ++count$1); } function Id(id) { this.id = id; this.href = new URL(`#${id}`, location) + ""; } Id.prototype.toString = function() { return "url(" + this.href + ")"; }; var DOM = { canvas: canvas, context2d: context2d, download: download, element: element, input: input$1, range: range$1, select: select, svg: svg$1, text: text$1, uid: uid }; function buffer(file) { return new Promise(function(resolve, reject) { var reader = new FileReader; reader.onload = function() { resolve(reader.result); }; reader.onerror = reject; reader.readAsArrayBuffer(file); }); } function text(file) { return new Promise(function(resolve, reject) { var reader = new FileReader; reader.onload = function() { resolve(reader.result); }; reader.onerror = reject; reader.readAsText(file); }); } function url(file) { return new Promise(function(resolve, reject) { var reader = new FileReader; reader.onload = function() { resolve(reader.result); }; reader.onerror = reject; reader.readAsDataURL(file); }); } var Files = { buffer: buffer, text: text, url: url }; function that() { return this; } function disposable(value, dispose) { let done = false; if (typeof dispose !== "function") { throw new Error("dispose is not a function"); } return { [Symbol.iterator]: that, next: () => done ? {done: true} : (done = true, {done: false, value}), return: () => (done = true, dispose(value), {done: true}), throw: () => ({done: done = true}) }; } function* filter(iterator, test) { var result, index = -1; while (!(result = iterator.next()).done) { if (test(result.value, ++index)) { yield result.value; } } } function observe(initialize) { let stale = false; let value; let resolve; const dispose = initialize(change); if (dispose != null && typeof dispose !== "function") { throw new Error(typeof dispose.then === "function" ? "async initializers are not supported" : "initializer returned something, but not a dispose function"); } function change(x) { if (resolve) resolve(x), resolve = null; else stale = true; return value = x; } function next() { return {done: false, value: stale ? (stale = false, Promise.resolve(value)) : new Promise(_ => (resolve = _))}; } return { [Symbol.iterator]: that, throw: () => ({done: true}), return: () => (dispose != null && dispose(), {done: true}), next }; } function input(input) { return observe(function(change) { var event = eventof(input), value = valueof$1(input); function inputted() { change(valueof$1(input)); } input.addEventListener(event, inputted); if (value !== undefined) change(value); return function() { input.removeEventListener(event, inputted); }; }); } function valueof$1(input) { switch (input.type) { case "range": case "number": return input.valueAsNumber; case "date": return input.valueAsDate; case "checkbox": return input.checked; case "file": return input.multiple ? input.files : input.files[0]; case "select-multiple": return Array.from(input.selectedOptions, o => o.value); default: return input.value; } } function eventof(input) { switch (input.type) { case "button": case "submit": case "checkbox": return "click"; case "file": return "change"; default: return "input"; } } function* map$1(iterator, transform) { var result, index = -1; while (!(result = iterator.next()).done) { yield transform(result.value, ++index); } } function queue(initialize) { let resolve; const queue = []; const dispose = initialize(push); if (dispose != null && typeof dispose !== "function") { throw new Error(typeof dispose.then === "function" ? "async initializers are not supported" : "initializer returned something, but not a dispose function"); } function push(x) { queue.push(x); if (resolve) resolve(queue.shift()), resolve = null; return x; } function next() { return {done: false, value: queue.length ? Promise.resolve(queue.shift()) : new Promise(_ => (resolve = _))}; } return { [Symbol.iterator]: that, throw: () => ({done: true}), return: () => (dispose != null && dispose(), {done: true}), next }; } function* range(start, stop, step) { start = +start; stop = +stop; step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; var i = -1, n = Math.max(0, Math.ceil((stop - start) / step)) | 0; while (++i < n) { yield start + i * step; } } function valueAt(iterator, i) { if (!isFinite(i = +i) || i < 0 || i !== i | 0) return; var result, index = -1; while (!(result = iterator.next()).done) { if (++index === i) { return result.value; } } } function worker(source) { const url = URL.createObjectURL(new Blob([source], {type: "text/javascript"})); const worker = new Worker(url); return disposable(worker, () => { worker.terminate(); URL.revokeObjectURL(url); }); } var Generators$1 = { disposable: disposable, filter: filter, input: input, map: map$1, observe: observe, queue: queue, range: range, valueAt: valueAt, worker: worker }; function template(render, wrapper) { return function(strings) { var string = strings[0], parts = [], part, root = null, node, nodes, walker, i, n, j, m, k = -1; // Concatenate the text using comments as placeholders. for (i = 1, n = arguments.length; i < n; ++i) { part = arguments[i]; if (part instanceof Node) { parts[++k] = part; string += ""; } else if (Array.isArray(part)) { for (j = 0, m = part.length; j < m; ++j) { node = part[j]; if (node instanceof Node) { if (root === null) { parts[++k] = root = document.createDocumentFragment(); string += ""; } root.appendChild(node); } else { root = null; string += node; } } root = null; } else { string += part; } string += strings[i]; } // Render the text. root = render(string); // Walk the rendered content to replace comment placeholders. if (++k > 0) { nodes = new Array(k); walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT, null, false); while (walker.nextNode()) { node = walker.currentNode; if (/^o:/.test(node.nodeValue)) { nodes[+node.nodeValue.slice(2)] = node; } } for (i = 0; i < k; ++i) { if (node = nodes[i]) { node.parentNode.replaceChild(parts[i], node); } } } // Is the rendered content // … a parent of a single child? Detach and return the child. // … a document fragment? Replace the fragment with an element. // … some other node? Return it. return root.childNodes.length === 1 ? root.removeChild(root.firstChild) : root.nodeType === 11 ? ((node = wrapper()).appendChild(root), node) : root; }; } var html$1 = template(function(string) { var template = document.createElement("template"); template.innerHTML = string.trim(); return document.importNode(template.content, true); }, function() { return document.createElement("span"); }); function md(require) { return require(marked.resolve()).then(function(marked) { return template( function(string) { var root = document.createElement("div"); root.innerHTML = marked(string, {langPrefix: ""}).trim(); var code = root.querySelectorAll("pre code[class]"); if (code.length > 0) { require(highlight.resolve()).then(function(hl) { code.forEach(function(block) { function done() { hl.highlightBlock(block); block.parentNode.classList.add("observablehq--md-pre"); } if (hl.getLanguage(block.className)) { done(); } else { require(highlight.resolve("async-languages/index.js")) .then(index => { if (index.has(block.className)) { return require(highlight.resolve("async-languages/" + index.get(block.className))).then(language => { hl.registerLanguage(block.className, language); }); } }) .then(done, done); } }); }); } return root; }, function() { return document.createElement("div"); } ); }); } async function mermaid(require) { const mer = await require(mermaid$1.resolve()); mer.initialize({securityLevel: "loose", theme: "neutral"}); return function mermaid() { const root = document.createElement("div"); root.innerHTML = mer.render(uid().id, String.raw.apply(String, arguments)); return root.removeChild(root.firstChild); }; } function Mutable(value) { let change; Object.defineProperties(this, { generator: {value: observe(_ => void (change = _))}, value: {get: () => value, set: x => change(value = x)} // eslint-disable-line no-setter-return }); if (value !== undefined) change(value); } function* now() { while (true) { yield Date.now(); } } function delay(duration, value) { return new Promise(function(resolve) { setTimeout(function() { resolve(value); }, duration); }); } var timeouts = new Map; function timeout(now, time) { var t = new Promise(function(resolve) { timeouts.delete(time); var delay = time - now; if (!(delay > 0)) throw new Error("invalid time"); if (delay > 0x7fffffff) throw new Error("too long to wait"); setTimeout(resolve, delay); }); timeouts.set(time, t); return t; } function when(time, value) { var now; return (now = timeouts.get(time = +time)) ? now.then(() => value) : (now = Date.now()) >= time ? Promise.resolve(value) : timeout(now, time).then(() => value); } function tick(duration, value) { return when(Math.ceil((Date.now() + 1) / duration) * duration, value); } var Promises = { delay: delay, tick: tick, when: when }; function resolve(name, base) { if (/^(\w+:)|\/\//i.test(name)) return name; if (/^[.]{0,2}\//i.test(name)) return new URL(name, base == null ? location : base).href; if (!name.length || /^[\s._]/.test(name) || /\s$/.test(name)) throw new Error("illegal name"); return "https://unpkg.com/" + name; } function requirer(resolve) { return resolve == null ? require : requireFrom(resolve); } var svg = template(function(string) { var root = document.createElementNS("http://www.w3.org/2000/svg", "g"); root.innerHTML = string.trim(); return root; }, function() { return document.createElementNS("http://www.w3.org/2000/svg", "g"); }); var raw = String.raw; function style(href) { return new Promise(function(resolve, reject) { var link = document.createElement("link"); link.rel = "stylesheet"; link.href = href; link.onerror = reject; link.onload = resolve; document.head.appendChild(link); }); } function tex(require) { return Promise.all([ require(katex.resolve()), style(katex.resolve("dist/katex.min.css")) ]).then(function(values) { var katex = values[0], tex = renderer(); function renderer(options) { return function() { var root = document.createElement("div"); katex.render(raw.apply(String, arguments), root, options); return root.removeChild(root.firstChild); }; } tex.options = renderer; tex.block = renderer({displayMode: true}); return tex; }); } async function vl(require) { const [v, vl, api] = await Promise.all([vega, vegalite, vegaliteApi].map(d => require(d.resolve()))); return api.register(v, vl); } function width() { return observe(function(change) { var width = change(document.body.clientWidth); function resized() { var w = document.body.clientWidth; if (w !== width) change(width = w); } window.addEventListener("resize", resized); return function() { window.removeEventListener("resize", resized); }; }); } var Library = Object.assign(function Library(resolver) { const require = requirer(resolver); Object.defineProperties(this, properties({ FileAttachment: () => NoFileAttachments, Arrow: () => require(arrow.resolve()), Inputs: () => require(inputs.resolve()).then(Inputs => ({...Inputs, file: Inputs.fileOf(AbstractFile)})), Mutable: () => Mutable, Plot: () => require(plot.resolve()), SQLite: () => sqlite(require), SQLiteDatabaseClient: () => SQLiteDatabaseClient, _: () => require(lodash.resolve()), aq: () => require.alias({"apache-arrow": arrow.resolve()})(arquero.resolve()), d3: () => require(d3.resolve()), dot: () => require(graphviz.resolve()), htl: () => require(htl.resolve()), html: () => html$1, md: () => md(require), mermaid: () => mermaid(require), now, require: () => require, resolve: () => resolve, svg: () => svg, tex: () => tex(require), topojson: () => require(topojson.resolve()), vl: () => vl(require), width, // Note: these are namespace objects, and thus exposed directly rather than // being wrapped in a function. This allows library.Generators to resolve, // rather than needing module.value. DOM, Files, Generators: Generators$1, Promises })); }, {resolve: require.resolve}); function properties(values) { return fromEntries(Object.entries(values).map(property)); // return Object.fromEntries(Object.entries(values).map(property)); } function property([key, value]) { return [key, ({value, writable: true, enumerable: true})]; } // src/main.js class PandocCodeDecorator { constructor(node) { this._node = node; this._spans = []; this.normalizeCodeRange(); this.initializeEntryPoints(); } normalizeCodeRange() { const n = this._node; const lines = n.querySelectorAll("code > span"); for (const line of lines) { Array.from(line.childNodes).filter((n2) => n2.nodeType === n2.TEXT_NODE).forEach((n2) => { const newSpan = document.createElement("span"); newSpan.textContent = n2.wholeText; n2.replaceWith(newSpan); }); } } initializeEntryPoints() { const lines = this._node.querySelectorAll("code > span"); let result = []; let offset = this._node.parentElement.dataset.sourceOffset && -Number(this._node.parentElement.dataset.sourceOffset) || 0; for (const line of lines) { let lineNumber = Number(line.id.split("-").pop()); let column = 1; Array.from(line.childNodes).filter((n) => n.nodeType === n.ELEMENT_NODE && n.nodeName === "SPAN").forEach((n) => { result.push({ offset, line: lineNumber, column, node: n }); offset += n.textContent.length; column += n.textContent.length; }); offset += 1; } this._elementEntryPoints = result; } locateEntry(offset) { let candidate; if (offset === Infinity) return void 0; for (let i = 0; i < this._elementEntryPoints.length; ++i) { const entry = this._elementEntryPoints[i]; if (entry.offset > offset) { return { entry: candidate, index: i - 1 }; } candidate = entry; } if (offset < candidate.offset + candidate.node.textContent.length) { return { entry: candidate, index: this._elementEntryPoints.length - 1 }; } else { return void 0; } } offsetToLineColumn(offset) { let entry = this.locateEntry(offset); if (entry === void 0) { const entries = this._elementEntryPoints; const last = entries[entries.length - 1]; return { line: last.line, column: last.column + Math.min(last.node.textContent.length, offset - last.offset) }; } return { line: entry.entry.line, column: entry.entry.column + offset - entry.entry.offset }; } *spanSelection(start, end) { this.ensureExactSpan(start, end); const startEntry = this.locateEntry(start); const endEntry = this.locateEntry(end); if (startEntry === void 0) { return; } const startIndex = startEntry.index; const endIndex = endEntry && endEntry.index || this._elementEntryPoints.length; for (let i = startIndex; i < endIndex; ++i) { yield this._elementEntryPoints[i]; } } decorateSpan(start, end, classes) { for (const entryPoint of this.spanSelection(start, end)) { for (const cssClass of classes) { entryPoint.node.classList.add(cssClass); } } } clearSpan(start, end, classes) { for (const entryPoint of this.spanSelection(start, end)) { for (const cssClass of classes) { entryPoint.node.classList.remove(cssClass); } } } ensureExactSpan(start, end) { const splitEntry = (entry, offset) => { const newSpan = document.createElement("span"); for (const cssClass of entry.node.classList) { newSpan.classList.add(cssClass); } const beforeText = entry.node.textContent.slice(0, offset - entry.offset); const afterText = entry.node.textContent.slice(offset - entry.offset); entry.node.textContent = beforeText; newSpan.textContent = afterText; entry.node.after(newSpan); this._elementEntryPoints.push({ column: entry.column + offset - entry.offset, line: entry.line, node: newSpan, offset }); this._elementEntryPoints.sort((a, b) => a.offset - b.offset); }; const startEntry = this.locateEntry(start); if (startEntry !== void 0 && startEntry.entry.offset != start) { splitEntry(startEntry.entry, start); } const endEntry = this.locateEntry(end); if (endEntry !== void 0 && endEntry.entry.offset !== end) { splitEntry(endEntry.entry, end); } } clearSpan(start, end, classes) { this.ensureExactSpan(start, end); const startEntry = this.locateEntry(start); const endEntry = this.locateEntry(end); if (startEntry === void 0) { return; } const startIndex = startEntry.index; const endIndex = endEntry && endEntry.index || this._elementEntryPoints.length; for (let i = startIndex; i < endIndex; ++i) { for (const cssClass of classes) { this._elementEntryPoints[i].node.classList.remove(cssClass); } } } } function dispatch(node, type, detail) { detail = detail || {}; var document = node.ownerDocument, event = document.defaultView.CustomEvent; if (typeof event === "function") { event = new event(type, {detail: detail}); } else { event = document.createEvent("Event"); event.initEvent(type, false, false); event.detail = detail; } node.dispatchEvent(event); } // TODO https://twitter.com/mbostock/status/702737065121742848 function isarray(value) { return Array.isArray(value) || value instanceof Int8Array || value instanceof Int16Array || value instanceof Int32Array || value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Uint16Array || value instanceof Uint32Array || value instanceof Float32Array || value instanceof Float64Array; } // Non-integer keys in arrays, e.g. [1, 2, 0.5: "value"]. function isindex(key) { return key === (key | 0) + ""; } function inspectName(name) { const n = document.createElement("span"); n.className = "observablehq--cellname"; n.textContent = `${name} = `; return n; } const symbolToString = Symbol.prototype.toString; // Symbols do not coerce to strings; they must be explicitly converted. function formatSymbol(symbol) { return symbolToString.call(symbol); } const {getOwnPropertySymbols, prototype: {hasOwnProperty: hasOwnProperty$1}} = Object; const {toStringTag} = Symbol; const FORBIDDEN = {}; const symbolsof = getOwnPropertySymbols; function isown(object, key) { return hasOwnProperty$1.call(object, key); } function tagof(object) { return object[toStringTag] || (object.constructor && object.constructor.name) || "Object"; } function valueof(object, key) { try { const value = object[key]; if (value) value.constructor; // Test for SecurityError. return value; } catch (ignore) { return FORBIDDEN; } } const SYMBOLS = [ { symbol: "@@__IMMUTABLE_INDEXED__@@", name: "Indexed", modifier: true }, { symbol: "@@__IMMUTABLE_KEYED__@@", name: "Keyed", modifier: true }, { symbol: "@@__IMMUTABLE_LIST__@@", name: "List", arrayish: true }, { symbol: "@@__IMMUTABLE_MAP__@@", name: "Map" }, { symbol: "@@__IMMUTABLE_ORDERED__@@", name: "Ordered", modifier: true, prefix: true }, { symbol: "@@__IMMUTABLE_RECORD__@@", name: "Record" }, { symbol: "@@__IMMUTABLE_SET__@@", name: "Set", arrayish: true, setish: true }, { symbol: "@@__IMMUTABLE_STACK__@@", name: "Stack", arrayish: true } ]; function immutableName(obj) { try { let symbols = SYMBOLS.filter(({ symbol }) => obj[symbol] === true); if (!symbols.length) return; const name = symbols.find(s => !s.modifier); const prefix = name.name === "Map" && symbols.find(s => s.modifier && s.prefix); const arrayish = symbols.some(s => s.arrayish); const setish = symbols.some(s => s.setish); return { name: `${prefix ? prefix.name : ""}${name.name}`, symbols, arrayish: arrayish && !setish, setish }; } catch (e) { return null; } } const {getPrototypeOf, getOwnPropertyDescriptors} = Object; const objectPrototype = getPrototypeOf({}); function inspectExpanded(object, _, name, proto) { let arrayish = isarray(object); let tag, fields, next, n; if (object instanceof Map) { if (object instanceof object.constructor) { tag = `Map(${object.size})`; fields = iterateMap$1; } else { // avoid incompatible receiver error for prototype tag = "Map()"; fields = iterateObject$1; } } else if (object instanceof Set) { if (object instanceof object.constructor) { tag = `Set(${object.size})`; fields = iterateSet$1; } else { // avoid incompatible receiver error for prototype tag = "Set()"; fields = iterateObject$1; } } else if (arrayish) { tag = `${object.constructor.name}(${object.length})`; fields = iterateArray$1; } else if ((n = immutableName(object))) { tag = `Immutable.${n.name}${n.name === "Record" ? "" : `(${object.size})`}`; arrayish = n.arrayish; fields = n.arrayish ? iterateImArray$1 : n.setish ? iterateImSet$1 : iterateImObject$1; } else if (proto) { tag = tagof(object); fields = iterateProto; } else { tag = tagof(object); fields = iterateObject$1; } const span = document.createElement("span"); span.className = "observablehq--expanded"; if (name) { span.appendChild(inspectName(name)); } const a = span.appendChild(document.createElement("a")); a.innerHTML = ` `; a.appendChild(document.createTextNode(`${tag}${arrayish ? " [" : " {"}`)); a.addEventListener("mouseup", function(event) { event.stopPropagation(); replace(span, inspectCollapsed(object, null, name, proto)); }); fields = fields(object); for (let i = 0; !(next = fields.next()).done && i < 20; ++i) { span.appendChild(next.value); } if (!next.done) { const a = span.appendChild(document.createElement("a")); a.className = "observablehq--field"; a.style.display = "block"; a.appendChild(document.createTextNode(` … more`)); a.addEventListener("mouseup", function(event) { event.stopPropagation(); span.insertBefore(next.value, span.lastChild.previousSibling); for (let i = 0; !(next = fields.next()).done && i < 19; ++i) { span.insertBefore(next.value, span.lastChild.previousSibling); } if (next.done) span.removeChild(span.lastChild.previousSibling); dispatch(span, "load"); }); } span.appendChild(document.createTextNode(arrayish ? "]" : "}")); return span; } function* iterateMap$1(map) { for (const [key, value] of map) { yield formatMapField$1(key, value); } yield* iterateObject$1(map); } function* iterateSet$1(set) { for (const value of set) { yield formatSetField(value); } yield* iterateObject$1(set); } function* iterateImSet$1(set) { for (const value of set) { yield formatSetField(value); } } function* iterateArray$1(array) { for (let i = 0, n = array.length; i < n; ++i) { if (i in array) { yield formatField$1(i, valueof(array, i), "observablehq--index"); } } for (const key in array) { if (!isindex(key) && isown(array, key)) { yield formatField$1(key, valueof(array, key), "observablehq--key"); } } for (const symbol of symbolsof(array)) { yield formatField$1( formatSymbol(symbol), valueof(array, symbol), "observablehq--symbol" ); } } function* iterateImArray$1(array) { let i1 = 0; for (const n = array.size; i1 < n; ++i1) { yield formatField$1(i1, array.get(i1), true); } } function* iterateProto(object) { for (const key in getOwnPropertyDescriptors(object)) { yield formatField$1(key, valueof(object, key), "observablehq--key"); } for (const symbol of symbolsof(object)) { yield formatField$1( formatSymbol(symbol), valueof(object, symbol), "observablehq--symbol" ); } const proto = getPrototypeOf(object); if (proto && proto !== objectPrototype) { yield formatPrototype(proto); } } function* iterateObject$1(object) { for (const key in object) { if (isown(object, key)) { yield formatField$1(key, valueof(object, key), "observablehq--key"); } } for (const symbol of symbolsof(object)) { yield formatField$1( formatSymbol(symbol), valueof(object, symbol), "observablehq--symbol" ); } const proto = getPrototypeOf(object); if (proto && proto !== objectPrototype) { yield formatPrototype(proto); } } function* iterateImObject$1(object) { for (const [key, value] of object) { yield formatField$1(key, value, "observablehq--key"); } } function formatPrototype(value) { const item = document.createElement("div"); const span = item.appendChild(document.createElement("span")); item.className = "observablehq--field"; span.className = "observablehq--prototype-key"; span.textContent = ` `; item.appendChild(document.createTextNode(": ")); item.appendChild(inspect(value, undefined, undefined, undefined, true)); return item; } function formatField$1(key, value, className) { const item = document.createElement("div"); const span = item.appendChild(document.createElement("span")); item.className = "observablehq--field"; span.className = className; span.textContent = ` ${key}`; item.appendChild(document.createTextNode(": ")); item.appendChild(inspect(value)); return item; } function formatMapField$1(key, value) { const item = document.createElement("div"); item.className = "observablehq--field"; item.appendChild(document.createTextNode(" ")); item.appendChild(inspect(key)); item.appendChild(document.createTextNode(" => ")); item.appendChild(inspect(value)); return item; } function formatSetField(value) { const item = document.createElement("div"); item.className = "observablehq--field"; item.appendChild(document.createTextNode(" ")); item.appendChild(inspect(value)); return item; } function hasSelection(elem) { const sel = window.getSelection(); return ( sel.type === "Range" && (sel.containsNode(elem, true) || sel.anchorNode.isSelfOrDescendant(elem) || sel.focusNode.isSelfOrDescendant(elem)) ); } function inspectCollapsed(object, shallow, name, proto) { let arrayish = isarray(object); let tag, fields, next, n; if (object instanceof Map) { if (object instanceof object.constructor) { tag = `Map(${object.size})`; fields = iterateMap; } else { // avoid incompatible receiver error for prototype tag = "Map()"; fields = iterateObject; } } else if (object instanceof Set) { if (object instanceof object.constructor) { tag = `Set(${object.size})`; fields = iterateSet; } else { // avoid incompatible receiver error for prototype tag = "Set()"; fields = iterateObject; } } else if (arrayish) { tag = `${object.constructor.name}(${object.length})`; fields = iterateArray; } else if ((n = immutableName(object))) { tag = `Immutable.${n.name}${n.name === 'Record' ? '' : `(${object.size})`}`; arrayish = n.arrayish; fields = n.arrayish ? iterateImArray : n.setish ? iterateImSet : iterateImObject; } else { tag = tagof(object); fields = iterateObject; } if (shallow) { const span = document.createElement("span"); span.className = "observablehq--shallow"; if (name) { span.appendChild(inspectName(name)); } span.appendChild(document.createTextNode(tag)); span.addEventListener("mouseup", function(event) { if (hasSelection(span)) return; event.stopPropagation(); replace(span, inspectCollapsed(object)); }); return span; } const span = document.createElement("span"); span.className = "observablehq--collapsed"; if (name) { span.appendChild(inspectName(name)); } const a = span.appendChild(document.createElement("a")); a.innerHTML = ` `; a.appendChild(document.createTextNode(`${tag}${arrayish ? " [" : " {"}`)); span.addEventListener("mouseup", function(event) { if (hasSelection(span)) return; event.stopPropagation(); replace(span, inspectExpanded(object, null, name, proto)); }, true); fields = fields(object); for (let i = 0; !(next = fields.next()).done && i < 20; ++i) { if (i > 0) span.appendChild(document.createTextNode(", ")); span.appendChild(next.value); } if (!next.done) span.appendChild(document.createTextNode(", …")); span.appendChild(document.createTextNode(arrayish ? "]" : "}")); return span; } function* iterateMap(map) { for (const [key, value] of map) { yield formatMapField(key, value); } yield* iterateObject(map); } function* iterateSet(set) { for (const value of set) { yield inspect(value, true); } yield* iterateObject(set); } function* iterateImSet(set) { for (const value of set) { yield inspect(value, true); } } function* iterateImArray(array) { let i0 = -1, i1 = 0; for (const n = array.size; i1 < n; ++i1) { if (i1 > i0 + 1) yield formatEmpty(i1 - i0 - 1); yield inspect(array.get(i1), true); i0 = i1; } if (i1 > i0 + 1) yield formatEmpty(i1 - i0 - 1); } function* iterateArray(array) { let i0 = -1, i1 = 0; for (const n = array.length; i1 < n; ++i1) { if (i1 in array) { if (i1 > i0 + 1) yield formatEmpty(i1 - i0 - 1); yield inspect(valueof(array, i1), true); i0 = i1; } } if (i1 > i0 + 1) yield formatEmpty(i1 - i0 - 1); for (const key in array) { if (!isindex(key) && isown(array, key)) { yield formatField(key, valueof(array, key), "observablehq--key"); } } for (const symbol of symbolsof(array)) { yield formatField(formatSymbol(symbol), valueof(array, symbol), "observablehq--symbol"); } } function* iterateObject(object) { for (const key in object) { if (isown(object, key)) { yield formatField(key, valueof(object, key), "observablehq--key"); } } for (const symbol of symbolsof(object)) { yield formatField(formatSymbol(symbol), valueof(object, symbol), "observablehq--symbol"); } } function* iterateImObject(object) { for (const [key, value] of object) { yield formatField(key, value, "observablehq--key"); } } function formatEmpty(e) { const span = document.createElement("span"); span.className = "observablehq--empty"; span.textContent = e === 1 ? "empty" : `empty × ${e}`; return span; } function formatField(key, value, className) { const fragment = document.createDocumentFragment(); const span = fragment.appendChild(document.createElement("span")); span.className = className; span.textContent = key; fragment.appendChild(document.createTextNode(": ")); fragment.appendChild(inspect(value, true)); return fragment; } function formatMapField(key, value) { const fragment = document.createDocumentFragment(); fragment.appendChild(inspect(key, true)); fragment.appendChild(document.createTextNode(" => ")); fragment.appendChild(inspect(value, true)); return fragment; } function format(date, fallback) { if (!(date instanceof Date)) date = new Date(+date); if (isNaN(date)) return typeof fallback === "function" ? fallback(date) : fallback; const hours = date.getUTCHours(); const minutes = date.getUTCMinutes(); const seconds = date.getUTCSeconds(); const milliseconds = date.getUTCMilliseconds(); return `${formatYear(date.getUTCFullYear())}-${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); } function pad(value, width) { return `${value}`.padStart(width, "0"); } function formatDate$1(date) { return format(date, "Invalid Date"); } var errorToString = Error.prototype.toString; function formatError(value) { return value.stack || errorToString.call(value); } var regExpToString = RegExp.prototype.toString; function formatRegExp(value) { return regExpToString.call(value); } /* eslint-disable no-control-regex */ const NEWLINE_LIMIT = 20; function formatString(string, shallow, expanded, name) { if (shallow === false) { // String has fewer escapes displayed with double quotes if (count(string, /["\n]/g) <= count(string, /`|\${/g)) { const span = document.createElement("span"); if (name) span.appendChild(inspectName(name)); const textValue = span.appendChild(document.createElement("span")); textValue.className = "observablehq--string"; textValue.textContent = JSON.stringify(string); return span; } const lines = string.split("\n"); if (lines.length > NEWLINE_LIMIT && !expanded) { const div = document.createElement("div"); if (name) div.appendChild(inspectName(name)); const textValue = div.appendChild(document.createElement("span")); textValue.className = "observablehq--string"; textValue.textContent = "`" + templatify(lines.slice(0, NEWLINE_LIMIT).join("\n")); const splitter = div.appendChild(document.createElement("span")); const truncatedCount = lines.length - NEWLINE_LIMIT; splitter.textContent = `Show ${truncatedCount} truncated line${truncatedCount > 1 ? "s": ""}`; splitter.className = "observablehq--string-expand"; splitter.addEventListener("mouseup", function (event) { event.stopPropagation(); replace(div, inspect(string, shallow, true, name)); }); return div; } const span = document.createElement("span"); if (name) span.appendChild(inspectName(name)); const textValue = span.appendChild(document.createElement("span")); textValue.className = `observablehq--string${expanded ? " observablehq--expanded" : ""}`; textValue.textContent = "`" + templatify(string) + "`"; return span; } const span = document.createElement("span"); if (name) span.appendChild(inspectName(name)); const textValue = span.appendChild(document.createElement("span")); textValue.className = "observablehq--string"; textValue.textContent = JSON.stringify(string.length > 100 ? `${string.slice(0, 50)}…${string.slice(-49)}` : string); return span; } function templatify(string) { return string.replace(/[\\`\x00-\x09\x0b-\x19]|\${/g, templatifyChar); } function templatifyChar(char) { var code = char.charCodeAt(0); switch (code) { case 0x8: return "\\b"; case 0x9: return "\\t"; case 0xb: return "\\v"; case 0xc: return "\\f"; case 0xd: return "\\r"; } return code < 0x10 ? "\\x0" + code.toString(16) : code < 0x20 ? "\\x" + code.toString(16) : "\\" + char; } function count(string, re) { var n = 0; while (re.exec(string)) ++n; return n; } var toString$2 = Function.prototype.toString, TYPE_ASYNC = {prefix: "async ƒ"}, TYPE_ASYNC_GENERATOR = {prefix: "async ƒ*"}, TYPE_CLASS = {prefix: "class"}, TYPE_FUNCTION = {prefix: "ƒ"}, TYPE_GENERATOR = {prefix: "ƒ*"}; function inspectFunction(f, name) { var type, m, t = toString$2.call(f); switch (f.constructor && f.constructor.name) { case "AsyncFunction": type = TYPE_ASYNC; break; case "AsyncGeneratorFunction": type = TYPE_ASYNC_GENERATOR; break; case "GeneratorFunction": type = TYPE_GENERATOR; break; default: type = /^class\b/.test(t) ? TYPE_CLASS : TYPE_FUNCTION; break; } // A class, possibly named. // class Name if (type === TYPE_CLASS) { return formatFunction(type, "", name); } // An arrow function with a single argument. // foo => // async foo => if ((m = /^(?:async\s*)?(\w+)\s*=>/.exec(t))) { return formatFunction(type, "(" + m[1] + ")", name); } // An arrow function with parenthesized arguments. // (…) // async (…) if ((m = /^(?:async\s*)?\(\s*(\w+(?:\s*,\s*\w+)*)?\s*\)/.exec(t))) { return formatFunction(type, m[1] ? "(" + m[1].replace(/\s*,\s*/g, ", ") + ")" : "()", name); } // A function, possibly: async, generator, anonymous, simply arguments. // function name(…) // function* name(…) // async function name(…) // async function* name(…) if ((m = /^(?:async\s*)?function(?:\s*\*)?(?:\s*\w+)?\s*\(\s*(\w+(?:\s*,\s*\w+)*)?\s*\)/.exec(t))) { return formatFunction(type, m[1] ? "(" + m[1].replace(/\s*,\s*/g, ", ") + ")" : "()", name); } // Something else, like destructuring, comments or default values. return formatFunction(type, "(…)", name); } function formatFunction(type, args, cellname) { var span = document.createElement("span"); span.className = "observablehq--function"; if (cellname) { span.appendChild(inspectName(cellname)); } var spanType = span.appendChild(document.createElement("span")); spanType.className = "observablehq--keyword"; spanType.textContent = type.prefix; span.appendChild(document.createTextNode(args)); return span; } const {prototype: {toString: toString$1}} = Object; function inspect(value, shallow, expand, name, proto) { let type = typeof value; switch (type) { case "boolean": case "undefined": { value += ""; break; } case "number": { value = value === 0 && 1 / value < 0 ? "-0" : value + ""; break; } case "bigint": { value = value + "n"; break; } case "symbol": { value = formatSymbol(value); break; } case "function": { return inspectFunction(value, name); } case "string": { return formatString(value, shallow, expand, name); } default: { if (value === null) { type = null, value = "null"; break; } if (value instanceof Date) { type = "date", value = formatDate$1(value); break; } if (value === FORBIDDEN) { type = "forbidden", value = "[forbidden]"; break; } switch (toString$1.call(value)) { case "[object RegExp]": { type = "regexp", value = formatRegExp(value); break; } case "[object Error]": // https://github.com/lodash/lodash/blob/master/isError.js#L26 case "[object DOMException]": { type = "error", value = formatError(value); break; } default: return (expand ? inspectExpanded : inspectCollapsed)(value, shallow, name, proto); } break; } } const span = document.createElement("span"); if (name) span.appendChild(inspectName(name)); const n = span.appendChild(document.createElement("span")); n.className = `observablehq--${type}`; n.textContent = value; return span; } function replace(spanOld, spanNew) { if (spanOld.classList.contains("observablehq--inspect")) spanNew.classList.add("observablehq--inspect"); spanOld.parentNode.replaceChild(spanNew, spanOld); dispatch(spanNew, "load"); } const LOCATION_MATCH = /\s+\(\d+:\d+\)$/m; class Inspector { constructor(node) { if (!node) throw new Error("invalid node"); this._node = node; node.classList.add("observablehq"); } pending() { const {_node} = this; _node.classList.remove("observablehq--error"); _node.classList.add("observablehq--running"); } fulfilled(value, name) { const {_node} = this; if (!isnode(value) || (value.parentNode && value.parentNode !== _node)) { value = inspect(value, false, _node.firstChild // TODO Do this better. && _node.firstChild.classList && _node.firstChild.classList.contains("observablehq--expanded"), name); value.classList.add("observablehq--inspect"); } _node.classList.remove("observablehq--running", "observablehq--error"); if (_node.firstChild !== value) { if (_node.firstChild) { while (_node.lastChild !== _node.firstChild) _node.removeChild(_node.lastChild); _node.replaceChild(value, _node.firstChild); } else { _node.appendChild(value); } } dispatch(_node, "update"); } rejected(error, name) { const {_node} = this; _node.classList.remove("observablehq--running"); _node.classList.add("observablehq--error"); while (_node.lastChild) _node.removeChild(_node.lastChild); var div = document.createElement("div"); div.className = "observablehq--inspect"; if (name) div.appendChild(inspectName(name)); div.appendChild(document.createTextNode((error + "").replace(LOCATION_MATCH, ""))); _node.appendChild(div); dispatch(_node, "error", {error: error}); } } Inspector.into = function(container) { if (typeof container === "string") { container = document.querySelector(container); if (container == null) throw new Error("container not found"); } return function() { return new Inspector(container.appendChild(document.createElement("div"))); }; }; // Returns true if the given value is something that should be added to the DOM // by the inspector, rather than being inspected. This deliberately excludes // DocumentFragment since appending a fragment “dissolves” (mutates) the // fragment, and we wish for the inspector to not have side-effects. Also, // HTMLElement.prototype is an instanceof Element, but not an element! function isnode(value) { return (value instanceof Element || value instanceof Text) && (value instanceof value.constructor); } function RuntimeError(message, input) { this.message = message + ""; this.input = input; } RuntimeError.prototype = Object.create(Error.prototype); RuntimeError.prototype.name = "RuntimeError"; RuntimeError.prototype.constructor = RuntimeError; function generatorish(value) { return value && typeof value.next === "function" && typeof value.return === "function"; } function load(notebook, library, observer) { if (typeof library == "function") observer = library, library = null; if (typeof observer !== "function") throw new Error("invalid observer"); if (library == null) library = new Library(); const {modules, id} = notebook; const map = new Map; const runtime = new Runtime(library); const main = runtime_module(id); function runtime_module(id) { let module = map.get(id); if (!module) map.set(id, module = runtime.module()); return module; } for (const m of modules) { const module = runtime_module(m.id); let i = 0; for (const v of m.variables) { if (v.from) module.import(v.remote, v.name, runtime_module(v.from)); else if (module === main) module.variable(observer(v, i, m.variables)).define(v.name, v.inputs, v.value); else module.define(v.name, v.inputs, v.value); ++i; } } return runtime; } var prototype = Array.prototype; var map = prototype.map; var forEach = prototype.forEach; function constant(x) { return function() { return x; }; } function identity$1(x) { return x; } function rethrow(e) { return function() { throw e; }; } function noop() {} var TYPE_NORMAL = 1; // a normal variable var TYPE_IMPLICIT = 2; // created on reference var TYPE_DUPLICATE = 3; // created on duplicate definition var no_observer = {}; function Variable(type, module, observer) { if (!observer) observer = no_observer; Object.defineProperties(this, { _observer: {value: observer, writable: true}, _definition: {value: variable_undefined, writable: true}, _duplicate: {value: undefined, writable: true}, _duplicates: {value: undefined, writable: true}, _indegree: {value: NaN, writable: true}, // The number of computing inputs. _inputs: {value: [], writable: true}, _invalidate: {value: noop, writable: true}, _module: {value: module}, _name: {value: null, writable: true}, _outputs: {value: new Set, writable: true}, _promise: {value: Promise.resolve(undefined), writable: true}, _reachable: {value: observer !== no_observer, writable: true}, // Is this variable transitively visible? _rejector: {value: variable_rejector(this)}, _type: {value: type}, _value: {value: undefined, writable: true}, _version: {value: 0, writable: true} }); } Object.defineProperties(Variable.prototype, { _pending: {value: variable_pending, writable: true, configurable: true}, _fulfilled: {value: variable_fulfilled, writable: true, configurable: true}, _rejected: {value: variable_rejected, writable: true, configurable: true}, define: {value: variable_define, writable: true, configurable: true}, delete: {value: variable_delete, writable: true, configurable: true}, import: {value: variable_import, writable: true, configurable: true} }); function variable_attach(variable) { variable._module._runtime._dirty.add(variable); variable._outputs.add(this); } function variable_detach(variable) { variable._module._runtime._dirty.add(variable); variable._outputs.delete(this); } function variable_undefined() { throw variable_undefined; } function variable_rejector(variable) { return function(error) { if (error === variable_undefined) throw new RuntimeError(variable._name + " is not defined", variable._name); if (error instanceof Error && error.message) throw new RuntimeError(error.message, variable._name); throw new RuntimeError(variable._name + " could not be resolved", variable._name); }; } function variable_duplicate(name) { return function() { throw new RuntimeError(name + " is defined more than once"); }; } function variable_define(name, inputs, definition) { switch (arguments.length) { case 1: { definition = name, name = inputs = null; break; } case 2: { definition = inputs; if (typeof name === "string") inputs = null; else inputs = name, name = null; break; } } return variable_defineImpl.call(this, name == null ? null : name + "", inputs == null ? [] : map.call(inputs, this._module._resolve, this._module), typeof definition === "function" ? definition : constant(definition) ); } function variable_defineImpl(name, inputs, definition) { var scope = this._module._scope, runtime = this._module._runtime; this._inputs.forEach(variable_detach, this); inputs.forEach(variable_attach, this); this._inputs = inputs; this._definition = definition; this._value = undefined; // Is this an active variable (that may require disposal)? if (definition === noop) runtime._variables.delete(this); else runtime._variables.add(this); // Did the variable’s name change? Time to patch references! if (name !== this._name || scope.get(name) !== this) { var error, found; if (this._name) { // Did this variable previously have a name? if (this._outputs.size) { // And did other variables reference this variable? scope.delete(this._name); found = this._module._resolve(this._name); found._outputs = this._outputs, this._outputs = new Set; found._outputs.forEach(function(output) { output._inputs[output._inputs.indexOf(this)] = found; }, this); found._outputs.forEach(runtime._updates.add, runtime._updates); runtime._dirty.add(found).add(this); scope.set(this._name, found); } else if ((found = scope.get(this._name)) === this) { // Do no other variables reference this variable? scope.delete(this._name); // It’s safe to delete! } else if (found._type === TYPE_DUPLICATE) { // Do other variables assign this name? found._duplicates.delete(this); // This variable no longer assigns this name. this._duplicate = undefined; if (found._duplicates.size === 1) { // Is there now only one variable assigning this name? found = found._duplicates.keys().next().value; // Any references are now fixed! error = scope.get(this._name); found._outputs = error._outputs, error._outputs = new Set; found._outputs.forEach(function(output) { output._inputs[output._inputs.indexOf(error)] = found; }); found._definition = found._duplicate, found._duplicate = undefined; runtime._dirty.add(error).add(found); runtime._updates.add(found); scope.set(this._name, found); } } else { throw new Error; } } if (this._outputs.size) throw new Error; if (name) { // Does this variable have a new name? if (found = scope.get(name)) { // Do other variables reference or assign this name? if (found._type === TYPE_DUPLICATE) { // Do multiple other variables already define this name? this._definition = variable_duplicate(name), this._duplicate = definition; found._duplicates.add(this); } else if (found._type === TYPE_IMPLICIT) { // Are the variable references broken? this._outputs = found._outputs, found._outputs = new Set; // Now they’re fixed! this._outputs.forEach(function(output) { output._inputs[output._inputs.indexOf(found)] = this; }, this); runtime._dirty.add(found).add(this); scope.set(name, this); } else { // Does another variable define this name? found._duplicate = found._definition, this._duplicate = definition; // Now they’re duplicates. error = new Variable(TYPE_DUPLICATE, this._module); error._name = name; error._definition = this._definition = found._definition = variable_duplicate(name); error._outputs = found._outputs, found._outputs = new Set; error._outputs.forEach(function(output) { output._inputs[output._inputs.indexOf(found)] = error; }); error._duplicates = new Set([this, found]); runtime._dirty.add(found).add(error); runtime._updates.add(found).add(error); scope.set(name, error); } } else { scope.set(name, this); } } this._name = name; } runtime._updates.add(this); runtime._compute(); return this; } function variable_import(remote, name, module) { if (arguments.length < 3) module = name, name = remote; return variable_defineImpl.call(this, name + "", [module._resolve(remote + "")], identity$1); } function variable_delete() { return variable_defineImpl.call(this, null, [], noop); } function variable_pending() { if (this._observer.pending) this._observer.pending(); } function variable_fulfilled(value) { if (this._observer.fulfilled) this._observer.fulfilled(value, this._name); } function variable_rejected(error) { if (this._observer.rejected) this._observer.rejected(error, this._name); } function Module(runtime, builtins = []) { Object.defineProperties(this, { _runtime: {value: runtime}, _scope: {value: new Map}, _builtins: {value: new Map([ ["invalidation", variable_invalidation], ["visibility", variable_visibility], ...builtins ])}, _source: {value: null, writable: true} }); } Object.defineProperties(Module.prototype, { _copy: {value: module_copy, writable: true, configurable: true}, _resolve: {value: module_resolve, writable: true, configurable: true}, redefine: {value: module_redefine, writable: true, configurable: true}, define: {value: module_define, writable: true, configurable: true}, derive: {value: module_derive, writable: true, configurable: true}, import: {value: module_import, writable: true, configurable: true}, value: {value: module_value, writable: true, configurable: true}, variable: {value: module_variable, writable: true, configurable: true}, builtin: {value: module_builtin, writable: true, configurable: true} }); function module_redefine(name) { var v = this._scope.get(name); if (!v) throw new RuntimeError(name + " is not defined"); if (v._type === TYPE_DUPLICATE) throw new RuntimeError(name + " is defined more than once"); return v.define.apply(v, arguments); } function module_define() { var v = new Variable(TYPE_NORMAL, this); return v.define.apply(v, arguments); } function module_import() { var v = new Variable(TYPE_NORMAL, this); return v.import.apply(v, arguments); } function module_variable(observer) { return new Variable(TYPE_NORMAL, this, observer); } async function module_value(name) { var v = this._scope.get(name); if (!v) throw new RuntimeError(name + " is not defined"); if (v._observer === no_observer) { v._observer = true; this._runtime._dirty.add(v); } await this._runtime._compute(); return v._promise; } function module_derive(injects, injectModule) { var copy = new Module(this._runtime, this._builtins); copy._source = this; forEach.call(injects, function(inject) { if (typeof inject !== "object") inject = {name: inject + ""}; if (inject.alias == null) inject.alias = inject.name; copy.import(inject.name, inject.alias, injectModule); }); Promise.resolve().then(() => { const modules = new Set([this]); for (const module of modules) { for (const variable of module._scope.values()) { if (variable._definition === identity$1) { // import const module = variable._inputs[0]._module; const source = module._source || module; if (source === this) { // circular import-with! console.warn("circular module definition; ignoring"); // eslint-disable-line no-console return; } modules.add(source); } } } this._copy(copy, new Map); }); return copy; } function module_copy(copy, map) { copy._source = this; map.set(this, copy); for (const [name, source] of this._scope) { var target = copy._scope.get(name); if (target && target._type === TYPE_NORMAL) continue; // injection if (source._definition === identity$1) { // import var sourceInput = source._inputs[0], sourceModule = sourceInput._module; copy.import(sourceInput._name, name, map.get(sourceModule) || (sourceModule._source ? sourceModule._copy(new Module(copy._runtime, copy._builtins), map) // import-with : sourceModule)); } else { copy.define(name, source._inputs.map(variable_name), source._definition); } } return copy; } function module_resolve(name) { var variable = this._scope.get(name), value; if (!variable) { variable = new Variable(TYPE_IMPLICIT, this); if (this._builtins.has(name)) { variable.define(name, constant(this._builtins.get(name))); } else if (this._runtime._builtin._scope.has(name)) { variable.import(name, this._runtime._builtin); } else { try { value = this._runtime._global(name); } catch (error) { return variable.define(name, rethrow(error)); } if (value === undefined) { this._scope.set(variable._name = name, variable); } else { variable.define(name, constant(value)); } } } return variable; } function module_builtin(name, value) { this._builtins.set(name, value); } function variable_name(variable) { return variable._name; } const frame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : typeof setImmediate === "function" ? setImmediate : f => setTimeout(f, 0); var variable_invalidation = {}; var variable_visibility = {}; function Runtime(builtins = new Library, global = window_global) { var builtin = this.module(); Object.defineProperties(this, { _dirty: {value: new Set}, _updates: {value: new Set}, _precomputes: {value: [], writable: true}, _computing: {value: null, writable: true}, _init: {value: null, writable: true}, _modules: {value: new Map}, _variables: {value: new Set}, _disposed: {value: false, writable: true}, _builtin: {value: builtin}, _global: {value: global} }); if (builtins) for (var name in builtins) { (new Variable(TYPE_IMPLICIT, builtin)).define(name, [], builtins[name]); } } Object.defineProperties(Runtime, { load: {value: load, writable: true, configurable: true} }); Object.defineProperties(Runtime.prototype, { _precompute: {value: runtime_precompute, writable: true, configurable: true}, _compute: {value: runtime_compute, writable: true, configurable: true}, _computeSoon: {value: runtime_computeSoon, writable: true, configurable: true}, _computeNow: {value: runtime_computeNow, writable: true, configurable: true}, dispose: {value: runtime_dispose, writable: true, configurable: true}, module: {value: runtime_module, writable: true, configurable: true}, fileAttachments: {value: FileAttachments, writable: true, configurable: true} }); function runtime_dispose() { this._computing = Promise.resolve(); this._disposed = true; this._variables.forEach(v => { v._invalidate(); v._version = NaN; }); } function runtime_module(define, observer = noop) { let module; if (define === undefined) { if (module = this._init) { this._init = null; return module; } return new Module(this); } module = this._modules.get(define); if (module) return module; this._init = module = new Module(this); this._modules.set(define, module); try { define(this, observer); } finally { this._init = null; } return module; } function runtime_precompute(callback) { this._precomputes.push(callback); this._compute(); } function runtime_compute() { return this._computing || (this._computing = this._computeSoon()); } function runtime_computeSoon() { return new Promise(frame).then(() => this._disposed ? undefined : this._computeNow()); } async function runtime_computeNow() { var queue = [], variables, variable, precomputes = this._precomputes; // If there are any paused generators, resume them before computing so they // can update (if synchronous) before computing downstream variables. if (precomputes.length) { this._precomputes = []; for (const callback of precomputes) callback(); await runtime_defer(3); } // Compute the reachability of the transitive closure of dirty variables. // Any newly-reachable variable must also be recomputed. // Any no-longer-reachable variable must be terminated. variables = new Set(this._dirty); variables.forEach(function(variable) { variable._inputs.forEach(variables.add, variables); const reachable = variable_reachable(variable); if (reachable > variable._reachable) { this._updates.add(variable); } else if (reachable < variable._reachable) { variable._invalidate(); } variable._reachable = reachable; }, this); // Compute the transitive closure of updating, reachable variables. variables = new Set(this._updates); variables.forEach(function(variable) { if (variable._reachable) { variable._indegree = 0; variable._outputs.forEach(variables.add, variables); } else { variable._indegree = NaN; variables.delete(variable); } }); this._computing = null; this._updates.clear(); this._dirty.clear(); // Compute the indegree of updating variables. variables.forEach(function(variable) { variable._outputs.forEach(variable_increment); }); do { // Identify the root variables (those with no updating inputs). variables.forEach(function(variable) { if (variable._indegree === 0) { queue.push(variable); } }); // Compute the variables in topological order. while (variable = queue.pop()) { variable_compute(variable); variable._outputs.forEach(postqueue); variables.delete(variable); } // Any remaining variables are circular, or depend on them. variables.forEach(function(variable) { if (variable_circular(variable)) { variable_error(variable, new RuntimeError("circular definition")); variable._outputs.forEach(variable_decrement); variables.delete(variable); } }); } while (variables.size); function postqueue(variable) { if (--variable._indegree === 0) { queue.push(variable); } } } // We want to give generators, if they’re defined synchronously, a chance to // update before computing downstream variables. This creates a synchronous // promise chain of the given depth that we’ll await before recomputing // downstream variables. function runtime_defer(depth = 0) { let p = Promise.resolve(); for (let i = 0; i < depth; ++i) p = p.then(() => {}); return p; } function variable_circular(variable) { const inputs = new Set(variable._inputs); for (const i of inputs) { if (i === variable) return true; i._inputs.forEach(inputs.add, inputs); } return false; } function variable_increment(variable) { ++variable._indegree; } function variable_decrement(variable) { --variable._indegree; } function variable_value(variable) { return variable._promise.catch(variable._rejector); } function variable_invalidator(variable) { return new Promise(function(resolve) { variable._invalidate = resolve; }); } function variable_intersector(invalidation, variable) { let node = typeof IntersectionObserver === "function" && variable._observer && variable._observer._node; let visible = !node, resolve = noop, reject = noop, promise, observer; if (node) { observer = new IntersectionObserver(([entry]) => (visible = entry.isIntersecting) && (promise = null, resolve())); observer.observe(node); invalidation.then(() => (observer.disconnect(), observer = null, reject())); } return function(value) { if (visible) return Promise.resolve(value); if (!observer) return Promise.reject(); if (!promise) promise = new Promise((y, n) => (resolve = y, reject = n)); return promise.then(() => value); }; } function variable_compute(variable) { variable._invalidate(); variable._invalidate = noop; variable._pending(); const value0 = variable._value; const version = ++variable._version; // Lazily-constructed invalidation variable; only constructed if referenced as an input. let invalidation = null; // If the variable doesn’t have any inputs, we can optimize slightly. const promise = variable._promise = (variable._inputs.length ? Promise.all(variable._inputs.map(variable_value)).then(define) : new Promise(resolve => resolve(variable._definition.call(value0)))) .then(generate); // Compute the initial value of the variable. function define(inputs) { if (variable._version !== version) return; // Replace any reference to invalidation with the promise, lazily. for (var i = 0, n = inputs.length; i < n; ++i) { switch (inputs[i]) { case variable_invalidation: { inputs[i] = invalidation = variable_invalidator(variable); break; } case variable_visibility: { if (!invalidation) invalidation = variable_invalidator(variable); inputs[i] = variable_intersector(invalidation, variable); break; } } } return variable._definition.apply(value0, inputs); } // If the value is a generator, then retrieve its first value, and dispose of // the generator if the variable is invalidated. Note that the cell may // already have been invalidated here, in which case we need to terminate the // generator immediately! function generate(value) { if (generatorish(value)) { if (variable._version !== version) return void value.return(); (invalidation || variable_invalidator(variable)).then(variable_return(value)); return variable_generate(variable, version, value); } return value; } promise.then((value) => { if (variable._version !== version) return; variable._value = value; variable._fulfilled(value); }, (error) => { if (variable._version !== version) return; variable._value = undefined; variable._rejected(error); }); } function variable_generate(variable, version, generator) { const runtime = variable._module._runtime; let currentValue; // so that yield resolves to the yielded value // Retrieve the next value from the generator; if successful, invoke the // specified callback. The returned promise resolves to the yielded value, or // to undefined if the generator is done. function compute(onfulfilled) { return new Promise(resolve => resolve(generator.next(currentValue))).then(({done, value}) => { return done ? undefined : Promise.resolve(value).then(onfulfilled); }); } // Retrieve the next value from the generator; if successful, fulfill the // variable, compute downstream variables, and schedule the next value to be // pulled from the generator at the start of the next animation frame. If not // successful, reject the variable, compute downstream variables, and return. function recompute() { const promise = compute((value) => { if (variable._version !== version) return; currentValue = value; postcompute(value, promise).then(() => runtime._precompute(recompute)); variable._fulfilled(value); return value; }); promise.catch((error) => { if (variable._version !== version) return; postcompute(undefined, promise); variable._rejected(error); }); } // After the generator fulfills or rejects, set its current value, promise, // and schedule any downstream variables for update. function postcompute(value, promise) { variable._value = value; variable._promise = promise; variable._outputs.forEach(runtime._updates.add, runtime._updates); return runtime._compute(); } // When retrieving the first value from the generator, the promise graph is // already established, so we only need to queue the next pull. return compute((value) => { if (variable._version !== version) return; currentValue = value; runtime._precompute(recompute); return value; }); } function variable_error(variable, error) { variable._invalidate(); variable._invalidate = noop; variable._pending(); ++variable._version; variable._indegree = NaN; (variable._promise = Promise.reject(error)).catch(noop); variable._value = undefined; variable._rejected(error); } function variable_return(generator) { return function() { generator.return(); }; } function variable_reachable(variable) { if (variable._observer !== no_observer) return true; // Directly reachable. var outputs = new Set(variable._outputs); for (const output of outputs) { if (output._observer !== no_observer) return true; output._outputs.forEach(outputs.add, outputs); } return false; } function window_global(name) { return window[name]; } function renderHtml(string) { const template = document.createElement("template"); template.innerHTML = string; return document.importNode(template.content, true); } function renderSvg(string) { const g = document.createElementNS("http://www.w3.org/2000/svg", "g"); g.innerHTML = string; return g; } const html = Object.assign(hypertext(renderHtml, fragment => { if (fragment.firstChild === null) return null; if (fragment.firstChild === fragment.lastChild) return fragment.removeChild(fragment.firstChild); const span = document.createElement("span"); span.appendChild(fragment); return span; }), {fragment: hypertext(renderHtml, fragment => fragment)}); Object.assign(hypertext(renderSvg, g => { if (g.firstChild === null) return null; if (g.firstChild === g.lastChild) return g.removeChild(g.firstChild); return g; }), {fragment: hypertext(renderSvg, g => { const fragment = document.createDocumentFragment(); while (g.firstChild) fragment.appendChild(g.firstChild); return fragment; })}); const CODE_TAB = 9, CODE_LF = 10, CODE_FF = 12, CODE_CR = 13, CODE_SPACE = 32, CODE_UPPER_A = 65, CODE_UPPER_Z = 90, CODE_LOWER_A = 97, CODE_LOWER_Z = 122, CODE_LT = 60, CODE_GT = 62, CODE_SLASH = 47, CODE_DASH = 45, CODE_BANG = 33, CODE_EQ = 61, CODE_DQUOTE = 34, CODE_SQUOTE = 39, CODE_QUESTION = 63, STATE_DATA = 1, STATE_TAG_OPEN = 2, STATE_END_TAG_OPEN = 3, STATE_TAG_NAME = 4, STATE_BOGUS_COMMENT = 5, STATE_BEFORE_ATTRIBUTE_NAME = 6, STATE_AFTER_ATTRIBUTE_NAME = 7, STATE_ATTRIBUTE_NAME = 8, STATE_BEFORE_ATTRIBUTE_VALUE = 9, STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED = 10, STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED = 11, STATE_ATTRIBUTE_VALUE_UNQUOTED = 12, STATE_AFTER_ATTRIBUTE_VALUE_QUOTED = 13, STATE_SELF_CLOSING_START_TAG = 14, STATE_COMMENT_START = 15, STATE_COMMENT_START_DASH = 16, STATE_COMMENT = 17, STATE_COMMENT_LESS_THAN_SIGN = 18, STATE_COMMENT_LESS_THAN_SIGN_BANG = 19, STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH = 20, STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH = 21, STATE_COMMENT_END_DASH = 22, STATE_COMMENT_END = 23, STATE_COMMENT_END_BANG = 24, STATE_MARKUP_DECLARATION_OPEN = 25, STATE_RAWTEXT = 26, STATE_RAWTEXT_LESS_THAN_SIGN = 27, STATE_RAWTEXT_END_TAG_OPEN = 28, STATE_RAWTEXT_END_TAG_NAME = 29, SHOW_COMMENT = 128, SHOW_ELEMENT = 1, TYPE_COMMENT = 8, TYPE_ELEMENT = 1, NS_SVG = "http://www.w3.org/2000/svg", NS_XLINK = "http://www.w3.org/1999/xlink", NS_XML = "http://www.w3.org/XML/1998/namespace", NS_XMLNS = "http://www.w3.org/2000/xmlns/"; const svgAdjustAttributes = new Map([ "attributeName", "attributeType", "baseFrequency", "baseProfile", "calcMode", "clipPathUnits", "diffuseConstant", "edgeMode", "filterUnits", "glyphRef", "gradientTransform", "gradientUnits", "kernelMatrix", "kernelUnitLength", "keyPoints", "keySplines", "keyTimes", "lengthAdjust", "limitingConeAngle", "markerHeight", "markerUnits", "markerWidth", "maskContentUnits", "maskUnits", "numOctaves", "pathLength", "patternContentUnits", "patternTransform", "patternUnits", "pointsAtX", "pointsAtY", "pointsAtZ", "preserveAlpha", "preserveAspectRatio", "primitiveUnits", "refX", "refY", "repeatCount", "repeatDur", "requiredExtensions", "requiredFeatures", "specularConstant", "specularExponent", "spreadMethod", "startOffset", "stdDeviation", "stitchTiles", "surfaceScale", "systemLanguage", "tableValues", "targetX", "targetY", "textLength", "viewBox", "viewTarget", "xChannelSelector", "yChannelSelector", "zoomAndPan" ].map(name => [name.toLowerCase(), name])); const svgForeignAttributes = new Map([ ["xlink:actuate", NS_XLINK], ["xlink:arcrole", NS_XLINK], ["xlink:href", NS_XLINK], ["xlink:role", NS_XLINK], ["xlink:show", NS_XLINK], ["xlink:title", NS_XLINK], ["xlink:type", NS_XLINK], ["xml:lang", NS_XML], ["xml:space", NS_XML], ["xmlns", NS_XMLNS], ["xmlns:xlink", NS_XMLNS] ]); function hypertext(render, postprocess) { return function({raw: strings}) { let state = STATE_DATA; let string = ""; let tagNameStart; // either an open tag or an end tag let tagName; // only open; beware nesting! used only for rawtext let attributeNameStart; let attributeNameEnd; let nodeFilter = 0; for (let j = 0, m = arguments.length; j < m; ++j) { const input = strings[j]; if (j > 0) { const value = arguments[j]; switch (state) { case STATE_RAWTEXT: { if (value != null) { const text = `${value}`; if (isEscapableRawText(tagName)) { string += text.replace(/[<]/g, entity); } else if (new RegExp(`/]`, "i").test(string.slice(-tagName.length - 2) + text)) { throw new Error("unsafe raw text"); // appropriate end tag } else { string += text; } } break; } case STATE_DATA: { if (value == null) ; else if (value instanceof Node || (typeof value !== "string" && value[Symbol.iterator]) || (/(?:^|>)$/.test(strings[j - 1]) && /^(?:<|$)/.test(input))) { string += ""; nodeFilter |= SHOW_COMMENT; } else { string += `${value}`.replace(/[<&]/g, entity); } break; } case STATE_BEFORE_ATTRIBUTE_VALUE: { state = STATE_ATTRIBUTE_VALUE_UNQUOTED; let text; if (/^[\s>]/.test(input)) { if (value == null || value === false) { string = string.slice(0, attributeNameStart - strings[j - 1].length); break; } if (value === true || (text = `${value}`) === "") { string += "''"; break; } const name = strings[j - 1].slice(attributeNameStart, attributeNameEnd); if ((name === "style" && isObjectLiteral(value)) || typeof value === "function") { string += "::" + j; nodeFilter |= SHOW_ELEMENT; break; } } if (text === undefined) text = `${value}`; if (text === "") throw new Error("unsafe unquoted empty string"); string += text.replace(/^['"]|[\s>&]/g, entity); break; } case STATE_ATTRIBUTE_VALUE_UNQUOTED: { string += `${value}`.replace(/[\s>&]/g, entity); break; } case STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED: { string += `${value}`.replace(/['&]/g, entity); break; } case STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED: { string += `${value}`.replace(/["&]/g, entity); break; } case STATE_BEFORE_ATTRIBUTE_NAME: { if (isObjectLiteral(value)) { string += "::" + j + "=''"; nodeFilter |= SHOW_ELEMENT; break; } throw new Error("invalid binding"); } case STATE_COMMENT: break; default: throw new Error("invalid binding"); } } for (let i = 0, n = input.length; i < n; ++i) { const code = input.charCodeAt(i); switch (state) { case STATE_DATA: { if (code === CODE_LT) { state = STATE_TAG_OPEN; } break; } case STATE_TAG_OPEN: { if (code === CODE_BANG) { state = STATE_MARKUP_DECLARATION_OPEN; } else if (code === CODE_SLASH) { state = STATE_END_TAG_OPEN; } else if (isAsciiAlphaCode(code)) { tagNameStart = i, tagName = undefined; state = STATE_TAG_NAME, --i; } else if (code === CODE_QUESTION) { state = STATE_BOGUS_COMMENT, --i; } else { state = STATE_DATA, --i; } break; } case STATE_END_TAG_OPEN: { if (isAsciiAlphaCode(code)) { state = STATE_TAG_NAME, --i; } else if (code === CODE_GT) { state = STATE_DATA; } else { state = STATE_BOGUS_COMMENT, --i; } break; } case STATE_TAG_NAME: { if (isSpaceCode(code)) { state = STATE_BEFORE_ATTRIBUTE_NAME; tagName = lower(input, tagNameStart, i); } else if (code === CODE_SLASH) { state = STATE_SELF_CLOSING_START_TAG; } else if (code === CODE_GT) { tagName = lower(input, tagNameStart, i); state = isRawText(tagName) ? STATE_RAWTEXT : STATE_DATA; } break; } case STATE_BEFORE_ATTRIBUTE_NAME: { if (isSpaceCode(code)) ; else if (code === CODE_SLASH || code === CODE_GT) { state = STATE_AFTER_ATTRIBUTE_NAME, --i; } else if (code === CODE_EQ) { state = STATE_ATTRIBUTE_NAME; attributeNameStart = i + 1, attributeNameEnd = undefined; } else { state = STATE_ATTRIBUTE_NAME, --i; attributeNameStart = i + 1, attributeNameEnd = undefined; } break; } case STATE_ATTRIBUTE_NAME: { if (isSpaceCode(code) || code === CODE_SLASH || code === CODE_GT) { state = STATE_AFTER_ATTRIBUTE_NAME, --i; attributeNameEnd = i; } else if (code === CODE_EQ) { state = STATE_BEFORE_ATTRIBUTE_VALUE; attributeNameEnd = i; } break; } case STATE_AFTER_ATTRIBUTE_NAME: { if (isSpaceCode(code)) ; else if (code === CODE_SLASH) { state = STATE_SELF_CLOSING_START_TAG; } else if (code === CODE_EQ) { state = STATE_BEFORE_ATTRIBUTE_VALUE; } else if (code === CODE_GT) { state = isRawText(tagName) ? STATE_RAWTEXT : STATE_DATA; } else { state = STATE_ATTRIBUTE_NAME, --i; attributeNameStart = i + 1, attributeNameEnd = undefined; } break; } case STATE_BEFORE_ATTRIBUTE_VALUE: { if (isSpaceCode(code)) ; else if (code === CODE_DQUOTE) { state = STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED; } else if (code === CODE_SQUOTE) { state = STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED; } else if (code === CODE_GT) { state = isRawText(tagName) ? STATE_RAWTEXT : STATE_DATA; } else { state = STATE_ATTRIBUTE_VALUE_UNQUOTED, --i; } break; } case STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED: { if (code === CODE_DQUOTE) { state = STATE_AFTER_ATTRIBUTE_VALUE_QUOTED; } break; } case STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED: { if (code === CODE_SQUOTE) { state = STATE_AFTER_ATTRIBUTE_VALUE_QUOTED; } break; } case STATE_ATTRIBUTE_VALUE_UNQUOTED: { if (isSpaceCode(code)) { state = STATE_BEFORE_ATTRIBUTE_NAME; } else if (code === CODE_GT) { state = isRawText(tagName) ? STATE_RAWTEXT : STATE_DATA; } break; } case STATE_AFTER_ATTRIBUTE_VALUE_QUOTED: { if (isSpaceCode(code)) { state = STATE_BEFORE_ATTRIBUTE_NAME; } else if (code === CODE_SLASH) { state = STATE_SELF_CLOSING_START_TAG; } else if (code === CODE_GT) { state = isRawText(tagName) ? STATE_RAWTEXT : STATE_DATA; } else { state = STATE_BEFORE_ATTRIBUTE_NAME, --i; } break; } case STATE_SELF_CLOSING_START_TAG: { if (code === CODE_GT) { state = STATE_DATA; } else { state = STATE_BEFORE_ATTRIBUTE_NAME, --i; } break; } case STATE_BOGUS_COMMENT: { if (code === CODE_GT) { state = STATE_DATA; } break; } case STATE_COMMENT_START: { if (code === CODE_DASH) { state = STATE_COMMENT_START_DASH; } else if (code === CODE_GT) { state = STATE_DATA; } else { state = STATE_COMMENT, --i; } break; } case STATE_COMMENT_START_DASH: { if (code === CODE_DASH) { state = STATE_COMMENT_END; } else if (code === CODE_GT) { state = STATE_DATA; } else { state = STATE_COMMENT, --i; } break; } case STATE_COMMENT: { if (code === CODE_LT) { state = STATE_COMMENT_LESS_THAN_SIGN; } else if (code === CODE_DASH) { state = STATE_COMMENT_END_DASH; } break; } case STATE_COMMENT_LESS_THAN_SIGN: { if (code === CODE_BANG) { state = STATE_COMMENT_LESS_THAN_SIGN_BANG; } else if (code !== CODE_LT) { state = STATE_COMMENT, --i; } break; } case STATE_COMMENT_LESS_THAN_SIGN_BANG: { if (code === CODE_DASH) { state = STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH; } else { state = STATE_COMMENT, --i; } break; } case STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH: { if (code === CODE_DASH) { state = STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH; } else { state = STATE_COMMENT_END, --i; } break; } case STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH: { state = STATE_COMMENT_END, --i; break; } case STATE_COMMENT_END_DASH: { if (code === CODE_DASH) { state = STATE_COMMENT_END; } else { state = STATE_COMMENT, --i; } break; } case STATE_COMMENT_END: { if (code === CODE_GT) { state = STATE_DATA; } else if (code === CODE_BANG) { state = STATE_COMMENT_END_BANG; } else if (code !== CODE_DASH) { state = STATE_COMMENT, --i; } break; } case STATE_COMMENT_END_BANG: { if (code === CODE_DASH) { state = STATE_COMMENT_END_DASH; } else if (code === CODE_GT) { state = STATE_DATA; } else { state = STATE_COMMENT, --i; } break; } case STATE_MARKUP_DECLARATION_OPEN: { if (code === CODE_DASH && input.charCodeAt(i + 1) === CODE_DASH) { state = STATE_COMMENT_START, ++i; } else { // Note: CDATA and DOCTYPE unsupported! state = STATE_BOGUS_COMMENT, --i; } break; } case STATE_RAWTEXT: { if (code === CODE_LT) { state = STATE_RAWTEXT_LESS_THAN_SIGN; } break; } case STATE_RAWTEXT_LESS_THAN_SIGN: { if (code === CODE_SLASH) { state = STATE_RAWTEXT_END_TAG_OPEN; } else { state = STATE_RAWTEXT, --i; } break; } case STATE_RAWTEXT_END_TAG_OPEN: { if (isAsciiAlphaCode(code)) { tagNameStart = i; state = STATE_RAWTEXT_END_TAG_NAME, --i; } else { state = STATE_RAWTEXT, --i; } break; } case STATE_RAWTEXT_END_TAG_NAME: { if (isSpaceCode(code) && tagName === lower(input, tagNameStart, i)) { state = STATE_BEFORE_ATTRIBUTE_NAME; } else if (code === CODE_SLASH && tagName === lower(input, tagNameStart, i)) { state = STATE_SELF_CLOSING_START_TAG; } else if (code === CODE_GT && tagName === lower(input, tagNameStart, i)) { state = STATE_DATA; } else if (!isAsciiAlphaCode(code)) { state = STATE_RAWTEXT, --i; } break; } default: { state = undefined; break; } } } string += input; } const root = render(string); const walker = document.createTreeWalker(root, nodeFilter, null, false); const removeNodes = []; while (walker.nextNode()) { const node = walker.currentNode; switch (node.nodeType) { case TYPE_ELEMENT: { const attributes = node.attributes; for (let i = 0, n = attributes.length; i < n; ++i) { const {name, value: currentValue} = attributes[i]; if (/^::/.test(name)) { const value = arguments[+name.slice(2)]; removeAttribute(node, name), --i, --n; for (const key in value) { const subvalue = value[key]; if (subvalue == null || subvalue === false) ; else if (typeof subvalue === "function") { node[key] = subvalue; } else if (key === "style" && isObjectLiteral(subvalue)) { setStyles(node[key], subvalue); } else { setAttribute(node, key, subvalue === true ? "" : subvalue); } } } else if (/^::/.test(currentValue)) { const value = arguments[+currentValue.slice(2)]; removeAttribute(node, name), --i, --n; if (typeof value === "function") { node[name] = value; } else { // style setStyles(node[name], value); } } } break; } case TYPE_COMMENT: { if (/^::/.test(node.data)) { const parent = node.parentNode; const value = arguments[+node.data.slice(2)]; if (value instanceof Node) { parent.insertBefore(value, node); } else if (typeof value !== "string" && value[Symbol.iterator]) { if (value instanceof NodeList || value instanceof HTMLCollection) { for (let i = value.length - 1, r = node; i >= 0; --i) { r = parent.insertBefore(value[i], r); } } else { for (const subvalue of value) { if (subvalue == null) continue; parent.insertBefore(subvalue instanceof Node ? subvalue : document.createTextNode(subvalue), node); } } } else { parent.insertBefore(document.createTextNode(value), node); } removeNodes.push(node); } break; } } } for (const node of removeNodes) { node.parentNode.removeChild(node); } return postprocess(root); }; } function entity(character) { return `&#${character.charCodeAt(0).toString()};`; } function isAsciiAlphaCode(code) { return (CODE_UPPER_A <= code && code <= CODE_UPPER_Z) || (CODE_LOWER_A <= code && code <= CODE_LOWER_Z); } function isSpaceCode(code) { return code === CODE_TAB || code === CODE_LF || code === CODE_FF || code === CODE_SPACE || code === CODE_CR; // normalize newlines } function isObjectLiteral(value) { return value && value.toString === Object.prototype.toString; } function isRawText(tagName) { return tagName === "script" || tagName === "style" || isEscapableRawText(tagName); } function isEscapableRawText(tagName) { return tagName === "textarea" || tagName === "title"; } function lower(input, start, end) { return input.slice(start, end).toLowerCase(); } function setAttribute(node, name, value) { if (node.namespaceURI === NS_SVG) { name = name.toLowerCase(); name = svgAdjustAttributes.get(name) || name; if (svgForeignAttributes.has(name)) { node.setAttributeNS(svgForeignAttributes.get(name), name, value); return; } } node.setAttribute(name, value); } function removeAttribute(node, name) { if (node.namespaceURI === NS_SVG) { name = name.toLowerCase(); name = svgAdjustAttributes.get(name) || name; if (svgForeignAttributes.has(name)) { node.removeAttributeNS(svgForeignAttributes.get(name), name); return; } } node.removeAttribute(name); } // We can’t use Object.assign because custom properties… function setStyles(style, values) { for (const name in values) { const value = values[name]; if (name.startsWith("--")) style.setProperty(name, value); else style[name] = value; } } function length(x) { return x == null ? null : typeof x === "number" ? `${x}px` : `${x}`; } const bubbles = {bubbles: true}; function preventDefault(event) { event.preventDefault(); } function dispatchInput({currentTarget}) { (currentTarget.form || currentTarget).dispatchEvent(new Event("input", bubbles)); } function identity(x) { return x; } let nextId = 0; function newId() { return `__ns__-${++nextId}`; } function maybeLabel(label, input) { if (!label) return; label = html`