UNPKG

@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

150 lines 6.67 kB
import { logDebug } from '../../lib/Logger'; import { InsertPositionPlacement, } from '../../lib/IFrameCommunicatorTypes'; import { DataAttribute } from './attributes'; import { getHighlightTypeForElement, HighlightType } from './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. */ export function parseEditButtonDataAttributes(target) { const type = getHighlightTypeForElement(target); const pattern = getEditButtonDataAttributesPattern(type); logDebug('Parsing edit button data attributes for element: ', target); logDebug('Parsing values from data attributes using this pattern: ', pattern); return 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. */ export function parseAddButtonDataAttributes(target) { const position = target.getAttribute(DataAttribute.AddButtonInsertPosition); const pattern = getAddButtonDataAttributesPattern(position); logDebug('Parsing add button data attributes for element: ', target); logDebug('Parsing values from data attributes following this pattern: ', pattern); return parseDataAttributes(pattern, target); } function getEditButtonDataAttributesPattern(type) { switch (type) { case HighlightType.Element: return elementEditButtonParserPattern; case HighlightType.ContentComponent: return componentEditButtonParserPattern; case HighlightType.ContentItem: return itemEditButtonParserPattern; default: return baseParserPattern; } } function getAddButtonDataAttributesPattern(position) { switch (position) { case InsertPositionPlacement.After: case InsertPositionPlacement.Before: return relativeAddButtonParserPattern; case InsertPositionPlacement.End: case InsertPositionPlacement.Start: 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; } export const parseDataAttributes = (pattern, element) => { if (!element || pattern.length === 0) { return { parsed: {}, debugData: [] }; } const parsedValues = Object.values(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 = 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, 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, })), }, ] : []), ], }; }; const baseParserPattern = [ { key: 'languageCodename', dataAttributes: [DataAttribute.LanguageCodename] }, { key: 'environmentId', dataAttributes: [DataAttribute.EnvironmentId] }, ]; // EDIT BUTTON PARSING PATTERNS const itemEditButtonParserPattern = [ { key: 'itemId', dataAttributes: [DataAttribute.ItemId] }, ...baseParserPattern, ]; const componentEditButtonParserPattern = [ { key: 'contentComponentId', dataAttributes: [DataAttribute.ComponentId] }, ...itemEditButtonParserPattern, ]; const elementEditButtonParserPattern = [ { key: 'elementCodename', dataAttributes: [DataAttribute.ElementCodename] }, { key: 'contentComponentId', dataAttributes: [DataAttribute.ComponentId], optional: true }, ...itemEditButtonParserPattern, ]; // ADD BUTTON PARSING PATTERNS const baseAddButtonParserPattern = [ { key: 'elementCodename', dataAttributes: [DataAttribute.ElementCodename] }, { key: 'contentComponentId', dataAttributes: [DataAttribute.ComponentId], optional: true }, { key: 'itemId', dataAttributes: [DataAttribute.ItemId] }, ...baseParserPattern, ]; const relativeAddButtonParserPattern = [ { key: 'placement', dataAttributes: [DataAttribute.AddButtonInsertPosition] }, { key: 'targetId', dataAttributes: [DataAttribute.ComponentId, DataAttribute.ItemId] }, ...baseAddButtonParserPattern, ]; const fixedAddButtonParserPattern = [ { key: 'placement', dataAttributes: [DataAttribute.AddButtonInsertPosition], optional: true }, ...baseAddButtonParserPattern, ]; //# sourceMappingURL=parser.js.map