Skip to the code
cf.

Turn a DOM tree into JSON

EasyDOM

Write domToJson(node), which describes a DOM tree as plain data you could send with JSON.stringify.

An element becomes { tag, attrs, children }. tag is the element's localName: its tag name in lowercase, like "p". attrs is an object with every attribute's name and value. children is an array of its child nodes, converted the same way. attrs and children are always there, even when empty.

A text node becomes its text, unchanged, spaces included. Text nodes that are only whitespace, and comments, are left out.

// <p class="note">Hello <b>world</b></p>
domToJson(document.querySelector("p"));
// {
//   tag: "p",
//   attrs: { class: "note" },
//   children: ["Hello ", { tag: "b", attrs: {}, children: ["world"] }],
// }

What the tests check

  1. converts an empty element, with its tag in lowercase
    expect(domToJson(document.createElement("hr"))).toEqual({ tag: "hr", attrs: {}, children: [] });
    
  2. copies every attribute
    expect(domToJson(document.getElementById("card")).attrs).toEqual({ id: "card", class: "card", "data-id": "42" });
    
  3. keeps text as strings, spaces included
    expect(domToJson(document.querySelector("p"))).toEqual({
      tag: "p",
      attrs: {},
      children: ["Hello ", { tag: "b", attrs: {}, children: ["world"] }, "!"],
    });
    
  4. leaves out comments and whitespace-only text
    const result = domToJson(document.getElementById("card"));
    expect(result.children.map((child) => child.tag)).toEqual(["h2", "p", "img"]);
    
  5. turns a text node into its text
    expect(domToJson(document.querySelector("p").firstChild)).toBe("Hello ");
    
  6. converts a whole tree
    expect(domToJson(document.getElementById("card"))).toEqual({
      tag: "article",
      attrs: { id: "card", class: "card", "data-id": "42" },
      children: [
        { tag: "h2", attrs: {}, children: ["Title"] },
        { tag: "p", attrs: {}, children: ["Hello ", { tag: "b", attrs: {}, children: ["world"] }, "!"] },
        { tag: "img", attrs: { src: "cat.png", alt: "A cat" }, children: [] },
      ],
    });
    

Learn more

solution.jsSaved in this browser

Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.

Ctrl + Enter runs the tests (⌘ + Enter on a Mac).