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,164 @@
|
|
|
1
|
+
import { ViewState } from './ViewState.js';
|
|
2
|
+
|
|
3
|
+
// Import Helpers
|
|
4
|
+
import EventHelper from './helpers/EventHelper.js';
|
|
5
|
+
import ReactiveHelper from './helpers/ReactiveHelper.js';
|
|
6
|
+
import BindingHelper from './helpers/BindingHelper.js';
|
|
7
|
+
import ResourceHelper from './helpers/ResourceHelper.js';
|
|
8
|
+
import RenderHelper from './helpers/RenderHelper.js';
|
|
9
|
+
import LifecycleHelper from './helpers/LifecycleHelper.js';
|
|
10
|
+
import ConfigHelper from './helpers/ConfigHelper.js';
|
|
11
|
+
import TemplateHelper from './helpers/TemplateHelper.js';
|
|
12
|
+
import { ViewHierarchyManager } from './managers/ViewHierarchyManager.js';
|
|
13
|
+
import { ChildrenRegistry } from './managers/ChildrenRegistry.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* ViewControllerOptimized (New Architecture)
|
|
17
|
+
* Fully stateless logic delegating to Static Helpers
|
|
18
|
+
*/
|
|
19
|
+
export class ViewControllerOptimized {
|
|
20
|
+
constructor(path, view, app) {
|
|
21
|
+
this.path = path;
|
|
22
|
+
this.view = view;
|
|
23
|
+
this.App = app;
|
|
24
|
+
|
|
25
|
+
// --- Core Properties ---
|
|
26
|
+
this.id = view.id || null;
|
|
27
|
+
this.states = new ViewState(this);
|
|
28
|
+
this.config = {};
|
|
29
|
+
this.data = {};
|
|
30
|
+
|
|
31
|
+
// --- State Management (Internal) ---
|
|
32
|
+
this.initializeInternalState();
|
|
33
|
+
|
|
34
|
+
// --- Legacy Manager Bridges (Optional: Keep only if strictly needed for Hierarchy/Children) ---
|
|
35
|
+
// Hierarchy and ChildrenRegistry are complex logic-heavy stateful managers.
|
|
36
|
+
// For now, we keep them as objects or migrate later.
|
|
37
|
+
this._hierarchyManager = new ViewHierarchyManager(this);
|
|
38
|
+
this._childrenRegistry = new ChildrenRegistry(this);
|
|
39
|
+
|
|
40
|
+
// --- Flags ---
|
|
41
|
+
this.isMounted = false;
|
|
42
|
+
this.isDestroyed = false;
|
|
43
|
+
this.isReady = false;
|
|
44
|
+
this.isRendered = false;
|
|
45
|
+
this.eventListenerStatus = false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
initializeInternalState() {
|
|
49
|
+
this._internal = {
|
|
50
|
+
events: {
|
|
51
|
+
unsubscribers: new Map()
|
|
52
|
+
},
|
|
53
|
+
reactive: {
|
|
54
|
+
components: new Map(),
|
|
55
|
+
config: [],
|
|
56
|
+
index: 0,
|
|
57
|
+
scanIndex: 0,
|
|
58
|
+
ids: [],
|
|
59
|
+
prerenderIDs: [],
|
|
60
|
+
renderIDs: [],
|
|
61
|
+
followingIDs: [],
|
|
62
|
+
followingRenderIDs: [],
|
|
63
|
+
followingPrerenderIDs: [],
|
|
64
|
+
parentWatch: null
|
|
65
|
+
},
|
|
66
|
+
binding: {
|
|
67
|
+
listeners: [],
|
|
68
|
+
isStarted: false,
|
|
69
|
+
elementFlags: new WeakMap(),
|
|
70
|
+
elementMap: new WeakMap(),
|
|
71
|
+
attrConfigs: [],
|
|
72
|
+
attrListeners: [],
|
|
73
|
+
attrIndex: 0,
|
|
74
|
+
classConfigs: [],
|
|
75
|
+
classListeners: [],
|
|
76
|
+
isClassReady: false
|
|
77
|
+
},
|
|
78
|
+
resources: {
|
|
79
|
+
insertedKeys: new Set()
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// --- Public API Bridges to Helpers ---
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Setup the view controller with configuration
|
|
88
|
+
* This is called by View.js after instantiation
|
|
89
|
+
*/
|
|
90
|
+
setup(path, config) {
|
|
91
|
+
if (this.isInitlized) {
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Set config and path
|
|
96
|
+
this.path = path;
|
|
97
|
+
this.config = config || {};
|
|
98
|
+
|
|
99
|
+
// Parse basic config properties
|
|
100
|
+
if (config) {
|
|
101
|
+
this.id = config.viewId || this.id;
|
|
102
|
+
this.data = config.data || {};
|
|
103
|
+
// ... map other flat config properties if needed ...
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Initialize Internal State via ConfigHelper
|
|
107
|
+
// This will define properties (props, methods, getters) on the controller itself
|
|
108
|
+
ConfigHelper.processDefinedProperties(this, config);
|
|
109
|
+
|
|
110
|
+
// Execute Initialization Lifecycle
|
|
111
|
+
this.initialize();
|
|
112
|
+
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
initialize() {
|
|
117
|
+
if (this.isInitlized) return;
|
|
118
|
+
this.isInitlized = true;
|
|
119
|
+
|
|
120
|
+
LifecycleHelper.callHook(this, 'beforeCreate');
|
|
121
|
+
|
|
122
|
+
// Commit initial data from constructor to state
|
|
123
|
+
// We need to implement commitConstructorData in ConfigHelper or here
|
|
124
|
+
// Assuming ConfigHelper handles it for now based on previous context
|
|
125
|
+
// ConfigHelper.commitConstructorData(this);
|
|
126
|
+
|
|
127
|
+
LifecycleHelper.callHook(this, 'created');
|
|
128
|
+
|
|
129
|
+
LifecycleHelper.callHook(this, 'beforeInit');
|
|
130
|
+
if (typeof this.init === 'function') {
|
|
131
|
+
this.init();
|
|
132
|
+
}
|
|
133
|
+
LifecycleHelper.callHook(this, 'init');
|
|
134
|
+
LifecycleHelper.callHook(this, 'afterInit');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
__reactive(id, keys, renderFn) {
|
|
138
|
+
return ReactiveHelper.renderOutputComponent(this, keys, renderFn);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ... replicate other necessary methods ...
|
|
142
|
+
|
|
143
|
+
mounted() {
|
|
144
|
+
LifecycleHelper.callHook(this, 'beforeMount');
|
|
145
|
+
// ... logic ...
|
|
146
|
+
EventHelper.startEventListener(this);
|
|
147
|
+
BindingHelper.startBindingEventListener(this);
|
|
148
|
+
// ... logic ...
|
|
149
|
+
this.isMounted = true;
|
|
150
|
+
LifecycleHelper.callHook(this, 'mounted');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
destroy() {
|
|
154
|
+
EventHelper.stopEventListener(this);
|
|
155
|
+
BindingHelper.destroy(this);
|
|
156
|
+
ReactiveHelper.destroy(this);
|
|
157
|
+
ResourceHelper.removeResources(this);
|
|
158
|
+
|
|
159
|
+
if (this._childrenRegistry) this._childrenRegistry.clear();
|
|
160
|
+
|
|
161
|
+
this._internal = null;
|
|
162
|
+
this.isDestroyed = true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View Identifier System
|
|
3
|
+
* Handles view identification and DOM mapping for server-rendered content
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export class ViewIdentifier {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.viewElements = new Map();
|
|
9
|
+
this.viewHierarchy = new Map();
|
|
10
|
+
this.currentView = null;
|
|
11
|
+
this.debugMode = false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Initialize view identification system
|
|
16
|
+
*/
|
|
17
|
+
init() {
|
|
18
|
+
this.scanViewElements();
|
|
19
|
+
this.buildViewHierarchy();
|
|
20
|
+
this.setupViewTracking();
|
|
21
|
+
|
|
22
|
+
if (this.debugMode) {
|
|
23
|
+
this.enableDebugMode();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Scan all elements with view identification attributes
|
|
29
|
+
*/
|
|
30
|
+
scanViewElements() {
|
|
31
|
+
const elements = document.querySelectorAll('[data-spa-view]');
|
|
32
|
+
|
|
33
|
+
elements.forEach(element => {
|
|
34
|
+
const viewInfo = this.extractViewInfo(element);
|
|
35
|
+
if (viewInfo) {
|
|
36
|
+
this.viewElements.set(viewInfo.id, {
|
|
37
|
+
element,
|
|
38
|
+
info: viewInfo,
|
|
39
|
+
children: [],
|
|
40
|
+
parent: null
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
console.log(`🔍 Found ${this.viewElements.size} view elements`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Extract view information from element
|
|
50
|
+
*/
|
|
51
|
+
extractViewInfo(element) {
|
|
52
|
+
const viewId = element.getAttribute('data-spa-view-id');
|
|
53
|
+
const viewName = element.getAttribute('data-spa-view-name');
|
|
54
|
+
const viewPath = element.getAttribute('data-spa-view-path');
|
|
55
|
+
const viewType = element.getAttribute('data-spa-view-type');
|
|
56
|
+
const viewScope = element.getAttribute('data-spa-view');
|
|
57
|
+
|
|
58
|
+
if (!viewId) return null;
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
id: viewId,
|
|
62
|
+
name: viewName || 'unknown',
|
|
63
|
+
path: viewPath || 'unknown',
|
|
64
|
+
type: viewType || 'view',
|
|
65
|
+
scope: viewScope || 'unknown',
|
|
66
|
+
element
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Build view hierarchy based on DOM structure
|
|
72
|
+
*/
|
|
73
|
+
buildViewHierarchy() {
|
|
74
|
+
this.viewElements.forEach((viewData, viewId) => {
|
|
75
|
+
const element = viewData.element;
|
|
76
|
+
|
|
77
|
+
// Find parent view
|
|
78
|
+
let parent = element.parentElement;
|
|
79
|
+
while (parent && parent !== document.body) {
|
|
80
|
+
const parentViewId = parent.getAttribute('data-spa-view-id');
|
|
81
|
+
if (parentViewId && this.viewElements.has(parentViewId)) {
|
|
82
|
+
viewData.parent = parentViewId;
|
|
83
|
+
this.viewElements.get(parentViewId).children.push(viewId);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
parent = parent.parentElement;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
console.log('🏗️ View hierarchy built');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Setup view tracking and event listeners
|
|
95
|
+
*/
|
|
96
|
+
setupViewTracking() {
|
|
97
|
+
// Track view changes
|
|
98
|
+
this.viewElements.forEach((viewData, viewId) => {
|
|
99
|
+
this.setupViewEventListeners(viewData);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Track DOM changes for dynamic content
|
|
103
|
+
this.setupMutationObserver();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Setup event listeners for a view
|
|
108
|
+
*/
|
|
109
|
+
setupViewEventListeners(viewData) {
|
|
110
|
+
const { element, info } = viewData;
|
|
111
|
+
|
|
112
|
+
// Add view lifecycle events
|
|
113
|
+
element.addEventListener('spa:view:enter', () => {
|
|
114
|
+
this.onViewEnter(info);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
element.addEventListener('spa:view:leave', () => {
|
|
118
|
+
this.onViewLeave(info);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Add click tracking for debugging
|
|
122
|
+
if (this.debugMode) {
|
|
123
|
+
element.addEventListener('click', (e) => {
|
|
124
|
+
console.log(`🖱️ Click on view: ${info.name} (${info.id})`, e.target);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Setup mutation observer for dynamic content
|
|
131
|
+
*/
|
|
132
|
+
setupMutationObserver() {
|
|
133
|
+
const observer = new MutationObserver((mutations) => {
|
|
134
|
+
mutations.forEach((mutation) => {
|
|
135
|
+
if (mutation.type === 'childList') {
|
|
136
|
+
mutation.addedNodes.forEach((node) => {
|
|
137
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
138
|
+
const viewId = node.getAttribute('data-spa-view-id');
|
|
139
|
+
if (viewId && !this.viewElements.has(viewId)) {
|
|
140
|
+
// New view element added
|
|
141
|
+
this.scanViewElements();
|
|
142
|
+
this.buildViewHierarchy();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
observer.observe(document.body, {
|
|
151
|
+
childList: true,
|
|
152
|
+
subtree: true
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Get view by ID
|
|
158
|
+
*/
|
|
159
|
+
getView(viewId) {
|
|
160
|
+
return this.viewElements.get(viewId);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get all views by type
|
|
165
|
+
*/
|
|
166
|
+
getViewsByType(type) {
|
|
167
|
+
const views = [];
|
|
168
|
+
this.viewElements.forEach((viewData, viewId) => {
|
|
169
|
+
if (viewData.info.type === type) {
|
|
170
|
+
views.push(viewData);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
return views;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Get current active view
|
|
178
|
+
*/
|
|
179
|
+
getCurrentView() {
|
|
180
|
+
return this.currentView;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Set current active view
|
|
185
|
+
*/
|
|
186
|
+
setCurrentView(viewId) {
|
|
187
|
+
const viewData = this.viewElements.get(viewId);
|
|
188
|
+
if (viewData) {
|
|
189
|
+
this.currentView = viewData;
|
|
190
|
+
this.emitViewChange(viewData);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Get view hierarchy for a specific view
|
|
196
|
+
*/
|
|
197
|
+
getViewHierarchy(viewId) {
|
|
198
|
+
const hierarchy = [];
|
|
199
|
+
let current = viewId;
|
|
200
|
+
|
|
201
|
+
while (current) {
|
|
202
|
+
const viewData = this.viewElements.get(current);
|
|
203
|
+
if (viewData) {
|
|
204
|
+
hierarchy.unshift(viewData);
|
|
205
|
+
current = viewData.parent;
|
|
206
|
+
} else {
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return hierarchy;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Find view containing a specific element
|
|
216
|
+
*/
|
|
217
|
+
findViewContainingElement(element) {
|
|
218
|
+
let current = element;
|
|
219
|
+
|
|
220
|
+
while (current && current !== document.body) {
|
|
221
|
+
const viewId = current.getAttribute('data-spa-view-id');
|
|
222
|
+
if (viewId && this.viewElements.has(viewId)) {
|
|
223
|
+
return this.viewElements.get(viewId);
|
|
224
|
+
}
|
|
225
|
+
current = current.parentElement;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* View lifecycle events
|
|
233
|
+
*/
|
|
234
|
+
onViewEnter(viewInfo) {
|
|
235
|
+
console.log(`🚀 View entered: ${viewInfo.name} (${viewInfo.id})`);
|
|
236
|
+
this.setCurrentView(viewInfo.id);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
onViewLeave(viewInfo) {
|
|
240
|
+
console.log(`👋 View left: ${viewInfo.name} (${viewInfo.id})`);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Emit view change event
|
|
245
|
+
*/
|
|
246
|
+
emitViewChange(viewData) {
|
|
247
|
+
const event = new CustomEvent('spa:view:changed', {
|
|
248
|
+
detail: {
|
|
249
|
+
view: viewData,
|
|
250
|
+
timestamp: Date.now()
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
document.dispatchEvent(event);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Enable debug mode
|
|
258
|
+
*/
|
|
259
|
+
enableDebugMode() {
|
|
260
|
+
this.debugMode = true;
|
|
261
|
+
document.body.classList.add('debug-view-boundaries');
|
|
262
|
+
|
|
263
|
+
// Add debug styles
|
|
264
|
+
const style = document.createElement('style');
|
|
265
|
+
style.textContent = `
|
|
266
|
+
.debug-view-boundaries [data-spa-view] {
|
|
267
|
+
border: 2px dashed #007cba !important;
|
|
268
|
+
margin: 2px !important;
|
|
269
|
+
position: relative !important;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.debug-view-boundaries [data-spa-view]::before {
|
|
273
|
+
content: attr(data-spa-view-name) " (" attr(data-spa-view-id) ")" !important;
|
|
274
|
+
position: absolute !important;
|
|
275
|
+
top: -20px !important;
|
|
276
|
+
left: 0 !important;
|
|
277
|
+
font-size: 10px !important;
|
|
278
|
+
color: white !important;
|
|
279
|
+
background: #007cba !important;
|
|
280
|
+
padding: 2px 6px !important;
|
|
281
|
+
border-radius: 3px !important;
|
|
282
|
+
opacity: 1 !important;
|
|
283
|
+
z-index: 1000 !important;
|
|
284
|
+
}
|
|
285
|
+
`;
|
|
286
|
+
document.head.appendChild(style);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Disable debug mode
|
|
291
|
+
*/
|
|
292
|
+
disableDebugMode() {
|
|
293
|
+
this.debugMode = false;
|
|
294
|
+
document.body.classList.remove('debug-view-boundaries');
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Get debug information
|
|
299
|
+
*/
|
|
300
|
+
getDebugInfo() {
|
|
301
|
+
return {
|
|
302
|
+
totalViews: this.viewElements.size,
|
|
303
|
+
currentView: this.currentView?.info,
|
|
304
|
+
viewTypes: this.getViewTypeStats(),
|
|
305
|
+
hierarchy: this.getViewHierarchyStats()
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Get view type statistics
|
|
311
|
+
*/
|
|
312
|
+
getViewTypeStats() {
|
|
313
|
+
const stats = {};
|
|
314
|
+
this.viewElements.forEach((viewData) => {
|
|
315
|
+
const type = viewData.info.type;
|
|
316
|
+
stats[type] = (stats[type] || 0) + 1;
|
|
317
|
+
});
|
|
318
|
+
return stats;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Get view hierarchy statistics
|
|
323
|
+
*/
|
|
324
|
+
getViewHierarchyStats() {
|
|
325
|
+
const stats = {
|
|
326
|
+
rootViews: 0,
|
|
327
|
+
nestedViews: 0,
|
|
328
|
+
maxDepth: 0
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
this.viewElements.forEach((viewData) => {
|
|
332
|
+
if (!viewData.parent) {
|
|
333
|
+
stats.rootViews++;
|
|
334
|
+
} else {
|
|
335
|
+
stats.nestedViews++;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const depth = this.getViewHierarchy(viewData.info.id).length;
|
|
339
|
+
stats.maxDepth = Math.max(stats.maxDepth, depth);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
return stats;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Export view data for debugging
|
|
347
|
+
*/
|
|
348
|
+
exportViewData() {
|
|
349
|
+
const data = {};
|
|
350
|
+
this.viewElements.forEach((viewData, viewId) => {
|
|
351
|
+
data[viewId] = {
|
|
352
|
+
info: viewData.info,
|
|
353
|
+
hasParent: !!viewData.parent,
|
|
354
|
+
childrenCount: viewData.children.length,
|
|
355
|
+
elementTag: viewData.element.tagName,
|
|
356
|
+
elementClasses: viewData.element.className
|
|
357
|
+
};
|
|
358
|
+
});
|
|
359
|
+
return data;
|
|
360
|
+
}
|
|
361
|
+
}
|