import * as Conventions from './conventions.js' import type * as Style from '../index.js' import * as ClassList from './class-list.js' import * as Definitions from './definitions.js' /** Return human readable label for given element */ export function getContextLabel(context: Style.Context) { if (!context) return if (!('localName' in context) && (context.name == 'ui' || context.name == '$root')) { return 'Version' } return Conventions.getLabelByName(getContextName(context)) } /** Extract element name from a class name */ export function getContextImplicitName(context: Style.Context): string { return getClassName(context, false) .split(/\s/g) .map((className) => Conventions.getImplicitElementName(className)) .filter(Boolean)[0] } /** Guess HTML element's name by matching its tag name with the mapping of text and structural tags */ export function getContextTagName(context: Style.Context): string { if (!('localName' in context)) return context.name return Definitions.all.find((definition) => context.localName == definition.htmlTagName)?.name ?? null } export function getInstanceId(context: Style.Context): string { return context?.getAttribute('data-instance-id') ? String(context.getAttribute('data-instance-id')) : null } /** * Return element name in a CKEditor compatible format. Custom element names are not part of CKEditor data model, * instead they are a part of style guides. But the builder UI is expected to display custom element labels correctly. */ export function getContextName(context: Style.Context, resolveCustom = false) { if (context == null) return null if ('localName' in context) { return ( (resolveCustom && getContextCustomName(context)) || getContextImplicitName(context) || getContextTagName(context) || 'container' ) } else { return context.name } } /** Extract element custom name from class name (for blocks and inlines) */ export function getContextCustomName(context: Style.Context): string { return getClassName(context)?.match(/(?:\s|^)-(?:block|inline)--(.*?)(?:--|\s|$)/)?.[1] } /** * Get class name augmented with implicit class. * * @example * `
` => `-section abc` * `
` => `-section--special abc` */ export function getClassName(context: Style.Context, addImplicitClasses = true) { if (!context) return null const className = context?.getAttribute('class')?.toString() var classList = String(className || '') .split(/\s+/g) .filter(Boolean) // ensure instance id is added //const instanceId = getInstanceId(context) //if (instanceId != null) { // classList.unshift(`-id--${instanceId}`) //} // ensure element tag name class is added if (addImplicitClasses) { classList = ClassList.expand(classList, getContextName(context)) } return classList.join(' ') } export function reduceClassList(context: Style.Context, classList: string[], tagName: string = null) { const contextName = getContextName(context) const htmlTagName = tagName || context.getAttribute('as') || contextName const definition = Definitions.all.find((d) => d.name == contextName) const definitionTagName = contextName == 'container' ? 'div' : definition.htmlTagName const implicitClass = contextName == 'container' ? '-container' : definition.isImplicit ? definition.className : null return classList.filter((className) => { return (className != implicitClass || htmlTagName != definitionTagName) && !className.startsWith('-id--') }) }