@mindexec/cli 0.2.303 → 0.2.305
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/package.json +1 -1
- package/wwwroot/_content/MindExecution.Shared/css/mind-map-overrides.css +8 -7
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +141 -1
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +63 -81
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +1 -1
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-nodes.js +8 -2
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-pipeline.js +4 -1
- package/wwwroot/_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js +2 -2
- package/wwwroot/index.html +15 -15
- package/wwwroot/service-worker-assets.js +9 -9
- package/wwwroot/service-worker.js +1 -1
package/package.json
CHANGED
|
@@ -86,11 +86,11 @@ body.mind-map-scroll-locked {
|
|
|
86
86
|
.map-node-note,
|
|
87
87
|
.map-node-memo,
|
|
88
88
|
.map-node-code {
|
|
89
|
-
-webkit-backface-visibility:
|
|
90
|
-
backface-visibility:
|
|
89
|
+
-webkit-backface-visibility: visible;
|
|
90
|
+
backface-visibility: visible;
|
|
91
91
|
/* 텍스트 렌더링 품질 */
|
|
92
|
-
-webkit-font-smoothing:
|
|
93
|
-
-moz-osx-font-smoothing:
|
|
92
|
+
-webkit-font-smoothing: auto;
|
|
93
|
+
-moz-osx-font-smoothing: auto;
|
|
94
94
|
/* 서브픽셀 정렬로 흐림 방지 */
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -104,7 +104,8 @@ body.mind-map-scroll-locked {
|
|
|
104
104
|
contain: layout style !important;
|
|
105
105
|
content-visibility: visible !important;
|
|
106
106
|
contain-intrinsic-size: auto !important;
|
|
107
|
-
transform:
|
|
107
|
+
transform: none !important;
|
|
108
|
+
zoom: var(--css3d-node-resolution-zoom, 1) !important;
|
|
108
109
|
will-change: auto !important;
|
|
109
110
|
-webkit-backface-visibility: visible !important;
|
|
110
111
|
backface-visibility: visible !important;
|
|
@@ -1437,8 +1438,8 @@ html.mindcanvas-platform-apple .css3d-resolution-wrapper.is-automation-relation-
|
|
|
1437
1438
|
box-sizing: border-box;
|
|
1438
1439
|
pointer-events: auto;
|
|
1439
1440
|
transform-origin: 0 0;
|
|
1440
|
-
-webkit-font-smoothing:
|
|
1441
|
-
-moz-osx-font-smoothing:
|
|
1441
|
+
-webkit-font-smoothing: auto;
|
|
1442
|
+
-moz-osx-font-smoothing: auto;
|
|
1442
1443
|
text-rendering: auto;
|
|
1443
1444
|
contain: layout style paint;
|
|
1444
1445
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
const DEBUG = false;
|
|
6
6
|
const FPS_DEBUG = false;
|
|
7
7
|
const FRAME_PERF_DEBUG = false;
|
|
8
|
-
const MINDMAP_CORE_BUILD_ID = '20260621-
|
|
8
|
+
const MINDMAP_CORE_BUILD_ID = '20260621-native-text-css3d-v768';
|
|
9
9
|
const CanvasPhase = Object.freeze({
|
|
10
10
|
Booting: 'booting',
|
|
11
11
|
BoardFileLoading: 'board-file-loading',
|
|
@@ -118,6 +118,14 @@
|
|
|
118
118
|
const CAMERA_MOTION_WEBGL_TRANSFORM_TRANSLATE_BUCKET_PX = 0.001;
|
|
119
119
|
const CAMERA_MOTION_WEBGL_TRANSFORM_SCALE_BUCKET = 0.000001;
|
|
120
120
|
const CSS3D_FLAT_CAMERA_MOTION_ENABLED = true;
|
|
121
|
+
const CSS3D_SETTLED_TEXT_FLAT_RENDER_ENABLED = true;
|
|
122
|
+
const CSS3D_SETTLED_TEXT_FLAT_SAFE_TYPES = new Set([
|
|
123
|
+
'text',
|
|
124
|
+
'note',
|
|
125
|
+
'memo',
|
|
126
|
+
'markdown',
|
|
127
|
+
'code'
|
|
128
|
+
]);
|
|
121
129
|
const CAMERA_STATIONARY_INTERACTION_FRAME_DELAY_MS = 48;
|
|
122
130
|
const CAMERA_ZOOM_END_DELAY_MS = 150;
|
|
123
131
|
const CAMERA_MOTION_GLOBAL_STYLE_CLASS_ENABLED = false;
|
|
@@ -673,11 +681,38 @@
|
|
|
673
681
|
return false;
|
|
674
682
|
}
|
|
675
683
|
|
|
684
|
+
const flatScene = canUseSettledTextFlatCss3dSceneRender(module, scene, camera, renderDebugFlags);
|
|
685
|
+
if (flatScene.ok === true && typeof renderer.renderFlat === 'function') {
|
|
686
|
+
syncCss3dViewportForSceneRender(module, renderer, camera);
|
|
687
|
+
const renderedFlat = renderer.renderFlat(scene, camera, {
|
|
688
|
+
translateBucketPx: CAMERA_MOTION_WEBGL_TRANSFORM_TRANSLATE_BUCKET_PX,
|
|
689
|
+
scaleBucket: CAMERA_MOTION_WEBGL_TRANSFORM_SCALE_BUCKET
|
|
690
|
+
}) === true;
|
|
691
|
+
if (renderedFlat === true) {
|
|
692
|
+
module._lastCss3dCameraMotionMode = 'flat-settled';
|
|
693
|
+
module._lastCss3dCameraMotionReason = reason;
|
|
694
|
+
module._lastCss3dSceneRenderInfo = {
|
|
695
|
+
mode: 'flat-settled',
|
|
696
|
+
reason,
|
|
697
|
+
visibleCount: flatScene.visibleCount,
|
|
698
|
+
unsafeCount: flatScene.unsafeCount
|
|
699
|
+
};
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
676
704
|
if (typeof renderer.render === 'function') {
|
|
677
705
|
syncCss3dViewportForSceneRender(module, renderer, camera);
|
|
678
706
|
renderer.render(scene, camera);
|
|
679
707
|
module._lastCss3dCameraMotionMode = 'matrix3d';
|
|
680
708
|
module._lastCss3dCameraMotionReason = reason;
|
|
709
|
+
module._lastCss3dSceneRenderInfo = {
|
|
710
|
+
mode: 'matrix3d',
|
|
711
|
+
reason,
|
|
712
|
+
flatSkipReason: flatScene.reason,
|
|
713
|
+
visibleCount: flatScene.visibleCount,
|
|
714
|
+
unsafeCount: flatScene.unsafeCount
|
|
715
|
+
};
|
|
681
716
|
return true;
|
|
682
717
|
}
|
|
683
718
|
|
|
@@ -816,6 +851,108 @@
|
|
|
816
851
|
Math.abs(Number(rotation.z || 0)) <= 1e-5;
|
|
817
852
|
}
|
|
818
853
|
|
|
854
|
+
function isCss3dEntryVisibleForFlatScene(entry) {
|
|
855
|
+
const cssObject = entry?.cssObject || null;
|
|
856
|
+
const element = cssObject?.element || null;
|
|
857
|
+
if (!cssObject || !element) {
|
|
858
|
+
return false;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
if (cssObject.visible !== true && entry?.currentType !== 'CSS') {
|
|
862
|
+
return false;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
const style = typeof globalThis.getComputedStyle === 'function'
|
|
866
|
+
? globalThis.getComputedStyle(element)
|
|
867
|
+
: null;
|
|
868
|
+
const rect = typeof element.getBoundingClientRect === 'function'
|
|
869
|
+
? element.getBoundingClientRect()
|
|
870
|
+
: null;
|
|
871
|
+
return style?.display !== 'none' &&
|
|
872
|
+
style?.visibility !== 'hidden' &&
|
|
873
|
+
Number(rect?.width || 0) > 0 &&
|
|
874
|
+
Number(rect?.height || 0) > 0;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
function isCss3dEntryUnsafeForSettledFlatScene(entry) {
|
|
878
|
+
const model = entry?.model || {};
|
|
879
|
+
const type = String(model.contentType ?? model.ContentType ?? '').trim().toLowerCase();
|
|
880
|
+
if (!CSS3D_SETTLED_TEXT_FLAT_SAFE_TYPES.has(type)) {
|
|
881
|
+
return true;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
if (type === 'image' ||
|
|
885
|
+
type === 'video' ||
|
|
886
|
+
type === 'embed' ||
|
|
887
|
+
type === 'csv-table' ||
|
|
888
|
+
type === 'templatelauncher') {
|
|
889
|
+
return true;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
const element = entry?.cssObject?.element || null;
|
|
893
|
+
if (!element) {
|
|
894
|
+
return true;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
const classList = element.classList;
|
|
898
|
+
if (classList?.contains?.('node-type-image') === true ||
|
|
899
|
+
classList?.contains?.('node-type-video') === true ||
|
|
900
|
+
classList?.contains?.('node-type-embed') === true ||
|
|
901
|
+
classList?.contains?.('node-type-csv-table') === true ||
|
|
902
|
+
classList?.contains?.('node-type-templatelauncher') === true) {
|
|
903
|
+
return true;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
return !!element.querySelector?.(
|
|
907
|
+
'iframe, video, canvas.mind-map-video-proxy, .map-node-template-card, .map-node-remote-fleet, .csv-table-scroll, [data-remote-fleet-resize-handle="true"]'
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
function canUseSettledTextFlatCss3dSceneRender(module, scene, camera, renderDebugFlags = null) {
|
|
912
|
+
const renderer = module?.cssRenderer || null;
|
|
913
|
+
if (CSS3D_SETTLED_TEXT_FLAT_RENDER_ENABLED !== true ||
|
|
914
|
+
!module ||
|
|
915
|
+
!scene ||
|
|
916
|
+
!renderer ||
|
|
917
|
+
typeof renderer.renderFlat !== 'function' ||
|
|
918
|
+
canUseFlatCss3dCameraMotion(module, renderer, camera, renderDebugFlags) !== true) {
|
|
919
|
+
return { ok: false, reason: 'not-eligible', visibleCount: 0, unsafeCount: 0 };
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
if (hasBusinessAutomationDraftOrTransformMotionWork(module) === true) {
|
|
923
|
+
return { ok: false, reason: 'automation-edge-active', visibleCount: 0, unsafeCount: 0 };
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
const entries = module.nodeObjectsById instanceof Map
|
|
927
|
+
? Array.from(module.nodeObjectsById.values())
|
|
928
|
+
: [];
|
|
929
|
+
let visibleCount = 0;
|
|
930
|
+
let unsafeCount = 0;
|
|
931
|
+
for (const entry of entries) {
|
|
932
|
+
if (isCss3dEntryVisibleForFlatScene(entry) !== true) {
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
visibleCount++;
|
|
937
|
+
if (isCss3dEntryUnsafeForSettledFlatScene(entry) === true) {
|
|
938
|
+
unsafeCount++;
|
|
939
|
+
if (unsafeCount > 0) {
|
|
940
|
+
break;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
if (visibleCount <= 0) {
|
|
946
|
+
return { ok: false, reason: 'no-visible-css3d', visibleCount, unsafeCount };
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
if (unsafeCount > 0) {
|
|
950
|
+
return { ok: false, reason: 'unsafe-live-css3d-surface', visibleCount, unsafeCount };
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
return { ok: true, reason: 'text-only-css3d', visibleCount, unsafeCount };
|
|
954
|
+
}
|
|
955
|
+
|
|
819
956
|
function syncBusinessAutomationEdgesForCameraNavigation(module, transformOnly = false, allowDraftRender = false) {
|
|
820
957
|
transformOnly = transformOnly === true;
|
|
821
958
|
allowDraftRender = allowDraftRender === true;
|
|
@@ -2480,6 +2617,9 @@
|
|
|
2480
2617
|
overlayContentChanged: moduleInstance._overlayDebugContentChanged === true,
|
|
2481
2618
|
overlayForceRefresh: moduleInstance._overlayDebugForceRefresh === true,
|
|
2482
2619
|
cameraMotionFastPathStatus: moduleInstance._cameraMotionFastPathStatus || null,
|
|
2620
|
+
lastCss3dCameraMotionMode: String(moduleInstance._lastCss3dCameraMotionMode || ''),
|
|
2621
|
+
lastCss3dCameraMotionReason: String(moduleInstance._lastCss3dCameraMotionReason || ''),
|
|
2622
|
+
lastCss3dSceneRenderInfo: moduleInstance._lastCss3dSceneRenderInfo || null,
|
|
2483
2623
|
metricsSnapshotMs: Number(metricsSnapshotMs.toFixed(2)),
|
|
2484
2624
|
metricsSnapshotCached: false,
|
|
2485
2625
|
metricsSnapshotAgeMs: 0,
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
const CSS_IMAGE_PROMOTION_BUDGET_MS = 4;
|
|
16
16
|
const CSS_IMAGE_BLOB_CACHE_LIMIT = 160;
|
|
17
17
|
const CSS_IMAGE_DISPLAY_MAX_CONCURRENCY = 8;
|
|
18
|
-
const CSS3D_TEXT_NODE_RESOLUTION_SCALE =
|
|
18
|
+
const CSS3D_TEXT_NODE_RESOLUTION_SCALE = 1.0;
|
|
19
19
|
const CSS3D_MEDIA_NODE_RESOLUTION_SCALE = 1.0;
|
|
20
20
|
const LOOPBACK_ASSET_URL_REGEX = /^http:\/\/(?:127(?:\.\d{1,3}){3}|localhost|\[::1\])(?::\d+)?\/assets\//i;
|
|
21
21
|
let _cssImagePreviewHoldUntil = 0;
|
|
@@ -68,6 +68,33 @@
|
|
|
68
68
|
return CSS3D_TEXT_NODE_RESOLUTION_SCALE;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
function getCss3dResolutionZoomValue(resolutionScale) {
|
|
72
|
+
const scale = Math.max(1, Number(resolutionScale || 1));
|
|
73
|
+
return Number.isFinite(scale) ? String(scale) : '1';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function applyCss3dResolutionLayout(element, worldWidth, worldHeight, resolutionScale, options = {}) {
|
|
77
|
+
if (!element?.style) return;
|
|
78
|
+
|
|
79
|
+
const width = Math.max(1, Math.round(Number(worldWidth || 1)));
|
|
80
|
+
const height = Math.max(1, Math.round(Number(worldHeight || 1)));
|
|
81
|
+
const zoom = getCss3dResolutionZoomValue(resolutionScale);
|
|
82
|
+
element.style.width = `${width}px`;
|
|
83
|
+
element.style.height = `${height}px`;
|
|
84
|
+
element.style.minWidth = `${width}px`;
|
|
85
|
+
element.style.minHeight = `${height}px`;
|
|
86
|
+
element.style.maxWidth = `${width}px`;
|
|
87
|
+
element.style.maxHeight = `${height}px`;
|
|
88
|
+
element.style.transform = 'none';
|
|
89
|
+
element.style.transformOrigin = '0 0';
|
|
90
|
+
element.style.removeProperty('--css3d-node-resolution-transform');
|
|
91
|
+
element.style.setProperty('--css3d-node-resolution-zoom', zoom);
|
|
92
|
+
element.style.setProperty('zoom', zoom);
|
|
93
|
+
if (options.resetLayoutTransform === true) {
|
|
94
|
+
element.style.webkitTransform = 'none';
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
71
98
|
function detectCsvDelimiter(csvText) {
|
|
72
99
|
const text = String(csvText || '');
|
|
73
100
|
const candidates = [',', '\t', ';', '|'];
|
|
@@ -341,8 +368,8 @@
|
|
|
341
368
|
line-height: var(--mind-map-editable-line-height);
|
|
342
369
|
font-weight: 400;
|
|
343
370
|
letter-spacing: normal;
|
|
344
|
-
-webkit-font-smoothing:
|
|
345
|
-
-moz-osx-font-smoothing:
|
|
371
|
+
-webkit-font-smoothing: auto;
|
|
372
|
+
-moz-osx-font-smoothing: auto;
|
|
346
373
|
text-rendering: auto;
|
|
347
374
|
}
|
|
348
375
|
.markdown-body h1 { font-size: 1.8em; font-weight: bold; margin-top: 1em; margin-bottom: 0.5em; border-bottom: 1px solid #eaecef; padding-bottom: 0.3em; }
|
|
@@ -717,11 +744,11 @@
|
|
|
717
744
|
.css3d-dynamic-node,
|
|
718
745
|
[id^="css3d-node-"],
|
|
719
746
|
.map-node {
|
|
720
|
-
-webkit-font-smoothing:
|
|
721
|
-
-moz-osx-font-smoothing:
|
|
747
|
+
-webkit-font-smoothing: auto !important;
|
|
748
|
+
-moz-osx-font-smoothing: auto !important;
|
|
722
749
|
text-rendering: auto !important;
|
|
723
|
-
backface-visibility:
|
|
724
|
-
-webkit-backface-visibility:
|
|
750
|
+
backface-visibility: visible !important;
|
|
751
|
+
-webkit-backface-visibility: visible !important;
|
|
725
752
|
transition: none !important;
|
|
726
753
|
-webkit-transition: none !important;
|
|
727
754
|
will-change: auto !important;
|
|
@@ -1034,11 +1061,11 @@
|
|
|
1034
1061
|
pointer-events: none;
|
|
1035
1062
|
overflow: visible;
|
|
1036
1063
|
transform-origin: 0 0;
|
|
1037
|
-
-webkit-font-smoothing:
|
|
1038
|
-
-moz-osx-font-smoothing:
|
|
1064
|
+
-webkit-font-smoothing: auto;
|
|
1065
|
+
-moz-osx-font-smoothing: auto;
|
|
1039
1066
|
text-rendering: auto;
|
|
1040
|
-
backface-visibility:
|
|
1041
|
-
-webkit-backface-visibility:
|
|
1067
|
+
backface-visibility: visible;
|
|
1068
|
+
-webkit-backface-visibility: visible;
|
|
1042
1069
|
}
|
|
1043
1070
|
|
|
1044
1071
|
.mind-map-text-overlay.mind-map-text-overlay-selectable {
|
|
@@ -1093,11 +1120,11 @@
|
|
|
1093
1120
|
pointer-events: auto;
|
|
1094
1121
|
overflow: visible;
|
|
1095
1122
|
transform-origin: 0 0;
|
|
1096
|
-
-webkit-font-smoothing:
|
|
1097
|
-
-moz-osx-font-smoothing:
|
|
1123
|
+
-webkit-font-smoothing: auto;
|
|
1124
|
+
-moz-osx-font-smoothing: auto;
|
|
1098
1125
|
text-rendering: auto;
|
|
1099
|
-
backface-visibility:
|
|
1100
|
-
-webkit-backface-visibility:
|
|
1126
|
+
backface-visibility: visible;
|
|
1127
|
+
-webkit-backface-visibility: visible;
|
|
1101
1128
|
}
|
|
1102
1129
|
|
|
1103
1130
|
.mind-map-edit-overlay-card {
|
|
@@ -1824,7 +1851,7 @@
|
|
|
1824
1851
|
|| wrapper.classList?.contains?.('node-type-csv-table')
|
|
1825
1852
|
);
|
|
1826
1853
|
|
|
1827
|
-
const resolutionScale = Math.max(1, Number(cssObject?.userData?.resolutionScale ||
|
|
1854
|
+
const resolutionScale = Math.max(1, Number(cssObject?.userData?.resolutionScale || 1));
|
|
1828
1855
|
const worldWidth = Math.max(1, Math.round(Number(width || 1)));
|
|
1829
1856
|
const worldHeight = Math.max(1, Math.round(Number(height || 1)));
|
|
1830
1857
|
const scaledWidth = worldWidth * resolutionScale;
|
|
@@ -1856,14 +1883,9 @@
|
|
|
1856
1883
|
|
|
1857
1884
|
const inner = wrapper.firstElementChild;
|
|
1858
1885
|
if (inner?.style) {
|
|
1859
|
-
inner
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
inner.style.minHeight = `${worldHeight}px`;
|
|
1863
|
-
inner.style.maxWidth = `${worldWidth}px`;
|
|
1864
|
-
inner.style.maxHeight = `${worldHeight}px`;
|
|
1865
|
-
inner.style.transform = `scale(${resolutionScale})`;
|
|
1866
|
-
inner.style.transformOrigin = '0 0';
|
|
1886
|
+
applyCss3dResolutionLayout(inner, worldWidth, worldHeight, resolutionScale, {
|
|
1887
|
+
resetLayoutTransform: true
|
|
1888
|
+
});
|
|
1867
1889
|
inner.style.overflow = hasContextSourcePins ? 'visible' : 'hidden';
|
|
1868
1890
|
if (hasContextSourcePins) {
|
|
1869
1891
|
inner.style.contain = 'layout style';
|
|
@@ -2165,7 +2187,7 @@
|
|
|
2165
2187
|
}
|
|
2166
2188
|
|
|
2167
2189
|
function resolveCss3dMediaFrameSize(nodeModel, cssObject, options = {}) {
|
|
2168
|
-
const resolutionScale = Math.max(1, Number(cssObject?.userData?.resolutionScale ||
|
|
2190
|
+
const resolutionScale = Math.max(1, Number(cssObject?.userData?.resolutionScale || 1));
|
|
2169
2191
|
const wrapper = cssObject?.element || null;
|
|
2170
2192
|
const inner = wrapper?.firstElementChild || null;
|
|
2171
2193
|
const nodeId = getNodeId(nodeModel);
|
|
@@ -5735,7 +5757,7 @@
|
|
|
5735
5757
|
caret-color: #1f2937;
|
|
5736
5758
|
box-sizing: border-box;
|
|
5737
5759
|
overflow-y: auto;
|
|
5738
|
-
-webkit-font-smoothing:
|
|
5760
|
+
-webkit-font-smoothing: auto;
|
|
5739
5761
|
text-rendering: auto;
|
|
5740
5762
|
white-space: pre-wrap;
|
|
5741
5763
|
overflow-wrap: break-word;
|
|
@@ -20124,7 +20146,7 @@
|
|
|
20124
20146
|
overflow-y: auto;
|
|
20125
20147
|
white-space: pre-wrap;
|
|
20126
20148
|
overflow-wrap: break-word;
|
|
20127
|
-
-webkit-font-smoothing:
|
|
20149
|
+
-webkit-font-smoothing: auto;
|
|
20128
20150
|
text-rendering: auto;
|
|
20129
20151
|
`;
|
|
20130
20152
|
|
|
@@ -22892,12 +22914,9 @@
|
|
|
22892
22914
|
|
|
22893
22915
|
// ▼▼▼ [Clarity] Scale factor for high-resolution rendering ▼▼▼
|
|
22894
22916
|
const resolutionScale = getCss3dNodeResolutionScale(contentTypeLower);
|
|
22895
|
-
clonedElement
|
|
22896
|
-
|
|
22897
|
-
|
|
22898
|
-
clonedElement.style.minHeight = `${height}px`;
|
|
22899
|
-
clonedElement.style.maxWidth = `${width}px`;
|
|
22900
|
-
clonedElement.style.maxHeight = `${height}px`;
|
|
22917
|
+
applyCss3dResolutionLayout(clonedElement, width, height, resolutionScale, {
|
|
22918
|
+
resetLayoutTransform: true
|
|
22919
|
+
});
|
|
22901
22920
|
clonedElement.style.borderRadius = '0px';
|
|
22902
22921
|
|
|
22903
22922
|
// ▼▼▼ [Changed] Remove offset to match WebGL positioning (top-left origin) ▼▼▼
|
|
@@ -22909,17 +22928,13 @@
|
|
|
22909
22928
|
clonedElement.style.top = '0px';
|
|
22910
22929
|
// ▲▲▲ [Changed] ▲▲▲
|
|
22911
22930
|
|
|
22912
|
-
const innerResolutionTransform = resolutionScale === 1 ? 'none' : `scale(${resolutionScale})`;
|
|
22913
|
-
clonedElement.style.transform = innerResolutionTransform;
|
|
22914
|
-
clonedElement.style.setProperty('--css3d-node-resolution-transform', innerResolutionTransform);
|
|
22915
|
-
clonedElement.style.transformOrigin = '0 0'; // Scale from top-left
|
|
22916
22931
|
clonedElement.style.transition = 'none';
|
|
22917
22932
|
clonedElement.style.webkitTransition = 'none';
|
|
22918
22933
|
|
|
22919
22934
|
// ▼▼▼ [Perf] GPU acceleration for smooth zoom/pan ▼▼▼
|
|
22920
22935
|
// 초기에는 꺼둠 (auto). 카메라 이동 시 mind-map-core.js가 setWillChange(true) 호출
|
|
22921
22936
|
clonedElement.style.willChange = 'auto'; // 'transform';
|
|
22922
|
-
clonedElement.style.backfaceVisibility =
|
|
22937
|
+
clonedElement.style.backfaceVisibility = 'visible';
|
|
22923
22938
|
// ▲▲▲ [Perf] ▲▲▲
|
|
22924
22939
|
|
|
22925
22940
|
const wrapper = document.createElement('div');
|
|
@@ -22951,7 +22966,7 @@
|
|
|
22951
22966
|
|
|
22952
22967
|
// ▼▼▼ [Perf] GPU acceleration for smooth zoom/pan ▼▼▼
|
|
22953
22968
|
wrapper.style.willChange = 'auto'; // 'transform';
|
|
22954
|
-
wrapper.style.backfaceVisibility =
|
|
22969
|
+
wrapper.style.backfaceVisibility = 'visible';
|
|
22955
22970
|
wrapper.style.transformStyle = isMediaNode ? 'flat' : '';
|
|
22956
22971
|
// ▲▲▲ [Perf] ▲▲▲
|
|
22957
22972
|
|
|
@@ -23140,32 +23155,9 @@
|
|
|
23140
23155
|
}
|
|
23141
23156
|
const inner = el.firstElementChild;
|
|
23142
23157
|
if (inner) {
|
|
23143
|
-
|
|
23144
|
-
|
|
23145
|
-
|
|
23146
|
-
}
|
|
23147
|
-
if (inner.style.height !== `${worldHeight}px`) {
|
|
23148
|
-
inner.style.height = `${worldHeight}px`;
|
|
23149
|
-
}
|
|
23150
|
-
if (inner.style.minWidth !== `${worldWidth}px`) {
|
|
23151
|
-
inner.style.minWidth = `${worldWidth}px`;
|
|
23152
|
-
}
|
|
23153
|
-
if (inner.style.minHeight !== `${worldHeight}px`) {
|
|
23154
|
-
inner.style.minHeight = `${worldHeight}px`;
|
|
23155
|
-
}
|
|
23156
|
-
if (inner.style.maxWidth !== `${worldWidth}px`) {
|
|
23157
|
-
inner.style.maxWidth = `${worldWidth}px`;
|
|
23158
|
-
}
|
|
23159
|
-
if (inner.style.maxHeight !== `${worldHeight}px`) {
|
|
23160
|
-
inner.style.maxHeight = `${worldHeight}px`;
|
|
23161
|
-
}
|
|
23162
|
-
if (inner.style.transform !== innerResolutionTransform) {
|
|
23163
|
-
inner.style.transform = innerResolutionTransform;
|
|
23164
|
-
inner.style.transformOrigin = '0 0';
|
|
23165
|
-
}
|
|
23166
|
-
if (inner.style.getPropertyValue('--css3d-node-resolution-transform') !== innerResolutionTransform) {
|
|
23167
|
-
inner.style.setProperty('--css3d-node-resolution-transform', innerResolutionTransform);
|
|
23168
|
-
}
|
|
23158
|
+
applyCss3dResolutionLayout(inner, worldWidth, worldHeight, resolutionScale, {
|
|
23159
|
+
resetLayoutTransform: true
|
|
23160
|
+
});
|
|
23169
23161
|
}
|
|
23170
23162
|
}
|
|
23171
23163
|
|
|
@@ -23241,14 +23233,9 @@
|
|
|
23241
23233
|
card.dataset.nodeId = nodeId;
|
|
23242
23234
|
card.dataset.semanticType = getNodeSemanticType(nodeModel);
|
|
23243
23235
|
card.classList.toggle('map-node-remote-device', isRemoteFleetDeviceNode(nodeModel));
|
|
23244
|
-
card
|
|
23245
|
-
|
|
23246
|
-
|
|
23247
|
-
card.style.minHeight = `${worldHeight}px`;
|
|
23248
|
-
card.style.maxWidth = `${worldWidth}px`;
|
|
23249
|
-
card.style.maxHeight = `${worldHeight}px`;
|
|
23250
|
-
card.style.transform = `scale(${resolutionScale})`;
|
|
23251
|
-
card.style.transformOrigin = '0 0';
|
|
23236
|
+
applyCss3dResolutionLayout(card, worldWidth, worldHeight, resolutionScale, {
|
|
23237
|
+
resetLayoutTransform: true
|
|
23238
|
+
});
|
|
23252
23239
|
ensureRemoteFleetResizeHandles(card, nodeModel);
|
|
23253
23240
|
|
|
23254
23241
|
const titleEl = card.querySelector('.template-card__title');
|
|
@@ -23281,14 +23268,9 @@
|
|
|
23281
23268
|
card.style.position = 'absolute';
|
|
23282
23269
|
card.style.left = '0px';
|
|
23283
23270
|
card.style.top = '0px';
|
|
23284
|
-
card
|
|
23285
|
-
|
|
23286
|
-
|
|
23287
|
-
card.style.minHeight = `${worldHeight}px`;
|
|
23288
|
-
card.style.maxWidth = `${worldWidth}px`;
|
|
23289
|
-
card.style.maxHeight = `${worldHeight}px`;
|
|
23290
|
-
card.style.transform = `scale(${resolutionScale})`;
|
|
23291
|
-
card.style.transformOrigin = '0 0';
|
|
23271
|
+
applyCss3dResolutionLayout(card, worldWidth, worldHeight, resolutionScale, {
|
|
23272
|
+
resetLayoutTransform: true
|
|
23273
|
+
});
|
|
23292
23274
|
card.style.transition = 'none';
|
|
23293
23275
|
card.style.webkitTransition = 'none';
|
|
23294
23276
|
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
// ▲▲▲ [Usage] ▲▲▲
|
|
52
52
|
|
|
53
53
|
// Procedural line rendering settings
|
|
54
|
-
const LOD_RENDERER_BUILD_ID = '20260621-
|
|
54
|
+
const LOD_RENDERER_BUILD_ID = '20260621-native-text-css3d-v768';
|
|
55
55
|
const DirtyKind = Object.freeze({
|
|
56
56
|
ResidentFullRebuild: 'resident-full-rebuild',
|
|
57
57
|
ResidentPatch: 'resident-patch',
|
|
@@ -1494,8 +1494,11 @@
|
|
|
1494
1494
|
inner.style.minHeight = `${height}px`;
|
|
1495
1495
|
inner.style.maxWidth = `${width}px`;
|
|
1496
1496
|
inner.style.maxHeight = `${height}px`;
|
|
1497
|
-
inner.style.transform =
|
|
1497
|
+
inner.style.transform = 'none';
|
|
1498
1498
|
inner.style.transformOrigin = '0 0';
|
|
1499
|
+
inner.style.removeProperty('--css3d-node-resolution-transform');
|
|
1500
|
+
inner.style.setProperty('--css3d-node-resolution-zoom', String(Math.max(1, Number(resolutionScale || 1))));
|
|
1501
|
+
inner.style.setProperty('zoom', String(Math.max(1, Number(resolutionScale || 1))));
|
|
1499
1502
|
inner.style.overflow = 'hidden';
|
|
1500
1503
|
}
|
|
1501
1504
|
if (module && nodeId) {
|
|
@@ -4012,8 +4015,11 @@
|
|
|
4012
4015
|
if (innerContent) {
|
|
4013
4016
|
innerContent.style.width = `${modelWidth}px`;
|
|
4014
4017
|
innerContent.style.height = `${modelHeight}px`;
|
|
4015
|
-
innerContent.style.transform =
|
|
4018
|
+
innerContent.style.transform = 'none';
|
|
4016
4019
|
innerContent.style.transformOrigin = '0 0';
|
|
4020
|
+
innerContent.style.removeProperty('--css3d-node-resolution-transform');
|
|
4021
|
+
innerContent.style.setProperty('--css3d-node-resolution-zoom', String(Math.max(1, Number(resolutionScale || 1))));
|
|
4022
|
+
innerContent.style.setProperty('zoom', String(Math.max(1, Number(resolutionScale || 1))));
|
|
4017
4023
|
}
|
|
4018
4024
|
|
|
4019
4025
|
// Update textarea size as well
|
|
@@ -587,8 +587,11 @@
|
|
|
587
587
|
inner.style.minHeight = h + 'px';
|
|
588
588
|
inner.style.maxWidth = w + 'px';
|
|
589
589
|
inner.style.maxHeight = h + 'px';
|
|
590
|
-
inner.style.transform =
|
|
590
|
+
inner.style.transform = 'none';
|
|
591
591
|
inner.style.transformOrigin = '0 0';
|
|
592
|
+
inner.style.removeProperty('--css3d-node-resolution-transform');
|
|
593
|
+
inner.style.setProperty('--css3d-node-resolution-zoom', String(Math.max(1, Number(resolutionScale || 1))));
|
|
594
|
+
inner.style.setProperty('zoom', String(Math.max(1, Number(resolutionScale || 1))));
|
|
592
595
|
}
|
|
593
596
|
const textarea = wrapper.querySelector('textarea');
|
|
594
597
|
if (textarea) {
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
|
|
33
33
|
function CSS3DRenderer(){
|
|
34
34
|
var _width, _height; var _widthHalf, _heightHalf; var cache = { camera:{ fov:0, style:'', mode:'matrix3d' }, objects: new WeakMap() };
|
|
35
|
-
var domElement = document.createElement('div'); domElement.style.overflow = 'hidden'; domElement.style.contain = 'layout style'; domElement.style.willChange = 'transform'; domElement.style.webkitTransition = domElement.style.transition = 'none'; domElement.style.webkitBackfaceVisibility = domElement.style.backfaceVisibility = '
|
|
36
|
-
var cameraElement = document.createElement('div'); cameraElement.style.webkitTransformStyle = cameraElement.style.transformStyle = 'preserve-3d'; cameraElement.style.pointerEvents = 'none'; cameraElement.style.webkitTransformOrigin = cameraElement.style.transformOrigin = '0 0'; cameraElement.style.contain = 'layout style'; cameraElement.style.willChange = 'transform'; cameraElement.style.webkitTransition = cameraElement.style.transition = 'none'; cameraElement.style.webkitBackfaceVisibility = cameraElement.style.backfaceVisibility = '
|
|
35
|
+
var domElement = document.createElement('div'); domElement.style.overflow = 'hidden'; domElement.style.contain = 'layout style'; domElement.style.willChange = 'transform'; domElement.style.webkitTransition = domElement.style.transition = 'none'; domElement.style.webkitBackfaceVisibility = domElement.style.backfaceVisibility = 'visible'; this.domElement = domElement;
|
|
36
|
+
var cameraElement = document.createElement('div'); cameraElement.style.webkitTransformStyle = cameraElement.style.transformStyle = 'preserve-3d'; cameraElement.style.pointerEvents = 'none'; cameraElement.style.webkitTransformOrigin = cameraElement.style.transformOrigin = '0 0'; cameraElement.style.contain = 'layout style'; cameraElement.style.willChange = 'transform'; cameraElement.style.webkitTransition = cameraElement.style.transition = 'none'; cameraElement.style.webkitBackfaceVisibility = cameraElement.style.backfaceVisibility = 'visible'; domElement.appendChild(cameraElement);
|
|
37
37
|
|
|
38
38
|
this.getSize = function(){ return { width:_width, height:_height }; };
|
|
39
39
|
this.getCameraElement = function(){ return cameraElement; };
|
package/wwwroot/index.html
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
|
|
4
4
|
<head>
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
<title>MindExec | Business Execution OS for solo builders</title>
|
|
8
8
|
<meta name="description" content="MindExec is an AI business execution OS for solo builders who want to turn notes, research, assets, and repeatable execution Skills into revenue-producing work." />
|
|
9
9
|
<base href="/" />
|
|
10
|
-
<link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260621-
|
|
11
|
-
<link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260621-
|
|
12
|
-
<!--
|
|
10
|
+
<link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260621-native-text-css3d-v768" />
|
|
11
|
+
<link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260621-native-text-css3d-v768" />
|
|
12
|
+
<!-- ??좎뜦堉??Font Awesome (local) ??좎뜦堉??-->
|
|
13
13
|
<link rel="stylesheet" href="_content/MindExecution.Shared/lib/font-awesome/css/all.min.css" />
|
|
14
|
-
<!--
|
|
14
|
+
<!-- ??좎뜦堉??-->
|
|
15
15
|
<style>
|
|
16
16
|
#app {
|
|
17
17
|
min-height: 100vh;
|
|
@@ -180,7 +180,7 @@
|
|
|
180
180
|
function adjustTextareaHeight(element) {
|
|
181
181
|
if (!element) return;
|
|
182
182
|
|
|
183
|
-
//
|
|
183
|
+
// ??좎뜦堉??[Change] Add jitter-prevention logic ??좎뜦堉??
|
|
184
184
|
// Compare the previous text length. When content grows, skip the 'auto' reset.
|
|
185
185
|
// Only reset to 'auto' when shrinking (during deletion).
|
|
186
186
|
const currentLength = element.value.length;
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
element.dataset.prevLength = currentLength; // store current length
|
|
194
|
-
//
|
|
194
|
+
// ??좎뜦堉??[Change] ??좎뜦堉??
|
|
195
195
|
|
|
196
196
|
const computedStyles = window.getComputedStyle(element);
|
|
197
197
|
const lineHeight = parseFloat(computedStyles.lineHeight || '24') || 24;
|
|
@@ -284,11 +284,11 @@
|
|
|
284
284
|
// Prevent default page-level DnD behavior
|
|
285
285
|
document.addEventListener('dragover', (e) => {
|
|
286
286
|
e.preventDefault();
|
|
287
|
-
//
|
|
287
|
+
// ??좎뜦堉??[Change] Remove/avoid stopPropagation (do not disrupt event flow) ??좎뜦堉??
|
|
288
288
|
// e.stopPropagation();
|
|
289
|
-
//
|
|
289
|
+
// ??좎뜦堉??[Change] ??좎뜦堉??
|
|
290
290
|
|
|
291
|
-
//
|
|
291
|
+
// ??좎뜦堉??[Change] Default is 'none', but only apply when not handled by children ??좎뜦堉??
|
|
292
292
|
// (If MindMapDnD handles it, this code won't run or will be ignored)
|
|
293
293
|
// e.dataTransfer.dropEffect = 'none';
|
|
294
294
|
}, false);
|
|
@@ -428,7 +428,7 @@
|
|
|
428
428
|
window.__matchesMarketingToolHost(host, location.host || '')
|
|
429
429
|
);
|
|
430
430
|
</script>
|
|
431
|
-
<!--
|
|
431
|
+
<!-- ??좎뜦堉??[Upgrade] Three.js r168 via ESM ??좎뜦堉??-->
|
|
432
432
|
<script type="importmap">
|
|
433
433
|
{
|
|
434
434
|
"imports": {
|
|
@@ -579,7 +579,7 @@
|
|
|
579
579
|
}
|
|
580
580
|
|
|
581
581
|
const base = '_content/MindExecution.Shared/js/';
|
|
582
|
-
const scriptVersion = '20260621-
|
|
582
|
+
const scriptVersion = '20260621-native-text-css3d-v768';
|
|
583
583
|
const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
|
|
584
584
|
console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
|
|
585
585
|
const criticalScripts = [
|
|
@@ -590,7 +590,7 @@
|
|
|
590
590
|
'background-themes.js',
|
|
591
591
|
'mind-map-logic-workers.js',
|
|
592
592
|
// Troika removed
|
|
593
|
-
'texture-worker-manager.js', // ??Web Worker
|
|
593
|
+
'texture-worker-manager.js', // ??Web Worker ??좎럩?ゅ뜝???좎럩苑?
|
|
594
594
|
'mind-map-texture-factory.js',
|
|
595
595
|
'mind-map-glow-shader.js', // ??SDF Glow (no textures, GPU only)
|
|
596
596
|
'mind-map-css3d-manager.js',
|
|
@@ -603,7 +603,7 @@
|
|
|
603
603
|
'mind-map-interactions.js',
|
|
604
604
|
'mind-map-dnd.js',
|
|
605
605
|
'mind-map-lod-renderer.js',
|
|
606
|
-
'mind-map-text-lod-system.js', // ??Text LOD
|
|
606
|
+
'mind-map-text-lod-system.js', // ??Text LOD ??좎럩???(??좎럩????좎럩?ゅ뜝???좎럩彛?
|
|
607
607
|
'mind-map-core.js',
|
|
608
608
|
'mindmap-toolbar.js',
|
|
609
609
|
'token-manager.js',
|
|
@@ -722,7 +722,7 @@
|
|
|
722
722
|
window.showBlazorBootError('The page could not finish loading. Reload and try again.');
|
|
723
723
|
});
|
|
724
724
|
</script>
|
|
725
|
-
<!--
|
|
725
|
+
<!-- ??좎뜦堉??[Upgrade] ??좎뜦堉??-->
|
|
726
726
|
</body>
|
|
727
727
|
|
|
728
728
|
</html>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
self.assetsManifest = {
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "MbOfumRW",
|
|
3
3
|
"assets": [
|
|
4
4
|
{
|
|
5
5
|
"hash": "sha256-+CSYMcqLNTsq3VnH11jgYyOCCdxvHzL74CBmo4sCmMU=",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"url": "_content/MindExecution.Shared/css/app.css"
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
|
-
"hash": "sha256-
|
|
45
|
+
"hash": "sha256-7nQpXb37sKR3RZmQKw2aOgyHiJhZIeD0ZjND2r6kPQA=",
|
|
46
46
|
"url": "_content/MindExecution.Shared/css/mind-map-overrides.css"
|
|
47
47
|
},
|
|
48
48
|
{
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"url": "_content/MindExecution.Shared/js/marked.min.js"
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
|
-
"hash": "sha256-
|
|
81
|
+
"hash": "sha256-MQlbxaL9dPkFLXMKym66rO86KqrhAENJ2as1RigkaAg=",
|
|
82
82
|
"url": "_content/MindExecution.Shared/js/mind-map-core.js"
|
|
83
83
|
},
|
|
84
84
|
{
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"url": "_content/MindExecution.Shared/js/mind-map-core.js.backup"
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
|
-
"hash": "sha256-
|
|
89
|
+
"hash": "sha256-47AXeYQsA/oib+SKpGtdZvNe46zeqUJIVjSSCWQh+R4=",
|
|
90
90
|
"url": "_content/MindExecution.Shared/js/mind-map-css3d-manager.js"
|
|
91
91
|
},
|
|
92
92
|
{
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
"url": "_content/MindExecution.Shared/js/mind-map-lod-plan-worker.js"
|
|
115
115
|
},
|
|
116
116
|
{
|
|
117
|
-
"hash": "sha256-
|
|
117
|
+
"hash": "sha256-jZXZkbCTSbx0/SeGrY8w8ftkqVJyxsoIVqPQY5VlxYI=",
|
|
118
118
|
"url": "_content/MindExecution.Shared/js/mind-map-lod-renderer.js"
|
|
119
119
|
},
|
|
120
120
|
{
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
"url": "_content/MindExecution.Shared/js/mind-map-node-search-worker.js"
|
|
135
135
|
},
|
|
136
136
|
{
|
|
137
|
-
"hash": "sha256-
|
|
137
|
+
"hash": "sha256-ILZvVKP1KjScKg2EAmPNokKNrZCv8do4XE3r1piy988=",
|
|
138
138
|
"url": "_content/MindExecution.Shared/js/mind-map-nodes.js"
|
|
139
139
|
},
|
|
140
140
|
{
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"url": "_content/MindExecution.Shared/js/mind-map-object-manager.js.backup"
|
|
147
147
|
},
|
|
148
148
|
{
|
|
149
|
-
"hash": "sha256-
|
|
149
|
+
"hash": "sha256-QvC3R24/3hjEyEkuxhKD2yA47gscsPoysFuaQJ6hhLQ=",
|
|
150
150
|
"url": "_content/MindExecution.Shared/js/mind-map-pipeline.js"
|
|
151
151
|
},
|
|
152
152
|
{
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
"url": "_content/MindExecution.Shared/js/plan-master.js"
|
|
183
183
|
},
|
|
184
184
|
{
|
|
185
|
-
"hash": "sha256-
|
|
185
|
+
"hash": "sha256-sw+qo4BCCICzNh4RmibnAFQaeNcZ0njo6b1VwFAzKdo=",
|
|
186
186
|
"url": "_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js"
|
|
187
187
|
},
|
|
188
188
|
{
|
|
@@ -834,7 +834,7 @@
|
|
|
834
834
|
"url": "image-manifest.json"
|
|
835
835
|
},
|
|
836
836
|
{
|
|
837
|
-
"hash": "sha256-
|
|
837
|
+
"hash": "sha256-k7kHDdZrrGs696vtUiMDao5o91j7fMxKEO5ZbrR+vxM=",
|
|
838
838
|
"url": "index.html"
|
|
839
839
|
},
|
|
840
840
|
{
|