@qihuang02/world-book-mcp 0.0.3

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.
Files changed (245) hide show
  1. package/README.md +187 -0
  2. package/dist/core/capability-matrix.d.ts +17 -0
  3. package/dist/core/capability-matrix.js +133 -0
  4. package/dist/core/capability-matrix.js.map +1 -0
  5. package/dist/core/chapter-extraction.d.ts +12 -0
  6. package/dist/core/chapter-extraction.js +65 -0
  7. package/dist/core/chapter-extraction.js.map +1 -0
  8. package/dist/core/character-card-builder.d.ts +76 -0
  9. package/dist/core/character-card-builder.js +112 -0
  10. package/dist/core/character-card-builder.js.map +1 -0
  11. package/dist/core/character-card-query.d.ts +5 -0
  12. package/dist/core/character-card-query.js +30 -0
  13. package/dist/core/character-card-query.js.map +1 -0
  14. package/dist/core/character-card-validator.d.ts +17 -0
  15. package/dist/core/character-card-validator.js +42 -0
  16. package/dist/core/character-card-validator.js.map +1 -0
  17. package/dist/core/character-templates.d.ts +29 -0
  18. package/dist/core/character-templates.js +60 -0
  19. package/dist/core/character-templates.js.map +1 -0
  20. package/dist/core/clarification.d.ts +24 -0
  21. package/dist/core/clarification.js +433 -0
  22. package/dist/core/clarification.js.map +1 -0
  23. package/dist/core/config-explainer.d.ts +2 -0
  24. package/dist/core/config-explainer.js +44 -0
  25. package/dist/core/config-explainer.js.map +1 -0
  26. package/dist/core/content-lint.d.ts +15 -0
  27. package/dist/core/content-lint.js +90 -0
  28. package/dist/core/content-lint.js.map +1 -0
  29. package/dist/core/decision-prompts.d.ts +45 -0
  30. package/dist/core/decision-prompts.js +93 -0
  31. package/dist/core/decision-prompts.js.map +1 -0
  32. package/dist/core/delivery-checklist.d.ts +21 -0
  33. package/dist/core/delivery-checklist.js +63 -0
  34. package/dist/core/delivery-checklist.js.map +1 -0
  35. package/dist/core/derivative-outline.d.ts +19 -0
  36. package/dist/core/derivative-outline.js +107 -0
  37. package/dist/core/derivative-outline.js.map +1 -0
  38. package/dist/core/draft-template.d.ts +2 -0
  39. package/dist/core/draft-template.js +19 -0
  40. package/dist/core/draft-template.js.map +1 -0
  41. package/dist/core/draft-update.d.ts +5 -0
  42. package/dist/core/draft-update.js +34 -0
  43. package/dist/core/draft-update.js.map +1 -0
  44. package/dist/core/ejs-entries.d.ts +5 -0
  45. package/dist/core/ejs-entries.js +22 -0
  46. package/dist/core/ejs-entries.js.map +1 -0
  47. package/dist/core/ejs-phase-plan.d.ts +27 -0
  48. package/dist/core/ejs-phase-plan.js +77 -0
  49. package/dist/core/ejs-phase-plan.js.map +1 -0
  50. package/dist/core/ejs-template.d.ts +10 -0
  51. package/dist/core/ejs-template.js +70 -0
  52. package/dist/core/ejs-template.js.map +1 -0
  53. package/dist/core/ejs-validator.d.ts +18 -0
  54. package/dist/core/ejs-validator.js +60 -0
  55. package/dist/core/ejs-validator.js.map +1 -0
  56. package/dist/core/entry-planner.d.ts +8 -0
  57. package/dist/core/entry-planner.js +79 -0
  58. package/dist/core/entry-planner.js.map +1 -0
  59. package/dist/core/entry-templates.d.ts +7 -0
  60. package/dist/core/entry-templates.js +66 -0
  61. package/dist/core/entry-templates.js.map +1 -0
  62. package/dist/core/extraction-outline.d.ts +2 -0
  63. package/dist/core/extraction-outline.js +46 -0
  64. package/dist/core/extraction-outline.js.map +1 -0
  65. package/dist/core/final-review.d.ts +13 -0
  66. package/dist/core/final-review.js +80 -0
  67. package/dist/core/final-review.js.map +1 -0
  68. package/dist/core/greeting-validator.d.ts +17 -0
  69. package/dist/core/greeting-validator.js +79 -0
  70. package/dist/core/greeting-validator.js.map +1 -0
  71. package/dist/core/html-beautify-assets.d.ts +6 -0
  72. package/dist/core/html-beautify-assets.js +59 -0
  73. package/dist/core/html-beautify-assets.js.map +1 -0
  74. package/dist/core/html-beautify-template.d.ts +8 -0
  75. package/dist/core/html-beautify-template.js +46 -0
  76. package/dist/core/html-beautify-template.js.map +1 -0
  77. package/dist/core/html-beautify-validator.d.ts +21 -0
  78. package/dist/core/html-beautify-validator.js +66 -0
  79. package/dist/core/html-beautify-validator.js.map +1 -0
  80. package/dist/core/html-regex-pair.d.ts +18 -0
  81. package/dist/core/html-regex-pair.js +77 -0
  82. package/dist/core/html-regex-pair.js.map +1 -0
  83. package/dist/core/item-entry-validator.d.ts +10 -0
  84. package/dist/core/item-entry-validator.js +27 -0
  85. package/dist/core/item-entry-validator.js.map +1 -0
  86. package/dist/core/mvu-assets.d.ts +44 -0
  87. package/dist/core/mvu-assets.js +140 -0
  88. package/dist/core/mvu-assets.js.map +1 -0
  89. package/dist/core/mvu-template.d.ts +8 -0
  90. package/dist/core/mvu-template.js +45 -0
  91. package/dist/core/mvu-template.js.map +1 -0
  92. package/dist/core/mvu-validator.d.ts +18 -0
  93. package/dist/core/mvu-validator.js +75 -0
  94. package/dist/core/mvu-validator.js.map +1 -0
  95. package/dist/core/position-map.d.ts +5 -0
  96. package/dist/core/position-map.js +27 -0
  97. package/dist/core/position-map.js.map +1 -0
  98. package/dist/core/project-lint.d.ts +15 -0
  99. package/dist/core/project-lint.js +54 -0
  100. package/dist/core/project-lint.js.map +1 -0
  101. package/dist/core/regex-validator.d.ts +13 -0
  102. package/dist/core/regex-validator.js +41 -0
  103. package/dist/core/regex-validator.js.map +1 -0
  104. package/dist/core/style-extraction.d.ts +12 -0
  105. package/dist/core/style-extraction.js +87 -0
  106. package/dist/core/style-extraction.js.map +1 -0
  107. package/dist/core/task-classifier.d.ts +17 -0
  108. package/dist/core/task-classifier.js +107 -0
  109. package/dist/core/task-classifier.js.map +1 -0
  110. package/dist/core/tool-usage-guide.d.ts +13 -0
  111. package/dist/core/tool-usage-guide.js +198 -0
  112. package/dist/core/tool-usage-guide.js.map +1 -0
  113. package/dist/core/workflow.d.ts +12 -0
  114. package/dist/core/workflow.js +129 -0
  115. package/dist/core/workflow.js.map +1 -0
  116. package/dist/core/worldbook-builder.d.ts +6 -0
  117. package/dist/core/worldbook-builder.js +60 -0
  118. package/dist/core/worldbook-builder.js.map +1 -0
  119. package/dist/core/worldbook-importer.d.ts +7 -0
  120. package/dist/core/worldbook-importer.js +50 -0
  121. package/dist/core/worldbook-importer.js.map +1 -0
  122. package/dist/core/worldbook-patch.d.ts +23 -0
  123. package/dist/core/worldbook-patch.js +100 -0
  124. package/dist/core/worldbook-patch.js.map +1 -0
  125. package/dist/core/worldbook-planning.d.ts +41 -0
  126. package/dist/core/worldbook-planning.js +74 -0
  127. package/dist/core/worldbook-planning.js.map +1 -0
  128. package/dist/core/worldbook-query.d.ts +7 -0
  129. package/dist/core/worldbook-query.js +58 -0
  130. package/dist/core/worldbook-query.js.map +1 -0
  131. package/dist/core/worldbook-validator.d.ts +19 -0
  132. package/dist/core/worldbook-validator.js +116 -0
  133. package/dist/core/worldbook-validator.js.map +1 -0
  134. package/dist/core/worldbuilding.d.ts +80 -0
  135. package/dist/core/worldbuilding.js +134 -0
  136. package/dist/core/worldbuilding.js.map +1 -0
  137. package/dist/core/writing-optimization-report.d.ts +19 -0
  138. package/dist/core/writing-optimization-report.js +25 -0
  139. package/dist/core/writing-optimization-report.js.map +1 -0
  140. package/dist/index.d.ts +2 -0
  141. package/dist/index.js +15 -0
  142. package/dist/index.js.map +1 -0
  143. package/dist/prompts/register.d.ts +2 -0
  144. package/dist/prompts/register.js +37 -0
  145. package/dist/prompts/register.js.map +1 -0
  146. package/dist/resources/usage-resources.d.ts +2 -0
  147. package/dist/resources/usage-resources.js +15 -0
  148. package/dist/resources/usage-resources.js.map +1 -0
  149. package/dist/schemas/chapter-outline.d.ts +28 -0
  150. package/dist/schemas/chapter-outline.js +17 -0
  151. package/dist/schemas/chapter-outline.js.map +1 -0
  152. package/dist/schemas/character-card.d.ts +124 -0
  153. package/dist/schemas/character-card.js +49 -0
  154. package/dist/schemas/character-card.js.map +1 -0
  155. package/dist/schemas/decision.d.ts +50 -0
  156. package/dist/schemas/decision.js +37 -0
  157. package/dist/schemas/decision.js.map +1 -0
  158. package/dist/schemas/derivative-outline.d.ts +204 -0
  159. package/dist/schemas/derivative-outline.js +55 -0
  160. package/dist/schemas/derivative-outline.js.map +1 -0
  161. package/dist/schemas/ejs.d.ts +189 -0
  162. package/dist/schemas/ejs.js +40 -0
  163. package/dist/schemas/ejs.js.map +1 -0
  164. package/dist/schemas/extraction.d.ts +219 -0
  165. package/dist/schemas/extraction.js +51 -0
  166. package/dist/schemas/extraction.js.map +1 -0
  167. package/dist/schemas/html-beautify.d.ts +159 -0
  168. package/dist/schemas/html-beautify.js +42 -0
  169. package/dist/schemas/html-beautify.js.map +1 -0
  170. package/dist/schemas/mvu.d.ts +60 -0
  171. package/dist/schemas/mvu.js +30 -0
  172. package/dist/schemas/mvu.js.map +1 -0
  173. package/dist/schemas/project.d.ts +579 -0
  174. package/dist/schemas/project.js +50 -0
  175. package/dist/schemas/project.js.map +1 -0
  176. package/dist/schemas/research.d.ts +56 -0
  177. package/dist/schemas/research.js +21 -0
  178. package/dist/schemas/research.js.map +1 -0
  179. package/dist/schemas/sillytavern-worldbook.d.ts +104 -0
  180. package/dist/schemas/sillytavern-worldbook.js +55 -0
  181. package/dist/schemas/sillytavern-worldbook.js.map +1 -0
  182. package/dist/schemas/source.d.ts +40 -0
  183. package/dist/schemas/source.js +20 -0
  184. package/dist/schemas/source.js.map +1 -0
  185. package/dist/schemas/style-profile.d.ts +35 -0
  186. package/dist/schemas/style-profile.js +16 -0
  187. package/dist/schemas/style-profile.js.map +1 -0
  188. package/dist/schemas/worldbook-draft.d.ts +236 -0
  189. package/dist/schemas/worldbook-draft.js +89 -0
  190. package/dist/schemas/worldbook-draft.js.map +1 -0
  191. package/dist/schemas/worldbook-patch.d.ts +423 -0
  192. package/dist/schemas/worldbook-patch.js +78 -0
  193. package/dist/schemas/worldbook-patch.js.map +1 -0
  194. package/dist/server.d.ts +2 -0
  195. package/dist/server.js +15 -0
  196. package/dist/server.js.map +1 -0
  197. package/dist/storage/path-policy.d.ts +13 -0
  198. package/dist/storage/path-policy.js +44 -0
  199. package/dist/storage/path-policy.js.map +1 -0
  200. package/dist/storage/project-store.d.ts +8 -0
  201. package/dist/storage/project-store.js +113 -0
  202. package/dist/storage/project-store.js.map +1 -0
  203. package/dist/tools/character-card-tools.d.ts +2 -0
  204. package/dist/tools/character-card-tools.js +118 -0
  205. package/dist/tools/character-card-tools.js.map +1 -0
  206. package/dist/tools/decision-tools.d.ts +2 -0
  207. package/dist/tools/decision-tools.js +55 -0
  208. package/dist/tools/decision-tools.js.map +1 -0
  209. package/dist/tools/extraction-tools.d.ts +2 -0
  210. package/dist/tools/extraction-tools.js +57 -0
  211. package/dist/tools/extraction-tools.js.map +1 -0
  212. package/dist/tools/helpers.d.ts +9 -0
  213. package/dist/tools/helpers.js +14 -0
  214. package/dist/tools/helpers.js.map +1 -0
  215. package/dist/tools/lint-review-tools.d.ts +2 -0
  216. package/dist/tools/lint-review-tools.js +30 -0
  217. package/dist/tools/lint-review-tools.js.map +1 -0
  218. package/dist/tools/mvu-html-ejs-tools.d.ts +2 -0
  219. package/dist/tools/mvu-html-ejs-tools.js +153 -0
  220. package/dist/tools/mvu-html-ejs-tools.js.map +1 -0
  221. package/dist/tools/project-tools.d.ts +2 -0
  222. package/dist/tools/project-tools.js +39 -0
  223. package/dist/tools/project-tools.js.map +1 -0
  224. package/dist/tools/register.d.ts +2 -0
  225. package/dist/tools/register.js +23 -0
  226. package/dist/tools/register.js.map +1 -0
  227. package/dist/tools/style-chapter-tools.d.ts +2 -0
  228. package/dist/tools/style-chapter-tools.js +40 -0
  229. package/dist/tools/style-chapter-tools.js.map +1 -0
  230. package/dist/tools/workflow-tools.d.ts +2 -0
  231. package/dist/tools/workflow-tools.js +60 -0
  232. package/dist/tools/workflow-tools.js.map +1 -0
  233. package/dist/tools/worldbook-tools.d.ts +2 -0
  234. package/dist/tools/worldbook-tools.js +180 -0
  235. package/dist/tools/worldbook-tools.js.map +1 -0
  236. package/dist/tools/worldbuilding-tools.d.ts +2 -0
  237. package/dist/tools/worldbuilding-tools.js +40 -0
  238. package/dist/tools/worldbuilding-tools.js.map +1 -0
  239. package/dist/utils/ids.d.ts +2 -0
  240. package/dist/utils/ids.js +8 -0
  241. package/dist/utils/ids.js.map +1 -0
  242. package/dist/utils/json.d.ts +2 -0
  243. package/dist/utils/json.js +7 -0
  244. package/dist/utils/json.js.map +1 -0
  245. package/package.json +32 -0
@@ -0,0 +1,80 @@
1
+ import { validateCharacterCardConfig } from "./character-card-validator.js";
2
+ import { validateEjsConfig } from "./ejs-validator.js";
3
+ import { validateHtmlBeautifyConfig } from "./html-beautify-validator.js";
4
+ import { validateMvuConfig } from "./mvu-validator.js";
5
+ import { lintProjectContent } from "./project-lint.js";
6
+ import { validateWorldbookDraft } from "./worldbook-validator.js";
7
+ import { validateWorldbuildingSummary } from "./worldbuilding.js";
8
+ import { createWritingOptimizationReport } from "./writing-optimization-report.js";
9
+ export function createFinalReviewReport(project) {
10
+ const sections = {};
11
+ const recommendations = [];
12
+ if (project.worldbuildingSummary) {
13
+ const result = validateWorldbuildingSummary(project.worldbuildingSummary);
14
+ sections.worldbuilding = result;
15
+ }
16
+ else {
17
+ sections.worldbuilding = { ok: true, errors: [], warnings: [{ field: "worldbuildingSummary", severity: "warning", message: "项目未保存世界观总纲;原创项目建议补充" }] };
18
+ }
19
+ if (project.draft) {
20
+ const result = validateWorldbookDraft(project.draft);
21
+ sections.worldbook = { ok: result.valid, errors: result.errors, warnings: result.warnings, summary: result.summary };
22
+ }
23
+ else {
24
+ sections.worldbook = { ok: false, errors: [{ field: "draft", severity: "error", message: "项目尚未保存 worldbook draft" }], warnings: [] };
25
+ }
26
+ if (project.characterCardConfig) {
27
+ const result = validateCharacterCardConfig({ config: project.characterCardConfig, draft: project.draft, mvuEnabled: project.mvuConfig?.enabled });
28
+ sections.character_card = { ok: result.valid, errors: result.errors, warnings: result.warnings, summary: result.summary };
29
+ }
30
+ else {
31
+ sections.character_card = { ok: true, errors: [], warnings: [{ field: "characterCardConfig", severity: "warning", message: "项目未配置角色卡;如只导出世界书可忽略" }] };
32
+ }
33
+ if (project.mvuConfig) {
34
+ const result = validateMvuConfig({ mvu: project.mvuConfig, characterCardConfig: project.characterCardConfig });
35
+ sections.mvu = { ok: result.valid, errors: result.errors, warnings: result.warnings, summary: result.summary };
36
+ }
37
+ if (project.htmlBeautifyConfig) {
38
+ const result = validateHtmlBeautifyConfig({ html: project.htmlBeautifyConfig, mvu: project.mvuConfig, characterCardConfig: project.characterCardConfig });
39
+ sections.html_beautify = { ok: result.valid, errors: result.errors, warnings: result.warnings, summary: result.summary };
40
+ }
41
+ if (project.ejsConfig) {
42
+ const result = validateEjsConfig({ ejs: project.ejsConfig, mvu: project.mvuConfig });
43
+ sections.ejs = { ok: result.valid, errors: result.errors, warnings: result.warnings, summary: result.summary };
44
+ }
45
+ const lint = lintProjectContent(project);
46
+ const pending = project.pendingDecisions ?? [];
47
+ if (pending.length > 0) {
48
+ sections.pending_decisions = {
49
+ ok: true,
50
+ errors: [],
51
+ warnings: pending.map((decision) => ({ field: `pendingDecisions.${decision.id}`, severity: "warning", message: `未解决决策:${decision.question}`, suggestion: decision.source_tool ? `回答后调用 record_user_decision,然后回到 ${decision.source_tool}` : "回答后调用 record_user_decision" })),
52
+ summary: { count: pending.length, ids: pending.map((decision) => decision.id) },
53
+ };
54
+ recommendations.push("项目存在未解决的用户决策,建议先调用 record_user_decision");
55
+ }
56
+ else {
57
+ sections.pending_decisions = { ok: true, errors: [], warnings: [], summary: { count: 0 } };
58
+ }
59
+ const writingReport = createWritingOptimizationReport({ project });
60
+ sections.writing_optimization = {
61
+ ok: writingReport.ok,
62
+ errors: writingReport.issues.filter((issue) => issue.severity === "error").map((issue) => ({ field: issue.path, severity: "error", message: issue.term ? `文本问题:${issue.term}` : issue.message, suggestion: issue.suggestion })),
63
+ warnings: writingReport.issues.filter((issue) => issue.severity === "warning").map((issue) => ({ field: issue.path, severity: "warning", message: issue.term ? `文本问题:${issue.term}` : issue.message, suggestion: issue.suggestion })),
64
+ summary: writingReport.summary,
65
+ };
66
+ sections.content_lint = {
67
+ ok: lint.ok,
68
+ errors: lint.issues.filter((issue) => issue.severity === "error").map((issue) => ({ field: issue.path, severity: "error", message: issue.term ? `文本问题:${issue.term}` : issue.message, suggestion: issue.suggestion })),
69
+ warnings: lint.issues.filter((issue) => issue.severity === "warning").map((issue) => ({ field: issue.path, severity: "warning", message: issue.term ? `文本问题:${issue.term}` : issue.message, suggestion: issue.suggestion })),
70
+ summary: lint.summary,
71
+ };
72
+ if (project.ejsConfig?.enabled && !project.mvuConfig?.enabled)
73
+ recommendations.push("启用 EJS 前必须启用 MVU");
74
+ if (project.htmlBeautifyConfig?.enabled && !project.characterCardConfig)
75
+ recommendations.push("HTML 美化资产需要通过角色卡 JSON 承载");
76
+ if (project.characterCardConfig && !project.draft)
77
+ recommendations.push("角色卡建议嵌入世界书,先完成 draft 再导出");
78
+ return { ok: Object.values(sections).every((section) => section.ok), sections, recommendations };
79
+ }
80
+ //# sourceMappingURL=final-review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"final-review.js","sourceRoot":"","sources":["../../src/core/final-review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { CharacterCardConfig } from "../schemas/character-card.js";
2
+ import type { ValidationIssue } from "./worldbook-validator.js";
3
+ export interface GreetingValidationResult {
4
+ valid: boolean;
5
+ errors: ValidationIssue[];
6
+ warnings: ValidationIssue[];
7
+ summary: {
8
+ first_mes_present: boolean;
9
+ alternate_greeting_count: number;
10
+ total_greeting_count: number;
11
+ mvu_placeholder_required: boolean;
12
+ };
13
+ }
14
+ export declare function validateGreetings(input: {
15
+ config: CharacterCardConfig;
16
+ mvu_enabled?: boolean;
17
+ }): GreetingValidationResult;
@@ -0,0 +1,79 @@
1
+ import { lintContent } from "./content-lint.js";
2
+ const USER_PRESET_PATTERNS = [
3
+ { pattern: /你(?:穿着|长着|有着|拥有|露出|坐在自己的房间|躺在床上|刚刚醒来)/, message: "开场白疑似预设 user 外貌、服装、动作或所在房间" },
4
+ { pattern: /<user>(?:是|已经|正在|穿着|长着|拥有)/i, message: "开场白疑似预设 <user> 的状态或行动" },
5
+ { pattern: /你(?:是个|是一个|作为)(?:男|女|少年|少女|学生|老师|贵族|平民)/, message: "开场白疑似预设 user 身份或性别" },
6
+ ];
7
+ export function validateGreetings(input) {
8
+ const errors = [];
9
+ const warnings = [];
10
+ const { config, mvu_enabled = false } = input;
11
+ const greetings = [config.card.first_mes, ...config.card.alternate_greetings];
12
+ if (!config.card.first_mes.trim()) {
13
+ errors.push({ field: "card.first_mes", severity: "error", message: "first_mes 必填" });
14
+ }
15
+ if (config.card.alternate_greetings.length < 2) {
16
+ warnings.push({ field: "card.alternate_greetings", severity: "warning", message: "建议提供 2-4 个 alternate_greetings" });
17
+ }
18
+ if (config.card.alternate_greetings.length > 4) {
19
+ warnings.push({ field: "card.alternate_greetings", severity: "warning", message: "alternate_greetings 建议控制在 2-4 个,避免维护成本过高" });
20
+ }
21
+ greetings.forEach((greeting, index) => {
22
+ const field = index === 0 ? "card.first_mes" : `card.alternate_greetings.${index - 1}`;
23
+ if (!greeting.trim()) {
24
+ if (index > 0)
25
+ warnings.push({ field, severity: "warning", message: "alternate greeting 为空,可删除或补全" });
26
+ return;
27
+ }
28
+ checkGreetingStructure(greeting, field, warnings);
29
+ checkUserPreset(greeting, field, errors);
30
+ checkOpenEnding(greeting, field, warnings);
31
+ if (mvu_enabled && !greeting.includes("<StatusPlaceHolderImpl/>")) {
32
+ warnings.push({ field, severity: "warning", message: "启用 MVU 时开场白建议包含 <StatusPlaceHolderImpl/>" });
33
+ }
34
+ const lint = lintContent(greeting);
35
+ for (const issue of lint.issues) {
36
+ const target = issue.severity === "error" ? errors : warnings;
37
+ target.push({ field, severity: issue.severity, message: issue.term ? `开场白文本问题:${issue.term}` : issue.message, suggestion: issue.suggestion });
38
+ }
39
+ });
40
+ return {
41
+ valid: errors.length === 0,
42
+ errors,
43
+ warnings,
44
+ summary: {
45
+ first_mes_present: Boolean(config.card.first_mes.trim()),
46
+ alternate_greeting_count: config.card.alternate_greetings.length,
47
+ total_greeting_count: greetings.length,
48
+ mvu_placeholder_required: mvu_enabled,
49
+ },
50
+ };
51
+ }
52
+ function checkGreetingStructure(greeting, field, warnings) {
53
+ if (!/(清晨|上午|中午|午后|下午|傍晚|夜|深夜|凌晨|黄昏|雨|雪|风|阳光|灯光|房间|街|城|店|庭院|走廊|门口|窗边|桌前)/.test(greeting)) {
54
+ warnings.push({ field, severity: "warning", message: "开场白建议交代可感知的时间或地点" });
55
+ }
56
+ if (!/(站|坐|停|看|拿|放|推|走|靠|抬|低|开口|沉默|等待|整理|握|递)/.test(greeting)) {
57
+ warnings.push({ field, severity: "warning", message: "开场白建议包含角色当前状态或动作" });
58
+ }
59
+ if (!/(你|<user>|用户|来客|对方)/i.test(greeting)) {
60
+ warnings.push({ field, severity: "warning", message: "开场白建议给 user 留出明确互动位置" });
61
+ }
62
+ }
63
+ function checkUserPreset(greeting, field, errors) {
64
+ for (const item of USER_PRESET_PATTERNS) {
65
+ if (item.pattern.test(greeting)) {
66
+ errors.push({ field, severity: "error", message: item.message, suggestion: "只描写角色可观察到的环境和互动契机,不替 user 决定身份、外貌、行动或房间" });
67
+ }
68
+ }
69
+ }
70
+ function checkOpenEnding(greeting, field, warnings) {
71
+ const trimmed = greeting.trim();
72
+ if (!/[??。…]$/.test(trimmed)) {
73
+ warnings.push({ field, severity: "warning", message: "开场白建议以可接续的句子收束,避免戛然而止" });
74
+ }
75
+ if (/(然后你|于是你|你只好|你必须|你不得不|你回答|你走上前|你伸手)/.test(greeting)) {
76
+ warnings.push({ field, severity: "warning", message: "开场白结尾疑似预设 user 后续行动,应改为开放式互动契机" });
77
+ }
78
+ }
79
+ //# sourceMappingURL=greeting-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"greeting-validator.js","sourceRoot":"","sources":["../../src/core/greeting-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { HtmlBeautifyConfig } from "../schemas/html-beautify.js";
2
+ import type { RegexScriptAsset } from "./mvu-assets.js";
3
+ export interface HtmlBeautifyAssets {
4
+ regexScripts: RegexScriptAsset[];
5
+ }
6
+ export declare function buildHtmlBeautifyAssets(html: HtmlBeautifyConfig): HtmlBeautifyAssets;
@@ -0,0 +1,59 @@
1
+ export function buildHtmlBeautifyAssets(html) {
2
+ if (!html.enabled)
3
+ return { regexScripts: [] };
4
+ const scripts = [];
5
+ if (html.statusbar.enabled && (html.target === "statusbar" || html.target === "both")) {
6
+ scripts.push(regexScript({
7
+ scriptName: "[界面]状态栏",
8
+ findRegex: "/<StatusPlaceHolderImpl\\/>/gs",
9
+ replaceString: html.statusbar.html,
10
+ markdownOnly: true,
11
+ promptOnly: false,
12
+ placement: [2],
13
+ runOnEdit: true,
14
+ }));
15
+ if (html.statusbar.hide_regex) {
16
+ scripts.push(regexScript({
17
+ scriptName: "[不发送]界面占位符",
18
+ findRegex: "/<StatusPlaceHolderImpl\\/>/gs",
19
+ replaceString: "",
20
+ markdownOnly: false,
21
+ promptOnly: true,
22
+ placement: [2],
23
+ runOnEdit: true,
24
+ }));
25
+ }
26
+ }
27
+ if (html.global.enabled && (html.target === "global" || html.target === "both")) {
28
+ scripts.push(...html.global.regex_scripts.map(fromConfig));
29
+ }
30
+ return { regexScripts: scripts };
31
+ }
32
+ function fromConfig(config) {
33
+ return regexScript({
34
+ scriptName: config.name,
35
+ findRegex: config.findRegex,
36
+ replaceString: config.replaceString,
37
+ markdownOnly: config.markdownOnly,
38
+ promptOnly: config.promptOnly,
39
+ placement: config.placement,
40
+ runOnEdit: config.runOnEdit,
41
+ });
42
+ }
43
+ function regexScript(input) {
44
+ return {
45
+ scriptName: input.scriptName,
46
+ findRegex: input.findRegex,
47
+ replaceString: input.replaceString,
48
+ trimStrings: [],
49
+ placement: input.placement ?? [2],
50
+ disabled: false,
51
+ markdownOnly: input.markdownOnly ?? true,
52
+ promptOnly: input.promptOnly ?? false,
53
+ runOnEdit: input.runOnEdit ?? false,
54
+ substituteRegex: input.substituteRegex ?? 0,
55
+ minDepth: input.minDepth ?? null,
56
+ maxDepth: input.maxDepth ?? null,
57
+ };
58
+ }
59
+ //# sourceMappingURL=html-beautify-assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-beautify-assets.js","sourceRoot":"","sources":["../../src/core/html-beautify-assets.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,uBAAuB,CAAC,IAAwB;IAC9D,IAAI,CAAC,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC/C,MAAM,OAAO,GAAuB,EAAE,CAAC;IAEvC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,CAAC;QACtF,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;YACvB,UAAU,EAAE,SAAS;YACrB,SAAS,EAAE,gCAAgC;YAC3C,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI;YAClC,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,CAAC,CAAC,CAAC;YACd,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC,CAAC;QACJ,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;gBACvB,UAAU,EAAE,YAAY;gBACxB,SAAS,EAAE,gCAAgC;gBAC3C,aAAa,EAAE,EAAE;gBACjB,YAAY,EAAE,KAAK;gBACnB,UAAU,EAAE,IAAI;gBAChB,SAAS,EAAE,CAAC,CAAC,CAAC;gBACd,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC,CAAC;QACN,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,UAAU,CAAC,MAA6B;IAC/C,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC,IAAI;QACvB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,KAAmG;IACtH,OAAO;QACL,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;QACjC,QAAQ,EAAE,KAAK;QACf,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;QACxC,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,KAAK;QACrC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK;QACnC,eAAe,EAAE,KAAK,CAAC,eAAe,IAAI,CAAC;QAC3C,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;QAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;KACjC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { HtmlBeautifyConfig } from "../schemas/html-beautify.js";
2
+ export declare function createHtmlBeautifyTemplate(input: {
3
+ target: "statusbar" | "global" | "both";
4
+ theme: "minimal" | "dark" | "light" | "custom";
5
+ }): {
6
+ html: HtmlBeautifyConfig;
7
+ rules: string[];
8
+ };
@@ -0,0 +1,46 @@
1
+ export function createHtmlBeautifyTemplate(input) {
2
+ const statusbarEnabled = input.target === "statusbar" || input.target === "both";
3
+ const globalEnabled = input.target === "global" || input.target === "both";
4
+ return {
5
+ html: {
6
+ enabled: true,
7
+ target: input.target,
8
+ theme: input.theme,
9
+ statusbar: {
10
+ enabled: statusbarEnabled,
11
+ html: statusbarEnabled ? statusbarHtml(input.theme) : "",
12
+ hide_regex: true,
13
+ },
14
+ global: {
15
+ enabled: globalEnabled,
16
+ regex_scripts: globalEnabled ? [globalLineBreakRegex()] : [],
17
+ },
18
+ },
19
+ rules: [
20
+ "状态栏 HTML 不要包含 <script>",
21
+ "CSS 使用 .wbm-statusbar 作用域,避免污染全局",
22
+ "状态栏通常配合 MVU 和 <StatusPlaceHolderImpl/> 使用",
23
+ "全局美化 regex 必须确认不会破坏宏和代码块",
24
+ ],
25
+ };
26
+ }
27
+ function statusbarHtml(theme) {
28
+ const palette = theme === "dark"
29
+ ? { bg: "#171717", fg: "#f5f5f5", border: "#3f3f46" }
30
+ : theme === "light"
31
+ ? { bg: "#ffffff", fg: "#27272a", border: "#d4d4d8" }
32
+ : { bg: "rgba(24,24,27,.82)", fg: "#f4f4f5", border: "rgba(244,244,245,.18)" };
33
+ return `<style>\n.wbm-statusbar {\n box-sizing: border-box;\n width: 100%;\n margin: .75rem 0;\n padding: .75rem .9rem;\n border: 1px solid ${palette.border};\n border-radius: 12px;\n background: ${palette.bg};\n color: ${palette.fg};\n font-size: 13px;\n line-height: 1.6;\n white-space: pre-wrap;\n}\n.wbm-statusbar__title {\n font-weight: 700;\n margin-bottom: .35rem;\n}\n</style>\n<div class="wbm-statusbar">\n <div class="wbm-statusbar__title">状态</div>\n <div class="wbm-statusbar__content">{{format_message_variable::stat_data}}</div>\n</div>`;
34
+ }
35
+ function globalLineBreakRegex() {
36
+ return {
37
+ name: "[美化]保留换行",
38
+ findRegex: "/\\n/g",
39
+ replaceString: "\n",
40
+ markdownOnly: true,
41
+ promptOnly: false,
42
+ placement: [2],
43
+ runOnEdit: true,
44
+ };
45
+ }
46
+ //# sourceMappingURL=html-beautify-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-beautify-template.js","sourceRoot":"","sources":["../../src/core/html-beautify-template.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,0BAA0B,CAAC,KAAkG;IAC3I,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,KAAK,WAAW,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC;IACjF,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC;IAC3E,OAAO;QACL,IAAI,EAAE;YACJ,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,SAAS,EAAE;gBACT,OAAO,EAAE,gBAAgB;gBACzB,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;gBACxD,UAAU,EAAE,IAAI;aACjB;YACD,MAAM,EAAE;gBACN,OAAO,EAAE,aAAa;gBACtB,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;aAC7D;SACF;QACD,KAAK,EAAE;YACL,wBAAwB;YACxB,kCAAkC;YAClC,2CAA2C;YAC3C,0BAA0B;SAC3B;KACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,OAAO,GAAG,KAAK,KAAK,MAAM;QAC9B,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE;QACrD,CAAC,CAAC,KAAK,KAAK,OAAO;YACjB,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE;YACrD,CAAC,CAAC,EAAE,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;IACnF,OAAO,4IAA4I,OAAO,CAAC,MAAM,4CAA4C,OAAO,CAAC,EAAE,eAAe,OAAO,CAAC,EAAE,qUAAqU,CAAC;AACxjB,CAAC;AAED,SAAS,oBAAoB;IAC3B,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,SAAS,EAAE,QAAQ;QACnB,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,KAAK;QACjB,SAAS,EAAE,CAAC,CAAC,CAAC;QACd,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { CharacterCardConfig } from "../schemas/character-card.js";
2
+ import type { HtmlBeautifyConfig } from "../schemas/html-beautify.js";
3
+ import type { MvuConfig } from "../schemas/mvu.js";
4
+ import type { ValidationIssue } from "./worldbook-validator.js";
5
+ export interface HtmlBeautifyValidationResult {
6
+ valid: boolean;
7
+ errors: ValidationIssue[];
8
+ warnings: ValidationIssue[];
9
+ summary: {
10
+ enabled: boolean;
11
+ target: string;
12
+ statusbar_enabled: boolean;
13
+ global_enabled: boolean;
14
+ regex_count: number;
15
+ };
16
+ }
17
+ export declare function validateHtmlBeautifyConfig(input: {
18
+ html: HtmlBeautifyConfig;
19
+ mvu?: MvuConfig;
20
+ characterCardConfig?: CharacterCardConfig;
21
+ }): HtmlBeautifyValidationResult;
@@ -0,0 +1,66 @@
1
+ export function validateHtmlBeautifyConfig(input) {
2
+ const { html, mvu, characterCardConfig } = input;
3
+ const errors = [];
4
+ const warnings = [];
5
+ if (!html.enabled)
6
+ return { valid: true, errors, warnings, summary: summary(html) };
7
+ const needsStatusbar = html.target === "statusbar" || html.target === "both";
8
+ const needsGlobal = html.target === "global" || html.target === "both";
9
+ if (needsStatusbar) {
10
+ if (!html.statusbar.enabled)
11
+ errors.push({ field: "statusbar.enabled", severity: "error", message: "target 包含 statusbar 时 statusbar.enabled 必须为 true" });
12
+ if (!html.statusbar.html.trim())
13
+ errors.push({ field: "statusbar.html", severity: "error", message: "statusbar.html 不能为空" });
14
+ if (/<script\b/i.test(html.statusbar.html))
15
+ warnings.push({ field: "statusbar.html", severity: "warning", message: "状态栏 HTML 包含 <script>,请确认安全性" });
16
+ if (/(^|[\s,{])(?:body|html|\*)\s*[{,]/i.test(html.statusbar.html))
17
+ warnings.push({ field: "statusbar.html", severity: "warning", message: "CSS 可能包含全局选择器,建议使用作用域 class" });
18
+ if (!html.statusbar.html.includes("wbm-statusbar"))
19
+ warnings.push({ field: "statusbar.html", severity: "warning", message: "建议包含 wbm-statusbar 作用域 class" });
20
+ if (/https?:\/\/|@import|<link\b|<img\b[^>]+src=["']https?:/i.test(html.statusbar.html))
21
+ errors.push({ field: "statusbar.html", severity: "error", message: "HTML 美化不得依赖外部 URL、外部字体或外部图片" });
22
+ if (/\b(?:let|const)\b|=>/.test(html.statusbar.html))
23
+ warnings.push({ field: "statusbar.html", severity: "warning", message: "酒馆内嵌环境建议使用 var 和 function,避免 let/const/箭头函数" });
24
+ if (/[^d]vh\b/.test(html.statusbar.html))
25
+ warnings.push({ field: "statusbar.html", severity: "warning", message: "高度单位建议使用 dvh,并提供必要降级" });
26
+ if (!/prefers-reduced-motion/.test(html.statusbar.html))
27
+ warnings.push({ field: "statusbar.html", severity: "warning", message: "建议添加 prefers-reduced-motion 动画降级" });
28
+ if (/[❤💖💗⭐✨🔥]/u.test(html.statusbar.html))
29
+ warnings.push({ field: "statusbar.html", severity: "warning", message: "图标建议使用内联 SVG,避免 emoji 跨平台差异" });
30
+ if (!mvu?.enabled)
31
+ warnings.push({ field: "statusbar", severity: "warning", message: "状态栏通常配合 MVU 使用;当前项目未启用 MVU" });
32
+ if (characterCardConfig) {
33
+ const greetings = [characterCardConfig.card.first_mes, ...characterCardConfig.card.alternate_greetings];
34
+ greetings.forEach((greeting, index) => {
35
+ if (!greeting.includes("<StatusPlaceHolderImpl/>")) {
36
+ warnings.push({ field: index === 0 ? "card.first_mes" : `card.alternate_greetings.${index - 1}`, severity: "warning", message: "状态栏启用时开场白建议包含 <StatusPlaceHolderImpl/>" });
37
+ }
38
+ });
39
+ }
40
+ }
41
+ if (needsGlobal) {
42
+ if (!html.global.enabled)
43
+ errors.push({ field: "global.enabled", severity: "error", message: "target 包含 global 时 global.enabled 必须为 true" });
44
+ if (html.global.regex_scripts.length === 0)
45
+ errors.push({ field: "global.regex_scripts", severity: "error", message: "全局美化至少需要一个 regex script" });
46
+ html.global.regex_scripts.forEach((script, index) => {
47
+ if (!script.name.trim())
48
+ errors.push({ field: `global.regex_scripts.${index}.name`, severity: "error", message: "regex script name 不能为空" });
49
+ if (!script.findRegex.trim())
50
+ errors.push({ field: `global.regex_scripts.${index}.findRegex`, severity: "error", message: "regex script findRegex 不能为空" });
51
+ if (script.placement.length === 0)
52
+ errors.push({ field: `global.regex_scripts.${index}.placement`, severity: "error", message: "regex script placement 不能为空" });
53
+ });
54
+ }
55
+ return { valid: errors.length === 0, errors, warnings, summary: summary(html) };
56
+ }
57
+ function summary(html) {
58
+ return {
59
+ enabled: html.enabled,
60
+ target: html.target,
61
+ statusbar_enabled: html.statusbar.enabled,
62
+ global_enabled: html.global.enabled,
63
+ regex_count: html.global.regex_scripts.length + (html.statusbar.enabled ? 1 : 0) + (html.statusbar.hide_regex ? 1 : 0),
64
+ };
65
+ }
66
+ //# sourceMappingURL=html-beautify-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-beautify-validator.js","sourceRoot":"","sources":["../../src/core/html-beautify-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { RegexScriptAsset } from "./mvu-assets.js";
2
+ export type RegexPairScope = "statusbar" | "global" | "start_picker";
3
+ export interface HtmlRegexPairInput {
4
+ scope: RegexPairScope;
5
+ find_regex?: string;
6
+ display_html: string;
7
+ hide_regex?: boolean;
8
+ display_name?: string;
9
+ hide_name?: string;
10
+ placement?: number[];
11
+ min_depth?: number | null;
12
+ max_depth?: number | null;
13
+ }
14
+ export interface HtmlRegexPairResult {
15
+ scripts: RegexScriptAsset[];
16
+ rules: string[];
17
+ }
18
+ export declare function createHtmlRegexPairTemplate(input: HtmlRegexPairInput): HtmlRegexPairResult;
@@ -0,0 +1,77 @@
1
+ const DEFAULT_FIND = {
2
+ statusbar: "/<StatusPlaceHolderImpl\\/>/gs",
3
+ global: "/(.*)<StatusPlaceHolderImpl\\/>/gs",
4
+ start_picker: "/<start>([\\s\\S]*?)<\\/start>/g",
5
+ };
6
+ export function createHtmlRegexPairTemplate(input) {
7
+ const findRegex = input.find_regex ?? DEFAULT_FIND[input.scope];
8
+ const placement = input.placement ?? [1, 2];
9
+ const display_name = input.display_name ?? defaultDisplayName(input.scope);
10
+ const hide_name = input.hide_name ?? defaultHideName(input.scope);
11
+ const hideRegex = input.hide_regex ?? true;
12
+ const scripts = [];
13
+ scripts.push(buildScript({
14
+ scriptName: display_name,
15
+ findRegex,
16
+ replaceString: input.display_html,
17
+ markdownOnly: true,
18
+ promptOnly: false,
19
+ placement,
20
+ runOnEdit: true,
21
+ minDepth: input.min_depth ?? null,
22
+ maxDepth: input.max_depth ?? null,
23
+ }));
24
+ if (hideRegex) {
25
+ scripts.push(buildScript({
26
+ scriptName: hide_name,
27
+ findRegex,
28
+ replaceString: input.scope === "global" ? "$1" : "",
29
+ markdownOnly: false,
30
+ promptOnly: true,
31
+ placement,
32
+ runOnEdit: true,
33
+ minDepth: input.min_depth ?? null,
34
+ maxDepth: input.max_depth ?? null,
35
+ }));
36
+ }
37
+ return {
38
+ scripts,
39
+ rules: [
40
+ "display 与 prompt 两条 regex 必须使用相同 findRegex",
41
+ "promptOnly 规则的 replaceString 必须留空(global 范围允许保留 $1 捕获原文)",
42
+ "全局美化时 replaceString 必须包含 <StatusPlaceHolderImpl/> 占位以兼容状态栏",
43
+ "placement 推荐 [1,2],runOnEdit 设为 true",
44
+ ],
45
+ };
46
+ }
47
+ function defaultDisplayName(scope) {
48
+ if (scope === "statusbar")
49
+ return "[界面]状态栏";
50
+ if (scope === "global")
51
+ return "[界面]全局美化";
52
+ return "[界面]开场选择";
53
+ }
54
+ function defaultHideName(scope) {
55
+ if (scope === "statusbar")
56
+ return "[不发送]界面占位符";
57
+ if (scope === "global")
58
+ return "[不发送]全局美化原文";
59
+ return "[不发送]开场选择原文";
60
+ }
61
+ function buildScript(input) {
62
+ return {
63
+ scriptName: input.scriptName,
64
+ findRegex: input.findRegex,
65
+ replaceString: input.replaceString,
66
+ trimStrings: [],
67
+ placement: input.placement ?? [2],
68
+ disabled: false,
69
+ markdownOnly: input.markdownOnly ?? true,
70
+ promptOnly: input.promptOnly ?? false,
71
+ runOnEdit: input.runOnEdit ?? false,
72
+ substituteRegex: input.substituteRegex ?? 0,
73
+ minDepth: input.minDepth ?? null,
74
+ maxDepth: input.maxDepth ?? null,
75
+ };
76
+ }
77
+ //# sourceMappingURL=html-regex-pair.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-regex-pair.js","sourceRoot":"","sources":["../../src/core/html-regex-pair.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ValidationIssue } from "./worldbook-validator.js";
2
+ export type ItemKind = "clothing" | "special_item" | "weapon" | "ability" | "equipment" | "generic";
3
+ export declare function validateItemEntry(input: {
4
+ content: string;
5
+ item_kind: ItemKind;
6
+ }): {
7
+ valid: boolean;
8
+ errors: ValidationIssue[];
9
+ warnings: ValidationIssue[];
10
+ };
@@ -0,0 +1,27 @@
1
+ export function validateItemEntry(input) {
2
+ const warnings = [];
3
+ const errors = [];
4
+ const content = input.content;
5
+ if (!/^\s*<([a-zA-Z_][\w-]*)>[\s\S]*<\/\1>\s*$/.test(content))
6
+ warnings.push({ field: "content", severity: "warning", message: "物品/能力条目建议使用 XML 包裹 YAML" });
7
+ if (input.item_kind === "clothing") {
8
+ if (/优点|缺点|舒适|显瘦|耐洗|不耐洗|穿着感|手感/.test(content))
9
+ warnings.push({ field: "content", severity: "warning", message: "服装条目只写外观、材质、剪裁、颜色,不写优缺点或穿着感受" });
10
+ }
11
+ if (input.item_kind === "special_item") {
12
+ if (/\d+(?:\.\d+)?\s*(?:厘米|cm|CM|毫米|mm|MM)/.test(content))
13
+ warnings.push({ field: "content", severity: "warning", message: "特殊道具不建议写精确长度/直径尺寸,改写外形和玩法结构" });
14
+ }
15
+ if (input.item_kind === "weapon") {
16
+ if (/威力巨大|精准度极高|最爱|无坚不摧|毁天灭地|强大/.test(content))
17
+ warnings.push({ field: "content", severity: "warning", message: "武器条目不要写评测式夸赞,写类型、弹种、结构和实际用途" });
18
+ }
19
+ if (input.item_kind === "ability") {
20
+ if (/强大|无敌|无所不能|威力巨大/.test(content))
21
+ warnings.push({ field: "content", severity: "warning", message: "能力条目应写具体效果、限制和代价,不写空泛强度标签" });
22
+ if (!/限制|代价|limits|effects|效果/.test(content))
23
+ warnings.push({ field: "content", severity: "warning", message: "能力条目建议包含 effects 与 limits/代价" });
24
+ }
25
+ return { valid: errors.length === 0, errors, warnings };
26
+ }
27
+ //# sourceMappingURL=item-entry-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"item-entry-validator.js","sourceRoot":"","sources":["../../src/core/item-entry-validator.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,iBAAiB,CAAC,KAA+C;IAC/E,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAE9B,IAAI,CAAC,0CAA0C,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC,CAAC;IAE5J,IAAI,KAAK,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;QACnC,IAAI,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC,CAAC;IACnJ,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,KAAK,cAAc,EAAE,CAAC;QACvC,IAAI,uCAAuC,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC,CAAC;IAC9J,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;QACjC,IAAI,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC,CAAC;IACnJ,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAClC,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC,CAAC;QACpI,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC,CAAC;IAClJ,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { MvuConfig } from "../schemas/mvu.js";
2
+ import type { WorldbookDraftEntry } from "../schemas/worldbook-draft.js";
3
+ export interface RegexScriptAsset {
4
+ id?: string;
5
+ scriptName: string;
6
+ findRegex: string;
7
+ replaceString: string;
8
+ trimStrings: string[];
9
+ placement: number[];
10
+ disabled: boolean;
11
+ markdownOnly: boolean;
12
+ promptOnly: boolean;
13
+ runOnEdit: boolean;
14
+ substituteRegex: number;
15
+ minDepth: number | null;
16
+ maxDepth: number | null;
17
+ }
18
+ export interface TavernHelperScriptAsset {
19
+ type: "script";
20
+ enabled: boolean;
21
+ name: string;
22
+ id?: string;
23
+ content: string;
24
+ info: string;
25
+ button: {
26
+ enabled: boolean;
27
+ buttons: Array<{
28
+ name: string;
29
+ visible: boolean;
30
+ }>;
31
+ };
32
+ data: Record<string, unknown>;
33
+ }
34
+ export interface MvuAssets {
35
+ worldbookEntries: WorldbookDraftEntry[];
36
+ regexScripts: RegexScriptAsset[];
37
+ tavernHelperScripts: TavernHelperScriptAsset[];
38
+ }
39
+ export declare const DEFAULT_MVU_BUNDLE = "import 'https://testingcf.jsdelivr.net/gh/MagicalAstrogy/MagVarUpdate/artifact/bundle.js';";
40
+ export declare const DEFAULT_MVU_BUTTONS: {
41
+ name: string;
42
+ visible: boolean;
43
+ }[];
44
+ export declare function buildMvuAssets(mvu: MvuConfig): MvuAssets;