You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
9.7 KiB
313 lines
9.7 KiB
/**
|
|
* This class defines the Component generator.
|
|
* It externalizes all decision making about script or style storage from the component.
|
|
* The component stores the generator (if set, if not =default or passed down from parent component).
|
|
* The CompelGenerator class enables the setup/definition of storage, generation and distribution.
|
|
*
|
|
* Further if other frameworks are targeted:
|
|
* if the components should be generated in a manner
|
|
* that they fullfill the setup/look of other framework-components.
|
|
* Only the generator has to be modified, implemented, extended ...
|
|
* not the component, modifier or any other of the classes.
|
|
*
|
|
* Therefore the usages of CompelGenerator-feature-logic resets all style and script storages to local.
|
|
* Only towards the end (when "generate()" is called) any of that will be resolved.
|
|
*/
|
|
class CompelGenerator {
|
|
/**
|
|
* @param {ExtStorage} styleStore default ExtStoreType.INTERNALIZED_WITHIN
|
|
* @param {ExtStorage} functionStore default ExtStoreType.CENTRALIZED_DOC_HEAD
|
|
*/
|
|
constructor(
|
|
styleStore = ExtStoreType.INTERNALIZED_WITHIN
|
|
.setOverwriteBehaviour(OverwriteBehaviour.REPLACE),
|
|
functionStore = ExtStoreType.CENTRALIZED_DOC_HEAD
|
|
.setOverwriteBehaviour(OverwriteBehaviour.REPLACE)
|
|
) {
|
|
this._styleStore = styleStore;
|
|
this._functionStore = functionStore;
|
|
}
|
|
|
|
|
|
/**
|
|
* Deals with the direct component stylings
|
|
* @param {Component} component
|
|
* @param {Array<WebTrinity>} childrenWenity
|
|
* @param {ExtStorage} extStore
|
|
* @returns {Array<SStoreDefinition>}
|
|
*/
|
|
processStyles(component, extStore = null) {
|
|
extStore = (extStore
|
|
? extStore
|
|
: component._stylesExtStore
|
|
)
|
|
.setupForGeneralStyling();
|
|
|
|
let forCollection = [];
|
|
|
|
let counter = 0;
|
|
for (const ssd of component._styles) {
|
|
/* Make sure that the type is unified for later processing */
|
|
if (ssd._definition instanceof Modifier) {
|
|
ssd._definition = ssd._definition._modifications;
|
|
}
|
|
|
|
/* Check/Ensure proper ExtStorageType for following comparison */
|
|
/**
|
|
* @type {ExtStorage}
|
|
*/
|
|
let curExtStore = extStore;
|
|
|
|
if (ssd.hasOwnProperty("_extStore") && ssd._extStore) {
|
|
curExtStore = ssd._extStore.setupForGeneralStyling();
|
|
}
|
|
|
|
if (curExtStore.getStylingDistribution()(ssd, component._element, counter)) {
|
|
forCollection.push(ssd);
|
|
}
|
|
}
|
|
|
|
return forCollection;
|
|
}
|
|
|
|
|
|
/**
|
|
* First deals with the scripts/functions.
|
|
*
|
|
* @param {Component} component
|
|
* @param {Array<WebTrinity>} childrenWenity
|
|
* @param {ExtStorage} extStore
|
|
* @returns {Array<SStoreDefinition>}
|
|
*/
|
|
processFunctions(component, extStore = null) {
|
|
extStore = (extStore
|
|
? extStore
|
|
: component._functionsExtStore
|
|
)
|
|
.setupForFunctions();
|
|
|
|
const forCollection = new Map();
|
|
const collectForBefore = [];
|
|
|
|
let counter = 0;
|
|
for (const ssd of component._functions) {
|
|
/* Make sure that the type is unified for later processing */
|
|
|
|
let curExtStore = extStore;
|
|
if (Object.hasOwn(ssd, "_extStore") && ssd._extStore) {
|
|
curExtStore = ssd._extStore.setupForFunctions();
|
|
}
|
|
|
|
if (curExtStore.getFunctionDistribution()(ssd, counter)) {
|
|
if (curExtStore._position.BEFORE) {
|
|
collectForBefore.push(ssd);
|
|
} else {
|
|
if (!forCollection.has(curExtStore)) {
|
|
forCollection.set(curExtStore, []);
|
|
}
|
|
forCollection.get(curExtStore).push(ssd);
|
|
}
|
|
}
|
|
}
|
|
|
|
return forCollection;
|
|
}
|
|
|
|
|
|
/**
|
|
* checks if the source has the extStoreType
|
|
* fills the target extStoreType-array with the corr. elements of source.
|
|
* @param {Map<ExtStoreType, Array<SStoreDefinition>>} source
|
|
* @param {Map<ExtStoreType, Array<SStoreDefinition>>} target
|
|
* @param {ExtStoreType} extStoreType
|
|
* @returns
|
|
*/
|
|
transferCollectedFunctions(source, target, extStoreType) {
|
|
if (source) {
|
|
if (source.has(extStoreType)) {
|
|
if (funcCollections.has(extStoreType)) {
|
|
target.get(extStoreType)
|
|
.push(source.get(extStoreType))
|
|
} else {
|
|
target.set(
|
|
extStoreType,
|
|
source.get(extStoreType)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*
|
|
* @param {Map<ExtStoreType, *>} extFuncMap
|
|
* @param {ExtStorageType} extStoreType
|
|
*/
|
|
dealCollectedFuncs(extFuncMap, extStoreType) {
|
|
if (extFuncMap.has(extStoreType)) {
|
|
let collectionScriptTag = generateAndFillScriptTag(extFuncMap.get(extStoreType));
|
|
if (extStoreType === ExtStoreType.COLLECTED_SEGMENT_BEGIN) {
|
|
this._element.insertAdjacentElement(
|
|
"afterbegin",
|
|
generateAndFillScriptTag(segment)
|
|
);
|
|
} else {
|
|
Page.addElementToPage(
|
|
collectionScriptTag,
|
|
extStoreType
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Generates and appends a child Component.
|
|
* @param {Component} parent component the child component to add it.
|
|
* @param {Component|WebTrinity|string} child
|
|
* @returns {WebTrinity}
|
|
*/
|
|
appendChildComponent(parent, child) {
|
|
let childWT = new WebTrinity();
|
|
if (child instanceof Component) {
|
|
childWT = child.generate(this);
|
|
}
|
|
|
|
if (child instanceof WebTrinity) {
|
|
childWT = child;
|
|
}
|
|
|
|
if (child instanceof HTMLElement) {
|
|
console.log("No wenity set - htmlEl was given");
|
|
childWT.compext = child;
|
|
}
|
|
|
|
parent._element.append(childWT.compext);
|
|
|
|
return childWT;
|
|
}
|
|
|
|
|
|
/**
|
|
* Iterates over the children of the component
|
|
* and calls generate on each child.
|
|
* The resulting compext (the text of the component) is added/appended accordingly.
|
|
* If the generation returns with delegatable scripts or styles
|
|
* the WebTrinity object is collected in an array,
|
|
* which will be returned.
|
|
*
|
|
* @param {Component} component
|
|
* @returns {Array<WebTrinity>}
|
|
*/
|
|
resolveChildren(component, styleStore, functionStore) {
|
|
/**
|
|
* @type {Array<WebTrinity>}
|
|
*/
|
|
let wenities = [];
|
|
|
|
for (let child of component._children) {
|
|
child = child.generate(this, styleStore, functionStore);
|
|
|
|
let wenity = this.appendChildComponent(component, child);
|
|
|
|
if (!wenity.isSSEmpty()) {
|
|
wenities.push(wenity);
|
|
}
|
|
}
|
|
|
|
return wenities;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* @param {Component} component
|
|
* @param {ExtStorage} [styleStore=null]
|
|
* @param {ExtStorage} [functionStore=null]
|
|
* @returns {WebTrinity}
|
|
*/
|
|
generate(component, styleStore = null, functionStore = null) {
|
|
|
|
if (!styleStore) {
|
|
styleStore = component._stylesExtStore;
|
|
}
|
|
if (!functionStore) {
|
|
functionStore = component._functionsExtStore;
|
|
}
|
|
|
|
/**
|
|
* DEAL WITH COMPONENT MODIFICATION FIRST
|
|
*
|
|
* @todo pay attention to the "overwrite" behaviour
|
|
* the local modifier styles are the "closest"
|
|
* it might be appropriate to use this._styles.unshift(...) instead.
|
|
*/
|
|
component._styles.push(new SStoreDefinition(
|
|
(styleStore._aggregation !== ESAggregation.INTERNALIZED
|
|
? "."
|
|
: "")
|
|
+ component._compName,
|
|
component._modifier,
|
|
component._stylesExtStore
|
|
));
|
|
|
|
/**
|
|
* DEAL WITH CHILDREN
|
|
*
|
|
* Depending on the setup of the generator/-tion
|
|
* The children might return scripts or styles
|
|
* that are supposed to be collected
|
|
* and dealt with as a collection.
|
|
*/
|
|
let childrenWenities = this.resolveChildren(component, styleStore, functionStore);
|
|
|
|
/**
|
|
* DEAL WITH STYLES AND SCRIPTS
|
|
*/
|
|
|
|
/**
|
|
* @type {Array<SStoreDefinition>}
|
|
*/
|
|
let styleCollection = this.processStyles(component, styleStore);
|
|
/**
|
|
* @type {Map<ExtStoreType, Array<SStoreDefinition>>}
|
|
*/
|
|
let funcCollections = this.processFunctions(component, functionStore);
|
|
|
|
/**
|
|
* DEAL WITH CHILDREN WENITY SCRIPTS
|
|
*/
|
|
for (const child of childrenWenities) {
|
|
if (child.scripts) {
|
|
executeOnExtStoreTypeCollectedTriple(
|
|
(extstoretype) => this.transferCollectedFunctions(child.scripts, funcCollections, extstoretype)
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
let wenity = new WebTrinity();
|
|
/**
|
|
* DEAL WITH CHILDREN WENITY STYLE
|
|
*/
|
|
if (component._isCompel) {
|
|
executeOnExtStoreTypeCollectedTriple((est) => this.dealCollectedFuncs(funcCollections, est));
|
|
} else {
|
|
wenity.scripts = funcCollections;
|
|
wenity.stylings = styleCollection;
|
|
}
|
|
|
|
wenity.compext = component._element
|
|
|
|
for (const group of component._toRegister) {
|
|
Page.subscribeComponentToGroup(group, component._compName);
|
|
}
|
|
|
|
return wenity;
|
|
}
|
|
|
|
}
|
|
|