@accelerated-agency/visual-editor 0.3.3 → 0.3.5
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/dist/index.js +3 -1
- package/dist/vite.cjs +573 -170
- package/dist/vite.js +573 -170
- package/package.json +1 -1
package/dist/vite.js
CHANGED
|
@@ -347,21 +347,21 @@ html,body{height:100%;overflow:hidden;font-family:-apple-system,BlinkMacSystemFo
|
|
|
347
347
|
.lp-sec{border-bottom:1px solid var(--border);flex-shrink:0;padding: 24px;}
|
|
348
348
|
.lp-sec-no-border{border-bottom:none!important}
|
|
349
349
|
.lp-sec-hd{
|
|
350
|
-
|
|
350
|
+
margin-bottom: 12px;
|
|
351
|
+
font-size:14px;font-weight:600;
|
|
351
352
|
color:#404040;display:flex;align-items:center;justify-content:space-between;gap:5px
|
|
352
353
|
}
|
|
353
354
|
.lp-sec-hd-left{display:flex;align-items:center;gap:5px}
|
|
354
355
|
#active-var-label{display:none;color:var(--accent-txt);font-size:10px;font-weight:500}
|
|
355
356
|
.lp-info-icon{font-size:11px;color:var(--text-3);cursor:default;opacity:.7}
|
|
356
357
|
.lp-add-btn{
|
|
357
|
-
display:none;
|
|
358
358
|
background:none;border:none;color:var(--text);font-size:14px;font-weight:500;
|
|
359
359
|
cursor:pointer;padding:2px 5px;border-radius:4px;transition:all .12s;flex-shrink:0
|
|
360
360
|
}
|
|
361
361
|
.lp-add-btn:hover{background:var(--bg-hover);color:var(--accent-txt)}
|
|
362
362
|
|
|
363
363
|
/* \u2500\u2500 Variation tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
364
|
-
#variation-tabs{
|
|
364
|
+
#variation-tabs{display:flex;flex-direction:column; gap:8px;}
|
|
365
365
|
.var-tab{
|
|
366
366
|
border-radius: 4px;
|
|
367
367
|
border: 1px solid #e5e7eb;
|
|
@@ -392,7 +392,7 @@ html,body{height:100%;overflow:hidden;font-family:-apple-system,BlinkMacSystemFo
|
|
|
392
392
|
#comp-search:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(99,102,241,.12)}
|
|
393
393
|
|
|
394
394
|
/* \u2500\u2500 Left tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
395
|
-
.lp-tabs{display:flex;border-bottom:1px solid var(--border);flex-shrink:0;background:#fff}
|
|
395
|
+
.lp-tabs, .section-components-tabs{display:flex;border-bottom:1px solid var(--border);flex-shrink:0;background:#fff}
|
|
396
396
|
.lp-tab{
|
|
397
397
|
flex:1;padding:8px 2px;text-align:center;font-size:10px;color:var(--text-3);
|
|
398
398
|
cursor:pointer;border-bottom:2px solid transparent;transition:all .15s;font-weight:600;line-height:1.15
|
|
@@ -402,10 +402,10 @@ html,body{height:100%;overflow:hidden;font-family:-apple-system,BlinkMacSystemFo
|
|
|
402
402
|
.future-hidden{display:none!important}
|
|
403
403
|
|
|
404
404
|
/* \u2500\u2500 Left panel body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
405
|
-
.lp-body{flex:1;overflow-y:auto}
|
|
406
|
-
.lp-body::-webkit-scrollbar{width:3px}
|
|
407
|
-
.lp-body::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}
|
|
408
|
-
.tab-pane{display:none}.tab-pane.active{display:block}
|
|
405
|
+
.lp-body, .section-components-body{flex:1;overflow-y:auto}
|
|
406
|
+
.lp-body::-webkit-scrollbar, .section-components-body::-webkit-scrollbar{width:3px}
|
|
407
|
+
.lp-body::-webkit-scrollbar-thumb, .section-components-body::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}
|
|
408
|
+
.tab-pane, .section-components-tab-pane{display:none}.tab-pane.active, .section-components-tab-pane.active{display:block}
|
|
409
409
|
|
|
410
410
|
/* \u2500\u2500 Component grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
411
411
|
.cg-hdr{padding:8px 10px 4px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)}
|
|
@@ -617,12 +617,83 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
617
617
|
}
|
|
618
618
|
#states-clear:hover{border-color:#fca5a5;color:#ef4444;background:#fef2f2}
|
|
619
619
|
#history-clear{
|
|
620
|
-
display:block;width:calc(100% - 24px);margin:10px 12px;
|
|
620
|
+
display:block;width:calc(100% - 24px);margin:10px 12px 8px;
|
|
621
621
|
background:none;border:1px solid var(--border);border-radius:6px;
|
|
622
622
|
padding:6px;font-size:11px;color:var(--text-2);cursor:pointer;font-family:inherit;
|
|
623
623
|
transition:all .15s
|
|
624
624
|
}
|
|
625
625
|
#history-clear:hover{border-color:#fca5a5;color:#ef4444;background:#fef2f2}
|
|
626
|
+
.history-timeline{
|
|
627
|
+
position:relative;
|
|
628
|
+
margin:8px 0 12px;
|
|
629
|
+
padding:0 12px 0 36px;
|
|
630
|
+
}
|
|
631
|
+
.history-timeline::before{
|
|
632
|
+
content:'';
|
|
633
|
+
position:absolute;
|
|
634
|
+
left:20px;
|
|
635
|
+
top:4px;
|
|
636
|
+
bottom:4px;
|
|
637
|
+
width:2px;
|
|
638
|
+
background:#eceff3;
|
|
639
|
+
border-radius:2px;
|
|
640
|
+
}
|
|
641
|
+
.history-item{
|
|
642
|
+
position:relative;
|
|
643
|
+
display:flex;
|
|
644
|
+
align-items:flex-start;
|
|
645
|
+
gap:10px;
|
|
646
|
+
padding:10px 8px 10px 0;
|
|
647
|
+
cursor:pointer;
|
|
648
|
+
}
|
|
649
|
+
.history-dot{
|
|
650
|
+
position:absolute;
|
|
651
|
+
left:-20px;
|
|
652
|
+
top:18px;
|
|
653
|
+
width:10px;
|
|
654
|
+
height:10px;
|
|
655
|
+
border-radius:50%;
|
|
656
|
+
background:#fff;
|
|
657
|
+
border:2px solid #d7dde6;
|
|
658
|
+
}
|
|
659
|
+
.history-card{
|
|
660
|
+
flex:1;
|
|
661
|
+
min-width:0;
|
|
662
|
+
}
|
|
663
|
+
.history-title{
|
|
664
|
+
font-size:14px;
|
|
665
|
+
font-weight:600;
|
|
666
|
+
color:var(--text);
|
|
667
|
+
line-height:1.3;
|
|
668
|
+
}
|
|
669
|
+
.history-meta{
|
|
670
|
+
margin-top:4px;
|
|
671
|
+
display:flex;
|
|
672
|
+
align-items:center;
|
|
673
|
+
gap:6px;
|
|
674
|
+
color:var(--text-2);
|
|
675
|
+
font-size:11px;
|
|
676
|
+
}
|
|
677
|
+
.history-avatar{
|
|
678
|
+
width:18px;
|
|
679
|
+
height:18px;
|
|
680
|
+
border-radius:50%;
|
|
681
|
+
background:#e9e5ff;
|
|
682
|
+
color:#5b47d6;
|
|
683
|
+
display:flex;
|
|
684
|
+
align-items:center;
|
|
685
|
+
justify-content:center;
|
|
686
|
+
font-size:10px;
|
|
687
|
+
font-weight:700;
|
|
688
|
+
}
|
|
689
|
+
.history-time{
|
|
690
|
+
margin-top:3px;
|
|
691
|
+
font-size:11px;
|
|
692
|
+
color:var(--text-3);
|
|
693
|
+
}
|
|
694
|
+
.history-remove{
|
|
695
|
+
margin-top:2px;
|
|
696
|
+
}
|
|
626
697
|
</style>
|
|
627
698
|
</head>
|
|
628
699
|
<body class="mode-editor">
|
|
@@ -704,7 +775,7 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
704
775
|
<div class="lp-sec">
|
|
705
776
|
<div class="lp-sec-hd">
|
|
706
777
|
<span class="lp-sec-hd-left">Variations <span id="active-var-label"></span></span>
|
|
707
|
-
<button class="lp-add-btn" title="Add variation">+ Add</button>
|
|
778
|
+
<button class="lp-add-btn" style="display:none" title="Add variation">+ Add</button>
|
|
708
779
|
</div>
|
|
709
780
|
<div id="variation-tabs"></div>
|
|
710
781
|
</div>
|
|
@@ -729,27 +800,39 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
729
800
|
<span class="lp-sec-hd-left">Elements <i class="bi bi-info-circle lp-info-icon" title="Page elements"></i></span>
|
|
730
801
|
<button class="lp-add-btn" title="Add element">+ Add</button>
|
|
731
802
|
</div>
|
|
732
|
-
</div>
|
|
733
803
|
|
|
734
|
-
|
|
735
|
-
<div
|
|
804
|
+
<!-- Search (hidden, kept for JS) -->
|
|
805
|
+
<div>
|
|
736
806
|
<input type="search" id="comp-search" placeholder="Search layers\u2026" autocomplete="off">
|
|
737
807
|
</div>
|
|
738
808
|
|
|
809
|
+
|
|
739
810
|
<!-- Tabs (hidden, kept for JS) -->
|
|
740
|
-
<div class="lp-tabs"
|
|
741
|
-
|
|
742
|
-
<div class="lp-tab
|
|
743
|
-
|
|
811
|
+
<div class="lp-tabs" >
|
|
812
|
+
<div class="lp-tab active" onclick="switchLeftTab('elements')">Elements</div>
|
|
813
|
+
<div class="lp-tab" onclick="switchLeftTab('dom-tree')">DOM Tree</div>
|
|
814
|
+
</div>
|
|
815
|
+
|
|
744
816
|
</div>
|
|
745
817
|
|
|
746
818
|
<!-- Tab content -->
|
|
747
819
|
<div class="lp-body">
|
|
748
|
-
<div id="tab-
|
|
749
|
-
<div id="
|
|
750
|
-
|
|
820
|
+
<div id="tab-dom-tree" class="tab-pane">
|
|
821
|
+
<div id="dom-tree-root" class="dt-tree">
|
|
822
|
+
</div>
|
|
823
|
+
</div>
|
|
824
|
+
<div id="tab-elements" class="tab-pane active">
|
|
825
|
+
<div id="elements-root" class="elements-tree">
|
|
826
|
+
</div>
|
|
827
|
+
</div>
|
|
751
828
|
</div>
|
|
752
829
|
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
|
|
753
836
|
</div><!-- #left-panel -->
|
|
754
837
|
|
|
755
838
|
<!-- Center / iframe panel -->
|
|
@@ -757,7 +840,8 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
757
840
|
|
|
758
841
|
<!-- Floating toolbar for selected element (positioned over iframe) -->
|
|
759
842
|
<div id="selection-floater" aria-label="Selection actions">
|
|
760
|
-
<button type="button" class="sf-btn" id="sf-
|
|
843
|
+
<button type="button" class="sf-btn" id="sf-move-up" title="Move up"><i class="bi bi-arrow-up"></i></button>
|
|
844
|
+
<button type="button" class="sf-btn" id="sf-move-down" title="Move down"><i class="bi bi-arrow-down"></i></button>
|
|
761
845
|
<span class="sf-sep"></span>
|
|
762
846
|
<button type="button" class="sf-btn" id="sf-resize" disabled title="Resize (coming soon)"><i class="bi bi-arrows-angle-expand"></i></button>
|
|
763
847
|
<button type="button" class="sf-btn" id="sf-rotate" disabled title="Rotate (coming soon)"><i class="bi bi-arrow-repeat"></i></button>
|
|
@@ -784,13 +868,20 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
784
868
|
|
|
785
869
|
<!-- Right panel -->
|
|
786
870
|
<div id="right-panel">
|
|
787
|
-
|
|
871
|
+
<!-- Left-tab controls moved here -->
|
|
872
|
+
<div class="section-components-tabs">
|
|
873
|
+
<div class="lp-tab" onclick="switchSectionComponentsTab('components')">Components</div>
|
|
874
|
+
<div class="lp-tab" onclick="switchSectionComponentsTab('sections')">Sections</div>
|
|
875
|
+
</div>
|
|
876
|
+
<div class="lp-body">
|
|
877
|
+
<div id="tab-components" class="tab-pane"></div>
|
|
878
|
+
<div id="tab-sections" class="tab-pane"></div>
|
|
879
|
+
</div>
|
|
788
880
|
<!-- Element badge (hidden until selection) -->
|
|
789
881
|
<div id="el-info" style="display:none">
|
|
790
882
|
<div id="el-info-tag"></div>
|
|
791
883
|
<div id="el-info-sel"></div>
|
|
792
884
|
</div>
|
|
793
|
-
|
|
794
885
|
<!-- \u2500\u2500 3 main tabs \u2500\u2500 -->
|
|
795
886
|
<div id="main-tabs">
|
|
796
887
|
<button class="main-tab active" onclick="switchMainTab('design')">Design</button>
|
|
@@ -872,12 +963,7 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
872
963
|
|
|
873
964
|
<!-- \u2500\u2500 States pane \u2500\u2500 -->
|
|
874
965
|
<div id="tab-states" class="rp-pane">
|
|
875
|
-
<div id="states-list">
|
|
876
|
-
<div class="states-empty">
|
|
877
|
-
<i class="bi bi-layers"></i>
|
|
878
|
-
No changes yet \u2014 edit elements on the page to see states here
|
|
879
|
-
</div>
|
|
880
|
-
</div>
|
|
966
|
+
<div id="states-list"></div>
|
|
881
967
|
</div><!-- #tab-states -->
|
|
882
968
|
|
|
883
969
|
<!-- \u2500\u2500 History pane (saved DB changesets for active variation) \u2500\u2500 -->
|
|
@@ -1125,6 +1211,7 @@ var suppressClickUntil = 0;
|
|
|
1125
1211
|
var dragAttachDoc = null;
|
|
1126
1212
|
var currentMainTab = 'design';
|
|
1127
1213
|
var currentLeftTab = 'elements';
|
|
1214
|
+
var currentSectionComponentsTab = 'components';
|
|
1128
1215
|
var dragHandleActive = false;
|
|
1129
1216
|
var domTreeCollapsed = {};
|
|
1130
1217
|
var domTreeRefreshTimer = null;
|
|
@@ -1156,6 +1243,13 @@ var stateChangesByVarId = {};
|
|
|
1156
1243
|
var appliedChangesetSnapshots = {};
|
|
1157
1244
|
/** Canonical JSON fingerprints of persisted changesets per variation (last load / finalize) */
|
|
1158
1245
|
var baselineChangesetsByVarId = {};
|
|
1246
|
+
/** Monotonic timestamp key for ordering mixed live + saved history rows. */
|
|
1247
|
+
var vveHistorySeq = 0;
|
|
1248
|
+
|
|
1249
|
+
function nextHistoryTimestamp() {
|
|
1250
|
+
vveHistorySeq += 1;
|
|
1251
|
+
return Date.now() * 1000 + vveHistorySeq;
|
|
1252
|
+
}
|
|
1159
1253
|
|
|
1160
1254
|
// \u2500\u2500 Dirty tracking (compare DB baseline + session stateChanges vs current export) \u2500\u2500
|
|
1161
1255
|
function beginSuppressIframeMutationDirty() {
|
|
@@ -1371,27 +1465,45 @@ function setDevice(device) {
|
|
|
1371
1465
|
|
|
1372
1466
|
// \u2500\u2500 Left panel tab switch \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1373
1467
|
function switchLeftTab(tab) {
|
|
1468
|
+
if (tab !== 'elements' && tab !== 'dom-tree') return;
|
|
1374
1469
|
currentLeftTab = tab;
|
|
1375
|
-
var tabs = document.querySelectorAll('.lp-tab');
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1470
|
+
var tabs = document.querySelectorAll('.lp-tabs .lp-tab');
|
|
1471
|
+
for (var i = 0; i < tabs.length; i++) {
|
|
1472
|
+
var oc = tabs[i].getAttribute('onclick') || '';
|
|
1473
|
+
tabs[i].classList.toggle('active', oc.indexOf("switchLeftTab('" + tab + "')") >= 0);
|
|
1474
|
+
}
|
|
1475
|
+
var paneNames = ['elements', 'dom-tree'];
|
|
1476
|
+
for (var p = 0; p < paneNames.length; p++) {
|
|
1477
|
+
var pane = document.getElementById('tab-' + paneNames[p]);
|
|
1478
|
+
if (pane) pane.classList.toggle('active', paneNames[p] === tab);
|
|
1479
|
+
}
|
|
1382
1480
|
var inp = document.getElementById('comp-search');
|
|
1383
1481
|
if (tab === 'elements') {
|
|
1482
|
+
inp.placeholder = 'Search elements\u2026';
|
|
1483
|
+
renderElementsTree(inp.value);
|
|
1484
|
+
} else if (tab === 'dom-tree') {
|
|
1384
1485
|
inp.placeholder = 'Search layers\u2026';
|
|
1385
1486
|
renderDomTree(inp.value);
|
|
1386
|
-
} else if (tab === 'sections') {
|
|
1387
|
-
inp.placeholder = 'Search sections\u2026';
|
|
1388
|
-
renderSidebar(inp.value);
|
|
1389
|
-
} else {
|
|
1390
|
-
inp.placeholder = 'Search components\u2026';
|
|
1391
|
-
renderSidebar(inp.value);
|
|
1392
1487
|
}
|
|
1393
1488
|
}
|
|
1394
1489
|
|
|
1490
|
+
function switchSectionComponentsTab(tab) {
|
|
1491
|
+
if (tab !== 'components' && tab !== 'sections') return;
|
|
1492
|
+
currentSectionComponentsTab = tab;
|
|
1493
|
+
var tabs = document.querySelectorAll('.section-components-tabs .lp-tab');
|
|
1494
|
+
for (var i = 0; i < tabs.length; i++) {
|
|
1495
|
+
var oc = tabs[i].getAttribute('onclick') || '';
|
|
1496
|
+
tabs[i].classList.toggle('active', oc.indexOf("switchSectionComponentsTab('" + tab + "')") >= 0);
|
|
1497
|
+
}
|
|
1498
|
+
var compPane = document.getElementById('tab-components');
|
|
1499
|
+
var secPane = document.getElementById('tab-sections');
|
|
1500
|
+
if (compPane) compPane.classList.toggle('active', tab === 'components');
|
|
1501
|
+
if (secPane) secPane.classList.toggle('active', tab === 'sections');
|
|
1502
|
+
var inp = document.getElementById('comp-search');
|
|
1503
|
+
if (inp) inp.placeholder = tab === 'sections' ? 'Search sections\u2026' : 'Search components\u2026';
|
|
1504
|
+
renderSidebar(inp ? inp.value : '');
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1395
1507
|
// \u2500\u2500 Accordion toggle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1396
1508
|
function toggleAcc(name) {
|
|
1397
1509
|
var sec = document.getElementById('acc-' + name);
|
|
@@ -1514,42 +1626,20 @@ function logChange(selector, inputId, value, targetEl, originalValue) {
|
|
|
1514
1626
|
: (originalValue != null ? originalValue : '');
|
|
1515
1627
|
var entry = {
|
|
1516
1628
|
selector: selector, inputId: inputId, label: meta.label,
|
|
1517
|
-
cssProp: meta.cssProp, value: value, targetEl: targetEl, originalValue: orig
|
|
1629
|
+
cssProp: meta.cssProp, value: value, targetEl: targetEl, originalValue: orig, vveTs: nextHistoryTimestamp()
|
|
1518
1630
|
};
|
|
1519
1631
|
if (idx >= 0) { stateChanges[idx] = entry; } else { stateChanges.push(entry); }
|
|
1520
1632
|
}
|
|
1521
1633
|
if (currentMainTab === 'states') renderStatesTab();
|
|
1634
|
+
if (currentMainTab === 'history') renderHistoryTab();
|
|
1522
1635
|
commitStateChangesForActiveVariation();
|
|
1523
1636
|
recomputeEditorDirty();
|
|
1524
1637
|
}
|
|
1525
1638
|
|
|
1526
1639
|
function renderStatesTab() {
|
|
1527
1640
|
var container = document.getElementById('states-list');
|
|
1528
|
-
if (!
|
|
1529
|
-
|
|
1530
|
-
return;
|
|
1531
|
-
}
|
|
1532
|
-
// Group by selector
|
|
1533
|
-
var groups = {};
|
|
1534
|
-
var order = [];
|
|
1535
|
-
stateChanges.forEach(function(c) {
|
|
1536
|
-
if (!groups[c.selector]) { groups[c.selector] = []; order.push(c.selector); }
|
|
1537
|
-
groups[c.selector].push(c);
|
|
1538
|
-
});
|
|
1539
|
-
var html = '<button id="states-clear" onclick="clearAllStates()"><i class="bi bi-trash3"></i> Clear all changes</button>';
|
|
1540
|
-
order.forEach(function(sel) {
|
|
1541
|
-
html += '<div class="state-group"><div class="state-group-sel">'+esc(sel)+'</div>';
|
|
1542
|
-
groups[sel].forEach(function(c) {
|
|
1543
|
-
var idx = stateChanges.indexOf(c);
|
|
1544
|
-
html += '<div class="state-item">' +
|
|
1545
|
-
'<span class="state-item-label">'+esc(c.label)+'</span>' +
|
|
1546
|
-
'<span class="state-item-val" title="'+esc(c.value)+'">'+esc(c.value)+'</span>' +
|
|
1547
|
-
'<button class="state-remove" title="Remove this change" onclick="removeStateChange('+idx+')">✕</button>' +
|
|
1548
|
-
'</div>';
|
|
1549
|
-
});
|
|
1550
|
-
html += '</div>';
|
|
1551
|
-
});
|
|
1552
|
-
container.innerHTML = html;
|
|
1641
|
+
if (!container) return;
|
|
1642
|
+
container.innerHTML = '';
|
|
1553
1643
|
}
|
|
1554
1644
|
|
|
1555
1645
|
// Resolve a live DOM element for a state-change entry.
|
|
@@ -1628,7 +1718,9 @@ function removeStateChange(idx) {
|
|
|
1628
1718
|
stateChanges.splice(idx, 1);
|
|
1629
1719
|
commitStateChangesForActiveVariation();
|
|
1630
1720
|
renderStatesTab();
|
|
1721
|
+
if (currentMainTab === 'history') renderHistoryTab();
|
|
1631
1722
|
recomputeEditorDirty();
|
|
1723
|
+
scheduleDomTreeRefresh();
|
|
1632
1724
|
}
|
|
1633
1725
|
|
|
1634
1726
|
function clearAllStates() {
|
|
@@ -1639,7 +1731,9 @@ function clearAllStates() {
|
|
|
1639
1731
|
stateChanges = [];
|
|
1640
1732
|
commitStateChangesForActiveVariation();
|
|
1641
1733
|
renderStatesTab();
|
|
1734
|
+
if (currentMainTab === 'history') renderHistoryTab();
|
|
1642
1735
|
recomputeEditorDirty();
|
|
1736
|
+
scheduleDomTreeRefresh();
|
|
1643
1737
|
}
|
|
1644
1738
|
|
|
1645
1739
|
// \u2500\u2500 History tab (saved changesets from DB for active variation) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
@@ -1812,61 +1906,169 @@ function historyEntryValuePreview(entry) {
|
|
|
1812
1906
|
return '';
|
|
1813
1907
|
}
|
|
1814
1908
|
|
|
1909
|
+
function getHistoryTimestampValue(raw, fallback) {
|
|
1910
|
+
var n = Number(raw);
|
|
1911
|
+
if (Number.isFinite(n) && n > 0) return n;
|
|
1912
|
+
return fallback;
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
function historyTimestampForChangeset(entry, idx) {
|
|
1916
|
+
var base = idx + 1;
|
|
1917
|
+
if (!entry) return base;
|
|
1918
|
+
return getHistoryTimestampValue(
|
|
1919
|
+
entry.vveTs != null ? entry.vveTs : (entry.timestamp != null ? entry.timestamp : entry.ts),
|
|
1920
|
+
base,
|
|
1921
|
+
);
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
function historyTimestampForStateChange(change, idx) {
|
|
1925
|
+
return getHistoryTimestampValue(change && change.vveTs, idx + 1);
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
function formatHistoryTimestamp(ts) {
|
|
1929
|
+
if (!Number.isFinite(ts) || ts <= 0) return '';
|
|
1930
|
+
var ms = ts > 9999999999999 ? Math.floor(ts / 1000) : ts;
|
|
1931
|
+
var d = new Date(ms);
|
|
1932
|
+
if (isNaN(d.getTime())) return '';
|
|
1933
|
+
return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
function formatHistoryRelativeTime(ts) {
|
|
1937
|
+
if (!Number.isFinite(ts) || ts <= 0) return '';
|
|
1938
|
+
var ms = ts > 9999999999999 ? Math.floor(ts / 1000) : ts;
|
|
1939
|
+
var diff = Math.max(0, Date.now() - ms);
|
|
1940
|
+
var sec = Math.floor(diff / 1000);
|
|
1941
|
+
if (sec < 5) return 'just now';
|
|
1942
|
+
if (sec < 60) return sec + ' seconds ago';
|
|
1943
|
+
var min = Math.floor(sec / 60);
|
|
1944
|
+
if (min < 60) return min + ' minute' + (min === 1 ? '' : 's') + ' ago';
|
|
1945
|
+
var hr = Math.floor(min / 60);
|
|
1946
|
+
if (hr < 24) return hr + ' hour' + (hr === 1 ? '' : 's') + ' ago';
|
|
1947
|
+
var day = Math.floor(hr / 24);
|
|
1948
|
+
return day + ' day' + (day === 1 ? '' : 's') + ' ago';
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
function getUnifiedHistoryItems() {
|
|
1952
|
+
var out = [];
|
|
1953
|
+
var v = getActiveVariationForHistory();
|
|
1954
|
+
var saved = v ? parseVariationChangesets(v) : [];
|
|
1955
|
+
for (var i = 0; i < saved.length; i++) {
|
|
1956
|
+
var e = saved[i];
|
|
1957
|
+
out.push({
|
|
1958
|
+
source: 'saved',
|
|
1959
|
+
idx: i,
|
|
1960
|
+
selector: (e && e.selector) || '(unknown)',
|
|
1961
|
+
label: historyEntryTypeLabel(e),
|
|
1962
|
+
value: historyEntryValuePreview(e),
|
|
1963
|
+
ts: historyTimestampForChangeset(e, i),
|
|
1964
|
+
tsLabel: formatHistoryTimestamp(historyTimestampForChangeset(e, i)),
|
|
1965
|
+
actor: 'Saved changeset',
|
|
1966
|
+
});
|
|
1967
|
+
}
|
|
1968
|
+
var live = stateChanges || [];
|
|
1969
|
+
for (var j = 0; j < live.length; j++) {
|
|
1970
|
+
var c = live[j];
|
|
1971
|
+
if (!c) continue;
|
|
1972
|
+
var ts = historyTimestampForStateChange(c, j + saved.length);
|
|
1973
|
+
out.push({
|
|
1974
|
+
source: 'live',
|
|
1975
|
+
idx: j,
|
|
1976
|
+
selector: c.selector || '(unknown)',
|
|
1977
|
+
label: c.label || 'Live change',
|
|
1978
|
+
value: c.value != null ? String(c.value).slice(0, 120) : '',
|
|
1979
|
+
ts: ts,
|
|
1980
|
+
tsLabel: formatHistoryTimestamp(ts),
|
|
1981
|
+
actor: 'You',
|
|
1982
|
+
});
|
|
1983
|
+
}
|
|
1984
|
+
out.sort(function(a, b) {
|
|
1985
|
+
if (b.ts !== a.ts) return b.ts - a.ts;
|
|
1986
|
+
if (a.source !== b.source) return a.source === 'live' ? -1 : 1;
|
|
1987
|
+
return b.idx - a.idx;
|
|
1988
|
+
});
|
|
1989
|
+
return out;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1815
1992
|
function renderHistoryTab() {
|
|
1816
1993
|
var container = document.getElementById('history-list');
|
|
1817
1994
|
if (!container) return;
|
|
1818
|
-
var
|
|
1819
|
-
|
|
1820
|
-
if (!arr.length) {
|
|
1995
|
+
var items = getUnifiedHistoryItems();
|
|
1996
|
+
if (!items.length) {
|
|
1821
1997
|
container.innerHTML =
|
|
1822
|
-
'<div class="states-empty"><i class="bi bi-clock-history"></i>No
|
|
1998
|
+
'<div class="states-empty"><i class="bi bi-clock-history"></i>No changes yet</div>';
|
|
1823
1999
|
return;
|
|
1824
2000
|
}
|
|
1825
|
-
var groups = {};
|
|
1826
|
-
var order = [];
|
|
1827
|
-
for (var gi = 0; gi < arr.length; gi++) {
|
|
1828
|
-
var entry = arr[gi];
|
|
1829
|
-
var sel = entry.selector || '(unknown)';
|
|
1830
|
-
if (!groups[sel]) {
|
|
1831
|
-
groups[sel] = [];
|
|
1832
|
-
order.push(sel);
|
|
1833
|
-
}
|
|
1834
|
-
groups[sel].push({ entry: entry, idx: gi });
|
|
1835
|
-
}
|
|
1836
2001
|
var html =
|
|
1837
|
-
'<button type="button" id="history-clear" onclick="
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
2002
|
+
'<button type="button" id="history-clear" onclick="clearAllUnifiedHistory()"><i class="bi bi-trash3"></i> Clear all changes</button>';
|
|
2003
|
+
html += '<div class="history-timeline">';
|
|
2004
|
+
for (var i = 0; i < items.length; i++) {
|
|
2005
|
+
var it = items[i];
|
|
2006
|
+
var title = 'Edit - ' + (it.label || 'Change');
|
|
2007
|
+
var avatarLabel = it.source === 'live' ? 'Y' : 'S';
|
|
2008
|
+
var timeText = formatHistoryRelativeTime(it.ts) || (it.tsLabel || '');
|
|
2009
|
+
html +=
|
|
2010
|
+
'<div class="history-item" role="button" tabindex="0" title="Jump to element in iframe" onclick="focusHistoryItem("' +
|
|
2011
|
+
esc(it.source) +
|
|
2012
|
+
'",' +
|
|
2013
|
+
it.idx +
|
|
2014
|
+
')">' +
|
|
2015
|
+
'<span class="history-dot"></span>' +
|
|
2016
|
+
'<div class="history-card">' +
|
|
2017
|
+
'<div class="history-title">' + esc(title) + '</div>' +
|
|
2018
|
+
'<div class="history-meta">' +
|
|
2019
|
+
'<span class="history-avatar">' + esc(avatarLabel) + '</span>' +
|
|
2020
|
+
'<span>' + esc(it.actor || 'Editor') + '</span>' +
|
|
2021
|
+
'</div>' +
|
|
2022
|
+
'<div class="history-time">' + esc(timeText || 'n/a') + '</div>' +
|
|
2023
|
+
'</div>' +
|
|
2024
|
+
'<button type="button" class="state-remove history-remove" title="Remove this change" onclick="removeHistoryItem("' +
|
|
2025
|
+
esc(it.source) +
|
|
2026
|
+
'",' +
|
|
2027
|
+
it.idx +
|
|
2028
|
+
', event)">✕</button>' +
|
|
2029
|
+
'</div>';
|
|
2030
|
+
}
|
|
2031
|
+
html += '</div>';
|
|
1867
2032
|
container.innerHTML = html;
|
|
1868
2033
|
}
|
|
1869
2034
|
|
|
2035
|
+
function focusHistoryItem(source, idx) {
|
|
2036
|
+
if (source === 'live') {
|
|
2037
|
+
var change = stateChanges[idx];
|
|
2038
|
+
if (!change || !change.selector) return;
|
|
2039
|
+
try {
|
|
2040
|
+
var iframe = document.getElementById('iframeId');
|
|
2041
|
+
var iframeDoc = iframe && iframe.contentDocument;
|
|
2042
|
+
if (!iframeDoc) return;
|
|
2043
|
+
var el = querySelectorResolved(iframeDoc, change.selector);
|
|
2044
|
+
if (!el) return;
|
|
2045
|
+
selectElement(el);
|
|
2046
|
+
try {
|
|
2047
|
+
el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
|
|
2048
|
+
} catch(_) {
|
|
2049
|
+
el.scrollIntoView();
|
|
2050
|
+
}
|
|
2051
|
+
} catch(_) {}
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
focusHistoryChangeset(idx);
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
function removeHistoryItem(source, idx, evt) {
|
|
2058
|
+
if (source === 'live') {
|
|
2059
|
+
if (evt && evt.stopPropagation) evt.stopPropagation();
|
|
2060
|
+
removeStateChange(idx);
|
|
2061
|
+
if (currentMainTab === 'history') renderHistoryTab();
|
|
2062
|
+
return;
|
|
2063
|
+
}
|
|
2064
|
+
removeHistoryChangeset(idx, evt);
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
function getLatestHistoryUndoTarget() {
|
|
2068
|
+
var list = getUnifiedHistoryItems();
|
|
2069
|
+
return list.length ? list[0] : null;
|
|
2070
|
+
}
|
|
2071
|
+
|
|
1870
2072
|
function changesetListHasStructural(arr) {
|
|
1871
2073
|
if (!arr || !arr.length) return false;
|
|
1872
2074
|
for (var i = 0; i < arr.length; i++) {
|
|
@@ -1978,6 +2180,12 @@ function clearAllHistoryChangesets() {
|
|
|
1978
2180
|
softReloadEditorIframe();
|
|
1979
2181
|
}
|
|
1980
2182
|
|
|
2183
|
+
function clearAllUnifiedHistory() {
|
|
2184
|
+
clearAllStates();
|
|
2185
|
+
clearAllHistoryChangesets();
|
|
2186
|
+
if (currentMainTab === 'history') renderHistoryTab();
|
|
2187
|
+
}
|
|
2188
|
+
|
|
1981
2189
|
// \u2500\u2500 Persisted active variation (survives iframe / full page reload) \u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1982
2190
|
/** All Visual Editor iframe keys in localStorage use this prefix \u2014 cleared on close. */
|
|
1983
2191
|
var VVE_LOCAL_STORAGE_PREFIX = 'vve:';
|
|
@@ -2058,7 +2266,8 @@ function handleLoadExperiment(data) {
|
|
|
2058
2266
|
return;
|
|
2059
2267
|
}
|
|
2060
2268
|
var proxyUrl = '/api/conversion-proxy?password=' + encodeURIComponent(data.editorPassword || '') +
|
|
2061
|
-
'&url=' + encodeURIComponent(pageUrl)
|
|
2269
|
+
'&url=' + encodeURIComponent(pageUrl) +
|
|
2270
|
+
'&strictObserverFreeze=' + encodeURIComponent(data && data.strictObserverFreeze ? '1' : '0');
|
|
2062
2271
|
|
|
2063
2272
|
// Parent often re-posts load-experiment when React re-renders (new object identity) or
|
|
2064
2273
|
// after mutations-changed. Reloading the iframe again wipes variant changesets mid-session.
|
|
@@ -2330,7 +2539,7 @@ function runConsistencyReconcile() {
|
|
|
2330
2539
|
var doc = iframe && iframe.contentDocument;
|
|
2331
2540
|
if (!doc || !doc.body) return;
|
|
2332
2541
|
var variation = variations.find(function(v) { return v._id === activeVarId; });
|
|
2333
|
-
var cs =
|
|
2542
|
+
var cs = buildPersistedChainSetsForVariation(variation);
|
|
2334
2543
|
if (!cs.length || changesetsHaveBodySnapshot(cs)) return;
|
|
2335
2544
|
var granular = filterGranularChangesetEntries(cs);
|
|
2336
2545
|
var unresolved = countUnresolvedGranularSelectors(doc, granular);
|
|
@@ -2590,6 +2799,7 @@ function mergeGranularChainSets(baseList, overlayList) {
|
|
|
2590
2799
|
function appendSessionStructuralChainRow(varId, row) {
|
|
2591
2800
|
if (!varId || !row) return;
|
|
2592
2801
|
if (!sessionStructuralChainRowsByVarId[varId]) sessionStructuralChainRowsByVarId[varId] = [];
|
|
2802
|
+
if (row.vveTs == null) row.vveTs = nextHistoryTimestamp();
|
|
2593
2803
|
sessionStructuralChainRowsByVarId[varId].push(row);
|
|
2594
2804
|
}
|
|
2595
2805
|
|
|
@@ -2597,33 +2807,33 @@ function appendSessionStructuralChainRow(varId, row) {
|
|
|
2597
2807
|
function stateChangeToChainSet(c) {
|
|
2598
2808
|
if (!c || !c.selector) return null;
|
|
2599
2809
|
if (c.cssProp) {
|
|
2600
|
-
return { selector: c.selector, type: 'style', property: c.cssProp, value: c.value };
|
|
2810
|
+
return { selector: c.selector, type: 'style', property: c.cssProp, value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2601
2811
|
}
|
|
2602
2812
|
switch (c.inputId) {
|
|
2603
2813
|
case 'pp-text':
|
|
2604
|
-
return { selector: c.selector, type: 'content', value: c.value };
|
|
2814
|
+
return { selector: c.selector, type: 'content', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2605
2815
|
case 'pp-html':
|
|
2606
|
-
return { selector: c.selector, type: 'content', html: c.value };
|
|
2816
|
+
return { selector: c.selector, type: 'content', html: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2607
2817
|
case 'pp-cls':
|
|
2608
|
-
return { selector: c.selector, type: 'attribute', attribute: 'class', value: c.value };
|
|
2818
|
+
return { selector: c.selector, type: 'attribute', attribute: 'class', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2609
2819
|
case 'pp-id':
|
|
2610
|
-
return { selector: c.selector, type: 'attribute', attribute: 'id', value: c.value };
|
|
2820
|
+
return { selector: c.selector, type: 'attribute', attribute: 'id', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2611
2821
|
case 'pp-href':
|
|
2612
|
-
return { selector: c.selector, type: 'attribute', attribute: 'href', value: c.value };
|
|
2822
|
+
return { selector: c.selector, type: 'attribute', attribute: 'href', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2613
2823
|
case 'pp-target':
|
|
2614
|
-
return { selector: c.selector, type: 'attribute', attribute: 'target', value: c.value };
|
|
2824
|
+
return { selector: c.selector, type: 'attribute', attribute: 'target', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2615
2825
|
case 'pp-src':
|
|
2616
|
-
return { selector: c.selector, type: 'attribute', attribute: 'src', value: c.value };
|
|
2826
|
+
return { selector: c.selector, type: 'attribute', attribute: 'src', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2617
2827
|
case 'pp-alt':
|
|
2618
|
-
return { selector: c.selector, type: 'attribute', attribute: 'alt', value: c.value };
|
|
2828
|
+
return { selector: c.selector, type: 'attribute', attribute: 'alt', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2619
2829
|
case 'pp-ph':
|
|
2620
|
-
return { selector: c.selector, type: 'attribute', attribute: 'placeholder', value: c.value };
|
|
2830
|
+
return { selector: c.selector, type: 'attribute', attribute: 'placeholder', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2621
2831
|
case 'pp-css':
|
|
2622
|
-
return { selector: c.selector, type: 'attribute', attribute: 'style', value: c.value };
|
|
2832
|
+
return { selector: c.selector, type: 'attribute', attribute: 'style', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2623
2833
|
case 'pp-mob-css':
|
|
2624
|
-
return { selector: c.selector, type: 'attribute', attribute: 'data-mobile-css', value: c.value };
|
|
2834
|
+
return { selector: c.selector, type: 'attribute', attribute: 'data-mobile-css', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2625
2835
|
case 'pp-tab-css':
|
|
2626
|
-
return { selector: c.selector, type: 'attribute', attribute: 'data-tablet-css', value: c.value };
|
|
2836
|
+
return { selector: c.selector, type: 'attribute', attribute: 'data-tablet-css', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2627
2837
|
default:
|
|
2628
2838
|
return null;
|
|
2629
2839
|
}
|
|
@@ -2911,7 +3121,7 @@ function applyActiveVariationHtml() {
|
|
|
2911
3121
|
if (!iframeDoc || !iframeDoc.body) return;
|
|
2912
3122
|
|
|
2913
3123
|
var variation = variations.find(function(v) { return v._id === activeVarId; });
|
|
2914
|
-
var cs =
|
|
3124
|
+
var cs = buildPersistedChainSetsForVariation(variation);
|
|
2915
3125
|
refreshPersistentChangesetStyleTagForActiveVariation();
|
|
2916
3126
|
|
|
2917
3127
|
beginSuppressIframeMutationDirty();
|
|
@@ -2969,7 +3179,7 @@ function applyVariationGranularOnly(iframeDoc) {
|
|
|
2969
3179
|
if (!activeVarId || !iframeDoc || !iframeDoc.body) return;
|
|
2970
3180
|
if (varHtmlCache[activeVarId]) return;
|
|
2971
3181
|
var variation = variations.find(function(v) { return v._id === activeVarId; });
|
|
2972
|
-
var cs =
|
|
3182
|
+
var cs = buildPersistedChainSetsForVariation(variation);
|
|
2973
3183
|
if (!cs.length || changesetsHaveBodySnapshot(cs)) return;
|
|
2974
3184
|
beginSuppressIframeMutationDirty();
|
|
2975
3185
|
try {
|
|
@@ -2988,7 +3198,7 @@ function reapplyActiveVariationGranular(iframeDoc) {
|
|
|
2988
3198
|
if (!activeVarId || !iframeDoc || !iframeDoc.body) return;
|
|
2989
3199
|
if (varHtmlCache[activeVarId]) return;
|
|
2990
3200
|
var variation = variations.find(function(v) { return v._id === activeVarId; });
|
|
2991
|
-
var cs =
|
|
3201
|
+
var cs = buildPersistedChainSetsForVariation(variation);
|
|
2992
3202
|
if (!cs.length || changesetsHaveBodySnapshot(cs)) return;
|
|
2993
3203
|
beginSuppressIframeMutationDirty();
|
|
2994
3204
|
try {
|
|
@@ -3032,7 +3242,7 @@ function startIframeContentApplyWatcher(navGen, prevDocRef) {
|
|
|
3032
3242
|
|
|
3033
3243
|
if (doc.readyState === 'loading') {
|
|
3034
3244
|
var variation = variations.find(function(v) { return v._id === activeVarId; });
|
|
3035
|
-
var cs0 =
|
|
3245
|
+
var cs0 = buildPersistedChainSetsForVariation(variation);
|
|
3036
3246
|
if (!cs0.length || changesetsHaveBodySnapshot(cs0)) return;
|
|
3037
3247
|
var granular = filterGranularChangesetEntries(cs0);
|
|
3038
3248
|
if (!granular.length) return;
|
|
@@ -3078,8 +3288,9 @@ function selectElement(el) {
|
|
|
3078
3288
|
document.getElementById('no-sel').style.display = 'none';
|
|
3079
3289
|
renderRightPanel(el);
|
|
3080
3290
|
updateSelectionToolbar();
|
|
3081
|
-
if (currentLeftTab === 'elements') {
|
|
3082
|
-
var
|
|
3291
|
+
if (currentLeftTab === 'elements' || currentLeftTab === 'dom-tree') {
|
|
3292
|
+
var treeRootId = currentLeftTab === 'elements' ? 'elements-root' : 'dom-tree-root';
|
|
3293
|
+
var dr = document.getElementById(treeRootId);
|
|
3083
3294
|
if (dr && dr.querySelector('.dt-row')) syncDomTreeSelection();
|
|
3084
3295
|
else scheduleDomTreeRefresh();
|
|
3085
3296
|
}
|
|
@@ -3342,27 +3553,32 @@ function deleteSelectedEl() {
|
|
|
3342
3553
|
}
|
|
3343
3554
|
|
|
3344
3555
|
function syncDomTreeSelection() {
|
|
3345
|
-
var
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
rows
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3556
|
+
var roots = ['dom-tree-root', 'elements-root'];
|
|
3557
|
+
for (var r = 0; r < roots.length; r++) {
|
|
3558
|
+
var root = document.getElementById(roots[r]);
|
|
3559
|
+
if (!root) continue;
|
|
3560
|
+
var rows = root.querySelectorAll('.dt-row');
|
|
3561
|
+
for (var i = 0; i < rows.length; i++) {
|
|
3562
|
+
rows[i].classList.toggle('dt-selected', !!(selectedEl && rows[i]._dtEl === selectedEl));
|
|
3563
|
+
}
|
|
3564
|
+
if (!selectedEl) continue;
|
|
3565
|
+
var found = null;
|
|
3566
|
+
for (var j = 0; j < rows.length; j++) {
|
|
3567
|
+
if (rows[j]._dtEl === selectedEl) { found = rows[j]; break; }
|
|
3568
|
+
}
|
|
3569
|
+
if (found) found.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
3355
3570
|
}
|
|
3356
|
-
if (found) found.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
3357
3571
|
}
|
|
3358
3572
|
|
|
3359
3573
|
function scheduleDomTreeRefresh() {
|
|
3360
|
-
if (currentLeftTab !== 'elements') return;
|
|
3574
|
+
if (currentLeftTab !== 'elements' && currentLeftTab !== 'dom-tree') return;
|
|
3361
3575
|
if (domTreeRefreshTimer) clearTimeout(domTreeRefreshTimer);
|
|
3362
3576
|
domTreeRefreshTimer = setTimeout(function() {
|
|
3363
3577
|
domTreeRefreshTimer = null;
|
|
3364
3578
|
var inp = document.getElementById('comp-search');
|
|
3365
|
-
|
|
3579
|
+
var q = inp ? inp.value : '';
|
|
3580
|
+
if (currentLeftTab === 'elements') renderElementsTree(q);
|
|
3581
|
+
else if (currentLeftTab === 'dom-tree') renderDomTree(q);
|
|
3366
3582
|
}, 150);
|
|
3367
3583
|
}
|
|
3368
3584
|
|
|
@@ -3385,6 +3601,129 @@ function domTreePathSegment(el) {
|
|
|
3385
3601
|
return tag + '[' + idx + ']';
|
|
3386
3602
|
}
|
|
3387
3603
|
|
|
3604
|
+
function renderElementsTree(filterRaw) {
|
|
3605
|
+
var filterText = (filterRaw || '').toLowerCase().trim();
|
|
3606
|
+
var root = document.getElementById('elements-root');
|
|
3607
|
+
if (!root) return;
|
|
3608
|
+
var iframe = document.getElementById('iframeId');
|
|
3609
|
+
var doc = iframe && iframe.contentDocument;
|
|
3610
|
+
if (!isIframeDomReady(iframe, doc)) {
|
|
3611
|
+
root.innerHTML = '<div class="dt-muted">Load a page to see the elements.</div>';
|
|
3612
|
+
return;
|
|
3613
|
+
}
|
|
3614
|
+
|
|
3615
|
+
function skippable(el) {
|
|
3616
|
+
return isDomTreeSkippableTagName(el.tagName);
|
|
3617
|
+
}
|
|
3618
|
+
|
|
3619
|
+
function nodeIcon(tag) {
|
|
3620
|
+
tag = (tag || '').toLowerCase();
|
|
3621
|
+
if (/^h[1-6]$/.test(tag)) return 'bi bi-type-h1';
|
|
3622
|
+
if (tag === 'a') return 'bi bi-link-45deg';
|
|
3623
|
+
if (tag === 'img') return 'bi bi-image';
|
|
3624
|
+
if (tag === 'section' || tag === 'main' || tag === 'article' || tag === 'header' || tag === 'footer' || tag === 'nav') return 'bi bi-layout-three-columns';
|
|
3625
|
+
if (tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea') return 'bi bi-ui-radios';
|
|
3626
|
+
if (tag === 'ul' || tag === 'ol') return 'bi bi-list-ul';
|
|
3627
|
+
if (tag === 'li') return 'bi bi-dot';
|
|
3628
|
+
if (tag === 'svg') return 'bi bi-bezier2';
|
|
3629
|
+
if (tag === 'p' || tag === 'span') return 'bi bi-text-left';
|
|
3630
|
+
return 'bi bi-square';
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3633
|
+
function labelFor(el) {
|
|
3634
|
+
var tag = (el.tagName || '').toLowerCase();
|
|
3635
|
+
return tag.toUpperCase();
|
|
3636
|
+
}
|
|
3637
|
+
|
|
3638
|
+
function isListableNode(el) {
|
|
3639
|
+
if (!el || el.nodeType !== 1) return false;
|
|
3640
|
+
if (skippable(el)) return false;
|
|
3641
|
+
var tag = (el.tagName || '').toLowerCase();
|
|
3642
|
+
if (tag !== 'svg') {
|
|
3643
|
+
var p = el.parentElement;
|
|
3644
|
+
while (p) {
|
|
3645
|
+
if ((p.tagName || '').toLowerCase() === 'svg') return false;
|
|
3646
|
+
p = p.parentElement;
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3649
|
+
return true;
|
|
3650
|
+
}
|
|
3651
|
+
|
|
3652
|
+
var nodes = [];
|
|
3653
|
+
var i, cursor;
|
|
3654
|
+
try {
|
|
3655
|
+
cursor = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ELEMENT, null);
|
|
3656
|
+
} catch(_) {
|
|
3657
|
+
cursor = null;
|
|
3658
|
+
}
|
|
3659
|
+
if (cursor) {
|
|
3660
|
+
while (cursor.nextNode()) {
|
|
3661
|
+
var node = cursor.currentNode;
|
|
3662
|
+
if (isListableNode(node)) nodes.push(node);
|
|
3663
|
+
if (nodes.length > 4000) break;
|
|
3664
|
+
}
|
|
3665
|
+
} else {
|
|
3666
|
+
function collectFlat(el) {
|
|
3667
|
+
if (!el || !el.children) return;
|
|
3668
|
+
for (var j = 0; j < el.children.length; j++) {
|
|
3669
|
+
var c = el.children[j];
|
|
3670
|
+
if (!isListableNode(c)) continue;
|
|
3671
|
+
nodes.push(c);
|
|
3672
|
+
if (nodes.length > 4000) return;
|
|
3673
|
+
collectFlat(c);
|
|
3674
|
+
if (nodes.length > 4000) return;
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
collectFlat(doc.body);
|
|
3678
|
+
}
|
|
3679
|
+
|
|
3680
|
+
root.innerHTML = '';
|
|
3681
|
+
for (i = 0; i < nodes.length; i++) {
|
|
3682
|
+
var el = nodes[i];
|
|
3683
|
+
var lblText = labelFor(el);
|
|
3684
|
+
if (filterText && lblText.toLowerCase().indexOf(filterText) < 0) continue;
|
|
3685
|
+
|
|
3686
|
+
var row = document.createElement('div');
|
|
3687
|
+
row.className = 'dt-row';
|
|
3688
|
+
row._dtEl = el;
|
|
3689
|
+
if (el === selectedEl) row.classList.add('dt-selected');
|
|
3690
|
+
row.style.paddingLeft = '4px';
|
|
3691
|
+
|
|
3692
|
+
var spacer = document.createElement('button');
|
|
3693
|
+
spacer.type = 'button';
|
|
3694
|
+
spacer.className = 'dt-chev dt-spacer';
|
|
3695
|
+
|
|
3696
|
+
var ico = document.createElement('div');
|
|
3697
|
+
ico.className = 'dt-ico';
|
|
3698
|
+
ico.innerHTML = '<i class="' + nodeIcon(el.tagName) + '"></i>';
|
|
3699
|
+
|
|
3700
|
+
var lbl = document.createElement('div');
|
|
3701
|
+
lbl.className = 'dt-lbl';
|
|
3702
|
+
lbl.textContent = lblText;
|
|
3703
|
+
lbl.title = buildSelector(el);
|
|
3704
|
+
|
|
3705
|
+
row.appendChild(spacer);
|
|
3706
|
+
row.appendChild(ico);
|
|
3707
|
+
row.appendChild(lbl);
|
|
3708
|
+
row.onclick = (function(targetEl) {
|
|
3709
|
+
return function() { selectElementFromTree(targetEl); };
|
|
3710
|
+
})(el);
|
|
3711
|
+
row.onmouseenter = (function(targetEl) {
|
|
3712
|
+
return function() { setTreeHoverHighlight(targetEl); };
|
|
3713
|
+
})(el);
|
|
3714
|
+
root.appendChild(row);
|
|
3715
|
+
}
|
|
3716
|
+
|
|
3717
|
+
if (!root.querySelector('.dt-row')) {
|
|
3718
|
+
root.innerHTML = filterText
|
|
3719
|
+
? '<div class="dt-muted">No elements match your search.</div>'
|
|
3720
|
+
: '<div class="dt-muted">No elements found.</div>';
|
|
3721
|
+
}
|
|
3722
|
+
root.onmouseleave = function() {
|
|
3723
|
+
clearTreeHoverHighlight();
|
|
3724
|
+
};
|
|
3725
|
+
}
|
|
3726
|
+
|
|
3388
3727
|
function renderDomTree(filterRaw) {
|
|
3389
3728
|
var filterText = (filterRaw || '').toLowerCase().trim();
|
|
3390
3729
|
var root = document.getElementById('dom-tree-root');
|
|
@@ -4123,6 +4462,20 @@ function recordReorderAfterDrag(movedEl) {
|
|
|
4123
4462
|
}
|
|
4124
4463
|
}
|
|
4125
4464
|
|
|
4465
|
+
function moveSelectedElByDirection(direction) {
|
|
4466
|
+
if (!selectedEl || !selectedEl.parentElement) return;
|
|
4467
|
+
var p = selectedEl.parentElement;
|
|
4468
|
+
var sibling = direction < 0 ? selectedEl.previousElementSibling : selectedEl.nextElementSibling;
|
|
4469
|
+
if (!sibling) return;
|
|
4470
|
+
if (direction < 0) p.insertBefore(selectedEl, sibling);
|
|
4471
|
+
else p.insertBefore(sibling, selectedEl);
|
|
4472
|
+
recordReorderAfterDrag(selectedEl);
|
|
4473
|
+
saveCurrentVariationHtml();
|
|
4474
|
+
recomputeEditorDirty();
|
|
4475
|
+
scheduleDomTreeRefresh();
|
|
4476
|
+
updateSelectionToolbar();
|
|
4477
|
+
}
|
|
4478
|
+
|
|
4126
4479
|
function attachDragReposition() {
|
|
4127
4480
|
try {
|
|
4128
4481
|
var iframe = document.getElementById('iframeId');
|
|
@@ -4309,7 +4662,9 @@ function syncIframeInteractions(reason) {
|
|
|
4309
4662
|
scheduleConsistencyReconcile();
|
|
4310
4663
|
bindSelectionToolbarScroll();
|
|
4311
4664
|
var inp = document.getElementById('comp-search');
|
|
4312
|
-
|
|
4665
|
+
var q = inp ? inp.value : '';
|
|
4666
|
+
if (currentLeftTab === 'elements') renderElementsTree(q);
|
|
4667
|
+
else if (currentLeftTab === 'dom-tree') renderDomTree(q);
|
|
4313
4668
|
updateSelectionToolbar();
|
|
4314
4669
|
recomputeEditorDirty();
|
|
4315
4670
|
} catch(_) {}
|
|
@@ -4473,8 +4828,11 @@ function renderSidebar(filter) {
|
|
|
4473
4828
|
}
|
|
4474
4829
|
|
|
4475
4830
|
document.getElementById('comp-search').addEventListener('input', function() {
|
|
4476
|
-
if (currentLeftTab === 'elements')
|
|
4477
|
-
else
|
|
4831
|
+
if (currentLeftTab === 'elements') renderElementsTree(this.value);
|
|
4832
|
+
else if (currentLeftTab === 'dom-tree') renderDomTree(this.value);
|
|
4833
|
+
if (currentSectionComponentsTab === 'components' || currentSectionComponentsTab === 'sections') {
|
|
4834
|
+
renderSidebar(this.value);
|
|
4835
|
+
}
|
|
4478
4836
|
});
|
|
4479
4837
|
|
|
4480
4838
|
// \u2500\u2500 Save / Close \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
@@ -4540,19 +4898,11 @@ document.addEventListener('keydown', function(e) {
|
|
|
4540
4898
|
var k = (e.key || '').toLowerCase();
|
|
4541
4899
|
if (meta && !e.shiftKey && k === 'z') {
|
|
4542
4900
|
e.preventDefault();
|
|
4543
|
-
|
|
4544
|
-
Vvveb.Undo.undo();
|
|
4545
|
-
saveCurrentVariationHtml();
|
|
4546
|
-
recomputeEditorDirty();
|
|
4547
|
-
}
|
|
4901
|
+
runEditorUndo();
|
|
4548
4902
|
}
|
|
4549
4903
|
if (meta && e.shiftKey && k === 'z') {
|
|
4550
4904
|
e.preventDefault();
|
|
4551
|
-
|
|
4552
|
-
Vvveb.Undo.redo();
|
|
4553
|
-
saveCurrentVariationHtml();
|
|
4554
|
-
recomputeEditorDirty();
|
|
4555
|
-
}
|
|
4905
|
+
runEditorRedo();
|
|
4556
4906
|
}
|
|
4557
4907
|
if (meta && e.key === 's') { e.preventDefault(); handleSave(); }
|
|
4558
4908
|
if (e.key === 'Escape') {
|
|
@@ -4572,8 +4922,39 @@ document.addEventListener('keydown', function(e) {
|
|
|
4572
4922
|
if (selectedEl) deselectElement();
|
|
4573
4923
|
}
|
|
4574
4924
|
});
|
|
4575
|
-
|
|
4576
|
-
|
|
4925
|
+
function runEditorUndo() {
|
|
4926
|
+
var target = getLatestHistoryUndoTarget();
|
|
4927
|
+
if (target) {
|
|
4928
|
+
removeHistoryItem(target.source, target.idx);
|
|
4929
|
+
return;
|
|
4930
|
+
}
|
|
4931
|
+
if (!(typeof Vvveb !== 'undefined' && Vvveb.Undo)) return;
|
|
4932
|
+
Vvveb.Undo.undo();
|
|
4933
|
+
saveCurrentVariationHtml();
|
|
4934
|
+
recomputeEditorDirty();
|
|
4935
|
+
scheduleDomTreeRefresh();
|
|
4936
|
+
updateSelectionToolbar();
|
|
4937
|
+
}
|
|
4938
|
+
|
|
4939
|
+
function runEditorRedo() {
|
|
4940
|
+
if (!(typeof Vvveb !== 'undefined' && Vvveb.Undo)) return;
|
|
4941
|
+
Vvveb.Undo.redo();
|
|
4942
|
+
saveCurrentVariationHtml();
|
|
4943
|
+
recomputeEditorDirty();
|
|
4944
|
+
scheduleDomTreeRefresh();
|
|
4945
|
+
updateSelectionToolbar();
|
|
4946
|
+
}
|
|
4947
|
+
|
|
4948
|
+
document.getElementById('btn-undo').addEventListener('click', function(e) {
|
|
4949
|
+
e.preventDefault();
|
|
4950
|
+
e.stopPropagation();
|
|
4951
|
+
runEditorUndo();
|
|
4952
|
+
});
|
|
4953
|
+
document.getElementById('btn-redo').addEventListener('click', function(e) {
|
|
4954
|
+
e.preventDefault();
|
|
4955
|
+
e.stopPropagation();
|
|
4956
|
+
runEditorRedo();
|
|
4957
|
+
});
|
|
4577
4958
|
|
|
4578
4959
|
function layoutLoadingTooltip(host) {
|
|
4579
4960
|
var tip = host.querySelector('.ve-pl-tooltip');
|
|
@@ -4649,8 +5030,8 @@ function registerCROSections() {
|
|
|
4649
5030
|
|
|
4650
5031
|
window.addEventListener('load', function() {
|
|
4651
5032
|
registerCROSections();
|
|
4652
|
-
|
|
4653
|
-
|
|
5033
|
+
switchSectionComponentsTab(currentSectionComponentsTab);
|
|
5034
|
+
renderElementsTree(document.getElementById('comp-search').value);
|
|
4654
5035
|
vvvebReady = true;
|
|
4655
5036
|
bindLoadingTooltipPositioning();
|
|
4656
5037
|
|
|
@@ -4703,12 +5084,22 @@ window.addEventListener('load', function() {
|
|
|
4703
5084
|
syncIframeInteractions('iframe-load');
|
|
4704
5085
|
});
|
|
4705
5086
|
|
|
4706
|
-
document.getElementById('sf-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
5087
|
+
var sfMoveUp = document.getElementById('sf-move-up');
|
|
5088
|
+
if (sfMoveUp) {
|
|
5089
|
+
sfMoveUp.addEventListener('click', function(e) {
|
|
5090
|
+
e.preventDefault();
|
|
5091
|
+
e.stopPropagation();
|
|
5092
|
+
moveSelectedElByDirection(-1);
|
|
5093
|
+
});
|
|
5094
|
+
}
|
|
5095
|
+
var sfMoveDown = document.getElementById('sf-move-down');
|
|
5096
|
+
if (sfMoveDown) {
|
|
5097
|
+
sfMoveDown.addEventListener('click', function(e) {
|
|
5098
|
+
e.preventDefault();
|
|
5099
|
+
e.stopPropagation();
|
|
5100
|
+
moveSelectedElByDirection(1);
|
|
5101
|
+
});
|
|
5102
|
+
}
|
|
4712
5103
|
document.getElementById('sf-dup').addEventListener('click', function(e) {
|
|
4713
5104
|
e.preventDefault();
|
|
4714
5105
|
e.stopPropagation();
|
|
@@ -4754,6 +5145,7 @@ var getDefaultAnthropicApiKey = () => {
|
|
|
4754
5145
|
function createVisualEditorMiddleware(options) {
|
|
4755
5146
|
const anthropicApiKey = options?.anthropicApiKey || getDefaultAnthropicApiKey();
|
|
4756
5147
|
const enableGenerateTestApi = options?.enableGenerateTestApi ?? true;
|
|
5148
|
+
const strictObserverFreeze = options?.strictObserverFreeze === true;
|
|
4757
5149
|
const allowedFrameOrigins = options?.allowedFrameOrigins ?? ["*"];
|
|
4758
5150
|
function setFrameHeaders(req, res) {
|
|
4759
5151
|
res.removeHeader("X-Frame-Options");
|
|
@@ -4921,6 +5313,8 @@ function createVisualEditorMiddleware(options) {
|
|
|
4921
5313
|
const url = new URL(req.url || "", "http://localhost");
|
|
4922
5314
|
const targetUrl = url.searchParams.get("url");
|
|
4923
5315
|
const password = url.searchParams.get("password") || "";
|
|
5316
|
+
const strictFreezeParam = (url.searchParams.get("strictObserverFreeze") || "").toLowerCase();
|
|
5317
|
+
const strictObserverFreezeForRequest = strictFreezeParam === "1" || strictFreezeParam === "true" || strictFreezeParam === "yes" ? true : strictFreezeParam === "0" || strictFreezeParam === "false" || strictFreezeParam === "no" ? false : strictObserverFreeze;
|
|
4924
5318
|
if (!targetUrl) {
|
|
4925
5319
|
res.statusCode = 400;
|
|
4926
5320
|
res.end(JSON.stringify({ error: "Missing url parameter" }));
|
|
@@ -5058,6 +5452,7 @@ ${iframeAlwaysShowCssGuardScript}
|
|
|
5058
5452
|
var TARGET_ORIGIN=${JSON.stringify(origin)};
|
|
5059
5453
|
var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};
|
|
5060
5454
|
var PROXY_PASSWORD=${JSON.stringify(password)};
|
|
5455
|
+
var STRICT_OBSERVER_FREEZE=${JSON.stringify(strictObserverFreezeForRequest)};
|
|
5061
5456
|
window.__CONVERSION_EDITOR_ACTIVE__=true;
|
|
5062
5457
|
function isSkippable(raw){if(!raw||typeof raw!=="string")return true;return raw.startsWith("data:")||raw.startsWith("blob:")||raw.startsWith("javascript:")||raw.startsWith("#");}
|
|
5063
5458
|
function toAbsolute(raw){if(isSkippable(raw))return raw;try{var base=raw.startsWith("/")||raw.startsWith("//")?TARGET_ORIGIN:TARGET_PAGE_URL;return new URL(raw,base).toString();}catch(_){return raw;}}
|
|
@@ -5077,6 +5472,9 @@ try{
|
|
|
5077
5472
|
var wrapped=function(list,obs){
|
|
5078
5473
|
try{
|
|
5079
5474
|
if(!window.__CONVERSION_EDITOR_ACTIVE__)return cb(list,obs);
|
|
5475
|
+
if(STRICT_OBSERVER_FREEZE){
|
|
5476
|
+
return;
|
|
5477
|
+
}
|
|
5080
5478
|
var now=Date.now();
|
|
5081
5479
|
if(now-last<120)return;
|
|
5082
5480
|
last=now;
|
|
@@ -5086,6 +5484,11 @@ try{
|
|
|
5086
5484
|
return new NativeMO(wrapped);
|
|
5087
5485
|
};
|
|
5088
5486
|
window.MutationObserver.prototype=NativeMO.prototype;
|
|
5487
|
+
try{
|
|
5488
|
+
if(STRICT_OBSERVER_FREEZE){
|
|
5489
|
+
console.info("[conversion-proxy] strict MutationObserver freeze active");
|
|
5490
|
+
}
|
|
5491
|
+
}catch(_){}
|
|
5089
5492
|
}
|
|
5090
5493
|
}catch(_){}
|
|
5091
5494
|
}catch(_){}})();</script>`;
|