@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.cjs
CHANGED
|
@@ -355,21 +355,21 @@ html,body{height:100%;overflow:hidden;font-family:-apple-system,BlinkMacSystemFo
|
|
|
355
355
|
.lp-sec{border-bottom:1px solid var(--border);flex-shrink:0;padding: 24px;}
|
|
356
356
|
.lp-sec-no-border{border-bottom:none!important}
|
|
357
357
|
.lp-sec-hd{
|
|
358
|
-
|
|
358
|
+
margin-bottom: 12px;
|
|
359
|
+
font-size:14px;font-weight:600;
|
|
359
360
|
color:#404040;display:flex;align-items:center;justify-content:space-between;gap:5px
|
|
360
361
|
}
|
|
361
362
|
.lp-sec-hd-left{display:flex;align-items:center;gap:5px}
|
|
362
363
|
#active-var-label{display:none;color:var(--accent-txt);font-size:10px;font-weight:500}
|
|
363
364
|
.lp-info-icon{font-size:11px;color:var(--text-3);cursor:default;opacity:.7}
|
|
364
365
|
.lp-add-btn{
|
|
365
|
-
display:none;
|
|
366
366
|
background:none;border:none;color:var(--text);font-size:14px;font-weight:500;
|
|
367
367
|
cursor:pointer;padding:2px 5px;border-radius:4px;transition:all .12s;flex-shrink:0
|
|
368
368
|
}
|
|
369
369
|
.lp-add-btn:hover{background:var(--bg-hover);color:var(--accent-txt)}
|
|
370
370
|
|
|
371
371
|
/* \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 */
|
|
372
|
-
#variation-tabs{
|
|
372
|
+
#variation-tabs{display:flex;flex-direction:column; gap:8px;}
|
|
373
373
|
.var-tab{
|
|
374
374
|
border-radius: 4px;
|
|
375
375
|
border: 1px solid #e5e7eb;
|
|
@@ -400,7 +400,7 @@ html,body{height:100%;overflow:hidden;font-family:-apple-system,BlinkMacSystemFo
|
|
|
400
400
|
#comp-search:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(99,102,241,.12)}
|
|
401
401
|
|
|
402
402
|
/* \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 */
|
|
403
|
-
.lp-tabs{display:flex;border-bottom:1px solid var(--border);flex-shrink:0;background:#fff}
|
|
403
|
+
.lp-tabs, .section-components-tabs{display:flex;border-bottom:1px solid var(--border);flex-shrink:0;background:#fff}
|
|
404
404
|
.lp-tab{
|
|
405
405
|
flex:1;padding:8px 2px;text-align:center;font-size:10px;color:var(--text-3);
|
|
406
406
|
cursor:pointer;border-bottom:2px solid transparent;transition:all .15s;font-weight:600;line-height:1.15
|
|
@@ -410,10 +410,10 @@ html,body{height:100%;overflow:hidden;font-family:-apple-system,BlinkMacSystemFo
|
|
|
410
410
|
.future-hidden{display:none!important}
|
|
411
411
|
|
|
412
412
|
/* \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 */
|
|
413
|
-
.lp-body{flex:1;overflow-y:auto}
|
|
414
|
-
.lp-body::-webkit-scrollbar{width:3px}
|
|
415
|
-
.lp-body::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}
|
|
416
|
-
.tab-pane{display:none}.tab-pane.active{display:block}
|
|
413
|
+
.lp-body, .section-components-body{flex:1;overflow-y:auto}
|
|
414
|
+
.lp-body::-webkit-scrollbar, .section-components-body::-webkit-scrollbar{width:3px}
|
|
415
|
+
.lp-body::-webkit-scrollbar-thumb, .section-components-body::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}
|
|
416
|
+
.tab-pane, .section-components-tab-pane{display:none}.tab-pane.active, .section-components-tab-pane.active{display:block}
|
|
417
417
|
|
|
418
418
|
/* \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 */
|
|
419
419
|
.cg-hdr{padding:8px 10px 4px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3)}
|
|
@@ -625,12 +625,83 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
625
625
|
}
|
|
626
626
|
#states-clear:hover{border-color:#fca5a5;color:#ef4444;background:#fef2f2}
|
|
627
627
|
#history-clear{
|
|
628
|
-
display:block;width:calc(100% - 24px);margin:10px 12px;
|
|
628
|
+
display:block;width:calc(100% - 24px);margin:10px 12px 8px;
|
|
629
629
|
background:none;border:1px solid var(--border);border-radius:6px;
|
|
630
630
|
padding:6px;font-size:11px;color:var(--text-2);cursor:pointer;font-family:inherit;
|
|
631
631
|
transition:all .15s
|
|
632
632
|
}
|
|
633
633
|
#history-clear:hover{border-color:#fca5a5;color:#ef4444;background:#fef2f2}
|
|
634
|
+
.history-timeline{
|
|
635
|
+
position:relative;
|
|
636
|
+
margin:8px 0 12px;
|
|
637
|
+
padding:0 12px 0 36px;
|
|
638
|
+
}
|
|
639
|
+
.history-timeline::before{
|
|
640
|
+
content:'';
|
|
641
|
+
position:absolute;
|
|
642
|
+
left:20px;
|
|
643
|
+
top:4px;
|
|
644
|
+
bottom:4px;
|
|
645
|
+
width:2px;
|
|
646
|
+
background:#eceff3;
|
|
647
|
+
border-radius:2px;
|
|
648
|
+
}
|
|
649
|
+
.history-item{
|
|
650
|
+
position:relative;
|
|
651
|
+
display:flex;
|
|
652
|
+
align-items:flex-start;
|
|
653
|
+
gap:10px;
|
|
654
|
+
padding:10px 8px 10px 0;
|
|
655
|
+
cursor:pointer;
|
|
656
|
+
}
|
|
657
|
+
.history-dot{
|
|
658
|
+
position:absolute;
|
|
659
|
+
left:-20px;
|
|
660
|
+
top:18px;
|
|
661
|
+
width:10px;
|
|
662
|
+
height:10px;
|
|
663
|
+
border-radius:50%;
|
|
664
|
+
background:#fff;
|
|
665
|
+
border:2px solid #d7dde6;
|
|
666
|
+
}
|
|
667
|
+
.history-card{
|
|
668
|
+
flex:1;
|
|
669
|
+
min-width:0;
|
|
670
|
+
}
|
|
671
|
+
.history-title{
|
|
672
|
+
font-size:14px;
|
|
673
|
+
font-weight:600;
|
|
674
|
+
color:var(--text);
|
|
675
|
+
line-height:1.3;
|
|
676
|
+
}
|
|
677
|
+
.history-meta{
|
|
678
|
+
margin-top:4px;
|
|
679
|
+
display:flex;
|
|
680
|
+
align-items:center;
|
|
681
|
+
gap:6px;
|
|
682
|
+
color:var(--text-2);
|
|
683
|
+
font-size:11px;
|
|
684
|
+
}
|
|
685
|
+
.history-avatar{
|
|
686
|
+
width:18px;
|
|
687
|
+
height:18px;
|
|
688
|
+
border-radius:50%;
|
|
689
|
+
background:#e9e5ff;
|
|
690
|
+
color:#5b47d6;
|
|
691
|
+
display:flex;
|
|
692
|
+
align-items:center;
|
|
693
|
+
justify-content:center;
|
|
694
|
+
font-size:10px;
|
|
695
|
+
font-weight:700;
|
|
696
|
+
}
|
|
697
|
+
.history-time{
|
|
698
|
+
margin-top:3px;
|
|
699
|
+
font-size:11px;
|
|
700
|
+
color:var(--text-3);
|
|
701
|
+
}
|
|
702
|
+
.history-remove{
|
|
703
|
+
margin-top:2px;
|
|
704
|
+
}
|
|
634
705
|
</style>
|
|
635
706
|
</head>
|
|
636
707
|
<body class="mode-editor">
|
|
@@ -712,7 +783,7 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
712
783
|
<div class="lp-sec">
|
|
713
784
|
<div class="lp-sec-hd">
|
|
714
785
|
<span class="lp-sec-hd-left">Variations <span id="active-var-label"></span></span>
|
|
715
|
-
<button class="lp-add-btn" title="Add variation">+ Add</button>
|
|
786
|
+
<button class="lp-add-btn" style="display:none" title="Add variation">+ Add</button>
|
|
716
787
|
</div>
|
|
717
788
|
<div id="variation-tabs"></div>
|
|
718
789
|
</div>
|
|
@@ -737,27 +808,39 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
737
808
|
<span class="lp-sec-hd-left">Elements <i class="bi bi-info-circle lp-info-icon" title="Page elements"></i></span>
|
|
738
809
|
<button class="lp-add-btn" title="Add element">+ Add</button>
|
|
739
810
|
</div>
|
|
740
|
-
</div>
|
|
741
811
|
|
|
742
|
-
|
|
743
|
-
<div
|
|
812
|
+
<!-- Search (hidden, kept for JS) -->
|
|
813
|
+
<div>
|
|
744
814
|
<input type="search" id="comp-search" placeholder="Search layers\u2026" autocomplete="off">
|
|
745
815
|
</div>
|
|
746
816
|
|
|
817
|
+
|
|
747
818
|
<!-- Tabs (hidden, kept for JS) -->
|
|
748
|
-
<div class="lp-tabs"
|
|
749
|
-
|
|
750
|
-
<div class="lp-tab
|
|
751
|
-
|
|
819
|
+
<div class="lp-tabs" >
|
|
820
|
+
<div class="lp-tab active" onclick="switchLeftTab('elements')">Elements</div>
|
|
821
|
+
<div class="lp-tab" onclick="switchLeftTab('dom-tree')">DOM Tree</div>
|
|
822
|
+
</div>
|
|
823
|
+
|
|
752
824
|
</div>
|
|
753
825
|
|
|
754
826
|
<!-- Tab content -->
|
|
755
827
|
<div class="lp-body">
|
|
756
|
-
<div id="tab-
|
|
757
|
-
<div id="
|
|
758
|
-
|
|
828
|
+
<div id="tab-dom-tree" class="tab-pane">
|
|
829
|
+
<div id="dom-tree-root" class="dt-tree">
|
|
830
|
+
</div>
|
|
831
|
+
</div>
|
|
832
|
+
<div id="tab-elements" class="tab-pane active">
|
|
833
|
+
<div id="elements-root" class="elements-tree">
|
|
834
|
+
</div>
|
|
835
|
+
</div>
|
|
759
836
|
</div>
|
|
760
837
|
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
|
|
761
844
|
</div><!-- #left-panel -->
|
|
762
845
|
|
|
763
846
|
<!-- Center / iframe panel -->
|
|
@@ -765,7 +848,8 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
765
848
|
|
|
766
849
|
<!-- Floating toolbar for selected element (positioned over iframe) -->
|
|
767
850
|
<div id="selection-floater" aria-label="Selection actions">
|
|
768
|
-
<button type="button" class="sf-btn" id="sf-
|
|
851
|
+
<button type="button" class="sf-btn" id="sf-move-up" title="Move up"><i class="bi bi-arrow-up"></i></button>
|
|
852
|
+
<button type="button" class="sf-btn" id="sf-move-down" title="Move down"><i class="bi bi-arrow-down"></i></button>
|
|
769
853
|
<span class="sf-sep"></span>
|
|
770
854
|
<button type="button" class="sf-btn" id="sf-resize" disabled title="Resize (coming soon)"><i class="bi bi-arrows-angle-expand"></i></button>
|
|
771
855
|
<button type="button" class="sf-btn" id="sf-rotate" disabled title="Rotate (coming soon)"><i class="bi bi-arrow-repeat"></i></button>
|
|
@@ -792,13 +876,20 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
792
876
|
|
|
793
877
|
<!-- Right panel -->
|
|
794
878
|
<div id="right-panel">
|
|
795
|
-
|
|
879
|
+
<!-- Left-tab controls moved here -->
|
|
880
|
+
<div class="section-components-tabs">
|
|
881
|
+
<div class="lp-tab" onclick="switchSectionComponentsTab('components')">Components</div>
|
|
882
|
+
<div class="lp-tab" onclick="switchSectionComponentsTab('sections')">Sections</div>
|
|
883
|
+
</div>
|
|
884
|
+
<div class="lp-body">
|
|
885
|
+
<div id="tab-components" class="tab-pane"></div>
|
|
886
|
+
<div id="tab-sections" class="tab-pane"></div>
|
|
887
|
+
</div>
|
|
796
888
|
<!-- Element badge (hidden until selection) -->
|
|
797
889
|
<div id="el-info" style="display:none">
|
|
798
890
|
<div id="el-info-tag"></div>
|
|
799
891
|
<div id="el-info-sel"></div>
|
|
800
892
|
</div>
|
|
801
|
-
|
|
802
893
|
<!-- \u2500\u2500 3 main tabs \u2500\u2500 -->
|
|
803
894
|
<div id="main-tabs">
|
|
804
895
|
<button class="main-tab active" onclick="switchMainTab('design')">Design</button>
|
|
@@ -880,12 +971,7 @@ select.pr-inp{cursor:pointer;background:#fff}
|
|
|
880
971
|
|
|
881
972
|
<!-- \u2500\u2500 States pane \u2500\u2500 -->
|
|
882
973
|
<div id="tab-states" class="rp-pane">
|
|
883
|
-
<div id="states-list">
|
|
884
|
-
<div class="states-empty">
|
|
885
|
-
<i class="bi bi-layers"></i>
|
|
886
|
-
No changes yet \u2014 edit elements on the page to see states here
|
|
887
|
-
</div>
|
|
888
|
-
</div>
|
|
974
|
+
<div id="states-list"></div>
|
|
889
975
|
</div><!-- #tab-states -->
|
|
890
976
|
|
|
891
977
|
<!-- \u2500\u2500 History pane (saved DB changesets for active variation) \u2500\u2500 -->
|
|
@@ -1133,6 +1219,7 @@ var suppressClickUntil = 0;
|
|
|
1133
1219
|
var dragAttachDoc = null;
|
|
1134
1220
|
var currentMainTab = 'design';
|
|
1135
1221
|
var currentLeftTab = 'elements';
|
|
1222
|
+
var currentSectionComponentsTab = 'components';
|
|
1136
1223
|
var dragHandleActive = false;
|
|
1137
1224
|
var domTreeCollapsed = {};
|
|
1138
1225
|
var domTreeRefreshTimer = null;
|
|
@@ -1164,6 +1251,13 @@ var stateChangesByVarId = {};
|
|
|
1164
1251
|
var appliedChangesetSnapshots = {};
|
|
1165
1252
|
/** Canonical JSON fingerprints of persisted changesets per variation (last load / finalize) */
|
|
1166
1253
|
var baselineChangesetsByVarId = {};
|
|
1254
|
+
/** Monotonic timestamp key for ordering mixed live + saved history rows. */
|
|
1255
|
+
var vveHistorySeq = 0;
|
|
1256
|
+
|
|
1257
|
+
function nextHistoryTimestamp() {
|
|
1258
|
+
vveHistorySeq += 1;
|
|
1259
|
+
return Date.now() * 1000 + vveHistorySeq;
|
|
1260
|
+
}
|
|
1167
1261
|
|
|
1168
1262
|
// \u2500\u2500 Dirty tracking (compare DB baseline + session stateChanges vs current export) \u2500\u2500
|
|
1169
1263
|
function beginSuppressIframeMutationDirty() {
|
|
@@ -1379,27 +1473,45 @@ function setDevice(device) {
|
|
|
1379
1473
|
|
|
1380
1474
|
// \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
|
|
1381
1475
|
function switchLeftTab(tab) {
|
|
1476
|
+
if (tab !== 'elements' && tab !== 'dom-tree') return;
|
|
1382
1477
|
currentLeftTab = tab;
|
|
1383
|
-
var tabs = document.querySelectorAll('.lp-tab');
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1478
|
+
var tabs = document.querySelectorAll('.lp-tabs .lp-tab');
|
|
1479
|
+
for (var i = 0; i < tabs.length; i++) {
|
|
1480
|
+
var oc = tabs[i].getAttribute('onclick') || '';
|
|
1481
|
+
tabs[i].classList.toggle('active', oc.indexOf("switchLeftTab('" + tab + "')") >= 0);
|
|
1482
|
+
}
|
|
1483
|
+
var paneNames = ['elements', 'dom-tree'];
|
|
1484
|
+
for (var p = 0; p < paneNames.length; p++) {
|
|
1485
|
+
var pane = document.getElementById('tab-' + paneNames[p]);
|
|
1486
|
+
if (pane) pane.classList.toggle('active', paneNames[p] === tab);
|
|
1487
|
+
}
|
|
1390
1488
|
var inp = document.getElementById('comp-search');
|
|
1391
1489
|
if (tab === 'elements') {
|
|
1490
|
+
inp.placeholder = 'Search elements\u2026';
|
|
1491
|
+
renderElementsTree(inp.value);
|
|
1492
|
+
} else if (tab === 'dom-tree') {
|
|
1392
1493
|
inp.placeholder = 'Search layers\u2026';
|
|
1393
1494
|
renderDomTree(inp.value);
|
|
1394
|
-
} else if (tab === 'sections') {
|
|
1395
|
-
inp.placeholder = 'Search sections\u2026';
|
|
1396
|
-
renderSidebar(inp.value);
|
|
1397
|
-
} else {
|
|
1398
|
-
inp.placeholder = 'Search components\u2026';
|
|
1399
|
-
renderSidebar(inp.value);
|
|
1400
1495
|
}
|
|
1401
1496
|
}
|
|
1402
1497
|
|
|
1498
|
+
function switchSectionComponentsTab(tab) {
|
|
1499
|
+
if (tab !== 'components' && tab !== 'sections') return;
|
|
1500
|
+
currentSectionComponentsTab = tab;
|
|
1501
|
+
var tabs = document.querySelectorAll('.section-components-tabs .lp-tab');
|
|
1502
|
+
for (var i = 0; i < tabs.length; i++) {
|
|
1503
|
+
var oc = tabs[i].getAttribute('onclick') || '';
|
|
1504
|
+
tabs[i].classList.toggle('active', oc.indexOf("switchSectionComponentsTab('" + tab + "')") >= 0);
|
|
1505
|
+
}
|
|
1506
|
+
var compPane = document.getElementById('tab-components');
|
|
1507
|
+
var secPane = document.getElementById('tab-sections');
|
|
1508
|
+
if (compPane) compPane.classList.toggle('active', tab === 'components');
|
|
1509
|
+
if (secPane) secPane.classList.toggle('active', tab === 'sections');
|
|
1510
|
+
var inp = document.getElementById('comp-search');
|
|
1511
|
+
if (inp) inp.placeholder = tab === 'sections' ? 'Search sections\u2026' : 'Search components\u2026';
|
|
1512
|
+
renderSidebar(inp ? inp.value : '');
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1403
1515
|
// \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
|
|
1404
1516
|
function toggleAcc(name) {
|
|
1405
1517
|
var sec = document.getElementById('acc-' + name);
|
|
@@ -1522,42 +1634,20 @@ function logChange(selector, inputId, value, targetEl, originalValue) {
|
|
|
1522
1634
|
: (originalValue != null ? originalValue : '');
|
|
1523
1635
|
var entry = {
|
|
1524
1636
|
selector: selector, inputId: inputId, label: meta.label,
|
|
1525
|
-
cssProp: meta.cssProp, value: value, targetEl: targetEl, originalValue: orig
|
|
1637
|
+
cssProp: meta.cssProp, value: value, targetEl: targetEl, originalValue: orig, vveTs: nextHistoryTimestamp()
|
|
1526
1638
|
};
|
|
1527
1639
|
if (idx >= 0) { stateChanges[idx] = entry; } else { stateChanges.push(entry); }
|
|
1528
1640
|
}
|
|
1529
1641
|
if (currentMainTab === 'states') renderStatesTab();
|
|
1642
|
+
if (currentMainTab === 'history') renderHistoryTab();
|
|
1530
1643
|
commitStateChangesForActiveVariation();
|
|
1531
1644
|
recomputeEditorDirty();
|
|
1532
1645
|
}
|
|
1533
1646
|
|
|
1534
1647
|
function renderStatesTab() {
|
|
1535
1648
|
var container = document.getElementById('states-list');
|
|
1536
|
-
if (!
|
|
1537
|
-
|
|
1538
|
-
return;
|
|
1539
|
-
}
|
|
1540
|
-
// Group by selector
|
|
1541
|
-
var groups = {};
|
|
1542
|
-
var order = [];
|
|
1543
|
-
stateChanges.forEach(function(c) {
|
|
1544
|
-
if (!groups[c.selector]) { groups[c.selector] = []; order.push(c.selector); }
|
|
1545
|
-
groups[c.selector].push(c);
|
|
1546
|
-
});
|
|
1547
|
-
var html = '<button id="states-clear" onclick="clearAllStates()"><i class="bi bi-trash3"></i> Clear all changes</button>';
|
|
1548
|
-
order.forEach(function(sel) {
|
|
1549
|
-
html += '<div class="state-group"><div class="state-group-sel">'+esc(sel)+'</div>';
|
|
1550
|
-
groups[sel].forEach(function(c) {
|
|
1551
|
-
var idx = stateChanges.indexOf(c);
|
|
1552
|
-
html += '<div class="state-item">' +
|
|
1553
|
-
'<span class="state-item-label">'+esc(c.label)+'</span>' +
|
|
1554
|
-
'<span class="state-item-val" title="'+esc(c.value)+'">'+esc(c.value)+'</span>' +
|
|
1555
|
-
'<button class="state-remove" title="Remove this change" onclick="removeStateChange('+idx+')">✕</button>' +
|
|
1556
|
-
'</div>';
|
|
1557
|
-
});
|
|
1558
|
-
html += '</div>';
|
|
1559
|
-
});
|
|
1560
|
-
container.innerHTML = html;
|
|
1649
|
+
if (!container) return;
|
|
1650
|
+
container.innerHTML = '';
|
|
1561
1651
|
}
|
|
1562
1652
|
|
|
1563
1653
|
// Resolve a live DOM element for a state-change entry.
|
|
@@ -1636,7 +1726,9 @@ function removeStateChange(idx) {
|
|
|
1636
1726
|
stateChanges.splice(idx, 1);
|
|
1637
1727
|
commitStateChangesForActiveVariation();
|
|
1638
1728
|
renderStatesTab();
|
|
1729
|
+
if (currentMainTab === 'history') renderHistoryTab();
|
|
1639
1730
|
recomputeEditorDirty();
|
|
1731
|
+
scheduleDomTreeRefresh();
|
|
1640
1732
|
}
|
|
1641
1733
|
|
|
1642
1734
|
function clearAllStates() {
|
|
@@ -1647,7 +1739,9 @@ function clearAllStates() {
|
|
|
1647
1739
|
stateChanges = [];
|
|
1648
1740
|
commitStateChangesForActiveVariation();
|
|
1649
1741
|
renderStatesTab();
|
|
1742
|
+
if (currentMainTab === 'history') renderHistoryTab();
|
|
1650
1743
|
recomputeEditorDirty();
|
|
1744
|
+
scheduleDomTreeRefresh();
|
|
1651
1745
|
}
|
|
1652
1746
|
|
|
1653
1747
|
// \u2500\u2500 History tab (saved changesets from DB for active variation) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
@@ -1820,61 +1914,169 @@ function historyEntryValuePreview(entry) {
|
|
|
1820
1914
|
return '';
|
|
1821
1915
|
}
|
|
1822
1916
|
|
|
1917
|
+
function getHistoryTimestampValue(raw, fallback) {
|
|
1918
|
+
var n = Number(raw);
|
|
1919
|
+
if (Number.isFinite(n) && n > 0) return n;
|
|
1920
|
+
return fallback;
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
function historyTimestampForChangeset(entry, idx) {
|
|
1924
|
+
var base = idx + 1;
|
|
1925
|
+
if (!entry) return base;
|
|
1926
|
+
return getHistoryTimestampValue(
|
|
1927
|
+
entry.vveTs != null ? entry.vveTs : (entry.timestamp != null ? entry.timestamp : entry.ts),
|
|
1928
|
+
base,
|
|
1929
|
+
);
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
function historyTimestampForStateChange(change, idx) {
|
|
1933
|
+
return getHistoryTimestampValue(change && change.vveTs, idx + 1);
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
function formatHistoryTimestamp(ts) {
|
|
1937
|
+
if (!Number.isFinite(ts) || ts <= 0) return '';
|
|
1938
|
+
var ms = ts > 9999999999999 ? Math.floor(ts / 1000) : ts;
|
|
1939
|
+
var d = new Date(ms);
|
|
1940
|
+
if (isNaN(d.getTime())) return '';
|
|
1941
|
+
return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
function formatHistoryRelativeTime(ts) {
|
|
1945
|
+
if (!Number.isFinite(ts) || ts <= 0) return '';
|
|
1946
|
+
var ms = ts > 9999999999999 ? Math.floor(ts / 1000) : ts;
|
|
1947
|
+
var diff = Math.max(0, Date.now() - ms);
|
|
1948
|
+
var sec = Math.floor(diff / 1000);
|
|
1949
|
+
if (sec < 5) return 'just now';
|
|
1950
|
+
if (sec < 60) return sec + ' seconds ago';
|
|
1951
|
+
var min = Math.floor(sec / 60);
|
|
1952
|
+
if (min < 60) return min + ' minute' + (min === 1 ? '' : 's') + ' ago';
|
|
1953
|
+
var hr = Math.floor(min / 60);
|
|
1954
|
+
if (hr < 24) return hr + ' hour' + (hr === 1 ? '' : 's') + ' ago';
|
|
1955
|
+
var day = Math.floor(hr / 24);
|
|
1956
|
+
return day + ' day' + (day === 1 ? '' : 's') + ' ago';
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
function getUnifiedHistoryItems() {
|
|
1960
|
+
var out = [];
|
|
1961
|
+
var v = getActiveVariationForHistory();
|
|
1962
|
+
var saved = v ? parseVariationChangesets(v) : [];
|
|
1963
|
+
for (var i = 0; i < saved.length; i++) {
|
|
1964
|
+
var e = saved[i];
|
|
1965
|
+
out.push({
|
|
1966
|
+
source: 'saved',
|
|
1967
|
+
idx: i,
|
|
1968
|
+
selector: (e && e.selector) || '(unknown)',
|
|
1969
|
+
label: historyEntryTypeLabel(e),
|
|
1970
|
+
value: historyEntryValuePreview(e),
|
|
1971
|
+
ts: historyTimestampForChangeset(e, i),
|
|
1972
|
+
tsLabel: formatHistoryTimestamp(historyTimestampForChangeset(e, i)),
|
|
1973
|
+
actor: 'Saved changeset',
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
1976
|
+
var live = stateChanges || [];
|
|
1977
|
+
for (var j = 0; j < live.length; j++) {
|
|
1978
|
+
var c = live[j];
|
|
1979
|
+
if (!c) continue;
|
|
1980
|
+
var ts = historyTimestampForStateChange(c, j + saved.length);
|
|
1981
|
+
out.push({
|
|
1982
|
+
source: 'live',
|
|
1983
|
+
idx: j,
|
|
1984
|
+
selector: c.selector || '(unknown)',
|
|
1985
|
+
label: c.label || 'Live change',
|
|
1986
|
+
value: c.value != null ? String(c.value).slice(0, 120) : '',
|
|
1987
|
+
ts: ts,
|
|
1988
|
+
tsLabel: formatHistoryTimestamp(ts),
|
|
1989
|
+
actor: 'You',
|
|
1990
|
+
});
|
|
1991
|
+
}
|
|
1992
|
+
out.sort(function(a, b) {
|
|
1993
|
+
if (b.ts !== a.ts) return b.ts - a.ts;
|
|
1994
|
+
if (a.source !== b.source) return a.source === 'live' ? -1 : 1;
|
|
1995
|
+
return b.idx - a.idx;
|
|
1996
|
+
});
|
|
1997
|
+
return out;
|
|
1998
|
+
}
|
|
1999
|
+
|
|
1823
2000
|
function renderHistoryTab() {
|
|
1824
2001
|
var container = document.getElementById('history-list');
|
|
1825
2002
|
if (!container) return;
|
|
1826
|
-
var
|
|
1827
|
-
|
|
1828
|
-
if (!arr.length) {
|
|
2003
|
+
var items = getUnifiedHistoryItems();
|
|
2004
|
+
if (!items.length) {
|
|
1829
2005
|
container.innerHTML =
|
|
1830
|
-
'<div class="states-empty"><i class="bi bi-clock-history"></i>No
|
|
2006
|
+
'<div class="states-empty"><i class="bi bi-clock-history"></i>No changes yet</div>';
|
|
1831
2007
|
return;
|
|
1832
2008
|
}
|
|
1833
|
-
var groups = {};
|
|
1834
|
-
var order = [];
|
|
1835
|
-
for (var gi = 0; gi < arr.length; gi++) {
|
|
1836
|
-
var entry = arr[gi];
|
|
1837
|
-
var sel = entry.selector || '(unknown)';
|
|
1838
|
-
if (!groups[sel]) {
|
|
1839
|
-
groups[sel] = [];
|
|
1840
|
-
order.push(sel);
|
|
1841
|
-
}
|
|
1842
|
-
groups[sel].push({ entry: entry, idx: gi });
|
|
1843
|
-
}
|
|
1844
2009
|
var html =
|
|
1845
|
-
'<button type="button" id="history-clear" onclick="
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
2010
|
+
'<button type="button" id="history-clear" onclick="clearAllUnifiedHistory()"><i class="bi bi-trash3"></i> Clear all changes</button>';
|
|
2011
|
+
html += '<div class="history-timeline">';
|
|
2012
|
+
for (var i = 0; i < items.length; i++) {
|
|
2013
|
+
var it = items[i];
|
|
2014
|
+
var title = 'Edit - ' + (it.label || 'Change');
|
|
2015
|
+
var avatarLabel = it.source === 'live' ? 'Y' : 'S';
|
|
2016
|
+
var timeText = formatHistoryRelativeTime(it.ts) || (it.tsLabel || '');
|
|
2017
|
+
html +=
|
|
2018
|
+
'<div class="history-item" role="button" tabindex="0" title="Jump to element in iframe" onclick="focusHistoryItem("' +
|
|
2019
|
+
esc(it.source) +
|
|
2020
|
+
'",' +
|
|
2021
|
+
it.idx +
|
|
2022
|
+
')">' +
|
|
2023
|
+
'<span class="history-dot"></span>' +
|
|
2024
|
+
'<div class="history-card">' +
|
|
2025
|
+
'<div class="history-title">' + esc(title) + '</div>' +
|
|
2026
|
+
'<div class="history-meta">' +
|
|
2027
|
+
'<span class="history-avatar">' + esc(avatarLabel) + '</span>' +
|
|
2028
|
+
'<span>' + esc(it.actor || 'Editor') + '</span>' +
|
|
2029
|
+
'</div>' +
|
|
2030
|
+
'<div class="history-time">' + esc(timeText || 'n/a') + '</div>' +
|
|
2031
|
+
'</div>' +
|
|
2032
|
+
'<button type="button" class="state-remove history-remove" title="Remove this change" onclick="removeHistoryItem("' +
|
|
2033
|
+
esc(it.source) +
|
|
2034
|
+
'",' +
|
|
2035
|
+
it.idx +
|
|
2036
|
+
', event)">✕</button>' +
|
|
2037
|
+
'</div>';
|
|
2038
|
+
}
|
|
2039
|
+
html += '</div>';
|
|
1875
2040
|
container.innerHTML = html;
|
|
1876
2041
|
}
|
|
1877
2042
|
|
|
2043
|
+
function focusHistoryItem(source, idx) {
|
|
2044
|
+
if (source === 'live') {
|
|
2045
|
+
var change = stateChanges[idx];
|
|
2046
|
+
if (!change || !change.selector) return;
|
|
2047
|
+
try {
|
|
2048
|
+
var iframe = document.getElementById('iframeId');
|
|
2049
|
+
var iframeDoc = iframe && iframe.contentDocument;
|
|
2050
|
+
if (!iframeDoc) return;
|
|
2051
|
+
var el = querySelectorResolved(iframeDoc, change.selector);
|
|
2052
|
+
if (!el) return;
|
|
2053
|
+
selectElement(el);
|
|
2054
|
+
try {
|
|
2055
|
+
el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
|
|
2056
|
+
} catch(_) {
|
|
2057
|
+
el.scrollIntoView();
|
|
2058
|
+
}
|
|
2059
|
+
} catch(_) {}
|
|
2060
|
+
return;
|
|
2061
|
+
}
|
|
2062
|
+
focusHistoryChangeset(idx);
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
function removeHistoryItem(source, idx, evt) {
|
|
2066
|
+
if (source === 'live') {
|
|
2067
|
+
if (evt && evt.stopPropagation) evt.stopPropagation();
|
|
2068
|
+
removeStateChange(idx);
|
|
2069
|
+
if (currentMainTab === 'history') renderHistoryTab();
|
|
2070
|
+
return;
|
|
2071
|
+
}
|
|
2072
|
+
removeHistoryChangeset(idx, evt);
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
function getLatestHistoryUndoTarget() {
|
|
2076
|
+
var list = getUnifiedHistoryItems();
|
|
2077
|
+
return list.length ? list[0] : null;
|
|
2078
|
+
}
|
|
2079
|
+
|
|
1878
2080
|
function changesetListHasStructural(arr) {
|
|
1879
2081
|
if (!arr || !arr.length) return false;
|
|
1880
2082
|
for (var i = 0; i < arr.length; i++) {
|
|
@@ -1986,6 +2188,12 @@ function clearAllHistoryChangesets() {
|
|
|
1986
2188
|
softReloadEditorIframe();
|
|
1987
2189
|
}
|
|
1988
2190
|
|
|
2191
|
+
function clearAllUnifiedHistory() {
|
|
2192
|
+
clearAllStates();
|
|
2193
|
+
clearAllHistoryChangesets();
|
|
2194
|
+
if (currentMainTab === 'history') renderHistoryTab();
|
|
2195
|
+
}
|
|
2196
|
+
|
|
1989
2197
|
// \u2500\u2500 Persisted active variation (survives iframe / full page reload) \u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1990
2198
|
/** All Visual Editor iframe keys in localStorage use this prefix \u2014 cleared on close. */
|
|
1991
2199
|
var VVE_LOCAL_STORAGE_PREFIX = 'vve:';
|
|
@@ -2066,7 +2274,8 @@ function handleLoadExperiment(data) {
|
|
|
2066
2274
|
return;
|
|
2067
2275
|
}
|
|
2068
2276
|
var proxyUrl = '/api/conversion-proxy?password=' + encodeURIComponent(data.editorPassword || '') +
|
|
2069
|
-
'&url=' + encodeURIComponent(pageUrl)
|
|
2277
|
+
'&url=' + encodeURIComponent(pageUrl) +
|
|
2278
|
+
'&strictObserverFreeze=' + encodeURIComponent(data && data.strictObserverFreeze ? '1' : '0');
|
|
2070
2279
|
|
|
2071
2280
|
// Parent often re-posts load-experiment when React re-renders (new object identity) or
|
|
2072
2281
|
// after mutations-changed. Reloading the iframe again wipes variant changesets mid-session.
|
|
@@ -2338,7 +2547,7 @@ function runConsistencyReconcile() {
|
|
|
2338
2547
|
var doc = iframe && iframe.contentDocument;
|
|
2339
2548
|
if (!doc || !doc.body) return;
|
|
2340
2549
|
var variation = variations.find(function(v) { return v._id === activeVarId; });
|
|
2341
|
-
var cs =
|
|
2550
|
+
var cs = buildPersistedChainSetsForVariation(variation);
|
|
2342
2551
|
if (!cs.length || changesetsHaveBodySnapshot(cs)) return;
|
|
2343
2552
|
var granular = filterGranularChangesetEntries(cs);
|
|
2344
2553
|
var unresolved = countUnresolvedGranularSelectors(doc, granular);
|
|
@@ -2598,6 +2807,7 @@ function mergeGranularChainSets(baseList, overlayList) {
|
|
|
2598
2807
|
function appendSessionStructuralChainRow(varId, row) {
|
|
2599
2808
|
if (!varId || !row) return;
|
|
2600
2809
|
if (!sessionStructuralChainRowsByVarId[varId]) sessionStructuralChainRowsByVarId[varId] = [];
|
|
2810
|
+
if (row.vveTs == null) row.vveTs = nextHistoryTimestamp();
|
|
2601
2811
|
sessionStructuralChainRowsByVarId[varId].push(row);
|
|
2602
2812
|
}
|
|
2603
2813
|
|
|
@@ -2605,33 +2815,33 @@ function appendSessionStructuralChainRow(varId, row) {
|
|
|
2605
2815
|
function stateChangeToChainSet(c) {
|
|
2606
2816
|
if (!c || !c.selector) return null;
|
|
2607
2817
|
if (c.cssProp) {
|
|
2608
|
-
return { selector: c.selector, type: 'style', property: c.cssProp, value: c.value };
|
|
2818
|
+
return { selector: c.selector, type: 'style', property: c.cssProp, value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2609
2819
|
}
|
|
2610
2820
|
switch (c.inputId) {
|
|
2611
2821
|
case 'pp-text':
|
|
2612
|
-
return { selector: c.selector, type: 'content', value: c.value };
|
|
2822
|
+
return { selector: c.selector, type: 'content', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2613
2823
|
case 'pp-html':
|
|
2614
|
-
return { selector: c.selector, type: 'content', html: c.value };
|
|
2824
|
+
return { selector: c.selector, type: 'content', html: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2615
2825
|
case 'pp-cls':
|
|
2616
|
-
return { selector: c.selector, type: 'attribute', attribute: 'class', value: c.value };
|
|
2826
|
+
return { selector: c.selector, type: 'attribute', attribute: 'class', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2617
2827
|
case 'pp-id':
|
|
2618
|
-
return { selector: c.selector, type: 'attribute', attribute: 'id', value: c.value };
|
|
2828
|
+
return { selector: c.selector, type: 'attribute', attribute: 'id', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2619
2829
|
case 'pp-href':
|
|
2620
|
-
return { selector: c.selector, type: 'attribute', attribute: 'href', value: c.value };
|
|
2830
|
+
return { selector: c.selector, type: 'attribute', attribute: 'href', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2621
2831
|
case 'pp-target':
|
|
2622
|
-
return { selector: c.selector, type: 'attribute', attribute: 'target', value: c.value };
|
|
2832
|
+
return { selector: c.selector, type: 'attribute', attribute: 'target', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2623
2833
|
case 'pp-src':
|
|
2624
|
-
return { selector: c.selector, type: 'attribute', attribute: 'src', value: c.value };
|
|
2834
|
+
return { selector: c.selector, type: 'attribute', attribute: 'src', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2625
2835
|
case 'pp-alt':
|
|
2626
|
-
return { selector: c.selector, type: 'attribute', attribute: 'alt', value: c.value };
|
|
2836
|
+
return { selector: c.selector, type: 'attribute', attribute: 'alt', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2627
2837
|
case 'pp-ph':
|
|
2628
|
-
return { selector: c.selector, type: 'attribute', attribute: 'placeholder', value: c.value };
|
|
2838
|
+
return { selector: c.selector, type: 'attribute', attribute: 'placeholder', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2629
2839
|
case 'pp-css':
|
|
2630
|
-
return { selector: c.selector, type: 'attribute', attribute: 'style', value: c.value };
|
|
2840
|
+
return { selector: c.selector, type: 'attribute', attribute: 'style', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2631
2841
|
case 'pp-mob-css':
|
|
2632
|
-
return { selector: c.selector, type: 'attribute', attribute: 'data-mobile-css', value: c.value };
|
|
2842
|
+
return { selector: c.selector, type: 'attribute', attribute: 'data-mobile-css', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2633
2843
|
case 'pp-tab-css':
|
|
2634
|
-
return { selector: c.selector, type: 'attribute', attribute: 'data-tablet-css', value: c.value };
|
|
2844
|
+
return { selector: c.selector, type: 'attribute', attribute: 'data-tablet-css', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
2635
2845
|
default:
|
|
2636
2846
|
return null;
|
|
2637
2847
|
}
|
|
@@ -2919,7 +3129,7 @@ function applyActiveVariationHtml() {
|
|
|
2919
3129
|
if (!iframeDoc || !iframeDoc.body) return;
|
|
2920
3130
|
|
|
2921
3131
|
var variation = variations.find(function(v) { return v._id === activeVarId; });
|
|
2922
|
-
var cs =
|
|
3132
|
+
var cs = buildPersistedChainSetsForVariation(variation);
|
|
2923
3133
|
refreshPersistentChangesetStyleTagForActiveVariation();
|
|
2924
3134
|
|
|
2925
3135
|
beginSuppressIframeMutationDirty();
|
|
@@ -2977,7 +3187,7 @@ function applyVariationGranularOnly(iframeDoc) {
|
|
|
2977
3187
|
if (!activeVarId || !iframeDoc || !iframeDoc.body) return;
|
|
2978
3188
|
if (varHtmlCache[activeVarId]) return;
|
|
2979
3189
|
var variation = variations.find(function(v) { return v._id === activeVarId; });
|
|
2980
|
-
var cs =
|
|
3190
|
+
var cs = buildPersistedChainSetsForVariation(variation);
|
|
2981
3191
|
if (!cs.length || changesetsHaveBodySnapshot(cs)) return;
|
|
2982
3192
|
beginSuppressIframeMutationDirty();
|
|
2983
3193
|
try {
|
|
@@ -2996,7 +3206,7 @@ function reapplyActiveVariationGranular(iframeDoc) {
|
|
|
2996
3206
|
if (!activeVarId || !iframeDoc || !iframeDoc.body) return;
|
|
2997
3207
|
if (varHtmlCache[activeVarId]) return;
|
|
2998
3208
|
var variation = variations.find(function(v) { return v._id === activeVarId; });
|
|
2999
|
-
var cs =
|
|
3209
|
+
var cs = buildPersistedChainSetsForVariation(variation);
|
|
3000
3210
|
if (!cs.length || changesetsHaveBodySnapshot(cs)) return;
|
|
3001
3211
|
beginSuppressIframeMutationDirty();
|
|
3002
3212
|
try {
|
|
@@ -3040,7 +3250,7 @@ function startIframeContentApplyWatcher(navGen, prevDocRef) {
|
|
|
3040
3250
|
|
|
3041
3251
|
if (doc.readyState === 'loading') {
|
|
3042
3252
|
var variation = variations.find(function(v) { return v._id === activeVarId; });
|
|
3043
|
-
var cs0 =
|
|
3253
|
+
var cs0 = buildPersistedChainSetsForVariation(variation);
|
|
3044
3254
|
if (!cs0.length || changesetsHaveBodySnapshot(cs0)) return;
|
|
3045
3255
|
var granular = filterGranularChangesetEntries(cs0);
|
|
3046
3256
|
if (!granular.length) return;
|
|
@@ -3086,8 +3296,9 @@ function selectElement(el) {
|
|
|
3086
3296
|
document.getElementById('no-sel').style.display = 'none';
|
|
3087
3297
|
renderRightPanel(el);
|
|
3088
3298
|
updateSelectionToolbar();
|
|
3089
|
-
if (currentLeftTab === 'elements') {
|
|
3090
|
-
var
|
|
3299
|
+
if (currentLeftTab === 'elements' || currentLeftTab === 'dom-tree') {
|
|
3300
|
+
var treeRootId = currentLeftTab === 'elements' ? 'elements-root' : 'dom-tree-root';
|
|
3301
|
+
var dr = document.getElementById(treeRootId);
|
|
3091
3302
|
if (dr && dr.querySelector('.dt-row')) syncDomTreeSelection();
|
|
3092
3303
|
else scheduleDomTreeRefresh();
|
|
3093
3304
|
}
|
|
@@ -3350,27 +3561,32 @@ function deleteSelectedEl() {
|
|
|
3350
3561
|
}
|
|
3351
3562
|
|
|
3352
3563
|
function syncDomTreeSelection() {
|
|
3353
|
-
var
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
rows
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3564
|
+
var roots = ['dom-tree-root', 'elements-root'];
|
|
3565
|
+
for (var r = 0; r < roots.length; r++) {
|
|
3566
|
+
var root = document.getElementById(roots[r]);
|
|
3567
|
+
if (!root) continue;
|
|
3568
|
+
var rows = root.querySelectorAll('.dt-row');
|
|
3569
|
+
for (var i = 0; i < rows.length; i++) {
|
|
3570
|
+
rows[i].classList.toggle('dt-selected', !!(selectedEl && rows[i]._dtEl === selectedEl));
|
|
3571
|
+
}
|
|
3572
|
+
if (!selectedEl) continue;
|
|
3573
|
+
var found = null;
|
|
3574
|
+
for (var j = 0; j < rows.length; j++) {
|
|
3575
|
+
if (rows[j]._dtEl === selectedEl) { found = rows[j]; break; }
|
|
3576
|
+
}
|
|
3577
|
+
if (found) found.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
3363
3578
|
}
|
|
3364
|
-
if (found) found.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
3365
3579
|
}
|
|
3366
3580
|
|
|
3367
3581
|
function scheduleDomTreeRefresh() {
|
|
3368
|
-
if (currentLeftTab !== 'elements') return;
|
|
3582
|
+
if (currentLeftTab !== 'elements' && currentLeftTab !== 'dom-tree') return;
|
|
3369
3583
|
if (domTreeRefreshTimer) clearTimeout(domTreeRefreshTimer);
|
|
3370
3584
|
domTreeRefreshTimer = setTimeout(function() {
|
|
3371
3585
|
domTreeRefreshTimer = null;
|
|
3372
3586
|
var inp = document.getElementById('comp-search');
|
|
3373
|
-
|
|
3587
|
+
var q = inp ? inp.value : '';
|
|
3588
|
+
if (currentLeftTab === 'elements') renderElementsTree(q);
|
|
3589
|
+
else if (currentLeftTab === 'dom-tree') renderDomTree(q);
|
|
3374
3590
|
}, 150);
|
|
3375
3591
|
}
|
|
3376
3592
|
|
|
@@ -3393,6 +3609,129 @@ function domTreePathSegment(el) {
|
|
|
3393
3609
|
return tag + '[' + idx + ']';
|
|
3394
3610
|
}
|
|
3395
3611
|
|
|
3612
|
+
function renderElementsTree(filterRaw) {
|
|
3613
|
+
var filterText = (filterRaw || '').toLowerCase().trim();
|
|
3614
|
+
var root = document.getElementById('elements-root');
|
|
3615
|
+
if (!root) return;
|
|
3616
|
+
var iframe = document.getElementById('iframeId');
|
|
3617
|
+
var doc = iframe && iframe.contentDocument;
|
|
3618
|
+
if (!isIframeDomReady(iframe, doc)) {
|
|
3619
|
+
root.innerHTML = '<div class="dt-muted">Load a page to see the elements.</div>';
|
|
3620
|
+
return;
|
|
3621
|
+
}
|
|
3622
|
+
|
|
3623
|
+
function skippable(el) {
|
|
3624
|
+
return isDomTreeSkippableTagName(el.tagName);
|
|
3625
|
+
}
|
|
3626
|
+
|
|
3627
|
+
function nodeIcon(tag) {
|
|
3628
|
+
tag = (tag || '').toLowerCase();
|
|
3629
|
+
if (/^h[1-6]$/.test(tag)) return 'bi bi-type-h1';
|
|
3630
|
+
if (tag === 'a') return 'bi bi-link-45deg';
|
|
3631
|
+
if (tag === 'img') return 'bi bi-image';
|
|
3632
|
+
if (tag === 'section' || tag === 'main' || tag === 'article' || tag === 'header' || tag === 'footer' || tag === 'nav') return 'bi bi-layout-three-columns';
|
|
3633
|
+
if (tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea') return 'bi bi-ui-radios';
|
|
3634
|
+
if (tag === 'ul' || tag === 'ol') return 'bi bi-list-ul';
|
|
3635
|
+
if (tag === 'li') return 'bi bi-dot';
|
|
3636
|
+
if (tag === 'svg') return 'bi bi-bezier2';
|
|
3637
|
+
if (tag === 'p' || tag === 'span') return 'bi bi-text-left';
|
|
3638
|
+
return 'bi bi-square';
|
|
3639
|
+
}
|
|
3640
|
+
|
|
3641
|
+
function labelFor(el) {
|
|
3642
|
+
var tag = (el.tagName || '').toLowerCase();
|
|
3643
|
+
return tag.toUpperCase();
|
|
3644
|
+
}
|
|
3645
|
+
|
|
3646
|
+
function isListableNode(el) {
|
|
3647
|
+
if (!el || el.nodeType !== 1) return false;
|
|
3648
|
+
if (skippable(el)) return false;
|
|
3649
|
+
var tag = (el.tagName || '').toLowerCase();
|
|
3650
|
+
if (tag !== 'svg') {
|
|
3651
|
+
var p = el.parentElement;
|
|
3652
|
+
while (p) {
|
|
3653
|
+
if ((p.tagName || '').toLowerCase() === 'svg') return false;
|
|
3654
|
+
p = p.parentElement;
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
return true;
|
|
3658
|
+
}
|
|
3659
|
+
|
|
3660
|
+
var nodes = [];
|
|
3661
|
+
var i, cursor;
|
|
3662
|
+
try {
|
|
3663
|
+
cursor = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ELEMENT, null);
|
|
3664
|
+
} catch(_) {
|
|
3665
|
+
cursor = null;
|
|
3666
|
+
}
|
|
3667
|
+
if (cursor) {
|
|
3668
|
+
while (cursor.nextNode()) {
|
|
3669
|
+
var node = cursor.currentNode;
|
|
3670
|
+
if (isListableNode(node)) nodes.push(node);
|
|
3671
|
+
if (nodes.length > 4000) break;
|
|
3672
|
+
}
|
|
3673
|
+
} else {
|
|
3674
|
+
function collectFlat(el) {
|
|
3675
|
+
if (!el || !el.children) return;
|
|
3676
|
+
for (var j = 0; j < el.children.length; j++) {
|
|
3677
|
+
var c = el.children[j];
|
|
3678
|
+
if (!isListableNode(c)) continue;
|
|
3679
|
+
nodes.push(c);
|
|
3680
|
+
if (nodes.length > 4000) return;
|
|
3681
|
+
collectFlat(c);
|
|
3682
|
+
if (nodes.length > 4000) return;
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
collectFlat(doc.body);
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3688
|
+
root.innerHTML = '';
|
|
3689
|
+
for (i = 0; i < nodes.length; i++) {
|
|
3690
|
+
var el = nodes[i];
|
|
3691
|
+
var lblText = labelFor(el);
|
|
3692
|
+
if (filterText && lblText.toLowerCase().indexOf(filterText) < 0) continue;
|
|
3693
|
+
|
|
3694
|
+
var row = document.createElement('div');
|
|
3695
|
+
row.className = 'dt-row';
|
|
3696
|
+
row._dtEl = el;
|
|
3697
|
+
if (el === selectedEl) row.classList.add('dt-selected');
|
|
3698
|
+
row.style.paddingLeft = '4px';
|
|
3699
|
+
|
|
3700
|
+
var spacer = document.createElement('button');
|
|
3701
|
+
spacer.type = 'button';
|
|
3702
|
+
spacer.className = 'dt-chev dt-spacer';
|
|
3703
|
+
|
|
3704
|
+
var ico = document.createElement('div');
|
|
3705
|
+
ico.className = 'dt-ico';
|
|
3706
|
+
ico.innerHTML = '<i class="' + nodeIcon(el.tagName) + '"></i>';
|
|
3707
|
+
|
|
3708
|
+
var lbl = document.createElement('div');
|
|
3709
|
+
lbl.className = 'dt-lbl';
|
|
3710
|
+
lbl.textContent = lblText;
|
|
3711
|
+
lbl.title = buildSelector(el);
|
|
3712
|
+
|
|
3713
|
+
row.appendChild(spacer);
|
|
3714
|
+
row.appendChild(ico);
|
|
3715
|
+
row.appendChild(lbl);
|
|
3716
|
+
row.onclick = (function(targetEl) {
|
|
3717
|
+
return function() { selectElementFromTree(targetEl); };
|
|
3718
|
+
})(el);
|
|
3719
|
+
row.onmouseenter = (function(targetEl) {
|
|
3720
|
+
return function() { setTreeHoverHighlight(targetEl); };
|
|
3721
|
+
})(el);
|
|
3722
|
+
root.appendChild(row);
|
|
3723
|
+
}
|
|
3724
|
+
|
|
3725
|
+
if (!root.querySelector('.dt-row')) {
|
|
3726
|
+
root.innerHTML = filterText
|
|
3727
|
+
? '<div class="dt-muted">No elements match your search.</div>'
|
|
3728
|
+
: '<div class="dt-muted">No elements found.</div>';
|
|
3729
|
+
}
|
|
3730
|
+
root.onmouseleave = function() {
|
|
3731
|
+
clearTreeHoverHighlight();
|
|
3732
|
+
};
|
|
3733
|
+
}
|
|
3734
|
+
|
|
3396
3735
|
function renderDomTree(filterRaw) {
|
|
3397
3736
|
var filterText = (filterRaw || '').toLowerCase().trim();
|
|
3398
3737
|
var root = document.getElementById('dom-tree-root');
|
|
@@ -4131,6 +4470,20 @@ function recordReorderAfterDrag(movedEl) {
|
|
|
4131
4470
|
}
|
|
4132
4471
|
}
|
|
4133
4472
|
|
|
4473
|
+
function moveSelectedElByDirection(direction) {
|
|
4474
|
+
if (!selectedEl || !selectedEl.parentElement) return;
|
|
4475
|
+
var p = selectedEl.parentElement;
|
|
4476
|
+
var sibling = direction < 0 ? selectedEl.previousElementSibling : selectedEl.nextElementSibling;
|
|
4477
|
+
if (!sibling) return;
|
|
4478
|
+
if (direction < 0) p.insertBefore(selectedEl, sibling);
|
|
4479
|
+
else p.insertBefore(sibling, selectedEl);
|
|
4480
|
+
recordReorderAfterDrag(selectedEl);
|
|
4481
|
+
saveCurrentVariationHtml();
|
|
4482
|
+
recomputeEditorDirty();
|
|
4483
|
+
scheduleDomTreeRefresh();
|
|
4484
|
+
updateSelectionToolbar();
|
|
4485
|
+
}
|
|
4486
|
+
|
|
4134
4487
|
function attachDragReposition() {
|
|
4135
4488
|
try {
|
|
4136
4489
|
var iframe = document.getElementById('iframeId');
|
|
@@ -4317,7 +4670,9 @@ function syncIframeInteractions(reason) {
|
|
|
4317
4670
|
scheduleConsistencyReconcile();
|
|
4318
4671
|
bindSelectionToolbarScroll();
|
|
4319
4672
|
var inp = document.getElementById('comp-search');
|
|
4320
|
-
|
|
4673
|
+
var q = inp ? inp.value : '';
|
|
4674
|
+
if (currentLeftTab === 'elements') renderElementsTree(q);
|
|
4675
|
+
else if (currentLeftTab === 'dom-tree') renderDomTree(q);
|
|
4321
4676
|
updateSelectionToolbar();
|
|
4322
4677
|
recomputeEditorDirty();
|
|
4323
4678
|
} catch(_) {}
|
|
@@ -4481,8 +4836,11 @@ function renderSidebar(filter) {
|
|
|
4481
4836
|
}
|
|
4482
4837
|
|
|
4483
4838
|
document.getElementById('comp-search').addEventListener('input', function() {
|
|
4484
|
-
if (currentLeftTab === 'elements')
|
|
4485
|
-
else
|
|
4839
|
+
if (currentLeftTab === 'elements') renderElementsTree(this.value);
|
|
4840
|
+
else if (currentLeftTab === 'dom-tree') renderDomTree(this.value);
|
|
4841
|
+
if (currentSectionComponentsTab === 'components' || currentSectionComponentsTab === 'sections') {
|
|
4842
|
+
renderSidebar(this.value);
|
|
4843
|
+
}
|
|
4486
4844
|
});
|
|
4487
4845
|
|
|
4488
4846
|
// \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
|
|
@@ -4548,19 +4906,11 @@ document.addEventListener('keydown', function(e) {
|
|
|
4548
4906
|
var k = (e.key || '').toLowerCase();
|
|
4549
4907
|
if (meta && !e.shiftKey && k === 'z') {
|
|
4550
4908
|
e.preventDefault();
|
|
4551
|
-
|
|
4552
|
-
Vvveb.Undo.undo();
|
|
4553
|
-
saveCurrentVariationHtml();
|
|
4554
|
-
recomputeEditorDirty();
|
|
4555
|
-
}
|
|
4909
|
+
runEditorUndo();
|
|
4556
4910
|
}
|
|
4557
4911
|
if (meta && e.shiftKey && k === 'z') {
|
|
4558
4912
|
e.preventDefault();
|
|
4559
|
-
|
|
4560
|
-
Vvveb.Undo.redo();
|
|
4561
|
-
saveCurrentVariationHtml();
|
|
4562
|
-
recomputeEditorDirty();
|
|
4563
|
-
}
|
|
4913
|
+
runEditorRedo();
|
|
4564
4914
|
}
|
|
4565
4915
|
if (meta && e.key === 's') { e.preventDefault(); handleSave(); }
|
|
4566
4916
|
if (e.key === 'Escape') {
|
|
@@ -4580,8 +4930,39 @@ document.addEventListener('keydown', function(e) {
|
|
|
4580
4930
|
if (selectedEl) deselectElement();
|
|
4581
4931
|
}
|
|
4582
4932
|
});
|
|
4583
|
-
|
|
4584
|
-
|
|
4933
|
+
function runEditorUndo() {
|
|
4934
|
+
var target = getLatestHistoryUndoTarget();
|
|
4935
|
+
if (target) {
|
|
4936
|
+
removeHistoryItem(target.source, target.idx);
|
|
4937
|
+
return;
|
|
4938
|
+
}
|
|
4939
|
+
if (!(typeof Vvveb !== 'undefined' && Vvveb.Undo)) return;
|
|
4940
|
+
Vvveb.Undo.undo();
|
|
4941
|
+
saveCurrentVariationHtml();
|
|
4942
|
+
recomputeEditorDirty();
|
|
4943
|
+
scheduleDomTreeRefresh();
|
|
4944
|
+
updateSelectionToolbar();
|
|
4945
|
+
}
|
|
4946
|
+
|
|
4947
|
+
function runEditorRedo() {
|
|
4948
|
+
if (!(typeof Vvveb !== 'undefined' && Vvveb.Undo)) return;
|
|
4949
|
+
Vvveb.Undo.redo();
|
|
4950
|
+
saveCurrentVariationHtml();
|
|
4951
|
+
recomputeEditorDirty();
|
|
4952
|
+
scheduleDomTreeRefresh();
|
|
4953
|
+
updateSelectionToolbar();
|
|
4954
|
+
}
|
|
4955
|
+
|
|
4956
|
+
document.getElementById('btn-undo').addEventListener('click', function(e) {
|
|
4957
|
+
e.preventDefault();
|
|
4958
|
+
e.stopPropagation();
|
|
4959
|
+
runEditorUndo();
|
|
4960
|
+
});
|
|
4961
|
+
document.getElementById('btn-redo').addEventListener('click', function(e) {
|
|
4962
|
+
e.preventDefault();
|
|
4963
|
+
e.stopPropagation();
|
|
4964
|
+
runEditorRedo();
|
|
4965
|
+
});
|
|
4585
4966
|
|
|
4586
4967
|
function layoutLoadingTooltip(host) {
|
|
4587
4968
|
var tip = host.querySelector('.ve-pl-tooltip');
|
|
@@ -4657,8 +5038,8 @@ function registerCROSections() {
|
|
|
4657
5038
|
|
|
4658
5039
|
window.addEventListener('load', function() {
|
|
4659
5040
|
registerCROSections();
|
|
4660
|
-
|
|
4661
|
-
|
|
5041
|
+
switchSectionComponentsTab(currentSectionComponentsTab);
|
|
5042
|
+
renderElementsTree(document.getElementById('comp-search').value);
|
|
4662
5043
|
vvvebReady = true;
|
|
4663
5044
|
bindLoadingTooltipPositioning();
|
|
4664
5045
|
|
|
@@ -4711,12 +5092,22 @@ window.addEventListener('load', function() {
|
|
|
4711
5092
|
syncIframeInteractions('iframe-load');
|
|
4712
5093
|
});
|
|
4713
5094
|
|
|
4714
|
-
document.getElementById('sf-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
5095
|
+
var sfMoveUp = document.getElementById('sf-move-up');
|
|
5096
|
+
if (sfMoveUp) {
|
|
5097
|
+
sfMoveUp.addEventListener('click', function(e) {
|
|
5098
|
+
e.preventDefault();
|
|
5099
|
+
e.stopPropagation();
|
|
5100
|
+
moveSelectedElByDirection(-1);
|
|
5101
|
+
});
|
|
5102
|
+
}
|
|
5103
|
+
var sfMoveDown = document.getElementById('sf-move-down');
|
|
5104
|
+
if (sfMoveDown) {
|
|
5105
|
+
sfMoveDown.addEventListener('click', function(e) {
|
|
5106
|
+
e.preventDefault();
|
|
5107
|
+
e.stopPropagation();
|
|
5108
|
+
moveSelectedElByDirection(1);
|
|
5109
|
+
});
|
|
5110
|
+
}
|
|
4720
5111
|
document.getElementById('sf-dup').addEventListener('click', function(e) {
|
|
4721
5112
|
e.preventDefault();
|
|
4722
5113
|
e.stopPropagation();
|
|
@@ -4762,6 +5153,7 @@ var getDefaultAnthropicApiKey = () => {
|
|
|
4762
5153
|
function createVisualEditorMiddleware(options) {
|
|
4763
5154
|
const anthropicApiKey = options?.anthropicApiKey || getDefaultAnthropicApiKey();
|
|
4764
5155
|
const enableGenerateTestApi = options?.enableGenerateTestApi ?? true;
|
|
5156
|
+
const strictObserverFreeze = options?.strictObserverFreeze === true;
|
|
4765
5157
|
const allowedFrameOrigins = options?.allowedFrameOrigins ?? ["*"];
|
|
4766
5158
|
function setFrameHeaders(req, res) {
|
|
4767
5159
|
res.removeHeader("X-Frame-Options");
|
|
@@ -4929,6 +5321,8 @@ function createVisualEditorMiddleware(options) {
|
|
|
4929
5321
|
const url = new URL(req.url || "", "http://localhost");
|
|
4930
5322
|
const targetUrl = url.searchParams.get("url");
|
|
4931
5323
|
const password = url.searchParams.get("password") || "";
|
|
5324
|
+
const strictFreezeParam = (url.searchParams.get("strictObserverFreeze") || "").toLowerCase();
|
|
5325
|
+
const strictObserverFreezeForRequest = strictFreezeParam === "1" || strictFreezeParam === "true" || strictFreezeParam === "yes" ? true : strictFreezeParam === "0" || strictFreezeParam === "false" || strictFreezeParam === "no" ? false : strictObserverFreeze;
|
|
4932
5326
|
if (!targetUrl) {
|
|
4933
5327
|
res.statusCode = 400;
|
|
4934
5328
|
res.end(JSON.stringify({ error: "Missing url parameter" }));
|
|
@@ -5066,6 +5460,7 @@ ${iframeAlwaysShowCssGuardScript}
|
|
|
5066
5460
|
var TARGET_ORIGIN=${JSON.stringify(origin)};
|
|
5067
5461
|
var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};
|
|
5068
5462
|
var PROXY_PASSWORD=${JSON.stringify(password)};
|
|
5463
|
+
var STRICT_OBSERVER_FREEZE=${JSON.stringify(strictObserverFreezeForRequest)};
|
|
5069
5464
|
window.__CONVERSION_EDITOR_ACTIVE__=true;
|
|
5070
5465
|
function isSkippable(raw){if(!raw||typeof raw!=="string")return true;return raw.startsWith("data:")||raw.startsWith("blob:")||raw.startsWith("javascript:")||raw.startsWith("#");}
|
|
5071
5466
|
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;}}
|
|
@@ -5085,6 +5480,9 @@ try{
|
|
|
5085
5480
|
var wrapped=function(list,obs){
|
|
5086
5481
|
try{
|
|
5087
5482
|
if(!window.__CONVERSION_EDITOR_ACTIVE__)return cb(list,obs);
|
|
5483
|
+
if(STRICT_OBSERVER_FREEZE){
|
|
5484
|
+
return;
|
|
5485
|
+
}
|
|
5088
5486
|
var now=Date.now();
|
|
5089
5487
|
if(now-last<120)return;
|
|
5090
5488
|
last=now;
|
|
@@ -5094,6 +5492,11 @@ try{
|
|
|
5094
5492
|
return new NativeMO(wrapped);
|
|
5095
5493
|
};
|
|
5096
5494
|
window.MutationObserver.prototype=NativeMO.prototype;
|
|
5495
|
+
try{
|
|
5496
|
+
if(STRICT_OBSERVER_FREEZE){
|
|
5497
|
+
console.info("[conversion-proxy] strict MutationObserver freeze active");
|
|
5498
|
+
}
|
|
5499
|
+
}catch(_){}
|
|
5097
5500
|
}
|
|
5098
5501
|
}catch(_){}
|
|
5099
5502
|
}catch(_){}})();</script>`;
|