@accelerated-agency/visual-editor 0.6.0 → 0.6.2
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/vite.cjs +338 -29
- package/dist/vite.js +338 -29
- package/package.json +1 -1
package/dist/vite.cjs
CHANGED
|
@@ -2194,10 +2194,13 @@ function simulateExperiment() {
|
|
|
2194
2194
|
variations[0];
|
|
2195
2195
|
}
|
|
2196
2196
|
var targetUrl =
|
|
2197
|
+
(test.metadata_1 && test.metadata_1.editor_url) ||
|
|
2197
2198
|
(Array.isArray(test.urltargeting) && test.urltargeting[0]) ||
|
|
2198
2199
|
test.pageUrl ||
|
|
2199
|
-
(test.metadata_1 && test.metadata_1.editor_url) ||
|
|
2200
2200
|
'';
|
|
2201
|
+
if (targetUrl && !/^https?:///i.test(String(targetUrl).trim())) {
|
|
2202
|
+
targetUrl = 'https://' + String(targetUrl).trim();
|
|
2203
|
+
}
|
|
2201
2204
|
var testId = resolveSimulationId(test, ['iid', 'experimentIid', 'experimentId', '_id', 'id']);
|
|
2202
2205
|
var variationId = resolveSimulationId(activeVariation, ['iid', 'platformIid', 'variationIid', '_id', 'id']);
|
|
2203
2206
|
if (testId === null || !activeVariation || variationId === null) {
|
|
@@ -3150,6 +3153,7 @@ var PROP_META = {
|
|
|
3150
3153
|
'pp-value': {label:'Value', cssProp:null},
|
|
3151
3154
|
'pp-text': {label:'Inner text', cssProp:null},
|
|
3152
3155
|
'pp-html': {label:'Inner HTML', cssProp:null},
|
|
3156
|
+
'pp-select-options': {label:'Options', cssProp:null},
|
|
3153
3157
|
'pp-mob-css': {label:'Mobile CSS', cssProp:null},
|
|
3154
3158
|
'pp-tab-css': {label:'Tablet CSS', cssProp:null},
|
|
3155
3159
|
};
|
|
@@ -3166,6 +3170,7 @@ function getOriginalValue(inputId, el) {
|
|
|
3166
3170
|
switch (inputId) {
|
|
3167
3171
|
case 'pp-text': return el.innerText || '';
|
|
3168
3172
|
case 'pp-html': return el.innerHTML || '';
|
|
3173
|
+
case 'pp-select-options': return getSelectOptionsText(el);
|
|
3169
3174
|
case 'pp-cls': return el.className || '';
|
|
3170
3175
|
case 'pp-id': return el.id || '';
|
|
3171
3176
|
case 'pp-href': return el.getAttribute('href') || '';
|
|
@@ -3315,6 +3320,7 @@ function revertChangeOnDom(change) {
|
|
|
3315
3320
|
switch (change.inputId) {
|
|
3316
3321
|
case 'pp-text': el.innerText = orig; break;
|
|
3317
3322
|
case 'pp-html': el.innerHTML = orig; break;
|
|
3323
|
+
case 'pp-select-options': applySelectOptionsFromText(el, orig); break;
|
|
3318
3324
|
case 'pp-cls': el.className = orig; break;
|
|
3319
3325
|
case 'pp-id': el.id = orig; break;
|
|
3320
3326
|
case 'pp-css': orig ? el.setAttribute('style', orig) : el.removeAttribute('style'); break;
|
|
@@ -4973,6 +4979,8 @@ function stateChangeToChainSet(c) {
|
|
|
4973
4979
|
return { selector: c.selector, type: 'content', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
4974
4980
|
case 'pp-html':
|
|
4975
4981
|
return { selector: c.selector, type: 'content', html: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
4982
|
+
case 'pp-select-options':
|
|
4983
|
+
return { selector: c.selector, type: 'content', html: selectOptionsTextToHtml(c.value), vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
4976
4984
|
case 'pp-cls':
|
|
4977
4985
|
return { selector: c.selector, type: 'attribute', attribute: 'class', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
4978
4986
|
case 'pp-id':
|
|
@@ -5586,6 +5594,10 @@ function setTreeHoverHighlight(el) {
|
|
|
5586
5594
|
}
|
|
5587
5595
|
|
|
5588
5596
|
function isTreeHoverOnlyClassMutation(mutation) {
|
|
5597
|
+
return isEditorChromeOnlyClassMutation(mutation);
|
|
5598
|
+
}
|
|
5599
|
+
|
|
5600
|
+
function isEditorChromeOnlyClassMutation(mutation) {
|
|
5589
5601
|
if (!mutation || mutation.type !== 'attributes' || mutation.attributeName !== 'class') return false;
|
|
5590
5602
|
var oldClass = String(mutation.oldValue || '');
|
|
5591
5603
|
var target = mutation.target;
|
|
@@ -5593,7 +5605,12 @@ function isTreeHoverOnlyClassMutation(mutation) {
|
|
|
5593
5605
|
try {
|
|
5594
5606
|
nextClass = target && typeof target.className === 'string' ? target.className : '';
|
|
5595
5607
|
} catch(_) {}
|
|
5596
|
-
|
|
5608
|
+
var combined = oldClass + ' ' + nextClass;
|
|
5609
|
+
return (
|
|
5610
|
+
combined.indexOf('vve-tree-hover') >= 0 ||
|
|
5611
|
+
combined.indexOf('vve-selected') >= 0 ||
|
|
5612
|
+
combined.indexOf('vve-dragging') >= 0
|
|
5613
|
+
);
|
|
5597
5614
|
}
|
|
5598
5615
|
|
|
5599
5616
|
function setDragHandleActive(on) {
|
|
@@ -5643,7 +5660,13 @@ function positionSelectionToolbar() {
|
|
|
5643
5660
|
if (!bar || !liveSelected || !iframe || !iframe.contentWindow || !panel) return;
|
|
5644
5661
|
if (selectedEl !== liveSelected) {
|
|
5645
5662
|
selectedEl = liveSelected;
|
|
5646
|
-
|
|
5663
|
+
if (!document.activeElement || (
|
|
5664
|
+
document.activeElement.id !== 'pp-html' &&
|
|
5665
|
+
document.activeElement.id !== 'pp-text' &&
|
|
5666
|
+
document.activeElement.id !== 'pp-select-options'
|
|
5667
|
+
)) {
|
|
5668
|
+
renderRightPanel(liveSelected);
|
|
5669
|
+
}
|
|
5647
5670
|
syncDomTreeSelection();
|
|
5648
5671
|
}
|
|
5649
5672
|
var elR = getIframeElementVisualRect(selectedEl);
|
|
@@ -6177,19 +6200,149 @@ function renderElementsTree(filterRaw) {
|
|
|
6177
6200
|
return;
|
|
6178
6201
|
}
|
|
6179
6202
|
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6203
|
+
function nodeIcon(tag) {
|
|
6204
|
+
tag = (tag || '').toLowerCase();
|
|
6205
|
+
|
|
6206
|
+
// Headings
|
|
6207
|
+
if (/^h[1-6]$/.test(tag)) return 'bi bi-type-h1';
|
|
6208
|
+
|
|
6209
|
+
// Document & metadata
|
|
6210
|
+
if (tag === 'html') return 'bi bi-filetype-html';
|
|
6211
|
+
if (tag === 'head') return 'bi bi-file-earmark-code';
|
|
6212
|
+
if (tag === 'body') return 'bi bi-file-earmark-richtext';
|
|
6213
|
+
if (tag === 'title') return 'bi bi-card-heading';
|
|
6214
|
+
if (tag === 'meta') return 'bi bi-info-circle';
|
|
6215
|
+
if (tag === 'link') return 'bi bi-link';
|
|
6216
|
+
if (tag === 'style') return 'bi bi-filetype-css';
|
|
6217
|
+
if (tag === 'script') return 'bi bi-filetype-js';
|
|
6218
|
+
if (tag === 'noscript') return 'bi bi-slash-circle';
|
|
6219
|
+
if (tag === 'base') return 'bi bi-house-gear';
|
|
6220
|
+
|
|
6221
|
+
// Sectioning & layout
|
|
6222
|
+
if (tag === 'section' || tag === 'main' || tag === 'article' ||
|
|
6223
|
+
tag === 'header' || tag === 'footer' || tag === 'nav' || tag === 'aside')
|
|
6224
|
+
return 'bi bi-layout-three-columns';
|
|
6225
|
+
if (tag === 'div') return 'bi bi-square';
|
|
6226
|
+
if (tag === 'address') return 'bi bi-geo-alt';
|
|
6227
|
+
|
|
6228
|
+
// Text content
|
|
6229
|
+
if (tag === 'p' || tag === 'span') return 'bi bi-text-left';
|
|
6230
|
+
if (tag === 'blockquote' || tag === 'q') return 'bi bi-blockquote-left';
|
|
6231
|
+
if (tag === 'pre') return 'bi bi-code-square';
|
|
6232
|
+
if (tag === 'code') return 'bi bi-code-slash';
|
|
6233
|
+
if (tag === 'kbd') return 'bi bi-keyboard';
|
|
6234
|
+
if (tag === 'samp') return 'bi bi-terminal';
|
|
6235
|
+
if (tag === 'var') return 'bi bi-braces';
|
|
6236
|
+
if (tag === 'cite') return 'bi bi-quote';
|
|
6237
|
+
if (tag === 'abbr') return 'bi bi-fonts';
|
|
6238
|
+
if (tag === 'time') return 'bi bi-clock';
|
|
6239
|
+
if (tag === 'mark') return 'bi bi-highlighter';
|
|
6240
|
+
if (tag === 'small') return 'bi bi-type';
|
|
6241
|
+
if (tag === 'sub') return 'bi bi-subscript';
|
|
6242
|
+
if (tag === 'sup') return 'bi bi-superscript';
|
|
6243
|
+
if (tag === 'br') return 'bi bi-arrow-return-left';
|
|
6244
|
+
if (tag === 'wbr') return 'bi bi-distribute-horizontal';
|
|
6245
|
+
|
|
6246
|
+
// Inline formatting
|
|
6247
|
+
if (tag === 'strong' || tag === 'b') return 'bi bi-type-bold';
|
|
6248
|
+
if (tag === 'em' || tag === 'i') return 'bi bi-type-italic';
|
|
6249
|
+
if (tag === 'u' || tag === 'ins') return 'bi bi-type-underline';
|
|
6250
|
+
if (tag === 's' || tag === 'del' || tag === 'strike') return 'bi bi-type-strikethrough';
|
|
6251
|
+
|
|
6252
|
+
// Lists
|
|
6253
|
+
if (tag === 'ul') return 'bi bi-list-ul';
|
|
6254
|
+
if (tag === 'ol') return 'bi bi-list-ol';
|
|
6255
|
+
if (tag === 'li') return 'bi bi-dot';
|
|
6256
|
+
if (tag === 'dl') return 'bi bi-card-list';
|
|
6257
|
+
if (tag === 'dt') return 'bi bi-tag';
|
|
6258
|
+
if (tag === 'dd') return 'bi bi-text-indent-left';
|
|
6259
|
+
|
|
6260
|
+
// Links & navigation
|
|
6261
|
+
if (tag === 'a') return 'bi bi-link-45deg';
|
|
6262
|
+
|
|
6263
|
+
// Media
|
|
6264
|
+
if (tag === 'img') return 'bi bi-image';
|
|
6265
|
+
if (tag === 'picture') return 'bi bi-images';
|
|
6266
|
+
if (tag === 'figure') return 'bi bi-card-image';
|
|
6267
|
+
if (tag === 'figcaption') return 'bi bi-card-text';
|
|
6268
|
+
if (tag === 'video') return 'bi bi-camera-video';
|
|
6269
|
+
if (tag === 'audio') return 'bi bi-music-note-beamed';
|
|
6270
|
+
if (tag === 'source') return 'bi bi-cloud-arrow-down';
|
|
6271
|
+
if (tag === 'track') return 'bi bi-badge-cc';
|
|
6272
|
+
if (tag === 'iframe') return 'bi bi-window';
|
|
6273
|
+
if (tag === 'embed' || tag === 'object') return 'bi bi-box-arrow-in-down';
|
|
6274
|
+
if (tag === 'param') return 'bi bi-sliders';
|
|
6275
|
+
if (tag === 'canvas') return 'bi bi-easel';
|
|
6276
|
+
if (tag === 'map') return 'bi bi-map';
|
|
6277
|
+
if (tag === 'area') return 'bi bi-bounding-box';
|
|
6278
|
+
|
|
6279
|
+
// Vector / math
|
|
6280
|
+
if (tag === 'svg') return 'bi bi-bezier2';
|
|
6281
|
+
if (tag === 'path') return 'bi bi-bezier';
|
|
6282
|
+
if (tag === 'circle') return 'bi bi-circle';
|
|
6283
|
+
if (tag === 'rect') return 'bi bi-square';
|
|
6284
|
+
if (tag === 'line') return 'bi bi-slash-lg';
|
|
6285
|
+
if (tag === 'polygon') return 'bi bi-pentagon';
|
|
6286
|
+
if (tag === 'polyline') return 'bi bi-share';
|
|
6287
|
+
if (tag === 'ellipse') return 'bi bi-circle-half';
|
|
6288
|
+
if (tag === 'g') return 'bi bi-collection';
|
|
6289
|
+
if (tag === 'use') return 'bi bi-arrow-repeat';
|
|
6290
|
+
if (tag === 'defs') return 'bi bi-bookmark';
|
|
6291
|
+
if (tag === 'symbol') return 'bi bi-star';
|
|
6292
|
+
if (tag === 'text') return 'bi bi-fonts';
|
|
6293
|
+
if (tag === 'math') return 'bi bi-calculator';
|
|
6294
|
+
|
|
6295
|
+
// Forms
|
|
6296
|
+
if (tag === 'form') return 'bi bi-file-earmark-check';
|
|
6297
|
+
if (tag === 'fieldset') return 'bi bi-bounding-box-circles';
|
|
6298
|
+
if (tag === 'legend') return 'bi bi-tag-fill';
|
|
6299
|
+
if (tag === 'label') return 'bi bi-tag';
|
|
6300
|
+
if (tag === 'input') return 'bi bi-input-cursor-text';
|
|
6301
|
+
if (tag === 'button') return 'bi bi-ui-radios';
|
|
6302
|
+
if (tag === 'select') return 'bi bi-menu-button';
|
|
6303
|
+
if (tag === 'option') return 'bi bi-check2-square';
|
|
6304
|
+
if (tag === 'optgroup') return 'bi bi-list-nested';
|
|
6305
|
+
if (tag === 'textarea') return 'bi bi-textarea-resize';
|
|
6306
|
+
if (tag === 'datalist') return 'bi bi-list-columns';
|
|
6307
|
+
if (tag === 'output') return 'bi bi-box-arrow-right';
|
|
6308
|
+
if (tag === 'progress') return 'bi bi-bar-chart-line';
|
|
6309
|
+
if (tag === 'meter') return 'bi bi-speedometer2';
|
|
6310
|
+
|
|
6311
|
+
// Tables
|
|
6312
|
+
if (tag === 'table') return 'bi bi-table';
|
|
6313
|
+
if (tag === 'caption') return 'bi bi-card-heading';
|
|
6314
|
+
if (tag === 'thead') return 'bi bi-layout-text-window';
|
|
6315
|
+
if (tag === 'tbody') return 'bi bi-layout-text-sidebar';
|
|
6316
|
+
if (tag === 'tfoot') return 'bi bi-layout-text-window-reverse';
|
|
6317
|
+
if (tag === 'tr') return 'bi bi-grip-horizontal';
|
|
6318
|
+
if (tag === 'th') return 'bi bi-grid-3x3-gap-fill';
|
|
6319
|
+
if (tag === 'td') return 'bi bi-grid-3x3-gap';
|
|
6320
|
+
if (tag === 'col') return 'bi bi-layout-three-columns';
|
|
6321
|
+
if (tag === 'colgroup') return 'bi bi-columns-gap';
|
|
6322
|
+
|
|
6323
|
+
// Interactive / disclosure
|
|
6324
|
+
if (tag === 'details') return 'bi bi-caret-down-square';
|
|
6325
|
+
if (tag === 'summary') return 'bi bi-card-text';
|
|
6326
|
+
if (tag === 'dialog') return 'bi bi-chat-square-text';
|
|
6327
|
+
if (tag === 'menu') return 'bi bi-list';
|
|
6328
|
+
|
|
6329
|
+
// Web components / templating
|
|
6330
|
+
if (tag === 'template') return 'bi bi-file-earmark-code';
|
|
6331
|
+
if (tag === 'slot') return 'bi bi-box-seam';
|
|
6332
|
+
|
|
6333
|
+
// Ruby annotation
|
|
6334
|
+
if (tag === 'ruby' || tag === 'rt' || tag === 'rp' || tag === 'rb')
|
|
6335
|
+
return 'bi bi-translate';
|
|
6336
|
+
if (tag === 'bdi' || tag === 'bdo') return 'bi bi-arrow-left-right';
|
|
6337
|
+
|
|
6338
|
+
// Misc
|
|
6339
|
+
if (tag === 'hr') return 'bi bi-hr';
|
|
6340
|
+
if (tag === '#text' || tag === 'text-node') return 'bi bi-cursor-text';
|
|
6341
|
+
if (tag === '#comment') return 'bi bi-chat-left-text';
|
|
6342
|
+
|
|
6343
|
+
return 'bi bi-square';
|
|
6344
|
+
}
|
|
6345
|
+
|
|
6193
6346
|
|
|
6194
6347
|
var nodes = collectEditorInsertedElements(doc);
|
|
6195
6348
|
|
|
@@ -6456,11 +6609,64 @@ function isFormControlElement(el) {
|
|
|
6456
6609
|
function shouldShowInnerContentFields(el) {
|
|
6457
6610
|
if (!el || el.nodeType !== 1) return false;
|
|
6458
6611
|
var tag = (el.tagName || '').toLowerCase();
|
|
6459
|
-
if (tag === 'input' || tag === 'textarea' || tag === 'video') return false;
|
|
6612
|
+
if (tag === 'input' || tag === 'textarea' || tag === 'select' || tag === 'video') return false;
|
|
6460
6613
|
if (isEmbeddedVideoIframe(el)) return false;
|
|
6461
6614
|
return true;
|
|
6462
6615
|
}
|
|
6463
6616
|
|
|
6617
|
+
function getSelectOptionsText(el) {
|
|
6618
|
+
if (!el || el.nodeType !== 1) return '';
|
|
6619
|
+
try {
|
|
6620
|
+
var opts = el.querySelectorAll('option');
|
|
6621
|
+
var lines = [];
|
|
6622
|
+
for (var i = 0; i < opts.length; i++) {
|
|
6623
|
+
lines.push(opts[i].textContent || '');
|
|
6624
|
+
}
|
|
6625
|
+
return lines.join('\\n');
|
|
6626
|
+
} catch(_) {
|
|
6627
|
+
return '';
|
|
6628
|
+
}
|
|
6629
|
+
}
|
|
6630
|
+
|
|
6631
|
+
function selectOptionsTextToHtml(text) {
|
|
6632
|
+
var lines = String(text == null ? '' : text).split('\\n');
|
|
6633
|
+
var parts = [];
|
|
6634
|
+
for (var i = 0; i < lines.length; i++) {
|
|
6635
|
+
var label = lines[i];
|
|
6636
|
+
if (!label && i === lines.length - 1 && lines.length > 1) continue;
|
|
6637
|
+
parts.push('<option>' + esc(label) + '</option>');
|
|
6638
|
+
}
|
|
6639
|
+
if (!parts.length) parts.push('<option>Option 1</option>');
|
|
6640
|
+
return parts.join('');
|
|
6641
|
+
}
|
|
6642
|
+
|
|
6643
|
+
function applySelectOptionsFromText(el, text) {
|
|
6644
|
+
if (!el || el.nodeType !== 1) return;
|
|
6645
|
+
beginSuppressIframeMutationDirty();
|
|
6646
|
+
try {
|
|
6647
|
+
var prevValue = '';
|
|
6648
|
+
try { prevValue = el.value || ''; } catch(_) {}
|
|
6649
|
+
var doc = el.ownerDocument;
|
|
6650
|
+
while (el.firstChild) el.removeChild(el.firstChild);
|
|
6651
|
+
var lines = String(text == null ? '' : text).split('\\n');
|
|
6652
|
+
if (!lines.length || (lines.length === 1 && !String(lines[0] || '').trim())) {
|
|
6653
|
+
lines = ['Option 1', 'Option 2'];
|
|
6654
|
+
}
|
|
6655
|
+
for (var i = 0; i < lines.length; i++) {
|
|
6656
|
+
var label = lines[i];
|
|
6657
|
+
if (!label && i === lines.length - 1) continue;
|
|
6658
|
+
var opt = doc.createElement('option');
|
|
6659
|
+
opt.textContent = label;
|
|
6660
|
+
el.appendChild(opt);
|
|
6661
|
+
}
|
|
6662
|
+
if (prevValue) {
|
|
6663
|
+
try { el.value = prevValue; } catch(_) {}
|
|
6664
|
+
}
|
|
6665
|
+
} finally {
|
|
6666
|
+
endSuppressIframeMutationDirty();
|
|
6667
|
+
}
|
|
6668
|
+
}
|
|
6669
|
+
|
|
6464
6670
|
function elementHasHtmlChildren(el) {
|
|
6465
6671
|
if (!el || el.nodeType !== 1) return false;
|
|
6466
6672
|
try {
|
|
@@ -7119,6 +7325,12 @@ function renderRightPanel(el, options) {
|
|
|
7119
7325
|
subLbl('Placeholder') +
|
|
7120
7326
|
'<input class="pr-inp" id="pp-ph" type="text" value="'+esc(el.getAttribute('placeholder')||'')+'" style="width:100%;margin-bottom:8px">';
|
|
7121
7327
|
}
|
|
7328
|
+
if (tag === 'select') {
|
|
7329
|
+
contentHtml +=
|
|
7330
|
+
subLbl('Options') +
|
|
7331
|
+
'<div style="font-size:11px;color:var(--text-3);margin:-4px 0 8px">One option label per line</div>' +
|
|
7332
|
+
'<textarea class="pr-inp" id="pp-select-options" style="width:100%;min-height:80px;font-family:var(--font-mono);font-size:11px">'+esc(getSelectOptionsText(el))+'</textarea>';
|
|
7333
|
+
}
|
|
7122
7334
|
if (shouldShowInnerContentFields(el)) {
|
|
7123
7335
|
if (elementHasHtmlChildren(el)) {
|
|
7124
7336
|
contentHtml +=
|
|
@@ -7226,18 +7438,49 @@ function renderRightPanel(el, options) {
|
|
|
7226
7438
|
function wireContentFieldSync(el, sel) {
|
|
7227
7439
|
var textInp = document.getElementById('pp-text');
|
|
7228
7440
|
var htmlInp = document.getElementById('pp-html');
|
|
7441
|
+
var selectOptsInp = document.getElementById('pp-select-options');
|
|
7229
7442
|
var syncing = false;
|
|
7230
|
-
|
|
7443
|
+
var htmlApplyTimer = null;
|
|
7444
|
+
var selectApplyTimer = null;
|
|
7445
|
+
|
|
7446
|
+
function applyHtmlToElement(htmlValue) {
|
|
7447
|
+
beginSuppressIframeMutationDirty();
|
|
7448
|
+
try {
|
|
7449
|
+
el.innerHTML = htmlValue;
|
|
7450
|
+
} finally {
|
|
7451
|
+
endSuppressIframeMutationDirty();
|
|
7452
|
+
}
|
|
7453
|
+
}
|
|
7454
|
+
|
|
7455
|
+
function applyContentChange(changedId, immediate) {
|
|
7231
7456
|
if (syncing) return;
|
|
7457
|
+
if (changedId === 'pp-html' && !immediate) {
|
|
7458
|
+
if (htmlApplyTimer) clearTimeout(htmlApplyTimer);
|
|
7459
|
+
htmlApplyTimer = setTimeout(function() { applyContentChange('pp-html', true); }, 250);
|
|
7460
|
+
return;
|
|
7461
|
+
}
|
|
7462
|
+
if (changedId === 'pp-select-options' && !immediate) {
|
|
7463
|
+
if (selectApplyTimer) clearTimeout(selectApplyTimer);
|
|
7464
|
+
selectApplyTimer = setTimeout(function() { applyContentChange('pp-select-options', true); }, 250);
|
|
7465
|
+
return;
|
|
7466
|
+
}
|
|
7232
7467
|
syncing = true;
|
|
7233
7468
|
try {
|
|
7234
7469
|
var orig = getOriginalValue(changedId, el);
|
|
7235
7470
|
if (changedId === 'pp-text') {
|
|
7236
|
-
|
|
7471
|
+
beginSuppressIframeMutationDirty();
|
|
7472
|
+
try {
|
|
7473
|
+
el.innerText = textInp.value;
|
|
7474
|
+
} finally {
|
|
7475
|
+
endSuppressIframeMutationDirty();
|
|
7476
|
+
}
|
|
7237
7477
|
if (htmlInp) htmlInp.value = el.innerHTML;
|
|
7238
7478
|
logChange(sel, 'pp-text', textInp.value, el, orig);
|
|
7479
|
+
} else if (changedId === 'pp-select-options') {
|
|
7480
|
+
applySelectOptionsFromText(el, selectOptsInp.value);
|
|
7481
|
+
logChange(sel, 'pp-select-options', selectOptsInp.value, el, orig);
|
|
7239
7482
|
} else {
|
|
7240
|
-
|
|
7483
|
+
applyHtmlToElement(htmlInp.value);
|
|
7241
7484
|
if (textInp) textInp.value = el.innerText;
|
|
7242
7485
|
logChange(sel, 'pp-html', htmlInp.value, el, orig);
|
|
7243
7486
|
}
|
|
@@ -7250,8 +7493,12 @@ function wireContentFieldSync(el, sel) {
|
|
|
7250
7493
|
textInp.addEventListener('change', function() { applyContentChange('pp-text'); });
|
|
7251
7494
|
}
|
|
7252
7495
|
if (htmlInp) {
|
|
7253
|
-
htmlInp.addEventListener('input', function() { applyContentChange('pp-html'); });
|
|
7254
|
-
htmlInp.addEventListener('change', function() { applyContentChange('pp-html'); });
|
|
7496
|
+
htmlInp.addEventListener('input', function() { applyContentChange('pp-html', false); });
|
|
7497
|
+
htmlInp.addEventListener('change', function() { applyContentChange('pp-html', true); });
|
|
7498
|
+
}
|
|
7499
|
+
if (selectOptsInp) {
|
|
7500
|
+
selectOptsInp.addEventListener('input', function() { applyContentChange('pp-select-options', false); });
|
|
7501
|
+
selectOptsInp.addEventListener('change', function() { applyContentChange('pp-select-options', true); });
|
|
7255
7502
|
}
|
|
7256
7503
|
}
|
|
7257
7504
|
|
|
@@ -7742,14 +7989,21 @@ function attachChangeObserver() {
|
|
|
7742
7989
|
changeObserverDoc = null;
|
|
7743
7990
|
}
|
|
7744
7991
|
changeObserver = new MutationObserver(function(mutations) {
|
|
7992
|
+
if (suppressIframeMutationDirty > 0) return;
|
|
7745
7993
|
var hasMeaningfulMutation = false;
|
|
7746
7994
|
for (var mi = 0; mi < mutations.length; mi++) {
|
|
7747
|
-
if (!
|
|
7995
|
+
if (!isEditorChromeOnlyClassMutation(mutations[mi])) {
|
|
7748
7996
|
hasMeaningfulMutation = true;
|
|
7749
7997
|
break;
|
|
7750
7998
|
}
|
|
7751
7999
|
}
|
|
7752
8000
|
if (!hasMeaningfulMutation) return;
|
|
8001
|
+
var activeId = '';
|
|
8002
|
+
try { activeId = document.activeElement && document.activeElement.id ? String(document.activeElement.id) : ''; } catch(_) {}
|
|
8003
|
+
if (activeId === 'pp-html' || activeId === 'pp-text' || activeId === 'pp-select-options') {
|
|
8004
|
+
scheduleDomTreeRefresh();
|
|
8005
|
+
return;
|
|
8006
|
+
}
|
|
7753
8007
|
// Dirty state is derived from changesets baseline + stateChanges (not raw DOM mutations).
|
|
7754
8008
|
// Host scripts can replace selected nodes every few frames (e.g. A/B tool observers).
|
|
7755
8009
|
// Keep selection sticky by re-resolving from fingerprint.
|
|
@@ -8245,7 +8499,9 @@ window.addEventListener('load', function() {
|
|
|
8245
8499
|
return;
|
|
8246
8500
|
}
|
|
8247
8501
|
hideIframeLoadError();
|
|
8248
|
-
|
|
8502
|
+
var iframeLiveUrl = '';
|
|
8503
|
+
try { iframeLiveUrl = String(iframe.contentWindow.location.href || ''); } catch(_) {}
|
|
8504
|
+
emitEditorUrlChanged(iframeLiveUrl || docUrl || iframe.src || '');
|
|
8249
8505
|
// Stale events: src may already be the proxy URL while the document is still
|
|
8250
8506
|
// about:blank (e.g. src cleared then reset to force reload). Ask sync path to retry.
|
|
8251
8507
|
if (docUrl === 'about:blank') {
|
|
@@ -8630,6 +8886,11 @@ function createVisualEditorMiddleware(options) {
|
|
|
8630
8886
|
}
|
|
8631
8887
|
if (chunks.length > 0) requestBody = Buffer.concat(chunks);
|
|
8632
8888
|
}
|
|
8889
|
+
const secFetchMode = (req.headers?.["sec-fetch-mode"] || "").toLowerCase();
|
|
8890
|
+
const secFetchDest = (req.headers?.["sec-fetch-dest"] || "").toLowerCase();
|
|
8891
|
+
const isLikelyDocumentNavigation = secFetchMode === "navigate" || secFetchDest === "iframe" || secFetchDest === "document" || secFetchDest === "nested-document" || secFetchDest === "frame";
|
|
8892
|
+
const isLikelyFetchOrXHR = secFetchDest === "empty" && (secFetchMode === "cors" || secFetchMode === "same-origin" || secFetchMode === "no-cors");
|
|
8893
|
+
const passthroughUpstreamRedirects = (method === "GET" || method === "HEAD") && (isLikelyDocumentNavigation || !isLikelyFetchOrXHR);
|
|
8633
8894
|
const upstreamTimeoutMs = 12e4;
|
|
8634
8895
|
const ac = new AbortController();
|
|
8635
8896
|
const timeoutId = setTimeout(() => ac.abort(), upstreamTimeoutMs);
|
|
@@ -8639,7 +8900,7 @@ function createVisualEditorMiddleware(options) {
|
|
|
8639
8900
|
method,
|
|
8640
8901
|
headers: fetchHeaders,
|
|
8641
8902
|
body: requestBody ? Buffer.from(requestBody) : null,
|
|
8642
|
-
redirect: "follow",
|
|
8903
|
+
redirect: passthroughUpstreamRedirects ? "manual" : "follow",
|
|
8643
8904
|
signal: ac.signal
|
|
8644
8905
|
});
|
|
8645
8906
|
} catch (fetchErr) {
|
|
@@ -8663,12 +8924,43 @@ function createVisualEditorMiddleware(options) {
|
|
|
8663
8924
|
return;
|
|
8664
8925
|
}
|
|
8665
8926
|
clearTimeout(timeoutId);
|
|
8927
|
+
if (passthroughUpstreamRedirects && upstream.status >= 300 && upstream.status < 400) {
|
|
8928
|
+
const locationHeader = upstream.headers.get("location") || upstream.headers.get("Location");
|
|
8929
|
+
if (locationHeader) {
|
|
8930
|
+
try {
|
|
8931
|
+
const redirectTarget = new URL(locationHeader, targetUrl);
|
|
8932
|
+
if (redirectTarget.origin === origin) {
|
|
8933
|
+
const proxyRedirect = new URL(proxyRootForRequest, "http://localhost");
|
|
8934
|
+
proxyRedirect.searchParams.set("password", password);
|
|
8935
|
+
proxyRedirect.searchParams.set("url", redirectTarget.toString());
|
|
8936
|
+
url.searchParams.forEach((value, key) => {
|
|
8937
|
+
if (key === "url" || key === "password") return;
|
|
8938
|
+
proxyRedirect.searchParams.set(key, value);
|
|
8939
|
+
});
|
|
8940
|
+
res.statusCode = upstream.status === 303 ? 303 : 302;
|
|
8941
|
+
res.setHeader("Location", `${proxyRedirect.pathname}${proxyRedirect.search}`);
|
|
8942
|
+
res.setHeader("Cache-Control", "no-store");
|
|
8943
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
8944
|
+
setFrameHeaders(req, res);
|
|
8945
|
+
res.end();
|
|
8946
|
+
return;
|
|
8947
|
+
}
|
|
8948
|
+
res.statusCode = 502;
|
|
8949
|
+
res.setHeader("Content-Type", "application/json");
|
|
8950
|
+
res.end(
|
|
8951
|
+
JSON.stringify({
|
|
8952
|
+
error: "Cross-origin redirect blocked in editor preview",
|
|
8953
|
+
location: redirectTarget.toString(),
|
|
8954
|
+
from: targetUrl
|
|
8955
|
+
})
|
|
8956
|
+
);
|
|
8957
|
+
return;
|
|
8958
|
+
} catch (_) {
|
|
8959
|
+
}
|
|
8960
|
+
}
|
|
8961
|
+
}
|
|
8666
8962
|
const responseContentType = upstream.headers.get("content-type") || "";
|
|
8667
8963
|
const isHtmlResponse = responseContentType.includes("text/html");
|
|
8668
|
-
const secFetchMode = (req.headers?.["sec-fetch-mode"] || "").toLowerCase();
|
|
8669
|
-
const secFetchDest = (req.headers?.["sec-fetch-dest"] || "").toLowerCase();
|
|
8670
|
-
const isLikelyDocumentNavigation = secFetchMode === "navigate" || secFetchDest === "iframe" || secFetchDest === "document" || secFetchDest === "nested-document" || secFetchDest === "frame";
|
|
8671
|
-
const isLikelyFetchOrXHR = secFetchDest === "empty" && (secFetchMode === "cors" || secFetchMode === "same-origin" || secFetchMode === "no-cors");
|
|
8672
8964
|
const shouldInjectHtmlBridge = isHtmlResponse && (isLikelyDocumentNavigation || !isLikelyFetchOrXHR);
|
|
8673
8965
|
if (!isHtmlResponse || !shouldInjectHtmlBridge) {
|
|
8674
8966
|
const binary = Buffer.from(await upstream.arrayBuffer());
|
|
@@ -8722,6 +9014,18 @@ ${iframeAlwaysShowCssGuardScript}
|
|
|
8722
9014
|
/<meta[^>]+name=["']?\s*content-security-policy\s*["']?[^>]*>/gi,
|
|
8723
9015
|
""
|
|
8724
9016
|
);
|
|
9017
|
+
html = html.replace(
|
|
9018
|
+
/(<meta[^>]+http-equiv=["']?refresh["']?[^>]*content=["'][^"']*url=)([^"';]+)(["'][^>]*>)/gi,
|
|
9019
|
+
(match, prefix, urlPart, suffix) => {
|
|
9020
|
+
try {
|
|
9021
|
+
const abs = new URL(String(urlPart).trim(), origin).toString();
|
|
9022
|
+
if (new URL(abs).origin !== origin) return match;
|
|
9023
|
+
return `${prefix}${proxyBase}${encodeURIComponent(abs)}${suffix}`;
|
|
9024
|
+
} catch {
|
|
9025
|
+
return match;
|
|
9026
|
+
}
|
|
9027
|
+
}
|
|
9028
|
+
);
|
|
8725
9029
|
const runtimePreflightScript = `<script>(function(){try{
|
|
8726
9030
|
var TARGET_ORIGIN=${JSON.stringify(origin)};
|
|
8727
9031
|
var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};
|
|
@@ -8928,6 +9232,8 @@ try{if(window.history&&typeof window.history.pushState==="function"){var nativeP
|
|
|
8928
9232
|
try{if(window.history&&typeof window.history.replaceState==="function"){var nativeReplaceState=window.history.replaceState;window.history.replaceState=function(){var ret=nativeReplaceState.apply(window.history,arguments);setTimeout(notifyEditorUrlChanged,0);return ret;};}}catch(_){}
|
|
8929
9233
|
try{window.addEventListener("popstate",notifyEditorUrlChanged,true);}catch(_){}
|
|
8930
9234
|
try{window.addEventListener("hashchange",notifyEditorUrlChanged,true);}catch(_){}
|
|
9235
|
+
try{window.addEventListener("pageshow",notifyEditorUrlChanged,true);}catch(_){}
|
|
9236
|
+
try{window.addEventListener("load",function(){setTimeout(notifyEditorUrlChanged,0);},true);}catch(_){}
|
|
8931
9237
|
function isSkippable(raw){if(!raw||typeof raw!=="string")return true;return raw.startsWith("data:")||raw.startsWith("blob:")||raw.startsWith("javascript:")||raw.startsWith("#");}
|
|
8932
9238
|
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;}}
|
|
8933
9239
|
function toProxy(raw){
|
|
@@ -8956,6 +9262,9 @@ function toProxy(raw){
|
|
|
8956
9262
|
var nativeAssign=window.location.assign?window.location.assign.bind(window.location):null;
|
|
8957
9263
|
var nativeReplace=window.location.replace?window.location.replace.bind(window.location):null;
|
|
8958
9264
|
function safeNavigate(raw,mode){var abs=toAbsolute(raw);var prox=toProxy(raw);if(!prox){try{console.warn("[conversion-proxy] redirect blocked",{mode:mode,requested:raw,resolved:abs,origin:TARGET_ORIGIN});}catch(_){}return false;}try{console.info("[conversion-proxy] redirect intercepted",{mode:mode,requested:raw,resolved:abs,proxied:prox});if(mode==="replace"&&nativeReplace){nativeReplace(prox);return true;}if(nativeAssign){nativeAssign(prox);return true;}window.location.href=prox;return true;}catch(err){try{console.warn("[conversion-proxy] redirect interception failed",{mode:mode,requested:raw,resolved:abs,proxied:prox,error:err&&err.message?err.message:String(err)});}catch(_){}return false;}}
|
|
9265
|
+
function interceptMetaRefresh(){try{var metas=document.querySelectorAll('meta[http-equiv="refresh" i],meta[http-equiv="Refresh"]');for(var i=0;i<metas.length;i++){var content=metas[i].getAttribute("content")||"";var m=content.match(/url=(.+)$/i);if(!m)continue;var raw=m[1].trim().replace(/^['"]|['"]$/g,"");if(safeNavigate(raw,"replace"))metas[i].parentNode&&metas[i].parentNode.removeChild(metas[i]);}}catch(_){}}
|
|
9266
|
+
try{interceptMetaRefresh();}catch(_){}
|
|
9267
|
+
try{document.addEventListener("DOMContentLoaded",interceptMetaRefresh,true);}catch(_){}
|
|
8959
9268
|
try{if(nativeAssign){window.location.assign=function(url){return safeNavigate(url,"assign");};}}catch(_){}
|
|
8960
9269
|
try{if(nativeReplace){window.location.replace=function(url){return safeNavigate(url,"replace");};}}catch(_){}
|
|
8961
9270
|
try{var hrefDesc=Object.getOwnPropertyDescriptor(Location.prototype,"href");if(hrefDesc&&hrefDesc.configurable&&hrefDesc.get&&hrefDesc.set){Object.defineProperty(Location.prototype,"href",{configurable:true,enumerable:hrefDesc.enumerable,get:function(){return hrefDesc.get.call(this);},set:function(v){safeNavigate(v,"assign");}});}}catch(_){}
|
package/dist/vite.js
CHANGED
|
@@ -2186,10 +2186,13 @@ function simulateExperiment() {
|
|
|
2186
2186
|
variations[0];
|
|
2187
2187
|
}
|
|
2188
2188
|
var targetUrl =
|
|
2189
|
+
(test.metadata_1 && test.metadata_1.editor_url) ||
|
|
2189
2190
|
(Array.isArray(test.urltargeting) && test.urltargeting[0]) ||
|
|
2190
2191
|
test.pageUrl ||
|
|
2191
|
-
(test.metadata_1 && test.metadata_1.editor_url) ||
|
|
2192
2192
|
'';
|
|
2193
|
+
if (targetUrl && !/^https?:///i.test(String(targetUrl).trim())) {
|
|
2194
|
+
targetUrl = 'https://' + String(targetUrl).trim();
|
|
2195
|
+
}
|
|
2193
2196
|
var testId = resolveSimulationId(test, ['iid', 'experimentIid', 'experimentId', '_id', 'id']);
|
|
2194
2197
|
var variationId = resolveSimulationId(activeVariation, ['iid', 'platformIid', 'variationIid', '_id', 'id']);
|
|
2195
2198
|
if (testId === null || !activeVariation || variationId === null) {
|
|
@@ -3142,6 +3145,7 @@ var PROP_META = {
|
|
|
3142
3145
|
'pp-value': {label:'Value', cssProp:null},
|
|
3143
3146
|
'pp-text': {label:'Inner text', cssProp:null},
|
|
3144
3147
|
'pp-html': {label:'Inner HTML', cssProp:null},
|
|
3148
|
+
'pp-select-options': {label:'Options', cssProp:null},
|
|
3145
3149
|
'pp-mob-css': {label:'Mobile CSS', cssProp:null},
|
|
3146
3150
|
'pp-tab-css': {label:'Tablet CSS', cssProp:null},
|
|
3147
3151
|
};
|
|
@@ -3158,6 +3162,7 @@ function getOriginalValue(inputId, el) {
|
|
|
3158
3162
|
switch (inputId) {
|
|
3159
3163
|
case 'pp-text': return el.innerText || '';
|
|
3160
3164
|
case 'pp-html': return el.innerHTML || '';
|
|
3165
|
+
case 'pp-select-options': return getSelectOptionsText(el);
|
|
3161
3166
|
case 'pp-cls': return el.className || '';
|
|
3162
3167
|
case 'pp-id': return el.id || '';
|
|
3163
3168
|
case 'pp-href': return el.getAttribute('href') || '';
|
|
@@ -3307,6 +3312,7 @@ function revertChangeOnDom(change) {
|
|
|
3307
3312
|
switch (change.inputId) {
|
|
3308
3313
|
case 'pp-text': el.innerText = orig; break;
|
|
3309
3314
|
case 'pp-html': el.innerHTML = orig; break;
|
|
3315
|
+
case 'pp-select-options': applySelectOptionsFromText(el, orig); break;
|
|
3310
3316
|
case 'pp-cls': el.className = orig; break;
|
|
3311
3317
|
case 'pp-id': el.id = orig; break;
|
|
3312
3318
|
case 'pp-css': orig ? el.setAttribute('style', orig) : el.removeAttribute('style'); break;
|
|
@@ -4965,6 +4971,8 @@ function stateChangeToChainSet(c) {
|
|
|
4965
4971
|
return { selector: c.selector, type: 'content', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
4966
4972
|
case 'pp-html':
|
|
4967
4973
|
return { selector: c.selector, type: 'content', html: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
4974
|
+
case 'pp-select-options':
|
|
4975
|
+
return { selector: c.selector, type: 'content', html: selectOptionsTextToHtml(c.value), vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
4968
4976
|
case 'pp-cls':
|
|
4969
4977
|
return { selector: c.selector, type: 'attribute', attribute: 'class', value: c.value, vveTs: c.vveTs || nextHistoryTimestamp() };
|
|
4970
4978
|
case 'pp-id':
|
|
@@ -5578,6 +5586,10 @@ function setTreeHoverHighlight(el) {
|
|
|
5578
5586
|
}
|
|
5579
5587
|
|
|
5580
5588
|
function isTreeHoverOnlyClassMutation(mutation) {
|
|
5589
|
+
return isEditorChromeOnlyClassMutation(mutation);
|
|
5590
|
+
}
|
|
5591
|
+
|
|
5592
|
+
function isEditorChromeOnlyClassMutation(mutation) {
|
|
5581
5593
|
if (!mutation || mutation.type !== 'attributes' || mutation.attributeName !== 'class') return false;
|
|
5582
5594
|
var oldClass = String(mutation.oldValue || '');
|
|
5583
5595
|
var target = mutation.target;
|
|
@@ -5585,7 +5597,12 @@ function isTreeHoverOnlyClassMutation(mutation) {
|
|
|
5585
5597
|
try {
|
|
5586
5598
|
nextClass = target && typeof target.className === 'string' ? target.className : '';
|
|
5587
5599
|
} catch(_) {}
|
|
5588
|
-
|
|
5600
|
+
var combined = oldClass + ' ' + nextClass;
|
|
5601
|
+
return (
|
|
5602
|
+
combined.indexOf('vve-tree-hover') >= 0 ||
|
|
5603
|
+
combined.indexOf('vve-selected') >= 0 ||
|
|
5604
|
+
combined.indexOf('vve-dragging') >= 0
|
|
5605
|
+
);
|
|
5589
5606
|
}
|
|
5590
5607
|
|
|
5591
5608
|
function setDragHandleActive(on) {
|
|
@@ -5635,7 +5652,13 @@ function positionSelectionToolbar() {
|
|
|
5635
5652
|
if (!bar || !liveSelected || !iframe || !iframe.contentWindow || !panel) return;
|
|
5636
5653
|
if (selectedEl !== liveSelected) {
|
|
5637
5654
|
selectedEl = liveSelected;
|
|
5638
|
-
|
|
5655
|
+
if (!document.activeElement || (
|
|
5656
|
+
document.activeElement.id !== 'pp-html' &&
|
|
5657
|
+
document.activeElement.id !== 'pp-text' &&
|
|
5658
|
+
document.activeElement.id !== 'pp-select-options'
|
|
5659
|
+
)) {
|
|
5660
|
+
renderRightPanel(liveSelected);
|
|
5661
|
+
}
|
|
5639
5662
|
syncDomTreeSelection();
|
|
5640
5663
|
}
|
|
5641
5664
|
var elR = getIframeElementVisualRect(selectedEl);
|
|
@@ -6169,19 +6192,149 @@ function renderElementsTree(filterRaw) {
|
|
|
6169
6192
|
return;
|
|
6170
6193
|
}
|
|
6171
6194
|
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6195
|
+
function nodeIcon(tag) {
|
|
6196
|
+
tag = (tag || '').toLowerCase();
|
|
6197
|
+
|
|
6198
|
+
// Headings
|
|
6199
|
+
if (/^h[1-6]$/.test(tag)) return 'bi bi-type-h1';
|
|
6200
|
+
|
|
6201
|
+
// Document & metadata
|
|
6202
|
+
if (tag === 'html') return 'bi bi-filetype-html';
|
|
6203
|
+
if (tag === 'head') return 'bi bi-file-earmark-code';
|
|
6204
|
+
if (tag === 'body') return 'bi bi-file-earmark-richtext';
|
|
6205
|
+
if (tag === 'title') return 'bi bi-card-heading';
|
|
6206
|
+
if (tag === 'meta') return 'bi bi-info-circle';
|
|
6207
|
+
if (tag === 'link') return 'bi bi-link';
|
|
6208
|
+
if (tag === 'style') return 'bi bi-filetype-css';
|
|
6209
|
+
if (tag === 'script') return 'bi bi-filetype-js';
|
|
6210
|
+
if (tag === 'noscript') return 'bi bi-slash-circle';
|
|
6211
|
+
if (tag === 'base') return 'bi bi-house-gear';
|
|
6212
|
+
|
|
6213
|
+
// Sectioning & layout
|
|
6214
|
+
if (tag === 'section' || tag === 'main' || tag === 'article' ||
|
|
6215
|
+
tag === 'header' || tag === 'footer' || tag === 'nav' || tag === 'aside')
|
|
6216
|
+
return 'bi bi-layout-three-columns';
|
|
6217
|
+
if (tag === 'div') return 'bi bi-square';
|
|
6218
|
+
if (tag === 'address') return 'bi bi-geo-alt';
|
|
6219
|
+
|
|
6220
|
+
// Text content
|
|
6221
|
+
if (tag === 'p' || tag === 'span') return 'bi bi-text-left';
|
|
6222
|
+
if (tag === 'blockquote' || tag === 'q') return 'bi bi-blockquote-left';
|
|
6223
|
+
if (tag === 'pre') return 'bi bi-code-square';
|
|
6224
|
+
if (tag === 'code') return 'bi bi-code-slash';
|
|
6225
|
+
if (tag === 'kbd') return 'bi bi-keyboard';
|
|
6226
|
+
if (tag === 'samp') return 'bi bi-terminal';
|
|
6227
|
+
if (tag === 'var') return 'bi bi-braces';
|
|
6228
|
+
if (tag === 'cite') return 'bi bi-quote';
|
|
6229
|
+
if (tag === 'abbr') return 'bi bi-fonts';
|
|
6230
|
+
if (tag === 'time') return 'bi bi-clock';
|
|
6231
|
+
if (tag === 'mark') return 'bi bi-highlighter';
|
|
6232
|
+
if (tag === 'small') return 'bi bi-type';
|
|
6233
|
+
if (tag === 'sub') return 'bi bi-subscript';
|
|
6234
|
+
if (tag === 'sup') return 'bi bi-superscript';
|
|
6235
|
+
if (tag === 'br') return 'bi bi-arrow-return-left';
|
|
6236
|
+
if (tag === 'wbr') return 'bi bi-distribute-horizontal';
|
|
6237
|
+
|
|
6238
|
+
// Inline formatting
|
|
6239
|
+
if (tag === 'strong' || tag === 'b') return 'bi bi-type-bold';
|
|
6240
|
+
if (tag === 'em' || tag === 'i') return 'bi bi-type-italic';
|
|
6241
|
+
if (tag === 'u' || tag === 'ins') return 'bi bi-type-underline';
|
|
6242
|
+
if (tag === 's' || tag === 'del' || tag === 'strike') return 'bi bi-type-strikethrough';
|
|
6243
|
+
|
|
6244
|
+
// Lists
|
|
6245
|
+
if (tag === 'ul') return 'bi bi-list-ul';
|
|
6246
|
+
if (tag === 'ol') return 'bi bi-list-ol';
|
|
6247
|
+
if (tag === 'li') return 'bi bi-dot';
|
|
6248
|
+
if (tag === 'dl') return 'bi bi-card-list';
|
|
6249
|
+
if (tag === 'dt') return 'bi bi-tag';
|
|
6250
|
+
if (tag === 'dd') return 'bi bi-text-indent-left';
|
|
6251
|
+
|
|
6252
|
+
// Links & navigation
|
|
6253
|
+
if (tag === 'a') return 'bi bi-link-45deg';
|
|
6254
|
+
|
|
6255
|
+
// Media
|
|
6256
|
+
if (tag === 'img') return 'bi bi-image';
|
|
6257
|
+
if (tag === 'picture') return 'bi bi-images';
|
|
6258
|
+
if (tag === 'figure') return 'bi bi-card-image';
|
|
6259
|
+
if (tag === 'figcaption') return 'bi bi-card-text';
|
|
6260
|
+
if (tag === 'video') return 'bi bi-camera-video';
|
|
6261
|
+
if (tag === 'audio') return 'bi bi-music-note-beamed';
|
|
6262
|
+
if (tag === 'source') return 'bi bi-cloud-arrow-down';
|
|
6263
|
+
if (tag === 'track') return 'bi bi-badge-cc';
|
|
6264
|
+
if (tag === 'iframe') return 'bi bi-window';
|
|
6265
|
+
if (tag === 'embed' || tag === 'object') return 'bi bi-box-arrow-in-down';
|
|
6266
|
+
if (tag === 'param') return 'bi bi-sliders';
|
|
6267
|
+
if (tag === 'canvas') return 'bi bi-easel';
|
|
6268
|
+
if (tag === 'map') return 'bi bi-map';
|
|
6269
|
+
if (tag === 'area') return 'bi bi-bounding-box';
|
|
6270
|
+
|
|
6271
|
+
// Vector / math
|
|
6272
|
+
if (tag === 'svg') return 'bi bi-bezier2';
|
|
6273
|
+
if (tag === 'path') return 'bi bi-bezier';
|
|
6274
|
+
if (tag === 'circle') return 'bi bi-circle';
|
|
6275
|
+
if (tag === 'rect') return 'bi bi-square';
|
|
6276
|
+
if (tag === 'line') return 'bi bi-slash-lg';
|
|
6277
|
+
if (tag === 'polygon') return 'bi bi-pentagon';
|
|
6278
|
+
if (tag === 'polyline') return 'bi bi-share';
|
|
6279
|
+
if (tag === 'ellipse') return 'bi bi-circle-half';
|
|
6280
|
+
if (tag === 'g') return 'bi bi-collection';
|
|
6281
|
+
if (tag === 'use') return 'bi bi-arrow-repeat';
|
|
6282
|
+
if (tag === 'defs') return 'bi bi-bookmark';
|
|
6283
|
+
if (tag === 'symbol') return 'bi bi-star';
|
|
6284
|
+
if (tag === 'text') return 'bi bi-fonts';
|
|
6285
|
+
if (tag === 'math') return 'bi bi-calculator';
|
|
6286
|
+
|
|
6287
|
+
// Forms
|
|
6288
|
+
if (tag === 'form') return 'bi bi-file-earmark-check';
|
|
6289
|
+
if (tag === 'fieldset') return 'bi bi-bounding-box-circles';
|
|
6290
|
+
if (tag === 'legend') return 'bi bi-tag-fill';
|
|
6291
|
+
if (tag === 'label') return 'bi bi-tag';
|
|
6292
|
+
if (tag === 'input') return 'bi bi-input-cursor-text';
|
|
6293
|
+
if (tag === 'button') return 'bi bi-ui-radios';
|
|
6294
|
+
if (tag === 'select') return 'bi bi-menu-button';
|
|
6295
|
+
if (tag === 'option') return 'bi bi-check2-square';
|
|
6296
|
+
if (tag === 'optgroup') return 'bi bi-list-nested';
|
|
6297
|
+
if (tag === 'textarea') return 'bi bi-textarea-resize';
|
|
6298
|
+
if (tag === 'datalist') return 'bi bi-list-columns';
|
|
6299
|
+
if (tag === 'output') return 'bi bi-box-arrow-right';
|
|
6300
|
+
if (tag === 'progress') return 'bi bi-bar-chart-line';
|
|
6301
|
+
if (tag === 'meter') return 'bi bi-speedometer2';
|
|
6302
|
+
|
|
6303
|
+
// Tables
|
|
6304
|
+
if (tag === 'table') return 'bi bi-table';
|
|
6305
|
+
if (tag === 'caption') return 'bi bi-card-heading';
|
|
6306
|
+
if (tag === 'thead') return 'bi bi-layout-text-window';
|
|
6307
|
+
if (tag === 'tbody') return 'bi bi-layout-text-sidebar';
|
|
6308
|
+
if (tag === 'tfoot') return 'bi bi-layout-text-window-reverse';
|
|
6309
|
+
if (tag === 'tr') return 'bi bi-grip-horizontal';
|
|
6310
|
+
if (tag === 'th') return 'bi bi-grid-3x3-gap-fill';
|
|
6311
|
+
if (tag === 'td') return 'bi bi-grid-3x3-gap';
|
|
6312
|
+
if (tag === 'col') return 'bi bi-layout-three-columns';
|
|
6313
|
+
if (tag === 'colgroup') return 'bi bi-columns-gap';
|
|
6314
|
+
|
|
6315
|
+
// Interactive / disclosure
|
|
6316
|
+
if (tag === 'details') return 'bi bi-caret-down-square';
|
|
6317
|
+
if (tag === 'summary') return 'bi bi-card-text';
|
|
6318
|
+
if (tag === 'dialog') return 'bi bi-chat-square-text';
|
|
6319
|
+
if (tag === 'menu') return 'bi bi-list';
|
|
6320
|
+
|
|
6321
|
+
// Web components / templating
|
|
6322
|
+
if (tag === 'template') return 'bi bi-file-earmark-code';
|
|
6323
|
+
if (tag === 'slot') return 'bi bi-box-seam';
|
|
6324
|
+
|
|
6325
|
+
// Ruby annotation
|
|
6326
|
+
if (tag === 'ruby' || tag === 'rt' || tag === 'rp' || tag === 'rb')
|
|
6327
|
+
return 'bi bi-translate';
|
|
6328
|
+
if (tag === 'bdi' || tag === 'bdo') return 'bi bi-arrow-left-right';
|
|
6329
|
+
|
|
6330
|
+
// Misc
|
|
6331
|
+
if (tag === 'hr') return 'bi bi-hr';
|
|
6332
|
+
if (tag === '#text' || tag === 'text-node') return 'bi bi-cursor-text';
|
|
6333
|
+
if (tag === '#comment') return 'bi bi-chat-left-text';
|
|
6334
|
+
|
|
6335
|
+
return 'bi bi-square';
|
|
6336
|
+
}
|
|
6337
|
+
|
|
6185
6338
|
|
|
6186
6339
|
var nodes = collectEditorInsertedElements(doc);
|
|
6187
6340
|
|
|
@@ -6448,11 +6601,64 @@ function isFormControlElement(el) {
|
|
|
6448
6601
|
function shouldShowInnerContentFields(el) {
|
|
6449
6602
|
if (!el || el.nodeType !== 1) return false;
|
|
6450
6603
|
var tag = (el.tagName || '').toLowerCase();
|
|
6451
|
-
if (tag === 'input' || tag === 'textarea' || tag === 'video') return false;
|
|
6604
|
+
if (tag === 'input' || tag === 'textarea' || tag === 'select' || tag === 'video') return false;
|
|
6452
6605
|
if (isEmbeddedVideoIframe(el)) return false;
|
|
6453
6606
|
return true;
|
|
6454
6607
|
}
|
|
6455
6608
|
|
|
6609
|
+
function getSelectOptionsText(el) {
|
|
6610
|
+
if (!el || el.nodeType !== 1) return '';
|
|
6611
|
+
try {
|
|
6612
|
+
var opts = el.querySelectorAll('option');
|
|
6613
|
+
var lines = [];
|
|
6614
|
+
for (var i = 0; i < opts.length; i++) {
|
|
6615
|
+
lines.push(opts[i].textContent || '');
|
|
6616
|
+
}
|
|
6617
|
+
return lines.join('\\n');
|
|
6618
|
+
} catch(_) {
|
|
6619
|
+
return '';
|
|
6620
|
+
}
|
|
6621
|
+
}
|
|
6622
|
+
|
|
6623
|
+
function selectOptionsTextToHtml(text) {
|
|
6624
|
+
var lines = String(text == null ? '' : text).split('\\n');
|
|
6625
|
+
var parts = [];
|
|
6626
|
+
for (var i = 0; i < lines.length; i++) {
|
|
6627
|
+
var label = lines[i];
|
|
6628
|
+
if (!label && i === lines.length - 1 && lines.length > 1) continue;
|
|
6629
|
+
parts.push('<option>' + esc(label) + '</option>');
|
|
6630
|
+
}
|
|
6631
|
+
if (!parts.length) parts.push('<option>Option 1</option>');
|
|
6632
|
+
return parts.join('');
|
|
6633
|
+
}
|
|
6634
|
+
|
|
6635
|
+
function applySelectOptionsFromText(el, text) {
|
|
6636
|
+
if (!el || el.nodeType !== 1) return;
|
|
6637
|
+
beginSuppressIframeMutationDirty();
|
|
6638
|
+
try {
|
|
6639
|
+
var prevValue = '';
|
|
6640
|
+
try { prevValue = el.value || ''; } catch(_) {}
|
|
6641
|
+
var doc = el.ownerDocument;
|
|
6642
|
+
while (el.firstChild) el.removeChild(el.firstChild);
|
|
6643
|
+
var lines = String(text == null ? '' : text).split('\\n');
|
|
6644
|
+
if (!lines.length || (lines.length === 1 && !String(lines[0] || '').trim())) {
|
|
6645
|
+
lines = ['Option 1', 'Option 2'];
|
|
6646
|
+
}
|
|
6647
|
+
for (var i = 0; i < lines.length; i++) {
|
|
6648
|
+
var label = lines[i];
|
|
6649
|
+
if (!label && i === lines.length - 1) continue;
|
|
6650
|
+
var opt = doc.createElement('option');
|
|
6651
|
+
opt.textContent = label;
|
|
6652
|
+
el.appendChild(opt);
|
|
6653
|
+
}
|
|
6654
|
+
if (prevValue) {
|
|
6655
|
+
try { el.value = prevValue; } catch(_) {}
|
|
6656
|
+
}
|
|
6657
|
+
} finally {
|
|
6658
|
+
endSuppressIframeMutationDirty();
|
|
6659
|
+
}
|
|
6660
|
+
}
|
|
6661
|
+
|
|
6456
6662
|
function elementHasHtmlChildren(el) {
|
|
6457
6663
|
if (!el || el.nodeType !== 1) return false;
|
|
6458
6664
|
try {
|
|
@@ -7111,6 +7317,12 @@ function renderRightPanel(el, options) {
|
|
|
7111
7317
|
subLbl('Placeholder') +
|
|
7112
7318
|
'<input class="pr-inp" id="pp-ph" type="text" value="'+esc(el.getAttribute('placeholder')||'')+'" style="width:100%;margin-bottom:8px">';
|
|
7113
7319
|
}
|
|
7320
|
+
if (tag === 'select') {
|
|
7321
|
+
contentHtml +=
|
|
7322
|
+
subLbl('Options') +
|
|
7323
|
+
'<div style="font-size:11px;color:var(--text-3);margin:-4px 0 8px">One option label per line</div>' +
|
|
7324
|
+
'<textarea class="pr-inp" id="pp-select-options" style="width:100%;min-height:80px;font-family:var(--font-mono);font-size:11px">'+esc(getSelectOptionsText(el))+'</textarea>';
|
|
7325
|
+
}
|
|
7114
7326
|
if (shouldShowInnerContentFields(el)) {
|
|
7115
7327
|
if (elementHasHtmlChildren(el)) {
|
|
7116
7328
|
contentHtml +=
|
|
@@ -7218,18 +7430,49 @@ function renderRightPanel(el, options) {
|
|
|
7218
7430
|
function wireContentFieldSync(el, sel) {
|
|
7219
7431
|
var textInp = document.getElementById('pp-text');
|
|
7220
7432
|
var htmlInp = document.getElementById('pp-html');
|
|
7433
|
+
var selectOptsInp = document.getElementById('pp-select-options');
|
|
7221
7434
|
var syncing = false;
|
|
7222
|
-
|
|
7435
|
+
var htmlApplyTimer = null;
|
|
7436
|
+
var selectApplyTimer = null;
|
|
7437
|
+
|
|
7438
|
+
function applyHtmlToElement(htmlValue) {
|
|
7439
|
+
beginSuppressIframeMutationDirty();
|
|
7440
|
+
try {
|
|
7441
|
+
el.innerHTML = htmlValue;
|
|
7442
|
+
} finally {
|
|
7443
|
+
endSuppressIframeMutationDirty();
|
|
7444
|
+
}
|
|
7445
|
+
}
|
|
7446
|
+
|
|
7447
|
+
function applyContentChange(changedId, immediate) {
|
|
7223
7448
|
if (syncing) return;
|
|
7449
|
+
if (changedId === 'pp-html' && !immediate) {
|
|
7450
|
+
if (htmlApplyTimer) clearTimeout(htmlApplyTimer);
|
|
7451
|
+
htmlApplyTimer = setTimeout(function() { applyContentChange('pp-html', true); }, 250);
|
|
7452
|
+
return;
|
|
7453
|
+
}
|
|
7454
|
+
if (changedId === 'pp-select-options' && !immediate) {
|
|
7455
|
+
if (selectApplyTimer) clearTimeout(selectApplyTimer);
|
|
7456
|
+
selectApplyTimer = setTimeout(function() { applyContentChange('pp-select-options', true); }, 250);
|
|
7457
|
+
return;
|
|
7458
|
+
}
|
|
7224
7459
|
syncing = true;
|
|
7225
7460
|
try {
|
|
7226
7461
|
var orig = getOriginalValue(changedId, el);
|
|
7227
7462
|
if (changedId === 'pp-text') {
|
|
7228
|
-
|
|
7463
|
+
beginSuppressIframeMutationDirty();
|
|
7464
|
+
try {
|
|
7465
|
+
el.innerText = textInp.value;
|
|
7466
|
+
} finally {
|
|
7467
|
+
endSuppressIframeMutationDirty();
|
|
7468
|
+
}
|
|
7229
7469
|
if (htmlInp) htmlInp.value = el.innerHTML;
|
|
7230
7470
|
logChange(sel, 'pp-text', textInp.value, el, orig);
|
|
7471
|
+
} else if (changedId === 'pp-select-options') {
|
|
7472
|
+
applySelectOptionsFromText(el, selectOptsInp.value);
|
|
7473
|
+
logChange(sel, 'pp-select-options', selectOptsInp.value, el, orig);
|
|
7231
7474
|
} else {
|
|
7232
|
-
|
|
7475
|
+
applyHtmlToElement(htmlInp.value);
|
|
7233
7476
|
if (textInp) textInp.value = el.innerText;
|
|
7234
7477
|
logChange(sel, 'pp-html', htmlInp.value, el, orig);
|
|
7235
7478
|
}
|
|
@@ -7242,8 +7485,12 @@ function wireContentFieldSync(el, sel) {
|
|
|
7242
7485
|
textInp.addEventListener('change', function() { applyContentChange('pp-text'); });
|
|
7243
7486
|
}
|
|
7244
7487
|
if (htmlInp) {
|
|
7245
|
-
htmlInp.addEventListener('input', function() { applyContentChange('pp-html'); });
|
|
7246
|
-
htmlInp.addEventListener('change', function() { applyContentChange('pp-html'); });
|
|
7488
|
+
htmlInp.addEventListener('input', function() { applyContentChange('pp-html', false); });
|
|
7489
|
+
htmlInp.addEventListener('change', function() { applyContentChange('pp-html', true); });
|
|
7490
|
+
}
|
|
7491
|
+
if (selectOptsInp) {
|
|
7492
|
+
selectOptsInp.addEventListener('input', function() { applyContentChange('pp-select-options', false); });
|
|
7493
|
+
selectOptsInp.addEventListener('change', function() { applyContentChange('pp-select-options', true); });
|
|
7247
7494
|
}
|
|
7248
7495
|
}
|
|
7249
7496
|
|
|
@@ -7734,14 +7981,21 @@ function attachChangeObserver() {
|
|
|
7734
7981
|
changeObserverDoc = null;
|
|
7735
7982
|
}
|
|
7736
7983
|
changeObserver = new MutationObserver(function(mutations) {
|
|
7984
|
+
if (suppressIframeMutationDirty > 0) return;
|
|
7737
7985
|
var hasMeaningfulMutation = false;
|
|
7738
7986
|
for (var mi = 0; mi < mutations.length; mi++) {
|
|
7739
|
-
if (!
|
|
7987
|
+
if (!isEditorChromeOnlyClassMutation(mutations[mi])) {
|
|
7740
7988
|
hasMeaningfulMutation = true;
|
|
7741
7989
|
break;
|
|
7742
7990
|
}
|
|
7743
7991
|
}
|
|
7744
7992
|
if (!hasMeaningfulMutation) return;
|
|
7993
|
+
var activeId = '';
|
|
7994
|
+
try { activeId = document.activeElement && document.activeElement.id ? String(document.activeElement.id) : ''; } catch(_) {}
|
|
7995
|
+
if (activeId === 'pp-html' || activeId === 'pp-text' || activeId === 'pp-select-options') {
|
|
7996
|
+
scheduleDomTreeRefresh();
|
|
7997
|
+
return;
|
|
7998
|
+
}
|
|
7745
7999
|
// Dirty state is derived from changesets baseline + stateChanges (not raw DOM mutations).
|
|
7746
8000
|
// Host scripts can replace selected nodes every few frames (e.g. A/B tool observers).
|
|
7747
8001
|
// Keep selection sticky by re-resolving from fingerprint.
|
|
@@ -8237,7 +8491,9 @@ window.addEventListener('load', function() {
|
|
|
8237
8491
|
return;
|
|
8238
8492
|
}
|
|
8239
8493
|
hideIframeLoadError();
|
|
8240
|
-
|
|
8494
|
+
var iframeLiveUrl = '';
|
|
8495
|
+
try { iframeLiveUrl = String(iframe.contentWindow.location.href || ''); } catch(_) {}
|
|
8496
|
+
emitEditorUrlChanged(iframeLiveUrl || docUrl || iframe.src || '');
|
|
8241
8497
|
// Stale events: src may already be the proxy URL while the document is still
|
|
8242
8498
|
// about:blank (e.g. src cleared then reset to force reload). Ask sync path to retry.
|
|
8243
8499
|
if (docUrl === 'about:blank') {
|
|
@@ -8622,6 +8878,11 @@ function createVisualEditorMiddleware(options) {
|
|
|
8622
8878
|
}
|
|
8623
8879
|
if (chunks.length > 0) requestBody = Buffer.concat(chunks);
|
|
8624
8880
|
}
|
|
8881
|
+
const secFetchMode = (req.headers?.["sec-fetch-mode"] || "").toLowerCase();
|
|
8882
|
+
const secFetchDest = (req.headers?.["sec-fetch-dest"] || "").toLowerCase();
|
|
8883
|
+
const isLikelyDocumentNavigation = secFetchMode === "navigate" || secFetchDest === "iframe" || secFetchDest === "document" || secFetchDest === "nested-document" || secFetchDest === "frame";
|
|
8884
|
+
const isLikelyFetchOrXHR = secFetchDest === "empty" && (secFetchMode === "cors" || secFetchMode === "same-origin" || secFetchMode === "no-cors");
|
|
8885
|
+
const passthroughUpstreamRedirects = (method === "GET" || method === "HEAD") && (isLikelyDocumentNavigation || !isLikelyFetchOrXHR);
|
|
8625
8886
|
const upstreamTimeoutMs = 12e4;
|
|
8626
8887
|
const ac = new AbortController();
|
|
8627
8888
|
const timeoutId = setTimeout(() => ac.abort(), upstreamTimeoutMs);
|
|
@@ -8631,7 +8892,7 @@ function createVisualEditorMiddleware(options) {
|
|
|
8631
8892
|
method,
|
|
8632
8893
|
headers: fetchHeaders,
|
|
8633
8894
|
body: requestBody ? Buffer.from(requestBody) : null,
|
|
8634
|
-
redirect: "follow",
|
|
8895
|
+
redirect: passthroughUpstreamRedirects ? "manual" : "follow",
|
|
8635
8896
|
signal: ac.signal
|
|
8636
8897
|
});
|
|
8637
8898
|
} catch (fetchErr) {
|
|
@@ -8655,12 +8916,43 @@ function createVisualEditorMiddleware(options) {
|
|
|
8655
8916
|
return;
|
|
8656
8917
|
}
|
|
8657
8918
|
clearTimeout(timeoutId);
|
|
8919
|
+
if (passthroughUpstreamRedirects && upstream.status >= 300 && upstream.status < 400) {
|
|
8920
|
+
const locationHeader = upstream.headers.get("location") || upstream.headers.get("Location");
|
|
8921
|
+
if (locationHeader) {
|
|
8922
|
+
try {
|
|
8923
|
+
const redirectTarget = new URL(locationHeader, targetUrl);
|
|
8924
|
+
if (redirectTarget.origin === origin) {
|
|
8925
|
+
const proxyRedirect = new URL(proxyRootForRequest, "http://localhost");
|
|
8926
|
+
proxyRedirect.searchParams.set("password", password);
|
|
8927
|
+
proxyRedirect.searchParams.set("url", redirectTarget.toString());
|
|
8928
|
+
url.searchParams.forEach((value, key) => {
|
|
8929
|
+
if (key === "url" || key === "password") return;
|
|
8930
|
+
proxyRedirect.searchParams.set(key, value);
|
|
8931
|
+
});
|
|
8932
|
+
res.statusCode = upstream.status === 303 ? 303 : 302;
|
|
8933
|
+
res.setHeader("Location", `${proxyRedirect.pathname}${proxyRedirect.search}`);
|
|
8934
|
+
res.setHeader("Cache-Control", "no-store");
|
|
8935
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
8936
|
+
setFrameHeaders(req, res);
|
|
8937
|
+
res.end();
|
|
8938
|
+
return;
|
|
8939
|
+
}
|
|
8940
|
+
res.statusCode = 502;
|
|
8941
|
+
res.setHeader("Content-Type", "application/json");
|
|
8942
|
+
res.end(
|
|
8943
|
+
JSON.stringify({
|
|
8944
|
+
error: "Cross-origin redirect blocked in editor preview",
|
|
8945
|
+
location: redirectTarget.toString(),
|
|
8946
|
+
from: targetUrl
|
|
8947
|
+
})
|
|
8948
|
+
);
|
|
8949
|
+
return;
|
|
8950
|
+
} catch (_) {
|
|
8951
|
+
}
|
|
8952
|
+
}
|
|
8953
|
+
}
|
|
8658
8954
|
const responseContentType = upstream.headers.get("content-type") || "";
|
|
8659
8955
|
const isHtmlResponse = responseContentType.includes("text/html");
|
|
8660
|
-
const secFetchMode = (req.headers?.["sec-fetch-mode"] || "").toLowerCase();
|
|
8661
|
-
const secFetchDest = (req.headers?.["sec-fetch-dest"] || "").toLowerCase();
|
|
8662
|
-
const isLikelyDocumentNavigation = secFetchMode === "navigate" || secFetchDest === "iframe" || secFetchDest === "document" || secFetchDest === "nested-document" || secFetchDest === "frame";
|
|
8663
|
-
const isLikelyFetchOrXHR = secFetchDest === "empty" && (secFetchMode === "cors" || secFetchMode === "same-origin" || secFetchMode === "no-cors");
|
|
8664
8956
|
const shouldInjectHtmlBridge = isHtmlResponse && (isLikelyDocumentNavigation || !isLikelyFetchOrXHR);
|
|
8665
8957
|
if (!isHtmlResponse || !shouldInjectHtmlBridge) {
|
|
8666
8958
|
const binary = Buffer.from(await upstream.arrayBuffer());
|
|
@@ -8714,6 +9006,18 @@ ${iframeAlwaysShowCssGuardScript}
|
|
|
8714
9006
|
/<meta[^>]+name=["']?\s*content-security-policy\s*["']?[^>]*>/gi,
|
|
8715
9007
|
""
|
|
8716
9008
|
);
|
|
9009
|
+
html = html.replace(
|
|
9010
|
+
/(<meta[^>]+http-equiv=["']?refresh["']?[^>]*content=["'][^"']*url=)([^"';]+)(["'][^>]*>)/gi,
|
|
9011
|
+
(match, prefix, urlPart, suffix) => {
|
|
9012
|
+
try {
|
|
9013
|
+
const abs = new URL(String(urlPart).trim(), origin).toString();
|
|
9014
|
+
if (new URL(abs).origin !== origin) return match;
|
|
9015
|
+
return `${prefix}${proxyBase}${encodeURIComponent(abs)}${suffix}`;
|
|
9016
|
+
} catch {
|
|
9017
|
+
return match;
|
|
9018
|
+
}
|
|
9019
|
+
}
|
|
9020
|
+
);
|
|
8717
9021
|
const runtimePreflightScript = `<script>(function(){try{
|
|
8718
9022
|
var TARGET_ORIGIN=${JSON.stringify(origin)};
|
|
8719
9023
|
var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};
|
|
@@ -8920,6 +9224,8 @@ try{if(window.history&&typeof window.history.pushState==="function"){var nativeP
|
|
|
8920
9224
|
try{if(window.history&&typeof window.history.replaceState==="function"){var nativeReplaceState=window.history.replaceState;window.history.replaceState=function(){var ret=nativeReplaceState.apply(window.history,arguments);setTimeout(notifyEditorUrlChanged,0);return ret;};}}catch(_){}
|
|
8921
9225
|
try{window.addEventListener("popstate",notifyEditorUrlChanged,true);}catch(_){}
|
|
8922
9226
|
try{window.addEventListener("hashchange",notifyEditorUrlChanged,true);}catch(_){}
|
|
9227
|
+
try{window.addEventListener("pageshow",notifyEditorUrlChanged,true);}catch(_){}
|
|
9228
|
+
try{window.addEventListener("load",function(){setTimeout(notifyEditorUrlChanged,0);},true);}catch(_){}
|
|
8923
9229
|
function isSkippable(raw){if(!raw||typeof raw!=="string")return true;return raw.startsWith("data:")||raw.startsWith("blob:")||raw.startsWith("javascript:")||raw.startsWith("#");}
|
|
8924
9230
|
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;}}
|
|
8925
9231
|
function toProxy(raw){
|
|
@@ -8948,6 +9254,9 @@ function toProxy(raw){
|
|
|
8948
9254
|
var nativeAssign=window.location.assign?window.location.assign.bind(window.location):null;
|
|
8949
9255
|
var nativeReplace=window.location.replace?window.location.replace.bind(window.location):null;
|
|
8950
9256
|
function safeNavigate(raw,mode){var abs=toAbsolute(raw);var prox=toProxy(raw);if(!prox){try{console.warn("[conversion-proxy] redirect blocked",{mode:mode,requested:raw,resolved:abs,origin:TARGET_ORIGIN});}catch(_){}return false;}try{console.info("[conversion-proxy] redirect intercepted",{mode:mode,requested:raw,resolved:abs,proxied:prox});if(mode==="replace"&&nativeReplace){nativeReplace(prox);return true;}if(nativeAssign){nativeAssign(prox);return true;}window.location.href=prox;return true;}catch(err){try{console.warn("[conversion-proxy] redirect interception failed",{mode:mode,requested:raw,resolved:abs,proxied:prox,error:err&&err.message?err.message:String(err)});}catch(_){}return false;}}
|
|
9257
|
+
function interceptMetaRefresh(){try{var metas=document.querySelectorAll('meta[http-equiv="refresh" i],meta[http-equiv="Refresh"]');for(var i=0;i<metas.length;i++){var content=metas[i].getAttribute("content")||"";var m=content.match(/url=(.+)$/i);if(!m)continue;var raw=m[1].trim().replace(/^['"]|['"]$/g,"");if(safeNavigate(raw,"replace"))metas[i].parentNode&&metas[i].parentNode.removeChild(metas[i]);}}catch(_){}}
|
|
9258
|
+
try{interceptMetaRefresh();}catch(_){}
|
|
9259
|
+
try{document.addEventListener("DOMContentLoaded",interceptMetaRefresh,true);}catch(_){}
|
|
8951
9260
|
try{if(nativeAssign){window.location.assign=function(url){return safeNavigate(url,"assign");};}}catch(_){}
|
|
8952
9261
|
try{if(nativeReplace){window.location.replace=function(url){return safeNavigate(url,"replace");};}}catch(_){}
|
|
8953
9262
|
try{var hrefDesc=Object.getOwnPropertyDescriptor(Location.prototype,"href");if(hrefDesc&&hrefDesc.configurable&&hrefDesc.get&&hrefDesc.set){Object.defineProperty(Location.prototype,"href",{configurable:true,enumerable:hrefDesc.enumerable,get:function(){return hrefDesc.get.call(this);},set:function(v){safeNavigate(v,"assign");}});}}catch(_){}
|