Files
qiming/qiming-vite-plugin-design-mode/packages/client-shared/src/attributeNames.ts
2026-06-01 13:43:09 +08:00

108 lines
2.6 KiB
TypeScript

/**
* Resolved `data-*` names for source mapping (prefix from global config or meta tag).
*/
const DEFAULT_PREFIX = 'data-xagi';
function getAttributePrefix(): string {
if (typeof window !== 'undefined') {
const globalConfig = (window as any).__APPDEV_DESIGN_MODE_CONFIG__;
if (globalConfig?.attributePrefix) {
return globalConfig.attributePrefix;
}
const metaTag = document.querySelector('meta[name="appdev-design-mode:attribute-prefix"]');
if (metaTag) {
const prefix = metaTag.getAttribute('content');
if (prefix) {
return prefix;
}
}
}
return DEFAULT_PREFIX;
}
/** Cached prefix */
let cachedPrefix: string | null = null;
/** e.g. `data-xagi` */
export function getPrefix(): string {
if (cachedPrefix === null) {
cachedPrefix = getAttributePrefix();
}
return cachedPrefix;
}
/** Call after changing `window.__APPDEV_DESIGN_MODE_CONFIG__` in tests. */
export function resetPrefixCache(): void {
cachedPrefix = null;
}
/** `{prefix}-{suffix}` */
export function getAttributeName(suffix: string): string {
const prefix = getPrefix();
return `${prefix}-${suffix}`;
}
/** Lazy getters so prefix changes propagate */
export const AttributeNames = {
get file() {
return getAttributeName('file');
},
get line() {
return getAttributeName('line');
},
get column() {
return getAttributeName('column');
},
get info() {
return getAttributeName('info');
},
get elementId() {
return getAttributeName('element-id');
},
get component() {
return getAttributeName('component');
},
get function() {
return getAttributeName('function');
},
get position() {
return getAttributeName('position');
},
get staticContent() {
return getAttributeName('static-content');
},
/**
* Get the children source attribute name (for tracking where static children come from)
* Example: data-xagi-children-source
*/
get childrenSource() {
return getAttributeName('children-source');
},
get contextMenu() {
return getAttributeName('context-menu');
},
get contextMenuHover() {
return getAttributeName('context-menu-hover');
},
get import() {
return getAttributeName('import');
},
/**
* Get the static-class attribute name (for tracking if className is a pure static string)
* Example: data-xagi-static-class
*/
get staticClass() {
return getAttributeName('static-class');
},
} as const;
/** True for any `{prefix}-*` */
export function isSourceMappingAttribute(attributeName: string): boolean {
const prefix = getPrefix();
return attributeName.startsWith(`${prefix}-`);
}