onelaraveljs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -0
- package/docs/integration_analysis.md +116 -0
- package/docs/onejs_analysis.md +108 -0
- package/docs/optimization_implementation_group2.md +458 -0
- package/docs/optimization_plan.md +130 -0
- package/index.js +16 -0
- package/package.json +13 -0
- package/src/app.js +61 -0
- package/src/core/API.js +72 -0
- package/src/core/ChildrenRegistry.js +410 -0
- package/src/core/DOMBatcher.js +207 -0
- package/src/core/ErrorBoundary.js +226 -0
- package/src/core/EventDelegator.js +416 -0
- package/src/core/Helper.js +817 -0
- package/src/core/LoopContext.js +97 -0
- package/src/core/OneDOM.js +246 -0
- package/src/core/OneMarkup.js +444 -0
- package/src/core/Router.js +996 -0
- package/src/core/SEOConfig.js +321 -0
- package/src/core/SectionEngine.js +75 -0
- package/src/core/TemplateEngine.js +83 -0
- package/src/core/View.js +273 -0
- package/src/core/ViewConfig.js +229 -0
- package/src/core/ViewController.js +1410 -0
- package/src/core/ViewControllerOptimized.js +164 -0
- package/src/core/ViewIdentifier.js +361 -0
- package/src/core/ViewLoader.js +272 -0
- package/src/core/ViewManager.js +1962 -0
- package/src/core/ViewState.js +761 -0
- package/src/core/ViewSystem.js +301 -0
- package/src/core/ViewTemplate.js +4 -0
- package/src/core/helpers/BindingHelper.js +239 -0
- package/src/core/helpers/ConfigHelper.js +37 -0
- package/src/core/helpers/EventHelper.js +172 -0
- package/src/core/helpers/LifecycleHelper.js +17 -0
- package/src/core/helpers/ReactiveHelper.js +169 -0
- package/src/core/helpers/RenderHelper.js +15 -0
- package/src/core/helpers/ResourceHelper.js +89 -0
- package/src/core/helpers/TemplateHelper.js +11 -0
- package/src/core/managers/BindingManager.js +671 -0
- package/src/core/managers/ConfigurationManager.js +136 -0
- package/src/core/managers/EventManager.js +309 -0
- package/src/core/managers/LifecycleManager.js +356 -0
- package/src/core/managers/ReactiveManager.js +334 -0
- package/src/core/managers/RenderEngine.js +292 -0
- package/src/core/managers/ResourceManager.js +441 -0
- package/src/core/managers/ViewHierarchyManager.js +258 -0
- package/src/core/managers/ViewTemplateManager.js +127 -0
- package/src/core/reactive/ReactiveComponent.js +592 -0
- package/src/core/services/EventService.js +418 -0
- package/src/core/services/HttpService.js +106 -0
- package/src/core/services/LoggerService.js +57 -0
- package/src/core/services/StateService.js +512 -0
- package/src/core/services/StorageService.js +856 -0
- package/src/core/services/StoreService.js +258 -0
- package/src/core/services/TemplateDetectorService.js +361 -0
- package/src/core/services/Test.js +18 -0
- package/src/helpers/devWarnings.js +205 -0
- package/src/helpers/performance.js +226 -0
- package/src/helpers/utils.js +287 -0
- package/src/init.js +343 -0
- package/src/plugins/auto-plugin.js +34 -0
- package/src/services/Test.js +18 -0
- package/src/types/index.js +193 -0
- package/src/utils/date-helper.js +51 -0
- package/src/utils/helpers.js +39 -0
- package/src/utils/validation.js +32 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RenderEngine - Manages view rendering and scanning
|
|
3
|
+
* Handles render, virtual render, prerender, and DOM scanning
|
|
4
|
+
*
|
|
5
|
+
* Extracted from ViewController.js to improve maintainability
|
|
6
|
+
* @author GitHub Copilot
|
|
7
|
+
* @date 2025-12-29
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import logger from '../services/LoggerService.js';
|
|
11
|
+
import OneMarkup from '../OneMarkup.js';
|
|
12
|
+
import { ATTR } from '../ViewConfig.js';
|
|
13
|
+
|
|
14
|
+
export class RenderEngine {
|
|
15
|
+
/**
|
|
16
|
+
* @param {ViewController} controller - Parent controller instance
|
|
17
|
+
*/
|
|
18
|
+
constructor(controller) {
|
|
19
|
+
this.controller = controller;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Render the view
|
|
24
|
+
* @returns {string|Object} Rendered content
|
|
25
|
+
*/
|
|
26
|
+
render() {
|
|
27
|
+
let renderFollowIDStart = this.controller._reactiveManager.followingIDs.length;
|
|
28
|
+
this.controller.commitConstructorData();
|
|
29
|
+
const result = this.controller.config.render.apply(this.controller, []);
|
|
30
|
+
this.controller.renderedContent = result;
|
|
31
|
+
let renderFollowIDEnd = this.controller._reactiveManager.followingIDs.length;
|
|
32
|
+
if (renderFollowIDEnd >= renderFollowIDStart) {
|
|
33
|
+
this.controller._reactiveManager.followingRenderIDs.push(...this.controller._reactiveManager.followingIDs.slice(renderFollowIDStart));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (typeof result === 'string' && result.trim() !== '' && this.controller.isHtmlString(result)) {
|
|
37
|
+
this.controller.renderedContent = this.controller.addXRefViewToRootElements(result);
|
|
38
|
+
}
|
|
39
|
+
if (this.controller.isFirstClientRendering) {
|
|
40
|
+
this.controller.isFirstClientRendering = false;
|
|
41
|
+
if (this.controller._templateManager.wrapperConfig.enable) {
|
|
42
|
+
return this.controller.startWrapper(this.controller._templateManager.wrapperConfig.tag, this.controller._templateManager.wrapperConfig.attributes || {}) + this.controller.renderedContent + this.controller.endWrapper(this.controller._templateManager.wrapperConfig.tag);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return this.controller.renderedContent;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Virtual render the view with data (Scan version)
|
|
50
|
+
* @returns {string|Object} Virtual rendered content
|
|
51
|
+
*/
|
|
52
|
+
virtualRender() {
|
|
53
|
+
this.controller.isScanning = true;
|
|
54
|
+
this.controller.isVirtualRendering = true;
|
|
55
|
+
let renderFollowIDStart = this.controller._reactiveManager.followingIDs.length;
|
|
56
|
+
this.controller.commitConstructorData();
|
|
57
|
+
let result = this.controller.config.render.apply(this.controller, []);
|
|
58
|
+
if (typeof result === 'string' && this.controller.isFirstClientRendering && this.controller._templateManager.wrapperConfig) {
|
|
59
|
+
result = this.controller.startWrapper(this.controller._templateManager.wrapperConfig.tag, this.controller._templateManager.wrapperConfig.attributes || {}) + result + this.controller.endWrapper(this.controller._templateManager.wrapperConfig.tag);
|
|
60
|
+
}
|
|
61
|
+
let renderFollowIDEnd = this.controller._reactiveManager.followingIDs.length;
|
|
62
|
+
if (renderFollowIDEnd >= renderFollowIDStart) {
|
|
63
|
+
this.controller._reactiveManager.followingRenderIDs.push(...this.controller._reactiveManager.followingIDs.slice(renderFollowIDStart));
|
|
64
|
+
}
|
|
65
|
+
this.controller.isVirtualRendering = false;
|
|
66
|
+
this.controller.isFirstClientRendering = false;
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Prerender the view with data
|
|
72
|
+
* @param {Object} _data - Additional data to merge
|
|
73
|
+
* @returns {string|Object} Prerendered content
|
|
74
|
+
*/
|
|
75
|
+
prerender(_data = {}) {
|
|
76
|
+
let renderFollowIDStart = this.controller._reactiveManager.followingIDs.length;
|
|
77
|
+
this.controller.commitConstructorData();
|
|
78
|
+
const result = this.controller.config.prerender.apply(this.controller, []);
|
|
79
|
+
let renderFollowIDEnd = this.controller._reactiveManager.followingIDs.length;
|
|
80
|
+
if (renderFollowIDEnd >= renderFollowIDStart) {
|
|
81
|
+
this.controller._reactiveManager.followingPrerenderIDs.push(...this.controller._reactiveManager.followingIDs.slice(renderFollowIDStart));
|
|
82
|
+
}
|
|
83
|
+
if (typeof result === 'string' && result.trim() !== '' && this.controller.isHtmlString(result)) {
|
|
84
|
+
return this.controller.addXRefViewToRootElements(result);
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Virtual prerender the view with data (Scan version)
|
|
91
|
+
* @param {Object} _data - Additional data to merge
|
|
92
|
+
* @returns {string|Object} Virtual prerendered content
|
|
93
|
+
*/
|
|
94
|
+
virtualPrerender(_data = {}) {
|
|
95
|
+
this.controller.isScanning = true;
|
|
96
|
+
this.controller.isVirtualRendering = true;
|
|
97
|
+
let renderFollowIDStart = this.controller._reactiveManager.followingIDs.length;
|
|
98
|
+
this.controller.commitConstructorData();
|
|
99
|
+
const result = this.controller.config.prerender.apply(this.controller, []);
|
|
100
|
+
let renderFollowIDEnd = this.controller._reactiveManager.followingIDs.length;
|
|
101
|
+
if (renderFollowIDEnd >= renderFollowIDStart) {
|
|
102
|
+
this.controller._reactiveManager.followingPrerenderIDs.push(...this.controller._reactiveManager.followingIDs.slice(renderFollowIDStart));
|
|
103
|
+
}
|
|
104
|
+
this.controller.isVirtualRendering = false;
|
|
105
|
+
this.controller.isScanning = false;
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
refresh(variableData = null) {
|
|
110
|
+
/**
|
|
111
|
+
* @type {ViewController}
|
|
112
|
+
*/
|
|
113
|
+
const ctrl = this.controller;
|
|
114
|
+
/**
|
|
115
|
+
* @type {ViewManager}
|
|
116
|
+
*/
|
|
117
|
+
const manager = ctrl.App.View;
|
|
118
|
+
if (ctrl.hasSuperView) {
|
|
119
|
+
const superView = ctrl.superView;
|
|
120
|
+
superView._lifecycleManager.unmounted();
|
|
121
|
+
ctrl.updateVariableData(variableData);
|
|
122
|
+
try {
|
|
123
|
+
const result = ctrl.render();
|
|
124
|
+
manager.emitChangedSections();
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error(error);
|
|
127
|
+
}
|
|
128
|
+
superView._lifecycleManager.mounted();
|
|
129
|
+
}
|
|
130
|
+
else if (ctrl.wrapperConfig.enable) {
|
|
131
|
+
ctrl._lifecycleManager.unmounted();
|
|
132
|
+
ctrl.updateVariableData(variableData);
|
|
133
|
+
try {
|
|
134
|
+
const result = ctrl.render();
|
|
135
|
+
if (ctrl.rootElement) {
|
|
136
|
+
OneDOM.replaceContent(ctrl.rootElement, result);
|
|
137
|
+
this.refElements = Array.from(ctrl.rootElement.children);
|
|
138
|
+
}
|
|
139
|
+
else if (ctrl.markup) {
|
|
140
|
+
ctrl.markup.replaceContent(result);
|
|
141
|
+
this.refElements = ctrl.markup.nodes;
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
console.error('No root element or markup found');
|
|
146
|
+
}
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.error(error);
|
|
149
|
+
}
|
|
150
|
+
ctrl._lifecycleManager.mounted();
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
console.error('No root element or markup found');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Scan view configuration and setup reactive components
|
|
159
|
+
* @param {Object} config - Scan configuration
|
|
160
|
+
*/
|
|
161
|
+
scan(config) {
|
|
162
|
+
if (this.controller.isScanned) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
this.controller.__scanData = config;
|
|
166
|
+
this.controller.isScanning = true;
|
|
167
|
+
const { viewId, data, attributes = [], events, outputComponents, children, parent } = config;
|
|
168
|
+
|
|
169
|
+
if (data && typeof data === 'object') {
|
|
170
|
+
this.controller.updateVariableData(data);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (typeof viewId !== 'string' || viewId === '') {
|
|
174
|
+
logger.warn('⚠️ RenderEngine.scan: Invalid viewId', viewId);
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Setup Output Components
|
|
179
|
+
if (outputComponents && outputComponents.length > 0) {
|
|
180
|
+
this._setupOutputComponents(outputComponents, viewId);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Setup Attribute Bindings
|
|
184
|
+
if (attributes && attributes.length > 0) {
|
|
185
|
+
this._setupAttributeBindings(attributes);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Store Children References
|
|
189
|
+
if (children && children.length > 0) {
|
|
190
|
+
this._storeChildrenReferences(children);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.controller.isScanned = true;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Find and store DOM elements for this view
|
|
198
|
+
* @param {string} viewId - View instance ID
|
|
199
|
+
*/
|
|
200
|
+
scanDOMElements(viewId) {
|
|
201
|
+
if (this.controller.isMarkupScanned) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
this.controller.isMarkupScanned = true;
|
|
205
|
+
|
|
206
|
+
if (this.controller.hasSuperView) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const wrpCfg = this.controller._templateManager.wrapperConfig;
|
|
210
|
+
|
|
211
|
+
if (wrpCfg.enable) {
|
|
212
|
+
if (wrpCfg.tag) {
|
|
213
|
+
// Custom wrapper tag
|
|
214
|
+
const rootElement = document.querySelector(
|
|
215
|
+
`${wrpCfg.tag}[data-wrap-view="${this.controller.path}"][${ATTR.KEYS.VIEW_WRAPPER}="${viewId}"]`
|
|
216
|
+
);
|
|
217
|
+
if (rootElement) {
|
|
218
|
+
this.controller.rootElement = rootElement;
|
|
219
|
+
const children = Array.from(rootElement.children);
|
|
220
|
+
this.controller.refElements = children;
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
// Use OneMarkup to find view boundary
|
|
224
|
+
const markup = OneMarkup.first('view', { name: this.controller.path, id: viewId });
|
|
225
|
+
if (markup) {
|
|
226
|
+
this.controller.markup = markup;
|
|
227
|
+
this.controller.refElements = markup.nodes && markup.nodes.length ? markup.nodes.filter(node => node.nodeType === Node.ELEMENT_NODE) : [];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
// Standard view wrapper
|
|
232
|
+
const rootElement = document.querySelector(`[data-view-wrapper="${viewId}"]`);
|
|
233
|
+
if (rootElement) {
|
|
234
|
+
this.controller.rootElement = rootElement;
|
|
235
|
+
const children = Array.from(rootElement.children);
|
|
236
|
+
this.controller.refElements = children;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (!this.controller.refElements || this.controller.refElements.length === 0) {
|
|
241
|
+
// logger.warn(`⚠️ RenderEngine.scanDOMElements: No elements found for ${this.controller.path} (${viewId})`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Setup output components for reactive state updates
|
|
247
|
+
* @private
|
|
248
|
+
* @param {Array} outputComponents - Output component configurations
|
|
249
|
+
* @param {string} viewId - View instance ID
|
|
250
|
+
*/
|
|
251
|
+
_setupOutputComponents(outputComponents, viewId) {
|
|
252
|
+
outputComponents.forEach(outputComponentConfig => {
|
|
253
|
+
const { id, stateKeys } = outputComponentConfig;
|
|
254
|
+
this.controller._reactiveManager.reactiveComponentConfig.push({
|
|
255
|
+
id,
|
|
256
|
+
stateKeys,
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Setup attribute bindings
|
|
263
|
+
* @private
|
|
264
|
+
* @param {Array} attributeBindings - Attribute binding configurations
|
|
265
|
+
*/
|
|
266
|
+
_setupAttributeBindings(attributeBindings) {
|
|
267
|
+
attributeBindings.forEach(binding => {
|
|
268
|
+
const { id, config } = binding;
|
|
269
|
+
this.controller._bindingManager.attributeConfigs.push({
|
|
270
|
+
id,
|
|
271
|
+
config,
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Store children view references
|
|
278
|
+
* @private
|
|
279
|
+
* @param {Array} children - Children configurations
|
|
280
|
+
*/
|
|
281
|
+
_storeChildrenReferences(children) {
|
|
282
|
+
this.controller.__storeChildrenReferences(children);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
get App() {
|
|
286
|
+
return this.controller.App;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
set App(value) {
|
|
290
|
+
devLog('RenderEngine.App is read-only.');
|
|
291
|
+
}
|
|
292
|
+
}
|