mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 10:40:58 +00:00
106 lines
3.3 KiB
TypeScript
106 lines
3.3 KiB
TypeScript
/**
|
|
* Pure CSS utility functions for TemplateSampleForm.
|
|
* Extracted here to keep the main form component under 300 lines.
|
|
*/
|
|
|
|
/** Normalize list-style CSS properties — preserves special values like disclosure-closed */
|
|
export function normalizeListStyleProps(
|
|
obj: Record<string, string>,
|
|
): Record<string, string> {
|
|
const normalized = { ...obj };
|
|
const specialListStyles = ["disclosure-closed", "disclosure-open", "none"];
|
|
|
|
if (normalized["list-style"]) {
|
|
const listStyleValue = normalized["list-style"].split(" ")[0];
|
|
if (specialListStyles.includes(listStyleValue)) {
|
|
delete normalized["list-style-type"];
|
|
return normalized;
|
|
}
|
|
if (!normalized["list-style-type"]) {
|
|
normalized["list-style-type"] = listStyleValue;
|
|
}
|
|
}
|
|
|
|
if (normalized["list-style-type"] && !normalized["list-style"]) {
|
|
normalized["list-style"] = normalized["list-style-type"];
|
|
}
|
|
|
|
return normalized;
|
|
}
|
|
|
|
/** Serialize a style object to a CSS declaration string */
|
|
export function styleObjectToCss(style: Record<string, unknown>): string {
|
|
return Object.entries(style)
|
|
.filter(([, v]) => v !== null && v !== undefined && v !== "null" && v !== "")
|
|
.map(([k, v]) => `${k}: ${String(v)};`)
|
|
.join(" ");
|
|
}
|
|
|
|
/**
|
|
* Parse CSS declarations from a string, correctly handling data URIs
|
|
* (colons and semicolons inside url(...) are not treated as delimiters).
|
|
*/
|
|
export function parseCSSDeclarations(cssString: string): Array<[string, string]> {
|
|
const results: Array<[string, string]> = [];
|
|
let depth = 0;
|
|
let current = "";
|
|
|
|
for (let i = 0; i < cssString.length; i++) {
|
|
const ch = cssString[i];
|
|
if (ch === "(") depth++;
|
|
else if (ch === ")") depth--;
|
|
|
|
if (ch === ";" && depth === 0) {
|
|
current = current.trim();
|
|
if (current) {
|
|
const colonIdx = current.indexOf(":");
|
|
if (colonIdx > 0) {
|
|
const prop = current.slice(0, colonIdx).trim();
|
|
const val = current.slice(colonIdx + 1).trim();
|
|
if (prop && val) results.push([prop, val]);
|
|
}
|
|
}
|
|
current = "";
|
|
} else {
|
|
current += ch;
|
|
}
|
|
}
|
|
|
|
// Handle last declaration with no trailing semicolon
|
|
current = current.trim();
|
|
if (current) {
|
|
const colonIdx = current.indexOf(":");
|
|
if (colonIdx > 0) {
|
|
const prop = current.slice(0, colonIdx).trim();
|
|
const val = current.slice(colonIdx + 1).trim();
|
|
if (prop && val) results.push([prop, val]);
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
/** Convert a CSS string to a normalized style object (data-URI safe) */
|
|
export function cssStringToObject(cssString: string): Record<string, string> {
|
|
const obj: Record<string, string> = {};
|
|
parseCSSDeclarations(cssString).forEach(([prop, val]) => {
|
|
obj[prop] = val;
|
|
});
|
|
return normalizeListStyleProps(obj);
|
|
}
|
|
|
|
/** Convert a simple CSS string to a style object (no data-URI support) */
|
|
export function parseCSSStringToObject(cssString: string): Record<string, string> {
|
|
const obj: Record<string, string> = {};
|
|
cssString
|
|
.split(";")
|
|
.filter((d) => d.trim())
|
|
.forEach((declaration) => {
|
|
const [property, value] = declaration.split(":").map((s) => s.trim());
|
|
if (property && value) {
|
|
obj[property] = value;
|
|
}
|
|
});
|
|
return normalizeListStyleProps(obj);
|
|
}
|