PNG: very basic UI skeleton
Looks awful and is unusable, but the data seems to be there.
This commit is contained in:
parent
d917aaab6b
commit
92098e69b6
|
@ -12,10 +12,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="error" hidden>Failed to parse PNG</div>
|
<div id="error" hidden>Failed to parse PNG</div>
|
||||||
<div id="explorer" hidden>
|
<div id="explorer" hidden></div>
|
||||||
<div id="bytesEl"></div>
|
|
||||||
<div id="treeEl"></div>
|
|
||||||
</div>
|
|
||||||
<script src="png.js" type="module"></script>
|
<script src="png.js" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
import { PngNodeType } from "./constants.js";
|
import { PngNodeType } from "./constants.js";
|
||||||
import { areBytesEqual, chunkBytes } from "../common/bytes.js";
|
import { areBytesEqual, chunkBytes } from "../common/bytes.js";
|
||||||
import crc32 from "./crc32.js";
|
import crc32 from "./crc32.js";
|
||||||
|
/** @typedef {import("../../types/png.d.ts").PngNode} PngNode */
|
||||||
/** @typedef {import("../../types/png.d.ts").Node<PngNodeType>} PngNode */
|
|
||||||
|
|
||||||
const PNG_SIGNATURE = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
|
const PNG_SIGNATURE = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,82 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
|
import crel from "../common/crel.js";
|
||||||
import parsePng from "./parsePng.js";
|
import parsePng from "./parsePng.js";
|
||||||
|
|
||||||
import parseHash from "./parseHash.js";
|
import parseHash from "./parseHash.js";
|
||||||
|
/** @typedef {import("./nodePath.js").NodePath} NodePath */
|
||||||
|
/** @typedef {import("../../types/png.d.ts").PngNode} PngNode */
|
||||||
|
|
||||||
const errorEl = document.getElementById("error");
|
const errorEl = document.getElementById("error");
|
||||||
const explorerEl = document.getElementById("explorer");
|
const explorerEl = document.getElementById("explorer");
|
||||||
if (!errorEl || !explorerEl) throw new Error("HTML is not set up correctly");
|
if (!errorEl || !explorerEl) throw new Error("HTML is not set up correctly");
|
||||||
|
|
||||||
|
class Explorer {
|
||||||
|
#bytesEl = crel("div", { class: "bytes" });
|
||||||
|
#treeEl = crel("div", { class: "tree" });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {PngNode} rootNode
|
||||||
|
*/
|
||||||
|
constructor(rootNode) {
|
||||||
|
/**
|
||||||
|
* @param {PngNode} node
|
||||||
|
* @param {NodePath} path
|
||||||
|
* @returns [HTMLElement, HTMLElement] Each node's bytes and tree elements.
|
||||||
|
*/
|
||||||
|
const traverse = (node, path) => {
|
||||||
|
const nodeBytesEl = crel("span", { "data-path": path });
|
||||||
|
|
||||||
|
// TODO: Show a user-friendly title.
|
||||||
|
const isRoot = path.length === 0;
|
||||||
|
const title = node.type;
|
||||||
|
const description = "TODO: Description";
|
||||||
|
const nodeTreeEl = crel(
|
||||||
|
"details",
|
||||||
|
{ "data-path": path, open: isRoot },
|
||||||
|
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),
|
||||||
|
);
|
||||||
|
nodeBytesEl.append(childBytesEl);
|
||||||
|
treeChildrenEl.append(childTreeEl);
|
||||||
|
});
|
||||||
|
nodeTreeEl.append(treeChildrenEl);
|
||||||
|
} else {
|
||||||
|
// TODO: Update this formatting
|
||||||
|
nodeBytesEl.innerHTML = [...node.bytes].map((b) =>
|
||||||
|
b.toString(16).padStart(2, "0")
|
||||||
|
).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return [nodeBytesEl, nodeTreeEl];
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: better variable names
|
||||||
|
const [a, b] = traverse(rootNode, []);
|
||||||
|
this.#bytesEl.append(a);
|
||||||
|
this.#treeEl.append(b);
|
||||||
|
|
||||||
|
this.el = document.createDocumentFragment();
|
||||||
|
this.el.append(this.#bytesEl, this.#treeEl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const main = () => {
|
const main = () => {
|
||||||
// TODO: We may want a better UI here.
|
// TODO: We may want a better UI here.
|
||||||
// TODO: Handle hash changes.
|
// TODO: Handle hash changes.
|
||||||
|
@ -26,8 +95,11 @@ const main = () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Actually do something!
|
const explorer = new Explorer(rootNode);
|
||||||
console.log(rootNode);
|
|
||||||
|
explorerEl.innerHTML = "";
|
||||||
|
explorerEl.append(explorer.el);
|
||||||
|
explorerEl.removeAttribute("hidden");
|
||||||
};
|
};
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
export type Node<T> = {
|
import { PngNodeType } from "../public/png/constants.js";
|
||||||
|
|
||||||
|
type Node<T> = {
|
||||||
/**
|
/**
|
||||||
* The type of this node. Typically an enum specific to the format.
|
* The type of this node. Typically an enum specific to the format.
|
||||||
*/
|
*/
|
||||||
|
@ -17,3 +19,5 @@ export type Node<T> = {
|
||||||
*/
|
*/
|
||||||
children?: ReadonlyArray<Node<T>>;
|
children?: ReadonlyArray<Node<T>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type PngNode = Node<PngNodeType>;
|
||||||
|
|
Loading…
Reference in New Issue