smartssr/ts/smartssr.function.serialize.ts

104 lines
3.5 KiB
TypeScript
Raw Permalink Normal View History

2020-02-12 21:31:22 +00:00
declare var document: Document;
2021-08-17 10:54:19 +00:00
export function serializeFunction(rootNode: Node) {
2020-02-12 21:31:22 +00:00
const uuidv4 = () => {
2020-08-06 15:13:38 +00:00
return 'unixxxxxxxxxxx'.replace(/[xy]/g, (c) => {
2020-02-12 21:31:22 +00:00
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
};
const prependCss = (uuidID: string, styleTemplate: string) => {
if (!styleTemplate.includes(':host')) {
styleTemplate = `:host {}\n\n${styleTemplate}`;
}
styleTemplate = styleTemplate.replace(/}[ \t\n]+\./g, `}\n\n.${uuidID} .`);
styleTemplate = styleTemplate.replace(/}[ \t\n]+\*/g, `}\n\n.${uuidID} *`);
styleTemplate = styleTemplate.replace(/\(\[/g, `[`);
styleTemplate = styleTemplate.replace(/\]\)/g, `]`);
styleTemplate = styleTemplate.replace(/:host/g, `.${uuidID}`);
styleTemplate = styleTemplate.replace(/:host/g, `.${uuidID}`);
2020-02-12 21:32:25 +00:00
2020-02-12 21:31:22 +00:00
styleTemplate = styleTemplate.replace(/{[ \t\n]+\./g, `{\n\n.${uuidID} .`);
styleTemplate = styleTemplate.replace(/}[ \t\n]+img/g, `}\n\n.${uuidID} img`);
styleTemplate = styleTemplate.replace(/}[ \t\n]+div/g, `}\n\n.${uuidID} div`);
return styleTemplate;
};
2020-08-06 15:13:38 +00:00
const loopProtection: any[] = [];
2020-02-12 21:31:22 +00:00
2021-08-17 10:54:19 +00:00
function serializeNode(nodeArg: HTMLElement | any, logThis = false) {
2020-08-06 15:13:38 +00:00
if (loopProtection.includes(nodeArg)) {
2020-02-12 21:31:22 +00:00
return;
}
2020-08-06 15:13:38 +00:00
loopProtection.push(nodeArg);
// console.log(nodeArg.nodeName);
if (nodeArg.shadowRoot) {
nodeArg.setAttribute('smartssr', 'yes');
2020-08-06 15:17:01 +00:00
2020-08-06 15:13:38 +00:00
// lets handle the current node
const nodeUUID = uuidv4();
2020-02-12 21:31:22 +00:00
2020-08-06 15:13:38 +00:00
nodeArg.classList.add(nodeUUID);
2021-05-19 11:32:12 +00:00
// find all slots
2020-08-06 15:13:38 +00:00
const slots = nodeArg.shadowRoot.querySelectorAll('slot');
2020-02-12 21:31:22 +00:00
2020-08-06 15:13:38 +00:00
// handle slot element
2020-08-06 17:50:00 +00:00
const slotsForMove: HTMLSlotElement[] = [];
2021-08-17 10:54:19 +00:00
slots.forEach((slot: any) => {
2020-08-06 17:50:00 +00:00
slotsForMove.push(slot);
2020-08-06 15:13:38 +00:00
});
2020-02-12 21:31:22 +00:00
2020-08-06 17:50:00 +00:00
for (const slot of slotsForMove) {
2021-08-17 10:54:19 +00:00
const slottedLightNodesForMove: any[] = [];
2020-08-06 17:50:00 +00:00
slot.assignedNodes().forEach((lightNode) => slottedLightNodesForMove.push(lightNode));
2021-01-08 22:08:01 +00:00
slottedLightNodesForMove.forEach((lightNode) =>
slot.parentNode.insertBefore(lightNode, slot)
);
2020-08-06 17:50:00 +00:00
}
2020-08-06 15:13:38 +00:00
// lets modify the css
const childNodes = nodeArg.shadowRoot.childNodes;
// tslint:disable-next-line: prefer-for-of
const noteForAppending: HTMLElement[] = [];
2021-05-19 11:32:12 +00:00
// lets care about static css first
2021-08-16 14:26:13 +00:00
if (
(nodeArg.constructor as any).styles &&
(nodeArg.constructor as any).styles instanceof Array
) {
2021-05-19 15:21:47 +00:00
for (const objectArg of (nodeArg.constructor as any).styles) {
const styleTag = document.createElement('style');
styleTag.textContent = prependCss(nodeUUID, objectArg.cssText);
noteForAppending.push(styleTag);
}
2021-05-19 11:32:12 +00:00
}
2021-08-17 10:54:19 +00:00
childNodes.forEach((childNode: ChildNode) => {
2020-08-06 15:13:38 +00:00
if (childNode instanceof HTMLElement) {
if (childNode.tagName === 'STYLE') {
childNode.textContent = prependCss(nodeUUID, childNode.textContent);
} else {
serializeNode(childNode, logThis);
}
noteForAppending.push(childNode);
}
});
2021-01-15 14:22:49 +00:00
while (nodeArg.firstChild) {
2021-01-15 07:17:08 +00:00
nodeArg.removeChild(nodeArg.firstChild);
}
2020-08-06 15:17:01 +00:00
noteForAppending.forEach((childNode) => {
2020-08-06 15:13:38 +00:00
nodeArg.append(childNode);
});
} else {
nodeArg.childNodes.forEach((nodeArg2: any) => {
serializeNode(nodeArg2, logThis);
});
2020-02-12 21:31:22 +00:00
}
}
2020-08-06 15:13:38 +00:00
rootNode.childNodes.forEach((nodeArg) => {
serializeNode(nodeArg);
});
2020-02-12 21:31:22 +00:00
}