Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
WebReflection committed Jan 4, 2024
1 parent 3522066 commit 0badb7d
Show file tree
Hide file tree
Showing 55 changed files with 107,736 additions and 85 deletions.
14 changes: 11 additions & 3 deletions .gitignore
Expand Up @@ -4,8 +4,16 @@ node_modules/
types/
cjs/*
!cjs/package.json
index.js
dom.js
esm/init.js
init.js
keyed.js
!esm/keyed.js
!esm/dom/keyed.js
index.js
!esm/index.js
!esm/dom/index.js
node.js
init.js
esm/init.js
!esm/node.js
!esm/dom/node.js
!test/dom/node.js
4 changes: 2 additions & 2 deletions esm/create-content.js
@@ -1,4 +1,4 @@
import { newRange } from './utils.js';
import { SVG_NAMESPACE, newRange } from './utils.js';

let template = document.createElement('template'), svg, range;

Expand All @@ -10,7 +10,7 @@ let template = document.createElement('template'), svg, range;
export default (text, xml) => {
if (xml) {
if (!svg) {
svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg = document.createElementNS(SVG_NAMESPACE, 'svg');
range = newRange();
range.selectNodeContents(svg);
}
Expand Down
2 changes: 1 addition & 1 deletion esm/creator.js
Expand Up @@ -28,7 +28,7 @@ export default parse => (
details[i] = detail(callback(node, values[i], name, empty), callback, node, name);
}
return parsed(
length === 1 ? root.firstChild : new PersistentFragment(root),
length === 1 ? (root.firstChild || current) : new PersistentFragment(root),
details
);
}
Expand Down
20 changes: 20 additions & 0 deletions esm/dom/array.js
@@ -0,0 +1,20 @@
import { DOCUMENT_FRAGMENT_NODE } from 'domconstants/constants';

import { nodeType, childNodes } from './symbols.js';

export const push = (array, nodes) => {
array.push(...nodes.flatMap(withoutFragments));
};

export const splice = (array, start, drop, nodes) => {
array.splice(start, drop, ...nodes.flatMap(withoutFragments));
};

export const unshift = (array, nodes) => {
array.unshift(...nodes.flatMap(withoutFragments));
};

const withoutFragments = node => (
node[nodeType] === DOCUMENT_FRAGMENT_NODE ?
node[childNodes].splice(0) : node
);
48 changes: 48 additions & 0 deletions esm/dom/attribute.js
@@ -0,0 +1,48 @@
import { ATTRIBUTE_NODE } from 'domconstants/constants';

import { escape } from 'html-escaper';

import Node from './node.js';

import { name, value, ownerElement, ownerDocument } from './symbols.js';

export default class Attribute extends Node {
constructor(nodeName, nodeValue = '', owner = null) {
super(ATTRIBUTE_NODE, owner?.[ownerDocument]);
this[ownerElement] = owner;
this[name] = nodeName;
this.value = nodeValue;
}

get ownerElement() {
return this[ownerElement];
}

get name() {
return this[name];
}

get localName() {
return this[name];
}

get nodeName() {
return this[name];
}

get value() {
return this[value];
}
set value(any) {
this[value] = String(any);
}

get nodeValue() {
return this[value];
}

toString() {
const { [name]: key, [value]: val } = this;
return val === '' ? key : `${key}="${escape(val)}"`;
}
}
28 changes: 28 additions & 0 deletions esm/dom/character-data.js
@@ -0,0 +1,28 @@
import Node from './node.js';
import { nodeName, value } from './symbols.js';

export default class CharacterData extends Node {
constructor(type, name, data, owner) {
super(type, owner)[nodeName] = name;
this.data = data;
}

get data() {
return this[value];
}
set data(any) {
this[value] = String(any);
}

get nodeName() {
return this[nodeName];
}

get textContent() {
return this.data;
}

set textContent(data) {
this.data = data;
}
}
18 changes: 18 additions & 0 deletions esm/dom/comment.js
@@ -0,0 +1,18 @@
import { COMMENT_NODE } from 'domconstants/constants';

import CharacterData from './character-data.js';
import { ownerDocument, value } from './symbols.js';

export default class Comment extends CharacterData {
constructor(data = '', owner = null) {
super(COMMENT_NODE, '#comment', data, owner);
}

cloneNode() {
return new Comment(this[value], this[ownerDocument]);
}

toString() {
return `<!--${this[value]}-->`;
}
}
28 changes: 28 additions & 0 deletions esm/dom/document-fragment.js
@@ -0,0 +1,28 @@
import { DOCUMENT_FRAGMENT_NODE } from 'domconstants/constants';

import Parent from './parent.js';

import { cloned } from './utils.js';
import { childNodes, nodeName, ownerDocument } from './symbols.js';

export default class DocumentFragment extends Parent {
constructor(owner = null) {
super(DOCUMENT_FRAGMENT_NODE, owner)[nodeName] = '#document-fragment';
}

get nodeName() {
return this[nodeName];
}

cloneNode(deep = false) {
const fragment = new DocumentFragment(this[ownerDocument]);
const { [childNodes]: nodes } = this;
if (deep && nodes.length)
fragment[childNodes] = nodes.map(cloned, fragment);
return fragment;
}

toString() {
return this[childNodes].join('');
}
}
23 changes: 23 additions & 0 deletions esm/dom/document-type.js
@@ -0,0 +1,23 @@
import { DOCUMENT_TYPE_NODE } from 'domconstants/constants';

import Node from './node.js';
import { nodeName } from './symbols.js';

export default class DocumentType extends Node {
constructor(name, owner = null) {
super(DOCUMENT_TYPE_NODE, owner)[nodeName] = name;
}

get nodeName() {
return this[nodeName];
}

get name() {
return this[nodeName];
}

toString() {
const { [nodeName]: value } = this;
return value ? `<!DOCTYPE ${value}>` : '';
}
}
106 changes: 106 additions & 0 deletions esm/dom/document.js
@@ -0,0 +1,106 @@
import { DOCUMENT_NODE } from 'domconstants/constants';

import { setParentNode } from './utils.js';

import { childNodes, documentElement, nodeName, ownerDocument } from './symbols.js';

import Attribute from './attribute.js';
import Comment from './comment.js';
import DocumentFragment from './document-fragment.js';
import DocumentType from './document-type.js';
import Element from './element.js';
import Event from './event.js';
import SVGElement from './svg-element.js';
import Parent from './parent.js';
import Range from './range.js';
import Text from './text.js';
import TreeWalker from './tree-walker.js';

const doctype = Symbol('doctype');
const head = Symbol('head');
const body = Symbol('body');

const defaultView = Object.create(globalThis, {
Event: { value: Event },
});

export default class Document extends Parent {
constructor(type = 'html') {
super(DOCUMENT_NODE, null)[nodeName] = '#document';
this[documentElement] = null;
this[doctype] = null;
this[head] = null;
this[body] = null;
if (type === 'html') {
const html = (this[documentElement] = new Element(type, this));
this[childNodes] = [
(this[doctype] = new DocumentType(type, this)),
html
].map(setParentNode, this)
html[childNodes] = [
(this[head] = new Element('head', this)),
(this[body] = new Element('body', this)),
].map(setParentNode, html);
}
}

get defaultView() {
return defaultView;
}

get doctype() {
return this[doctype];
}

get documentElement() {
return this[documentElement];
}

get head() {
return this[head];
}

get body() {
return this[body];
}

createAttribute(name) {
const attribute = new Attribute(name);
attribute[ownerDocument] = this;
return attribute;
}

createComment(data) {
return new Comment(data, this);
}

createDocumentFragment() {
return new DocumentFragment(this);
}

createElement(name, options = null) {
const element = new Element(name, this);
if (options?.is) element.setAttribute('is', options.is);
return element;
}

createElementNS(_, name) {
return new SVGElement(name, this);
}

createRange() {
return new Range;
}

createTextNode(data) {
return new Text(data, this);
}

createTreeWalker(parent, accept) {
return new TreeWalker(parent, accept);
}

toString() {
return this[childNodes].join('');
}
}

0 comments on commit 0badb7d

Please sign in to comment.