chore(spec): 归档 blog-5n——八任务收敛(后台深度优化全家桶)
Spec: 2026-11-05_blog-5n-admin-deep-optimization Co-authored-by: GLM-5.3
This commit is contained in:
1 parent
a555a3e450
commit
5c0e6ed900
29 files changed
+1559
-512
No files matched your search
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* 后台预览一致性(5l T1):把站点排版效果注入 Sveltia 预览窗格。
|
||||
* 后台预览一致性(5l T1 / 5n T7):把站点排版效果注入 Sveltia 预览窗格。
|
||||
*
|
||||
* 现状问题:markdown 里的排版类(font- 字体、c-/ink- 颜色)在预览里是素文本——
|
||||
* 类名随 DOM 保留(typography-editor 的 toPreview 输出带 class),但预览
|
||||
@@ -12,6 +12,10 @@
|
||||
* 2. 自托管艺术字体挂切片 CSS(public/fonts/<family>/fonts.css,
|
||||
* unicode-range 按需取片——预览里只拉用到的字所落在的切片,不整包)。
|
||||
*
|
||||
* 暗色(5n T7):所有色值走 CSS 自定义属性,变量缺省值 = 亮态(与改造前同一批
|
||||
* 字面量,无暗色命中时逐字节等价),末尾一段 @media (prefers-color-scheme: dark)
|
||||
* 统一换档——后台切暗色时预览不再用亮态色值配暗底。
|
||||
*
|
||||
* serif/kai/kuaile 的 CSS 经 Vite ?url 打包成哈希名,后台引不到稳定 URL,
|
||||
* 预览走字体栈里的系统回退(Kaiti SC/Songti)——近似可见,文档已注明。
|
||||
* 加载顺序:须在 typography-classes.js 之后、CMS init 之前(index.html 固定序)。
|
||||
@@ -20,30 +24,96 @@
|
||||
const CLASSES = window.TYPOGRAPHY_CLASSES;
|
||||
if (!CLASSES || !window.CMS || !window.CMS.registerPreviewStyle) return;
|
||||
|
||||
/**
|
||||
* 基础排版的暗态值(亮态值不在这里登记,直接作各条 var() 的回落值)。
|
||||
* 出处:src/styles/tokens.css `[data-theme="dark"]` 段,勿凭观感改。
|
||||
*/
|
||||
const BASE_DARK = {
|
||||
'pv-accent': '#8ea2ff', // --accent
|
||||
'pv-line': '#262b33', // --line(站点暗色分隔线就是这个档)
|
||||
'pv-quote-ink': '#8b8f98', // --ink-3
|
||||
'pv-code-bg': '#1f242b', // --bg-soft
|
||||
};
|
||||
|
||||
/**
|
||||
* 颜色类暗态值,键 = typography-classes.js 里的 cls。同样取自暗色 tokens 段:
|
||||
* 站点语义色板暗态是独立取值(不是亮态加亮),硬套亮态在 #191d23 底上不达 AA。
|
||||
*/
|
||||
const CLASS_DARK = {
|
||||
'ink-1': '#f5f5f7', // --ink-1
|
||||
'ink-2': '#c9ccd4', // --ink-2
|
||||
'ink-3': '#8b8f98', // --ink-3
|
||||
// 站点 CSS 里 ink-muted 映射 --ink-4,而暗态 --ink-4 (#5c6066) 是装饰档,
|
||||
// 暗底上近乎不可见;亮态 swatch 本就取的是 --ink-faint 的值,暗态随之一致
|
||||
'ink-muted': '#84888f', // --ink-faint
|
||||
'ink-warm': '#d6cbbd', // --ink-warm
|
||||
'ink-cool': '#b9c6d6', // --ink-cool
|
||||
'ink-faint': '#84888f', // --ink-faint
|
||||
'ink-accent': '#8ea2ff', // --accent
|
||||
'ink-accent-soft': '#a8b7f7', // --accent-soft-text
|
||||
'c-blue': '#7fb0ff',
|
||||
'c-blue-soft': '#3381ff',
|
||||
'c-teal': '#6fd6c8',
|
||||
'c-teal-soft': '#2a9384',
|
||||
'c-green': '#7ddf99',
|
||||
'c-green-soft': '#269a47',
|
||||
'c-yellow': '#ffd166',
|
||||
'c-yellow-soft': '#af7a00',
|
||||
'c-orange': '#ffb163',
|
||||
'c-orange-soft': '#d16800',
|
||||
'c-red': '#ff8b8b',
|
||||
'c-red-soft': '#ff2828',
|
||||
'c-pink': '#ff9ecb',
|
||||
'c-pink-soft': '#ff0d7e',
|
||||
'c-purple': '#c4a6ff',
|
||||
'c-purple-soft': '#9a67ff',
|
||||
};
|
||||
|
||||
/**
|
||||
* 未登记暗态值的类(清单后续新增)用 color-mix 提亮近似——宁可偏亮,
|
||||
* 也不要暗底上跑亮态深色(那是这次要修的问题本身)。
|
||||
*/
|
||||
const approxDark = (swatch) => `color-mix(in oklab, ${swatch} 82%, #fff)`;
|
||||
|
||||
/** 预览基调:近似站点 .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}",
|
||||
'a{color:var(--pv-accent,#3454d1);text-decoration:underline}',
|
||||
'blockquote{margin:.8em 0;padding:.2em 1em;border-left:3px solid var(--pv-line,#e6e7eb);color:var(--pv-quote-ink,#6b6e78)}',
|
||||
"code{font-family:'JetBrains Mono',ui-monospace,monospace;font-size:.92em;background:var(--pv-code-bg,#f2f3f5);padding:.1em .35em;border-radius:4px}",
|
||||
'img{max-width:100%}',
|
||||
'hr{border:none;border-top:1px solid #e6e7eb;margin:1.5em 0}',
|
||||
'hr{border:none;border-top:1px solid var(--pv-line,#e6e7eb);margin:1.5em 0}',
|
||||
'strong{font-weight:700}',
|
||||
].join('');
|
||||
|
||||
/** 排版类规则:清单驱动(swatch/ family 即预览所用值,亮态口径) */
|
||||
/** 排版类规则:清单驱动(swatch/family 亮态值作 var() 回落 = 面板所见) */
|
||||
const rules = [];
|
||||
const darkDecls = [];
|
||||
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}}`);
|
||||
if (!c.swatch) continue;
|
||||
const name = `--pv-${c.cls}`;
|
||||
rules.push(`.${c.cls}{color:var(${name},${c.swatch})}`);
|
||||
darkDecls.push(`${name}:${CLASS_DARK[c.cls] || approxDark(c.swatch)}`);
|
||||
}
|
||||
for (const [name, value] of Object.entries(BASE_DARK)) darkDecls.push(`--${name}:${value}`);
|
||||
|
||||
window.CMS.registerPreviewStyle(baseCss + rules.join(''), { raw: true });
|
||||
/**
|
||||
* 为什么用媒体查询而不是监听「后台切主题」:Sveltia 的 registerPreviewStyle 是
|
||||
* 一次性注入(无更新/移除接口),registerEventListener 只支持 pre/postSave 与
|
||||
* pre/postPublish 这类保存事件,没有任何主题切换回调;后台主题默认跟随系统,
|
||||
* 预览文档的 prefers-color-scheme 与后台同源,浏览器自己换档即可,零重注入。
|
||||
* 代价:用户在后台显式选 light 而系统是 dark 时预览偏暗——已知取舍,比监听
|
||||
* Sveltia 内部 DOM(非公开契约)稳妥。
|
||||
*/
|
||||
const darkCss = darkDecls.length ? `@media (prefers-color-scheme: dark){:root{${darkDecls.join(';')}}}` : '';
|
||||
|
||||
window.CMS.registerPreviewStyle(baseCss + rules.join('') + darkCss, { raw: true });
|
||||
|
||||
// 字体切片(URL 模式):预览文档自己的 @font-face;去重后逐个挂
|
||||
const seen = new Set();
|
||||
|
||||
Reference in new issue
Block a user