@burger-editor/client 4.0.0-alpha.63 → 4.0.0-alpha.64
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/client.js +584 -719
- package/dist/client.js.map +1 -1
- package/package.json +6 -6
package/dist/client.js
CHANGED
|
@@ -1266,7 +1266,6 @@ function setValue(el, name, datum, attr = 'field', filter, xssSanitize = true) {
|
|
|
1266
1266
|
if (filter) {
|
|
1267
1267
|
datum = filter(datum);
|
|
1268
1268
|
}
|
|
1269
|
-
// console.log({ name, field, fieldName, propName, datum, el: el.innerHTML });
|
|
1270
1269
|
if (!propName) {
|
|
1271
1270
|
setContent$1(el, datum, undefined, xssSanitize);
|
|
1272
1271
|
return;
|
|
@@ -1315,6 +1314,53 @@ function setValue(el, name, datum, attr = 'field', filter, xssSanitize = true) {
|
|
|
1315
1314
|
}
|
|
1316
1315
|
el.setAttribute(propName, `${datum}`);
|
|
1317
1316
|
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Set a boolean attribute on an element via its DOM property.
|
|
1319
|
+
* Empty string is treated as true (HTML boolean attribute convention).
|
|
1320
|
+
* Falls back to setAttribute if the element doesn't match any of the expected types.
|
|
1321
|
+
* @param el
|
|
1322
|
+
* @param datum
|
|
1323
|
+
* @param types
|
|
1324
|
+
* @param prop
|
|
1325
|
+
* @param emptyIsTrue
|
|
1326
|
+
* @returns true if handled
|
|
1327
|
+
*/
|
|
1328
|
+
function setBooleanAttr(el, datum, types, prop, emptyIsTrue = true) {
|
|
1329
|
+
if (types.some((T) => el instanceof T)) {
|
|
1330
|
+
// SAFETY: prop is always a hardcoded string literal from setBooleanAttrByName
|
|
1331
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1332
|
+
el[prop] = emptyIsTrue ? (datum === '' ? true : !!datum) : !!datum;
|
|
1333
|
+
return true;
|
|
1334
|
+
}
|
|
1335
|
+
return false;
|
|
1336
|
+
}
|
|
1337
|
+
/**
|
|
1338
|
+
* Set an integer attribute on an element via its DOM property.
|
|
1339
|
+
* Removes the attribute if the parsed value is NaN.
|
|
1340
|
+
* Falls back to setAttribute if the element doesn't match any of the expected types.
|
|
1341
|
+
* @param el
|
|
1342
|
+
* @param name
|
|
1343
|
+
* @param datum
|
|
1344
|
+
* @param types
|
|
1345
|
+
* @param prop
|
|
1346
|
+
* @param floor
|
|
1347
|
+
* @returns true if handled
|
|
1348
|
+
*/
|
|
1349
|
+
function setIntegerAttr(el, name, datum, types, prop, floor = false) {
|
|
1350
|
+
if (types.some((T) => el instanceof T)) {
|
|
1351
|
+
const val = toInt(datum);
|
|
1352
|
+
if (Number.isNaN(val)) {
|
|
1353
|
+
el.removeAttribute(name);
|
|
1354
|
+
}
|
|
1355
|
+
else {
|
|
1356
|
+
// SAFETY: prop is always a hardcoded string literal from setIntegerAttrByName
|
|
1357
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1358
|
+
el[prop] = floor ? Math.floor(val) : val;
|
|
1359
|
+
}
|
|
1360
|
+
return true;
|
|
1361
|
+
}
|
|
1362
|
+
return false;
|
|
1363
|
+
}
|
|
1318
1364
|
/**
|
|
1319
1365
|
*
|
|
1320
1366
|
* @param el
|
|
@@ -1374,6 +1420,25 @@ function set$1(el, prefix, name, datum, xssSanitize = true) {
|
|
|
1374
1420
|
}
|
|
1375
1421
|
return;
|
|
1376
1422
|
}
|
|
1423
|
+
if (setSpecialAttr(el, name, datum)) {
|
|
1424
|
+
return;
|
|
1425
|
+
}
|
|
1426
|
+
if (setBooleanAttrByName(el, name, datum)) {
|
|
1427
|
+
return;
|
|
1428
|
+
}
|
|
1429
|
+
if (setIntegerAttrByName(el, name, datum)) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
el.setAttribute(name, `${datum}`);
|
|
1433
|
+
}
|
|
1434
|
+
/**
|
|
1435
|
+
* Handle attributes with unique logic that doesn't fit boolean/integer patterns.
|
|
1436
|
+
* @param el
|
|
1437
|
+
* @param name
|
|
1438
|
+
* @param datum
|
|
1439
|
+
* @returns true if handled
|
|
1440
|
+
*/
|
|
1441
|
+
function setSpecialAttr(el, name, datum) {
|
|
1377
1442
|
switch (name) {
|
|
1378
1443
|
case 'contenteditable': {
|
|
1379
1444
|
switch (datum) {
|
|
@@ -1387,7 +1452,7 @@ function set$1(el, prefix, name, datum, xssSanitize = true) {
|
|
|
1387
1452
|
el.removeAttribute(name);
|
|
1388
1453
|
}
|
|
1389
1454
|
}
|
|
1390
|
-
return;
|
|
1455
|
+
return true;
|
|
1391
1456
|
}
|
|
1392
1457
|
case 'dir': {
|
|
1393
1458
|
switch (datum) {
|
|
@@ -1396,45 +1461,45 @@ function set$1(el, prefix, name, datum, xssSanitize = true) {
|
|
|
1396
1461
|
el.dir = datum;
|
|
1397
1462
|
break;
|
|
1398
1463
|
}
|
|
1399
|
-
// case 'auto':
|
|
1400
1464
|
default: {
|
|
1401
1465
|
el.removeAttribute(name);
|
|
1402
1466
|
}
|
|
1403
1467
|
}
|
|
1404
|
-
return;
|
|
1468
|
+
return true;
|
|
1405
1469
|
}
|
|
1406
1470
|
case 'draggable': {
|
|
1407
1471
|
if (typeof datum === 'boolean') {
|
|
1408
1472
|
el.draggable = datum;
|
|
1409
|
-
break;
|
|
1410
1473
|
}
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1474
|
+
else {
|
|
1475
|
+
switch (datum) {
|
|
1476
|
+
case 'true': {
|
|
1477
|
+
el.draggable = true;
|
|
1478
|
+
break;
|
|
1479
|
+
}
|
|
1480
|
+
case 'false': {
|
|
1481
|
+
el.draggable = false;
|
|
1482
|
+
break;
|
|
1483
|
+
}
|
|
1484
|
+
default: {
|
|
1485
|
+
el.removeAttribute(name);
|
|
1486
|
+
}
|
|
1423
1487
|
}
|
|
1424
1488
|
}
|
|
1425
|
-
return;
|
|
1489
|
+
return true;
|
|
1426
1490
|
}
|
|
1427
1491
|
case 'hidden': {
|
|
1428
1492
|
if (datum === 'until-found') {
|
|
1429
1493
|
el.setAttribute(name, datum);
|
|
1430
|
-
return;
|
|
1431
1494
|
}
|
|
1432
|
-
|
|
1433
|
-
|
|
1495
|
+
else {
|
|
1496
|
+
el.hidden = !!datum;
|
|
1497
|
+
}
|
|
1498
|
+
return true;
|
|
1434
1499
|
}
|
|
1435
1500
|
case 'spellcheck': {
|
|
1436
1501
|
el.spellcheck = !!datum;
|
|
1437
|
-
return;
|
|
1502
|
+
return true;
|
|
1438
1503
|
}
|
|
1439
1504
|
case 'tabindex': {
|
|
1440
1505
|
let i;
|
|
@@ -1445,501 +1510,224 @@ function set$1(el, prefix, name, datum, xssSanitize = true) {
|
|
|
1445
1510
|
i = Number.parseInt(datum, 10);
|
|
1446
1511
|
}
|
|
1447
1512
|
else {
|
|
1448
|
-
i = datum;
|
|
1513
|
+
i = datum ?? -1;
|
|
1449
1514
|
}
|
|
1450
1515
|
el.tabIndex = Number.isNaN(i) ? -1 : Math.floor(i);
|
|
1451
|
-
return;
|
|
1452
|
-
}
|
|
1453
|
-
case 'async': {
|
|
1454
|
-
if (el instanceof HTMLScriptElement) {
|
|
1455
|
-
el.async = !!datum;
|
|
1456
|
-
}
|
|
1457
|
-
else {
|
|
1458
|
-
el.setAttribute(name, `${datum}`);
|
|
1459
|
-
}
|
|
1460
|
-
return;
|
|
1516
|
+
return true;
|
|
1461
1517
|
}
|
|
1462
1518
|
case 'autocomplete': {
|
|
1463
1519
|
if (el instanceof HTMLInputElement || el instanceof HTMLFormElement) {
|
|
1464
|
-
|
|
1465
|
-
el.autocomplete = datum ? `${datum}` : 'off';
|
|
1520
|
+
el.setAttribute(name, datum ? `${datum}` : 'off');
|
|
1466
1521
|
}
|
|
1467
1522
|
else {
|
|
1468
1523
|
el.setAttribute(name, `${datum}`);
|
|
1469
1524
|
}
|
|
1470
|
-
return;
|
|
1525
|
+
return true;
|
|
1471
1526
|
}
|
|
1472
|
-
case '
|
|
1473
|
-
if (el instanceof
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1527
|
+
case 'download': {
|
|
1528
|
+
if (el instanceof HTMLAnchorElement) {
|
|
1529
|
+
if (datum || datum === '') {
|
|
1530
|
+
el.download = `${datum}`;
|
|
1531
|
+
}
|
|
1532
|
+
else {
|
|
1533
|
+
el.removeAttribute(name);
|
|
1534
|
+
}
|
|
1478
1535
|
}
|
|
1479
1536
|
else {
|
|
1480
1537
|
el.setAttribute(name, `${datum}`);
|
|
1481
1538
|
}
|
|
1482
|
-
return;
|
|
1539
|
+
return true;
|
|
1483
1540
|
}
|
|
1484
|
-
case '
|
|
1541
|
+
case 'preload': {
|
|
1485
1542
|
if (el instanceof HTMLAudioElement || el instanceof HTMLVideoElement) {
|
|
1486
|
-
|
|
1543
|
+
switch (datum) {
|
|
1544
|
+
case '':
|
|
1545
|
+
case 'auto':
|
|
1546
|
+
case 'metadata': {
|
|
1547
|
+
el.preload = datum;
|
|
1548
|
+
break;
|
|
1549
|
+
}
|
|
1550
|
+
default: {
|
|
1551
|
+
el.preload = 'none';
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1487
1554
|
}
|
|
1488
1555
|
else {
|
|
1489
1556
|
el.setAttribute(name, `${datum}`);
|
|
1490
1557
|
}
|
|
1491
|
-
return;
|
|
1558
|
+
return true;
|
|
1492
1559
|
}
|
|
1493
|
-
case '
|
|
1560
|
+
case 'step': {
|
|
1494
1561
|
if (el instanceof HTMLInputElement) {
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
else {
|
|
1498
|
-
el.setAttribute(name, `${datum}`);
|
|
1499
|
-
}
|
|
1500
|
-
return;
|
|
1501
|
-
}
|
|
1502
|
-
case 'cols': {
|
|
1503
|
-
if (el instanceof HTMLTextAreaElement) {
|
|
1504
|
-
const cols = toInt(datum);
|
|
1505
|
-
if (Number.isNaN(cols)) {
|
|
1506
|
-
el.removeAttribute(name);
|
|
1562
|
+
if (datum === 'any') {
|
|
1563
|
+
el.step = datum;
|
|
1507
1564
|
}
|
|
1508
1565
|
else {
|
|
1509
|
-
|
|
1566
|
+
const step = toNum(datum);
|
|
1567
|
+
if (Number.isNaN(step)) {
|
|
1568
|
+
el.removeAttribute(name);
|
|
1569
|
+
}
|
|
1570
|
+
else {
|
|
1571
|
+
el.step = step.toString(10);
|
|
1572
|
+
}
|
|
1510
1573
|
}
|
|
1511
1574
|
}
|
|
1512
1575
|
else {
|
|
1513
1576
|
el.setAttribute(name, `${datum}`);
|
|
1514
1577
|
}
|
|
1515
|
-
return;
|
|
1578
|
+
return true;
|
|
1516
1579
|
}
|
|
1517
|
-
case '
|
|
1518
|
-
if (el instanceof
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1580
|
+
case 'target': {
|
|
1581
|
+
if (el instanceof HTMLAnchorElement ||
|
|
1582
|
+
el instanceof HTMLAreaElement ||
|
|
1583
|
+
el instanceof HTMLFormElement) {
|
|
1584
|
+
if (datum) {
|
|
1585
|
+
el.target = `${datum}`;
|
|
1522
1586
|
}
|
|
1523
1587
|
else {
|
|
1524
|
-
el.
|
|
1588
|
+
el.removeAttribute(name);
|
|
1525
1589
|
}
|
|
1526
1590
|
}
|
|
1527
1591
|
else {
|
|
1528
1592
|
el.setAttribute(name, `${datum}`);
|
|
1529
1593
|
}
|
|
1530
|
-
return;
|
|
1594
|
+
return true;
|
|
1595
|
+
}
|
|
1596
|
+
default: {
|
|
1597
|
+
return false;
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
/**
|
|
1602
|
+
* Handle boolean HTML attributes via their DOM properties.
|
|
1603
|
+
* @param el
|
|
1604
|
+
* @param name
|
|
1605
|
+
* @param datum
|
|
1606
|
+
* @returns true if handled
|
|
1607
|
+
*/
|
|
1608
|
+
function setBooleanAttrByName(el, name, datum) {
|
|
1609
|
+
switch (name) {
|
|
1610
|
+
case 'async': {
|
|
1611
|
+
return setBooleanAttr(el, datum, [HTMLScriptElement], 'async', false);
|
|
1612
|
+
}
|
|
1613
|
+
case 'autofocus': {
|
|
1614
|
+
return setBooleanAttr(el, datum, [HTMLButtonElement, HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement], 'autofocus');
|
|
1615
|
+
}
|
|
1616
|
+
case 'autoplay': {
|
|
1617
|
+
return setBooleanAttr(el, datum, [HTMLAudioElement, HTMLVideoElement], 'autoplay');
|
|
1618
|
+
}
|
|
1619
|
+
case 'checked': {
|
|
1620
|
+
return setBooleanAttr(el, datum, [HTMLInputElement], 'checked');
|
|
1531
1621
|
}
|
|
1532
1622
|
case 'controls': {
|
|
1533
|
-
|
|
1534
|
-
el.controls = datum === '' ? true : !!datum;
|
|
1535
|
-
}
|
|
1536
|
-
else {
|
|
1537
|
-
el.setAttribute(name, `${datum}`);
|
|
1538
|
-
}
|
|
1539
|
-
return;
|
|
1623
|
+
return setBooleanAttr(el, datum, [HTMLAudioElement, HTMLVideoElement], 'controls');
|
|
1540
1624
|
}
|
|
1541
1625
|
case 'default': {
|
|
1542
|
-
|
|
1543
|
-
el.default = datum === '' ? true : !!datum;
|
|
1544
|
-
}
|
|
1545
|
-
else {
|
|
1546
|
-
el.setAttribute(name, `${datum}`);
|
|
1547
|
-
}
|
|
1548
|
-
return;
|
|
1626
|
+
return setBooleanAttr(el, datum, [HTMLTrackElement], 'default');
|
|
1549
1627
|
}
|
|
1550
1628
|
case 'defer': {
|
|
1551
|
-
|
|
1552
|
-
el.defer = !!datum;
|
|
1553
|
-
}
|
|
1554
|
-
else {
|
|
1555
|
-
el.setAttribute(name, `${datum}`);
|
|
1556
|
-
}
|
|
1557
|
-
return;
|
|
1629
|
+
return setBooleanAttr(el, datum, [HTMLScriptElement], 'defer', false);
|
|
1558
1630
|
}
|
|
1559
1631
|
case 'disabled': {
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
else {
|
|
1570
|
-
el.setAttribute(name, `${datum}`);
|
|
1571
|
-
}
|
|
1572
|
-
return;
|
|
1573
|
-
}
|
|
1574
|
-
case 'download': {
|
|
1575
|
-
if (el instanceof HTMLAnchorElement) {
|
|
1576
|
-
if (datum || datum === '') {
|
|
1577
|
-
el.download = `${datum}`;
|
|
1578
|
-
}
|
|
1579
|
-
else {
|
|
1580
|
-
el.removeAttribute(name);
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
else {
|
|
1584
|
-
el.setAttribute(name, `${datum}`);
|
|
1585
|
-
}
|
|
1586
|
-
return;
|
|
1587
|
-
}
|
|
1588
|
-
case 'high': {
|
|
1589
|
-
if (el instanceof HTMLMeterElement) {
|
|
1590
|
-
const high = toInt(datum);
|
|
1591
|
-
if (Number.isNaN(high)) {
|
|
1592
|
-
el.removeAttribute(name);
|
|
1593
|
-
}
|
|
1594
|
-
else {
|
|
1595
|
-
el.high = high;
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
else {
|
|
1599
|
-
el.setAttribute(name, `${datum}`);
|
|
1600
|
-
}
|
|
1601
|
-
return;
|
|
1632
|
+
return setBooleanAttr(el, datum, [
|
|
1633
|
+
HTMLButtonElement,
|
|
1634
|
+
HTMLFieldSetElement,
|
|
1635
|
+
HTMLInputElement,
|
|
1636
|
+
HTMLOptGroupElement,
|
|
1637
|
+
HTMLOptionElement,
|
|
1638
|
+
HTMLSelectElement,
|
|
1639
|
+
HTMLTextAreaElement,
|
|
1640
|
+
], 'disabled');
|
|
1602
1641
|
}
|
|
1603
1642
|
case 'ismap': {
|
|
1604
|
-
|
|
1605
|
-
el.isMap = datum === '' ? true : !!datum;
|
|
1606
|
-
}
|
|
1607
|
-
else {
|
|
1608
|
-
el.setAttribute(name, `${datum}`);
|
|
1609
|
-
}
|
|
1610
|
-
return;
|
|
1643
|
+
return setBooleanAttr(el, datum, [HTMLImageElement], 'isMap');
|
|
1611
1644
|
}
|
|
1612
1645
|
case 'loop': {
|
|
1613
|
-
|
|
1614
|
-
el.loop = datum === '' ? true : !!datum;
|
|
1615
|
-
}
|
|
1616
|
-
else {
|
|
1617
|
-
el.setAttribute(name, `${datum}`);
|
|
1618
|
-
}
|
|
1619
|
-
return;
|
|
1620
|
-
}
|
|
1621
|
-
case 'low': {
|
|
1622
|
-
if (el instanceof HTMLMeterElement) {
|
|
1623
|
-
const low = toInt(datum);
|
|
1624
|
-
if (Number.isNaN(low)) {
|
|
1625
|
-
el.removeAttribute(name);
|
|
1626
|
-
}
|
|
1627
|
-
else {
|
|
1628
|
-
el.low = low;
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
else {
|
|
1632
|
-
el.setAttribute(name, `${datum}`);
|
|
1633
|
-
}
|
|
1634
|
-
return;
|
|
1635
|
-
}
|
|
1636
|
-
case 'max': {
|
|
1637
|
-
if (el instanceof HTMLInputElement ||
|
|
1638
|
-
el instanceof HTMLMeterElement ||
|
|
1639
|
-
el instanceof HTMLProgressElement) {
|
|
1640
|
-
const max = toInt(datum);
|
|
1641
|
-
if (Number.isNaN(max)) {
|
|
1642
|
-
el.removeAttribute(name);
|
|
1643
|
-
}
|
|
1644
|
-
else {
|
|
1645
|
-
el.max = max;
|
|
1646
|
-
}
|
|
1647
|
-
}
|
|
1648
|
-
else {
|
|
1649
|
-
el.setAttribute(name, `${datum}`);
|
|
1650
|
-
}
|
|
1651
|
-
return;
|
|
1652
|
-
}
|
|
1653
|
-
case 'maxlength': {
|
|
1654
|
-
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
1655
|
-
const maxLength = toInt(datum);
|
|
1656
|
-
if (Number.isNaN(maxLength)) {
|
|
1657
|
-
el.removeAttribute(name);
|
|
1658
|
-
}
|
|
1659
|
-
else {
|
|
1660
|
-
el.maxLength = Math.floor(maxLength);
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
else {
|
|
1664
|
-
el.setAttribute(name, `${datum}`);
|
|
1665
|
-
}
|
|
1666
|
-
return;
|
|
1667
|
-
}
|
|
1668
|
-
case 'min': {
|
|
1669
|
-
if (el instanceof HTMLInputElement || el instanceof HTMLMeterElement) {
|
|
1670
|
-
const min = toInt(datum);
|
|
1671
|
-
if (Number.isNaN(min)) {
|
|
1672
|
-
el.removeAttribute(name);
|
|
1673
|
-
}
|
|
1674
|
-
else {
|
|
1675
|
-
el.min = min;
|
|
1676
|
-
}
|
|
1677
|
-
}
|
|
1678
|
-
else {
|
|
1679
|
-
el.setAttribute(name, `${datum}`);
|
|
1680
|
-
}
|
|
1681
|
-
return;
|
|
1646
|
+
return setBooleanAttr(el, datum, [HTMLAudioElement, HTMLVideoElement], 'loop');
|
|
1682
1647
|
}
|
|
1683
1648
|
case 'multiple': {
|
|
1684
|
-
|
|
1685
|
-
el.multiple = datum === '' ? true : !!datum;
|
|
1686
|
-
}
|
|
1687
|
-
else {
|
|
1688
|
-
el.setAttribute(name, `${datum}`);
|
|
1689
|
-
}
|
|
1690
|
-
return;
|
|
1649
|
+
return setBooleanAttr(el, datum, [HTMLInputElement, HTMLSelectElement], 'multiple');
|
|
1691
1650
|
}
|
|
1692
1651
|
case 'novalidate': {
|
|
1693
|
-
|
|
1694
|
-
el.noValidate = datum === '' ? true : !!datum;
|
|
1695
|
-
}
|
|
1696
|
-
else {
|
|
1697
|
-
el.setAttribute(name, `${datum}`);
|
|
1698
|
-
}
|
|
1699
|
-
return;
|
|
1652
|
+
return setBooleanAttr(el, datum, [HTMLFormElement], 'noValidate');
|
|
1700
1653
|
}
|
|
1701
1654
|
case 'open': {
|
|
1702
|
-
|
|
1703
|
-
el.open = datum === '' ? true : !!datum;
|
|
1704
|
-
}
|
|
1705
|
-
else {
|
|
1706
|
-
el.setAttribute(name, `${datum}`);
|
|
1707
|
-
}
|
|
1708
|
-
break;
|
|
1709
|
-
}
|
|
1710
|
-
case 'optimum': {
|
|
1711
|
-
if (el instanceof HTMLMeterElement) {
|
|
1712
|
-
const optimum = toInt(datum);
|
|
1713
|
-
if (Number.isNaN(optimum)) {
|
|
1714
|
-
el.removeAttribute(name);
|
|
1715
|
-
}
|
|
1716
|
-
else {
|
|
1717
|
-
el.optimum = Math.floor(optimum);
|
|
1718
|
-
}
|
|
1719
|
-
}
|
|
1720
|
-
else {
|
|
1721
|
-
el.setAttribute(name, `${datum}`);
|
|
1722
|
-
}
|
|
1723
|
-
return;
|
|
1724
|
-
}
|
|
1725
|
-
case 'preload': {
|
|
1726
|
-
if (el instanceof HTMLAudioElement || el instanceof HTMLVideoElement) {
|
|
1727
|
-
switch (datum) {
|
|
1728
|
-
case '':
|
|
1729
|
-
case 'auto':
|
|
1730
|
-
case 'metadata': {
|
|
1731
|
-
el.preload = datum;
|
|
1732
|
-
break;
|
|
1733
|
-
}
|
|
1734
|
-
default: {
|
|
1735
|
-
el.preload = 'none';
|
|
1736
|
-
}
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
else {
|
|
1740
|
-
el.setAttribute(name, `${datum}`);
|
|
1741
|
-
}
|
|
1742
|
-
return;
|
|
1655
|
+
return setBooleanAttr(el, datum, [HTMLDetailsElement], 'open');
|
|
1743
1656
|
}
|
|
1744
1657
|
case 'readonly': {
|
|
1745
|
-
|
|
1746
|
-
el.readOnly = datum === '' ? true : !!datum;
|
|
1747
|
-
}
|
|
1748
|
-
else {
|
|
1749
|
-
el.setAttribute(name, `${datum}`);
|
|
1750
|
-
}
|
|
1751
|
-
return;
|
|
1658
|
+
return setBooleanAttr(el, datum, [HTMLInputElement, HTMLTextAreaElement], 'readOnly');
|
|
1752
1659
|
}
|
|
1753
1660
|
case 'required': {
|
|
1754
|
-
|
|
1755
|
-
el instanceof HTMLSelectElement ||
|
|
1756
|
-
el instanceof HTMLTextAreaElement) {
|
|
1757
|
-
el.required = datum === '' ? true : !!datum;
|
|
1758
|
-
}
|
|
1759
|
-
else {
|
|
1760
|
-
el.setAttribute(name, `${datum}`);
|
|
1761
|
-
}
|
|
1762
|
-
return;
|
|
1661
|
+
return setBooleanAttr(el, datum, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement], 'required');
|
|
1763
1662
|
}
|
|
1764
1663
|
case 'reversed': {
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1664
|
+
return setBooleanAttr(el, datum, [HTMLOListElement], 'reversed');
|
|
1665
|
+
}
|
|
1666
|
+
default: {
|
|
1667
|
+
return false;
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
/**
|
|
1672
|
+
* Handle integer HTML attributes via their DOM properties.
|
|
1673
|
+
* @param el
|
|
1674
|
+
* @param name
|
|
1675
|
+
* @param datum
|
|
1676
|
+
* @returns true if handled
|
|
1677
|
+
*/
|
|
1678
|
+
function setIntegerAttrByName(el, name, datum) {
|
|
1679
|
+
switch (name) {
|
|
1680
|
+
case 'cols': {
|
|
1681
|
+
return setIntegerAttr(el, name, datum, [HTMLTextAreaElement], 'cols');
|
|
1682
|
+
}
|
|
1683
|
+
case 'colspan': {
|
|
1684
|
+
return setIntegerAttr(el, name, datum, [HTMLTableCellElement], 'colSpan');
|
|
1685
|
+
}
|
|
1686
|
+
case 'high': {
|
|
1687
|
+
return setIntegerAttr(el, name, datum, [HTMLMeterElement], 'high');
|
|
1688
|
+
}
|
|
1689
|
+
case 'low': {
|
|
1690
|
+
return setIntegerAttr(el, name, datum, [HTMLMeterElement], 'low');
|
|
1691
|
+
}
|
|
1692
|
+
case 'max': {
|
|
1693
|
+
return setIntegerAttr(el, name, datum, [HTMLInputElement, HTMLMeterElement, HTMLProgressElement], 'max');
|
|
1694
|
+
}
|
|
1695
|
+
case 'maxlength': {
|
|
1696
|
+
return setIntegerAttr(el, name, datum, [HTMLInputElement, HTMLTextAreaElement], 'maxLength', true);
|
|
1697
|
+
}
|
|
1698
|
+
case 'min': {
|
|
1699
|
+
return setIntegerAttr(el, name, datum, [HTMLInputElement, HTMLMeterElement], 'min');
|
|
1700
|
+
}
|
|
1701
|
+
case 'optimum': {
|
|
1702
|
+
return setIntegerAttr(el, name, datum, [HTMLMeterElement], 'optimum', true);
|
|
1772
1703
|
}
|
|
1773
1704
|
case 'rows': {
|
|
1774
|
-
|
|
1775
|
-
const rows = toInt(datum);
|
|
1776
|
-
if (Number.isNaN(rows)) {
|
|
1777
|
-
el.removeAttribute(name);
|
|
1778
|
-
}
|
|
1779
|
-
else {
|
|
1780
|
-
el.rows = Math.floor(rows);
|
|
1781
|
-
}
|
|
1782
|
-
}
|
|
1783
|
-
else {
|
|
1784
|
-
el.setAttribute(name, `${datum}`);
|
|
1785
|
-
}
|
|
1786
|
-
return;
|
|
1705
|
+
return setIntegerAttr(el, name, datum, [HTMLTextAreaElement], 'rows', true);
|
|
1787
1706
|
}
|
|
1788
1707
|
case 'rowspan': {
|
|
1789
|
-
|
|
1790
|
-
const rowSpan = toInt(datum);
|
|
1791
|
-
if (Number.isNaN(rowSpan)) {
|
|
1792
|
-
el.removeAttribute(name);
|
|
1793
|
-
}
|
|
1794
|
-
else {
|
|
1795
|
-
el.rowSpan = Math.floor(rowSpan);
|
|
1796
|
-
}
|
|
1797
|
-
}
|
|
1798
|
-
else {
|
|
1799
|
-
el.setAttribute(name, `${datum}`);
|
|
1800
|
-
}
|
|
1801
|
-
return;
|
|
1708
|
+
return setIntegerAttr(el, name, datum, [HTMLTableCellElement], 'rowSpan', true);
|
|
1802
1709
|
}
|
|
1803
1710
|
case 'size': {
|
|
1804
|
-
|
|
1805
|
-
const size = toInt(datum);
|
|
1806
|
-
if (Number.isNaN(size)) {
|
|
1807
|
-
el.removeAttribute(name);
|
|
1808
|
-
}
|
|
1809
|
-
else {
|
|
1810
|
-
el.size = size;
|
|
1811
|
-
}
|
|
1812
|
-
}
|
|
1813
|
-
else {
|
|
1814
|
-
el.setAttribute(name, `${datum}`);
|
|
1815
|
-
}
|
|
1816
|
-
return;
|
|
1711
|
+
return setIntegerAttr(el, name, datum, [HTMLInputElement, HTMLSelectElement], 'size');
|
|
1817
1712
|
}
|
|
1818
1713
|
case 'span': {
|
|
1819
|
-
|
|
1820
|
-
const span = toInt(datum);
|
|
1821
|
-
if (Number.isNaN(span)) {
|
|
1822
|
-
el.removeAttribute(name);
|
|
1823
|
-
}
|
|
1824
|
-
else {
|
|
1825
|
-
el.span = span;
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1828
|
-
else {
|
|
1829
|
-
el.setAttribute(name, `${datum}`);
|
|
1830
|
-
}
|
|
1831
|
-
return;
|
|
1714
|
+
return setIntegerAttr(el, name, datum, [HTMLTableColElement], 'span');
|
|
1832
1715
|
}
|
|
1833
1716
|
case 'start': {
|
|
1834
|
-
|
|
1835
|
-
const start = toInt(datum);
|
|
1836
|
-
if (Number.isNaN(start)) {
|
|
1837
|
-
el.removeAttribute(name);
|
|
1838
|
-
}
|
|
1839
|
-
else {
|
|
1840
|
-
el.start = start;
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
else {
|
|
1844
|
-
el.setAttribute(name, `${datum}`);
|
|
1845
|
-
}
|
|
1846
|
-
return;
|
|
1847
|
-
}
|
|
1848
|
-
case 'step': {
|
|
1849
|
-
if (el instanceof HTMLInputElement) {
|
|
1850
|
-
if (datum === 'any') {
|
|
1851
|
-
el.step = datum;
|
|
1852
|
-
break;
|
|
1853
|
-
}
|
|
1854
|
-
const step = toNum(datum);
|
|
1855
|
-
if (Number.isNaN(step)) {
|
|
1856
|
-
el.removeAttribute(name);
|
|
1857
|
-
}
|
|
1858
|
-
else {
|
|
1859
|
-
el.step = step.toString(10);
|
|
1860
|
-
}
|
|
1861
|
-
}
|
|
1862
|
-
else {
|
|
1863
|
-
el.setAttribute(name, `${datum}`);
|
|
1864
|
-
}
|
|
1865
|
-
return;
|
|
1866
|
-
}
|
|
1867
|
-
case 'target': {
|
|
1868
|
-
if (el instanceof HTMLAnchorElement ||
|
|
1869
|
-
el instanceof HTMLAreaElement ||
|
|
1870
|
-
el instanceof HTMLFormElement) {
|
|
1871
|
-
if (datum) {
|
|
1872
|
-
el.target = `${datum}`;
|
|
1873
|
-
}
|
|
1874
|
-
else {
|
|
1875
|
-
el.removeAttribute(name);
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
else {
|
|
1879
|
-
el.setAttribute(name, `${datum}`);
|
|
1880
|
-
}
|
|
1881
|
-
return;
|
|
1717
|
+
return setIntegerAttr(el, name, datum, [HTMLOListElement], 'start');
|
|
1882
1718
|
}
|
|
1883
|
-
// case 'accesskey':
|
|
1884
|
-
// case 'class':
|
|
1885
|
-
// case 'contextmenu':
|
|
1886
|
-
// case 'dropzone': // breakable support
|
|
1887
|
-
// case 'id':
|
|
1888
|
-
// case 'itemid':
|
|
1889
|
-
// case 'itemprop':
|
|
1890
|
-
// case 'itemref':
|
|
1891
|
-
// case 'itemscope':
|
|
1892
|
-
// case 'itemtype':
|
|
1893
|
-
// case 'lang':
|
|
1894
|
-
// case 'slot': // breakable support
|
|
1895
|
-
// case 'style':
|
|
1896
|
-
// case 'title':
|
|
1897
|
-
// case 'translate': // breakable support
|
|
1898
|
-
// case 'accept':
|
|
1899
|
-
// case 'accept-charset':
|
|
1900
|
-
// case 'action':
|
|
1901
|
-
// case 'align':
|
|
1902
|
-
// case 'alt':
|
|
1903
|
-
// case 'cite':
|
|
1904
|
-
// case 'coords':
|
|
1905
|
-
// case 'datetime':
|
|
1906
|
-
// case 'enctype':
|
|
1907
|
-
// case 'for':
|
|
1908
|
-
// case 'headers':
|
|
1909
|
-
// case 'href':
|
|
1910
|
-
// case 'hreflang':
|
|
1911
|
-
// case 'kind':
|
|
1912
|
-
// case 'label':
|
|
1913
|
-
// case 'list':
|
|
1914
|
-
// case 'media':
|
|
1915
|
-
// case 'method':
|
|
1916
|
-
// case 'name':
|
|
1917
|
-
// case 'pattern':
|
|
1918
|
-
// case 'placeholder':
|
|
1919
|
-
// case 'poster':
|
|
1920
|
-
// case 'pubdate':
|
|
1921
|
-
// case 'rel':
|
|
1922
|
-
// case 'sandbox':
|
|
1923
|
-
// case 'src':
|
|
1924
|
-
// case 'srcdoc':
|
|
1925
|
-
// case 'srclang':
|
|
1926
|
-
// case 'summary':
|
|
1927
|
-
// case 'type':
|
|
1928
|
-
// case 'usemap':
|
|
1929
|
-
// case 'value':
|
|
1930
|
-
// case 'wrap':
|
|
1931
|
-
// and Data-* attributes
|
|
1932
1719
|
default: {
|
|
1933
|
-
|
|
1720
|
+
return false;
|
|
1934
1721
|
}
|
|
1935
1722
|
}
|
|
1936
1723
|
}
|
|
1937
1724
|
/**
|
|
1938
|
-
*
|
|
1939
|
-
*
|
|
1940
|
-
* @param
|
|
1941
|
-
* @param
|
|
1942
|
-
* @param
|
|
1725
|
+
* Set content value on a form element or general element.
|
|
1726
|
+
* Handles checkbox/radio checked state, input values, and innerHTML/textContent.
|
|
1727
|
+
* @param el - The target element
|
|
1728
|
+
* @param datum - The value to set
|
|
1729
|
+
* @param asHtml - Whether to set as innerHTML (true) or textContent (false)
|
|
1730
|
+
* @param xssSanitize - Whether to sanitize HTML content for XSS protection
|
|
1943
1731
|
*/
|
|
1944
1732
|
function setContent$1(el, datum, asHtml = true, xssSanitize = true) {
|
|
1945
1733
|
if (el instanceof HTMLInputElement ||
|
|
@@ -2909,8 +2697,11 @@ class EditorUI {
|
|
|
2909
2697
|
show() {
|
|
2910
2698
|
this.#el.hidden = false;
|
|
2911
2699
|
}
|
|
2700
|
+
/**
|
|
2701
|
+
* @returns Whether the UI element is currently visible (not hidden)
|
|
2702
|
+
*/
|
|
2912
2703
|
visible() {
|
|
2913
|
-
return
|
|
2704
|
+
return !this.#el.hidden;
|
|
2914
2705
|
}
|
|
2915
2706
|
}
|
|
2916
2707
|
|
|
@@ -2963,10 +2754,11 @@ class EditorDialog extends EditorUI {
|
|
|
2963
2754
|
this.clearTemplate();
|
|
2964
2755
|
this.#onClosed();
|
|
2965
2756
|
}
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2757
|
+
/**
|
|
2758
|
+
* Handle form completion. Subclasses override to process form data before closing.
|
|
2759
|
+
* @param _formData - The submitted form data
|
|
2760
|
+
*/
|
|
2761
|
+
complete(_formData) {
|
|
2970
2762
|
this.close();
|
|
2971
2763
|
}
|
|
2972
2764
|
dispatchEvent(event) {
|
|
@@ -2981,17 +2773,18 @@ class EditorDialog extends EditorUI {
|
|
|
2981
2773
|
? elements.map((el) => el.shadowRoot?.querySelector(shadowSelector) ?? el)
|
|
2982
2774
|
: elements;
|
|
2983
2775
|
}
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2776
|
+
/**
|
|
2777
|
+
* Handle form submission. Subclasses override to add custom behavior.
|
|
2778
|
+
* Return `false` to cancel submission.
|
|
2779
|
+
* @param _e - The submit event
|
|
2780
|
+
* @param _submitter - The element that triggered submission
|
|
2781
|
+
*/
|
|
2782
|
+
onSubmit(_e, _submitter) { }
|
|
2783
|
+
/**
|
|
2784
|
+
* Open the dialog. Subclasses override to set up content before showing.
|
|
2785
|
+
* @param _args - Arguments passed by subclass overrides
|
|
2786
|
+
*/
|
|
2787
|
+
open(..._args) {
|
|
2995
2788
|
const cancel = this.#onOpen();
|
|
2996
2789
|
if (cancel === true) {
|
|
2997
2790
|
return;
|
|
@@ -3215,21 +3008,38 @@ class ComponentObserver {
|
|
|
3215
3008
|
constructor() {
|
|
3216
3009
|
this.#instanceId = instanceId++;
|
|
3217
3010
|
}
|
|
3011
|
+
/**
|
|
3012
|
+
* Dispatch a custom event on the window.
|
|
3013
|
+
* @template A - The action type key
|
|
3014
|
+
* @param name - The action name to dispatch
|
|
3015
|
+
* @param payload - The event payload matching the action type
|
|
3016
|
+
*/
|
|
3218
3017
|
notify(name, payload) {
|
|
3219
3018
|
window.dispatchEvent(new CustomEvent(`bge:_${this.#instanceId}_:${name}`, { detail: payload }));
|
|
3220
3019
|
}
|
|
3020
|
+
/**
|
|
3021
|
+
* Remove all registered event listeners and clear the internal map.
|
|
3022
|
+
*/
|
|
3221
3023
|
off() {
|
|
3222
|
-
for (const [
|
|
3223
|
-
|
|
3224
|
-
window.removeEventListener(`bge:_${this.#instanceId}_:${name}`, listener);
|
|
3024
|
+
for (const [wrapper, name] of this.#listeners) {
|
|
3025
|
+
window.removeEventListener(`bge:_${this.#instanceId}_:${name}`, wrapper);
|
|
3225
3026
|
}
|
|
3226
3027
|
this.#listeners.clear();
|
|
3227
3028
|
}
|
|
3029
|
+
/**
|
|
3030
|
+
* Register an event listener. Each call creates a separate wrapper,
|
|
3031
|
+
* so calling with the same listener multiple times will fire it
|
|
3032
|
+
* multiple times per event.
|
|
3033
|
+
* @template A - The action type key
|
|
3034
|
+
* @param name - The action name to listen for
|
|
3035
|
+
* @param listener - Callback receiving the typed payload
|
|
3036
|
+
*/
|
|
3228
3037
|
on(name, listener) {
|
|
3229
|
-
|
|
3230
|
-
window.addEventListener(`bge:_${this.#instanceId}_:${name}`, (e) => {
|
|
3038
|
+
const wrapper = (e) => {
|
|
3231
3039
|
listener(e.detail);
|
|
3232
|
-
}
|
|
3040
|
+
};
|
|
3041
|
+
this.#listeners.set(wrapper, name);
|
|
3042
|
+
window.addEventListener(`bge:_${this.#instanceId}_:${name}`, wrapper);
|
|
3233
3043
|
}
|
|
3234
3044
|
}
|
|
3235
3045
|
|
|
@@ -4256,9 +4066,21 @@ class ItemEditorDialog extends EditorDialog {
|
|
|
4256
4066
|
$ctrl.max = value.toString();
|
|
4257
4067
|
}
|
|
4258
4068
|
}
|
|
4069
|
+
/**
|
|
4070
|
+
* Register a change handler for a named form control.
|
|
4071
|
+
* When `runOnInit` is true, fires immediately with the current value
|
|
4072
|
+
* (oldValue is null) and stores the initial value for subsequent comparisons.
|
|
4073
|
+
* @template N - The item data property name
|
|
4074
|
+
* @template D - The data type for the property
|
|
4075
|
+
* @param name - The control name prefixed with `$`
|
|
4076
|
+
* @param handler - Callback receiving new value and previous value
|
|
4077
|
+
* @param runOnInit - Whether to invoke the handler immediately with the current value
|
|
4078
|
+
*/
|
|
4259
4079
|
onChange(name, handler, runOnInit = true) {
|
|
4260
4080
|
if (runOnInit) {
|
|
4261
|
-
|
|
4081
|
+
const initialValue = this.get(name);
|
|
4082
|
+
this.#values.set(name, initialValue);
|
|
4083
|
+
handler(initialValue, null);
|
|
4262
4084
|
}
|
|
4263
4085
|
for (const $ctrl of this.#findAll(name)) {
|
|
4264
4086
|
$ctrl.addEventListener('change', () => {
|
|
@@ -4763,12 +4585,10 @@ class BurgerEditorEngine {
|
|
|
4763
4585
|
const mainInitialContent = typeof options.initialContents === 'string'
|
|
4764
4586
|
? options.initialContents
|
|
4765
4587
|
: options.initialContents.main;
|
|
4766
|
-
// @ts-ignore force assign to readonly property
|
|
4767
4588
|
engine.#main =
|
|
4768
4589
|
//
|
|
4769
4590
|
await EditableArea.new('main', mainInitialContent, engine, options.blockMenu, options.initialInsertionButton, stylesheets, options.config.classList, options.editableAreaShell);
|
|
4770
4591
|
const draftInitialContent = typeof options.initialContents === 'string' ? null : options.initialContents.draft;
|
|
4771
|
-
// @ts-ignore force assign to readonly property
|
|
4772
4592
|
engine.#draft =
|
|
4773
4593
|
draftInitialContent == null
|
|
4774
4594
|
? null
|
|
@@ -33712,6 +33532,281 @@ function getCurrentEditorState(wysiwygElement) {
|
|
|
33712
33532
|
};
|
|
33713
33533
|
}
|
|
33714
33534
|
|
|
33535
|
+
const controlUIStyles = `
|
|
33536
|
+
:host {
|
|
33537
|
+
display: block;
|
|
33538
|
+
}
|
|
33539
|
+
|
|
33540
|
+
textarea,
|
|
33541
|
+
iframe {
|
|
33542
|
+
block-size: 50svh;
|
|
33543
|
+
inline-size: 100%;
|
|
33544
|
+
resize: vertical;
|
|
33545
|
+
overflow-y: auto;
|
|
33546
|
+
background: var(--bge-lightest-color);
|
|
33547
|
+
border: 1px solid var(--bge-border-color);
|
|
33548
|
+
border-radius: var(--border-radius);
|
|
33549
|
+
}
|
|
33550
|
+
|
|
33551
|
+
iframe[data-focus-within="true"],
|
|
33552
|
+
textarea:focus-visible {
|
|
33553
|
+
--bge-border-color: var(--bge-ui-primary-color);
|
|
33554
|
+
--bge-outline-color: var(--bge-ui-primary-color);
|
|
33555
|
+
outline: var(--bge-focus-outline-width) solid var(--bge-outline-color);
|
|
33556
|
+
}
|
|
33557
|
+
|
|
33558
|
+
textarea {
|
|
33559
|
+
font-family: var(--bge-font-family-monospace);
|
|
33560
|
+
}
|
|
33561
|
+
|
|
33562
|
+
[data-bge-mode="wysiwyg"] textarea {
|
|
33563
|
+
display: none;
|
|
33564
|
+
}
|
|
33565
|
+
|
|
33566
|
+
[data-bge-mode="html"] iframe {
|
|
33567
|
+
display: none;
|
|
33568
|
+
}
|
|
33569
|
+
|
|
33570
|
+
[data-text-only-editor] {
|
|
33571
|
+
block-size: 50svh;
|
|
33572
|
+
inline-size: 100%;
|
|
33573
|
+
resize: vertical;
|
|
33574
|
+
overflow-y: auto;
|
|
33575
|
+
background: var(--bge-lightest-color);
|
|
33576
|
+
border: 1px solid var(--bge-border-color);
|
|
33577
|
+
border-radius: var(--border-radius);
|
|
33578
|
+
padding: 1rem;
|
|
33579
|
+
box-sizing: border-box;
|
|
33580
|
+
}
|
|
33581
|
+
|
|
33582
|
+
[data-bge-mode="wysiwyg"] [data-text-only-editor],
|
|
33583
|
+
[data-bge-mode="html"] [data-text-only-editor] {
|
|
33584
|
+
display: none;
|
|
33585
|
+
}
|
|
33586
|
+
|
|
33587
|
+
[data-bge-mode="text-only"] iframe,
|
|
33588
|
+
[data-bge-mode="text-only"] textarea {
|
|
33589
|
+
display: none;
|
|
33590
|
+
}
|
|
33591
|
+
|
|
33592
|
+
[contenteditable="plaintext-only"] {
|
|
33593
|
+
outline: 1px dashed var(--bge-border-color);
|
|
33594
|
+
cursor: text;
|
|
33595
|
+
}
|
|
33596
|
+
|
|
33597
|
+
[contenteditable="plaintext-only"]:hover {
|
|
33598
|
+
outline-color: var(--bge-ui-primary-color);
|
|
33599
|
+
}
|
|
33600
|
+
|
|
33601
|
+
[contenteditable="plaintext-only"]:focus {
|
|
33602
|
+
outline: 2px solid var(--bge-ui-primary-color);
|
|
33603
|
+
outline-offset: 2px;
|
|
33604
|
+
}
|
|
33605
|
+
|
|
33606
|
+
[role="alert"] {
|
|
33607
|
+
margin-block-start: 0.5rem;
|
|
33608
|
+
padding: 0.5rem;
|
|
33609
|
+
background-color: var(--bge-error-color, #fee);
|
|
33610
|
+
border: 1px solid var(--bge-error-border-color, #fcc);
|
|
33611
|
+
border-radius: var(--border-radius);
|
|
33612
|
+
color: var(--bge-error-text-color, #c00);
|
|
33613
|
+
font-size: 0.875rem;
|
|
33614
|
+
}
|
|
33615
|
+
`;
|
|
33616
|
+
const editorContentStyles = (css) => `
|
|
33617
|
+
:where(html, body) {
|
|
33618
|
+
margin: 0;
|
|
33619
|
+
padding: 0;
|
|
33620
|
+
|
|
33621
|
+
:where(&, *) {
|
|
33622
|
+
box-sizing: border-box;
|
|
33623
|
+
}
|
|
33624
|
+
}
|
|
33625
|
+
|
|
33626
|
+
iframe,
|
|
33627
|
+
[contenteditable="true"] {
|
|
33628
|
+
padding: 1rem;
|
|
33629
|
+
block-size: 100%;
|
|
33630
|
+
box-sizing: border-box;
|
|
33631
|
+
}
|
|
33632
|
+
|
|
33633
|
+
[contenteditable="true"]:focus-visible {
|
|
33634
|
+
outline: none;
|
|
33635
|
+
}
|
|
33636
|
+
|
|
33637
|
+
${css}
|
|
33638
|
+
|
|
33639
|
+
a:any-link {
|
|
33640
|
+
pointer-events: none !important;
|
|
33641
|
+
}
|
|
33642
|
+
`;
|
|
33643
|
+
|
|
33644
|
+
var __typeError$2 = (msg) => {
|
|
33645
|
+
throw TypeError(msg);
|
|
33646
|
+
};
|
|
33647
|
+
var __accessCheck$2 = (obj, member, msg) => member.has(obj) || __typeError$2("Cannot " + msg);
|
|
33648
|
+
var __privateGet$2 = (obj, member, getter) => (__accessCheck$2(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
33649
|
+
var __privateAdd$2 = (obj, member, value) => member.has(obj) ? __typeError$2("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
33650
|
+
var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$2(obj, member, "write to private field"), member.set(obj, value), value);
|
|
33651
|
+
var __privateMethod$1 = (obj, member, method) => (__accessCheck$2(obj, member, "access private method"), method);
|
|
33652
|
+
var _container, _setToTextarea, _preventEnterKey, _syncToTextarea, _TextOnlyModeController_instances, attachEventListeners_fn, identifyEditableElements_fn;
|
|
33653
|
+
class TextOnlyModeController {
|
|
33654
|
+
/**
|
|
33655
|
+
* @param setToTextarea - Callback to sync cleaned HTML back to the textarea
|
|
33656
|
+
*/
|
|
33657
|
+
constructor(setToTextarea) {
|
|
33658
|
+
__privateAdd$2(this, _TextOnlyModeController_instances);
|
|
33659
|
+
__privateAdd$2(this, _container, null);
|
|
33660
|
+
__privateAdd$2(this, _setToTextarea);
|
|
33661
|
+
/**
|
|
33662
|
+
* Enter キーを防止するハンドラー
|
|
33663
|
+
* @param event
|
|
33664
|
+
*/
|
|
33665
|
+
__privateAdd$2(this, _preventEnterKey, (event) => {
|
|
33666
|
+
if (event.key === "Enter") {
|
|
33667
|
+
event.preventDefault();
|
|
33668
|
+
}
|
|
33669
|
+
});
|
|
33670
|
+
/**
|
|
33671
|
+
* text-onlyコンテナからtextareaへ同期
|
|
33672
|
+
*/
|
|
33673
|
+
__privateAdd$2(this, _syncToTextarea, () => {
|
|
33674
|
+
if (!__privateGet$2(this, _container)) {
|
|
33675
|
+
return;
|
|
33676
|
+
}
|
|
33677
|
+
const cleanHTML = this.cleanHTML();
|
|
33678
|
+
__privateGet$2(this, _setToTextarea).call(this, cleanHTML);
|
|
33679
|
+
});
|
|
33680
|
+
__privateSet$2(this, _setToTextarea, setToTextarea);
|
|
33681
|
+
}
|
|
33682
|
+
/**
|
|
33683
|
+
* The text-only editing container element, or null if not yet activated.
|
|
33684
|
+
*/
|
|
33685
|
+
get container() {
|
|
33686
|
+
return __privateGet$2(this, _container);
|
|
33687
|
+
}
|
|
33688
|
+
/**
|
|
33689
|
+
* text-onlyモードを有効化
|
|
33690
|
+
* @param shadowRoot
|
|
33691
|
+
* @param currentHTML
|
|
33692
|
+
* @param structureChangeMessage
|
|
33693
|
+
* @param previewStyleContent
|
|
33694
|
+
*/
|
|
33695
|
+
activate(shadowRoot, currentHTML, structureChangeMessage, previewStyleContent) {
|
|
33696
|
+
if (!__privateGet$2(this, _container)) {
|
|
33697
|
+
__privateSet$2(this, _container, document.createElement("div"));
|
|
33698
|
+
__privateGet$2(this, _container).dataset.textOnlyEditor = "";
|
|
33699
|
+
const modeContainer = shadowRoot.querySelector("[data-bge-mode]");
|
|
33700
|
+
modeContainer.insertBefore(__privateGet$2(this, _container), structureChangeMessage);
|
|
33701
|
+
}
|
|
33702
|
+
const textOnlyStyle = document.createElement("style");
|
|
33703
|
+
textOnlyStyle.dataset.textOnlyStyle = "";
|
|
33704
|
+
if (previewStyleContent) {
|
|
33705
|
+
textOnlyStyle.textContent = previewStyleContent;
|
|
33706
|
+
}
|
|
33707
|
+
__privateGet$2(this, _container).innerHTML = currentHTML;
|
|
33708
|
+
__privateGet$2(this, _container).prepend(textOnlyStyle);
|
|
33709
|
+
__privateMethod$1(this, _TextOnlyModeController_instances, identifyEditableElements_fn).call(this, __privateGet$2(this, _container));
|
|
33710
|
+
__privateMethod$1(this, _TextOnlyModeController_instances, attachEventListeners_fn).call(this);
|
|
33711
|
+
shadowRoot.querySelector(`[data-bge-mode]`).dataset.bgeMode = "text-only";
|
|
33712
|
+
}
|
|
33713
|
+
/**
|
|
33714
|
+
* contenteditable属性を削除してクリーンなHTMLを返す
|
|
33715
|
+
*/
|
|
33716
|
+
cleanHTML() {
|
|
33717
|
+
if (!__privateGet$2(this, _container)) {
|
|
33718
|
+
return "";
|
|
33719
|
+
}
|
|
33720
|
+
const clone = __privateGet$2(this, _container).cloneNode(true);
|
|
33721
|
+
const editableElements = clone.querySelectorAll('[contenteditable="plaintext-only"]');
|
|
33722
|
+
for (const el of editableElements) {
|
|
33723
|
+
el.removeAttribute("contenteditable");
|
|
33724
|
+
}
|
|
33725
|
+
const styleElements = clone.querySelectorAll("[data-text-only-style]");
|
|
33726
|
+
for (const el of styleElements) {
|
|
33727
|
+
el.remove();
|
|
33728
|
+
}
|
|
33729
|
+
return clone.innerHTML;
|
|
33730
|
+
}
|
|
33731
|
+
/**
|
|
33732
|
+
* text-onlyモードを無効化
|
|
33733
|
+
*/
|
|
33734
|
+
deactivate() {
|
|
33735
|
+
if (!__privateGet$2(this, _container)) {
|
|
33736
|
+
return;
|
|
33737
|
+
}
|
|
33738
|
+
const editableElements = __privateGet$2(this, _container).querySelectorAll(
|
|
33739
|
+
'[contenteditable="plaintext-only"]'
|
|
33740
|
+
);
|
|
33741
|
+
for (const el of editableElements) {
|
|
33742
|
+
el.removeEventListener("keydown", __privateGet$2(this, _preventEnterKey));
|
|
33743
|
+
el.removeEventListener("input", __privateGet$2(this, _syncToTextarea));
|
|
33744
|
+
}
|
|
33745
|
+
__privateGet$2(this, _container).innerHTML = "";
|
|
33746
|
+
}
|
|
33747
|
+
/**
|
|
33748
|
+
* text-onlyモードの値を取得
|
|
33749
|
+
* @param textareaValue
|
|
33750
|
+
*/
|
|
33751
|
+
getValue(textareaValue) {
|
|
33752
|
+
if (!__privateGet$2(this, _container)) {
|
|
33753
|
+
return textareaValue;
|
|
33754
|
+
}
|
|
33755
|
+
return this.cleanHTML();
|
|
33756
|
+
}
|
|
33757
|
+
/**
|
|
33758
|
+
* text-onlyモードに値を設定
|
|
33759
|
+
* @param value
|
|
33760
|
+
* @param shadowRoot
|
|
33761
|
+
* @param structureChangeMessage
|
|
33762
|
+
* @param previewStyleContent
|
|
33763
|
+
*/
|
|
33764
|
+
setValue(value, shadowRoot, structureChangeMessage, previewStyleContent) {
|
|
33765
|
+
this.deactivate();
|
|
33766
|
+
__privateGet$2(this, _setToTextarea).call(this, value);
|
|
33767
|
+
this.activate(shadowRoot, value, structureChangeMessage, previewStyleContent);
|
|
33768
|
+
}
|
|
33769
|
+
}
|
|
33770
|
+
_container = new WeakMap();
|
|
33771
|
+
_setToTextarea = new WeakMap();
|
|
33772
|
+
_preventEnterKey = new WeakMap();
|
|
33773
|
+
_syncToTextarea = new WeakMap();
|
|
33774
|
+
_TextOnlyModeController_instances = new WeakSet();
|
|
33775
|
+
attachEventListeners_fn = function() {
|
|
33776
|
+
if (!__privateGet$2(this, _container)) {
|
|
33777
|
+
return;
|
|
33778
|
+
}
|
|
33779
|
+
const editableElements = __privateGet$2(this, _container).querySelectorAll(
|
|
33780
|
+
'[contenteditable="plaintext-only"]'
|
|
33781
|
+
);
|
|
33782
|
+
for (const el of editableElements) {
|
|
33783
|
+
el.addEventListener("keydown", __privateGet$2(this, _preventEnterKey));
|
|
33784
|
+
el.addEventListener("input", __privateGet$2(this, _syncToTextarea));
|
|
33785
|
+
}
|
|
33786
|
+
};
|
|
33787
|
+
identifyEditableElements_fn = function(container) {
|
|
33788
|
+
const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
|
|
33789
|
+
acceptNode: (node) => {
|
|
33790
|
+
const element = node;
|
|
33791
|
+
const hasDirectTextChild = [...element.childNodes].some(
|
|
33792
|
+
(child) => child.nodeType === Node.TEXT_NODE && child.textContent?.trim()
|
|
33793
|
+
);
|
|
33794
|
+
if (hasDirectTextChild) {
|
|
33795
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
33796
|
+
}
|
|
33797
|
+
return NodeFilter.FILTER_SKIP;
|
|
33798
|
+
}
|
|
33799
|
+
});
|
|
33800
|
+
const editableElements = [];
|
|
33801
|
+
let currentNode;
|
|
33802
|
+
while (currentNode = walker.nextNode()) {
|
|
33803
|
+
editableElements.push(currentNode);
|
|
33804
|
+
}
|
|
33805
|
+
for (const el of editableElements) {
|
|
33806
|
+
el.setAttribute("contenteditable", "plaintext-only");
|
|
33807
|
+
}
|
|
33808
|
+
};
|
|
33809
|
+
|
|
33715
33810
|
var __defProp$1 = Object.defineProperty;
|
|
33716
33811
|
var __typeError$1 = (msg) => {
|
|
33717
33812
|
throw TypeError(msg);
|
|
@@ -33723,7 +33818,7 @@ var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "rea
|
|
|
33723
33818
|
var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
33724
33819
|
var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
|
|
33725
33820
|
var __privateMethod = (obj, member, method) => (__accessCheck$1(obj, member, "access private method"), method);
|
|
33726
|
-
var _editor, _editorRoot, _hasStructureChange, _isExpectingHTML, _isInitializing, _previewStyle, _structureChangeMessage, _textarea, _textareaDescriptor,
|
|
33821
|
+
var _editor, _editorRoot, _hasStructureChange, _isExpectingHTML, _isInitializing, _previewStyle, _structureChangeMessage, _textarea, _textareaDescriptor, _textOnlyMode, _BgeWysiwygElement_instances, checkStructureChange_fn, setStructureChange_fn, setToTextarea_fn, transaction_fn, updateStructureChangeMessage_fn;
|
|
33727
33822
|
function defineBgeWysiwygElement(options, global = window) {
|
|
33728
33823
|
if (options?.extensions) {
|
|
33729
33824
|
BgeWysiwygElement.extensions = options.extensions;
|
|
@@ -33752,26 +33847,7 @@ const _BgeWysiwygElement = class _BgeWysiwygElement extends HTMLElement {
|
|
|
33752
33847
|
__privateAdd$1(this, _structureChangeMessage, null);
|
|
33753
33848
|
__privateAdd$1(this, _textarea, null);
|
|
33754
33849
|
__privateAdd$1(this, _textareaDescriptor, null);
|
|
33755
|
-
__privateAdd$1(this,
|
|
33756
|
-
/**
|
|
33757
|
-
* Enter キーを防止するハンドラー
|
|
33758
|
-
* @param event
|
|
33759
|
-
*/
|
|
33760
|
-
__privateAdd$1(this, _preventEnterKey, (event) => {
|
|
33761
|
-
if (event.key === "Enter") {
|
|
33762
|
-
event.preventDefault();
|
|
33763
|
-
}
|
|
33764
|
-
});
|
|
33765
|
-
/**
|
|
33766
|
-
* text-onlyコンテナからtextareaへ同期
|
|
33767
|
-
*/
|
|
33768
|
-
__privateAdd$1(this, _syncTextOnlyToTextarea, () => {
|
|
33769
|
-
if (this.mode !== "text-only" || !__privateGet$1(this, _textOnlyContainer)) {
|
|
33770
|
-
return;
|
|
33771
|
-
}
|
|
33772
|
-
const cleanHTML = __privateMethod(this, _BgeWysiwygElement_instances, cleanTextOnlyHTML_fn).call(this, "");
|
|
33773
|
-
__privateMethod(this, _BgeWysiwygElement_instances, setToTextarea_fn).call(this, cleanHTML);
|
|
33774
|
-
});
|
|
33850
|
+
__privateAdd$1(this, _textOnlyMode, null);
|
|
33775
33851
|
this.attachShadow({ mode: "open" });
|
|
33776
33852
|
if (!this.shadowRoot) {
|
|
33777
33853
|
throw new Error("Not supported shadow DOM");
|
|
@@ -33782,7 +33858,7 @@ const _BgeWysiwygElement = class _BgeWysiwygElement extends HTMLElement {
|
|
|
33782
33858
|
throw new ReferenceError("<bge-wysiwyg> is not connected");
|
|
33783
33859
|
}
|
|
33784
33860
|
if (this.mode === "text-only") {
|
|
33785
|
-
return
|
|
33861
|
+
return __privateGet$1(this, _textOnlyMode)?.getValue(__privateGet$1(this, _textarea).value) ?? __privateGet$1(this, _textarea).value;
|
|
33786
33862
|
}
|
|
33787
33863
|
if (this.mode === "wysiwyg") {
|
|
33788
33864
|
if (!__privateGet$1(this, _editor)) {
|
|
@@ -33799,7 +33875,12 @@ const _BgeWysiwygElement = class _BgeWysiwygElement extends HTMLElement {
|
|
|
33799
33875
|
throw new ReferenceError("<bge-wysiwyg> is not connected");
|
|
33800
33876
|
}
|
|
33801
33877
|
if (this.mode === "text-only") {
|
|
33802
|
-
|
|
33878
|
+
__privateGet$1(this, _textOnlyMode)?.setValue(
|
|
33879
|
+
value,
|
|
33880
|
+
this.shadowRoot,
|
|
33881
|
+
__privateGet$1(this, _structureChangeMessage),
|
|
33882
|
+
__privateGet$1(this, _previewStyle)?.textContent ?? null
|
|
33883
|
+
);
|
|
33803
33884
|
return;
|
|
33804
33885
|
}
|
|
33805
33886
|
if (this.mode === "html") {
|
|
@@ -33834,14 +33915,20 @@ const _BgeWysiwygElement = class _BgeWysiwygElement extends HTMLElement {
|
|
|
33834
33915
|
return;
|
|
33835
33916
|
}
|
|
33836
33917
|
if (this.mode === "text-only") {
|
|
33837
|
-
|
|
33918
|
+
__privateGet$1(this, _textOnlyMode)?.deactivate();
|
|
33838
33919
|
}
|
|
33839
33920
|
if (mode === "wysiwyg" && this.mode === "html" && __privateMethod(this, _BgeWysiwygElement_instances, checkStructureChange_fn).call(this)) {
|
|
33840
33921
|
__privateMethod(this, _BgeWysiwygElement_instances, setStructureChange_fn).call(this, true);
|
|
33841
33922
|
return;
|
|
33842
33923
|
}
|
|
33843
33924
|
if (mode === "text-only") {
|
|
33844
|
-
|
|
33925
|
+
const currentHTML = this.mode === "wysiwyg" ? __privateGet$1(this, _editor).getHTML().replaceAll("<p></p>", "") : __privateGet$1(this, _textarea).value;
|
|
33926
|
+
__privateGet$1(this, _textOnlyMode)?.activate(
|
|
33927
|
+
this.shadowRoot,
|
|
33928
|
+
currentHTML,
|
|
33929
|
+
__privateGet$1(this, _structureChangeMessage),
|
|
33930
|
+
__privateGet$1(this, _previewStyle)?.textContent ?? null
|
|
33931
|
+
);
|
|
33845
33932
|
return;
|
|
33846
33933
|
}
|
|
33847
33934
|
this.shadowRoot.querySelector(`[data-bge-mode]`)?.setAttribute(
|
|
@@ -33886,87 +33973,7 @@ const _BgeWysiwygElement = class _BgeWysiwygElement extends HTMLElement {
|
|
|
33886
33973
|
const textarea = this.shadowRoot.querySelector("textarea");
|
|
33887
33974
|
const controlUIStyle = document.createElement("style");
|
|
33888
33975
|
this.shadowRoot.append(controlUIStyle);
|
|
33889
|
-
controlUIStyle.textContent =
|
|
33890
|
-
:host {
|
|
33891
|
-
display: block;
|
|
33892
|
-
}
|
|
33893
|
-
|
|
33894
|
-
textarea,
|
|
33895
|
-
iframe {
|
|
33896
|
-
block-size: 50svh;
|
|
33897
|
-
inline-size: 100%;
|
|
33898
|
-
resize: vertical;
|
|
33899
|
-
overflow-y: auto;
|
|
33900
|
-
background: var(--bge-lightest-color);
|
|
33901
|
-
border: 1px solid var(--bge-border-color);
|
|
33902
|
-
border-radius: var(--border-radius);
|
|
33903
|
-
}
|
|
33904
|
-
|
|
33905
|
-
iframe[data-focus-within="true"],
|
|
33906
|
-
textarea:focus-visible {
|
|
33907
|
-
--bge-border-color: var(--bge-ui-primary-color);
|
|
33908
|
-
--bge-outline-color: var(--bge-ui-primary-color);
|
|
33909
|
-
outline: var(--bge-focus-outline-width) solid var(--bge-outline-color);
|
|
33910
|
-
}
|
|
33911
|
-
|
|
33912
|
-
textarea {
|
|
33913
|
-
font-family: var(--bge-font-family-monospace);
|
|
33914
|
-
}
|
|
33915
|
-
|
|
33916
|
-
[data-bge-mode="wysiwyg"] textarea {
|
|
33917
|
-
display: none;
|
|
33918
|
-
}
|
|
33919
|
-
|
|
33920
|
-
[data-bge-mode="html"] iframe {
|
|
33921
|
-
display: none;
|
|
33922
|
-
}
|
|
33923
|
-
|
|
33924
|
-
[data-text-only-editor] {
|
|
33925
|
-
block-size: 50svh;
|
|
33926
|
-
inline-size: 100%;
|
|
33927
|
-
resize: vertical;
|
|
33928
|
-
overflow-y: auto;
|
|
33929
|
-
background: var(--bge-lightest-color);
|
|
33930
|
-
border: 1px solid var(--bge-border-color);
|
|
33931
|
-
border-radius: var(--border-radius);
|
|
33932
|
-
padding: 1rem;
|
|
33933
|
-
box-sizing: border-box;
|
|
33934
|
-
}
|
|
33935
|
-
|
|
33936
|
-
[data-bge-mode="wysiwyg"] [data-text-only-editor],
|
|
33937
|
-
[data-bge-mode="html"] [data-text-only-editor] {
|
|
33938
|
-
display: none;
|
|
33939
|
-
}
|
|
33940
|
-
|
|
33941
|
-
[data-bge-mode="text-only"] iframe,
|
|
33942
|
-
[data-bge-mode="text-only"] textarea {
|
|
33943
|
-
display: none;
|
|
33944
|
-
}
|
|
33945
|
-
|
|
33946
|
-
[contenteditable="plaintext-only"] {
|
|
33947
|
-
outline: 1px dashed var(--bge-border-color);
|
|
33948
|
-
cursor: text;
|
|
33949
|
-
}
|
|
33950
|
-
|
|
33951
|
-
[contenteditable="plaintext-only"]:hover {
|
|
33952
|
-
outline-color: var(--bge-ui-primary-color);
|
|
33953
|
-
}
|
|
33954
|
-
|
|
33955
|
-
[contenteditable="plaintext-only"]:focus {
|
|
33956
|
-
outline: 2px solid var(--bge-ui-primary-color);
|
|
33957
|
-
outline-offset: 2px;
|
|
33958
|
-
}
|
|
33959
|
-
|
|
33960
|
-
[role="alert"] {
|
|
33961
|
-
margin-block-start: 0.5rem;
|
|
33962
|
-
padding: 0.5rem;
|
|
33963
|
-
background-color: var(--bge-error-color, #fee);
|
|
33964
|
-
border: 1px solid var(--bge-error-border-color, #fcc);
|
|
33965
|
-
border-radius: var(--border-radius);
|
|
33966
|
-
color: var(--bge-error-text-color, #c00);
|
|
33967
|
-
font-size: 0.875rem;
|
|
33968
|
-
}
|
|
33969
|
-
`;
|
|
33976
|
+
controlUIStyle.textContent = controlUIStyles;
|
|
33970
33977
|
preview.contentDocument.body.addEventListener("focusin", () => {
|
|
33971
33978
|
preview.dataset.focusWithin = "true";
|
|
33972
33979
|
});
|
|
@@ -34027,6 +34034,9 @@ const _BgeWysiwygElement = class _BgeWysiwygElement extends HTMLElement {
|
|
|
34027
34034
|
HTMLTextAreaElement.prototype,
|
|
34028
34035
|
"value"
|
|
34029
34036
|
));
|
|
34037
|
+
__privateSet$1(this, _textOnlyMode, new TextOnlyModeController((html) => {
|
|
34038
|
+
__privateMethod(this, _BgeWysiwygElement_instances, setToTextarea_fn).call(this, html);
|
|
34039
|
+
}));
|
|
34030
34040
|
Object.defineProperty(__privateGet$1(this, _textarea), "value", {
|
|
34031
34041
|
get: () => {
|
|
34032
34042
|
return __privateGet$1(this, _textareaDescriptor)?.get?.call(__privateGet$1(this, _textarea)) ?? "";
|
|
@@ -34087,33 +34097,7 @@ const _BgeWysiwygElement = class _BgeWysiwygElement extends HTMLElement {
|
|
|
34087
34097
|
if (!__privateGet$1(this, _previewStyle)) {
|
|
34088
34098
|
throw new ReferenceError("<bge-wysiwyg> is not connected");
|
|
34089
34099
|
}
|
|
34090
|
-
__privateGet$1(this, _previewStyle).textContent =
|
|
34091
|
-
:where(html, body) {
|
|
34092
|
-
margin: 0;
|
|
34093
|
-
padding: 0;
|
|
34094
|
-
|
|
34095
|
-
:where(&, *) {
|
|
34096
|
-
box-sizing: border-box;
|
|
34097
|
-
}
|
|
34098
|
-
}
|
|
34099
|
-
|
|
34100
|
-
iframe,
|
|
34101
|
-
[contenteditable="true"] {
|
|
34102
|
-
padding: 1rem;
|
|
34103
|
-
block-size: 100%;
|
|
34104
|
-
box-sizing: border-box;
|
|
34105
|
-
}
|
|
34106
|
-
|
|
34107
|
-
[contenteditable="true"]:focus-visible {
|
|
34108
|
-
outline: none;
|
|
34109
|
-
}
|
|
34110
|
-
|
|
34111
|
-
${css}
|
|
34112
|
-
|
|
34113
|
-
a:any-link {
|
|
34114
|
-
pointer-events: none !important;
|
|
34115
|
-
}
|
|
34116
|
-
`;
|
|
34100
|
+
__privateGet$1(this, _previewStyle).textContent = editorContentStyles(css);
|
|
34117
34101
|
}
|
|
34118
34102
|
syncWysiwygToTextarea() {
|
|
34119
34103
|
if (__privateGet$1(this, _isExpectingHTML)) {
|
|
@@ -34184,47 +34168,8 @@ _previewStyle = new WeakMap();
|
|
|
34184
34168
|
_structureChangeMessage = new WeakMap();
|
|
34185
34169
|
_textarea = new WeakMap();
|
|
34186
34170
|
_textareaDescriptor = new WeakMap();
|
|
34187
|
-
|
|
34188
|
-
_preventEnterKey = new WeakMap();
|
|
34189
|
-
_syncTextOnlyToTextarea = new WeakMap();
|
|
34171
|
+
_textOnlyMode = new WeakMap();
|
|
34190
34172
|
_BgeWysiwygElement_instances = new WeakSet();
|
|
34191
|
-
/**
|
|
34192
|
-
* text-onlyモードを有効化
|
|
34193
|
-
*/
|
|
34194
|
-
activateTextOnlyMode_fn = function() {
|
|
34195
|
-
const currentHTML = this.mode === "wysiwyg" ? __privateGet$1(this, _editor).getHTML().replaceAll("<p></p>", "") : __privateGet$1(this, _textarea).value;
|
|
34196
|
-
if (!__privateGet$1(this, _textOnlyContainer)) {
|
|
34197
|
-
__privateSet$1(this, _textOnlyContainer, document.createElement("div"));
|
|
34198
|
-
__privateGet$1(this, _textOnlyContainer).dataset.textOnlyEditor = "";
|
|
34199
|
-
const modeContainer = this.shadowRoot.querySelector("[data-bge-mode]");
|
|
34200
|
-
modeContainer.insertBefore(__privateGet$1(this, _textOnlyContainer), __privateGet$1(this, _structureChangeMessage));
|
|
34201
|
-
}
|
|
34202
|
-
const textOnlyStyle = document.createElement("style");
|
|
34203
|
-
textOnlyStyle.dataset.textOnlyStyle = "";
|
|
34204
|
-
if (__privateGet$1(this, _previewStyle)) {
|
|
34205
|
-
textOnlyStyle.textContent = __privateGet$1(this, _previewStyle).textContent;
|
|
34206
|
-
}
|
|
34207
|
-
__privateGet$1(this, _textOnlyContainer).innerHTML = currentHTML;
|
|
34208
|
-
__privateGet$1(this, _textOnlyContainer).prepend(textOnlyStyle);
|
|
34209
|
-
__privateMethod(this, _BgeWysiwygElement_instances, identifyEditableElements_fn).call(this, __privateGet$1(this, _textOnlyContainer));
|
|
34210
|
-
__privateMethod(this, _BgeWysiwygElement_instances, attachTextOnlyEventListeners_fn).call(this);
|
|
34211
|
-
this.shadowRoot.querySelector(`[data-bge-mode]`).dataset.bgeMode = "text-only";
|
|
34212
|
-
};
|
|
34213
|
-
/**
|
|
34214
|
-
* text-onlyモード用のイベントリスナーを設定
|
|
34215
|
-
*/
|
|
34216
|
-
attachTextOnlyEventListeners_fn = function() {
|
|
34217
|
-
if (!__privateGet$1(this, _textOnlyContainer)) {
|
|
34218
|
-
return;
|
|
34219
|
-
}
|
|
34220
|
-
const editableElements = __privateGet$1(this, _textOnlyContainer).querySelectorAll(
|
|
34221
|
-
'[contenteditable="plaintext-only"]'
|
|
34222
|
-
);
|
|
34223
|
-
for (const el of editableElements) {
|
|
34224
|
-
el.addEventListener("keydown", __privateGet$1(this, _preventEnterKey));
|
|
34225
|
-
el.addEventListener("input", __privateGet$1(this, _syncTextOnlyToTextarea));
|
|
34226
|
-
}
|
|
34227
|
-
};
|
|
34228
34173
|
checkStructureChange_fn = function() {
|
|
34229
34174
|
if (!__privateGet$1(this, _editor) || !__privateGet$1(this, _textarea) || this.mode !== "html") {
|
|
34230
34175
|
return false;
|
|
@@ -34233,76 +34178,6 @@ checkStructureChange_fn = function() {
|
|
|
34233
34178
|
const isStructureSame = normalizeHtmlStructure(__privateGet$1(this, _textarea).value, expectedHTML);
|
|
34234
34179
|
return !isStructureSame;
|
|
34235
34180
|
};
|
|
34236
|
-
/**
|
|
34237
|
-
* contenteditable属性を削除してクリーンなHTMLを返す
|
|
34238
|
-
* @param html
|
|
34239
|
-
*/
|
|
34240
|
-
cleanTextOnlyHTML_fn = function(html) {
|
|
34241
|
-
if (!__privateGet$1(this, _textOnlyContainer)) {
|
|
34242
|
-
return html;
|
|
34243
|
-
}
|
|
34244
|
-
const clone = __privateGet$1(this, _textOnlyContainer).cloneNode(true);
|
|
34245
|
-
const editableElements = clone.querySelectorAll('[contenteditable="plaintext-only"]');
|
|
34246
|
-
for (const el of editableElements) {
|
|
34247
|
-
el.removeAttribute("contenteditable");
|
|
34248
|
-
}
|
|
34249
|
-
const styleElements = clone.querySelectorAll("[data-text-only-style]");
|
|
34250
|
-
for (const el of styleElements) {
|
|
34251
|
-
el.remove();
|
|
34252
|
-
}
|
|
34253
|
-
return clone.innerHTML;
|
|
34254
|
-
};
|
|
34255
|
-
/**
|
|
34256
|
-
* text-onlyモードを無効化
|
|
34257
|
-
*/
|
|
34258
|
-
deactivateTextOnlyMode_fn = function() {
|
|
34259
|
-
if (!__privateGet$1(this, _textOnlyContainer)) {
|
|
34260
|
-
return;
|
|
34261
|
-
}
|
|
34262
|
-
const editableElements = __privateGet$1(this, _textOnlyContainer).querySelectorAll(
|
|
34263
|
-
'[contenteditable="plaintext-only"]'
|
|
34264
|
-
);
|
|
34265
|
-
for (const el of editableElements) {
|
|
34266
|
-
el.removeEventListener("keydown", __privateGet$1(this, _preventEnterKey));
|
|
34267
|
-
el.removeEventListener("input", __privateGet$1(this, _syncTextOnlyToTextarea));
|
|
34268
|
-
}
|
|
34269
|
-
__privateGet$1(this, _textOnlyContainer).innerHTML = "";
|
|
34270
|
-
};
|
|
34271
|
-
/**
|
|
34272
|
-
* text-onlyモードの値を取得
|
|
34273
|
-
*/
|
|
34274
|
-
getTextOnlyValue_fn = function() {
|
|
34275
|
-
if (!__privateGet$1(this, _textOnlyContainer)) {
|
|
34276
|
-
return __privateGet$1(this, _textarea)?.value ?? "";
|
|
34277
|
-
}
|
|
34278
|
-
return __privateMethod(this, _BgeWysiwygElement_instances, cleanTextOnlyHTML_fn).call(this, "");
|
|
34279
|
-
};
|
|
34280
|
-
/**
|
|
34281
|
-
* 編集可能要素を特定してcontenteditable="plaintext-only"を付与
|
|
34282
|
-
* @param container
|
|
34283
|
-
*/
|
|
34284
|
-
identifyEditableElements_fn = function(container) {
|
|
34285
|
-
const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
|
|
34286
|
-
acceptNode: (node) => {
|
|
34287
|
-
const element = node;
|
|
34288
|
-
const hasDirectTextChild = [...element.childNodes].some(
|
|
34289
|
-
(child) => child.nodeType === Node.TEXT_NODE && child.textContent?.trim()
|
|
34290
|
-
);
|
|
34291
|
-
if (hasDirectTextChild) {
|
|
34292
|
-
return NodeFilter.FILTER_ACCEPT;
|
|
34293
|
-
}
|
|
34294
|
-
return NodeFilter.FILTER_SKIP;
|
|
34295
|
-
}
|
|
34296
|
-
});
|
|
34297
|
-
const editableElements = [];
|
|
34298
|
-
let currentNode;
|
|
34299
|
-
while (currentNode = walker.nextNode()) {
|
|
34300
|
-
editableElements.push(currentNode);
|
|
34301
|
-
}
|
|
34302
|
-
for (const el of editableElements) {
|
|
34303
|
-
el.setAttribute("contenteditable", "plaintext-only");
|
|
34304
|
-
}
|
|
34305
|
-
};
|
|
34306
34181
|
setStructureChange_fn = function(hasChange) {
|
|
34307
34182
|
if (__privateGet$1(this, _hasStructureChange) === hasChange) {
|
|
34308
34183
|
return;
|
|
@@ -34317,22 +34192,12 @@ setStructureChange_fn = function(hasChange) {
|
|
|
34317
34192
|
})
|
|
34318
34193
|
);
|
|
34319
34194
|
};
|
|
34320
|
-
/**
|
|
34321
|
-
* text-onlyモードに値を設定
|
|
34322
|
-
* @param value
|
|
34323
|
-
*/
|
|
34324
|
-
setTextOnlyValue_fn = function(value) {
|
|
34325
|
-
__privateMethod(this, _BgeWysiwygElement_instances, deactivateTextOnlyMode_fn).call(this);
|
|
34326
|
-
__privateMethod(this, _BgeWysiwygElement_instances, setToTextarea_fn).call(this, value);
|
|
34327
|
-
__privateMethod(this, _BgeWysiwygElement_instances, activateTextOnlyMode_fn).call(this);
|
|
34328
|
-
};
|
|
34329
34195
|
setToTextarea_fn = function(html) {
|
|
34330
34196
|
if (!__privateGet$1(this, _textarea) || !__privateGet$1(this, _textareaDescriptor)) {
|
|
34331
34197
|
throw new ReferenceError("<bge-wysiwyg> is not connected");
|
|
34332
34198
|
}
|
|
34333
34199
|
__privateGet$1(this, _textareaDescriptor).set?.call(__privateGet$1(this, _textarea), html);
|
|
34334
34200
|
};
|
|
34335
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
34336
34201
|
transaction_fn = function(_editor2) {
|
|
34337
34202
|
const data = {
|
|
34338
34203
|
state: getCurrentEditorState(this)
|
|
@@ -45105,7 +44970,7 @@ function parseConfig(config) {
|
|
|
45105
44970
|
}
|
|
45106
44971
|
}
|
|
45107
44972
|
|
|
45108
|
-
const version = "4.0.0-alpha.
|
|
44973
|
+
const version = "4.0.0-alpha.63";
|
|
45109
44974
|
function attachDraftSwitcher(engine) {
|
|
45110
44975
|
if (engine.hasDraft()) {
|
|
45111
44976
|
const container = document.createElement("div");
|