chore(spec): 归档 blog-5l——三任务收敛(预览一致性/排版提醒/瞬间置顶隐藏)
Spec: 2026-11-05_blog-5l-admin-preview-moments Co-authored-by: GLM-5.3
This commit is contained in:
1 parent
c5889f960b
commit
b99e6e744b
17 files changed
+406
-17
No files matched your search
@@ -62,7 +62,7 @@ collections:
|
||||
default: false
|
||||
hint: '打开后这篇不进首页/归档/书架/RSS/sitemap,但页面本身仍生成、链接可分享(想彻底不生成请用草稿)。与「置顶」同时打开时以隐藏为准——2026-11-04 修:旧开关只写一个没人读的字段,导致隐藏+置顶的文章照样显示还排第一'
|
||||
- { label: 草稿, name: draft, widget: boolean, required: false, default: false }
|
||||
- { label: 正文, name: body, widget: markdown }
|
||||
- { label: 正文, name: body, widget: markdown, hint: '排版:选中文字 → Insert ▸ 排版(字体/颜色可视化选);或或手写 <span class="font-kai c-red c-red">…</span>。字体 17 类、颜色 24 档,清单见写作指南「文章排版类」' }
|
||||
|
||||
# 主题旋钮(样式即数据 · 层 4):只放白名单内的 9 组,越界值会被构建期钳制
|
||||
- name: site_theme
|
||||
@@ -107,12 +107,14 @@ collections:
|
||||
name: text
|
||||
widget: markdown
|
||||
required: false
|
||||
hint: '与图片至少填一项。支持 markdown(**加粗**、列表、> 引用)与排版类 HTML,例如 <span class="c-blue font-kai">彩色+楷体</span>;装饰色仍守“外壳灰阶、彩色只作强调”的纪律'
|
||||
hint: '与图片至少填一项。支持 markdown 与排版类 HTML,例如 <span class="c-blue font-kai">彩色+楷体</span>;选中文字 → Insert ▸ 排版 可视化选字体/颜色(预览窗格直接显色显字体)。装饰色仍守“外壳灰阶、彩色只作强调”的纪律'
|
||||
- { label: 图片, name: image, widget: image, required: false, hint: '与文字至少填一项;建议先压缩' }
|
||||
- label: 标签
|
||||
name: tags
|
||||
widget: list
|
||||
required: false
|
||||
- { label: 置顶, name: pinned, widget: boolean, required: false, default: false, hint: '置顶瞬间排时间线最前(可多置顶,之间按日期倒序);只影响顺序不改日期' }
|
||||
- { label: 隐藏, name: hidden, widget: boolean, required: false, default: false, hint: '隐藏后从时间线移除;评论数据保留在服务端,关掉开关即恢复' }
|
||||
- name: photos
|
||||
label: 图库照片
|
||||
folder: content/photos
|
||||
@@ -336,7 +338,7 @@ collections:
|
||||
name: doc
|
||||
widget: object
|
||||
required: false
|
||||
hint: '整页就这一个 markdown 字段:想写什么写什么、想多长写多长(支持排版类与 ## 标题)。清空则回落到下面的 blocks 结构化通道'
|
||||
hint: '整页就这一个 markdown 字段:想写什么写什么、想多长写多长(支持排版类与 ## 标题)。选中文字 → Insert ▸ 排版 可视化选字体/颜色,预览窗格直接显色显字体。清空则回落到下面的 blocks 结构化通道'
|
||||
fields:
|
||||
- { label: 中文, name: zh, widget: markdown, required: false }
|
||||
- { label: English, name: en, widget: markdown, required: false }
|
||||
|
||||
+10
-1
@@ -8,8 +8,17 @@
|
||||
<body>
|
||||
<!-- pinned 本地 bundle(0.252.0):官方模板仅此一个 script,无 CSS link、无 type=module -->
|
||||
<script src="./sveltia-cms.js"></script>
|
||||
<!-- 可视化排版选择:类清单(单一数据源)→ 编辑器组件注册(须在 CMS 之后、init 之前注册) -->
|
||||
<!-- 艺术字体切片(unicode-range 按需取片):选择面板的示例字形用真实字体渲染 -->
|
||||
<link rel="stylesheet" href="/fonts/subset/hwmc/fonts.css" />
|
||||
<link rel="stylesheet" href="/fonts/xiaowei/fonts.css" />
|
||||
<link rel="stylesheet" href="/fonts/huangyou/fonts.css" />
|
||||
<link rel="stylesheet" href="/fonts/mashanzheng/fonts.css" />
|
||||
<link rel="stylesheet" href="/fonts/liujianmaocao/fonts.css" />
|
||||
<link rel="stylesheet" href="/fonts/smiley/fonts.css" />
|
||||
<link rel="stylesheet" href="/fonts/neoxihei/fonts.css" />
|
||||
<!-- 可视化排版选择:类清单(单一数据源)→ 编辑器组件注册 → 预览样式注入(顺序固定:CMS 之后、init 之前) -->
|
||||
<script src="./typography-classes.js"></script>
|
||||
<script src="./typography-editor.js"></script>
|
||||
<script src="./preview-style.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 后台预览一致性(5l T1):把站点排版效果注入 Sveltia 预览窗格。
|
||||
*
|
||||
* 现状问题:markdown 里的排版类(font- 字体、c-/ink- 颜色)在预览里是素文本——
|
||||
* 类名随 DOM 保留(typography-editor 的 toPreview 输出带 class),但预览
|
||||
* 文档没有站点 CSS,颜色字体全部不可见。
|
||||
*
|
||||
* 方案(官方口子,勿改成 iframe hack——见 spec 5l §2.5):
|
||||
* 1. 基础富文本排版 + 全部排版类 CSS 从 window.TYPOGRAPHY_CLASSES
|
||||
* **运行时生成**(清单单一事实源:typography-classes.js 改一处,
|
||||
* 选择面板与预览自动同步),raw 模式注入;
|
||||
* 2. 自托管艺术字体挂切片 CSS(public/fonts/<family>/fonts.css,
|
||||
* unicode-range 按需取片——预览里只拉用到的字所落在的切片,不整包)。
|
||||
*
|
||||
* serif/kai/kuaile 的 CSS 经 Vite ?url 打包成哈希名,后台引不到稳定 URL,
|
||||
* 预览走字体栈里的系统回退(Kaiti SC/Songti)——近似可见,文档已注明。
|
||||
* 加载顺序:须在 typography-classes.js 之后、CMS init 之前(index.html 固定序)。
|
||||
*/
|
||||
(function () {
|
||||
const CLASSES = window.TYPOGRAPHY_CLASSES;
|
||||
if (!CLASSES || !window.CMS || !window.CMS.registerPreviewStyle) return;
|
||||
|
||||
/** 预览基调:近似站点 .rich 的通用排版(目标是类效果可见,非像素级还原) */
|
||||
const baseCss = [
|
||||
'p{margin:.6em 0;line-height:1.75}',
|
||||
'h1,h2,h3,h4{font-weight:600;line-height:1.4;margin:1.2em 0 .5em}',
|
||||
'h2{font-size:1.3em}h3{font-size:1.15em}',
|
||||
'ul,ol{padding-left:1.5em;margin:.6em 0}li{margin:.25em 0}',
|
||||
'a{color:#3454d1;text-decoration:underline}',
|
||||
'blockquote{margin:.8em 0;padding:.2em 1em;border-left:3px solid #e6e7eb;color:#6b6e78}',
|
||||
"code{font-family:'JetBrains Mono',ui-monospace,monospace;font-size:.92em;background:#f2f3f5;padding:.1em .35em;border-radius:4px}",
|
||||
'img{max-width:100%}',
|
||||
'hr{border:none;border-top:1px solid #e6e7eb;margin:1.5em 0}',
|
||||
'strong{font-weight:700}',
|
||||
].join('');
|
||||
|
||||
/** 排版类规则:清单驱动(swatch/ family 即预览所用值,亮态口径) */
|
||||
const rules = [];
|
||||
for (const f of CLASSES.font || []) {
|
||||
if (f.family) rules.push(`.${f.cls}{font-family:${f.family}}`);
|
||||
}
|
||||
for (const c of CLASSES.color || []) {
|
||||
if (c.swatch) rules.push(`.${c.cls}{color:${c.swatch}}`);
|
||||
}
|
||||
|
||||
window.CMS.registerPreviewStyle(baseCss + rules.join(''), { raw: true });
|
||||
|
||||
// 字体切片(URL 模式):预览文档自己的 @font-face;去重后逐个挂
|
||||
const seen = new Set();
|
||||
for (const f of CLASSES.font || []) {
|
||||
if (!f.css || seen.has(f.css)) continue;
|
||||
seen.add(f.css);
|
||||
window.CMS.registerPreviewStyle(f.css);
|
||||
}
|
||||
})();
|
||||
@@ -5,6 +5,9 @@
|
||||
*
|
||||
* swatch / family 仅供**后台面板预览**使用(后台无站点 CSS 变量,故给具体值):
|
||||
* swatch 取亮态值(后台是浅色 UI),family 为该类的真实字体栈。
|
||||
* css = 该类自托管的切片 CSS(public/fonts/<family>/fonts.css,unicode-range
|
||||
* 按需取片);选择面板与预览窗格都会挂它,让字形真实可见。serif/kai/kuaile
|
||||
* 走 Vite ?url 哈希名引不到稳定 URL,不给 css 字段(系统回退近似)。
|
||||
*/
|
||||
window.TYPOGRAPHY_CLASSES = {
|
||||
font: [
|
||||
@@ -16,16 +19,16 @@ window.TYPOGRAPHY_CLASSES = {
|
||||
{ cls: 'font-kai-sys', label: '楷体族', family: '"LXGW WenKai Screen", "Kaiti SC", STKaiti, serif', kind: '自托管优先' },
|
||||
{ cls: 'font-hei-sys', label: '黑体族', family: '"Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif', kind: '自托管优先' },
|
||||
{ cls: 'font-fangsong', label: '仿宋族', family: 'FangSong, STFangsong, serif', kind: '系统回退' },
|
||||
{ cls: 'font-huiwen', label: '汇文明朝体', family: '"WF-Hwmc", serif', kind: '自托管' },
|
||||
{ cls: 'font-huiwen', css: '/fonts/subset/hwmc/fonts.css', label: '汇文明朝体', family: '"WF-Hwmc", serif', kind: '自托管' },
|
||||
{ cls: 'font-kuaile', label: '站酷快乐体', family: '"ZCOOL KuaiLe", serif', kind: '自托管' },
|
||||
{ cls: 'font-art-kuaile', label: '快乐体(艺术·仅标题)', family: '"ZCOOL KuaiLe", serif', kind: '艺术字' },
|
||||
// 5i T9 五款字族扩展(2026-11-03,均 OFL / 免费商用且允许 web 嵌入)
|
||||
{ cls: 'font-xiaowei', label: '站酷小薇(文学·宋)', family: '"ZCOOL XiaoWei", serif', kind: '自托管' },
|
||||
{ cls: 'font-huangyou', label: '站酷庆科黄油(标题)', family: '"ZCOOL QingKe HuangYou", sans-serif', kind: '自托管' },
|
||||
{ cls: 'font-mashanzheng', label: '马善政(书法)', family: '"Ma Shan Zheng", "Kaiti SC", serif', kind: '自托管' },
|
||||
{ cls: 'font-liujianmaocao', label: '柳建毛草(草书)', family: '"Liu Jian Mao Cao", "Kaiti SC", cursive', kind: '自托管' },
|
||||
{ cls: 'font-smiley', label: '得意黑(斜体标题)', family: '"Smiley Sans", sans-serif', kind: '自托管' },
|
||||
{ cls: 'font-neoxihei', label: '霞鹜新晰黑(正文黑)', family: '"LXGW Neo XiHei", "Noto Sans SC", sans-serif', kind: '自托管' },
|
||||
{ cls: 'font-xiaowei', css: '/fonts/xiaowei/fonts.css', label: '站酷小薇(文学·宋)', family: '"ZCOOL XiaoWei", serif', kind: '自托管' },
|
||||
{ cls: 'font-huangyou', css: '/fonts/huangyou/fonts.css', label: '站酷庆科黄油(标题)', family: '"ZCOOL QingKe HuangYou", sans-serif', kind: '自托管' },
|
||||
{ cls: 'font-mashanzheng', css: '/fonts/mashanzheng/fonts.css', label: '马善政(书法)', family: '"Ma Shan Zheng", "Kaiti SC", serif', kind: '自托管' },
|
||||
{ cls: 'font-liujianmaocao', css: '/fonts/liujianmaocao/fonts.css', label: '柳建毛草(草书)', family: '"Liu Jian Mao Cao", "Kaiti SC", cursive', kind: '自托管' },
|
||||
{ cls: 'font-smiley', css: '/fonts/smiley/fonts.css', label: '得意黑(斜体标题)', family: '"Smiley Sans", sans-serif', kind: '自托管' },
|
||||
{ cls: 'font-neoxihei', css: '/fonts/neoxihei/fonts.css', label: '霞鹜新晰黑(正文黑)', family: '"LXGW Neo XiHei", "Noto Sans SC", sans-serif', kind: '自托管' },
|
||||
],
|
||||
color: [
|
||||
{ cls: 'ink-1', label: '最重(标题级)', swatch: '#111113' },
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
label: '排版(字体/颜色)',
|
||||
icon: 'format_paint',
|
||||
type: 'inline',
|
||||
pattern: /<span class="(?<cls>[a-z0-9-]+)">(?<text>[^<]*?)<\/span>/,
|
||||
pattern: /<span class="(?<cls>[a-z0-9- ]+)">(?<text>[^<]*?)<\/span>/, // 多类空格分隔(font-kai c-red)也匹配
|
||||
toInline: ({ cls = '', text = '' }) => `<span class="${cls}">${text}</span>`,
|
||||
toPreview: ({ cls = '', text = '' }) => {
|
||||
const span = document.createElement('span');
|
||||
|
||||
Reference in new issue
Block a user