@lynn123411/dsh-maple-theme 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DETAILS.md +2 -2
- package/README.md +2 -1
- package/lib/client.js +76 -9
- package/lib/client.js.map +3 -3
- package/lib/index.js +3 -1
- package/lib/index.js.map +2 -2
- package/locale/en.json +1 -1
- package/locale/zh.json +1 -1
- package/package.json +2 -3
- package/src/client/binding.ts +0 -69
- package/src/client/card-css.ts +0 -20
- package/src/client/card.tsx +0 -179
- package/src/client/css.d.ts +0 -5
- package/src/client/index.ts +0 -149
- package/src/client/locales.ts +0 -60
- package/src/client/settings.ts +0 -171
- package/src/client/styles/markdown.css +0 -266
- package/src/client/styles/shell.css +0 -83
- package/src/client/styles/tokens.css +0 -119
- package/src/client/tokens.ts +0 -78
- package/src/index.ts +0 -69
package/lib/index.js
CHANGED
|
@@ -20,7 +20,9 @@ var Config = z.object({
|
|
|
20
20
|
/** 代码块使用 Maple 的语法配色。 */
|
|
21
21
|
codePalette: z.boolean().default(true).volatile(),
|
|
22
22
|
/** 外壳装饰:侧栏与标签条的圆角、输入卡填充、去掉会话头部那条分隔线。 */
|
|
23
|
-
shellSkin: z.boolean().default(true).volatile()
|
|
23
|
+
shellSkin: z.boolean().default(true).volatile(),
|
|
24
|
+
/** 内嵌 Maple 的字体:正文与界面换成 maplemono。 */
|
|
25
|
+
mapleFont: z.boolean().default(true).volatile()
|
|
24
26
|
});
|
|
25
27
|
function apply(ctx) {
|
|
26
28
|
ctx.settings.configure({ auto: false }, ctx.fiber);
|
package/lib/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import z from '@deepseek-ai/schemastery';\n\n/**\n * `@lynn123411/dsh-maple-theme` \u2014\u2014 \u628A Maple \u7684\u914D\u8272\u4E0E\u804A\u5929\u6B63\u6587\u6392\u7248\u5E26\u8FDB DSH\u3002\n *\n * \u5BBF\u4E3B\u534A\u8FB9\u53EA\u58F0\u660E\u8FD9\u4EFD\u914D\u7F6E\u7684\u5F62\u72B6\uFF1A\u754C\u9762\u5168\u90E8\u7531\u6D4F\u89C8\u5668\u534A\u8FB9\u753B\uFF08\u6CE8\u5165\u6837\u5F0F\u8868 + \u63D2\u4EF6\u9875\u4E0A\u7684\u914D\u7F6E\u5361\u7247\uFF09\uFF0C\n * \u8FD9\u91CC\u4E0D\u78B0\u4EFB\u4F55\u754C\u9762\uFF0C\u4E5F\u4E0D\u6CE8\u518C\u5DE5\u5177\u3002\u914D\u7F6E\u9879\u843D\u8FDB\u672C\u63D2\u4EF6\u90A3\u4E00\u884C\u7684 config\uFF0C\u6D4F\u89C8\u5668\u534A\u8FB9\u7ECF\n * `ctx.configForms.get('dsh-maple-theme')` \u8BFB\u5199\u540C\u4E00\u4EFD\u503C\u3002\n *\n * \u6BCF\u4E2A\u5B57\u6BB5\u90FD\u6807 `volatile()`\uFF1A\u6539\u4E00\u4E2A\u5F00\u5173\u4E0D\u8BE5\u91CD\u6302\u6574\u6761 loader entry\uFF0C\u6D4F\u89C8\u5668\u534A\u8FB9\u6536\u5230\u901A\u77E5\u540E\n * \u81EA\u5DF1\u6539 <html> \u4E0A\u7684\u5C5E\u6027\u4E0E\u53D8\u91CF\uFF0C\u6837\u5F0F\u8868\u4E0D\u91CD\u5EFA\u3002\n */\nexport const name = 'dsh-maple-theme';\n\n/** \u53EA\u9700\u8981 settings \u670D\u52A1\uFF1A\u5B83\u627F\u8F7D\u8FD9\u4E00\u884C\u7684\u914D\u7F6E\uFF0C\u4E5F\u662F\u300C\u4E0D\u81EA\u52A8\u751F\u6210\u8BBE\u7F6E\u9875\u300D\u90A3\u6761\u7B56\u7565\u7684\u5165\u53E3\u3002 */\nexport const inject = ['settings'];\n\n/** \u6807\u9898\u914D\u8272\u7684\u4E09\u79CD\u53D6\u6750\u65B9\u5F0F\u3002 */\nexport const HEADING_MODES = ['colorful', 'accent', 'text'] as const;\n\n/** \u6807\u9898\u914D\u8272\uFF1A\u516D\u8272\u4F9D\u6B21\u6362 / \u5168\u7528\u5F3A\u8C03\u8272 / \u5168\u7528\u6B63\u6587\u8272\u3002 */\nexport type HeadingMode = typeof HEADING_MODES[number];\n\n/** \u672C\u63D2\u4EF6\u5728 profile \u91CC\u7684 loader \u884C id\uFF0C\u540C\u65F6\u662F\u8BBE\u7F6E\u7684\u547D\u540D\u7A7A\u95F4\u3002 */\nexport const SETTINGS_NAMESPACE = name;\n\n/**\n * \u914D\u7F6E\u7684\u5F62\u72B6\u4E0E\u9ED8\u8BA4\u503C\u3002\u8272\u76F8\u53D6 Maple \u81EA\u5DF1\u7684\u51FA\u5382\u503C\uFF08\u6D45\u8272 35\u3001\u6DF1\u8272 207\uFF09\u3002\n * \u884C\u9AD8\u4E0E\u6BB5\u843D\u95F4\u8DDD\u6BD4 Maple \u7684 1.8 / 8px \u677E\u4E00\u6863\uFF1A\u5BF9\u8BDD\u6B63\u6587\u7684\u884C\u5BBD\u6BD4\u7B14\u8BB0\u7A84\uFF0C\n * \u6309\u7B14\u8BB0\u7684\u884C\u8DDD\u6392\u4F1A\u663E\u5F97\u7A00\uFF0C\u6240\u4EE5\u8FD9\u91CC\u6536\u7D27\u884C\u8DDD\u3001\u653E\u5927\u6BB5\u8DDD\u3002\n */\nexport const Config = z.object({\n /** \u6D45\u8272\u57FA\u7840\u8272\u76F8\uFF08\u5EA6\uFF09\uFF1A\u6574\u5957\u6D45\u8272\u4ECE\u5B83\u63A8\u5BFC\u3002 */\n hueLight: z.number().step(1).min(0).max(360).default(35).volatile(),\n /** \u6DF1\u8272\u57FA\u7840\u8272\u76F8\uFF08\u5EA6\uFF09\u3002 */\n hueDark: z.number().step(1).min(0).max(360).default(207).volatile(),\n /** \u6B63\u6587\u884C\u9AD8\u500D\u6570\uFF08Maple \u7684\u51FA\u5382\u503C\u662F 1.8\uFF0C\u5BF9\u8BDD\u6B63\u6587\u53D6 1.75\uFF09\u3002 */\n lineHeight: z.number().step(0.05).min(1.4).max(2).default(1.75).volatile(),\n /** \u6BB5\u843D\u95F4\u8DDD\uFF08px\uFF1BMaple \u7684\u51FA\u5382\u503C\u662F 8\uFF0C\u5BF9\u8BDD\u6B63\u6587\u53D6 10\uFF09\u3002 */\n paragraphGap: z.number().step(1).min(4).max(24).default(10).volatile(),\n /** \u6807\u9898\u914D\u8272\u65B9\u5F0F\u3002 */\n headingColor: z.union([...HEADING_MODES]).default('colorful').volatile(),\n /** \u60AC\u505C\u65F6\u5728\u6807\u9898\u5DE6\u4FA7\u663E\u793A H1\u2026H6 \u7B49\u7EA7\u6807\u8BB0\u3002 */\n headingIndicator: z.boolean().default(true).volatile(),\n /** \u4EE3\u7801\u5757\u4F7F\u7528 Maple \u7684\u8BED\u6CD5\u914D\u8272\u3002 */\n codePalette: z.boolean().default(true).volatile(),\n /** \u5916\u58F3\u88C5\u9970\uFF1A\u4FA7\u680F\u4E0E\u6807\u7B7E\u6761\u7684\u5706\u89D2\u3001\u8F93\u5165\u5361\u586B\u5145\u3001\u53BB\u6389\u4F1A\u8BDD\u5934\u90E8\u90A3\u6761\u5206\u9694\u7EBF\u3002 */\n shellSkin: z.boolean().default(true).volatile(),\n});\n\n/** \u5BBF\u4E3B\u4E0A\u4E0B\u6587\u91CC\u672C\u63D2\u4EF6\u7528\u5230\u7684\u90A3\u4E24\u4E2A\u6210\u5458\u3002 */\ninterface HostContext {\n fiber: unknown;\n settings: {\n /** \u767B\u8BB0\u8FD9\u4E00\u884C\u5728\u8BBE\u7F6E\u9875\u4E0A\u7684\u81EA\u52A8\u751F\u6210\u7B56\u7565\uFF1B`auto: false` \u8868\u793A\u4E0D\u751F\u6210\u3002 */\n configure(presentation: { auto?: boolean }, owner?: unknown): () => void;\n };\n}\n\n/**\n * \u63D2\u4EF6\u672C\u4F53\uFF1A\u58F0\u660E\u672C\u884C\u7684\u8BBE\u7F6E\u9875\u7B56\u7565\u3002\n *\n * \u914D\u7F6E\u754C\u9762\u5728\u5BBF\u4E3B\u300C\u63D2\u4EF6\u300D\u9875\u4E0A\uFF08\u6D4F\u89C8\u5668\u534A\u8FB9\u6CE8\u518C `plugins.bundle.config`\uFF09\uFF0C\n * \u6240\u4EE5\u8FD9\u91CC\u8981\u663E\u5F0F\u5173\u6389\u5185\u6838\u6309 Config schema \u81EA\u52A8\u751F\u6210\u7684\u8BBE\u7F6E\u9875\uFF0C\u5426\u5219\u540C\u4E00\u6279\u5B57\u6BB5\u4F1A\u51FA\u73B0\u4E24\u6B21\u3002\n * @param ctx - \u5BBF\u4E3B\u63D2\u4EF6\u4E0A\u4E0B\u6587\u3002\n */\nexport function apply(ctx: HostContext): void {\n ctx.settings.configure({ auto: false }, ctx.fiber);\n}\n"],
|
|
5
|
-
"mappings": ";AAAA,OAAO,OAAO;AAYP,IAAM,OAAO;AAGb,IAAM,SAAS,CAAC,UAAU;AAG1B,IAAM,gBAAgB,CAAC,YAAY,UAAU,MAAM;AAMnD,IAAM,qBAAqB;AAO3B,IAAM,SAAS,EAAE,OAAO;AAAA;AAAA,EAE7B,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS;AAAA;AAAA,EAElE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,GAAG,EAAE,SAAS;AAAA;AAAA,EAElE,YAAY,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,IAAI,GAAG,EAAE,IAAI,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS;AAAA;AAAA,EAEzE,cAAc,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS;AAAA;AAAA,EAErE,cAAc,EAAE,MAAM,CAAC,GAAG,aAAa,CAAC,EAAE,QAAQ,UAAU,EAAE,SAAS;AAAA;AAAA,EAEvE,kBAAkB,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS;AAAA;AAAA,EAErD,aAAa,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS;AAAA;AAAA,EAEhD,WAAW,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS;AAChD,CAAC;AAkBM,SAAS,MAAM,KAAwB;AAC5C,MAAI,SAAS,UAAU,EAAE,MAAM,MAAM,GAAG,IAAI,KAAK;AACnD;",
|
|
4
|
+
"sourcesContent": ["import z from '@deepseek-ai/schemastery';\n\n/**\n * `@lynn123411/dsh-maple-theme` \u2014\u2014 \u628A Maple \u7684\u914D\u8272\u4E0E\u804A\u5929\u6B63\u6587\u6392\u7248\u5E26\u8FDB DSH\u3002\n *\n * \u5BBF\u4E3B\u534A\u8FB9\u53EA\u58F0\u660E\u8FD9\u4EFD\u914D\u7F6E\u7684\u5F62\u72B6\uFF1A\u754C\u9762\u5168\u90E8\u7531\u6D4F\u89C8\u5668\u534A\u8FB9\u753B\uFF08\u6CE8\u5165\u6837\u5F0F\u8868 + \u63D2\u4EF6\u9875\u4E0A\u7684\u914D\u7F6E\u5361\u7247\uFF09\uFF0C\n * \u8FD9\u91CC\u4E0D\u78B0\u4EFB\u4F55\u754C\u9762\uFF0C\u4E5F\u4E0D\u6CE8\u518C\u5DE5\u5177\u3002\u914D\u7F6E\u9879\u843D\u8FDB\u672C\u63D2\u4EF6\u90A3\u4E00\u884C\u7684 config\uFF0C\u6D4F\u89C8\u5668\u534A\u8FB9\u7ECF\n * `ctx.configForms.get('dsh-maple-theme')` \u8BFB\u5199\u540C\u4E00\u4EFD\u503C\u3002\n *\n * \u6BCF\u4E2A\u5B57\u6BB5\u90FD\u6807 `volatile()`\uFF1A\u6539\u4E00\u4E2A\u5F00\u5173\u4E0D\u8BE5\u91CD\u6302\u6574\u6761 loader entry\uFF0C\u6D4F\u89C8\u5668\u534A\u8FB9\u6536\u5230\u901A\u77E5\u540E\n * \u81EA\u5DF1\u6539 <html> \u4E0A\u7684\u5C5E\u6027\u4E0E\u53D8\u91CF\uFF0C\u6837\u5F0F\u8868\u4E0D\u91CD\u5EFA\u3002\n */\nexport const name = 'dsh-maple-theme';\n\n/** \u53EA\u9700\u8981 settings \u670D\u52A1\uFF1A\u5B83\u627F\u8F7D\u8FD9\u4E00\u884C\u7684\u914D\u7F6E\uFF0C\u4E5F\u662F\u300C\u4E0D\u81EA\u52A8\u751F\u6210\u8BBE\u7F6E\u9875\u300D\u90A3\u6761\u7B56\u7565\u7684\u5165\u53E3\u3002 */\nexport const inject = ['settings'];\n\n/** \u6807\u9898\u914D\u8272\u7684\u4E09\u79CD\u53D6\u6750\u65B9\u5F0F\u3002 */\nexport const HEADING_MODES = ['colorful', 'accent', 'text'] as const;\n\n/** \u6807\u9898\u914D\u8272\uFF1A\u516D\u8272\u4F9D\u6B21\u6362 / \u5168\u7528\u5F3A\u8C03\u8272 / \u5168\u7528\u6B63\u6587\u8272\u3002 */\nexport type HeadingMode = typeof HEADING_MODES[number];\n\n/** \u672C\u63D2\u4EF6\u5728 profile \u91CC\u7684 loader \u884C id\uFF0C\u540C\u65F6\u662F\u8BBE\u7F6E\u7684\u547D\u540D\u7A7A\u95F4\u3002 */\nexport const SETTINGS_NAMESPACE = name;\n\n/**\n * \u914D\u7F6E\u7684\u5F62\u72B6\u4E0E\u9ED8\u8BA4\u503C\u3002\u8272\u76F8\u53D6 Maple \u81EA\u5DF1\u7684\u51FA\u5382\u503C\uFF08\u6D45\u8272 35\u3001\u6DF1\u8272 207\uFF09\u3002\n * \u884C\u9AD8\u4E0E\u6BB5\u843D\u95F4\u8DDD\u6BD4 Maple \u7684 1.8 / 8px \u677E\u4E00\u6863\uFF1A\u5BF9\u8BDD\u6B63\u6587\u7684\u884C\u5BBD\u6BD4\u7B14\u8BB0\u7A84\uFF0C\n * \u6309\u7B14\u8BB0\u7684\u884C\u8DDD\u6392\u4F1A\u663E\u5F97\u7A00\uFF0C\u6240\u4EE5\u8FD9\u91CC\u6536\u7D27\u884C\u8DDD\u3001\u653E\u5927\u6BB5\u8DDD\u3002\n */\nexport const Config = z.object({\n /** \u6D45\u8272\u57FA\u7840\u8272\u76F8\uFF08\u5EA6\uFF09\uFF1A\u6574\u5957\u6D45\u8272\u4ECE\u5B83\u63A8\u5BFC\u3002 */\n hueLight: z.number().step(1).min(0).max(360).default(35).volatile(),\n /** \u6DF1\u8272\u57FA\u7840\u8272\u76F8\uFF08\u5EA6\uFF09\u3002 */\n hueDark: z.number().step(1).min(0).max(360).default(207).volatile(),\n /** \u6B63\u6587\u884C\u9AD8\u500D\u6570\uFF08Maple \u7684\u51FA\u5382\u503C\u662F 1.8\uFF0C\u5BF9\u8BDD\u6B63\u6587\u53D6 1.75\uFF09\u3002 */\n lineHeight: z.number().step(0.05).min(1.4).max(2).default(1.75).volatile(),\n /** \u6BB5\u843D\u95F4\u8DDD\uFF08px\uFF1BMaple \u7684\u51FA\u5382\u503C\u662F 8\uFF0C\u5BF9\u8BDD\u6B63\u6587\u53D6 10\uFF09\u3002 */\n paragraphGap: z.number().step(1).min(4).max(24).default(10).volatile(),\n /** \u6807\u9898\u914D\u8272\u65B9\u5F0F\u3002 */\n headingColor: z.union([...HEADING_MODES]).default('colorful').volatile(),\n /** \u60AC\u505C\u65F6\u5728\u6807\u9898\u5DE6\u4FA7\u663E\u793A H1\u2026H6 \u7B49\u7EA7\u6807\u8BB0\u3002 */\n headingIndicator: z.boolean().default(true).volatile(),\n /** \u4EE3\u7801\u5757\u4F7F\u7528 Maple \u7684\u8BED\u6CD5\u914D\u8272\u3002 */\n codePalette: z.boolean().default(true).volatile(),\n /** \u5916\u58F3\u88C5\u9970\uFF1A\u4FA7\u680F\u4E0E\u6807\u7B7E\u6761\u7684\u5706\u89D2\u3001\u8F93\u5165\u5361\u586B\u5145\u3001\u53BB\u6389\u4F1A\u8BDD\u5934\u90E8\u90A3\u6761\u5206\u9694\u7EBF\u3002 */\n shellSkin: z.boolean().default(true).volatile(),\n /** \u5185\u5D4C Maple \u7684\u5B57\u4F53\uFF1A\u6B63\u6587\u4E0E\u754C\u9762\u6362\u6210 maplemono\u3002 */\n mapleFont: z.boolean().default(true).volatile(),\n});\n\n/** \u5BBF\u4E3B\u4E0A\u4E0B\u6587\u91CC\u672C\u63D2\u4EF6\u7528\u5230\u7684\u90A3\u4E24\u4E2A\u6210\u5458\u3002 */\ninterface HostContext {\n fiber: unknown;\n settings: {\n /** \u767B\u8BB0\u8FD9\u4E00\u884C\u5728\u8BBE\u7F6E\u9875\u4E0A\u7684\u81EA\u52A8\u751F\u6210\u7B56\u7565\uFF1B`auto: false` \u8868\u793A\u4E0D\u751F\u6210\u3002 */\n configure(presentation: { auto?: boolean }, owner?: unknown): () => void;\n };\n}\n\n/**\n * \u63D2\u4EF6\u672C\u4F53\uFF1A\u58F0\u660E\u672C\u884C\u7684\u8BBE\u7F6E\u9875\u7B56\u7565\u3002\n *\n * \u914D\u7F6E\u754C\u9762\u5728\u5BBF\u4E3B\u300C\u63D2\u4EF6\u300D\u9875\u4E0A\uFF08\u6D4F\u89C8\u5668\u534A\u8FB9\u6CE8\u518C `plugins.bundle.config`\uFF09\uFF0C\n * \u6240\u4EE5\u8FD9\u91CC\u8981\u663E\u5F0F\u5173\u6389\u5185\u6838\u6309 Config schema \u81EA\u52A8\u751F\u6210\u7684\u8BBE\u7F6E\u9875\uFF0C\u5426\u5219\u540C\u4E00\u6279\u5B57\u6BB5\u4F1A\u51FA\u73B0\u4E24\u6B21\u3002\n * @param ctx - \u5BBF\u4E3B\u63D2\u4EF6\u4E0A\u4E0B\u6587\u3002\n */\nexport function apply(ctx: HostContext): void {\n ctx.settings.configure({ auto: false }, ctx.fiber);\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,OAAO,OAAO;AAYP,IAAM,OAAO;AAGb,IAAM,SAAS,CAAC,UAAU;AAG1B,IAAM,gBAAgB,CAAC,YAAY,UAAU,MAAM;AAMnD,IAAM,qBAAqB;AAO3B,IAAM,SAAS,EAAE,OAAO;AAAA;AAAA,EAE7B,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS;AAAA;AAAA,EAElE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,GAAG,EAAE,SAAS;AAAA;AAAA,EAElE,YAAY,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,IAAI,GAAG,EAAE,IAAI,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS;AAAA;AAAA,EAEzE,cAAc,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS;AAAA;AAAA,EAErE,cAAc,EAAE,MAAM,CAAC,GAAG,aAAa,CAAC,EAAE,QAAQ,UAAU,EAAE,SAAS;AAAA;AAAA,EAEvE,kBAAkB,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS;AAAA;AAAA,EAErD,aAAa,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS;AAAA;AAAA,EAEhD,WAAW,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS;AAAA;AAAA,EAE9C,WAAW,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS;AAChD,CAAC;AAkBM,SAAS,MAAM,KAAwB;AAC5C,MAAI,SAAS,UAAU,EAAE,MAAM,MAAM,GAAG,IAAI,KAAK;AACnD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/locale/en.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"title": "Maple theme",
|
|
4
|
-
"description": "Brings the Maple Obsidian theme into DSH: a warm-white and a cool-grey palette,
|
|
4
|
+
"description": "Brings the Maple Obsidian theme into DSH: a warm-white and a cool-grey palette, the bundled Maple Mono font, conversation typography, code blocks and shell surfaces."
|
|
5
5
|
}
|
|
6
6
|
}
|
package/locale/zh.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynn123411/dsh-maple-theme",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "把 Obsidian 的 Maple 主题搬进 DSH:暖白 /
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "把 Obsidian 的 Maple 主题搬进 DSH:暖白 / 冷灰两套配色、内嵌字体、对话正文的排版、代码块与侧栏观感。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"lib",
|
|
18
|
-
"src",
|
|
19
18
|
"cordis.patch.yml",
|
|
20
19
|
"README.md",
|
|
21
20
|
"DETAILS.md",
|
package/src/client/binding.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 配置卡片与主题投影的唯一接线处:读哪一份表单、写哪几个字段。
|
|
3
|
-
*
|
|
4
|
-
* 这一层只做「读快照 → 收拢 → 投影 → 写到 <html>」三件事,不画界面。
|
|
5
|
-
* 卡片(`card.tsx`)与自检(`scripts/test-projection.mjs`)都从这里的同一个函数走,
|
|
6
|
-
* 所以「卡片改了字段」与「页面真的换了样子」不可能各走一边。
|
|
7
|
-
*/
|
|
8
|
-
import {
|
|
9
|
-
applyProjection,
|
|
10
|
-
clearProjection,
|
|
11
|
-
normalizeSettings,
|
|
12
|
-
projectSettings,
|
|
13
|
-
type MapleSettings,
|
|
14
|
-
} from './settings.ts';
|
|
15
|
-
|
|
16
|
-
/** 本插件在 profile 里的 loader 行 id,也是配置表单的命名空间。 */
|
|
17
|
-
export const SETTINGS_NAMESPACE = 'dsh-maple-theme';
|
|
18
|
-
|
|
19
|
-
/** 主题在宿主「插件」页上的座位。 */
|
|
20
|
-
export const BUNDLE_CONFIG_SLOT = 'plugins.bundle.config';
|
|
21
|
-
|
|
22
|
-
/** 本插件 bundle 的包名:`plugins.bundle.config` 的 key 就是它。 */
|
|
23
|
-
export const BUNDLE_NAME = '@lynn123411/dsh-maple-theme';
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 一张卡片要用到的配置表单:只取真正用到的那几个成员的结构子集。
|
|
27
|
-
* 这样自检用假件冒充它时不必拖进整个 ui-settings 运行时。
|
|
28
|
-
*/
|
|
29
|
-
export interface MapleForm {
|
|
30
|
-
getSnapshot(): {
|
|
31
|
-
status: 'loading' | 'ready' | 'unavailable';
|
|
32
|
-
value?: Partial<MapleSettings> | undefined;
|
|
33
|
-
writable?: boolean;
|
|
34
|
-
revision?: number | undefined;
|
|
35
|
-
};
|
|
36
|
-
subscribe(listener: () => void): () => void;
|
|
37
|
-
set(field: string, value: unknown): Promise<boolean>;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 读表单当前值,收拢成一份可信配置。
|
|
42
|
-
* @param form - 本命名空间的配置表单。
|
|
43
|
-
* @returns 宿主还没服务这个命名空间时返回 undefined。
|
|
44
|
-
*/
|
|
45
|
-
export function readSettings(form: MapleForm): MapleSettings | undefined {
|
|
46
|
-
const snapshot = form.getSnapshot();
|
|
47
|
-
if (snapshot.status === 'unavailable') return undefined;
|
|
48
|
-
return normalizeSettings(snapshot.value);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* 订阅表单并持续投影,直到返回的 disposer 被调用。
|
|
53
|
-
* 这也包括卸载时把 `<html>` 上的痕迹撤干净——插件停用后页面必须回到宿主原本的样子。
|
|
54
|
-
* @param root - 文档根元素。
|
|
55
|
-
* @param form - 本命名空间的配置表单。
|
|
56
|
-
* @returns 停止订阅并撤掉投影的 disposer。
|
|
57
|
-
*/
|
|
58
|
-
export function bindProjection(root: HTMLElement, form: MapleForm): () => void {
|
|
59
|
-
const sync = (): void => {
|
|
60
|
-
const settings = readSettings(form);
|
|
61
|
-
applyProjection(root, projectSettings(settings ?? normalizeSettings(undefined)));
|
|
62
|
-
};
|
|
63
|
-
sync();
|
|
64
|
-
const off = form.subscribe(sync);
|
|
65
|
-
return () => {
|
|
66
|
-
off();
|
|
67
|
-
clearProjection(root);
|
|
68
|
-
};
|
|
69
|
-
}
|
package/src/client/card-css.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/** 卡片自己的样式。宿主「插件」页只提供页面骨架,行布局由卡片自己给。
|
|
2
|
-
*
|
|
3
|
-
* 形状照宿主的设置行:左边标题与说明,右边控件;整块是一张卡片(填充 + 发丝描边),
|
|
4
|
-
* 不加阴影——浮起来的才是菜单与弹窗。颜色一律取 --dsw-alias-*,深浅两套自动跟随。
|
|
5
|
-
*/
|
|
6
|
-
export const CARD_CSS = `
|
|
7
|
-
.dsh-maple-card{display:flex;flex-direction:column;gap:20px;padding:16px 0}
|
|
8
|
-
.dsh-maple-group{display:flex;flex-direction:column;gap:4px}
|
|
9
|
-
.dsh-maple-group-title{font-size:12px;line-height:18px;font-weight:600;color:var(--dsw-alias-label-tertiary);letter-spacing:.02em}
|
|
10
|
-
.dsh-maple-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:8px 0;border-bottom:0.5px solid var(--dsw-alias-border-l1)}
|
|
11
|
-
.dsh-maple-row:last-child{border-bottom:0}
|
|
12
|
-
.dsh-maple-row-info{display:flex;flex-direction:column;gap:2px;min-width:0}
|
|
13
|
-
.dsh-maple-row-title{font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary)}
|
|
14
|
-
.dsh-maple-row-hint{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
15
|
-
.dsh-maple-row-field{flex:none;display:flex;align-items:center;gap:8px}
|
|
16
|
-
.dsh-maple-number{width:88px}
|
|
17
|
-
.dsh-maple-unit{font-size:12px;color:var(--dsw-alias-label-tertiary);min-width:18px}
|
|
18
|
-
.dsh-maple-note{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);padding-top:12px}
|
|
19
|
-
.dsh-maple-empty{font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary)}
|
|
20
|
-
`;
|
package/src/client/card.tsx
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 宿主「插件」页上的配置卡片:Maple 主题的全部旋钮。
|
|
3
|
-
*
|
|
4
|
-
* 改动即时生效:控件的每一次变化都直接写进配置表单,表单回写快照,投影订阅把值
|
|
5
|
-
* 写到 <html> 上,样式表不重建。没有「保存」按钮——这几个旋钮都是所见即所得的,
|
|
6
|
-
* 加一步保存只会让人以为没生效。
|
|
7
|
-
*/
|
|
8
|
-
import { useEffect, useState } from 'react';
|
|
9
|
-
import * as React from 'react';
|
|
10
|
-
import { Input, SegmentedControl, Switch } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
11
|
-
import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
12
|
-
import { readSettings, type MapleForm } from './binding.ts';
|
|
13
|
-
import { DEFAULT_SETTINGS, type MapleSettings } from './settings.ts';
|
|
14
|
-
import { NS } from './locales.ts';
|
|
15
|
-
|
|
16
|
-
/** 标题配色的三个选项:值、文案键、面板 id 后缀。 */
|
|
17
|
-
const HEADING_OPTIONS = [
|
|
18
|
-
{ value: 'colorful', key: 'card.headingColorColorful' },
|
|
19
|
-
{ value: 'accent', key: 'card.headingColorAccent' },
|
|
20
|
-
{ value: 'text', key: 'card.headingColorText' },
|
|
21
|
-
] as const;
|
|
22
|
-
|
|
23
|
-
/** 一行「标题 + 说明 + 控件」。 */
|
|
24
|
-
function Row({ title, hint, children }: {
|
|
25
|
-
title: string;
|
|
26
|
-
hint?: string | undefined;
|
|
27
|
-
children: React.ReactNode;
|
|
28
|
-
}): React.ReactElement {
|
|
29
|
-
return (
|
|
30
|
-
<div className="dsh-maple-row">
|
|
31
|
-
<div className="dsh-maple-row-info">
|
|
32
|
-
<div className="dsh-maple-row-title">{title}</div>
|
|
33
|
-
{hint !== undefined && <div className="dsh-maple-row-hint">{hint}</div>}
|
|
34
|
-
</div>
|
|
35
|
-
<div className="dsh-maple-row-field">{children}</div>
|
|
36
|
-
</div>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 一个数字旋钮:本地保存输入中的字符串,失焦或回车时才提交。
|
|
42
|
-
*
|
|
43
|
-
* 不逐键提交:输入 `1.75` 的中途会经过 `1`、`1.` 这些值,逐键写会让页面在中间态闪一下。
|
|
44
|
-
* @param props.value - 当前生效的值。
|
|
45
|
-
* @param props.onCommit - 提交一个合法值。
|
|
46
|
-
*/
|
|
47
|
-
function NumberField({ value, min, max, step, unit, label, onCommit }: {
|
|
48
|
-
value: number;
|
|
49
|
-
min: number;
|
|
50
|
-
max: number;
|
|
51
|
-
step: number;
|
|
52
|
-
unit: string;
|
|
53
|
-
label: string;
|
|
54
|
-
onCommit: (next: number) => void;
|
|
55
|
-
}): React.ReactElement {
|
|
56
|
-
const [text, setText] = useState(String(value));
|
|
57
|
-
// 外部改了值(别处写入、恢复默认)就跟着换,但正在编辑时不打断。
|
|
58
|
-
useEffect(() => { setText(String(value)) }, [value]);
|
|
59
|
-
const commit = (): void => {
|
|
60
|
-
const parsed = Number(text);
|
|
61
|
-
if (!Number.isFinite(parsed)) { setText(String(value)); return; }
|
|
62
|
-
const clamped = Math.min(max, Math.max(min, Math.round(parsed / step) * step));
|
|
63
|
-
setText(String(clamped));
|
|
64
|
-
if (clamped !== value) onCommit(clamped);
|
|
65
|
-
};
|
|
66
|
-
return (
|
|
67
|
-
<>
|
|
68
|
-
<Input
|
|
69
|
-
className="dsh-maple-number"
|
|
70
|
-
type="number"
|
|
71
|
-
inputMode="decimal"
|
|
72
|
-
min={min}
|
|
73
|
-
max={max}
|
|
74
|
-
step={step}
|
|
75
|
-
value={text}
|
|
76
|
-
aria-label={label}
|
|
77
|
-
onChange={(event: React.ChangeEvent<HTMLInputElement>) => { setText(event.target.value) }}
|
|
78
|
-
onBlur={commit}
|
|
79
|
-
onKeyDown={(event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
80
|
-
if (event.key === 'Enter') { event.currentTarget.blur(); }
|
|
81
|
-
}}
|
|
82
|
-
/>
|
|
83
|
-
<span className="dsh-maple-unit">{unit}</span>
|
|
84
|
-
</>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* 渲染配置卡片。
|
|
90
|
-
* @param props - 座位给的 `t`,加上本插件在 `inject` 里投出去的那张表单。
|
|
91
|
-
* @returns 卡片的元素树。
|
|
92
|
-
*/
|
|
93
|
-
export function MapleThemeCard(
|
|
94
|
-
props: PropsRuntime<'plugins.bundle.config'> & PropsLocale<typeof NS> & { form: MapleForm },
|
|
95
|
-
): React.ReactElement {
|
|
96
|
-
// 座位在 `locale: NS` 时把绑定好的 t 挂在 `t` 上;类型声明里它是运行期注入的,这里取出来。
|
|
97
|
-
const { form } = props;
|
|
98
|
-
const t = (key: keyof typeof import('./locales.ts').en): string =>
|
|
99
|
-
(props as unknown as { t: (k: string) => string }).t(key);
|
|
100
|
-
const [settings, setSettings] = useState<MapleSettings | undefined>(() => readSettings(form));
|
|
101
|
-
const [available, setAvailable] = useState(() => form.getSnapshot().status !== 'unavailable');
|
|
102
|
-
|
|
103
|
-
useEffect(() => {
|
|
104
|
-
const sync = (): void => {
|
|
105
|
-
setSettings(readSettings(form));
|
|
106
|
-
setAvailable(form.getSnapshot().status !== 'unavailable');
|
|
107
|
-
};
|
|
108
|
-
sync();
|
|
109
|
-
return form.subscribe(sync);
|
|
110
|
-
}, [form]);
|
|
111
|
-
|
|
112
|
-
if (!available) return <div className="dsh-maple-card"><div className="dsh-maple-empty">{t('card.unavailable')}</div></div>;
|
|
113
|
-
|
|
114
|
-
const current = settings ?? DEFAULT_SETTINGS;
|
|
115
|
-
const write = (field: keyof MapleSettings, value: unknown): void => { void form.set(field, value); };
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
<div className="dsh-maple-card">
|
|
119
|
-
<section className="dsh-maple-group">
|
|
120
|
-
<div className="dsh-maple-group-title">{t('card.colors')}</div>
|
|
121
|
-
<Row title={t('card.hueLight')} hint={t('card.hueLightHint')}>
|
|
122
|
-
<NumberField value={current.hueLight} min={0} max={360} step={1} unit="°"
|
|
123
|
-
label={t('card.hueLight')} onCommit={(next) => { write('hueLight', next) }} />
|
|
124
|
-
</Row>
|
|
125
|
-
<Row title={t('card.hueDark')} hint={t('card.hueDarkHint')}>
|
|
126
|
-
<NumberField value={current.hueDark} min={0} max={360} step={1} unit="°"
|
|
127
|
-
label={t('card.hueDark')} onCommit={(next) => { write('hueDark', next) }} />
|
|
128
|
-
</Row>
|
|
129
|
-
</section>
|
|
130
|
-
|
|
131
|
-
<section className="dsh-maple-group">
|
|
132
|
-
<div className="dsh-maple-group-title">{t('card.typography')}</div>
|
|
133
|
-
<Row title={t('card.lineHeight')} hint={t('card.lineHeightHint')}>
|
|
134
|
-
<NumberField value={current.lineHeight} min={1.4} max={2} step={0.05} unit="×"
|
|
135
|
-
label={t('card.lineHeight')} onCommit={(next) => { write('lineHeight', next) }} />
|
|
136
|
-
</Row>
|
|
137
|
-
<Row title={t('card.paragraphGap')} hint={t('card.paragraphGapHint')}>
|
|
138
|
-
<NumberField value={current.paragraphGap} min={4} max={24} step={1} unit="px"
|
|
139
|
-
label={t('card.paragraphGap')} onCommit={(next) => { write('paragraphGap', next) }} />
|
|
140
|
-
</Row>
|
|
141
|
-
</section>
|
|
142
|
-
|
|
143
|
-
<section className="dsh-maple-group">
|
|
144
|
-
<div className="dsh-maple-group-title">{t('card.headings')}</div>
|
|
145
|
-
<Row title={t('card.headingColor')}>
|
|
146
|
-
<SegmentedControl
|
|
147
|
-
id="dsh-maple-heading"
|
|
148
|
-
value={current.headingColor}
|
|
149
|
-
label={t('card.headingColor')}
|
|
150
|
-
options={HEADING_OPTIONS.map(option => ({ value: option.value, label: t(option.key) }))}
|
|
151
|
-
onChange={(next) => { write('headingColor', next) }}
|
|
152
|
-
/>
|
|
153
|
-
</Row>
|
|
154
|
-
<Row title={t('card.headingIndicator')} hint={t('card.headingIndicatorHint')}>
|
|
155
|
-
<Switch checked={current.headingIndicator} label={t('card.headingIndicator')}
|
|
156
|
-
onChange={(next) => { write('headingIndicator', next) }} />
|
|
157
|
-
</Row>
|
|
158
|
-
</section>
|
|
159
|
-
|
|
160
|
-
<section className="dsh-maple-group">
|
|
161
|
-
<div className="dsh-maple-group-title">{t('card.code')}</div>
|
|
162
|
-
<Row title={t('card.codePalette')} hint={t('card.codePaletteHint')}>
|
|
163
|
-
<Switch checked={current.codePalette} label={t('card.codePalette')}
|
|
164
|
-
onChange={(next) => { write('codePalette', next) }} />
|
|
165
|
-
</Row>
|
|
166
|
-
</section>
|
|
167
|
-
|
|
168
|
-
<section className="dsh-maple-group">
|
|
169
|
-
<div className="dsh-maple-group-title">{t('card.shell')}</div>
|
|
170
|
-
<Row title={t('card.shellSkin')} hint={t('card.shellSkinHint')}>
|
|
171
|
-
<Switch checked={current.shellSkin} label={t('card.shellSkin')}
|
|
172
|
-
onChange={(next) => { write('shellSkin', next) }} />
|
|
173
|
-
</Row>
|
|
174
|
-
</section>
|
|
175
|
-
|
|
176
|
-
<div className="dsh-maple-note">{t('card.scope')}</div>
|
|
177
|
-
</div>
|
|
178
|
-
);
|
|
179
|
-
}
|
package/src/client/css.d.ts
DELETED
package/src/client/index.ts
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Maple 主题的浏览器半边:注入样式表、把配置投影到 `<html>`、在宿主「插件」页上挂配置卡片。
|
|
3
|
-
*
|
|
4
|
-
* 三件事各有归属:
|
|
5
|
-
* 1. 样式表在 `apply()` 里注入,标签带 `data-plugin` / `data-plugin-css`:client-modules
|
|
6
|
-
* 按前者在卸载与热更时删掉它们(docs/rules/plugin-ui.md「覆盖宿主控件的样式」)。
|
|
7
|
-
* 2. 投影订阅本插件那一行的配置表单,值变了只改 `<html>` 上的属性与变量,样式表不重建。
|
|
8
|
-
* 3. 卡片走 `plugins.bundle.config`,key 是 bundle 的 npm 包名;宿主「插件」页没挂载时
|
|
9
|
-
* 这个座位不存在,所以注册必须包在 `slots.inject` 里,并与 `configForms.whileServed`
|
|
10
|
-
* 串起来——宿主没服务这份配置,就一个字的界面都不出现。
|
|
11
|
-
*/
|
|
12
|
-
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
13
|
-
// 类型只读:这几个包的浏览器半边把座位契约、`ctx.configForms` 与 `ctx.locale` 合并进 Context。
|
|
14
|
-
import type {} from '@deepseek-ai/dsh-client-locale/client';
|
|
15
|
-
import type {} from '@deepseek-ai/dsh-client-ui-plugin-manager/client';
|
|
16
|
-
import type {} from '@deepseek-ai/dsh-client-ui-renderer/client';
|
|
17
|
-
import type {} from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
18
|
-
import { bindProjection, BUNDLE_NAME, BUNDLE_CONFIG_SLOT, SETTINGS_NAMESPACE, type MapleForm } from './binding.ts';
|
|
19
|
-
import { CARD_CSS } from './card-css.ts';
|
|
20
|
-
import { MapleThemeCard } from './card.tsx';
|
|
21
|
-
import { NS, en, zh } from './locales.ts';
|
|
22
|
-
import tokens from './styles/tokens.css?inline';
|
|
23
|
-
import { MAPLE_TOKENS, THEME_SOURCE } from './tokens.ts';
|
|
24
|
-
import markdown from './styles/markdown.css?inline';
|
|
25
|
-
import shell from './styles/shell.css?inline';
|
|
26
|
-
|
|
27
|
-
export { NS } from './locales.ts';
|
|
28
|
-
export {
|
|
29
|
-
BUNDLE_CONFIG_SLOT, BUNDLE_NAME, SETTINGS_NAMESPACE, bindProjection, readSettings,
|
|
30
|
-
} from './binding.ts';
|
|
31
|
-
export { MapleThemeCard } from './card.tsx';
|
|
32
|
-
export {
|
|
33
|
-
DEFAULT_SETTINGS, HEADING_ATTRIBUTE, INDICATOR_ATTRIBUTE, CODE_ATTRIBUTE, ROOT_ATTRIBUTE, ROOT_VARIABLES,
|
|
34
|
-
applyProjection, clearProjection, clampNumber, normalizeSettings, projectSettings,
|
|
35
|
-
} from './settings.ts';
|
|
36
|
-
|
|
37
|
-
/** 包名:样式表标签的归属键,也是浏览器 bundle 的自注册 id。 */
|
|
38
|
-
export const name = '@lynn123411/dsh-maple-theme';
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 声明的服务:`configForms` 读本插件那一行的配置,`slots` 与 `locale` 画配置卡片,
|
|
42
|
-
* `theme` 把两套调色板交给宿主的主题通道。
|
|
43
|
-
* 漏声明不会报错,只会让整个浏览器半边在页面里消失(docs/rules/client-wiring.md)。
|
|
44
|
-
*/
|
|
45
|
-
export const inject = ['configForms', 'slots', 'locale', 'theme'];
|
|
46
|
-
|
|
47
|
-
/** 本插件的样式表:归属键按「包名/文件名」拼,卸载时整批删。 */
|
|
48
|
-
const SHEETS: readonly (readonly [string, string])[] = [
|
|
49
|
-
['tokens.css', tokens],
|
|
50
|
-
['markdown.css', markdown],
|
|
51
|
-
['shell.css', shell],
|
|
52
|
-
['card.css', CARD_CSS],
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 注入本插件的样式表;同一个键已存在时替换内容而不是再插一张。
|
|
57
|
-
* 键按文件走:热更后重新执行这个模块时,新内容覆盖旧标签,不会叠出第二份。
|
|
58
|
-
*/
|
|
59
|
-
function injectStyles(): void {
|
|
60
|
-
if (typeof document === 'undefined') return;
|
|
61
|
-
for (const [file, css] of SHEETS) {
|
|
62
|
-
const key = `${name}/${file}`;
|
|
63
|
-
const existing = document.head.querySelector<HTMLStyleElement>(`style[data-plugin-css="${key}"]`);
|
|
64
|
-
const tag = existing ?? document.createElement('style');
|
|
65
|
-
tag.dataset.plugin = name;
|
|
66
|
-
tag.dataset.pluginCss = key;
|
|
67
|
-
tag.textContent = css;
|
|
68
|
-
if (existing === null) document.head.appendChild(tag);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/** 撤掉本插件的样式标签。 */
|
|
73
|
-
function removeStyles(): void {
|
|
74
|
-
if (typeof document === 'undefined') return;
|
|
75
|
-
for (const tag of document.head.querySelectorAll(`style[data-plugin="${name}"]`)) tag.remove();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** 浏览器上下文里本插件用到的成员。 */
|
|
79
|
-
interface ClientServices {
|
|
80
|
-
configForms: {
|
|
81
|
-
get(namespace: string): MapleForm;
|
|
82
|
-
whileServed(namespaces: readonly string[], register: (served: ReadonlySet<string>) => () => void): () => void;
|
|
83
|
-
};
|
|
84
|
-
slots: {
|
|
85
|
-
inject(slot: string, register: () => () => void): () => void;
|
|
86
|
-
register(options: Record<string, unknown>, component: unknown): () => void;
|
|
87
|
-
};
|
|
88
|
-
locale: {
|
|
89
|
-
register(namespace: string, dictionaries: { zh: unknown; en: unknown }): () => void;
|
|
90
|
-
};
|
|
91
|
-
theme: {
|
|
92
|
-
overrideTokens(source: string, tokens: Record<string, { light: string; dark: string }>): () => void;
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* 插件本体。
|
|
98
|
-
* @param ctx - 客户端根上下文。
|
|
99
|
-
*/
|
|
100
|
-
export function apply(ctx: ClientContext): void {
|
|
101
|
-
const services = ctx as unknown as ClientServices;
|
|
102
|
-
|
|
103
|
-
ctx.effect(() => {
|
|
104
|
-
injectStyles();
|
|
105
|
-
return () => { removeStyles(); };
|
|
106
|
-
}, 'dsh-maple-theme: stylesheets');
|
|
107
|
-
|
|
108
|
-
// 配色:走宿主的主题通道,由它写到 body 的行内样式上(docs/web-styling.md 的所有权归主题,
|
|
109
|
-
// 功能包消费令牌而不是另立一份全局主题)。disposer 会把这层覆盖整份撤掉。
|
|
110
|
-
ctx.effect(
|
|
111
|
-
() => services.theme.overrideTokens(THEME_SOURCE, MAPLE_TOKENS),
|
|
112
|
-
'dsh-maple-theme: palette',
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
ctx.effect(
|
|
116
|
-
() => services.locale.register(NS, { zh, en }),
|
|
117
|
-
'dsh-maple-theme: dictionaries',
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
// 投影:配置一变就重写 <html>,卸载时把痕迹撤干净。
|
|
121
|
-
ctx.effect(() => {
|
|
122
|
-
if (typeof document === 'undefined') return () => {};
|
|
123
|
-
return bindProjection(document.documentElement, services.configForms.get(SETTINGS_NAMESPACE));
|
|
124
|
-
}, 'dsh-maple-theme: projection');
|
|
125
|
-
|
|
126
|
-
// 配置卡片:宿主「插件」页挂载时才注册,宿主没服务这份配置就不出现。
|
|
127
|
-
ctx.effect(
|
|
128
|
-
() => services.configForms.whileServed([SETTINGS_NAMESPACE], () => services.slots.inject(
|
|
129
|
-
BUNDLE_CONFIG_SLOT,
|
|
130
|
-
() => slotsRegister(services, () => ({
|
|
131
|
-
name: BUNDLE_CONFIG_SLOT,
|
|
132
|
-
key: BUNDLE_NAME,
|
|
133
|
-
locale: NS,
|
|
134
|
-
inject: () => ({ form: services.configForms.get(SETTINGS_NAMESPACE) }),
|
|
135
|
-
})),
|
|
136
|
-
)),
|
|
137
|
-
'dsh-maple-theme: plugins page config',
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* 把「注册项的选项」与组件绑在一起,抽出来只为让上面那段读起来是三层而不是五层。
|
|
143
|
-
* @param services - 上下文里用到的服务。
|
|
144
|
-
* @param options - 注册项的选项工厂(每次注册都新建一份)。
|
|
145
|
-
* @returns 注册的 disposer。
|
|
146
|
-
*/
|
|
147
|
-
function slotsRegister(services: ClientServices, options: () => Record<string, unknown>): () => void {
|
|
148
|
-
return services.slots.register(options(), MapleThemeCard);
|
|
149
|
-
}
|
package/src/client/locales.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/** Maple 主题的界面文案。键集与英文逐一对齐,自检会查这一条。 */
|
|
2
|
-
export const NS = 'mapletheme';
|
|
3
|
-
|
|
4
|
-
/** 英文文案。 */
|
|
5
|
-
export const en = {
|
|
6
|
-
'card.colors': 'Colors',
|
|
7
|
-
'card.hueLight': 'Light hue',
|
|
8
|
-
'card.hueLightHint': 'Base hue the whole light palette is derived from. Maple ships 35 (warm white).',
|
|
9
|
-
'card.hueDark': 'Dark hue',
|
|
10
|
-
'card.hueDarkHint': 'Base hue the whole dark palette is derived from. Maple ships 207 (cool grey).',
|
|
11
|
-
'card.typography': 'Typing',
|
|
12
|
-
'card.lineHeight': 'Line height',
|
|
13
|
-
'card.lineHeightHint': 'Line height for conversation body text. Tighter than Maple’s 1.8 because chat lines run narrower.',
|
|
14
|
-
'card.paragraphGap': 'Paragraph gap',
|
|
15
|
-
'card.paragraphGapHint': 'Space between two paragraphs in an answer, in pixels. Looser than Maple’s 8.',
|
|
16
|
-
'card.headings': 'Headings',
|
|
17
|
-
'card.headingColor': 'Heading color',
|
|
18
|
-
'card.headingColorColorful': 'Six colors',
|
|
19
|
-
'card.headingColorAccent': 'Accent',
|
|
20
|
-
'card.headingColorText': 'Body text',
|
|
21
|
-
'card.headingIndicator': 'Level marker',
|
|
22
|
-
'card.headingIndicatorHint': 'Show H1–H6 to the left of a heading while the pointer rests on it.',
|
|
23
|
-
'card.code': 'Code',
|
|
24
|
-
'card.codePalette': 'Maple syntax colors',
|
|
25
|
-
'card.codePaletteHint': 'Recolor fenced code blocks with the Maple syntax palette.',
|
|
26
|
-
'card.shell': 'Surroundings',
|
|
27
|
-
'card.shellSkin': 'Sidebar and tabs',
|
|
28
|
-
'card.shellSkinHint': 'Round the sidebar rows and the active tab, drop the seam under the session header, and give the input card Maple paper.',
|
|
29
|
-
'card.scope': 'The palette is global; headings, quotes, tables, lists and rules only change inside conversation answers.',
|
|
30
|
-
'card.unavailable': 'The Host does not serve this configuration right now.',
|
|
31
|
-
} as const;
|
|
32
|
-
|
|
33
|
-
/** 中文文案。 */
|
|
34
|
-
export const zh: Record<keyof typeof en, string> = {
|
|
35
|
-
'card.colors': '配色',
|
|
36
|
-
'card.hueLight': '浅色基础色相',
|
|
37
|
-
'card.hueLightHint': '浅色整套颜色由这个色相推导。Maple 出厂值是 35(暖白)。',
|
|
38
|
-
'card.hueDark': '深色基础色相',
|
|
39
|
-
'card.hueDarkHint': '深色整套颜色由这个色相推导。Maple 出厂值是 207(冷灰)。',
|
|
40
|
-
'card.typography': '打字体验',
|
|
41
|
-
'card.lineHeight': '行高',
|
|
42
|
-
'card.lineHeightHint': '对话正文的行高倍数。比 Maple 的 1.8 紧一档,对话的行宽比笔记窄。',
|
|
43
|
-
'card.paragraphGap': '段落间距',
|
|
44
|
-
'card.paragraphGapHint': '一个回答里两段之间空多少像素。比 Maple 的 8 松一档。',
|
|
45
|
-
'card.headings': '标题',
|
|
46
|
-
'card.headingColor': '标题颜色',
|
|
47
|
-
'card.headingColorColorful': '六级换色',
|
|
48
|
-
'card.headingColorAccent': '强调色',
|
|
49
|
-
'card.headingColorText': '正文色',
|
|
50
|
-
'card.headingIndicator': '等级标记',
|
|
51
|
-
'card.headingIndicatorHint': '指针停在标题上时,在左边显示 H1–H6。',
|
|
52
|
-
'card.code': '代码',
|
|
53
|
-
'card.codePalette': 'Maple 语法配色',
|
|
54
|
-
'card.codePaletteHint': '用 Maple 的调色板给围栏代码块换语法色。',
|
|
55
|
-
'card.shell': '周边',
|
|
56
|
-
'card.shellSkin': '侧栏与标签条',
|
|
57
|
-
'card.shellSkinHint': '侧栏行与活动标签改成圆角,去掉会话头部下面那条接缝,输入卡换成 Maple 的纸色。',
|
|
58
|
-
'card.scope': '配色是全局的;标题、引用、表格、列表与分隔线只在对话正文里换样子。',
|
|
59
|
-
'card.unavailable': '宿主当前没有提供这份配置。',
|
|
60
|
-
};
|