// @ts-check import crel, { fragment } from "../common/crel.js"; import formatBytes from "../common/formatBytes.js"; /** @typedef {import("./nodePath.js").NodePath} NodePath */ /** @typedef {import("../../types/png.d.ts").PngNode} PngNode */ /** * @typedef {Function} NodeUiFn * @param {PngNode} node * @returns {NodeUi} */ /** * @param {PngNode} rootNode * @param {NodeUiFn} getNodeUi * @returns {DocumentFragment} */ export default (rootNode, getNodeUi) => { const [bytesRootEl, treeRootEl] = traverse(rootNode, [], getNodeUi); const outerBytesEl = crel("div", { class: "bytes" }, bytesRootEl); const outerTreeEl = crel("div", { class: "tree" }, treeRootEl); return fragment(outerBytesEl, outerTreeEl); }; /** * @param {PngNode} node * @param {NodePath} path * @param {NodeUiFn} getNodeUi * @returns [HTMLElement, HTMLElement] Each node's bytes and tree elements. */ const traverse = (node, path, getNodeUi) => { const nodeBytesEl = crel("span", { "data-path": path }); const isRoot = path.length === 0; const { title, description } = getNodeUi(node); const nodeTreeEl = crel( "details", { "data-path": path, ...(isRoot ? { open: "open" } : {}) }, crel( "summary", {}, crel("span", { "class": "title" }, title), crel( "span", { "class": "bytecount" }, "TODO: X bytes", ), ), description, ); if (node.children) { const treeChildrenEl = crel("div", { class: "children" }); node.children.forEach((child, index) => { const [childBytesEl, childTreeEl] = traverse( child, path.concat(index), getNodeUi, ); if (index > 0) nodeBytesEl.append(" "); nodeBytesEl.append(childBytesEl); treeChildrenEl.append(childTreeEl); }); nodeTreeEl.append(treeChildrenEl); } else { nodeBytesEl.innerHTML = formatBytes(node.bytes, 256); } return [nodeBytesEl, nodeTreeEl]; };