aboutsummaryrefslogtreecommitdiffhomepage
path: root/nuldoc-src/dom.ts
blob: d8f53d760d13213ee55532245d91e28157753e88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
export type Text = {
  kind: "text";
  content: string;
  raw: false;
};

export type RawHTML = {
  kind: "text";
  content: string;
  raw: true;
};

export type Element = {
  kind: "element";
  name: string;
  attributes: Map<string, string>;
  children: Node[];
};

export type Node = Element | Text | RawHTML;

export function addClass(e: Element, klass: string) {
  const classes = e.attributes.get("class");
  if (classes === undefined) {
    e.attributes.set("class", klass);
  } else {
    const classList = classes.split(" ");
    classList.push(klass);
    classList.sort();
    e.attributes.set("class", classList.join(" "));
  }
}

export function findFirstChildElement(
  e: Element,
  name: string,
): Element | null {
  for (const c of e.children) {
    if (c.kind === "element" && c.name === name) {
      return c;
    }
  }
  return null;
}

export function findChildElements(e: Element, name: string): Element[] {
  const cs = [];
  for (const c of e.children) {
    if (c.kind === "element" && c.name === name) {
      cs.push(c);
    }
  }
  return cs;
}

export function removeChildElements(e: Element, name: string) {
  e.children = e.children.filter((c) =>
    c.kind !== "element" || c.name !== name
  );
}

export function innerText(e: Element): string {
  let t = "";
  forEachChild(e, (c) => {
    if (c.kind === "text") {
      t += c.content;
    }
  });
  return t;
}

export function forEachChild(e: Element, f: (n: Node) => void) {
  for (const c of e.children) {
    f(c);
  }
}

export function forEachChildRecursively(e: Element, f: (n: Node) => void) {
  const g = (c: Node) => {
    f(c);
    if (c.kind === "element") {
      forEachChild(c, g);
    }
  };
  forEachChild(e, g);
}

export function text(content: string): Text {
  return {
    kind: "text",
    content: content,
    raw: false,
  };
}

export function el(
  name: string,
  attrs: [string, string][],
  ...children: Node[]
): Element {
  return {
    kind: "element",
    name: name,
    attributes: new Map(attrs),
    children: children,
  };
}