@kontent-ai/smart-link
Version:
Kontent.ai Smart Link SDK allowing to automatically inject [smart links](https://docs.kontent.ai/tutorials/develop-apps/build-strong-foundation/set-up-editing-from-preview#a-using-smart-links) to Kontent.ai according to manually specified [HTML data attri
159 lines • 7.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseDataAttributes = void 0;
exports.parseEditButtonDataAttributes = parseEditButtonDataAttributes;
exports.parseAddButtonDataAttributes = parseAddButtonDataAttributes;
const IFrameCommunicatorTypes_1 = require("../../lib/IFrameCommunicatorTypes");
const Logger_1 = require("../../lib/Logger");
const errors_1 = require("../errors");
const attributes_1 = require("./attributes");
const elementHighlight_1 = require("./elementHighlight");
/**
* Parses data attributes from an HTML element to extract edit button information.
* The function determines the type of element being edited (element, component, or item)
* and extracts relevant data attributes based on that type.
*/
function parseEditButtonDataAttributes(target) {
const type = (0, elementHighlight_1.getHighlightTypeForElement)(target);
const pattern = getEditButtonDataAttributesPattern(type);
(0, Logger_1.logDebug)("Parsing edit button data attributes for element: ", target);
(0, Logger_1.logDebug)("Parsing values from data attributes using this pattern: ", pattern);
return (0, exports.parseDataAttributes)(pattern, target);
}
/**
* Parses data attributes from an HTML element to extract add button information.
* The function determines the insert position type (fixed or relative) and extracts
* relevant data attributes based on that type.
*/
function parseAddButtonDataAttributes(target) {
const position = target.getAttribute(attributes_1.DataAttribute.AddButtonInsertPosition);
const pattern = getAddButtonDataAttributesPattern(position);
(0, Logger_1.logDebug)("Parsing add button data attributes for element: ", target);
(0, Logger_1.logDebug)("Parsing values from data attributes following this pattern: ", pattern);
return (0, exports.parseDataAttributes)(pattern, target);
}
function getEditButtonDataAttributesPattern(type) {
switch (type) {
case elementHighlight_1.HighlightType.Element:
return elementEditButtonParserPattern;
case elementHighlight_1.HighlightType.ContentComponent:
return componentEditButtonParserPattern;
case elementHighlight_1.HighlightType.ContentItem:
return itemEditButtonParserPattern;
case elementHighlight_1.HighlightType.None:
return baseParserPattern;
}
}
function getAddButtonDataAttributesPattern(position) {
switch (position) {
case IFrameCommunicatorTypes_1.InsertPositionPlacement.After:
case IFrameCommunicatorTypes_1.InsertPositionPlacement.Before:
return relativeAddButtonParserPattern;
default:
return fixedAddButtonParserPattern;
}
}
/**
* Creates result from found data attributes on an element.
* This function follow rules:
* - If token is found, it is added to the result
* - If token is not found or the data attribute is already taken, but is optional, it is skipped
* - If token is not found, and is required, the function stops searching as higher precedence tokens cannot be found
*/
function applyPatternToParsedValues(pattern, parsedValues) {
const takenDataAttributes = new Set();
const result = [];
for (const p of pattern) {
const data = parsedValues.find((a) => p.dataAttributes.includes(a.dataAttribute) && !takenDataAttributes.has(a.dataAttribute));
if (!data && p.optional) {
continue;
}
if (!data) {
break;
}
takenDataAttributes.add(data.dataAttribute);
result.push({ token: p.key, value: data.value, dataAttribute: data.dataAttribute });
}
return result;
}
const parseDataAttributes = (pattern, element) => {
if (!element || pattern.length === 0) {
return { parsed: {}, debugData: [] };
}
const parsedValues = Object.values(attributes_1.DataAttribute)
.map((a) => {
const value = element.getAttribute(a);
return value ? { dataAttribute: a, value } : null;
})
.filter((a) => a !== null);
const result = applyPatternToParsedValues(pattern, parsedValues);
const lastFoundTokenIndex = pattern.findIndex((p) => p.key === result.at(-1)?.token);
const newPattern = pattern.slice(lastFoundTokenIndex + 1);
const parentResult = (0, exports.parseDataAttributes)(newPattern, element.parentElement);
return {
parsed: {
...Object.fromEntries(result.map((r) => [r.token, r.value])),
...parentResult.parsed,
},
debugData: [
...parentResult.debugData,
...(parsedValues.length > 0
? [
{
element,
parsedAttributes: parsedValues
.filter((a) => result.find((r) => r.dataAttribute === a.dataAttribute) !== undefined)
.map((a) => ({
token: result.find((r) => r.dataAttribute === a.dataAttribute)?.token ??
(0, errors_1.throwError)("[Parser]: Token not found"),
dataAttribute: a.dataAttribute,
value: a.value,
})),
skippedAttributes: parsedValues
.filter((a) => result.find((r) => r.dataAttribute === a.dataAttribute) === undefined)
.map((a) => ({
dataAttribute: a.dataAttribute,
value: a.value,
})),
},
]
: []),
],
};
};
exports.parseDataAttributes = parseDataAttributes;
const baseParserPattern = [
{ key: "languageCodename", dataAttributes: [attributes_1.DataAttribute.LanguageCodename] },
{ key: "environmentId", dataAttributes: [attributes_1.DataAttribute.EnvironmentId] },
];
// EDIT BUTTON PARSING PATTERNS
const itemEditButtonParserPattern = [
{ key: "itemId", dataAttributes: [attributes_1.DataAttribute.ItemId] },
...baseParserPattern,
];
const componentEditButtonParserPattern = [
{ key: "contentComponentId", dataAttributes: [attributes_1.DataAttribute.ComponentId] },
...itemEditButtonParserPattern,
];
const elementEditButtonParserPattern = [
{ key: "elementCodename", dataAttributes: [attributes_1.DataAttribute.ElementCodename] },
{ key: "contentComponentId", dataAttributes: [attributes_1.DataAttribute.ComponentId], optional: true },
...itemEditButtonParserPattern,
];
// ADD BUTTON PARSING PATTERNS
const baseAddButtonParserPattern = [
{ key: "elementCodename", dataAttributes: [attributes_1.DataAttribute.ElementCodename] },
{ key: "contentComponentId", dataAttributes: [attributes_1.DataAttribute.ComponentId], optional: true },
{ key: "itemId", dataAttributes: [attributes_1.DataAttribute.ItemId] },
...baseParserPattern,
];
const relativeAddButtonParserPattern = [
{ key: "placement", dataAttributes: [attributes_1.DataAttribute.AddButtonInsertPosition] },
{ key: "targetId", dataAttributes: [attributes_1.DataAttribute.ComponentId, attributes_1.DataAttribute.ItemId] },
...baseAddButtonParserPattern,
];
const fixedAddButtonParserPattern = [
{ key: "placement", dataAttributes: [attributes_1.DataAttribute.AddButtonInsertPosition], optional: true },
...baseAddButtonParserPattern,
];
//# sourceMappingURL=parser.js.map