MODULE-COVER-001: full package for external AI consumption - server.js + renderer.js + generate.js + config.js - templates/ (5 templates: xiaohongshu + dynamic + jike + poster + registry) - package.json + README.md + MODULE.hdlp - INDEX.hdlp + SYSTEM.hdlp (HLDP declarations) - Fonts: Noto Sans CJK SC priority (no tofu blocks) - No domain watermark - Updated module-registry.json - Copyright 2026-A-00037559
164 lines
4.5 KiB
JavaScript
164 lines
4.5 KiB
JavaScript
/**
|
||
* ═══════════════════════════════════════════════════
|
||
* 铸渊封面工作室 · 模板注册表
|
||
* ═══════════════════════════════════════════════════
|
||
*
|
||
* 所有模板在此注册。新增模板只需:
|
||
* 1. 在 templates/ 下创建模板文件
|
||
* 2. 在此文件 import + 注册
|
||
* 3. 核心代码零改动
|
||
*/
|
||
|
||
import { xiaohongshuCard } from './xiaohongshu.js'
|
||
|
||
/**
|
||
* 模板注册表
|
||
*/
|
||
export const TEMPLATE_REGISTRY = {
|
||
|
||
xiaohongshu: {
|
||
id: 'xiaohongshu',
|
||
name: '小红书封面',
|
||
description: '1080×1440 · 3:4 竖版 · 适合小红书笔记封面',
|
||
icon: '📕',
|
||
sizes: { width: 1080, height: 1440 },
|
||
category: '封面',
|
||
isDefault: true,
|
||
instructions: '输入标题和正文,自动排版生成小红书封面。支持金句、干货列表、教程等多种布局。',
|
||
features: ['智能排版', '金句模式', '干货列表', '多页轮播'],
|
||
presets: [
|
||
{
|
||
id: 'tech',
|
||
name: '科技蓝',
|
||
cssVars: {
|
||
'--bg': '#0a0e27',
|
||
'--primary': '#e0e6ff',
|
||
'--accent': '#4f8cff',
|
||
'--highlight': '#00d4ff',
|
||
'--gold': '#ffb347',
|
||
'--warm': '#1a1f3a',
|
||
'--text': '#c8d6e5',
|
||
'--textMuted': '#6b7d99',
|
||
'--cardBg': '#121838',
|
||
'--border': '#1e2a4a',
|
||
},
|
||
},
|
||
{
|
||
id: 'warm',
|
||
name: '奶油暖调',
|
||
cssVars: {
|
||
'--bg': '#fef7f0',
|
||
'--primary': '#5d4037',
|
||
'--accent': '#e07a5f',
|
||
'--highlight': '#d4a373',
|
||
'--gold': '#c9a96e',
|
||
'--warm': '#fae1dd',
|
||
'--text': '#3e2723',
|
||
'--textMuted': '#8d6e63',
|
||
'--cardBg': '#ffffff',
|
||
'--border': '#f0e6d3',
|
||
},
|
||
},
|
||
{
|
||
id: 'minimal',
|
||
name: '极简黑白',
|
||
cssVars: {
|
||
'--bg': '#ffffff',
|
||
'--primary': '#111111',
|
||
'--accent': '#333333',
|
||
'--highlight': '#ff4757',
|
||
'--gold': '#999999',
|
||
'--warm': '#f5f5f5',
|
||
'--text': '#222222',
|
||
'--textMuted': '#888888',
|
||
'--cardBg': '#fafafa',
|
||
'--border': '#e0e0e0',
|
||
},
|
||
},
|
||
{
|
||
id: 'rose',
|
||
name: '玫瑰粉调',
|
||
cssVars: {
|
||
'--bg': '#fdf2f8',
|
||
'--primary': '#4a1942',
|
||
'--accent': '#9d4e8d',
|
||
'--highlight': '#e8435e',
|
||
'--gold': '#c9a96e',
|
||
'--warm': '#fce4ec',
|
||
'--text': '#311b2e',
|
||
'--textMuted': '#8e6290',
|
||
'--cardBg': '#ffffff',
|
||
'--border': '#f0d4e0',
|
||
},
|
||
},
|
||
{
|
||
id: 'green',
|
||
name: '文艺绿植',
|
||
cssVars: {
|
||
'--bg': '#f5f9f2',
|
||
'--primary': '#1b3a1b',
|
||
'--accent': '#5a8f5a',
|
||
'--highlight': '#c78b5c',
|
||
'--gold': '#b8a06e',
|
||
'--warm': '#e8f0e0',
|
||
'--text': '#2d3e2f',
|
||
'--textMuted': '#6b8b6b',
|
||
'--cardBg': '#ffffff',
|
||
'--border': '#d4e4cc',
|
||
},
|
||
},
|
||
],
|
||
render: xiaohongshuCard,
|
||
},
|
||
|
||
/* ── 后续接入(模板文件待创建时取消注释即可)── */
|
||
// poster: { ... },
|
||
// jike: { ... },
|
||
// dynamic: { ... },
|
||
}
|
||
|
||
|
||
/** 获取所有可用模板列表 */
|
||
export function listTemplates() {
|
||
return Object.values(TEMPLATE_REGISTRY).map(t => ({
|
||
id: t.id,
|
||
name: t.name,
|
||
description: t.description,
|
||
icon: t.icon,
|
||
sizes: t.sizes,
|
||
category: t.category,
|
||
features: t.features,
|
||
instructions: t.instructions,
|
||
presets: t.presets.map(p => ({ id: p.id, name: p.name })),
|
||
isDefault: t.isDefault,
|
||
}))
|
||
}
|
||
|
||
/** 获取单个模板 */
|
||
export function getTemplate(id) {
|
||
return TEMPLATE_REGISTRY[id] || null
|
||
}
|
||
|
||
/** 获取默认模板 */
|
||
export function getDefaultTemplate() {
|
||
return Object.values(TEMPLATE_REGISTRY).find(t => t.isDefault)
|
||
|| Object.values(TEMPLATE_REGISTRY)[0]
|
||
}
|
||
|
||
/** 根据模板+预设+内容,准备渲染数据 */
|
||
export function prepareRenderData(templateId, presetId, contentData) {
|
||
const template = getTemplate(templateId)
|
||
if (!template) return null
|
||
|
||
const preset = template.presets.find(p => p.id === presetId)
|
||
|| template.presets[0]
|
||
|
||
return {
|
||
...contentData,
|
||
templateId,
|
||
presetId: preset?.id || 'default',
|
||
cssVars: preset?.cssVars || {},
|
||
sizes: template.sizes,
|
||
}
|
||
}
|