@silexlabs/grapesjs-symbols
Version:
Symbols for GrapesJS
167 lines • 6.71 kB
JavaScript
;
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeInstanceIdsUnique = makeInstanceIdsUnique;
/**
* Attributes that can contain references to element IDs.
* These should be updated when IDs are made unique.
*/
var ID_REFERENCE_ATTRIBUTES = [
'for', // <label for="...">
'aria-labelledby', // ARIA: labels
'aria-describedby', // ARIA: descriptions
'aria-controls', // ARIA: controls
'aria-owns', // ARIA: ownership
'aria-activedescendant', // ARIA: active descendant
'aria-flowto', // ARIA: flow
'aria-errormessage', // ARIA: error message
'list', // <input list="..."> for datalist
'form', // <input form="..."> for form association
'headers', // <td headers="..."> for table headers
];
/**
* Attributes that contain ID references prefixed with #
*/
var HASH_ID_ATTRIBUTES = [
'href', // <a href="#id">
'data-target', // Bootstrap 4: data-target="#id"
'data-bs-target', // Bootstrap 5: data-bs-target="#id"
];
/**
* Helper to get all components under a root component in depth-first order.
*/
function flattenComponents(root) {
var components = [];
root.onAll(function (c) { return components.push(c); });
return components;
}
/**
* Build a map from main symbol component IDs to instance component IDs
* Uses component order to correlate since both have the same structure
*/
function buildIdMap(mainSymbol, instance) {
var idMap = new Map();
var mainComponents = flattenComponents(mainSymbol);
var instanceComponents = flattenComponents(instance);
var n = Math.min(mainComponents.length, instanceComponents.length);
for (var i = 0; i < n; i++) {
var mainId = mainComponents[i].getAttributes().id;
var instanceId = instanceComponents[i].getAttributes().id;
if (mainId && instanceId) {
idMap.set(mainId, instanceId);
}
}
return idMap;
}
/**
* Collect all ID reference values from the main symbol.
* Returns a map of: referenced ID -> list of {component index, attribute name, isHash}
*/
function collectIdReferences(mainSymbol) {
var refs = new Map();
flattenComponents(mainSymbol).forEach(function (component, index) {
var attrs = component.getAttributes();
var _loop_1 = function (attr) {
var value = attrs[attr];
if (typeof value === 'string' && value) {
var ids = value.split(/\s+/);
ids.forEach(function (id) {
if (!refs.has(id))
refs.set(id, []);
refs.get(id).push({ index: index, attr: attr, isHash: false });
});
}
};
// Check direct ID references
for (var _i = 0, ID_REFERENCE_ATTRIBUTES_1 = ID_REFERENCE_ATTRIBUTES; _i < ID_REFERENCE_ATTRIBUTES_1.length; _i++) {
var attr = ID_REFERENCE_ATTRIBUTES_1[_i];
_loop_1(attr);
}
// Check hash-prefixed ID references
for (var _a = 0, HASH_ID_ATTRIBUTES_1 = HASH_ID_ATTRIBUTES; _a < HASH_ID_ATTRIBUTES_1.length; _a++) {
var attr = HASH_ID_ATTRIBUTES_1[_a];
var value = attrs[attr];
if (typeof value === 'string' && value.startsWith('#')) {
var id = value.substring(1);
if (!refs.has(id))
refs.set(id, []);
refs.get(id).push({ index: index, attr: attr, isHash: true });
}
}
});
return refs;
}
/**
* Update ID references in a symbol instance to match the new unique IDs.
*
* This function:
* 1. Gets the main symbol for this instance
* 2. Builds a map of main symbol IDs -> instance IDs
* 3. Finds all ID references in the main symbol (for, aria-*, href="#...", etc.)
* 4. Updates those references in the instance to use the new IDs
*
* @param editor - The GrapesJS editor instance
* @param instance - The root component of the symbol instance
*/
function makeInstanceIdsUnique(editor, instance) {
var symbolInfo = editor.Components.getSymbolInfo(instance);
if (!(symbolInfo === null || symbolInfo === void 0 ? void 0 : symbolInfo.main))
return;
var mainSymbol = symbolInfo.main;
var idMap = buildIdMap(mainSymbol, instance);
if (idMap.size === 0)
return;
var refs = collectIdReferences(mainSymbol);
var instanceComponents = flattenComponents(instance);
refs.forEach(function (refList, referencedId) {
// Prefer exact match, fallback to prefix match (e.g., for GrapesJS suffixes)
var newId;
idMap.forEach(function (instanceId, mainId) {
if (mainId === referencedId || mainId.startsWith(referencedId + '-')) {
newId = instanceId;
}
});
if (!newId)
return;
refList.forEach(function (ref) {
var _a;
var component = instanceComponents[ref.index];
if (!component)
return;
var attrs = component.getAttributes();
var currentValue = attrs[ref.attr];
var newValue;
if (ref.isHash) {
newValue = "#".concat(newId);
}
else if (typeof currentValue === 'string' && currentValue.includes(' ')) {
// Handle space-separated list of IDs
newValue = currentValue
.split(/\s+/)
.map(function (id) { return id === referencedId ? newId : id; })
.join(' ');
}
else {
newValue = newId;
}
// Temporarily add symbol override for attributes, then set attribute, then restore overrides
var overrides = component.getSymbolOverride() || [];
var overridesArray = Array.isArray(overrides) ? overrides : [];
var hasAttrOverride = overridesArray.includes('attributes');
if (!hasAttrOverride)
component.setSymbolOverride(__spreadArray(__spreadArray([], overridesArray, true), ['attributes'], false));
component.setAttributes((_a = {}, _a[ref.attr] = newValue, _a));
if (!hasAttrOverride)
component.setSymbolOverride(overrides);
});
});
}
//# sourceMappingURL=id-utils.js.map