ttrpg-tools/src/components/md-deck/hooks/layer-parser.ts

74 lines
1.8 KiB
TypeScript
Raw Normal View History

2026-02-27 12:34:55 +08:00
import type { Layer, LayerConfig } from '../types';
2026-02-27 12:24:51 +08:00
/**
2026-02-28 11:50:57 +08:00
* layers
* body:1,7-5,8 title:1,1-4,1f6.6s
* f[fontSize]
2026-02-27 12:24:51 +08:00
*/
export function parseLayers(layersStr: string): Layer[] {
if (!layersStr) return [];
const layers: Layer[] = [];
2026-02-28 11:50:57 +08:00
// 匹配prop:x1,y1-x2,y2[ffontSize][direction]
const regex = /(\w+):(\d+),(\d+)-(\d+),(\d+)(?:f([\d.]+))?([nsew])?/g;
2026-02-27 12:24:51 +08:00
let match;
while ((match = regex.exec(layersStr)) !== null) {
layers.push({
prop: match[1],
x1: parseInt(match[2]),
y1: parseInt(match[3]),
x2: parseInt(match[4]),
2026-02-27 22:56:06 +08:00
y2: parseInt(match[5]),
2026-02-28 11:50:57 +08:00
fontSize: match[7] ? parseFloat(match[7]) : undefined,
orientation: match[8] as 'n' | 's' | 'e' | 'w' | undefined
2026-02-27 12:24:51 +08:00
});
}
return layers;
}
/**
* layers
*/
export function formatLayers(layers: LayerConfig[]): string {
return layers
.filter(l => l.visible)
2026-02-28 11:50:57 +08:00
.map(l => {
let str = `${l.prop}:${l.x1},${l.y1}-${l.x2},${l.y2}`;
if (l.fontSize) {
str += `f${l.fontSize}`;
}
if (l.orientation && l.orientation !== 'n') {
str += l.orientation;
}
return str;
})
2026-02-27 12:24:51 +08:00
.join(' ');
}
/**
*
*/
export function initLayerConfigs(
data: any[],
existingLayersStr: string
): LayerConfig[] {
const parsed = parseLayers(existingLayersStr);
const allProps = Object.keys(data[0] || {}).filter(k => k !== 'label');
2026-02-27 22:56:06 +08:00
2026-02-27 12:24:51 +08:00
return allProps.map(prop => {
const existing = parsed.find(l => l.prop === prop);
return {
prop,
visible: !!existing,
x1: existing?.x1 || 1,
y1: existing?.y1 || 1,
x2: existing?.x2 || 2,
2026-02-27 22:56:06 +08:00
y2: existing?.y2 || 2,
2026-02-28 11:50:57 +08:00
orientation: existing?.orientation,
fontSize: existing?.fontSize
2026-02-27 12:24:51 +08:00
};
});
}