fix(core): Fixed package and file path typos and removed GitLab CI configuration.
This commit is contained in:
parent
51fe0fe5d2
commit
74f494131f
@ -119,6 +119,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
npmci node install stable
|
npmci node install stable
|
||||||
npmci npm install
|
npmci npm install
|
||||||
pnpm install -g @gitzone/tsdoc
|
pnpm install -g @git.zone/tsdoc
|
||||||
npmci command tsdoc
|
npmci command tsdoc
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
128
.gitlab-ci.yml
128
.gitlab-ci.yml
@ -1,128 +0,0 @@
|
|||||||
# gitzone ci_default
|
|
||||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
|
||||||
|
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- .npmci_cache/
|
|
||||||
key: '$CI_BUILD_STAGE'
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- security
|
|
||||||
- test
|
|
||||||
- release
|
|
||||||
- metadata
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- pnpm install -g pnpm
|
|
||||||
- pnpm install -g @shipzone/npmci
|
|
||||||
- npmci npm prepare
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# security stage
|
|
||||||
# ====================
|
|
||||||
# ====================
|
|
||||||
# security stage
|
|
||||||
# ====================
|
|
||||||
auditProductionDependencies:
|
|
||||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
|
||||||
stage: security
|
|
||||||
script:
|
|
||||||
- npmci command npm config set registry https://registry.npmjs.org
|
|
||||||
- npmci command pnpm audit --audit-level=high --prod
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
auditDevDependencies:
|
|
||||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
|
||||||
stage: security
|
|
||||||
script:
|
|
||||||
- npmci command npm config set registry https://registry.npmjs.org
|
|
||||||
- npmci command pnpm audit --audit-level=high --dev
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# test stage
|
|
||||||
# ====================
|
|
||||||
|
|
||||||
testStable:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm install
|
|
||||||
- npmci npm test
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
testBuild:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm install
|
|
||||||
- npmci npm build
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
release:
|
|
||||||
stage: release
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm publish
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# metadata stage
|
|
||||||
# ====================
|
|
||||||
codequality:
|
|
||||||
stage: metadata
|
|
||||||
allow_failure: true
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
script:
|
|
||||||
- npmci command npm install -g typescript
|
|
||||||
- npmci npm prepare
|
|
||||||
- npmci npm install
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
- priv
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
stage: metadata
|
|
||||||
script:
|
|
||||||
- npmci trigger
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
pages:
|
|
||||||
stage: metadata
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm install
|
|
||||||
- npmci command npm run buildDocs
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
allow_failure: true
|
|
51
changelog.md
Normal file
51
changelog.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-01-01 - 1.0.39 - fix(core)
|
||||||
|
Fixed package and file path typos and removed GitLab CI configuration.
|
||||||
|
|
||||||
|
- Corrected the package scope typos from '@gitzone' to '@git.zone'.
|
||||||
|
- Removed unused GitLab CI YAML configuration file.
|
||||||
|
- Normalized CSS scoping for shadow DOM serialization with incremental ID generation.
|
||||||
|
- Updated smartfile dependency version in package.json.
|
||||||
|
|
||||||
|
## 2024-05-29 - 1.0.38 - Configuration Updates
|
||||||
|
Minor updates to project configuration files.
|
||||||
|
|
||||||
|
- Updated description
|
||||||
|
- Revised tsconfig
|
||||||
|
- Updated npmextra.json: githost
|
||||||
|
|
||||||
|
## 2023-07-27 - 1.0.35 to 1.0.37 - Core Fixes
|
||||||
|
Maintenance releases focusing on core updates.
|
||||||
|
|
||||||
|
- Multiple fixes to the core module
|
||||||
|
|
||||||
|
## 2021-08-16 - 1.0.27 to 1.0.34 - Core Enhancements
|
||||||
|
Several updates targeting enhancements in the core functionality.
|
||||||
|
|
||||||
|
- Series of core module updates
|
||||||
|
|
||||||
|
## 2021-05-19 - 1.0.23 to 1.0.26 - Core Updates
|
||||||
|
Focused update cycle on improving core stability.
|
||||||
|
|
||||||
|
- Addressed core update issues
|
||||||
|
|
||||||
|
## 2021-01-15 - 1.0.19 to 1.0.22 - Core Fix Cycle
|
||||||
|
Incremental core updates for better performance.
|
||||||
|
|
||||||
|
- Applied multiple core updates
|
||||||
|
|
||||||
|
## 2020-08-06 - 1.0.10 to 1.0.18 - Core Adjustments
|
||||||
|
Consistent improvements and fixes in the core module.
|
||||||
|
|
||||||
|
- Ongoing core updates
|
||||||
|
|
||||||
|
## 2020-03-01 - 1.0.6 to 1.0.9 - Iterative Core Fixes
|
||||||
|
Maintaining core functionality with multiple updates.
|
||||||
|
|
||||||
|
- Continued core updates
|
||||||
|
|
||||||
|
## 2020-02-12 - 1.0.1 to 1.0.5 - Initial Core Fixes
|
||||||
|
Initial round of updates on core functionality.
|
||||||
|
|
||||||
|
- Initial set of core fixes
|
2
license
2
license
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2020 Lossless GmbH (hello@lossless.com)
|
Copyright (c) 2020 Task Venture Capital GmbH (hello@lossless.com)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
10
package.json
10
package.json
@ -14,15 +14,15 @@
|
|||||||
"buildDocs": "tsdoc"
|
"buildDocs": "tsdoc"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@gitzone/tsbuild": "^2.1.66",
|
"@git.zone/tsbuild": "^2.1.66",
|
||||||
"@gitzone/tsrun": "^1.2.44",
|
"@git.zone/tsrun": "^1.2.44",
|
||||||
"@gitzone/tstest": "^1.0.77",
|
"@git.zone/tstest": "^1.0.77",
|
||||||
"@push.rocks/tapbundle": "^5.0.8",
|
"@push.rocks/tapbundle": "^5.0.8",
|
||||||
"@types/node": "^20.4.5"
|
"@types/node": "^22.10.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@push.rocks/smartdelay": "^3.0.1",
|
"@push.rocks/smartdelay": "^3.0.1",
|
||||||
"@push.rocks/smartfile": "^10.0.26",
|
"@push.rocks/smartfile": "^11.0.23",
|
||||||
"@push.rocks/smartpath": "^5.0.5",
|
"@push.rocks/smartpath": "^5.0.5",
|
||||||
"@push.rocks/smartpromise": "^4.0.2",
|
"@push.rocks/smartpromise": "^4.0.2",
|
||||||
"@push.rocks/smartpuppeteer": "^2.0.2",
|
"@push.rocks/smartpuppeteer": "^2.0.2",
|
||||||
|
11370
pnpm-lock.yaml
generated
11370
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* autocreated commitinfo by @pushrocks/commitinfo
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartssr',
|
name: '@push.rocks/smartssr',
|
||||||
version: '1.0.38',
|
version: '1.0.39',
|
||||||
description: 'a smart server side renderer supporting shadow dom'
|
description: 'A smart server-side renderer that supports shadow DOM.'
|
||||||
}
|
}
|
||||||
|
@ -1,103 +1,151 @@
|
|||||||
|
/**
|
||||||
|
* Represents a style object on a custom element.
|
||||||
|
*/
|
||||||
|
export interface IStyleObject {
|
||||||
|
cssText: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a constructor for a custom element that may have a static `styles` property.
|
||||||
|
*/
|
||||||
|
export interface ICustomElementConstructor extends Function {
|
||||||
|
styles?: IStyleObject[];
|
||||||
|
}
|
||||||
|
|
||||||
declare var document: Document;
|
declare var document: Document;
|
||||||
export function serializeFunction(rootNode: Node) {
|
|
||||||
const uuidv4 = () => {
|
/**
|
||||||
return 'unixxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
* Serializes shadow-DOM-based elements into light DOM by:
|
||||||
const r = (Math.random() * 16) | 0;
|
* 1. Moving slotted children out of their <slot> elements.
|
||||||
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
* 2. Converting shadow-root CSS to scoping-based CSS.
|
||||||
return v.toString(16);
|
* 3. Appending styles and elements back onto the node.
|
||||||
});
|
*
|
||||||
|
* @param rootNode The root node under which all child nodes will be serialized.
|
||||||
|
*/
|
||||||
|
export function serializeFunction(rootNode: Node): void {
|
||||||
|
/**
|
||||||
|
* Instead of a UUID, we use a globally incrementing counter for stable,
|
||||||
|
* predictable IDs across multiple serializations of the same tree.
|
||||||
|
*/
|
||||||
|
let globalIdCounter = 0;
|
||||||
|
const generateStableId = (): string => {
|
||||||
|
globalIdCounter++;
|
||||||
|
// Feel free to adjust the prefix/suffix as you like
|
||||||
|
return `unix-${globalIdCounter}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const prependCss = (uuidID: string, styleTemplate: string) => {
|
/**
|
||||||
|
* Prepend the generated ID class to CSS in order to emulate :host scoping.
|
||||||
|
*/
|
||||||
|
const prependCss = (uuidID: string, styleTemplate: string): string => {
|
||||||
|
// Ensure there's at least one :host, so the user code typically expects scoping
|
||||||
if (!styleTemplate.includes(':host')) {
|
if (!styleTemplate.includes(':host')) {
|
||||||
styleTemplate = `:host {}\n\n${styleTemplate}`;
|
styleTemplate = `:host {}\n\n${styleTemplate}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace patterns that should be placed under the .uuidID scope
|
||||||
styleTemplate = styleTemplate.replace(/}[ \t\n]+\./g, `}\n\n.${uuidID} .`);
|
styleTemplate = styleTemplate.replace(/}[ \t\n]+\./g, `}\n\n.${uuidID} .`);
|
||||||
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(/\]\)/g, `]`);
|
styleTemplate = styleTemplate.replace(/\]\)/g, `]`);
|
||||||
styleTemplate = styleTemplate.replace(/:host/g, `.${uuidID}`);
|
|
||||||
|
// Replace :host with .uuidID
|
||||||
styleTemplate = styleTemplate.replace(/:host/g, `.${uuidID}`);
|
styleTemplate = styleTemplate.replace(/:host/g, `.${uuidID}`);
|
||||||
|
|
||||||
styleTemplate = styleTemplate.replace(/{[ \t\n]+\./g, `{\n\n.${uuidID} .`);
|
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]+img/g, `}\n\n.${uuidID} img`);
|
||||||
styleTemplate = styleTemplate.replace(/}[ \t\n]+div/g, `}\n\n.${uuidID} div`);
|
styleTemplate = styleTemplate.replace(/}[ \t\n]+div/g, `}\n\n.${uuidID} div`);
|
||||||
|
|
||||||
return styleTemplate;
|
return styleTemplate;
|
||||||
};
|
};
|
||||||
const loopProtection: any[] = [];
|
|
||||||
|
|
||||||
function serializeNode(nodeArg: HTMLElement | any, logThis = false) {
|
// Keep track of visited nodes to avoid loops
|
||||||
if (loopProtection.includes(nodeArg)) {
|
const visitedNodes = new WeakSet<Node>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively serializes a node, moving shadow DOM content into light DOM.
|
||||||
|
*
|
||||||
|
* @param nodeArg The node to serialize.
|
||||||
|
*/
|
||||||
|
function serializeNode(nodeArg: HTMLElement | Node): void {
|
||||||
|
// Prevent re-serializing the same node
|
||||||
|
if (visitedNodes.has(nodeArg)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loopProtection.push(nodeArg);
|
visitedNodes.add(nodeArg);
|
||||||
// console.log(nodeArg.nodeName);
|
|
||||||
if (nodeArg.shadowRoot) {
|
// If the node has a shadowRoot, move everything into light DOM
|
||||||
|
if (
|
||||||
|
nodeArg instanceof HTMLElement &&
|
||||||
|
nodeArg.shadowRoot &&
|
||||||
|
nodeArg.shadowRoot instanceof ShadowRoot
|
||||||
|
) {
|
||||||
|
// Mark node for SSR
|
||||||
nodeArg.setAttribute('smartssr', 'yes');
|
nodeArg.setAttribute('smartssr', 'yes');
|
||||||
|
|
||||||
// lets handle the current node
|
// Generate a stable ID for CSS scoping
|
||||||
const nodeUUID = uuidv4();
|
const nodeId = generateStableId();
|
||||||
|
nodeArg.classList.add(nodeId);
|
||||||
|
|
||||||
nodeArg.classList.add(nodeUUID);
|
// Move slotted nodes from <slot> to the light DOM
|
||||||
|
|
||||||
// find all slots
|
|
||||||
const slots = nodeArg.shadowRoot.querySelectorAll('slot');
|
const slots = nodeArg.shadowRoot.querySelectorAll('slot');
|
||||||
|
const slotsForMove: HTMLSlotElement[] = Array.from(slots);
|
||||||
// handle slot element
|
|
||||||
const slotsForMove: HTMLSlotElement[] = [];
|
|
||||||
slots.forEach((slot: any) => {
|
|
||||||
slotsForMove.push(slot);
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const slot of slotsForMove) {
|
for (const slot of slotsForMove) {
|
||||||
const slottedLightNodesForMove: any[] = [];
|
const slottedLightNodesForMove = slot.assignedNodes();
|
||||||
slot.assignedNodes().forEach((lightNode) => slottedLightNodesForMove.push(lightNode));
|
slottedLightNodesForMove.forEach((lightNode) => {
|
||||||
slottedLightNodesForMove.forEach((lightNode) =>
|
if (slot.parentNode) {
|
||||||
slot.parentNode.insertBefore(lightNode, slot)
|
slot.parentNode.insertBefore(lightNode, slot);
|
||||||
);
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// lets modify the css
|
// Prepare nodes to append after transformations
|
||||||
const childNodes = nodeArg.shadowRoot.childNodes;
|
const nodesToAppend: Node[] = [];
|
||||||
// tslint:disable-next-line: prefer-for-of
|
|
||||||
const noteForAppending: HTMLElement[] = [];
|
|
||||||
|
|
||||||
// lets care about static css first
|
// Some frameworks store static styles in a static `styles` property on the constructor
|
||||||
if (
|
const elementConstructor = nodeArg.constructor as ICustomElementConstructor;
|
||||||
(nodeArg.constructor as any).styles &&
|
if (Array.isArray(elementConstructor.styles)) {
|
||||||
(nodeArg.constructor as any).styles instanceof Array
|
for (const styleObj of elementConstructor.styles) {
|
||||||
) {
|
|
||||||
for (const objectArg of (nodeArg.constructor as any).styles) {
|
|
||||||
const styleTag = document.createElement('style');
|
const styleTag = document.createElement('style');
|
||||||
styleTag.textContent = prependCss(nodeUUID, objectArg.cssText);
|
styleTag.textContent = prependCss(nodeId, styleObj.cssText);
|
||||||
noteForAppending.push(styleTag);
|
nodesToAppend.push(styleTag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
childNodes.forEach((childNode: ChildNode) => {
|
// Convert existing shadow DOM childNodes
|
||||||
|
nodeArg.shadowRoot.childNodes.forEach((childNode: ChildNode) => {
|
||||||
if (childNode instanceof HTMLElement) {
|
if (childNode instanceof HTMLElement) {
|
||||||
|
// If it's a <style>, prepend the scoping class
|
||||||
if (childNode.tagName === 'STYLE') {
|
if (childNode.tagName === 'STYLE') {
|
||||||
childNode.textContent = prependCss(nodeUUID, childNode.textContent);
|
childNode.textContent = prependCss(nodeId, childNode.textContent ?? '');
|
||||||
} else {
|
} else {
|
||||||
serializeNode(childNode, logThis);
|
// Recursively serialize sub-elements
|
||||||
|
serializeNode(childNode);
|
||||||
}
|
}
|
||||||
noteForAppending.push(childNode);
|
nodesToAppend.push(childNode);
|
||||||
|
} else {
|
||||||
|
// For non-HTMLElement child nodes, just append
|
||||||
|
nodesToAppend.push(childNode);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Clear the element and re-append the now converted nodes
|
||||||
while (nodeArg.firstChild) {
|
while (nodeArg.firstChild) {
|
||||||
nodeArg.removeChild(nodeArg.firstChild);
|
nodeArg.removeChild(nodeArg.firstChild);
|
||||||
}
|
}
|
||||||
noteForAppending.forEach((childNode) => {
|
for (const childNode of nodesToAppend) {
|
||||||
nodeArg.append(childNode);
|
nodeArg.appendChild(childNode);
|
||||||
});
|
}
|
||||||
} else {
|
} else {
|
||||||
nodeArg.childNodes.forEach((nodeArg2: any) => {
|
// If it's a normal (light DOM) node, just recurse into its childNodes
|
||||||
serializeNode(nodeArg2, logThis);
|
nodeArg.childNodes.forEach((child) => {
|
||||||
|
serializeNode(child);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start serialization from the children of the provided root
|
||||||
rootNode.childNodes.forEach((nodeArg) => {
|
rootNode.childNodes.forEach((nodeArg) => {
|
||||||
serializeNode(nodeArg);
|
serializeNode(nodeArg);
|
||||||
});
|
});
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user