replace script tag with noscript and inline the states of form field components

This commit is contained in:
Yanzhen Yu
2018-09-30 17:38:44 +08:00
parent 7d1cf13266
commit 05e4103f7a
6 changed files with 195 additions and 75 deletions

View File

@@ -11,11 +11,20 @@ function buildNode(n: serializedNodeWithId): Node | null {
n.systemId,
);
case NodeType.Element:
const node = document.createElement(n.tagName);
const tagName = n.tagName === 'script' ? 'noscript' : n.tagName;
const node = document.createElement(tagName);
for (const name in n.attributes) {
if (n.attributes.hasOwnProperty(name)) {
let value = n.attributes[name];
value = typeof value === 'boolean' ? '' : value;
// textarea hack
if (n.tagName === 'textarea' && name === 'value') {
const child = document.createTextNode(value);
node.appendChild(child);
continue;
}
try {
node.setAttribute(name, n.attributes[name]);
node.setAttribute(name, value);
} catch (error) {
// skip invalid attribute
}

View File

@@ -11,6 +11,10 @@ function genId(): number {
return _id++;
}
function resetId() {
_id = 1;
}
function serializeNode(n: Node): serializedNode | false {
switch (n.nodeType) {
case n.DOCUMENT_NODE:
@@ -31,6 +35,28 @@ function serializeNode(n: Node): serializedNode | false {
for (const { name, value } of Array.from((n as HTMLElement).attributes)) {
attributes[name] = value;
}
if (
tagName === 'input' ||
tagName === 'textarea' ||
tagName === 'select'
) {
const value = (n as HTMLInputElement | HTMLTextAreaElement).value;
if (
attributes.type !== 'radio' &&
attributes.type !== 'checkbox' &&
value
) {
attributes.value = value;
} else if ((n as HTMLInputElement).checked) {
attributes.checked = (n as HTMLInputElement).checked;
}
}
if (tagName === 'option') {
const selectValue = (n as HTMLOptionElement).parentElement;
if (attributes.value === (selectValue as HTMLSelectElement).value) {
attributes.selected = (n as HTMLOptionElement).selected;
}
}
return {
type: NodeType.Element,
tagName,
@@ -65,7 +91,7 @@ function serializeNode(n: Node): serializedNode | false {
}
}
function snapshot(n: Node): serializedNodeWithId | null {
function _snapshot(n: Node): serializedNodeWithId | null {
const _serializedNode = serializeNode(n);
if (!_serializedNode) {
// TODO: dev only
@@ -80,10 +106,15 @@ function snapshot(n: Node): serializedNodeWithId | null {
serializedNode.type === NodeType.Element
) {
for (const childN of Array.from(n.childNodes)) {
serializedNode.childNodes.push(snapshot(childN));
serializedNode.childNodes.push(_snapshot(childN));
}
}
return serializedNode;
}
function snapshot(n: Node): serializedNodeWithId | null {
resetId();
return _snapshot(n);
}
export default snapshot;

View File

@@ -20,7 +20,7 @@ export type documentTypeNode = {
};
export type attributes = {
[key: string]: string;
[key: string]: string | boolean;
};
export type elementNode = {
type: NodeType.Element;