Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 6x 544x 11x 533x 1032x 516x 554x 61x 30x 11x 1673x | /**
* Attribute Utilities
*
* Pure, stateless functions for formatting HTML attributes, escaping values,
* and converting between naming conventions (camelCase ↔ kebab-case).
* No dependency on UIF types or generation context.
*/
export type AttributeValue = string | boolean | number;
export const VOID_ELEMENTS = new Set([
'area',
'base',
'br',
'col',
'embed',
'hr',
'img',
'input',
'link',
'meta',
'param',
'source',
'track',
'wbr',
]);
/**
* Format a single HTML attribute as a key="value" string.
* Boolean true renders the attribute name alone; false returns null.
*/
export function formatAttribute(key: string, value: AttributeValue): string | null {
if (typeof value === 'boolean') {
return value ? key : null;
}
return `${key}="${escapeAttributeValue(String(value))}"`;
}
/**
* Format a bound attribute driven by an active state or modifier boolean.
* ARIA attributes (aria-*) require an explicit string value ("true"/"false"),
* while boolean HTML attributes (disabled, readonly, etc.) are presence-based.
* Returns null when the state is inactive.
*/
export function formatStateAttribute(key: string, active: boolean): string | null {
if (!active) return null;
return key.startsWith('aria-') ? `${key}="true"` : key;
}
/**
* Escape special characters in HTML attribute values.
*/
export function escapeAttributeValue(value: string): string {
return value
.replaceAll('&', '&')
.replaceAll('"', '"')
.replaceAll('<', '<')
.replaceAll('>', '>');
}
/**
* Convert a camelCase or PascalCase name to kebab-case.
* e.g., "iconName" → "icon-name", "ButtonIcon" → "button-icon"
*/
export function toKebabCase(name: string): string {
return name.replaceAll(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
}
/**
* Convert a PascalCase component name to an LBC custom element tag.
* e.g., "Icon" → "lightning-icon", "ButtonIcon" → "lightning-button-icon"
*/
export function toLbcTagName(componentName: string): string {
return `lightning-${toKebabCase(componentName)}`;
}
/**
* Convert a camelCase or PascalCase name to a human-readable label.
* e.g., "fieldLevelHelp" → "Field Level Help"
*/
export function humanize(name: string): string {
return name.replaceAll(/([a-z])([A-Z])/g, '$1 $2').replace(/^./, (s) => s.toUpperCase());
}
/**
* Produce an indentation string of the given depth (2 spaces per level).
*/
export function indent(levels: number): string {
return ' '.repeat(levels);
}
|