root 651cc9e1fd D121: xiaohongshu-cover module v5 complete
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
2026-06-01 16:36:00 +08:00

243 lines
7.4 KiB
JavaScript
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.

/**
* ═══════════════════════════════════════════════════
* 铸渊图片工作室 · 风格配置系统
* ═══════════════════════════════════════════════════
*
* 冰朔,这里所有的颜色、字体、间距你都可以改。
* 告诉我想要的「感觉」,我来调。
*/
export const STYLES = {
/* ── 当前风格:光湖极简 ── */
name: '光湖极简',
colors: {
primary: '#1a1a2e', // 主色 · 深蓝黑
secondary: '#16213e', // 辅色 · 深蓝
accent: '#0f3460', // 强调色 · 普鲁士蓝
highlight: '#e94560', // 高亮 · 珊瑚红
gold: '#c9a96e', // 金色 · 点缀
warm: '#f5e6c8', // 暖白 · 背景
bg: '#faf8f5', // 页面背景
bgCard: '#ffffff', // 卡片背景
text: '#1a1a2e', // 正文
textMuted: '#6b7280', // 辅助文字
textLight: '#ffffff', // 浅色背景上的文字
border: '#e5e7eb', // 边框
divider: '#f0e6d3', // 分割线 · 暖色
},
fonts: {
title: '"Noto Serif SC", "Source Han Serif SC", serif',
body: '"Noto Sans SC", "Source Han Sans SC", "PingFang SC", sans-serif',
quote: '"ZCOOL QingKe HuangYou", cursive',
mono: '"JetBrains Mono", "Fira Code", monospace',
},
/* 卡片尺寸 —— 这些只是参考,可以随时改 */
sizes: {
xiaohongshu: { width: 1080, height: 1440 }, // 3:4
jike: { width: 1080, height: 1080 }, // 1:1
poster: { width: 1080, height: 1920 }, // 9:16 海报
wechat: { width: 1080, height: 1350 }, // 4:5 朋友圈
square: { width: 1080, height: 1080 }, // 1:1 通用方图
wide: { width: 1920, height: 1080 }, // 16:9 宽图
},
/* 排版 */
typography: {
titleSize: 56,
subtitleSize: 32,
bodySize: 28,
smallSize: 22,
captionSize: 18,
lineHeight: 1.6,
},
/* 间距 */
spacing: {
paddingX: 64,
paddingY: 60,
gap: 32,
},
/* 水印/品牌标识 */
brand: {
show: true,
text: '光湖 · 铸渊',
size: 16,
opacity: 0.4,
},
}
/* ── 配色方案 ── */
export const COLOR_SCHEMES = {
guanghu: {
name: '光湖极简',
primary: '#1a1a2e', bg: '#faf8f5', accent: '#0f3460',
highlight: '#e94560', gold: '#c9a96e', warm: '#f5e6c8',
},
cream: {
name: '奶油暖调',
primary: '#5d4037', bg: '#fef7f0', accent: '#8d6e63',
highlight: '#e07a5f', gold: '#d4a373', warm: '#fae1dd',
},
night: {
name: '暗夜深蓝',
primary: '#e0e0e0', bg: '#0d1117', accent: '#58a6ff',
highlight: '#f78166', gold: '#d4a373', warm: '#21262d',
},
green: {
name: '文艺绿植',
primary: '#2d3e2f', bg: '#f5f9f2', accent: '#5a8f5a',
highlight: '#c78b5c', gold: '#b8a06e', warm: '#e8f0e0',
},
rose: {
name: '玫瑰粉调',
primary: '#4a1942', bg: '#fdf2f8', accent: '#9d4e8d',
highlight: '#e8435e', gold: '#c9a96e', warm: '#fce4ec',
},
}
export function useScheme(name) {
const scheme = COLOR_SCHEMES[name]
if (!scheme) return false
const c = STYLES.colors
c.primary = scheme.primary; c.bg = scheme.bg
c.accent = scheme.accent; c.highlight = scheme.highlight
c.gold = scheme.gold; c.warm = scheme.warm
STYLES.name = scheme.name
return true
}
/* ═══════════════════════════════════════════════════
* 内容感知 · 自动检测函数
* ═══════════════════════════════════════════════════
*
* 冰朔给我一段文字,我分析它是什么类型的、什么情绪、
* 适合什么布局。不需要她告诉我。
*/
/**
* 分析文本特征,返回检测结果
*/
export function analyzeText(text) {
if (!text) return { type: 'empty' }
const t = text.trim()
/* ── 特征检测 ── */
const hasList = /^[-•·*]\s|^\d+[\.\)]\s/m.test(t) // 列表项
const isShort = t.length < 30 // 短句(金句)
const isMedium = t.length < 100 // 中等长度
const hasTitle = t.includes('标题') || t.includes('') // 可能有标题
const lines = t.split('\n').filter(Boolean)
const lineCount = lines.length
const keywords = {
notice: /通知|公告|放假|放假安排|节假日|放假通知/i,
recruit: /征稿|收稿|投稿|征集|诚征|招聘|招募|稿酬/i,
share: /干货|教程|指南|技巧|方法|如何|步骤|经验|分享/i,
quote: /说|说过|句话|名言|语录|金句|记得|曾经/i,
product: /新品|上线|发布|推出|产品|功能|更新/i,
event: /活动|沙龙|讲座|直播|分享会|聚会/i,
}
const detected = {}
let type = 'general'
for (const [key, re] of Object.entries(keywords)) {
if (re.test(t)) detected[key] = true
}
/* ── 类型推断 ── */
if (detected.notice) type = 'notice'
else if (detected.recruit) type = 'recruit'
else if (detected.quote || isShort) type = 'quote'
else if (detected.share || hasList) type = 'list'
else if (detected.product) type = 'product'
else if (detected.event) type = 'event'
else if (lineCount >= 4) type = 'article'
else if (isMedium) type = 'paragraph'
/* ── 情绪推断(基于关键词) ── */
let mood = 'neutral'
const warmWords = /感谢|温暖|爱|喜欢|开心|快乐|幸福|美好|谢谢/i
const urgentWords = /紧急|重要|注意|必读|截止|最后/i
const elegantWords = /岁月|时光|静好|诗意|远方|温柔/i
if (elegantWords.test(t)) mood = 'elegant'
else if (warmWords.test(t)) mood = 'warm'
else if (urgentWords.test(t)) mood = 'urgent'
return {
type,
mood,
lineCount,
isShort,
hasList,
lines,
detected,
text: t,
}
}
/**
* 根据内容分析结果推荐配色方案
*/
export function recommendScheme(analysis) {
const { mood, type } = analysis
if (mood === 'warm') return 'cream'
if (mood === 'elegant') return 'green'
if (mood === 'urgent') return 'guanghu'
if (type === 'recruit') return 'cream'
if (type === 'notice') return 'guanghu'
if (type === 'quote') return 'rose'
return 'guanghu'
}
/**
* 根据内容分析推荐布局
*/
export function recommendLayout(analysis) {
const { type, hasList, isShort, lineCount } = analysis
if (isShort) return 'quote'
if (type === 'notice') return 'notice'
if (type === 'recruit') return 'recruit'
if (hasList) return 'list'
if (lineCount <= 3) return 'minimal'
return 'default'
}
/**
* 根据内容分析推荐尺寸
* @param {'xiaohongshu'|'jike'|'poster'|'wechat'|'wide'|string} platform
*/
export function recommendSize(platform) {
const sizes = STYLES.sizes
if (sizes[platform]) return sizes[platform]
// 关键词匹配
if (/小红书/i.test(platform)) return sizes.xiaohongshu
if (/即刻/i.test(platform)) return sizes.jike
if (/海报/i.test(platform) || /通知/i.test(platform) || /收稿/i.test(platform)) return sizes.poster
if (/朋友圈/i.test(platform)) return sizes.wechat
if (/宽/i.test(platform) || /横/i.test(platform)) return sizes.wide
// 默认识别
return sizes.square
}