aboutsummaryrefslogtreecommitdiff
path: root/src/index.ts
blob: 02da27a1698f4505a871407f8643b6092d90ed21 (plain) (blame)
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
const UNSET_PROPERTY_VALUE = '<unset>';
const EVENT_HANDLERS = {
  click: '--cssx-on-click',
  load: '--cssx-on-load',
}

const injectStyles = () => {
  const STYLE_TAG_CLASS = 'cssx-style-root';
  if (document.querySelector(`.${STYLE_TAG_CLASS}`)) return;

  const $style = document.createElement('style');
  $style.className = STYLE_TAG_CLASS;

  const properties = [
    '--cssx-children',
    ...Object.values(EVENT_HANDLERS),
  ];

  $style.textContent = `.cssx-layer {
    ${properties.map(p => `${p}: ${UNSET_PROPERTY_VALUE};`).join(' ')}
  }`;

  document.body.appendChild($style);
}

const getPropertyValue = ($element: HTMLElement, prop: string) => {
  const value = `${getComputedStyle($element).getPropertyValue(prop)}`.trim()
  return !value || value === UNSET_PROPERTY_VALUE ? '' : value;
};

const getChildrenIds = ($element: HTMLElement) => {
  const value = getPropertyValue($element, '--cssx-children')
  return value.split(/(\s*,\s*)|\s*/g).filter(Boolean)
}

const handleEvents = ($element: HTMLElement) => {
  Object.entries(EVENT_HANDLERS).forEach(([event, property]) => {
    const handlerExpr = getPropertyValue($element, property);
    if (handlerExpr) {
      // TODO: Parse onclick
      // TODO: attach handler for eval
      console.log(event, handlerExpr);
    }
  });
};

let iters = 0;
const manageElement = ($element: HTMLElement) => {
  if (iters++ > 100) return; // NOTE: Temporary. To prevent infinite rec

  handleEvents($element);

  const $childrenRoot = Object.assign(document.createElement('div'), {
    className: 'cssx-layer',
  });
  $element.appendChild($childrenRoot);

  const childrenIds = getChildrenIds($element);
  for (const id of childrenIds) {
    const $child = Object.assign(document.createElement('div'), { id });
    $childrenRoot.appendChild($child);
    manageElement($child);
  }
}

interface Options {
  root?: HTMLElement;
}
const render = ({ root = document.body }: Options = {}) => {
  injectStyles();
  manageElement(root);
}

render();