DEV Community

Murahashi [Matt] Kenichi
Murahashi [Matt] Kenichi

Posted on • Edited on

Let's build browser engine! in typescript vol5 DOM Shortcut

Create DOM Shortcut. I'll "actually" parse this later.

// $ node_modules/.bin/ts-node example/dom-shortcut.ts
import { elem, text } from "../src/dom";

// <html><body>Hello, world!</body></html>
//
// let root = elem("html");
// let body = elem("body");
// root.children.push(body);
// body.children.push(text("Hello, world!"));

const root = elem("html", new Map([]), []);
const body = elem("body", new Map([]), []);
root.children.push(body);
body.children.push(text("Hello, world!"));
console.dir(root, { depth: null });

// DomNode {
//   children: [
//     DomNode {
//       children: [
//         DomNode {
//           children: [],
//           nodeType: Text { format: 1, text: 'Hello, world!' }
//     }
//   ],
//     nodeType: Element {
//     format: 0,
//       element: ElementData { tagName: 'body', attributes: Map {} }
//   }
// }
// ],
//   nodeType: Element {
//     format: 0,
//       element: ElementData { tagName: 'html', attributes: Map {} }
//   }
// }
//
Enter fullscreen mode Exit fullscreen mode
test("node type text", () => {
  expect(() => new NodeType.Text("no mean")).not.toThrow();
});

test("node type element", () => {
  expect(() => new NodeType.Element(new ElementData("no mean", new Map([])))).not.toThrow();
});
Enter fullscreen mode Exit fullscreen mode
export class DomNode {
  children: DomNode[];
  nodeType: NodeType;

  constructor(children: DomNode[], nodeType: NodeType) {
    this.children = children;
    this.nodeType = nodeType;
  }
}

export namespace NodeType {
  export enum Format {
    Element,
    Text
  }

  export class Element {
    readonly format = Format.Element;
    element: ElementData;

    constructor(element: ElementData) {
      this.element = element;
    }
  }

  export class Text {
    readonly format = Format.Text;
    text: string;

    constructor(text: string) {
      this.text = text;
    }
  }
}

export type NodeType = NodeType.Element | NodeType.Text;

type AttrMap = Map<string, string>;

export class ElementData {
  tagName: string;
  attributes: AttrMap;

  constructor(tagName: string, attributes: AttrMap) {
    this.tagName = tagName;
    this.attributes = attributes;
  }
}
Enter fullscreen mode Exit fullscreen mode

Alias shortcut for node type text.

test("text", () => {
  expect(text("target")).toEqual(new DomNode([], new NodeType.Text("target")));
});
Enter fullscreen mode Exit fullscreen mode
export function text(data: string): DomNode {
  return new DomNode([], new NodeType.Text(data));
}
Enter fullscreen mode Exit fullscreen mode

Alias shortcut for node type element.

test("elem", () => {
  expect(elem("a", new Map([["b", "c"]]), [])).toEqual(
    new DomNode([], new NodeType.Element(new ElementData("a", new Map([["b", "c"]]))))
  );
});
Enter fullscreen mode Exit fullscreen mode
export function elem(name: string, attrs: AttrMap, children: DomNode[]): DomNode {
  return new DomNode(children, new NodeType.Element(new ElementData(name, attrs)));
}
Enter fullscreen mode Exit fullscreen mode

yeah!

references

series

Top comments (0)