@burger-editor/local 4.0.0-alpha.3 → 4.0.0-alpha.4
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 +1431 -407
- package/dist/client.js.map +1 -1
- package/dist/local.css +50 -2
- package/package.json +6 -6
- package/server/helpers/$upload.d.ts +12 -6
- package/server/helpers/$upload.js +22 -22
- package/server/helpers/debug.d.ts +1 -1
- package/server/helpers/edit-content.d.ts +10 -3
- package/server/helpers/edit-content.js +35 -36
- package/server/helpers/file-name.d.ts +5 -5
- package/server/helpers/file-name.js +28 -28
- package/server/helpers/pagination.d.ts +14 -10
- package/server/helpers/pagination.js +33 -33
- package/server/index.d.ts +1 -1
- package/server/index.js +6 -5
- package/server/model/default-config.d.ts +5 -5
- package/server/model/default-config.js +4 -4
- package/server/model/file-list-manager.d.ts +15 -11
- package/server/model/file-list-manager.js +128 -124
- package/server/model/file-tree.d.ts +10 -7
- package/server/model/file-tree.js +26 -25
- package/server/model/get-user-config.d.ts +1 -1
- package/server/model/get-user-config.js +67 -67
- package/server/route.d.ts +269 -258
- package/server/route.js +260 -208
- package/server/types.d.ts +21 -18
- package/server/view/app.d.ts +11 -6
- package/server/view/app.js +18 -2
- package/server/view/layout.d.ts +6 -3
- package/server/view/layout.d.ts.map +1 -1
- package/server/view/layout.js +23 -2
- package/server/view/nav-tree.d.ts +6 -4
- package/server/view/nav-tree.js +19 -2
- package/server/view/nav.d.ts +6 -4
- package/server/view/nav.js +46 -3
package/dist/client.js
CHANGED
|
@@ -3131,14 +3131,14 @@ function next (prev, current, isPre) {
|
|
|
3131
3131
|
* Set up window for Node.js
|
|
3132
3132
|
*/
|
|
3133
3133
|
|
|
3134
|
-
var root$
|
|
3134
|
+
var root$6 = (typeof window !== 'undefined' ? window : {});
|
|
3135
3135
|
|
|
3136
3136
|
/*
|
|
3137
3137
|
* Parsing HTML strings
|
|
3138
3138
|
*/
|
|
3139
3139
|
|
|
3140
3140
|
function canParseHTMLNatively$1 () {
|
|
3141
|
-
var Parser = root$
|
|
3141
|
+
var Parser = root$6.DOMParser;
|
|
3142
3142
|
var canParse = false;
|
|
3143
3143
|
|
|
3144
3144
|
// Adapted from https://gist.github.com/1129031
|
|
@@ -3184,12 +3184,12 @@ function shouldUseActiveX$1 () {
|
|
|
3184
3184
|
try {
|
|
3185
3185
|
document.implementation.createHTMLDocument('').open();
|
|
3186
3186
|
} catch (e) {
|
|
3187
|
-
if (root$
|
|
3187
|
+
if (root$6.ActiveXObject) useActiveX = true;
|
|
3188
3188
|
}
|
|
3189
3189
|
return useActiveX
|
|
3190
3190
|
}
|
|
3191
3191
|
|
|
3192
|
-
var HTMLParser = canParseHTMLNatively$1() ? root$
|
|
3192
|
+
var HTMLParser = canParseHTMLNatively$1() ? root$6.DOMParser : createHTMLParser$1();
|
|
3193
3193
|
|
|
3194
3194
|
function RootNode (input, options) {
|
|
3195
3195
|
var root;
|
|
@@ -6323,6 +6323,20 @@ let NoHTMLElementError$1 = class NoHTMLElementError extends Error {
|
|
|
6323
6323
|
}
|
|
6324
6324
|
};
|
|
6325
6325
|
|
|
6326
|
+
/**
|
|
6327
|
+
* List of dangerous HTML elements to block for XSS protection
|
|
6328
|
+
*/
|
|
6329
|
+
const DANGEROUS_ELEMENTS$1 = [
|
|
6330
|
+
'script',
|
|
6331
|
+
'style',
|
|
6332
|
+
'template',
|
|
6333
|
+
'object',
|
|
6334
|
+
'embed',
|
|
6335
|
+
'iframe',
|
|
6336
|
+
'frame',
|
|
6337
|
+
'frameset',
|
|
6338
|
+
'applet',
|
|
6339
|
+
];
|
|
6326
6340
|
/**
|
|
6327
6341
|
*
|
|
6328
6342
|
* @param kvs
|
|
@@ -6346,31 +6360,302 @@ function arrayToHash$1(kvs) {
|
|
|
6346
6360
|
}
|
|
6347
6361
|
return result;
|
|
6348
6362
|
}
|
|
6363
|
+
const kebabCaseCache$1 = new Map();
|
|
6349
6364
|
/**
|
|
6350
6365
|
*
|
|
6351
6366
|
* @param str
|
|
6352
6367
|
*/
|
|
6353
6368
|
function kebabCase$1(str) {
|
|
6354
|
-
|
|
6369
|
+
if (kebabCaseCache$1.has(str)) {
|
|
6370
|
+
return kebabCaseCache$1.get(str);
|
|
6371
|
+
}
|
|
6372
|
+
const result = str.replaceAll(/([A-Z])/g, '-$1').toLowerCase();
|
|
6373
|
+
kebabCaseCache$1.set(str, result);
|
|
6374
|
+
return result;
|
|
6355
6375
|
}
|
|
6376
|
+
const camelCaseCache$1 = new Map();
|
|
6356
6377
|
/**
|
|
6357
6378
|
*
|
|
6358
6379
|
* @param str
|
|
6359
6380
|
*/
|
|
6360
6381
|
function camelCase$1(str) {
|
|
6361
|
-
|
|
6382
|
+
if (camelCaseCache$1.has(str)) {
|
|
6383
|
+
return camelCaseCache$1.get(str);
|
|
6384
|
+
}
|
|
6385
|
+
const result = str.replaceAll(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
6386
|
+
camelCaseCache$1.set(str, result);
|
|
6387
|
+
return result;
|
|
6388
|
+
}
|
|
6389
|
+
/**
|
|
6390
|
+
*
|
|
6391
|
+
* @param el
|
|
6392
|
+
* @param nodeName
|
|
6393
|
+
* @param attr
|
|
6394
|
+
* @param xssSanitize
|
|
6395
|
+
*/
|
|
6396
|
+
function replaceNode$1(el, nodeName, attr, xssSanitize = true) {
|
|
6397
|
+
nodeName = nodeName.toLowerCase();
|
|
6398
|
+
const currentName = el.localName ?? el.nodeName.toLowerCase();
|
|
6399
|
+
if (currentName === nodeName) {
|
|
6400
|
+
return el;
|
|
6401
|
+
}
|
|
6402
|
+
// Check element name if XSS protection is enabled
|
|
6403
|
+
if (xssSanitize && // Disallow dangerous elements
|
|
6404
|
+
DANGEROUS_ELEMENTS$1.includes(nodeName)) {
|
|
6405
|
+
return el;
|
|
6406
|
+
}
|
|
6407
|
+
const node = (el.ownerDocument ?? document).createElement(nodeName);
|
|
6408
|
+
for (const child of el.childNodes) {
|
|
6409
|
+
node.append(child.cloneNode(true));
|
|
6410
|
+
}
|
|
6411
|
+
const fields = getFields$1(el, attr);
|
|
6412
|
+
const attrs = new Set(fields.map((field) => field.propName));
|
|
6413
|
+
for (const { name, value } of el.attributes) {
|
|
6414
|
+
if (attrs.has(name)) {
|
|
6415
|
+
continue;
|
|
6416
|
+
}
|
|
6417
|
+
// Check attribute value if XSS protection is enabled
|
|
6418
|
+
if (xssSanitize) {
|
|
6419
|
+
const sanitizedValue = sanitizeAttributeValue$1(name, value);
|
|
6420
|
+
if (sanitizedValue !== null) {
|
|
6421
|
+
node.setAttribute(name, sanitizedValue);
|
|
6422
|
+
}
|
|
6423
|
+
continue;
|
|
6424
|
+
}
|
|
6425
|
+
node.setAttribute(name, value);
|
|
6426
|
+
}
|
|
6427
|
+
el.replaceWith(node);
|
|
6428
|
+
return node;
|
|
6429
|
+
}
|
|
6430
|
+
/**
|
|
6431
|
+
* Removes dangerous script elements from HTML string
|
|
6432
|
+
* @param html HTML string
|
|
6433
|
+
* @returns Sanitized HTML
|
|
6434
|
+
*/
|
|
6435
|
+
function sanitizeHtml$1(html) {
|
|
6436
|
+
if (typeof html !== 'string') {
|
|
6437
|
+
return '';
|
|
6438
|
+
}
|
|
6439
|
+
// Simple approach to handle script tags content
|
|
6440
|
+
// First remove script tags but keep their content
|
|
6441
|
+
let sanitized = html;
|
|
6442
|
+
// For each dangerous element, replace tag but keep content using regex
|
|
6443
|
+
// Example: <script>alert("XSS")</script> -> alert("XSS")
|
|
6444
|
+
for (const tagName of DANGEROUS_ELEMENTS$1) {
|
|
6445
|
+
const regex = new RegExp(`<${tagName}[^>]*>(.*?)<\\/${tagName}>`, 'gis');
|
|
6446
|
+
sanitized = sanitized.replace(regex, '$1');
|
|
6447
|
+
}
|
|
6448
|
+
// Parse HTML safely using DOM parser for remaining sanitization
|
|
6449
|
+
const doc = new DOMParser().parseFromString(sanitized, 'text/html');
|
|
6450
|
+
const body = doc.body;
|
|
6451
|
+
// Remove event handler attributes from all elements
|
|
6452
|
+
sanitizeElementAndChildren$1(body);
|
|
6453
|
+
return body.innerHTML;
|
|
6454
|
+
}
|
|
6455
|
+
/**
|
|
6456
|
+
* Sanitizes an element and all its child elements
|
|
6457
|
+
* @param element Target element
|
|
6458
|
+
*/
|
|
6459
|
+
function sanitizeElementAndChildren$1(element) {
|
|
6460
|
+
// Remove dangerous attributes from current element
|
|
6461
|
+
sanitizeAttributes$1(element);
|
|
6462
|
+
// Process child elements recursively
|
|
6463
|
+
const children = element.children;
|
|
6464
|
+
for (const child of children) {
|
|
6465
|
+
sanitizeElementAndChildren$1(child);
|
|
6466
|
+
}
|
|
6467
|
+
}
|
|
6468
|
+
/**
|
|
6469
|
+
* Sanitizes attribute value
|
|
6470
|
+
* @param name Attribute name
|
|
6471
|
+
* @param value Attribute value
|
|
6472
|
+
* @returns Safe attribute value, or null if dangerous
|
|
6473
|
+
*/
|
|
6474
|
+
function sanitizeAttributeValue$1(name, value) {
|
|
6475
|
+
if (typeof value !== 'string') {
|
|
6476
|
+
return value;
|
|
6477
|
+
}
|
|
6478
|
+
name = name.toLowerCase();
|
|
6479
|
+
// Disallow event handler attributes
|
|
6480
|
+
if (name.startsWith('on')) {
|
|
6481
|
+
return null;
|
|
6482
|
+
}
|
|
6483
|
+
// Check for dangerous protocol in link attributes
|
|
6484
|
+
if (name === 'href' ||
|
|
6485
|
+
name === 'src' ||
|
|
6486
|
+
name === 'action' ||
|
|
6487
|
+
name === 'formaction' ||
|
|
6488
|
+
name === 'xlink:href') {
|
|
6489
|
+
const trimmedValue = value.trim().toLowerCase();
|
|
6490
|
+
if (trimmedValue.startsWith('javascript:') ||
|
|
6491
|
+
trimmedValue.startsWith('data:') ||
|
|
6492
|
+
trimmedValue.startsWith('vbscript:')) {
|
|
6493
|
+
return null;
|
|
6494
|
+
}
|
|
6495
|
+
}
|
|
6496
|
+
// Other dangerous attributes
|
|
6497
|
+
if (['manifest'].includes(name)) {
|
|
6498
|
+
return null;
|
|
6499
|
+
}
|
|
6500
|
+
return value;
|
|
6501
|
+
}
|
|
6502
|
+
/**
|
|
6503
|
+
* Removes dangerous attributes from an element
|
|
6504
|
+
* @param element Target element
|
|
6505
|
+
*/
|
|
6506
|
+
function sanitizeAttributes$1(element) {
|
|
6507
|
+
// Collect list of dangerous attributes
|
|
6508
|
+
const dangerousAttrs = [...element.attributes]
|
|
6509
|
+
.filter((attr) => sanitizeAttributeValue$1(attr.name, attr.value) === null)
|
|
6510
|
+
.map((attr) => attr.name);
|
|
6511
|
+
// Remove dangerous attributes
|
|
6512
|
+
for (const attrName of dangerousAttrs) {
|
|
6513
|
+
element.removeAttribute(attrName);
|
|
6514
|
+
}
|
|
6515
|
+
}
|
|
6516
|
+
/**
|
|
6517
|
+
*
|
|
6518
|
+
* @param data
|
|
6519
|
+
* @param definedFields
|
|
6520
|
+
*/
|
|
6521
|
+
function maxLengthOf$1(data, definedFields) {
|
|
6522
|
+
let maxLength = 0;
|
|
6523
|
+
for (const key in data) {
|
|
6524
|
+
if (definedFields.includes(key) && Array.isArray(data[key])) {
|
|
6525
|
+
maxLength = Math.max(maxLength, data[key].length);
|
|
6526
|
+
}
|
|
6527
|
+
}
|
|
6528
|
+
return maxLength;
|
|
6529
|
+
}
|
|
6530
|
+
/**
|
|
6531
|
+
*
|
|
6532
|
+
* @param el
|
|
6533
|
+
* @param attr
|
|
6534
|
+
*/
|
|
6535
|
+
function definedFields$1(el, attr) {
|
|
6536
|
+
const fieldDefinitions = getFields$1(el, attr);
|
|
6537
|
+
return fieldDefinitions.map((field) => field.fieldName);
|
|
6538
|
+
}
|
|
6539
|
+
/**
|
|
6540
|
+
*
|
|
6541
|
+
* @param el
|
|
6542
|
+
* @param attr
|
|
6543
|
+
*/
|
|
6544
|
+
function getFields$1(el, attr) {
|
|
6545
|
+
const fields = el.getAttribute(`data-${attr}`);
|
|
6546
|
+
if (!fields) {
|
|
6547
|
+
return [];
|
|
6548
|
+
}
|
|
6549
|
+
return parseFields$1(fields);
|
|
6550
|
+
}
|
|
6551
|
+
/**
|
|
6552
|
+
*
|
|
6553
|
+
* @param el
|
|
6554
|
+
* @param attr
|
|
6555
|
+
* @param dataKeyName
|
|
6556
|
+
*/
|
|
6557
|
+
function hasField$1(el, attr, dataKeyName) {
|
|
6558
|
+
const fieldDefinitions = getFields$1(el, attr);
|
|
6559
|
+
return fieldDefinitions.some((field) => field.fieldName === dataKeyName);
|
|
6560
|
+
}
|
|
6561
|
+
/**
|
|
6562
|
+
*
|
|
6563
|
+
* @param fields
|
|
6564
|
+
* @param oldPropName
|
|
6565
|
+
* @param newPropName
|
|
6566
|
+
*/
|
|
6567
|
+
function replaceProp$1(fields, oldPropName, newPropName) {
|
|
6568
|
+
return fields.map((field) => {
|
|
6569
|
+
if (field.propName === oldPropName) {
|
|
6570
|
+
return {
|
|
6571
|
+
...field,
|
|
6572
|
+
propName: newPropName,
|
|
6573
|
+
};
|
|
6574
|
+
}
|
|
6575
|
+
return field;
|
|
6576
|
+
});
|
|
6577
|
+
}
|
|
6578
|
+
/**
|
|
6579
|
+
*
|
|
6580
|
+
* @param fields
|
|
6581
|
+
* @param propName
|
|
6582
|
+
*/
|
|
6583
|
+
function removeProp$1(fields, propName) {
|
|
6584
|
+
return fields.filter((field) => field.propName !== propName);
|
|
6585
|
+
}
|
|
6586
|
+
/**
|
|
6587
|
+
* - 値が配列の場合は、index に対応する値を返す。
|
|
6588
|
+
* - 値が配列でない場合は、そのまま返す。
|
|
6589
|
+
* - ⚠️ 値が配列で、index に対応する値が undefined の場合は、配列の最初の値を返す。
|
|
6590
|
+
* @param data
|
|
6591
|
+
* @param index
|
|
6592
|
+
*/
|
|
6593
|
+
function flattenData$1(data, index) {
|
|
6594
|
+
const result = {};
|
|
6595
|
+
for (const key in data) {
|
|
6596
|
+
result[key] = Array.isArray(data[key])
|
|
6597
|
+
? data[key][index] === undefined
|
|
6598
|
+
? data[key][0]
|
|
6599
|
+
: data[key][index]
|
|
6600
|
+
: data[key];
|
|
6601
|
+
}
|
|
6602
|
+
return result;
|
|
6603
|
+
}
|
|
6604
|
+
/**
|
|
6605
|
+
* 特定の要素で、`propName in element`で判定できない属性名
|
|
6606
|
+
*/
|
|
6607
|
+
const specificProp$1 = {
|
|
6608
|
+
/*
|
|
6609
|
+
* JSDOMの未実装対策
|
|
6610
|
+
* @see https://github.com/jsdom/jsdom/blob/main/lib/jsdom/living/nodes/HTMLSourceElement.webidl
|
|
6611
|
+
* Living Standardでは実装済み
|
|
6612
|
+
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#htmlsourceelement
|
|
6613
|
+
*/
|
|
6614
|
+
source: ['width', 'height'],
|
|
6615
|
+
};
|
|
6616
|
+
/**
|
|
6617
|
+
*
|
|
6618
|
+
* @param el
|
|
6619
|
+
* @param name
|
|
6620
|
+
*/
|
|
6621
|
+
function propInElement$1(el, name) {
|
|
6622
|
+
const has = name in el;
|
|
6623
|
+
if (has) {
|
|
6624
|
+
return true;
|
|
6625
|
+
}
|
|
6626
|
+
return specificProp$1[el.localName]?.includes(name) ?? false;
|
|
6362
6627
|
}
|
|
6363
6628
|
|
|
6629
|
+
const cache$1 = new Map();
|
|
6630
|
+
/**
|
|
6631
|
+
*
|
|
6632
|
+
* @param query
|
|
6633
|
+
*/
|
|
6634
|
+
function parseFields$1(query) {
|
|
6635
|
+
const cached = cache$1.get(query);
|
|
6636
|
+
if (cached) {
|
|
6637
|
+
return cached;
|
|
6638
|
+
}
|
|
6639
|
+
const fields = query.split(',');
|
|
6640
|
+
const result = fields.map(parseField$1);
|
|
6641
|
+
cache$1.set(query, result);
|
|
6642
|
+
return result;
|
|
6643
|
+
}
|
|
6364
6644
|
/**
|
|
6365
6645
|
*
|
|
6366
6646
|
* @param field
|
|
6367
6647
|
*/
|
|
6368
|
-
function
|
|
6648
|
+
function parseField$1(field) {
|
|
6369
6649
|
field = field.trim().toLowerCase();
|
|
6370
6650
|
if (!field) {
|
|
6371
6651
|
throw new Error('Field name is empty.');
|
|
6372
6652
|
}
|
|
6373
|
-
let [fieldName, propName
|
|
6653
|
+
let [fieldName, propName,
|
|
6654
|
+
// eslint-disable-next-line prefer-const
|
|
6655
|
+
...rest] = field.split(':');
|
|
6656
|
+
if (rest.length > 0) {
|
|
6657
|
+
throw new Error('Invalid field format.');
|
|
6658
|
+
}
|
|
6374
6659
|
propName = propName?.trim() || '';
|
|
6375
6660
|
fieldName = fieldName?.trim() || propName || field;
|
|
6376
6661
|
return {
|
|
@@ -6390,58 +6675,67 @@ function fieldNameParser$1(field) {
|
|
|
6390
6675
|
* @param datum A datum of value
|
|
6391
6676
|
* @param attr Data attribute name for specifying the node that FrozenPatty treats as a field
|
|
6392
6677
|
* @param filter
|
|
6678
|
+
* @param xssSanitize Enable XSS protection
|
|
6393
6679
|
*/
|
|
6394
|
-
function setValue$1(el, name, datum, attr = 'field', filter) {
|
|
6680
|
+
function setValue$1(el, name, datum, attr = 'field', filter, xssSanitize = true) {
|
|
6395
6681
|
const rawValue = el.getAttribute(`data-${attr}`);
|
|
6396
|
-
const
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
//
|
|
6427
|
-
default: {
|
|
6428
|
-
cssValue = `${datum}`;
|
|
6429
|
-
}
|
|
6430
|
-
}
|
|
6431
|
-
el.setAttribute('style', `${cssPropertyName}: ${cssValue}`);
|
|
6432
|
-
}
|
|
6433
|
-
else if (el instanceof HTMLElement) {
|
|
6434
|
-
// HTMLElement
|
|
6435
|
-
set$4(el, attr, propName, datum);
|
|
6682
|
+
const fields = parseFields$1(rawValue ?? '');
|
|
6683
|
+
const field = fields.find((field) => field.fieldName === name);
|
|
6684
|
+
if (!field) {
|
|
6685
|
+
return;
|
|
6686
|
+
}
|
|
6687
|
+
const { propName } = field;
|
|
6688
|
+
if (filter) {
|
|
6689
|
+
datum = filter(datum);
|
|
6690
|
+
}
|
|
6691
|
+
// console.log({ name, field, fieldName, propName, datum, el: el.innerHTML });
|
|
6692
|
+
if (!propName) {
|
|
6693
|
+
setContent$1(el, datum, undefined, xssSanitize);
|
|
6694
|
+
return;
|
|
6695
|
+
}
|
|
6696
|
+
if (propName === 'style' && el instanceof HTMLElement) {
|
|
6697
|
+
el.style.cssText = `${datum}`;
|
|
6698
|
+
return;
|
|
6699
|
+
}
|
|
6700
|
+
if (/^style\([a-z-]+\)$/i.test(propName)) {
|
|
6701
|
+
const cssPropertyName = propName.replace(/^style\(([a-z-]+)\)$/i, '$1');
|
|
6702
|
+
let cssValue;
|
|
6703
|
+
switch (cssPropertyName) {
|
|
6704
|
+
case 'background-image': {
|
|
6705
|
+
// Using CSS method would create absolute URLs with host
|
|
6706
|
+
// This would prevent migration from demo to production server
|
|
6707
|
+
// Using simple string insertion (setAttribute) instead
|
|
6708
|
+
// URL may not contain multibyte or whitespace characters, but escape anyway
|
|
6709
|
+
const url = encodeURI(`${datum}`);
|
|
6710
|
+
cssValue = `url(${url})`;
|
|
6711
|
+
break;
|
|
6436
6712
|
}
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6713
|
+
//
|
|
6714
|
+
// TODO: Handle other cases where values need units
|
|
6715
|
+
//
|
|
6716
|
+
default: {
|
|
6717
|
+
cssValue = `${datum}`;
|
|
6440
6718
|
}
|
|
6441
|
-
return;
|
|
6442
6719
|
}
|
|
6443
|
-
|
|
6720
|
+
el.setAttribute('style', `${cssPropertyName}: ${cssValue}`);
|
|
6721
|
+
return;
|
|
6444
6722
|
}
|
|
6723
|
+
if (el instanceof HTMLElement) {
|
|
6724
|
+
// HTMLElement
|
|
6725
|
+
set$2(el, attr, propName, datum, xssSanitize);
|
|
6726
|
+
return;
|
|
6727
|
+
}
|
|
6728
|
+
// SVGElement or more
|
|
6729
|
+
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
|
6730
|
+
// Check attribute value if XSS protection is enabled
|
|
6731
|
+
if (xssSanitize) {
|
|
6732
|
+
const safeValue = sanitizeAttributeValue$1(propName, `${datum}`);
|
|
6733
|
+
if (safeValue !== null) {
|
|
6734
|
+
el.setAttribute(propName, safeValue);
|
|
6735
|
+
}
|
|
6736
|
+
return;
|
|
6737
|
+
}
|
|
6738
|
+
el.setAttribute(propName, `${datum}`);
|
|
6445
6739
|
}
|
|
6446
6740
|
/**
|
|
6447
6741
|
*
|
|
@@ -6449,41 +6743,54 @@ function setValue$1(el, name, datum, attr = 'field', filter) {
|
|
|
6449
6743
|
* @param prefix
|
|
6450
6744
|
* @param name
|
|
6451
6745
|
* @param datum
|
|
6746
|
+
* @param xssSanitize
|
|
6452
6747
|
*/
|
|
6453
|
-
function set$
|
|
6748
|
+
function set$2(el, prefix, name, datum, xssSanitize = true) {
|
|
6454
6749
|
if (datum == null) {
|
|
6455
6750
|
el.removeAttribute(name);
|
|
6456
6751
|
return;
|
|
6457
6752
|
}
|
|
6458
6753
|
switch (name) {
|
|
6459
6754
|
case 'text': {
|
|
6460
|
-
setContent$1(el, datum, false);
|
|
6755
|
+
setContent$1(el, datum, false, xssSanitize);
|
|
6461
6756
|
return;
|
|
6462
6757
|
}
|
|
6463
6758
|
case 'html': {
|
|
6464
|
-
|
|
6759
|
+
// Sanitize HTML if XSS protection is enabled
|
|
6760
|
+
if (xssSanitize && typeof datum === 'string') {
|
|
6761
|
+
setContent$1(el, sanitizeHtml$1(datum), true, xssSanitize);
|
|
6762
|
+
}
|
|
6763
|
+
else {
|
|
6764
|
+
setContent$1(el, datum, true, xssSanitize);
|
|
6765
|
+
}
|
|
6465
6766
|
return;
|
|
6466
6767
|
}
|
|
6467
6768
|
case 'node': {
|
|
6468
6769
|
if (typeof datum !== 'string') {
|
|
6469
6770
|
return;
|
|
6470
6771
|
}
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6772
|
+
replaceNode$1(el, datum, prefix, xssSanitize);
|
|
6773
|
+
return;
|
|
6774
|
+
}
|
|
6775
|
+
}
|
|
6776
|
+
// If XSS protection is enabled
|
|
6777
|
+
if (xssSanitize) {
|
|
6778
|
+
// Don't set event handler attributes (starting with 'on')
|
|
6779
|
+
if (name.toLowerCase().startsWith('on')) {
|
|
6780
|
+
return;
|
|
6781
|
+
}
|
|
6782
|
+
const beforeSanitize = datum;
|
|
6783
|
+
datum = sanitizeAttributeValue$1(name, datum);
|
|
6784
|
+
// If sanitization results in null value (except when original value was null), don't change the value
|
|
6785
|
+
if (datum === null && beforeSanitize !== null) {
|
|
6483
6786
|
return;
|
|
6484
6787
|
}
|
|
6485
6788
|
}
|
|
6486
|
-
if (
|
|
6789
|
+
if (datum == null) {
|
|
6790
|
+
el.removeAttribute(name);
|
|
6791
|
+
return;
|
|
6792
|
+
}
|
|
6793
|
+
if (!name.startsWith('data-') && !propInElement$1(el, name)) {
|
|
6487
6794
|
const dataAttr = `data-${prefix}-${kebabCase$1(name)}`;
|
|
6488
6795
|
if (el.hasAttribute(dataAttr)) {
|
|
6489
6796
|
el.setAttribute(dataAttr, `${datum}`);
|
|
@@ -7055,8 +7362,9 @@ function set$4(el, prefix, name, datum) {
|
|
|
7055
7362
|
* @param el
|
|
7056
7363
|
* @param datum
|
|
7057
7364
|
* @param asHtml
|
|
7365
|
+
* @param xssSanitize
|
|
7058
7366
|
*/
|
|
7059
|
-
function setContent$1(el, datum, asHtml = true) {
|
|
7367
|
+
function setContent$1(el, datum, asHtml = true, xssSanitize = true) {
|
|
7060
7368
|
if (el instanceof HTMLInputElement ||
|
|
7061
7369
|
el instanceof HTMLSelectElement ||
|
|
7062
7370
|
el instanceof HTMLTextAreaElement ||
|
|
@@ -7074,9 +7382,18 @@ function setContent$1(el, datum, asHtml = true) {
|
|
|
7074
7382
|
return;
|
|
7075
7383
|
}
|
|
7076
7384
|
if (asHtml) {
|
|
7077
|
-
|
|
7385
|
+
// Sanitize HTML if XSS protection is enabled
|
|
7386
|
+
const htmlStr = datum == null ? '' : `${datum}`;
|
|
7387
|
+
if (xssSanitize && typeof htmlStr === 'string') {
|
|
7388
|
+
// sanitizeHtml will now replace dangerous elements instead of removing them
|
|
7389
|
+
el.innerHTML = sanitizeHtml$1(htmlStr);
|
|
7390
|
+
}
|
|
7391
|
+
else {
|
|
7392
|
+
el.innerHTML = htmlStr;
|
|
7393
|
+
}
|
|
7078
7394
|
return;
|
|
7079
7395
|
}
|
|
7396
|
+
// No need to sanitize textContent (automatically escaped)
|
|
7080
7397
|
el.textContent = datum == null ? '' : `${datum}`;
|
|
7081
7398
|
}
|
|
7082
7399
|
/**
|
|
@@ -7113,16 +7430,16 @@ function toInt$1(datum) {
|
|
|
7113
7430
|
*/
|
|
7114
7431
|
function getValues$1(el, convertType = false, attr = 'field', filter) {
|
|
7115
7432
|
const result = [];
|
|
7116
|
-
const
|
|
7117
|
-
|
|
7118
|
-
const forceArray = !!listRoot;
|
|
7119
|
-
if (rawValue == null) {
|
|
7433
|
+
const query = el.getAttribute(`data-${attr}`);
|
|
7434
|
+
if (query == null) {
|
|
7120
7435
|
throw new Error(`data-${attr} attriblute is empty.`);
|
|
7121
7436
|
}
|
|
7122
|
-
const
|
|
7123
|
-
|
|
7437
|
+
const listRoot = el.closest(`[data-${attr}-list]`);
|
|
7438
|
+
const forceArray = !!listRoot;
|
|
7439
|
+
const fields = parseFields$1(query);
|
|
7440
|
+
for (const field of fields) {
|
|
7124
7441
|
let value;
|
|
7125
|
-
const { fieldName, propName } =
|
|
7442
|
+
const { fieldName, propName } = field;
|
|
7126
7443
|
if (propName) {
|
|
7127
7444
|
switch (propName) {
|
|
7128
7445
|
case 'node': {
|
|
@@ -7137,6 +7454,12 @@ function getValues$1(el, convertType = false, attr = 'field', filter) {
|
|
|
7137
7454
|
value = el.innerHTML.trim();
|
|
7138
7455
|
break;
|
|
7139
7456
|
}
|
|
7457
|
+
case 'style': {
|
|
7458
|
+
if (el instanceof HTMLElement) {
|
|
7459
|
+
value = el.style.cssText;
|
|
7460
|
+
}
|
|
7461
|
+
break;
|
|
7462
|
+
}
|
|
7140
7463
|
default: {
|
|
7141
7464
|
if (/^style\([a-z-]+\)$/i.test(propName)) {
|
|
7142
7465
|
const css = propName.replace(/^style\(([a-z-]+)\)$/i, '$1');
|
|
@@ -7153,7 +7476,7 @@ function getValues$1(el, convertType = false, attr = 'field', filter) {
|
|
|
7153
7476
|
}
|
|
7154
7477
|
break;
|
|
7155
7478
|
}
|
|
7156
|
-
value = getAttribute$1(el,
|
|
7479
|
+
value = getAttribute$1(el, propName, attr, convertType);
|
|
7157
7480
|
}
|
|
7158
7481
|
}
|
|
7159
7482
|
}
|
|
@@ -7181,11 +7504,11 @@ function getValues$1(el, convertType = false, attr = 'field', filter) {
|
|
|
7181
7504
|
/**
|
|
7182
7505
|
*
|
|
7183
7506
|
* @param el
|
|
7184
|
-
* @param attr
|
|
7185
7507
|
* @param keyAttr
|
|
7508
|
+
* @param attr
|
|
7186
7509
|
* @param typeConvert
|
|
7187
7510
|
*/
|
|
7188
|
-
function getAttribute$1(el,
|
|
7511
|
+
function getAttribute$1(el, keyAttr, attr, typeConvert) {
|
|
7189
7512
|
switch (keyAttr) {
|
|
7190
7513
|
case 'contenteditable': {
|
|
7191
7514
|
if (el instanceof HTMLElement) {
|
|
@@ -7207,24 +7530,35 @@ function getAttribute$1(el, attr, keyAttr, typeConvert) {
|
|
|
7207
7530
|
return el.hasAttribute('download') ? el.getAttribute('download') : null;
|
|
7208
7531
|
}
|
|
7209
7532
|
case 'href': {
|
|
7210
|
-
//
|
|
7211
|
-
|
|
7533
|
+
// Example: (el as HTMLAnchorElement).href;
|
|
7534
|
+
// Expected: return defined value of plain string
|
|
7535
|
+
return el.getAttribute(keyAttr) ?? '';
|
|
7212
7536
|
}
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
value = el.getAttribute(keyAttr) || '';
|
|
7221
|
-
}
|
|
7222
|
-
if (typeConvert) {
|
|
7223
|
-
value = convert$1(value);
|
|
7224
|
-
}
|
|
7225
|
-
return value;
|
|
7537
|
+
}
|
|
7538
|
+
let value =
|
|
7539
|
+
// @ts-ignore
|
|
7540
|
+
el[keyAttr];
|
|
7541
|
+
if (value !== undefined) {
|
|
7542
|
+
if (typeConvert) {
|
|
7543
|
+
value = convert$1(value);
|
|
7226
7544
|
}
|
|
7545
|
+
return value;
|
|
7227
7546
|
}
|
|
7547
|
+
// For shorthand notation, get value from data-field-* attribute
|
|
7548
|
+
const dataAttr = ['data', attr, kebabCase$1(keyAttr)].join('-');
|
|
7549
|
+
if (el.hasAttribute(dataAttr)) {
|
|
7550
|
+
return el.getAttribute(dataAttr) ?? '';
|
|
7551
|
+
}
|
|
7552
|
+
value = el.getAttribute(keyAttr) ?? null;
|
|
7553
|
+
if ((value === '' || value == null) &&
|
|
7554
|
+
typeof keyAttr === 'string' &&
|
|
7555
|
+
keyAttr.startsWith('data-')) {
|
|
7556
|
+
return '';
|
|
7557
|
+
}
|
|
7558
|
+
if (typeConvert) {
|
|
7559
|
+
value = convert$1(value);
|
|
7560
|
+
}
|
|
7561
|
+
return value;
|
|
7228
7562
|
}
|
|
7229
7563
|
/**
|
|
7230
7564
|
*
|
|
@@ -7232,8 +7566,9 @@ function getAttribute$1(el, attr, keyAttr, typeConvert) {
|
|
|
7232
7566
|
*/
|
|
7233
7567
|
function convert$1(value) {
|
|
7234
7568
|
value = parse$1(value);
|
|
7235
|
-
|
|
7236
|
-
|
|
7569
|
+
const str = `${value}`;
|
|
7570
|
+
if (URL.canParse(str)) {
|
|
7571
|
+
const url = new URL(str, location.href);
|
|
7237
7572
|
if (url.origin === location.origin) {
|
|
7238
7573
|
return url.pathname;
|
|
7239
7574
|
}
|
|
@@ -7246,7 +7581,7 @@ function convert$1(value) {
|
|
|
7246
7581
|
*/
|
|
7247
7582
|
function parse$1(value) {
|
|
7248
7583
|
try {
|
|
7249
|
-
return JSON.parse(value);
|
|
7584
|
+
return JSON.parse(`${value}`);
|
|
7250
7585
|
}
|
|
7251
7586
|
catch {
|
|
7252
7587
|
return value;
|
|
@@ -7261,6 +7596,7 @@ function getBackgroundImagePath$1(value) {
|
|
|
7261
7596
|
return decodeURI(value.replace(/^url\(["']?([^"']+)["']?\)$/i, '$1').replace(origin, ''));
|
|
7262
7597
|
}
|
|
7263
7598
|
|
|
7599
|
+
const reverseListElementSelectors$1 = ['picture'];
|
|
7264
7600
|
/**
|
|
7265
7601
|
*
|
|
7266
7602
|
* @param el
|
|
@@ -7268,9 +7604,18 @@ function getBackgroundImagePath$1(value) {
|
|
|
7268
7604
|
* @param typeConvert
|
|
7269
7605
|
* @param filter
|
|
7270
7606
|
*/
|
|
7271
|
-
function
|
|
7272
|
-
|
|
7273
|
-
const
|
|
7607
|
+
function getComponent$1(el, attr, typeConvert, filter) {
|
|
7608
|
+
el = el.cloneNode(true);
|
|
7609
|
+
const reverseListElements = el.querySelectorAll(`:is(${reverseListElementSelectors$1.join(',')})[data-${attr}-list]`);
|
|
7610
|
+
for (const reverseListElement of reverseListElements) {
|
|
7611
|
+
const children = [];
|
|
7612
|
+
while (reverseListElement.lastElementChild) {
|
|
7613
|
+
children.push(reverseListElement.lastElementChild);
|
|
7614
|
+
reverseListElement.lastElementChild.remove();
|
|
7615
|
+
}
|
|
7616
|
+
reverseListElement.append(...children);
|
|
7617
|
+
}
|
|
7618
|
+
const filedElements = el.querySelectorAll(`[data-${attr}]`);
|
|
7274
7619
|
let values = [];
|
|
7275
7620
|
for (const _el of filedElements) {
|
|
7276
7621
|
values = [...values, ...getValues$1(_el, typeConvert, attr, filter)];
|
|
@@ -7279,59 +7624,105 @@ function get$2 (el, attr, typeConvert, filter) {
|
|
|
7279
7624
|
return result;
|
|
7280
7625
|
}
|
|
7281
7626
|
|
|
7627
|
+
/**
|
|
7628
|
+
* Combines multiple field definitions with comma separation
|
|
7629
|
+
* @param fields Array of field definitions
|
|
7630
|
+
* @returns Comma-separated field definition string
|
|
7631
|
+
*/
|
|
7632
|
+
function stringifyFields$1(fields) {
|
|
7633
|
+
return fields
|
|
7634
|
+
.map((field) => stringifyField$1(field.fieldName, field.propName))
|
|
7635
|
+
.join(', ');
|
|
7636
|
+
}
|
|
7637
|
+
/**
|
|
7638
|
+
* Generates a field definition string from field name and attribute name
|
|
7639
|
+
* @param fieldName Field name
|
|
7640
|
+
* @param propName Attribute name (optional)
|
|
7641
|
+
* @returns Field definition string
|
|
7642
|
+
*/
|
|
7643
|
+
function stringifyField$1(fieldName, propName) {
|
|
7644
|
+
if (!propName) {
|
|
7645
|
+
return fieldName;
|
|
7646
|
+
}
|
|
7647
|
+
// Use shorthand notation when fieldName and propName are the same
|
|
7648
|
+
if (fieldName === propName) {
|
|
7649
|
+
return `:${propName}`;
|
|
7650
|
+
}
|
|
7651
|
+
return `${fieldName}:${propName}`;
|
|
7652
|
+
}
|
|
7653
|
+
|
|
7282
7654
|
/**
|
|
7283
7655
|
*
|
|
7284
7656
|
* @param el
|
|
7285
7657
|
* @param data
|
|
7286
7658
|
* @param attr
|
|
7287
7659
|
* @param filter
|
|
7660
|
+
* @param xssSanitize Enable XSS protection
|
|
7288
7661
|
*/
|
|
7289
|
-
function
|
|
7662
|
+
function setComponent$1(el, data, attr, filter, xssSanitize = true) {
|
|
7290
7663
|
el = el.cloneNode(true);
|
|
7291
7664
|
for (const dataKeyName in data) {
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7665
|
+
const datum = data[dataKeyName];
|
|
7666
|
+
if (Array.isArray(datum)) {
|
|
7667
|
+
continue;
|
|
7668
|
+
}
|
|
7669
|
+
const targetList = [
|
|
7670
|
+
// Include self
|
|
7671
|
+
el,
|
|
7672
|
+
// Perform rough filtering for performance
|
|
7673
|
+
...el.querySelectorAll(`[data-${attr}*="${kebabCase$1(dataKeyName)}"]`),
|
|
7674
|
+
]
|
|
7675
|
+
// Perform more accurate filtering
|
|
7676
|
+
.filter((el) => hasField$1(el, attr, dataKeyName));
|
|
7677
|
+
for (const targetEl of targetList) {
|
|
7678
|
+
setValue$1(targetEl, dataKeyName, datum, attr, filter, xssSanitize);
|
|
7679
|
+
}
|
|
7680
|
+
}
|
|
7681
|
+
for (const listRoot of el.querySelectorAll(`[data-${attr}-list]`)) {
|
|
7682
|
+
const decendants = listRoot.querySelectorAll('*');
|
|
7683
|
+
const definedFieldsOfDecendants = new Set([...decendants].flatMap((el) => definedFields$1(el, attr)));
|
|
7684
|
+
const maxLength = maxLengthOf$1(data, [...definedFieldsOfDecendants]);
|
|
7685
|
+
const listItem = listRoot.children[0]?.cloneNode(true);
|
|
7686
|
+
if (!listItem) {
|
|
7687
|
+
continue;
|
|
7688
|
+
}
|
|
7689
|
+
while (listRoot.firstChild) {
|
|
7690
|
+
listRoot.firstChild.remove();
|
|
7691
|
+
}
|
|
7692
|
+
for (let i = 0; i < maxLength; i++) {
|
|
7693
|
+
let item = listItem.cloneNode(true);
|
|
7694
|
+
const itemData = flattenData$1(data, i);
|
|
7695
|
+
let reverse = false;
|
|
7696
|
+
switch (listRoot.localName) {
|
|
7697
|
+
case 'picture': {
|
|
7698
|
+
reverse = true;
|
|
7699
|
+
let fields = getFields$1(item, attr);
|
|
7700
|
+
if (i === 0) {
|
|
7701
|
+
// Convert first item to img element
|
|
7702
|
+
item = replaceNode$1(item, 'img', attr, xssSanitize);
|
|
7703
|
+
fields = replaceProp$1(fields, 'srcset', 'src');
|
|
7704
|
+
fields = removeProp$1(fields, 'sizes');
|
|
7705
|
+
const fieldQuery = stringifyFields$1(fields);
|
|
7706
|
+
item.setAttribute(`data-${attr}`, fieldQuery);
|
|
7322
7707
|
}
|
|
7323
7708
|
else {
|
|
7324
|
-
|
|
7325
|
-
|
|
7709
|
+
// Convert subsequent items to source elements
|
|
7710
|
+
item = replaceNode$1(item, 'source', attr, xssSanitize);
|
|
7711
|
+
fields = replaceProp$1(fields, 'src', 'srcset');
|
|
7712
|
+
fields = removeProp$1(fields, 'alt');
|
|
7713
|
+
fields = removeProp$1(fields, 'loading');
|
|
7714
|
+
const fieldQuery = stringifyFields$1(fields);
|
|
7715
|
+
item.setAttribute(`data-${attr}`, fieldQuery);
|
|
7326
7716
|
}
|
|
7717
|
+
break;
|
|
7327
7718
|
}
|
|
7328
|
-
|
|
7329
|
-
|
|
7719
|
+
}
|
|
7720
|
+
const newEl = setComponent$1(item, itemData, attr, filter, xssSanitize);
|
|
7721
|
+
if (reverse) {
|
|
7722
|
+
listRoot.prepend(newEl);
|
|
7330
7723
|
}
|
|
7331
7724
|
else {
|
|
7332
|
-
|
|
7333
|
-
setValue$1(targetEl, dataKeyName, datum, attr, filter);
|
|
7334
|
-
}
|
|
7725
|
+
listRoot.append(newEl);
|
|
7335
7726
|
}
|
|
7336
7727
|
}
|
|
7337
7728
|
}
|
|
@@ -7346,6 +7737,10 @@ let FrozenPatty$1 = class FrozenPatty {
|
|
|
7346
7737
|
*/
|
|
7347
7738
|
#filter;
|
|
7348
7739
|
#typeConvert = false;
|
|
7740
|
+
/**
|
|
7741
|
+
* Enable XSS protection
|
|
7742
|
+
*/
|
|
7743
|
+
#xssSanitize = true;
|
|
7349
7744
|
/**
|
|
7350
7745
|
*
|
|
7351
7746
|
* @param html Original HTML
|
|
@@ -7353,7 +7748,14 @@ let FrozenPatty$1 = class FrozenPatty {
|
|
|
7353
7748
|
*/
|
|
7354
7749
|
constructor(html, options) {
|
|
7355
7750
|
this.#dom = document.createElement('fp-placeholer');
|
|
7356
|
-
|
|
7751
|
+
// Sanitize initial HTML if XSS protection is enabled
|
|
7752
|
+
if (options?.xssSanitize === false) {
|
|
7753
|
+
this.#dom.innerHTML = html;
|
|
7754
|
+
this.#xssSanitize = false;
|
|
7755
|
+
}
|
|
7756
|
+
else {
|
|
7757
|
+
this.#dom.innerHTML = sanitizeHtml$1(html);
|
|
7758
|
+
}
|
|
7357
7759
|
if (options) {
|
|
7358
7760
|
if (options.attr) {
|
|
7359
7761
|
this.#attr = options.attr;
|
|
@@ -7365,7 +7767,8 @@ let FrozenPatty$1 = class FrozenPatty {
|
|
|
7365
7767
|
merge(data) {
|
|
7366
7768
|
const currentData = this.toJSON(false);
|
|
7367
7769
|
const newData = Object.assign(currentData, data);
|
|
7368
|
-
|
|
7770
|
+
// Pass XSS protection flag to set (default is true if not set)
|
|
7771
|
+
this.#dom = setComponent$1(this.#dom, newData, this.#attr, this.#filter, this.#xssSanitize);
|
|
7369
7772
|
return this;
|
|
7370
7773
|
}
|
|
7371
7774
|
toDOM() {
|
|
@@ -7376,7 +7779,7 @@ let FrozenPatty$1 = class FrozenPatty {
|
|
|
7376
7779
|
}
|
|
7377
7780
|
toJSON(filtering = true) {
|
|
7378
7781
|
const filter = filtering ? this.#filter : undefined;
|
|
7379
|
-
return
|
|
7782
|
+
return getComponent$1(this.#dom, this.#attr, this.#typeConvert, filter);
|
|
7380
7783
|
}
|
|
7381
7784
|
};
|
|
7382
7785
|
|
|
@@ -7595,7 +7998,7 @@ var style$9 = ".bgi-btn-container {\n\ttext-align: center;\n}\n\n.bgi-btn {\n\ta
|
|
|
7595
7998
|
var template$A = "<div class=\"bgi-btn-container\" data-bgi-button-kind=\"link\" data-bge=\"kind:data-bgi-button-kind\">\n\t<a class=\"bgi-btn\" href=\"\" data-bge=\"link:href, target:target\">\n\t\t<span class=\"bgi-btn__text\" data-bge=\"text\">ボタン</span>\n\t</a>\n</div>\n";
|
|
7596
7999
|
|
|
7597
8000
|
var button = createItem({
|
|
7598
|
-
version: "4.0.0-alpha.
|
|
8001
|
+
version: "4.0.0-alpha.3",
|
|
7599
8002
|
name: "button",
|
|
7600
8003
|
template: template$A,
|
|
7601
8004
|
style: style$9,
|
|
@@ -7609,7 +8012,7 @@ var style$8 = ".bgi-link__size {\n\t&::before {\n\t\tcontent: '(';\n\t}\n\n\t&::
|
|
|
7609
8012
|
var template$z = "<div class=\"bgi-download-file\">\n\t<a class=\"bgi-download-file__link\" href=\"./files/bgeditor/bg-sample.pdf\" target=\"_blank\" data-bge=\"path:href, download:download\">\n\t\t<span class=\"bgi-link__icon bgi-link__icon--before\" role=\"none\"></span>\n\t\t<span class=\"bgi-link__name\" data-bge=\"name\">サンプルダウンロードファイル</span>\n\t\t<span class=\"bgi-link__size\" data-bge=\"formated-size, size:data-size\" data-size=\"138158\">134.92kB</span>\n\t\t<span class=\"bgi-link__icon bgi-link__icon--after\" role=\"none\"></span>\n\t</a>\n</div>\n";
|
|
7610
8013
|
|
|
7611
8014
|
var downloadFile = createItem({
|
|
7612
|
-
version: "4.0.0-alpha.
|
|
8015
|
+
version: "4.0.0-alpha.3",
|
|
7613
8016
|
name: "download-file",
|
|
7614
8017
|
template: template$z,
|
|
7615
8018
|
style: style$8,
|
|
@@ -7648,7 +8051,7 @@ var style$7 = "[data-bgi='google-maps'] {\n\tdiv {\n\t\tinline-size: 100%;\n\t\t
|
|
|
7648
8051
|
var template$y = "<div data-lat=\"35.681382\" data-lng=\"139.766084\" data-zoom=\"16\" data-bge=\"lat:data-lat, lng:data-lng, zoom:data-zoom\">\n\t<img data-bge=\"img:src\" src=\"https://maps.google.com/maps/api/staticmap?center=35.681382,139.766084&zoom=16&size=640x400&markers=color:red|color:red|35.681382,139.766084&scale=2&key=%googleMapsApiKey%\" width=\"8\" height=\"5\" alt=\"Google Maps\" />\n</div>\n<a href=\"https://maps.apple.com/?q=35.681382,139.766084\" data-bge=\"url:href\" target=\"_blank\"><span>アプリで開く</span></a>\n";
|
|
7649
8052
|
|
|
7650
8053
|
var googleMaps = createItem({
|
|
7651
|
-
version: "4.0.0-alpha.
|
|
8054
|
+
version: "4.0.0-alpha.3",
|
|
7652
8055
|
name: "google-maps",
|
|
7653
8056
|
template: template$y,
|
|
7654
8057
|
style: style$7,
|
|
@@ -7783,7 +8186,7 @@ var style$6 = "[data-bgi='hr'] {\n\t--border-color: #000;\n\t--border-width: 1px
|
|
|
7783
8186
|
var template$x = "<div class=\"bgi-hr-container\" data-bgi-hr-kind=\"primary\" data-bge=\"kind:data-bgi-hr-kind\">\n\t<hr class=\"bgi-hr\" />\n</div>\n";
|
|
7784
8187
|
|
|
7785
8188
|
var hr$1 = createItem({
|
|
7786
|
-
version: "4.0.0-alpha.
|
|
8189
|
+
version: "4.0.0-alpha.3",
|
|
7787
8190
|
name: "hr",
|
|
7788
8191
|
template: template$x,
|
|
7789
8192
|
style: style$6,
|
|
@@ -7803,22 +8206,22 @@ var hr$1 = createItem({
|
|
|
7803
8206
|
}
|
|
7804
8207
|
});
|
|
7805
8208
|
|
|
7806
|
-
var editor$5 = "<div data-bge-dialog=\"2col\">\n\t<div data-bge-dialog-ui=\"sticky\">\n\t\t<
|
|
8209
|
+
var editor$5 = "<div data-bge-dialog=\"2col\">\n\t<div data-bge-dialog-ui=\"sticky\">\n\t\t<div>\n\t\t\t<div data-bge-editor-ui=\"tabs\" data-bge-editor-ui-for=\"bgi-image__tabs-content\"></div>\n\n\t\t\t<div id=\"bgi-image__tabs-content\" role=\"tabpanel\" aria-label=\"画像\">\n\t\t\t\t<div data-bge-editor-ui=\"preview\"></div>\n\t\t\t\t<input type=\"hidden\" name=\"bge-path[]\" />\n\t\t\t\t<input type=\"hidden\" name=\"bge-alt[]\" />\n\t\t\t\t<input type=\"hidden\" name=\"bge-width[]\" />\n\t\t\t\t<input type=\"hidden\" name=\"bge-height[]\" />\n\t\t\t\t<input type=\"hidden\" name=\"bge-media[]\" />\n\n\t\t\t\t<input type=\"hidden\" name=\"bge-file-size\" />\n\t\t\t\t<div>\n\t\t\t\t\t<label>\n\t\t\t\t\t\t<span>メディアクエリー</span>\n\t\t\t\t\t\t<input type=\"text\" name=\"bge-media-input\" />\n\t\t\t\t\t</label>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div>\n\t\t\t<fieldset>\n\t\t\t\t<legend>画像のサイズ</legend>\n\t\t\t\t<div role=\"radiogroup\" aria-labelledby=\"bgi-image__radio-group1\">\n\t\t\t\t\t<div id=\"bgi-image__radio-group1\">基準</div>\n\t\t\t\t\t<label><input type=\"radio\" name=\"bge-scale-type\" value=\"container\" /><span>基準</span></label>\n\t\t\t\t\t<label><input type=\"radio\" name=\"bge-scale-type\" value=\"original\" checked />画像基準</label>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<span>\n\t\t\t\t\t\t<label for=\"bgi-image__range\">幅</label>\n\t\t\t\t\t\t<output name=\"bge-css-width\"></output>\n\t\t\t\t\t</span>\n\t\t\t\t\t<input id=\"bgi-image__range\" type=\"range\" name=\"bge-scale\" min=\"1\" max=\"100\" step=\"1\" value=\"100\" />\n\t\t\t\t</div>\n\t\t\t\t<hr />\n\t\t\t\t<div role=\"radiogroup\" aria-labelledby=\"bgi-image__radio-group2\">\n\t\t\t\t\t<div id=\"bgi-image__radio-group2\">縦横比</div>\n\t\t\t\t\t<label><input type=\"radio\" name=\"bge-aspect-ratio\" value=\"unset\" checked />オリジナル</label>\n\t\t\t\t\t<label><input type=\"radio\" name=\"bge-aspect-ratio\" value=\"1/1\" />1 : 1</label>\n\t\t\t\t\t<label><input type=\"radio\" name=\"bge-aspect-ratio\" value=\"4/3\" />4 : 3</label>\n\t\t\t\t\t<label><input type=\"radio\" name=\"bge-aspect-ratio\" value=\"16/9\" />16 : 9</label>\n\t\t\t\t</div>\n\t\t\t</fieldset>\n\t\t\t<label>\n\t\t\t\t<span>画像の代替テキスト(alt)</span>\n\t\t\t\t<input type=\"text\" name=\"bge-alt\" />\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\t<span>キャプション</span>\n\t\t\t\t<input type=\"text\" name=\"bge-caption\" />\n\t\t\t</label>\n\t\t\t<fieldset>\n\t\t\t\t<legend>リンク</legend>\n\t\t\t\t<label><input type=\"checkbox\" name=\"bge-popup\" />ポップアップで画像を開く</label>\n\t\t\t\t<label>\n\t\t\t\t\t<span>リンク先URL</span>\n\t\t\t\t\t<input type=\"url\" name=\"bge-href\" />\n\t\t\t\t</label>\n\t\t\t\t<label><input type=\"checkbox\" name=\"bge-target-blank\" />別タブで開く</label>\n\t\t\t</fieldset>\n\t\t\t<label><input type=\"checkbox\" name=\"bge-lazy\" checked aria-describedby=\"bge-lazy-desc\" />遅延読み込み</label>\n\t\t\t<small id=\"bge-lazy-desc\">画像がブラウザの表示エリアに現れるまでファイルを読み込みません。</small>\n\t\t</div>\n\t</div>\n\t<div>\n\t\t<div data-bge-editor-ui=\"imageUploader\"></div>\n\t\t<div data-bge-editor-ui=\"imageList\"></div>\n\t</div>\n</div>\n";
|
|
7807
8210
|
|
|
7808
8211
|
var style$5 = "[data-bgi='image'] {\n\tinline-size: 100%;\n\n\tfigure {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tinline-size: 100%;\n\t\tpadding: 0;\n\t\tmargin: 0;\n\n\t\t> :is(div, a, button) {\n\t\t\tdisplay: block;\n\t\t\tpadding: 0;\n\t\t\tbackground: transparent;\n\t\t\tborder: none;\n\t\t}\n\t}\n\n\timg {\n\t\tdisplay: block;\n\t\tinline-size: var(--css-width, auto);\n\t\tmax-inline-size: 100%;\n\t\tblock-size: auto;\n\t\taspect-ratio: var(--aspect-ratio, unset);\n\t\tobject-fit: var(--object-fit, unset);\n\t}\n\n\tfigcaption {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\tinline-size: 100%;\n\n\t\t&:empty {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n}\n";
|
|
7809
8212
|
|
|
7810
|
-
var template$w = "<div data-bge=\":style, :scale, :scale-type, :aspect-ratio\" data-bge-scale=\"100\" data-bge-scale-type=\"container\" data-bge-aspect-ratio=\"unset\" style=\"--css-width: 100cqi; --object-fit: cover; --aspect-ratio: unset\">\n\t<figure>\n\t\t<div data-bge=\":node, :href, :target, :command\">\n\t\t\t<img src=\"%sampleImagePath%\" alt=\"サンプル画像\" data-bge=\"path:src, :
|
|
8213
|
+
var template$w = "<div data-bge=\":style, :scale, :scale-type, :aspect-ratio\" data-bge-scale=\"100\" data-bge-scale-type=\"container\" data-bge-aspect-ratio=\"unset\" style=\"--css-width: 100cqi; --object-fit: cover; --aspect-ratio: unset\">\n\t<figure>\n\t\t<div data-bge=\":node, :href, :target, :command\">\n\t\t\t<picture data-bge-list>\n\t\t\t\t<img src=\"%sampleImagePath%\" alt=\"サンプル画像\" data-bge=\"path:src, :alt, :width, :height, :loading, :media\" width=\"400\" height=\"300\" loading=\"lazy\" />\n\t\t\t</picture>\n\t\t</div>\n\t\t<figcaption data-bge=\"caption\"></figcaption>\n\t</figure>\n</div>\n";
|
|
7811
8214
|
|
|
7812
8215
|
const ORIGIN = "__org";
|
|
7813
8216
|
var image = createItem({
|
|
7814
|
-
version: "4.0.0-alpha.
|
|
8217
|
+
version: "4.0.0-alpha.3",
|
|
7815
8218
|
name: "image",
|
|
7816
8219
|
template: template$w,
|
|
7817
8220
|
style: style$5,
|
|
7818
8221
|
editor: editor$5,
|
|
7819
8222
|
editorOptions: {
|
|
7820
8223
|
beforeOpen(data) {
|
|
7821
|
-
const path = data.path.replace(ORIGIN, "");
|
|
8224
|
+
const path = data.path.map((p) => p.replace(ORIGIN, ""));
|
|
7822
8225
|
const lazy = data.loading === "lazy";
|
|
7823
8226
|
const popup = data.node === "button" && data.command === "show-modal";
|
|
7824
8227
|
const targetBlank = data.node === "a" && data.target === "_blank";
|
|
@@ -7830,48 +8233,71 @@ var image = createItem({
|
|
|
7830
8233
|
targetBlank
|
|
7831
8234
|
};
|
|
7832
8235
|
},
|
|
7833
|
-
open(
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
8236
|
+
open(_, editor2) {
|
|
8237
|
+
let currentIndex = 0;
|
|
8238
|
+
fileSelect();
|
|
8239
|
+
function fileSelect() {
|
|
8240
|
+
editor2.engine.componentObserver.notify("file-select", {
|
|
8241
|
+
path: editor2.get("$path")[currentIndex],
|
|
8242
|
+
fileSize: Number.parseFloat(editor2.get("$fileSize") ?? "0"),
|
|
8243
|
+
isEmpty: editor2.get("$path")[currentIndex] === "",
|
|
8244
|
+
isMounted: false
|
|
8245
|
+
});
|
|
8246
|
+
}
|
|
7840
8247
|
editor2.engine.componentObserver.on("file-select", ({ path, isEmpty }) => {
|
|
7841
8248
|
if (isEmpty) {
|
|
7842
8249
|
return;
|
|
7843
8250
|
}
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
);
|
|
8251
|
+
void _updateImage(path);
|
|
8252
|
+
});
|
|
8253
|
+
async function _updateImage(path) {
|
|
8254
|
+
const $src = await loadImage(path);
|
|
8255
|
+
updateImage($src);
|
|
8256
|
+
}
|
|
8257
|
+
function updateImage($src) {
|
|
8258
|
+
if (!$src) {
|
|
8259
|
+
console.error("\u753B\u50CF\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
8260
|
+
return;
|
|
8261
|
+
}
|
|
8262
|
+
const path = [...editor2.get("$path")];
|
|
8263
|
+
path[currentIndex] = $src.src;
|
|
8264
|
+
editor2.update("$path", path);
|
|
8265
|
+
const width = [...editor2.get("$width")];
|
|
8266
|
+
width[currentIndex] = $src.width;
|
|
8267
|
+
editor2.update("$width", width);
|
|
8268
|
+
const height = [...editor2.get("$height")];
|
|
8269
|
+
height[currentIndex] = $src.height;
|
|
8270
|
+
editor2.update("$height", height);
|
|
8271
|
+
const media = [...editor2.get("$media")];
|
|
8272
|
+
media[currentIndex] = editor2.get("$mediaInput");
|
|
8273
|
+
editor2.update("$media", media);
|
|
8274
|
+
updateCSSWidth();
|
|
8275
|
+
}
|
|
8276
|
+
editor2.engine.componentObserver.on("select-tab-in-item-editor", ({ index }) => {
|
|
8277
|
+
currentIndex = index;
|
|
8278
|
+
fileSelect();
|
|
8279
|
+
void _updateImage(editor2.get("$path")[currentIndex]);
|
|
8280
|
+
const media = editor2.get("$media")[currentIndex];
|
|
8281
|
+
editor2.disable("$mediaInput", currentIndex === 0);
|
|
8282
|
+
editor2.update("$mediaInput", media);
|
|
7865
8283
|
});
|
|
7866
8284
|
editor2.onChange("$scale", updateCSSWidth);
|
|
7867
8285
|
editor2.onChange("$scaleType", updateCSSWidth);
|
|
8286
|
+
editor2.onChange("$mediaInput", (value) => {
|
|
8287
|
+
const media = [...editor2.get("$media")];
|
|
8288
|
+
media[currentIndex] = value;
|
|
8289
|
+
editor2.update("$media", media);
|
|
8290
|
+
});
|
|
7868
8291
|
function updateCSSWidth() {
|
|
7869
8292
|
const scale = editor2.get("$scale");
|
|
7870
8293
|
const width = editor2.get("$width");
|
|
7871
8294
|
const scaleType = editor2.get("$scaleType");
|
|
7872
8295
|
editor2.update(
|
|
7873
8296
|
"$cssWidth",
|
|
7874
|
-
scaleType === "container" ? `${scale}cqi` :
|
|
8297
|
+
scaleType === "container" ? `${scale}cqi` : (
|
|
8298
|
+
// TODO: 複数画像の場合は、最初の画像の幅を使用するか、それともすべての画像の幅を使用するか検討
|
|
8299
|
+
`${Math.round(width[0] * scale / 100)}px`
|
|
8300
|
+
)
|
|
7875
8301
|
);
|
|
7876
8302
|
}
|
|
7877
8303
|
editor2.onChange("$popup", (disable) => {
|
|
@@ -7929,20 +8355,6 @@ async function loadImage(src) {
|
|
|
7929
8355
|
}, 3e4);
|
|
7930
8356
|
});
|
|
7931
8357
|
}
|
|
7932
|
-
function originImage(src) {
|
|
7933
|
-
const filePath = src.match(/^(.*)(\.(?:jpe?g|gif|png|webp))$/i);
|
|
7934
|
-
if (filePath) {
|
|
7935
|
-
const [, name, ext] = filePath;
|
|
7936
|
-
return {
|
|
7937
|
-
src,
|
|
7938
|
-
origin: `${name}${ORIGIN}${ext}`
|
|
7939
|
-
};
|
|
7940
|
-
}
|
|
7941
|
-
return {
|
|
7942
|
-
src,
|
|
7943
|
-
origin: null
|
|
7944
|
-
};
|
|
7945
|
-
}
|
|
7946
8358
|
|
|
7947
8359
|
var editor$4 = "<div data-bge-dialog=\"wide\">\n\t<div>\n\t\t<label>\n\t\t\t<span>表見出し</span>\n\t\t\t<input type=\"text\" name=\"bge-caption\" />\n\t\t</label>\n\t</div>\n\n\t<div data-bge-editor-ui=\"tableEditor\"></div>\n\t<input type=\"hidden\" name=\"bge\" />\n</div>\n";
|
|
7948
8360
|
|
|
@@ -7951,7 +8363,7 @@ var style$4 = ".bge-type-table {\n\tmargin: 0;\n\n\tth {\n\t\tinline-size: calc(
|
|
|
7951
8363
|
var template$v = "<table>\n\t<caption data-bge=\"caption\">\n\t\tキャプションを入力してください\n\t</caption>\n\t<tbody data-bge-list>\n\t\t<tr>\n\t\t\t<th data-bge=\"th\">表組の見出し</th>\n\t\t\t<td data-bge=\"td\">表組の内容を入力してください</td>\n\t\t</tr>\n\t</tbody>\n</table>\n";
|
|
7952
8364
|
|
|
7953
8365
|
var table = createItem({
|
|
7954
|
-
version: "4.0.0-alpha.
|
|
8366
|
+
version: "4.0.0-alpha.3",
|
|
7955
8367
|
name: "table",
|
|
7956
8368
|
template: template$v,
|
|
7957
8369
|
style: style$4,
|
|
@@ -7979,7 +8391,7 @@ var style$3 = ".bge-title-h2 {\n\tmargin-block-end: 0;\n}\n";
|
|
|
7979
8391
|
var template$u = "<h2 class=\"bge-title-h2\" data-bge=\"title-h2\">見出しを入力してください</h2>\n";
|
|
7980
8392
|
|
|
7981
8393
|
var titleH2 = createItem({
|
|
7982
|
-
version: "4.0.0-alpha.
|
|
8394
|
+
version: "4.0.0-alpha.3",
|
|
7983
8395
|
name: "title-h2",
|
|
7984
8396
|
template: template$u,
|
|
7985
8397
|
style: style$3,
|
|
@@ -7993,7 +8405,7 @@ var style$2 = ".bge-title-h3 {\n\tmargin-block-end: 0;\n}\n";
|
|
|
7993
8405
|
var template$t = "<h2 class=\"bge-title-h3\" data-bge=\"title-h3\">見出しを入力してください</h2>\n";
|
|
7994
8406
|
|
|
7995
8407
|
var titleH3 = createItem({
|
|
7996
|
-
version: "4.0.0-alpha.
|
|
8408
|
+
version: "4.0.0-alpha.3",
|
|
7997
8409
|
name: "title-h3",
|
|
7998
8410
|
template: template$t,
|
|
7999
8411
|
style: style$2,
|
|
@@ -8007,7 +8419,7 @@ var style$1 = "/* No Styling */\n";
|
|
|
8007
8419
|
var template$s = "<div class=\"bge-wysiwyg\" data-bge=\"wysiwyg\"><p>本文を入力してください</p></div>\n";
|
|
8008
8420
|
|
|
8009
8421
|
var wysiwyg = createItem({
|
|
8010
|
-
version: "4.0.0-alpha.
|
|
8422
|
+
version: "4.0.0-alpha.3",
|
|
8011
8423
|
name: "wysiwyg",
|
|
8012
8424
|
template: template$s,
|
|
8013
8425
|
style: style$1,
|
|
@@ -8058,7 +8470,7 @@ var template$r = "<div data-id=\"3KtWfp0UopM\" data-title=\"YouTube動画\" data
|
|
|
8058
8470
|
|
|
8059
8471
|
const FALLBACK_TITLE = "YouTube\u52D5\u753B";
|
|
8060
8472
|
var youtube = createItem({
|
|
8061
|
-
version: "4.0.0-alpha.
|
|
8473
|
+
version: "4.0.0-alpha.3",
|
|
8062
8474
|
name: "youtube",
|
|
8063
8475
|
template: template$r,
|
|
8064
8476
|
style,
|
|
@@ -8120,7 +8532,8 @@ function importItems(template) {
|
|
|
8120
8532
|
try {
|
|
8121
8533
|
const data = attr ? JSON.parse(`${attr}`) : {};
|
|
8122
8534
|
html = dataToHtml$1(typedItem.template, data);
|
|
8123
|
-
} catch {
|
|
8535
|
+
} catch (error) {
|
|
8536
|
+
console.error(error);
|
|
8124
8537
|
throw new Error(`${typedItem.name}\u306E\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002`);
|
|
8125
8538
|
}
|
|
8126
8539
|
return `<div data-bgi="${typedItem.name}" data-bgi-ver="${typedItem.version}">${html}</div>`;
|
|
@@ -8211,7 +8624,7 @@ const blockTemplate$j = {
|
|
|
8211
8624
|
|
|
8212
8625
|
var icon$i = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"17.85mm\" height=\"13.87mm\" viewBox=\"0 0 50.59 39.31\"><defs><clipPath id=\"a14548ce-d842-4fd8-917c-74fc065283e0\"><rect width=\"50.59\" height=\"39.31\" fill=\"none\"/></clipPath><clipPath id=\"a760b4d9-d8b5-4ed5-a648-35d410384b4b\"><rect width=\"50.59\" height=\"37.5\" rx=\"5.06\" fill=\"none\"/></clipPath><linearGradient id=\"f1b0e6a1-76a5-46d8-9e26-0d5144fc95c2\" x1=\"187.4\" y1=\"214.88\" x2=\"188.39\" y2=\"214.88\" gradientTransform=\"matrix(0, -72.25, -72.25, 0, 15550.6, 13581.17)\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\" stop-color=\"#d9e7a4\"/><stop offset=\"1\" stop-color=\"#b2d57b\"/></linearGradient></defs><title>image1</title><g id=\"f1bc02b5-2ece-4cc1-abc8-0695f8a7f32b\" data-name=\"レイヤー 2\"><g id=\"ee57bbe4-f1e8-4009-96f2-c3c0f25e8376\" data-name=\"レイヤー1\"><g clip-path=\"url(#a14548ce-d842-4fd8-917c-74fc065283e0)\"><rect y=\"1.81\" width=\"50.59\" height=\"37.5\" rx=\"5.06\" fill=\"#b7c678\"/></g><g clip-path=\"url(#a760b4d9-d8b5-4ed5-a648-35d410384b4b)\"><rect width=\"50.59\" height=\"37.5\" fill=\"url(#f1b0e6a1-76a5-46d8-9e26-0d5144fc95c2)\"/></g><g clip-path=\"url(#a14548ce-d842-4fd8-917c-74fc065283e0)\"><rect x=\"9.75\" y=\"12.22\" width=\"31.09\" height=\"14.41\" fill=\"#7aaf39\"/><polygon points=\"40.84 26.63 9.75 26.63 40.84 12.22 40.84 26.63\" fill=\"#649432\"/></g></g></g></svg>";
|
|
8213
8626
|
|
|
8214
|
-
var template$i = "<div data-bge-container=\"grid\">\n\t<div data-bge-group>\n\t\t<div data-bge-item><!-- image --></div>\n\t</div>\n
|
|
8627
|
+
var template$i = "<div data-bge-container=\"grid:1\">\n\t<div data-bge-group>\n\t\t<div data-bge-item><!-- image --></div>\n\t</div>\n</div>\n";
|
|
8215
8628
|
|
|
8216
8629
|
const blockTemplate$i = {
|
|
8217
8630
|
name: "image",
|
|
@@ -11012,14 +11425,14 @@ _Lexer.lex;
|
|
|
11012
11425
|
* Set up window for Node.js
|
|
11013
11426
|
*/
|
|
11014
11427
|
|
|
11015
|
-
var root$
|
|
11428
|
+
var root$c = (typeof window !== 'undefined' ? window : {});
|
|
11016
11429
|
|
|
11017
11430
|
/*
|
|
11018
11431
|
* Parsing HTML strings
|
|
11019
11432
|
*/
|
|
11020
11433
|
|
|
11021
11434
|
function canParseHTMLNatively () {
|
|
11022
|
-
var Parser = root$
|
|
11435
|
+
var Parser = root$c.DOMParser;
|
|
11023
11436
|
var canParse = false;
|
|
11024
11437
|
|
|
11025
11438
|
// Adapted from https://gist.github.com/1129031
|
|
@@ -11065,12 +11478,12 @@ function shouldUseActiveX () {
|
|
|
11065
11478
|
try {
|
|
11066
11479
|
document.implementation.createHTMLDocument('').open();
|
|
11067
11480
|
} catch (e) {
|
|
11068
|
-
if (root$
|
|
11481
|
+
if (root$c.ActiveXObject) useActiveX = true;
|
|
11069
11482
|
}
|
|
11070
11483
|
return useActiveX
|
|
11071
11484
|
}
|
|
11072
11485
|
|
|
11073
|
-
canParseHTMLNatively() ? root$
|
|
11486
|
+
canParseHTMLNatively() ? root$c.DOMParser : createHTMLParser();
|
|
11074
11487
|
|
|
11075
11488
|
function getDefaultExportFromCjs (x) {
|
|
11076
11489
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
@@ -14642,6 +15055,20 @@ function createBgeEvent(type, eventData) {
|
|
|
14642
15055
|
return new CustomEvent(type, { detail: eventData });
|
|
14643
15056
|
}
|
|
14644
15057
|
|
|
15058
|
+
/**
|
|
15059
|
+
* List of dangerous HTML elements to block for XSS protection
|
|
15060
|
+
*/
|
|
15061
|
+
const DANGEROUS_ELEMENTS = [
|
|
15062
|
+
'script',
|
|
15063
|
+
'style',
|
|
15064
|
+
'template',
|
|
15065
|
+
'object',
|
|
15066
|
+
'embed',
|
|
15067
|
+
'iframe',
|
|
15068
|
+
'frame',
|
|
15069
|
+
'frameset',
|
|
15070
|
+
'applet',
|
|
15071
|
+
];
|
|
14645
15072
|
/**
|
|
14646
15073
|
*
|
|
14647
15074
|
* @param kvs
|
|
@@ -14665,31 +15092,302 @@ function arrayToHash(kvs) {
|
|
|
14665
15092
|
}
|
|
14666
15093
|
return result;
|
|
14667
15094
|
}
|
|
15095
|
+
const kebabCaseCache = new Map();
|
|
14668
15096
|
/**
|
|
14669
15097
|
*
|
|
14670
15098
|
* @param str
|
|
14671
15099
|
*/
|
|
14672
|
-
function kebabCase(str) {
|
|
14673
|
-
|
|
15100
|
+
function kebabCase(str) {
|
|
15101
|
+
if (kebabCaseCache.has(str)) {
|
|
15102
|
+
return kebabCaseCache.get(str);
|
|
15103
|
+
}
|
|
15104
|
+
const result = str.replaceAll(/([A-Z])/g, '-$1').toLowerCase();
|
|
15105
|
+
kebabCaseCache.set(str, result);
|
|
15106
|
+
return result;
|
|
15107
|
+
}
|
|
15108
|
+
const camelCaseCache = new Map();
|
|
15109
|
+
/**
|
|
15110
|
+
*
|
|
15111
|
+
* @param str
|
|
15112
|
+
*/
|
|
15113
|
+
function camelCase(str) {
|
|
15114
|
+
if (camelCaseCache.has(str)) {
|
|
15115
|
+
return camelCaseCache.get(str);
|
|
15116
|
+
}
|
|
15117
|
+
const result = str.replaceAll(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
15118
|
+
camelCaseCache.set(str, result);
|
|
15119
|
+
return result;
|
|
15120
|
+
}
|
|
15121
|
+
/**
|
|
15122
|
+
*
|
|
15123
|
+
* @param el
|
|
15124
|
+
* @param nodeName
|
|
15125
|
+
* @param attr
|
|
15126
|
+
* @param xssSanitize
|
|
15127
|
+
*/
|
|
15128
|
+
function replaceNode(el, nodeName, attr, xssSanitize = true) {
|
|
15129
|
+
nodeName = nodeName.toLowerCase();
|
|
15130
|
+
const currentName = el.localName ?? el.nodeName.toLowerCase();
|
|
15131
|
+
if (currentName === nodeName) {
|
|
15132
|
+
return el;
|
|
15133
|
+
}
|
|
15134
|
+
// Check element name if XSS protection is enabled
|
|
15135
|
+
if (xssSanitize && // Disallow dangerous elements
|
|
15136
|
+
DANGEROUS_ELEMENTS.includes(nodeName)) {
|
|
15137
|
+
return el;
|
|
15138
|
+
}
|
|
15139
|
+
const node = (el.ownerDocument ?? document).createElement(nodeName);
|
|
15140
|
+
for (const child of el.childNodes) {
|
|
15141
|
+
node.append(child.cloneNode(true));
|
|
15142
|
+
}
|
|
15143
|
+
const fields = getFields(el, attr);
|
|
15144
|
+
const attrs = new Set(fields.map((field) => field.propName));
|
|
15145
|
+
for (const { name, value } of el.attributes) {
|
|
15146
|
+
if (attrs.has(name)) {
|
|
15147
|
+
continue;
|
|
15148
|
+
}
|
|
15149
|
+
// Check attribute value if XSS protection is enabled
|
|
15150
|
+
if (xssSanitize) {
|
|
15151
|
+
const sanitizedValue = sanitizeAttributeValue(name, value);
|
|
15152
|
+
if (sanitizedValue !== null) {
|
|
15153
|
+
node.setAttribute(name, sanitizedValue);
|
|
15154
|
+
}
|
|
15155
|
+
continue;
|
|
15156
|
+
}
|
|
15157
|
+
node.setAttribute(name, value);
|
|
15158
|
+
}
|
|
15159
|
+
el.replaceWith(node);
|
|
15160
|
+
return node;
|
|
15161
|
+
}
|
|
15162
|
+
/**
|
|
15163
|
+
* Removes dangerous script elements from HTML string
|
|
15164
|
+
* @param html HTML string
|
|
15165
|
+
* @returns Sanitized HTML
|
|
15166
|
+
*/
|
|
15167
|
+
function sanitizeHtml(html) {
|
|
15168
|
+
if (typeof html !== 'string') {
|
|
15169
|
+
return '';
|
|
15170
|
+
}
|
|
15171
|
+
// Simple approach to handle script tags content
|
|
15172
|
+
// First remove script tags but keep their content
|
|
15173
|
+
let sanitized = html;
|
|
15174
|
+
// For each dangerous element, replace tag but keep content using regex
|
|
15175
|
+
// Example: <script>alert("XSS")</script> -> alert("XSS")
|
|
15176
|
+
for (const tagName of DANGEROUS_ELEMENTS) {
|
|
15177
|
+
const regex = new RegExp(`<${tagName}[^>]*>(.*?)<\\/${tagName}>`, 'gis');
|
|
15178
|
+
sanitized = sanitized.replace(regex, '$1');
|
|
15179
|
+
}
|
|
15180
|
+
// Parse HTML safely using DOM parser for remaining sanitization
|
|
15181
|
+
const doc = new DOMParser().parseFromString(sanitized, 'text/html');
|
|
15182
|
+
const body = doc.body;
|
|
15183
|
+
// Remove event handler attributes from all elements
|
|
15184
|
+
sanitizeElementAndChildren(body);
|
|
15185
|
+
return body.innerHTML;
|
|
15186
|
+
}
|
|
15187
|
+
/**
|
|
15188
|
+
* Sanitizes an element and all its child elements
|
|
15189
|
+
* @param element Target element
|
|
15190
|
+
*/
|
|
15191
|
+
function sanitizeElementAndChildren(element) {
|
|
15192
|
+
// Remove dangerous attributes from current element
|
|
15193
|
+
sanitizeAttributes(element);
|
|
15194
|
+
// Process child elements recursively
|
|
15195
|
+
const children = element.children;
|
|
15196
|
+
for (const child of children) {
|
|
15197
|
+
sanitizeElementAndChildren(child);
|
|
15198
|
+
}
|
|
15199
|
+
}
|
|
15200
|
+
/**
|
|
15201
|
+
* Sanitizes attribute value
|
|
15202
|
+
* @param name Attribute name
|
|
15203
|
+
* @param value Attribute value
|
|
15204
|
+
* @returns Safe attribute value, or null if dangerous
|
|
15205
|
+
*/
|
|
15206
|
+
function sanitizeAttributeValue(name, value) {
|
|
15207
|
+
if (typeof value !== 'string') {
|
|
15208
|
+
return value;
|
|
15209
|
+
}
|
|
15210
|
+
name = name.toLowerCase();
|
|
15211
|
+
// Disallow event handler attributes
|
|
15212
|
+
if (name.startsWith('on')) {
|
|
15213
|
+
return null;
|
|
15214
|
+
}
|
|
15215
|
+
// Check for dangerous protocol in link attributes
|
|
15216
|
+
if (name === 'href' ||
|
|
15217
|
+
name === 'src' ||
|
|
15218
|
+
name === 'action' ||
|
|
15219
|
+
name === 'formaction' ||
|
|
15220
|
+
name === 'xlink:href') {
|
|
15221
|
+
const trimmedValue = value.trim().toLowerCase();
|
|
15222
|
+
if (trimmedValue.startsWith('javascript:') ||
|
|
15223
|
+
trimmedValue.startsWith('data:') ||
|
|
15224
|
+
trimmedValue.startsWith('vbscript:')) {
|
|
15225
|
+
return null;
|
|
15226
|
+
}
|
|
15227
|
+
}
|
|
15228
|
+
// Other dangerous attributes
|
|
15229
|
+
if (['manifest'].includes(name)) {
|
|
15230
|
+
return null;
|
|
15231
|
+
}
|
|
15232
|
+
return value;
|
|
15233
|
+
}
|
|
15234
|
+
/**
|
|
15235
|
+
* Removes dangerous attributes from an element
|
|
15236
|
+
* @param element Target element
|
|
15237
|
+
*/
|
|
15238
|
+
function sanitizeAttributes(element) {
|
|
15239
|
+
// Collect list of dangerous attributes
|
|
15240
|
+
const dangerousAttrs = [...element.attributes]
|
|
15241
|
+
.filter((attr) => sanitizeAttributeValue(attr.name, attr.value) === null)
|
|
15242
|
+
.map((attr) => attr.name);
|
|
15243
|
+
// Remove dangerous attributes
|
|
15244
|
+
for (const attrName of dangerousAttrs) {
|
|
15245
|
+
element.removeAttribute(attrName);
|
|
15246
|
+
}
|
|
15247
|
+
}
|
|
15248
|
+
/**
|
|
15249
|
+
*
|
|
15250
|
+
* @param data
|
|
15251
|
+
* @param definedFields
|
|
15252
|
+
*/
|
|
15253
|
+
function maxLengthOf(data, definedFields) {
|
|
15254
|
+
let maxLength = 0;
|
|
15255
|
+
for (const key in data) {
|
|
15256
|
+
if (definedFields.includes(key) && Array.isArray(data[key])) {
|
|
15257
|
+
maxLength = Math.max(maxLength, data[key].length);
|
|
15258
|
+
}
|
|
15259
|
+
}
|
|
15260
|
+
return maxLength;
|
|
15261
|
+
}
|
|
15262
|
+
/**
|
|
15263
|
+
*
|
|
15264
|
+
* @param el
|
|
15265
|
+
* @param attr
|
|
15266
|
+
*/
|
|
15267
|
+
function definedFields(el, attr) {
|
|
15268
|
+
const fieldDefinitions = getFields(el, attr);
|
|
15269
|
+
return fieldDefinitions.map((field) => field.fieldName);
|
|
15270
|
+
}
|
|
15271
|
+
/**
|
|
15272
|
+
*
|
|
15273
|
+
* @param el
|
|
15274
|
+
* @param attr
|
|
15275
|
+
*/
|
|
15276
|
+
function getFields(el, attr) {
|
|
15277
|
+
const fields = el.getAttribute(`data-${attr}`);
|
|
15278
|
+
if (!fields) {
|
|
15279
|
+
return [];
|
|
15280
|
+
}
|
|
15281
|
+
return parseFields(fields);
|
|
15282
|
+
}
|
|
15283
|
+
/**
|
|
15284
|
+
*
|
|
15285
|
+
* @param el
|
|
15286
|
+
* @param attr
|
|
15287
|
+
* @param dataKeyName
|
|
15288
|
+
*/
|
|
15289
|
+
function hasField(el, attr, dataKeyName) {
|
|
15290
|
+
const fieldDefinitions = getFields(el, attr);
|
|
15291
|
+
return fieldDefinitions.some((field) => field.fieldName === dataKeyName);
|
|
15292
|
+
}
|
|
15293
|
+
/**
|
|
15294
|
+
*
|
|
15295
|
+
* @param fields
|
|
15296
|
+
* @param oldPropName
|
|
15297
|
+
* @param newPropName
|
|
15298
|
+
*/
|
|
15299
|
+
function replaceProp(fields, oldPropName, newPropName) {
|
|
15300
|
+
return fields.map((field) => {
|
|
15301
|
+
if (field.propName === oldPropName) {
|
|
15302
|
+
return {
|
|
15303
|
+
...field,
|
|
15304
|
+
propName: newPropName,
|
|
15305
|
+
};
|
|
15306
|
+
}
|
|
15307
|
+
return field;
|
|
15308
|
+
});
|
|
15309
|
+
}
|
|
15310
|
+
/**
|
|
15311
|
+
*
|
|
15312
|
+
* @param fields
|
|
15313
|
+
* @param propName
|
|
15314
|
+
*/
|
|
15315
|
+
function removeProp(fields, propName) {
|
|
15316
|
+
return fields.filter((field) => field.propName !== propName);
|
|
15317
|
+
}
|
|
15318
|
+
/**
|
|
15319
|
+
* - 値が配列の場合は、index に対応する値を返す。
|
|
15320
|
+
* - 値が配列でない場合は、そのまま返す。
|
|
15321
|
+
* - ⚠️ 値が配列で、index に対応する値が undefined の場合は、配列の最初の値を返す。
|
|
15322
|
+
* @param data
|
|
15323
|
+
* @param index
|
|
15324
|
+
*/
|
|
15325
|
+
function flattenData(data, index) {
|
|
15326
|
+
const result = {};
|
|
15327
|
+
for (const key in data) {
|
|
15328
|
+
result[key] = Array.isArray(data[key])
|
|
15329
|
+
? data[key][index] === undefined
|
|
15330
|
+
? data[key][0]
|
|
15331
|
+
: data[key][index]
|
|
15332
|
+
: data[key];
|
|
15333
|
+
}
|
|
15334
|
+
return result;
|
|
15335
|
+
}
|
|
15336
|
+
/**
|
|
15337
|
+
* 特定の要素で、`propName in element`で判定できない属性名
|
|
15338
|
+
*/
|
|
15339
|
+
const specificProp = {
|
|
15340
|
+
/*
|
|
15341
|
+
* JSDOMの未実装対策
|
|
15342
|
+
* @see https://github.com/jsdom/jsdom/blob/main/lib/jsdom/living/nodes/HTMLSourceElement.webidl
|
|
15343
|
+
* Living Standardでは実装済み
|
|
15344
|
+
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#htmlsourceelement
|
|
15345
|
+
*/
|
|
15346
|
+
source: ['width', 'height'],
|
|
15347
|
+
};
|
|
15348
|
+
/**
|
|
15349
|
+
*
|
|
15350
|
+
* @param el
|
|
15351
|
+
* @param name
|
|
15352
|
+
*/
|
|
15353
|
+
function propInElement(el, name) {
|
|
15354
|
+
const has = name in el;
|
|
15355
|
+
if (has) {
|
|
15356
|
+
return true;
|
|
15357
|
+
}
|
|
15358
|
+
return specificProp[el.localName]?.includes(name) ?? false;
|
|
14674
15359
|
}
|
|
15360
|
+
|
|
15361
|
+
const cache = new Map();
|
|
14675
15362
|
/**
|
|
14676
15363
|
*
|
|
14677
|
-
* @param
|
|
15364
|
+
* @param query
|
|
14678
15365
|
*/
|
|
14679
|
-
function
|
|
14680
|
-
|
|
15366
|
+
function parseFields(query) {
|
|
15367
|
+
const cached = cache.get(query);
|
|
15368
|
+
if (cached) {
|
|
15369
|
+
return cached;
|
|
15370
|
+
}
|
|
15371
|
+
const fields = query.split(',');
|
|
15372
|
+
const result = fields.map(parseField);
|
|
15373
|
+
cache.set(query, result);
|
|
15374
|
+
return result;
|
|
14681
15375
|
}
|
|
14682
|
-
|
|
14683
15376
|
/**
|
|
14684
15377
|
*
|
|
14685
15378
|
* @param field
|
|
14686
15379
|
*/
|
|
14687
|
-
function
|
|
15380
|
+
function parseField(field) {
|
|
14688
15381
|
field = field.trim().toLowerCase();
|
|
14689
15382
|
if (!field) {
|
|
14690
15383
|
throw new Error('Field name is empty.');
|
|
14691
15384
|
}
|
|
14692
|
-
let [fieldName, propName
|
|
15385
|
+
let [fieldName, propName,
|
|
15386
|
+
// eslint-disable-next-line prefer-const
|
|
15387
|
+
...rest] = field.split(':');
|
|
15388
|
+
if (rest.length > 0) {
|
|
15389
|
+
throw new Error('Invalid field format.');
|
|
15390
|
+
}
|
|
14693
15391
|
propName = propName?.trim() || '';
|
|
14694
15392
|
fieldName = fieldName?.trim() || propName || field;
|
|
14695
15393
|
return {
|
|
@@ -14709,58 +15407,67 @@ function fieldNameParser(field) {
|
|
|
14709
15407
|
* @param datum A datum of value
|
|
14710
15408
|
* @param attr Data attribute name for specifying the node that FrozenPatty treats as a field
|
|
14711
15409
|
* @param filter
|
|
15410
|
+
* @param xssSanitize Enable XSS protection
|
|
14712
15411
|
*/
|
|
14713
|
-
function setValue(el, name, datum, attr = 'field', filter) {
|
|
15412
|
+
function setValue(el, name, datum, attr = 'field', filter, xssSanitize = true) {
|
|
14714
15413
|
const rawValue = el.getAttribute(`data-${attr}`);
|
|
14715
|
-
const
|
|
14716
|
-
|
|
14717
|
-
|
|
14718
|
-
|
|
14719
|
-
|
|
14720
|
-
|
|
14721
|
-
|
|
14722
|
-
|
|
14723
|
-
|
|
14724
|
-
|
|
14725
|
-
|
|
14726
|
-
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
|
|
14730
|
-
|
|
14731
|
-
|
|
14732
|
-
|
|
14733
|
-
|
|
14734
|
-
|
|
14735
|
-
|
|
14736
|
-
|
|
14737
|
-
|
|
14738
|
-
|
|
14739
|
-
|
|
14740
|
-
|
|
14741
|
-
|
|
14742
|
-
|
|
14743
|
-
|
|
14744
|
-
|
|
14745
|
-
//
|
|
14746
|
-
default: {
|
|
14747
|
-
cssValue = `${datum}`;
|
|
14748
|
-
}
|
|
14749
|
-
}
|
|
14750
|
-
el.setAttribute('style', `${cssPropertyName}: ${cssValue}`);
|
|
14751
|
-
}
|
|
14752
|
-
else if (el instanceof HTMLElement) {
|
|
14753
|
-
// HTMLElement
|
|
14754
|
-
set$2(el, attr, propName, datum);
|
|
15414
|
+
const fields = parseFields(rawValue ?? '');
|
|
15415
|
+
const field = fields.find((field) => field.fieldName === name);
|
|
15416
|
+
if (!field) {
|
|
15417
|
+
return;
|
|
15418
|
+
}
|
|
15419
|
+
const { propName } = field;
|
|
15420
|
+
if (filter) {
|
|
15421
|
+
datum = filter(datum);
|
|
15422
|
+
}
|
|
15423
|
+
// console.log({ name, field, fieldName, propName, datum, el: el.innerHTML });
|
|
15424
|
+
if (!propName) {
|
|
15425
|
+
setContent(el, datum, undefined, xssSanitize);
|
|
15426
|
+
return;
|
|
15427
|
+
}
|
|
15428
|
+
if (propName === 'style' && el instanceof HTMLElement) {
|
|
15429
|
+
el.style.cssText = `${datum}`;
|
|
15430
|
+
return;
|
|
15431
|
+
}
|
|
15432
|
+
if (/^style\([a-z-]+\)$/i.test(propName)) {
|
|
15433
|
+
const cssPropertyName = propName.replace(/^style\(([a-z-]+)\)$/i, '$1');
|
|
15434
|
+
let cssValue;
|
|
15435
|
+
switch (cssPropertyName) {
|
|
15436
|
+
case 'background-image': {
|
|
15437
|
+
// Using CSS method would create absolute URLs with host
|
|
15438
|
+
// This would prevent migration from demo to production server
|
|
15439
|
+
// Using simple string insertion (setAttribute) instead
|
|
15440
|
+
// URL may not contain multibyte or whitespace characters, but escape anyway
|
|
15441
|
+
const url = encodeURI(`${datum}`);
|
|
15442
|
+
cssValue = `url(${url})`;
|
|
15443
|
+
break;
|
|
14755
15444
|
}
|
|
14756
|
-
|
|
14757
|
-
|
|
14758
|
-
|
|
15445
|
+
//
|
|
15446
|
+
// TODO: Handle other cases where values need units
|
|
15447
|
+
//
|
|
15448
|
+
default: {
|
|
15449
|
+
cssValue = `${datum}`;
|
|
14759
15450
|
}
|
|
14760
|
-
return;
|
|
14761
15451
|
}
|
|
14762
|
-
|
|
15452
|
+
el.setAttribute('style', `${cssPropertyName}: ${cssValue}`);
|
|
15453
|
+
return;
|
|
15454
|
+
}
|
|
15455
|
+
if (el instanceof HTMLElement) {
|
|
15456
|
+
// HTMLElement
|
|
15457
|
+
set$1(el, attr, propName, datum, xssSanitize);
|
|
15458
|
+
return;
|
|
15459
|
+
}
|
|
15460
|
+
// SVGElement or more
|
|
15461
|
+
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
|
15462
|
+
// Check attribute value if XSS protection is enabled
|
|
15463
|
+
if (xssSanitize) {
|
|
15464
|
+
const safeValue = sanitizeAttributeValue(propName, `${datum}`);
|
|
15465
|
+
if (safeValue !== null) {
|
|
15466
|
+
el.setAttribute(propName, safeValue);
|
|
15467
|
+
}
|
|
15468
|
+
return;
|
|
14763
15469
|
}
|
|
15470
|
+
el.setAttribute(propName, `${datum}`);
|
|
14764
15471
|
}
|
|
14765
15472
|
/**
|
|
14766
15473
|
*
|
|
@@ -14768,41 +15475,54 @@ function setValue(el, name, datum, attr = 'field', filter) {
|
|
|
14768
15475
|
* @param prefix
|
|
14769
15476
|
* @param name
|
|
14770
15477
|
* @param datum
|
|
15478
|
+
* @param xssSanitize
|
|
14771
15479
|
*/
|
|
14772
|
-
function set$
|
|
15480
|
+
function set$1(el, prefix, name, datum, xssSanitize = true) {
|
|
14773
15481
|
if (datum == null) {
|
|
14774
15482
|
el.removeAttribute(name);
|
|
14775
15483
|
return;
|
|
14776
15484
|
}
|
|
14777
15485
|
switch (name) {
|
|
14778
15486
|
case 'text': {
|
|
14779
|
-
setContent(el, datum, false);
|
|
15487
|
+
setContent(el, datum, false, xssSanitize);
|
|
14780
15488
|
return;
|
|
14781
15489
|
}
|
|
14782
15490
|
case 'html': {
|
|
14783
|
-
|
|
15491
|
+
// Sanitize HTML if XSS protection is enabled
|
|
15492
|
+
if (xssSanitize && typeof datum === 'string') {
|
|
15493
|
+
setContent(el, sanitizeHtml(datum), true, xssSanitize);
|
|
15494
|
+
}
|
|
15495
|
+
else {
|
|
15496
|
+
setContent(el, datum, true, xssSanitize);
|
|
15497
|
+
}
|
|
14784
15498
|
return;
|
|
14785
15499
|
}
|
|
14786
15500
|
case 'node': {
|
|
14787
15501
|
if (typeof datum !== 'string') {
|
|
14788
15502
|
return;
|
|
14789
15503
|
}
|
|
14790
|
-
|
|
14791
|
-
|
|
14792
|
-
|
|
14793
|
-
|
|
14794
|
-
|
|
14795
|
-
|
|
14796
|
-
|
|
14797
|
-
|
|
14798
|
-
|
|
14799
|
-
|
|
14800
|
-
|
|
14801
|
-
|
|
15504
|
+
replaceNode(el, datum, prefix, xssSanitize);
|
|
15505
|
+
return;
|
|
15506
|
+
}
|
|
15507
|
+
}
|
|
15508
|
+
// If XSS protection is enabled
|
|
15509
|
+
if (xssSanitize) {
|
|
15510
|
+
// Don't set event handler attributes (starting with 'on')
|
|
15511
|
+
if (name.toLowerCase().startsWith('on')) {
|
|
15512
|
+
return;
|
|
15513
|
+
}
|
|
15514
|
+
const beforeSanitize = datum;
|
|
15515
|
+
datum = sanitizeAttributeValue(name, datum);
|
|
15516
|
+
// If sanitization results in null value (except when original value was null), don't change the value
|
|
15517
|
+
if (datum === null && beforeSanitize !== null) {
|
|
14802
15518
|
return;
|
|
14803
15519
|
}
|
|
14804
15520
|
}
|
|
14805
|
-
if (
|
|
15521
|
+
if (datum == null) {
|
|
15522
|
+
el.removeAttribute(name);
|
|
15523
|
+
return;
|
|
15524
|
+
}
|
|
15525
|
+
if (!name.startsWith('data-') && !propInElement(el, name)) {
|
|
14806
15526
|
const dataAttr = `data-${prefix}-${kebabCase(name)}`;
|
|
14807
15527
|
if (el.hasAttribute(dataAttr)) {
|
|
14808
15528
|
el.setAttribute(dataAttr, `${datum}`);
|
|
@@ -15374,8 +16094,9 @@ function set$2(el, prefix, name, datum) {
|
|
|
15374
16094
|
* @param el
|
|
15375
16095
|
* @param datum
|
|
15376
16096
|
* @param asHtml
|
|
16097
|
+
* @param xssSanitize
|
|
15377
16098
|
*/
|
|
15378
|
-
function setContent(el, datum, asHtml = true) {
|
|
16099
|
+
function setContent(el, datum, asHtml = true, xssSanitize = true) {
|
|
15379
16100
|
if (el instanceof HTMLInputElement ||
|
|
15380
16101
|
el instanceof HTMLSelectElement ||
|
|
15381
16102
|
el instanceof HTMLTextAreaElement ||
|
|
@@ -15393,9 +16114,18 @@ function setContent(el, datum, asHtml = true) {
|
|
|
15393
16114
|
return;
|
|
15394
16115
|
}
|
|
15395
16116
|
if (asHtml) {
|
|
15396
|
-
|
|
16117
|
+
// Sanitize HTML if XSS protection is enabled
|
|
16118
|
+
const htmlStr = datum == null ? '' : `${datum}`;
|
|
16119
|
+
if (xssSanitize && typeof htmlStr === 'string') {
|
|
16120
|
+
// sanitizeHtml will now replace dangerous elements instead of removing them
|
|
16121
|
+
el.innerHTML = sanitizeHtml(htmlStr);
|
|
16122
|
+
}
|
|
16123
|
+
else {
|
|
16124
|
+
el.innerHTML = htmlStr;
|
|
16125
|
+
}
|
|
15397
16126
|
return;
|
|
15398
16127
|
}
|
|
16128
|
+
// No need to sanitize textContent (automatically escaped)
|
|
15399
16129
|
el.textContent = datum == null ? '' : `${datum}`;
|
|
15400
16130
|
}
|
|
15401
16131
|
/**
|
|
@@ -15469,6 +16199,16 @@ class ItemEditorDialog extends EditorDialog {
|
|
|
15469
16199
|
}
|
|
15470
16200
|
}
|
|
15471
16201
|
}
|
|
16202
|
+
if ($ctrl.name.endsWith('[]')) {
|
|
16203
|
+
return $ctrl.value.split(',').map((value) => {
|
|
16204
|
+
try {
|
|
16205
|
+
return JSON.parse(value);
|
|
16206
|
+
}
|
|
16207
|
+
catch {
|
|
16208
|
+
return value;
|
|
16209
|
+
}
|
|
16210
|
+
});
|
|
16211
|
+
}
|
|
15472
16212
|
try {
|
|
15473
16213
|
return JSON.parse($ctrl.value);
|
|
15474
16214
|
}
|
|
@@ -15520,7 +16260,11 @@ class ItemEditorDialog extends EditorDialog {
|
|
|
15520
16260
|
const $data = this.findAll(`[name^="${prefix}"]`);
|
|
15521
16261
|
const map = new Map();
|
|
15522
16262
|
for (const $datum of $data) {
|
|
15523
|
-
|
|
16263
|
+
let name = camelCase($datum.name.slice(prefix.length));
|
|
16264
|
+
if (name.endsWith('[]')) {
|
|
16265
|
+
name = name.slice(0, -2);
|
|
16266
|
+
map.delete(name);
|
|
16267
|
+
}
|
|
15524
16268
|
if (map.has(name)) {
|
|
15525
16269
|
continue;
|
|
15526
16270
|
}
|
|
@@ -15563,7 +16307,7 @@ class ItemEditorDialog extends EditorDialog {
|
|
|
15563
16307
|
const propName = name.slice(1);
|
|
15564
16308
|
let el;
|
|
15565
16309
|
for (const n of [kebabCase(propName), propName]) {
|
|
15566
|
-
el = this.findAll(`[name="bge-${n}"]`);
|
|
16310
|
+
el = this.findAll(`[name="bge-${n}"], [name="bge-${n}[]"]`);
|
|
15567
16311
|
if (el.length > 0) {
|
|
15568
16312
|
return [...el];
|
|
15569
16313
|
}
|
|
@@ -15573,30 +16317,10 @@ class ItemEditorDialog extends EditorDialog {
|
|
|
15573
16317
|
#setValues(data) {
|
|
15574
16318
|
for (const [_name, datum] of Object.entries(data)) {
|
|
15575
16319
|
const name = kebabCase(_name);
|
|
15576
|
-
const inputSelector = `[name="bge-${name}"]`;
|
|
15577
|
-
|
|
15578
|
-
const $targetEl = this.find(inputSelector);
|
|
15579
|
-
if (!$targetEl) {
|
|
15580
|
-
continue;
|
|
15581
|
-
}
|
|
15582
|
-
const $listRoot = $targetEl.closest('[data-bge-list]');
|
|
15583
|
-
if (!$listRoot || $listRoot.children.length === 0) {
|
|
15584
|
-
continue;
|
|
15585
|
-
}
|
|
15586
|
-
const $listItem = $listRoot.firstElementChild?.cloneNode(true);
|
|
15587
|
-
if (!$listItem) {
|
|
15588
|
-
continue;
|
|
15589
|
-
}
|
|
15590
|
-
while (datum.length > $listRoot.children.length) {
|
|
15591
|
-
$listRoot.append($listItem.cloneNode(true));
|
|
15592
|
-
}
|
|
15593
|
-
for (const [i, targetEl] of $listRoot.querySelectorAll(inputSelector).entries()) {
|
|
15594
|
-
setContent(targetEl, datum[i] || '');
|
|
15595
|
-
}
|
|
15596
|
-
continue;
|
|
15597
|
-
}
|
|
16320
|
+
const inputSelector = `[name="bge-${name}"], [name="bge-${name}[]"]`;
|
|
16321
|
+
const value = Array.isArray(datum) ? datum.join(',') : datum;
|
|
15598
16322
|
for (const targetEl of this.findAll(inputSelector)) {
|
|
15599
|
-
setContent(targetEl,
|
|
16323
|
+
setContent(targetEl, value);
|
|
15600
16324
|
}
|
|
15601
16325
|
}
|
|
15602
16326
|
this.update(data);
|
|
@@ -15893,16 +16617,16 @@ class BurgerEditorEngine {
|
|
|
15893
16617
|
*/
|
|
15894
16618
|
function getValues(el, convertType = false, attr = 'field', filter) {
|
|
15895
16619
|
const result = [];
|
|
15896
|
-
const
|
|
15897
|
-
|
|
15898
|
-
const forceArray = !!listRoot;
|
|
15899
|
-
if (rawValue == null) {
|
|
16620
|
+
const query = el.getAttribute(`data-${attr}`);
|
|
16621
|
+
if (query == null) {
|
|
15900
16622
|
throw new Error(`data-${attr} attriblute is empty.`);
|
|
15901
16623
|
}
|
|
15902
|
-
const
|
|
15903
|
-
|
|
16624
|
+
const listRoot = el.closest(`[data-${attr}-list]`);
|
|
16625
|
+
const forceArray = !!listRoot;
|
|
16626
|
+
const fields = parseFields(query);
|
|
16627
|
+
for (const field of fields) {
|
|
15904
16628
|
let value;
|
|
15905
|
-
const { fieldName, propName } =
|
|
16629
|
+
const { fieldName, propName } = field;
|
|
15906
16630
|
if (propName) {
|
|
15907
16631
|
switch (propName) {
|
|
15908
16632
|
case 'node': {
|
|
@@ -15917,6 +16641,12 @@ function getValues(el, convertType = false, attr = 'field', filter) {
|
|
|
15917
16641
|
value = el.innerHTML.trim();
|
|
15918
16642
|
break;
|
|
15919
16643
|
}
|
|
16644
|
+
case 'style': {
|
|
16645
|
+
if (el instanceof HTMLElement) {
|
|
16646
|
+
value = el.style.cssText;
|
|
16647
|
+
}
|
|
16648
|
+
break;
|
|
16649
|
+
}
|
|
15920
16650
|
default: {
|
|
15921
16651
|
if (/^style\([a-z-]+\)$/i.test(propName)) {
|
|
15922
16652
|
const css = propName.replace(/^style\(([a-z-]+)\)$/i, '$1');
|
|
@@ -15933,7 +16663,7 @@ function getValues(el, convertType = false, attr = 'field', filter) {
|
|
|
15933
16663
|
}
|
|
15934
16664
|
break;
|
|
15935
16665
|
}
|
|
15936
|
-
value = getAttribute(el,
|
|
16666
|
+
value = getAttribute(el, propName, attr, convertType);
|
|
15937
16667
|
}
|
|
15938
16668
|
}
|
|
15939
16669
|
}
|
|
@@ -15961,11 +16691,11 @@ function getValues(el, convertType = false, attr = 'field', filter) {
|
|
|
15961
16691
|
/**
|
|
15962
16692
|
*
|
|
15963
16693
|
* @param el
|
|
15964
|
-
* @param attr
|
|
15965
16694
|
* @param keyAttr
|
|
16695
|
+
* @param attr
|
|
15966
16696
|
* @param typeConvert
|
|
15967
16697
|
*/
|
|
15968
|
-
function getAttribute(el,
|
|
16698
|
+
function getAttribute(el, keyAttr, attr, typeConvert) {
|
|
15969
16699
|
switch (keyAttr) {
|
|
15970
16700
|
case 'contenteditable': {
|
|
15971
16701
|
if (el instanceof HTMLElement) {
|
|
@@ -15987,24 +16717,35 @@ function getAttribute(el, attr, keyAttr, typeConvert) {
|
|
|
15987
16717
|
return el.hasAttribute('download') ? el.getAttribute('download') : null;
|
|
15988
16718
|
}
|
|
15989
16719
|
case 'href': {
|
|
15990
|
-
//
|
|
15991
|
-
|
|
16720
|
+
// Example: (el as HTMLAnchorElement).href;
|
|
16721
|
+
// Expected: return defined value of plain string
|
|
16722
|
+
return el.getAttribute(keyAttr) ?? '';
|
|
15992
16723
|
}
|
|
15993
|
-
|
|
15994
|
-
|
|
15995
|
-
|
|
15996
|
-
|
|
15997
|
-
|
|
15998
|
-
|
|
15999
|
-
|
|
16000
|
-
value = el.getAttribute(keyAttr) || '';
|
|
16001
|
-
}
|
|
16002
|
-
if (typeConvert) {
|
|
16003
|
-
value = convert(value);
|
|
16004
|
-
}
|
|
16005
|
-
return value;
|
|
16724
|
+
}
|
|
16725
|
+
let value =
|
|
16726
|
+
// @ts-ignore
|
|
16727
|
+
el[keyAttr];
|
|
16728
|
+
if (value !== undefined) {
|
|
16729
|
+
if (typeConvert) {
|
|
16730
|
+
value = convert(value);
|
|
16006
16731
|
}
|
|
16732
|
+
return value;
|
|
16733
|
+
}
|
|
16734
|
+
// For shorthand notation, get value from data-field-* attribute
|
|
16735
|
+
const dataAttr = ['data', attr, kebabCase(keyAttr)].join('-');
|
|
16736
|
+
if (el.hasAttribute(dataAttr)) {
|
|
16737
|
+
return el.getAttribute(dataAttr) ?? '';
|
|
16738
|
+
}
|
|
16739
|
+
value = el.getAttribute(keyAttr) ?? null;
|
|
16740
|
+
if ((value === '' || value == null) &&
|
|
16741
|
+
typeof keyAttr === 'string' &&
|
|
16742
|
+
keyAttr.startsWith('data-')) {
|
|
16743
|
+
return '';
|
|
16007
16744
|
}
|
|
16745
|
+
if (typeConvert) {
|
|
16746
|
+
value = convert(value);
|
|
16747
|
+
}
|
|
16748
|
+
return value;
|
|
16008
16749
|
}
|
|
16009
16750
|
/**
|
|
16010
16751
|
*
|
|
@@ -16012,8 +16753,9 @@ function getAttribute(el, attr, keyAttr, typeConvert) {
|
|
|
16012
16753
|
*/
|
|
16013
16754
|
function convert(value) {
|
|
16014
16755
|
value = parse(value);
|
|
16015
|
-
|
|
16016
|
-
|
|
16756
|
+
const str = `${value}`;
|
|
16757
|
+
if (URL.canParse(str)) {
|
|
16758
|
+
const url = new URL(str, location.href);
|
|
16017
16759
|
if (url.origin === location.origin) {
|
|
16018
16760
|
return url.pathname;
|
|
16019
16761
|
}
|
|
@@ -16026,7 +16768,7 @@ function convert(value) {
|
|
|
16026
16768
|
*/
|
|
16027
16769
|
function parse(value) {
|
|
16028
16770
|
try {
|
|
16029
|
-
return JSON.parse(value);
|
|
16771
|
+
return JSON.parse(`${value}`);
|
|
16030
16772
|
}
|
|
16031
16773
|
catch {
|
|
16032
16774
|
return value;
|
|
@@ -16041,6 +16783,7 @@ function getBackgroundImagePath(value) {
|
|
|
16041
16783
|
return decodeURI(value.replace(/^url\(["']?([^"']+)["']?\)$/i, '$1').replace(origin, ''));
|
|
16042
16784
|
}
|
|
16043
16785
|
|
|
16786
|
+
const reverseListElementSelectors = ['picture'];
|
|
16044
16787
|
/**
|
|
16045
16788
|
*
|
|
16046
16789
|
* @param el
|
|
@@ -16048,9 +16791,18 @@ function getBackgroundImagePath(value) {
|
|
|
16048
16791
|
* @param typeConvert
|
|
16049
16792
|
* @param filter
|
|
16050
16793
|
*/
|
|
16051
|
-
function
|
|
16052
|
-
|
|
16053
|
-
const
|
|
16794
|
+
function getComponent(el, attr, typeConvert, filter) {
|
|
16795
|
+
el = el.cloneNode(true);
|
|
16796
|
+
const reverseListElements = el.querySelectorAll(`:is(${reverseListElementSelectors.join(',')})[data-${attr}-list]`);
|
|
16797
|
+
for (const reverseListElement of reverseListElements) {
|
|
16798
|
+
const children = [];
|
|
16799
|
+
while (reverseListElement.lastElementChild) {
|
|
16800
|
+
children.push(reverseListElement.lastElementChild);
|
|
16801
|
+
reverseListElement.lastElementChild.remove();
|
|
16802
|
+
}
|
|
16803
|
+
reverseListElement.append(...children);
|
|
16804
|
+
}
|
|
16805
|
+
const filedElements = el.querySelectorAll(`[data-${attr}]`);
|
|
16054
16806
|
let values = [];
|
|
16055
16807
|
for (const _el of filedElements) {
|
|
16056
16808
|
values = [...values, ...getValues(_el, typeConvert, attr, filter)];
|
|
@@ -16059,59 +16811,105 @@ function get$1 (el, attr, typeConvert, filter) {
|
|
|
16059
16811
|
return result;
|
|
16060
16812
|
}
|
|
16061
16813
|
|
|
16814
|
+
/**
|
|
16815
|
+
* Combines multiple field definitions with comma separation
|
|
16816
|
+
* @param fields Array of field definitions
|
|
16817
|
+
* @returns Comma-separated field definition string
|
|
16818
|
+
*/
|
|
16819
|
+
function stringifyFields(fields) {
|
|
16820
|
+
return fields
|
|
16821
|
+
.map((field) => stringifyField(field.fieldName, field.propName))
|
|
16822
|
+
.join(', ');
|
|
16823
|
+
}
|
|
16824
|
+
/**
|
|
16825
|
+
* Generates a field definition string from field name and attribute name
|
|
16826
|
+
* @param fieldName Field name
|
|
16827
|
+
* @param propName Attribute name (optional)
|
|
16828
|
+
* @returns Field definition string
|
|
16829
|
+
*/
|
|
16830
|
+
function stringifyField(fieldName, propName) {
|
|
16831
|
+
if (!propName) {
|
|
16832
|
+
return fieldName;
|
|
16833
|
+
}
|
|
16834
|
+
// Use shorthand notation when fieldName and propName are the same
|
|
16835
|
+
if (fieldName === propName) {
|
|
16836
|
+
return `:${propName}`;
|
|
16837
|
+
}
|
|
16838
|
+
return `${fieldName}:${propName}`;
|
|
16839
|
+
}
|
|
16840
|
+
|
|
16062
16841
|
/**
|
|
16063
16842
|
*
|
|
16064
16843
|
* @param el
|
|
16065
16844
|
* @param data
|
|
16066
16845
|
* @param attr
|
|
16067
16846
|
* @param filter
|
|
16847
|
+
* @param xssSanitize Enable XSS protection
|
|
16068
16848
|
*/
|
|
16069
|
-
function
|
|
16849
|
+
function setComponent(el, data, attr, filter, xssSanitize = true) {
|
|
16070
16850
|
el = el.cloneNode(true);
|
|
16071
16851
|
for (const dataKeyName in data) {
|
|
16072
|
-
|
|
16073
|
-
|
|
16074
|
-
|
|
16075
|
-
|
|
16076
|
-
|
|
16077
|
-
|
|
16078
|
-
|
|
16079
|
-
|
|
16080
|
-
|
|
16081
|
-
|
|
16082
|
-
|
|
16083
|
-
|
|
16084
|
-
|
|
16085
|
-
|
|
16086
|
-
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
|
|
16095
|
-
|
|
16096
|
-
|
|
16097
|
-
|
|
16098
|
-
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16852
|
+
const datum = data[dataKeyName];
|
|
16853
|
+
if (Array.isArray(datum)) {
|
|
16854
|
+
continue;
|
|
16855
|
+
}
|
|
16856
|
+
const targetList = [
|
|
16857
|
+
// Include self
|
|
16858
|
+
el,
|
|
16859
|
+
// Perform rough filtering for performance
|
|
16860
|
+
...el.querySelectorAll(`[data-${attr}*="${kebabCase(dataKeyName)}"]`),
|
|
16861
|
+
]
|
|
16862
|
+
// Perform more accurate filtering
|
|
16863
|
+
.filter((el) => hasField(el, attr, dataKeyName));
|
|
16864
|
+
for (const targetEl of targetList) {
|
|
16865
|
+
setValue(targetEl, dataKeyName, datum, attr, filter, xssSanitize);
|
|
16866
|
+
}
|
|
16867
|
+
}
|
|
16868
|
+
for (const listRoot of el.querySelectorAll(`[data-${attr}-list]`)) {
|
|
16869
|
+
const decendants = listRoot.querySelectorAll('*');
|
|
16870
|
+
const definedFieldsOfDecendants = new Set([...decendants].flatMap((el) => definedFields(el, attr)));
|
|
16871
|
+
const maxLength = maxLengthOf(data, [...definedFieldsOfDecendants]);
|
|
16872
|
+
const listItem = listRoot.children[0]?.cloneNode(true);
|
|
16873
|
+
if (!listItem) {
|
|
16874
|
+
continue;
|
|
16875
|
+
}
|
|
16876
|
+
while (listRoot.firstChild) {
|
|
16877
|
+
listRoot.firstChild.remove();
|
|
16878
|
+
}
|
|
16879
|
+
for (let i = 0; i < maxLength; i++) {
|
|
16880
|
+
let item = listItem.cloneNode(true);
|
|
16881
|
+
const itemData = flattenData(data, i);
|
|
16882
|
+
let reverse = false;
|
|
16883
|
+
switch (listRoot.localName) {
|
|
16884
|
+
case 'picture': {
|
|
16885
|
+
reverse = true;
|
|
16886
|
+
let fields = getFields(item, attr);
|
|
16887
|
+
if (i === 0) {
|
|
16888
|
+
// Convert first item to img element
|
|
16889
|
+
item = replaceNode(item, 'img', attr, xssSanitize);
|
|
16890
|
+
fields = replaceProp(fields, 'srcset', 'src');
|
|
16891
|
+
fields = removeProp(fields, 'sizes');
|
|
16892
|
+
const fieldQuery = stringifyFields(fields);
|
|
16893
|
+
item.setAttribute(`data-${attr}`, fieldQuery);
|
|
16102
16894
|
}
|
|
16103
16895
|
else {
|
|
16104
|
-
|
|
16105
|
-
|
|
16896
|
+
// Convert subsequent items to source elements
|
|
16897
|
+
item = replaceNode(item, 'source', attr, xssSanitize);
|
|
16898
|
+
fields = replaceProp(fields, 'src', 'srcset');
|
|
16899
|
+
fields = removeProp(fields, 'alt');
|
|
16900
|
+
fields = removeProp(fields, 'loading');
|
|
16901
|
+
const fieldQuery = stringifyFields(fields);
|
|
16902
|
+
item.setAttribute(`data-${attr}`, fieldQuery);
|
|
16106
16903
|
}
|
|
16904
|
+
break;
|
|
16107
16905
|
}
|
|
16108
|
-
|
|
16109
|
-
|
|
16906
|
+
}
|
|
16907
|
+
const newEl = setComponent(item, itemData, attr, filter, xssSanitize);
|
|
16908
|
+
if (reverse) {
|
|
16909
|
+
listRoot.prepend(newEl);
|
|
16110
16910
|
}
|
|
16111
16911
|
else {
|
|
16112
|
-
|
|
16113
|
-
setValue(targetEl, dataKeyName, datum, attr, filter);
|
|
16114
|
-
}
|
|
16912
|
+
listRoot.append(newEl);
|
|
16115
16913
|
}
|
|
16116
16914
|
}
|
|
16117
16915
|
}
|
|
@@ -16126,6 +16924,10 @@ class FrozenPatty {
|
|
|
16126
16924
|
*/
|
|
16127
16925
|
#filter;
|
|
16128
16926
|
#typeConvert = false;
|
|
16927
|
+
/**
|
|
16928
|
+
* Enable XSS protection
|
|
16929
|
+
*/
|
|
16930
|
+
#xssSanitize = true;
|
|
16129
16931
|
/**
|
|
16130
16932
|
*
|
|
16131
16933
|
* @param html Original HTML
|
|
@@ -16133,7 +16935,14 @@ class FrozenPatty {
|
|
|
16133
16935
|
*/
|
|
16134
16936
|
constructor(html, options) {
|
|
16135
16937
|
this.#dom = document.createElement('fp-placeholer');
|
|
16136
|
-
|
|
16938
|
+
// Sanitize initial HTML if XSS protection is enabled
|
|
16939
|
+
if (options?.xssSanitize === false) {
|
|
16940
|
+
this.#dom.innerHTML = html;
|
|
16941
|
+
this.#xssSanitize = false;
|
|
16942
|
+
}
|
|
16943
|
+
else {
|
|
16944
|
+
this.#dom.innerHTML = sanitizeHtml(html);
|
|
16945
|
+
}
|
|
16137
16946
|
if (options) {
|
|
16138
16947
|
if (options.attr) {
|
|
16139
16948
|
this.#attr = options.attr;
|
|
@@ -16145,7 +16954,8 @@ class FrozenPatty {
|
|
|
16145
16954
|
merge(data) {
|
|
16146
16955
|
const currentData = this.toJSON(false);
|
|
16147
16956
|
const newData = Object.assign(currentData, data);
|
|
16148
|
-
|
|
16957
|
+
// Pass XSS protection flag to set (default is true if not set)
|
|
16958
|
+
this.#dom = setComponent(this.#dom, newData, this.#attr, this.#filter, this.#xssSanitize);
|
|
16149
16959
|
return this;
|
|
16150
16960
|
}
|
|
16151
16961
|
toDOM() {
|
|
@@ -16156,7 +16966,7 @@ class FrozenPatty {
|
|
|
16156
16966
|
}
|
|
16157
16967
|
toJSON(filtering = true) {
|
|
16158
16968
|
const filter = filtering ? this.#filter : undefined;
|
|
16159
|
-
return
|
|
16969
|
+
return getComponent(this.#dom, this.#attr, this.#typeConvert, filter);
|
|
16160
16970
|
}
|
|
16161
16971
|
}
|
|
16162
16972
|
|
|
@@ -17493,6 +18303,19 @@ function mutable_source(initial_value, immutable = false) {
|
|
|
17493
18303
|
return s;
|
|
17494
18304
|
}
|
|
17495
18305
|
|
|
18306
|
+
/**
|
|
18307
|
+
* @template V
|
|
18308
|
+
* @param {Value<V>} source
|
|
18309
|
+
* @param {V} value
|
|
18310
|
+
*/
|
|
18311
|
+
function mutate(source, value) {
|
|
18312
|
+
set(
|
|
18313
|
+
source,
|
|
18314
|
+
untrack(() => get(source))
|
|
18315
|
+
);
|
|
18316
|
+
return value;
|
|
18317
|
+
}
|
|
18318
|
+
|
|
17496
18319
|
/**
|
|
17497
18320
|
* @template V
|
|
17498
18321
|
* @param {Source<V>} source
|
|
@@ -18411,13 +19234,13 @@ function flush_queued_root_effects() {
|
|
|
18411
19234
|
var collected_effects = process_effects(root_effects[i]);
|
|
18412
19235
|
flush_queued_effects(collected_effects);
|
|
18413
19236
|
}
|
|
19237
|
+
old_values.clear();
|
|
18414
19238
|
}
|
|
18415
19239
|
} finally {
|
|
18416
19240
|
is_flushing = false;
|
|
18417
19241
|
is_updating_effect = was_updating_effect;
|
|
18418
19242
|
|
|
18419
19243
|
last_scheduled_effect = null;
|
|
18420
|
-
old_values.clear();
|
|
18421
19244
|
}
|
|
18422
19245
|
}
|
|
18423
19246
|
|
|
@@ -19293,6 +20116,20 @@ function resume_children(effect, local) {
|
|
|
19293
20116
|
}
|
|
19294
20117
|
}
|
|
19295
20118
|
|
|
20119
|
+
/* This file is generated by scripts/process-messages/index.js. Do not edit! */
|
|
20120
|
+
|
|
20121
|
+
|
|
20122
|
+
/**
|
|
20123
|
+
* `%name%(...)` can only be used during component initialisation
|
|
20124
|
+
* @param {string} name
|
|
20125
|
+
* @returns {never}
|
|
20126
|
+
*/
|
|
20127
|
+
function lifecycle_outside_component(name) {
|
|
20128
|
+
{
|
|
20129
|
+
throw new Error(`https://svelte.dev/e/lifecycle_outside_component`);
|
|
20130
|
+
}
|
|
20131
|
+
}
|
|
20132
|
+
|
|
19296
20133
|
/** @import { ComponentContext } from '#client' */
|
|
19297
20134
|
|
|
19298
20135
|
|
|
@@ -21541,7 +22378,7 @@ function bind_this(element_or_component = {}, update, get_value, get_parts) {
|
|
|
21541
22378
|
render_effect(() => {
|
|
21542
22379
|
old_parts = parts;
|
|
21543
22380
|
// We only track changes to the parts, not the value itself to avoid unnecessary reruns.
|
|
21544
|
-
parts = [];
|
|
22381
|
+
parts = get_parts?.() || [];
|
|
21545
22382
|
|
|
21546
22383
|
untrack(() => {
|
|
21547
22384
|
if (element_or_component !== get_value(...parts)) {
|
|
@@ -21646,6 +22483,48 @@ function observe_all(context, props) {
|
|
|
21646
22483
|
props();
|
|
21647
22484
|
}
|
|
21648
22485
|
|
|
22486
|
+
/** @import { ComponentContext, ComponentContextLegacy } from '#client' */
|
|
22487
|
+
/** @import { EventDispatcher } from './index.js' */
|
|
22488
|
+
/** @import { NotFunction } from './internal/types.js' */
|
|
22489
|
+
|
|
22490
|
+
/**
|
|
22491
|
+
* `onMount`, like [`$effect`](https://svelte.dev/docs/svelte/$effect), schedules a function to run as soon as the component has been mounted to the DOM.
|
|
22492
|
+
* Unlike `$effect`, the provided function only runs once.
|
|
22493
|
+
*
|
|
22494
|
+
* It must be called during the component's initialisation (but doesn't need to live _inside_ the component;
|
|
22495
|
+
* it can be called from an external module). If a function is returned _synchronously_ from `onMount`,
|
|
22496
|
+
* it will be called when the component is unmounted.
|
|
22497
|
+
*
|
|
22498
|
+
* `onMount` functions do not run during [server-side rendering](https://svelte.dev/docs/svelte/svelte-server#render).
|
|
22499
|
+
*
|
|
22500
|
+
* @template T
|
|
22501
|
+
* @param {() => NotFunction<T> | Promise<NotFunction<T>> | (() => any)} fn
|
|
22502
|
+
* @returns {void}
|
|
22503
|
+
*/
|
|
22504
|
+
function onMount(fn) {
|
|
22505
|
+
if (component_context === null) {
|
|
22506
|
+
lifecycle_outside_component();
|
|
22507
|
+
}
|
|
22508
|
+
|
|
22509
|
+
if (legacy_mode_flag && component_context.l !== null) {
|
|
22510
|
+
init_update_callbacks(component_context).m.push(fn);
|
|
22511
|
+
} else {
|
|
22512
|
+
user_effect(() => {
|
|
22513
|
+
const cleanup = untrack(fn);
|
|
22514
|
+
if (typeof cleanup === 'function') return /** @type {() => void} */ (cleanup);
|
|
22515
|
+
});
|
|
22516
|
+
}
|
|
22517
|
+
}
|
|
22518
|
+
|
|
22519
|
+
/**
|
|
22520
|
+
* Legacy-mode: Init callbacks object for onMount/beforeUpdate/afterUpdate
|
|
22521
|
+
* @param {ComponentContext} context
|
|
22522
|
+
*/
|
|
22523
|
+
function init_update_callbacks(context) {
|
|
22524
|
+
var l = /** @type {ComponentContextLegacy} */ (context).l;
|
|
22525
|
+
return (l.u ??= { a: [], b: [], m: [] });
|
|
22526
|
+
}
|
|
22527
|
+
|
|
21649
22528
|
/** @import { StoreReferencesContainer } from '#client' */
|
|
21650
22529
|
/** @import { Store } from '#shared' */
|
|
21651
22530
|
|
|
@@ -22015,8 +22894,8 @@ function prop(props, key, flags, fallback) {
|
|
|
22015
22894
|
var root_4$3 = template(`<img alt="" loading="lazy" class="svelte-s2t554">`);
|
|
22016
22895
|
var root_3$5 = template(`<figure class="svelte-s2t554"><div class="img svelte-s2t554"><!></div> <figcaption class="svelte-s2t554"> </figcaption></figure>`);
|
|
22017
22896
|
var root_2$3 = template(`<dd class="svelte-s2t554"><button type="button" class="svelte-s2t554"><!></button></dd>`);
|
|
22018
|
-
var root_1$
|
|
22019
|
-
var root$
|
|
22897
|
+
var root_1$6 = template(`<dt class="svelte-s2t554"> </dt> <div class="svelte-s2t554"></div>`, 1);
|
|
22898
|
+
var root$b = template(`<div class="block-catalog"><dl class="svelte-s2t554"></dl></div>`);
|
|
22020
22899
|
|
|
22021
22900
|
function Block_catalog($$anchor, $$props) {
|
|
22022
22901
|
push($$props, false);
|
|
@@ -22034,13 +22913,13 @@ function Block_catalog($$anchor, $$props) {
|
|
|
22034
22913
|
|
|
22035
22914
|
init();
|
|
22036
22915
|
|
|
22037
|
-
var div = root$
|
|
22916
|
+
var div = root$b();
|
|
22038
22917
|
var dl = child(div);
|
|
22039
22918
|
|
|
22040
22919
|
each(dl, 5, () => engine().blockCatalogDialog.catalog, ([category, blocks]) => category, ($$anchor, $$item) => {
|
|
22041
22920
|
let category = () => get($$item)[0];
|
|
22042
22921
|
let blocks = () => get($$item)[1];
|
|
22043
|
-
var fragment = root_1$
|
|
22922
|
+
var fragment = root_1$6();
|
|
22044
22923
|
var dt = first_child(fragment);
|
|
22045
22924
|
var text$1 = child(dt);
|
|
22046
22925
|
|
|
@@ -22141,7 +23020,7 @@ const defaultAttributes = {
|
|
|
22141
23020
|
},
|
|
22142
23021
|
};
|
|
22143
23022
|
|
|
22144
|
-
var root$
|
|
23023
|
+
var root$a = ns_template(`<svg><!><!></svg>`);
|
|
22145
23024
|
|
|
22146
23025
|
function Icon($$anchor, $$props) {
|
|
22147
23026
|
const $$sanitized_props = legacy_rest_props($$props, [
|
|
@@ -22171,7 +23050,7 @@ function Icon($$anchor, $$props) {
|
|
|
22171
23050
|
|
|
22172
23051
|
init();
|
|
22173
23052
|
|
|
22174
|
-
var svg = root$
|
|
23053
|
+
var svg = root$a();
|
|
22175
23054
|
let attributes;
|
|
22176
23055
|
var node = child(svg);
|
|
22177
23056
|
|
|
@@ -22535,11 +23414,11 @@ function Trash($$anchor, $$props) {
|
|
|
22535
23414
|
}));
|
|
22536
23415
|
}
|
|
22537
23416
|
|
|
22538
|
-
var root$
|
|
23417
|
+
var root$9 = template(`<div class="svelte-1m6pw9u"><button type="button" class="svelte-1m6pw9u"><!></button> <span class="svelte-1m6pw9u"> </span></div>`);
|
|
22539
23418
|
|
|
22540
23419
|
function Block_menu_button($$anchor, $$props) {
|
|
22541
23420
|
const uid = props_id();
|
|
22542
|
-
var div = root$
|
|
23421
|
+
var div = root$9();
|
|
22543
23422
|
|
|
22544
23423
|
set_style(div, '', {}, { '--name': `--anchor-${uid}` });
|
|
22545
23424
|
|
|
@@ -22628,7 +23507,7 @@ async function replaceElement(elA, elB, duration = 600) {
|
|
|
22628
23507
|
}
|
|
22629
23508
|
|
|
22630
23509
|
var root_5$3 = template(`<!> <!>`, 1);
|
|
22631
|
-
var root$
|
|
23510
|
+
var root$8 = template(`<div class="bge-menu-base svelte-15fci6"><div class="bge-menu svelte-15fci6"><div class="bge-move-group svelte-15fci6"><!> <!></div> <div class="bge-standard-group svelte-15fci6"><!> <!> <!> <!> <!> <!></div></div> <div class="bge-menu-margin svelte-15fci6"><span class="svelte-15fci6"> </span></div></div>`);
|
|
22632
23511
|
|
|
22633
23512
|
function Block_menu($$anchor, $$props) {
|
|
22634
23513
|
push($$props, false);
|
|
@@ -22780,7 +23659,7 @@ function Block_menu($$anchor, $$props) {
|
|
|
22780
23659
|
legacy_pre_effect_reset();
|
|
22781
23660
|
init();
|
|
22782
23661
|
|
|
22783
|
-
var div = root$
|
|
23662
|
+
var div = root$8();
|
|
22784
23663
|
var div_1 = child(div);
|
|
22785
23664
|
var div_2 = child(div_1);
|
|
22786
23665
|
var node = child(div_2);
|
|
@@ -22902,11 +23781,11 @@ var root_4$2 = template(`<div role="radiogroup" aria-labelledby="justify-group">
|
|
|
22902
23781
|
var root_5$2 = template(`<label><span>列数</span> <output> </output> <input name="bge-options-columns" type="range" min="1" max="5"></label>`);
|
|
22903
23782
|
var root_6$1 = template(`<div role="radiogroup" aria-labelledby="float-group"><div id="float-group">回り込み</div> <label><input type="radio" name="bge-options-float" value="start"><span>左寄せ</span></label> <label><input type="radio" name="bge-options-float" value="end"><span>右寄せ</span></label></div>`);
|
|
22904
23783
|
var root_3$4 = template(`<!> <!> <!>`, 1);
|
|
22905
|
-
var root_1$
|
|
23784
|
+
var root_1$5 = template(`<fieldset><legend>コンテナ特性</legend> <label><span>コンテナタイプ</span> <output> </output></label> <!></fieldset>`);
|
|
22906
23785
|
var root_9$1 = template(`<option> </option>`);
|
|
22907
23786
|
var root_8$1 = template(`<label><span> </span> <select></select></label>`);
|
|
22908
23787
|
var root_7$2 = template(`<fieldset><legend>ブロックのスタイル拡張</legend> <!></fieldset>`);
|
|
22909
|
-
var root$
|
|
23788
|
+
var root$7 = template(`<!> <!> <label><span>独自class設定</span> <input type="text" name="bge-options-classes" aria-describedby="block-option-classes-desc"></label> <small id="block-option-classes-desc">複数指定する場合はスペース(空白文字)で区切ってください。</small> <label><span>ID設定: <code>bge-</code></span> <input name="bge-options-id" type="text" aria-describedby="block-option-id-desc"></label> <small id="block-option-id-desc">アンカーリンク用のID属性を設定します。実際のIDは<code>bge-</code>が自動的に先頭に付加されます。</small>`, 1);
|
|
22910
23789
|
|
|
22911
23790
|
function Block_options($$anchor, $$props) {
|
|
22912
23791
|
push($$props, true);
|
|
@@ -22921,12 +23800,12 @@ function Block_options($$anchor, $$props) {
|
|
|
22921
23800
|
|
|
22922
23801
|
const options = currentBlock.exportOptions();
|
|
22923
23802
|
let currentColumns = state(proxy(options.props.columns ?? 1));
|
|
22924
|
-
var fragment = root$
|
|
23803
|
+
var fragment = root$7();
|
|
22925
23804
|
var node = first_child(fragment);
|
|
22926
23805
|
|
|
22927
23806
|
{
|
|
22928
23807
|
var consequent_4 = ($$anchor) => {
|
|
22929
|
-
var fieldset = root_1$
|
|
23808
|
+
var fieldset = root_1$5();
|
|
22930
23809
|
var label = sibling(child(fieldset), 2);
|
|
22931
23810
|
var output = sibling(child(label), 2);
|
|
22932
23811
|
var text = child(output);
|
|
@@ -23427,9 +24306,9 @@ function getExt(src) {
|
|
|
23427
24306
|
};
|
|
23428
24307
|
}
|
|
23429
24308
|
|
|
23430
|
-
var root_1$
|
|
24309
|
+
var root_1$3 = template(`<img alt="画像のプレビュー" loading="lazy" class="svelte-1zu56m">`);
|
|
23431
24310
|
var root_3$2 = template(`<video playsinline="" class="svelte-1zu56m"><source> <track kind="captions" src=""> <!></video>`, 2);
|
|
23432
|
-
var root$
|
|
24311
|
+
var root$5 = template(`<span data-bge-editor-ui-component="thumbnail" class="svelte-1zu56m"><!></span>`);
|
|
23433
24312
|
|
|
23434
24313
|
function Thumbnail($$anchor, $$props) {
|
|
23435
24314
|
push($$props, false);
|
|
@@ -23440,12 +24319,12 @@ function Thumbnail($$anchor, $$props) {
|
|
|
23440
24319
|
|
|
23441
24320
|
init();
|
|
23442
24321
|
|
|
23443
|
-
var span = root$
|
|
24322
|
+
var span = root$5();
|
|
23444
24323
|
var node = child(span);
|
|
23445
24324
|
|
|
23446
24325
|
{
|
|
23447
24326
|
var consequent = ($$anchor) => {
|
|
23448
|
-
var img = root_1$
|
|
24327
|
+
var img = root_1$3();
|
|
23449
24328
|
|
|
23450
24329
|
template_effect(() => set_attribute(img, 'src', src()));
|
|
23451
24330
|
event('load', img, () => set(isLoaded, true));
|
|
@@ -23581,7 +24460,7 @@ var root_5$1 = template(`<span class="svelte-15rcfwg">アップロード中... <
|
|
|
23581
24460
|
var root_6 = template(`<span class="attr svelte-15rcfwg"><span class="svelte-15rcfwg">ID</span><span class="svelte-15rcfwg"><!></span> <span class="svelte-15rcfwg">名称</span><span class="svelte-15rcfwg"><!></span> <span class="svelte-15rcfwg">更新</span><span class="svelte-15rcfwg"> </span> <span class="svelte-15rcfwg">サイズ</span><span class="svelte-15rcfwg"> </span></span>`);
|
|
23582
24461
|
var root_7$1 = template(`<button class="delete svelte-15rcfwg" type="button">削除</button>`);
|
|
23583
24462
|
var root_4 = template(`<li class="svelte-15rcfwg"><button class="file svelte-15rcfwg" type="button"><span class="thumbnail svelte-15rcfwg"><!></span> <!></button> <!></li>`);
|
|
23584
|
-
var root$
|
|
24463
|
+
var root$4 = template(`<div class="ctrl svelte-15rcfwg"><div class="pagination svelte-15rcfwg"><button type="button" class="svelte-15rcfwg">前へ</button> <div class="page svelte-15rcfwg"><span><input type="number" min="1" aria-label="ページ番号"></span> <span>/</span> <span> </span></div> <button type="button" class="svelte-15rcfwg">次へ</button></div> <input type="search" placeholder="検索"></div> <ul class="list svelte-15rcfwg"></ul>`, 1);
|
|
23585
24464
|
|
|
23586
24465
|
function File_list($$anchor, $$props) {
|
|
23587
24466
|
push($$props, false);
|
|
@@ -23763,7 +24642,7 @@ function File_list($$anchor, $$props) {
|
|
|
23763
24642
|
|
|
23764
24643
|
init();
|
|
23765
24644
|
|
|
23766
|
-
var fragment_2 = root$
|
|
24645
|
+
var fragment_2 = root$4();
|
|
23767
24646
|
var div = first_child(fragment_2);
|
|
23768
24647
|
var div_1 = child(div);
|
|
23769
24648
|
var button = child(div_1);
|
|
@@ -23887,7 +24766,7 @@ function File_list($$anchor, $$props) {
|
|
|
23887
24766
|
pop();
|
|
23888
24767
|
}
|
|
23889
24768
|
|
|
23890
|
-
var root$
|
|
24769
|
+
var root$3 = template(`<div><input type="file" class="svelte-1kuhunj"> <button type="button">ファイルを追加アップロードする</button></div>`);
|
|
23891
24770
|
|
|
23892
24771
|
function File_uploader($$anchor, $$props) {
|
|
23893
24772
|
push($$props, false);
|
|
@@ -23940,7 +24819,7 @@ function File_uploader($$anchor, $$props) {
|
|
|
23940
24819
|
|
|
23941
24820
|
init();
|
|
23942
24821
|
|
|
23943
|
-
var div = root$
|
|
24822
|
+
var div = root$3();
|
|
23944
24823
|
var input = child(div);
|
|
23945
24824
|
|
|
23946
24825
|
set_attribute(input, 'accept', accept);
|
|
@@ -23953,7 +24832,7 @@ function File_uploader($$anchor, $$props) {
|
|
|
23953
24832
|
pop();
|
|
23954
24833
|
}
|
|
23955
24834
|
|
|
23956
|
-
var root_1$
|
|
24835
|
+
var root_1$2 = template(`<img alt="画像プレビュー" class="svelte-1ie51m5">`);
|
|
23957
24836
|
var root_3 = template(`<video controls playsinline="" class="svelte-1ie51m5"><source> <track kind="captions" src=""></video>`, 2);
|
|
23958
24837
|
var root_5 = template(`<audio controls class="svelte-1ie51m5"><source> <track kind="metadata" src=""></audio>`);
|
|
23959
24838
|
var root_7 = template(`<object class="svelte-1ie51m5"><p class="svelte-1ie51m5">プレビューできません</p></object>`);
|
|
@@ -23962,7 +24841,7 @@ var root_9 = template(`<div class="progress svelte-1ie51m5"></div>`);
|
|
|
23962
24841
|
var root_10 = template(`<li class="upload svelte-1ie51m5"><span>アップロード...</span> <span class="progress svelte-1ie51m5"> </span></li>`);
|
|
23963
24842
|
var root_11 = template(`<li class="path svelte-1ie51m5"><a target="_blank" class="svelte-1ie51m5"> </a></li>`);
|
|
23964
24843
|
var root_12 = template(`<li class="dimension svelte-1ie51m5"> </li>`);
|
|
23965
|
-
var root$
|
|
24844
|
+
var root$2 = template(`<div><div><!> <!></div> <ul class="svelte-1ie51m5"><!> <!></ul></div>`);
|
|
23966
24845
|
|
|
23967
24846
|
function Preview($$anchor, $$props) {
|
|
23968
24847
|
push($$props, false);
|
|
@@ -24028,14 +24907,14 @@ function Preview($$anchor, $$props) {
|
|
|
24028
24907
|
legacy_pre_effect_reset();
|
|
24029
24908
|
init();
|
|
24030
24909
|
|
|
24031
|
-
var div = root$
|
|
24910
|
+
var div = root$2();
|
|
24032
24911
|
var div_1 = child(div);
|
|
24033
24912
|
let classes;
|
|
24034
24913
|
var node = child(div_1);
|
|
24035
24914
|
|
|
24036
24915
|
{
|
|
24037
24916
|
var consequent = ($$anchor) => {
|
|
24038
|
-
var img = root_1$
|
|
24917
|
+
var img = root_1$2();
|
|
24039
24918
|
|
|
24040
24919
|
template_effect(() => set_attribute(img, 'src', get(selectedPath)));
|
|
24041
24920
|
append($$anchor, img);
|
|
@@ -24247,8 +25126,8 @@ function Arrows_transfer_down($$anchor, $$props) {
|
|
|
24247
25126
|
}));
|
|
24248
25127
|
}
|
|
24249
25128
|
|
|
24250
|
-
var root_1 = template(`<div class="row svelte-37o4yi"><div class="th"><textarea class="svelte-37o4yi"></textarea></div> <div class="td"><textarea class="svelte-37o4yi"></textarea></div> <div class="btn svelte-37o4yi"><ul class="svelte-37o4yi"><li class="svelte-37o4yi"><button type="button" title="下に追加"><!></button></li> <li class="svelte-37o4yi"><button type="button" title="削除"><!></button></li> <li class="svelte-37o4yi"><button type="button" title="下に移動"><!></button></li></ul></div></div>`);
|
|
24251
|
-
var root = template(`<div class="table svelte-37o4yi"></div>`);
|
|
25129
|
+
var root_1$1 = template(`<div class="row svelte-37o4yi"><div class="th"><textarea class="svelte-37o4yi"></textarea></div> <div class="td"><textarea class="svelte-37o4yi"></textarea></div> <div class="btn svelte-37o4yi"><ul class="svelte-37o4yi"><li class="svelte-37o4yi"><button type="button" title="下に追加"><!></button></li> <li class="svelte-37o4yi"><button type="button" title="削除"><!></button></li> <li class="svelte-37o4yi"><button type="button" title="下に移動"><!></button></li></ul></div></div>`);
|
|
25130
|
+
var root$1 = template(`<div class="table svelte-37o4yi"></div>`);
|
|
24252
25131
|
|
|
24253
25132
|
function Table_editor($$anchor, $$props) {
|
|
24254
25133
|
push($$props, false);
|
|
@@ -24317,10 +25196,10 @@ function Table_editor($$anchor, $$props) {
|
|
|
24317
25196
|
|
|
24318
25197
|
init();
|
|
24319
25198
|
|
|
24320
|
-
var div = root();
|
|
25199
|
+
var div = root$1();
|
|
24321
25200
|
|
|
24322
25201
|
each(div, 5, () => get(table), index, ($$anchor, row, i) => {
|
|
24323
|
-
var div_1 = root_1();
|
|
25202
|
+
var div_1 = root_1$1();
|
|
24324
25203
|
var div_2 = child(div_1);
|
|
24325
25204
|
var textarea = child(div_2);
|
|
24326
25205
|
set_attribute(textarea, 'aria-label', `${i}行目の見出しセル`);
|
|
@@ -24384,6 +25263,138 @@ function Table_editor($$anchor, $$props) {
|
|
|
24384
25263
|
}
|
|
24385
25264
|
|
|
24386
25265
|
delegate(['input', 'click']);
|
|
25266
|
+
|
|
25267
|
+
function Circle_plus($$anchor, $$props) {
|
|
25268
|
+
const $$sanitized_props = legacy_rest_props($$props, [
|
|
25269
|
+
'children',
|
|
25270
|
+
'$$slots',
|
|
25271
|
+
'$$events',
|
|
25272
|
+
'$$legacy'
|
|
25273
|
+
]);
|
|
25274
|
+
|
|
25275
|
+
const iconNode = [
|
|
25276
|
+
[
|
|
25277
|
+
"path",
|
|
25278
|
+
{ "d": "M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" }
|
|
25279
|
+
],
|
|
25280
|
+
["path", { "d": "M9 12h6" }],
|
|
25281
|
+
["path", { "d": "M12 9v6" }]
|
|
25282
|
+
];
|
|
25283
|
+
|
|
25284
|
+
Icon($$anchor, spread_props({ type: 'outline', name: 'circle-plus' }, () => $$sanitized_props, {
|
|
25285
|
+
iconNode,
|
|
25286
|
+
children: ($$anchor, $$slotProps) => {
|
|
25287
|
+
var fragment_1 = comment();
|
|
25288
|
+
var node = first_child(fragment_1);
|
|
25289
|
+
|
|
25290
|
+
slot(node, $$props, 'default', {});
|
|
25291
|
+
append($$anchor, fragment_1);
|
|
25292
|
+
},
|
|
25293
|
+
$$slots: { default: true }
|
|
25294
|
+
}));
|
|
25295
|
+
}
|
|
25296
|
+
|
|
25297
|
+
const onKeyDown = (event, update, currentIndex, length) => {
|
|
25298
|
+
if (event.key === 'ArrowLeft') {
|
|
25299
|
+
update(Math.max(0, get(currentIndex) - 1));
|
|
25300
|
+
} else if (event.key === 'ArrowRight') {
|
|
25301
|
+
update(Math.min(length - 1, get(currentIndex) + 1));
|
|
25302
|
+
} else {
|
|
25303
|
+
return;
|
|
25304
|
+
}
|
|
25305
|
+
};
|
|
25306
|
+
|
|
25307
|
+
var on_click = (__1, onClick, index) => onClick(get(index));
|
|
25308
|
+
var root_1 = template(`<button type="button" role="tab" class="svelte-2oedib"> </button>`);
|
|
25309
|
+
var on_click_1 = () => {};
|
|
25310
|
+
var root = template(`<div role="tablist" class="svelte-2oedib"><!> <button class="add-tab svelte-2oedib" type="button" title="タブを追加"><!></button></div>`);
|
|
25311
|
+
|
|
25312
|
+
function Tabs($$anchor, $$props) {
|
|
25313
|
+
push($$props, false);
|
|
25314
|
+
|
|
25315
|
+
let engine = prop($$props, 'engine', 8);
|
|
25316
|
+
let contentId = prop($$props, 'contentId', 8);
|
|
25317
|
+
const refs = mutable_source([]);
|
|
25318
|
+
let tabPanel = null;
|
|
25319
|
+
const length = 2;
|
|
25320
|
+
let currentIndex = mutable_source(0);
|
|
25321
|
+
|
|
25322
|
+
engine().componentObserver.on('select-tab-in-item-editor', ({ index }) => {
|
|
25323
|
+
set(currentIndex, index);
|
|
25324
|
+
get(refs)[get(currentIndex)]?.focus();
|
|
25325
|
+
});
|
|
25326
|
+
|
|
25327
|
+
const onClick = (index) => {
|
|
25328
|
+
update(index);
|
|
25329
|
+
};
|
|
25330
|
+
|
|
25331
|
+
/**
|
|
25332
|
+
*
|
|
25333
|
+
* @param index
|
|
25334
|
+
*/
|
|
25335
|
+
function createLabel(index) {
|
|
25336
|
+
return `画像${index + 1}`;
|
|
25337
|
+
}
|
|
25338
|
+
|
|
25339
|
+
/**
|
|
25340
|
+
*
|
|
25341
|
+
* @param index
|
|
25342
|
+
*/
|
|
25343
|
+
function update(index) {
|
|
25344
|
+
set(currentIndex, index);
|
|
25345
|
+
get(refs)[get(currentIndex)]?.focus();
|
|
25346
|
+
engine().componentObserver.notify('select-tab-in-item-editor', { index: get(currentIndex) });
|
|
25347
|
+
tabPanel?.setAttribute('aria-label', createLabel(get(currentIndex)));
|
|
25348
|
+
}
|
|
25349
|
+
|
|
25350
|
+
onMount(() => {
|
|
25351
|
+
tabPanel = document.getElementById(contentId());
|
|
25352
|
+
|
|
25353
|
+
if (!tabPanel) {
|
|
25354
|
+
throw new Error('Tab panel not found');
|
|
25355
|
+
}
|
|
25356
|
+
});
|
|
25357
|
+
|
|
25358
|
+
init();
|
|
25359
|
+
|
|
25360
|
+
var div = root();
|
|
25361
|
+
var node = child(div);
|
|
25362
|
+
|
|
25363
|
+
each(node, 1, () => Array.from({ length }, (_, index) => index), (index) => index, ($$anchor, index) => {
|
|
25364
|
+
var button = root_1();
|
|
25365
|
+
|
|
25366
|
+
button.__click = [on_click, onClick, index];
|
|
25367
|
+
button.__keydown = [onKeyDown, update, currentIndex, length];
|
|
25368
|
+
|
|
25369
|
+
var text = child(button);
|
|
25370
|
+
bind_this(button, ($$value, index) => mutate(refs, get(refs)[index] = $$value), (index) => get(refs)?.[index], () => [get(index)]);
|
|
25371
|
+
|
|
25372
|
+
template_effect(
|
|
25373
|
+
($0) => {
|
|
25374
|
+
set_attribute(button, 'aria-controls', contentId());
|
|
25375
|
+
set_attribute(button, 'aria-selected', get(currentIndex) === get(index));
|
|
25376
|
+
set_attribute(button, 'tabindex', get(currentIndex) === get(index) ? 0 : -1);
|
|
25377
|
+
set_text(text, $0);
|
|
25378
|
+
},
|
|
25379
|
+
[() => createLabel(get(index))],
|
|
25380
|
+
derived_safe_equal
|
|
25381
|
+
);
|
|
25382
|
+
|
|
25383
|
+
append($$anchor, button);
|
|
25384
|
+
});
|
|
25385
|
+
|
|
25386
|
+
var button_1 = sibling(node, 2);
|
|
25387
|
+
|
|
25388
|
+
button_1.__click = [on_click_1];
|
|
25389
|
+
|
|
25390
|
+
var node_1 = child(button_1);
|
|
25391
|
+
|
|
25392
|
+
Circle_plus(node_1, {});
|
|
25393
|
+
append($$anchor, div);
|
|
25394
|
+
pop();
|
|
25395
|
+
}
|
|
25396
|
+
|
|
25397
|
+
delegate(['click', 'keydown']);
|
|
24387
25398
|
async function createBurgerEditorClient(options) {
|
|
24388
25399
|
const engine = await BurgerEditorEngine.new({
|
|
24389
25400
|
...options,
|
|
@@ -24456,6 +25467,19 @@ async function createBurgerEditorClient(options) {
|
|
|
24456
25467
|
}
|
|
24457
25468
|
});
|
|
24458
25469
|
},
|
|
25470
|
+
tabs: (el, engine2) => {
|
|
25471
|
+
const contentId = el.dataset.bgeEditorUiFor;
|
|
25472
|
+
if (!contentId) {
|
|
25473
|
+
throw new Error("Tab UI component requires contentId attribute");
|
|
25474
|
+
}
|
|
25475
|
+
return svelteMount(Tabs, {
|
|
25476
|
+
target: el,
|
|
25477
|
+
props: {
|
|
25478
|
+
engine: engine2,
|
|
25479
|
+
contentId
|
|
25480
|
+
}
|
|
25481
|
+
});
|
|
25482
|
+
},
|
|
24459
25483
|
tableEditor: (el, engine2) => {
|
|
24460
25484
|
return svelteMount(Table_editor, {
|
|
24461
25485
|
target: el,
|