Files
probably-rendering-one-more…/apps/waterfall-wiki/src/studio/lib/render-cover.ts
T

23 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {createElement} from 'react';
import {ideas} from '../content/ideas';
import {Ref17Cover} from '../components/Ref17Cover';
import {SourceCover,selections} from '../components/SourceCover';
const record=(v:unknown):v is Record<string,unknown>=>!!v&&typeof v==='object'&&!Array.isArray(v);
function color(value:unknown,fallback:string){if(value===undefined)return fallback;if(typeof value!=='string'||!/^#[0-9a-f]{6}$/i.test(value))throw Error('颜色必须为 #RRGGBB');return value;}
function text(value:unknown,fallback:string,max:number,lines=1){if(value===undefined)return fallback;if(typeof value!=='string'||!value.trim()||Array.from(value).length>max||value.split('\n').length>lines)throw Error('文字长度或行数超限');return value;}
function keys(input:Record<string,unknown>,allowed:string[]){if(Object.keys(input).some(k=>!allowed.includes(k)))throw Error('包含不支持的参数');}
export function renderCover(slug:string,input:unknown){
if(!record(input))throw Error('需要 JSON 对象');
if(slug==='layout-selection'){
keys(input,['layoutId','fields','color','accent']);const layout=selections.find(l=>l.id===input.layoutId);if(!layout)throw Error('layoutId 必须为 ref-01、ref-07 或 ref-26');
if(input.fields!==undefined&&!record(input.fields))throw Error('fields 必须为对象');const supplied=(input.fields||{}) as Record<string,unknown>,defaults=Object.fromEntries(Object.entries(layout.fields).filter(([,v])=>v!==undefined)) as Record<string,string>;
keys(supplied,Object.keys(defaults));const fields=Object.fromEntries(Object.entries(defaults).map(([key,value])=>[key,text(supplied[key],value,120,4)]));
const values={fields,color:color(input.color,'#83918a'),accent:color(input.accent,'#c3cec5')};return {node:createElement(SourceCover,{layout,values}),data:{version:3,tool:slug,layoutId:layout.id,template:layout,...values}};
}
const idea=ideas.find(i=>i.slug===slug);if(!idea?.template)throw Error('这个方案不支持封面渲染');keys(input,['slide','heading','body','color','accent','masthead']);
const index=input.slide??0;if(typeof index!=='number'||!Number.isInteger(index)||!idea.slides[index])throw Error('slide 必须是 0–3 的整数');const initial=idea.slides[index];
const slide={...initial,heading:text(input.heading,initial.heading,6),body:text(input.body,initial.body,360,3),color:color(input.color,initial.color),accent:color(input.accent,initial.accent!)};
const masthead=input.masthead??idea.template.masthead;if(!Array.isArray(masthead)||masthead.length!==2||!masthead.every(v=>typeof v==='string'&&/^[A-Za-z ]{1,8}$/.test(v)&&v.trim()))throw Error('masthead 为两行、每行 1–8 个英文字母或空格');
return {node:createElement(Ref17Cover,{template:idea.template,slide,masthead}),data:{version:2,tool:slug,template:{...idea.template,masthead},slide}};
}