@capyclaw/ppt-workbench 0.0.0-stage → 2.4.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.
Files changed (130) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +126 -3
  3. package/THIRD_PARTY_NOTICES.md +21 -0
  4. package/contract/ppt-contract.json +1529 -0
  5. package/cordis.patch.yml +25 -0
  6. package/core/audit.js +500 -0
  7. package/core/chart.js +199 -0
  8. package/core/color.js +80 -0
  9. package/core/deck-layout.js +195 -0
  10. package/core/formula.js +80 -0
  11. package/core/hfmath/hershey.js +1763 -0
  12. package/core/hfmath/index.js +1176 -0
  13. package/core/hfmath/stretch.js +41 -0
  14. package/core/hfmath/symbols.js +408 -0
  15. package/core/ops/browser.js +28 -0
  16. package/core/ops/chart.js +64 -0
  17. package/core/ops/deck.js +21 -0
  18. package/core/ops/dispatcher.js +2 -0
  19. package/core/ops/element.js +55 -0
  20. package/core/ops/history.js +11 -0
  21. package/core/ops/import.js +95 -0
  22. package/core/ops/index.js +39 -0
  23. package/core/ops/playback.js +9 -0
  24. package/core/ops/recolor.js +33 -0
  25. package/core/ops/slide.js +66 -0
  26. package/core/ops/table.js +85 -0
  27. package/core/ops/text.js +35 -0
  28. package/core/ops/view.js +13 -0
  29. package/core/ops.js +12 -0
  30. package/core/quick.js +52 -0
  31. package/core/shape-library.js +122 -0
  32. package/core/table.js +178 -0
  33. package/core/text.js +200 -0
  34. package/editor/app.js +5366 -0
  35. package/editor/heartbeat-worker.js +116 -0
  36. package/editor/index.html +89 -0
  37. package/editor/ppt-full-app.js +376 -0
  38. package/lib/host.mjs +98 -0
  39. package/package.json +51 -4
  40. package/server/audit.mjs +2 -0
  41. package/server/bridge-client.mjs +174 -0
  42. package/server/constants.mjs +20 -0
  43. package/server/contract-snapshots.mjs +62 -0
  44. package/server/contract.mjs +24 -0
  45. package/server/deck-layout.mjs +2 -0
  46. package/server/http-utils.mjs +2 -0
  47. package/server/infra/http.mjs +113 -0
  48. package/server/infra/runtime/context.mjs +128 -0
  49. package/server/infra/store/blob-store.mjs +109 -0
  50. package/server/infra/tuning.mjs +82 -0
  51. package/server/infra/util/fs-lock.mjs +132 -0
  52. package/server/infra/workspace/manager.mjs +657 -0
  53. package/server/mcp/dispatch.mjs +2 -0
  54. package/server/mcp/handler.mjs +2 -0
  55. package/server/mcp/instructions.mjs +40 -0
  56. package/server/mcp-http.mjs +3 -0
  57. package/server/ppt-shim.mjs +156 -0
  58. package/server/relay.mjs +245 -0
  59. package/server/routes/assets.mjs +2 -0
  60. package/server/routes/bridge.mjs +47 -0
  61. package/server/routes/editor.mjs +9 -0
  62. package/server/routes/import.mjs +258 -0
  63. package/server/routes/mcp.mjs +17 -0
  64. package/server/runtime/recovery.mjs +9 -0
  65. package/server/runtime/watch.mjs +17 -0
  66. package/server/shared/SHARED_MANIFEST.json +47 -0
  67. package/server/shared/asset-service.mjs +217 -0
  68. package/server/shared/editor-host.mjs +125 -0
  69. package/server/shared/kit/editor/lease.mjs +139 -0
  70. package/server/shared/kit/service/api.mjs +45 -0
  71. package/server/shared/kit/service/http.mjs +113 -0
  72. package/server/shared/kit/service/mcp-http.mjs +142 -0
  73. package/server/shared/kit/service/single-instance.mjs +72 -0
  74. package/server/shared/kit/tools/validate.mjs +115 -0
  75. package/server/shared/kit/tuning.mjs +82 -0
  76. package/server/shared/kit/util/fs-lock.mjs +132 -0
  77. package/server/shared/service-host.mjs +511 -0
  78. package/server/shared/state-service.mjs +249 -0
  79. package/server/shared/tool-host.mjs +341 -0
  80. package/server/shared/tuning.mjs +63 -0
  81. package/server/single-instance.mjs +2 -0
  82. package/server/store/backends/file-backend.mjs +13 -0
  83. package/server/store/checkpoints.mjs +28 -0
  84. package/server/store/doc.mjs +52 -0
  85. package/server/store/index.mjs +34 -0
  86. package/server/store/journal.mjs +9 -0
  87. package/server/store/lease.mjs +2 -0
  88. package/server/store/sanitize.mjs +32 -0
  89. package/server/store.mjs +2 -0
  90. package/server/tools/capabilities/apply.mjs +33 -0
  91. package/server/tools/capabilities/audit.mjs +24 -0
  92. package/server/tools/capabilities/chart.mjs +83 -0
  93. package/server/tools/capabilities/compose.mjs +97 -0
  94. package/server/tools/capabilities/contract.mjs +34 -0
  95. package/server/tools/capabilities/deck.mjs +27 -0
  96. package/server/tools/capabilities/element.mjs +67 -0
  97. package/server/tools/capabilities/export.mjs +95 -0
  98. package/server/tools/capabilities/formula.mjs +72 -0
  99. package/server/tools/capabilities/history.mjs +29 -0
  100. package/server/tools/capabilities/image.mjs +152 -0
  101. package/server/tools/capabilities/imagesearch.mjs +152 -0
  102. package/server/tools/capabilities/import.mjs +180 -0
  103. package/server/tools/capabilities/index.mjs +58 -0
  104. package/server/tools/capabilities/line.mjs +58 -0
  105. package/server/tools/capabilities/notes.mjs +33 -0
  106. package/server/tools/capabilities/present.mjs +34 -0
  107. package/server/tools/capabilities/recolor.mjs +60 -0
  108. package/server/tools/capabilities/screenshot.mjs +86 -0
  109. package/server/tools/capabilities/shape.mjs +64 -0
  110. package/server/tools/capabilities/slide.mjs +81 -0
  111. package/server/tools/capabilities/style.mjs +48 -0
  112. package/server/tools/capabilities/table.mjs +127 -0
  113. package/server/tools/capabilities/task.mjs +52 -0
  114. package/server/tools/capabilities/text.mjs +82 -0
  115. package/server/tools/domains/color.mjs +4 -0
  116. package/server/tools/domains/image.mjs +49 -0
  117. package/server/tools/domains/index.mjs +7 -0
  118. package/server/tools/domains/pptx-export.mjs +566 -0
  119. package/server/tools/domains/recolor.mjs +25 -0
  120. package/server/tools/domains/remote-image.mjs +291 -0
  121. package/server/tools/domains/slide.mjs +21 -0
  122. package/server/tools/domains/text-style.mjs +11 -0
  123. package/server/tools/domains/tooling.mjs +13 -0
  124. package/server/tools/index.mjs +14 -0
  125. package/server/tools/kernel/define.mjs +5 -0
  126. package/server/tools/kernel/ports.mjs +42 -0
  127. package/server/tools/kernel/registry.mjs +17 -0
  128. package/server/tools.mjs +18 -0
  129. package/server/tuning.mjs +86 -0
  130. package/server/validate.mjs +2 -0
@@ -0,0 +1,41 @@
1
+ function curve(a, b, c, d, steps = 8) {
2
+ const points = [];
3
+ for (let i = 0; i <= steps; i++) {
4
+ const t = i / steps;
5
+ const u = 1 - t;
6
+ points.push([
7
+ u ** 3 * a[0] + 3 * u ** 2 * t * b[0] + 3 * u * t ** 2 * c[0] + t ** 3 * d[0],
8
+ u ** 3 * a[1] + 3 * u ** 2 * t * b[1] + 3 * u * t ** 2 * c[1] + t ** 3 * d[1]
9
+ ]);
10
+ }
11
+ return points;
12
+ }
13
+ function stretch(kind, width, height, reversed = false) {
14
+ let lines;
15
+ if (kind === "arrow") {
16
+ const head = Math.min(height, width / 2);
17
+ lines = [
18
+ [[0, height / 2], [width, height / 2]],
19
+ [[width - head, 0], [width, height / 2], [width - head, height]]
20
+ ];
21
+ } else if (kind === "brace") {
22
+ const cap = Math.min(width / 4, height * 0.8);
23
+ const mid = width / 2;
24
+ const half = height / 2;
25
+ lines = [[
26
+ ...curve([0, height], [0, half], [cap / 2, half], [cap, half]),
27
+ [mid - cap, half],
28
+ ...curve([mid - cap, half], [mid - cap / 2, half], [mid, half], [mid, 0]).slice(1),
29
+ ...curve([mid, 0], [mid, half], [mid + cap / 2, half], [mid + cap, half]).slice(1),
30
+ [width - cap, half],
31
+ ...curve([width - cap, half], [width - cap / 2, half], [width, half], [width, height]).slice(1)
32
+ ]];
33
+ } else {
34
+ lines = [curve([0, height], [0, -height / 3], [width, -height / 3], [width, height], 32)];
35
+ }
36
+ if (!reversed) return lines;
37
+ return lines.map((line) => line.map(([x, y]) => kind === "arrow" ? [width - x, y] : [x, height - y]));
38
+ }
39
+ export {
40
+ stretch
41
+ };
@@ -0,0 +1,408 @@
1
+ const SYMB = {
2
+ "\\frac": { glyph: 0, arity: 2, flags: { frac: true } },
3
+ "\\dfrac": { glyph: 0, arity: 2, flags: { frac: true } },
4
+ "\\tfrac": { glyph: 0, arity: 2, flags: { frac: true } },
5
+ "\\binom": { glyph: 0, arity: 2, flags: { binom: true } },
6
+ "\\dbinom": { glyph: 0, arity: 2, flags: { binom: true } },
7
+ "\\tbinom": { glyph: 0, arity: 2, flags: { binom: true } },
8
+ "\\overset": { glyph: 0, arity: 2, flags: { above: true } },
9
+ "\\stackrel": { glyph: 0, arity: 2, flags: { above: true } },
10
+ "\\underset": { glyph: 0, arity: 2, flags: { below: true } },
11
+ "\\xrightarrow": { glyph: 0, arity: 1, flags: { xarrow: true, opt: true } },
12
+ "\\xleftarrow": { glyph: 0, arity: 1, flags: { xarrow: true, opt: true, left: true } },
13
+ "\\operatorname": { glyph: 0, arity: 1, flags: {} },
14
+ "\\operatorname*": { glyph: 0, arity: 1, flags: { big: true } },
15
+ "\\sqrt": { glyph: 2267, arity: 1, flags: { opt: true, xfl: true, yfl: true } },
16
+ "^": { glyph: 0, arity: 1, flags: {} },
17
+ "_": { glyph: 0, arity: 1, flags: {} },
18
+ "(": { glyph: 2221, arity: 0, flags: { yfl: true } },
19
+ ")": { glyph: 2222, arity: 0, flags: { yfl: true } },
20
+ "[": { glyph: 2223, arity: 0, flags: { yfl: true } },
21
+ "]": { glyph: 2224, arity: 0, flags: { yfl: true } },
22
+ "\\langle": { glyph: 2227, arity: 0, flags: { yfl: true } },
23
+ "\\rangle": { glyph: 2228, arity: 0, flags: { yfl: true } },
24
+ "|": { glyph: 2229, arity: 0, flags: { yfl: true } },
25
+ "\\|": { glyph: 2230, arity: 0, flags: { yfl: true } },
26
+ "\\{": { glyph: 2225, arity: 0, flags: { yfl: true } },
27
+ "\\}": { glyph: 2226, arity: 0, flags: { yfl: true } },
28
+ "\\lparen": { glyph: 2221, flags: { yfl: true } },
29
+ "\\rparen": { glyph: 2222, flags: { yfl: true } },
30
+ "\\lbrack": { glyph: 2223, flags: { yfl: true } },
31
+ "\\rbrack": { glyph: 2224, flags: { yfl: true } },
32
+ "\\lbrace": { glyph: 2225, flags: { yfl: true } },
33
+ "\\rbrace": { glyph: 2226, flags: { yfl: true } },
34
+ "\\lvert": { glyph: 2229, flags: { yfl: true } },
35
+ "\\rvert": { glyph: 2229, flags: { yfl: true } },
36
+ "\\vert": { glyph: 2229, flags: { yfl: true } },
37
+ "\\lVert": { glyph: 2230, flags: { yfl: true } },
38
+ "\\rVert": { glyph: 2230, flags: { yfl: true } },
39
+ "\\Vert": { glyph: 2230, flags: { yfl: true } },
40
+ "\\lfloor": { glyph: 5051, flags: { yfl: true } },
41
+ "\\rfloor": { glyph: 5052, flags: { yfl: true } },
42
+ "\\lceil": { glyph: 5053, flags: { yfl: true } },
43
+ "\\rceil": { glyph: 5054, flags: { yfl: true } },
44
+ "\\backslash": { glyph: 5055, flags: { yfl: true } },
45
+ "\\#": { glyph: 2275, arity: 0, flags: {} },
46
+ "\\$": { glyph: 2274, arity: 0, flags: {} },
47
+ "\\&": { glyph: 2273, arity: 0, flags: {} },
48
+ "\\%": { glyph: 2271, arity: 0, flags: {} },
49
+ /* semantics*/
50
+ "\\begin": { glyph: 0, arity: 1, flags: {} },
51
+ "\\end": { glyph: 0, arity: 1, flags: {} },
52
+ "\\left": { glyph: 0, arity: 1, flags: {} },
53
+ "\\right": { glyph: 0, arity: 1, flags: {} },
54
+ "\\middle": { glyph: 0, arity: 1, flags: {} },
55
+ "\\big": { glyph: 0, arity: 1, size: 1.2, flags: {} },
56
+ "\\bigl": { glyph: 0, arity: 1, size: 1.2, flags: {} },
57
+ "\\bigr": { glyph: 0, arity: 1, size: 1.2, flags: {} },
58
+ "\\bigm": { glyph: 0, arity: 1, size: 1.2, flags: {} },
59
+ "\\Big": { glyph: 0, arity: 1, size: 1.6, flags: {} },
60
+ "\\Bigl": { glyph: 0, arity: 1, size: 1.6, flags: {} },
61
+ "\\Bigr": { glyph: 0, arity: 1, size: 1.6, flags: {} },
62
+ "\\Bigm": { glyph: 0, arity: 1, size: 1.6, flags: {} },
63
+ "\\bigg": { glyph: 0, arity: 1, size: 2, flags: {} },
64
+ "\\biggl": { glyph: 0, arity: 1, size: 2, flags: {} },
65
+ "\\biggr": { glyph: 0, arity: 1, size: 2, flags: {} },
66
+ "\\biggm": { glyph: 0, arity: 1, size: 2, flags: {} },
67
+ "\\Bigg": { glyph: 0, arity: 1, size: 2.5, flags: {} },
68
+ "\\Biggl": { glyph: 0, arity: 1, size: 2.5, flags: {} },
69
+ "\\Biggr": { glyph: 0, arity: 1, size: 2.5, flags: {} },
70
+ "\\Biggm": { glyph: 0, arity: 1, size: 2.5, flags: {} },
71
+ /* operators*/
72
+ "\\cdot": { glyph: 2236, arity: 0, flags: {} },
73
+ "\\pm": { glyph: 2233, arity: 0, flags: {} },
74
+ "\\mp": { glyph: 2234, arity: 0, flags: {} },
75
+ "\\times": { glyph: 2235, arity: 0, flags: {} },
76
+ "\\div": { glyph: 2237, arity: 0, flags: {} },
77
+ "\\leqq": { glyph: 2243, arity: 0, flags: {} },
78
+ "\\geqq": { glyph: 2244, arity: 0, flags: {} },
79
+ "\\leq": { glyph: 2243, arity: 0, flags: {} },
80
+ "\\geq": { glyph: 2244, arity: 0, flags: {} },
81
+ "\\propto": { glyph: 2245, arity: 0, flags: {} },
82
+ "\\sim": { glyph: 2246, arity: 0, flags: {} },
83
+ "\\equiv": { glyph: 2240, arity: 0, flags: {} },
84
+ "\\dagger": { glyph: 2277, arity: 0, flags: {} },
85
+ "\\ddagger": { glyph: 2278, arity: 0, flags: {} },
86
+ "\\ell": { glyph: 662, arity: 0, flags: {} },
87
+ "\\otimes": { glyph: 5035, flags: {} },
88
+ "\\ominus": { glyph: 5036, flags: {} },
89
+ "\\oslash": { glyph: 5037, flags: {} },
90
+ "\\uplus": { glyph: 5038, flags: {} },
91
+ "\\parallel": { glyph: 5039, flags: {} },
92
+ "\\nparallel": { glyph: 5040, flags: {} },
93
+ "\\nmid": { glyph: 5041, flags: {} },
94
+ "\\ll": { glyph: 5042, flags: {} },
95
+ "\\gg": { glyph: 5043, flags: {} },
96
+ "\\cong": { glyph: 5044, flags: {} },
97
+ "\\asymp": { glyph: 5045, flags: {} },
98
+ "\\prec": { glyph: 5046, flags: {} },
99
+ "\\succ": { glyph: 5047, flags: {} },
100
+ "\\preceq": { glyph: 5048, flags: {} },
101
+ "\\succeq": { glyph: 5049, flags: {} },
102
+ "\\vdash": { glyph: 5056, flags: {} },
103
+ "\\dashv": { glyph: 5057, flags: {} },
104
+ "\\models": { glyph: 5058, flags: {} },
105
+ /* ellipses: dots selects the baseline or centered form from its context. */
106
+ "\\dots": { glyph: 5030, flags: {} },
107
+ "\\ldots": { glyph: 5030, flags: {} },
108
+ "\\cdots": { glyph: 5031, flags: {} },
109
+ "\\vdots": { glyph: 5032, flags: {} },
110
+ "\\ddots": { glyph: 5033, flags: {} },
111
+ /* accents*/
112
+ "\\vec": { glyph: 2261, arity: 1, flags: { hat: true, xfl: true, yfl: true } },
113
+ "\\overrightarrow": { glyph: 2261, arity: 1, flags: { hat: true, xfl: true, yfl: true } },
114
+ "\\overleftarrow": { glyph: 2263, arity: 1, flags: { hat: true, xfl: true, yfl: true } },
115
+ "\\bar": { glyph: 2231, arity: 1, flags: { hat: true, xfl: true } },
116
+ "\\overline": { glyph: 2231, arity: 1, flags: { hat: true, xfl: true } },
117
+ "\\widehat": { glyph: 2247, arity: 1, flags: { hat: true, xfl: true, yfl: true } },
118
+ "\\hat": { glyph: 2247, arity: 1, flags: { hat: true } },
119
+ "\\acute": { glyph: 2248, arity: 1, flags: { hat: true } },
120
+ "\\grave": { glyph: 2249, arity: 1, flags: { hat: true } },
121
+ "\\breve": { glyph: 2250, arity: 1, flags: { hat: true } },
122
+ "\\tilde": { glyph: 2246, arity: 1, flags: { hat: true } },
123
+ "\\underline": { glyph: 2231, arity: 1, flags: { mat: true, xfl: true } },
124
+ "\\dot": { glyph: 2236, arity: 1, flags: { hat: true } },
125
+ "\\ddot": { glyph: 5034, arity: 1, flags: { hat: true } },
126
+ "\\check": { glyph: 5059, arity: 1, flags: { hat: true } },
127
+ "\\mathring": { glyph: 5060, arity: 1, flags: { hat: true } },
128
+ "\\widetilde": { glyph: 2246, arity: 1, flags: { hat: true, xfl: true, yfl: true } },
129
+ "\\overleftrightarrow": { glyph: 5015, arity: 1, flags: { hat: true, xfl: true, yfl: true } },
130
+ "\\boxed": { glyph: 5050, arity: 1, flags: { xfl: true, yfl: true } },
131
+ "\\overbrace": { glyph: 0, arity: 1, flags: { group: true, brace: true } },
132
+ "\\underbrace": { glyph: 0, arity: 1, flags: { group: true, brace: true, under: true } },
133
+ "\\overparen": { glyph: 0, arity: 1, flags: { group: true } },
134
+ "\\underparen": { glyph: 0, arity: 1, flags: { group: true, under: true } },
135
+ "\\not": { glyph: 2220, arity: 1, flags: {} },
136
+ "\\neq": { glyph: 2239, arity: 0, flags: {} },
137
+ "\\ne": { glyph: 2239, arity: 0, flags: {} },
138
+ "\\le": { glyph: 2243, flags: {} },
139
+ "\\ge": { glyph: 2244, flags: {} },
140
+ "\\approx": { glyph: 5011, flags: {} },
141
+ "\\simeq": { glyph: 5012, flags: {} },
142
+ "\\forall": { glyph: 5e3, flags: {} },
143
+ "\\nexists": { glyph: 5001, flags: {} },
144
+ "\\notin": { glyph: 5002, flags: {} },
145
+ "\\ni": { glyph: 5003, flags: {} },
146
+ "\\owns": { glyph: 5003, flags: {} },
147
+ "\\emptyset": { glyph: 5004, flags: {} },
148
+ "\\varnothing": { glyph: 5004, flags: {} },
149
+ "\\subseteq": { glyph: 5005, flags: {} },
150
+ "\\supseteq": { glyph: 5006, flags: {} },
151
+ "\\nsubseteq": { glyph: 5007, flags: {} },
152
+ "\\nsupseteq": { glyph: 5008, flags: {} },
153
+ "\\land": { glyph: 5009, flags: {} },
154
+ "\\wedge": { glyph: 5009, flags: {} },
155
+ "\\lor": { glyph: 5010, flags: {} },
156
+ "\\vee": { glyph: 5010, flags: {} },
157
+ "\\neg": { glyph: 5013, flags: {} },
158
+ "\\lnot": { glyph: 5013, flags: {} },
159
+ "\\setminus": { glyph: 5014, flags: {} },
160
+ "\\smallsetminus": { glyph: 5014, flags: {} },
161
+ "\\exists": { glyph: 2279, arity: 0, flags: {} },
162
+ "\\in": { glyph: 2260, arity: 0, flags: {} },
163
+ "\\subset": { glyph: 2256, arity: 0, flags: {} },
164
+ "\\supset": { glyph: 2258, arity: 0, flags: {} },
165
+ "\\cup": { glyph: 2257, arity: 0, flags: {} },
166
+ "\\cap": { glyph: 2259, arity: 0, flags: {} },
167
+ "\\infty": { glyph: 2270, arity: 0, flags: {} },
168
+ "\\partial": { glyph: 2265, arity: 0, flags: {} },
169
+ "\\nabla": { glyph: 2266, arity: 0, flags: {} },
170
+ "\\aleph": { glyph: 2077, arity: 0, flags: {} },
171
+ "\\wp": { glyph: 2190, arity: 0, flags: {} },
172
+ "\\therefore": { glyph: 740, arity: 0, flags: {} },
173
+ "\\mid": { glyph: 2229, arity: 0, flags: {} },
174
+ "\\sum": { glyph: 2402, arity: 0, flags: { big: true } },
175
+ "\\prod": { glyph: 2401, arity: 0, flags: { big: true } },
176
+ "\\bigoplus": { glyph: 2284, arity: 0, flags: { big: true } },
177
+ "\\bigodot": { glyph: 2281, arity: 0, flags: { big: true } },
178
+ "\\bigotimes": { glyph: 5035, flags: { big: true, xfl: true, yfl: true } },
179
+ "\\bigcup": { glyph: 2257, flags: { big: true, xfl: true, yfl: true } },
180
+ "\\bigcap": { glyph: 2259, flags: { big: true, xfl: true, yfl: true } },
181
+ "\\bigvee": { glyph: 5010, flags: { big: true, xfl: true, yfl: true } },
182
+ "\\bigwedge": { glyph: 5009, flags: { big: true, xfl: true, yfl: true } },
183
+ "\\biguplus": { glyph: 5038, flags: { big: true, xfl: true, yfl: true } },
184
+ "\\int": { glyph: 2412, arity: 0, flags: { yfl: true, integral: true } },
185
+ "\\oint": { glyph: 2269, arity: 0, flags: { yfl: true, integral: true } },
186
+ "\\iint": { glyph: 5020, flags: { yfl: true, integral: true } },
187
+ "\\iiint": { glyph: 5021, flags: { yfl: true, integral: true } },
188
+ "\\iiiint": { glyph: 5022, flags: { yfl: true, integral: true } },
189
+ "\\oplus": { glyph: 1284, arity: 0, flags: {} },
190
+ "\\odot": { glyph: 1281, arity: 0, flags: {} },
191
+ "\\perp": { glyph: 738, arity: 0, flags: {} },
192
+ "\\angle": { glyph: 739, arity: 0, flags: {} },
193
+ "\\triangle": { glyph: 842, arity: 0, flags: {} },
194
+ "\\Box": { glyph: 841, arity: 0, flags: {} },
195
+ "\\rightarrow": { glyph: 2261, arity: 0, flags: {} },
196
+ "\\to": { glyph: 2261, arity: 0, flags: {} },
197
+ "\\leftarrow": { glyph: 2263, arity: 0, flags: {} },
198
+ "\\gets": { glyph: 2263, arity: 0, flags: {} },
199
+ "\\leftrightarrow": { glyph: 5015, flags: {} },
200
+ "\\Rightarrow": { glyph: 5016, flags: {} },
201
+ "\\implies": { glyph: 5016, flags: {} },
202
+ "\\Leftarrow": { glyph: 5017, flags: {} },
203
+ "\\impliedby": { glyph: 5017, flags: {} },
204
+ "\\Leftrightarrow": { glyph: 5018, flags: {} },
205
+ "\\iff": { glyph: 5018, flags: {} },
206
+ "\\mapsto": { glyph: 5019, flags: {} },
207
+ "\\circ": { glyph: 902, arity: 0, flags: {} },
208
+ "\\bigcirc": { glyph: 904, arity: 0, flags: {} },
209
+ "\\bullet": { glyph: 828, arity: 0, flags: {} },
210
+ "\\star": { glyph: 856, arity: 0, flags: {} },
211
+ "\\diamond": { glyph: 743, arity: 0, flags: {} },
212
+ "\\ast": { glyph: 728, arity: 0, flags: {} },
213
+ /* verbatim symbols*/
214
+ "\\log": { glyph: 0, arity: 0, flags: { txt: true } },
215
+ "\\ln": { glyph: 0, arity: 0, flags: { txt: true } },
216
+ "\\exp": { glyph: 0, arity: 0, flags: { txt: true } },
217
+ "\\mod": { glyph: 0, arity: 0, flags: { txt: true } },
218
+ "\\lim": { glyph: 0, arity: 0, flags: { txt: true, big: true } },
219
+ "\\det": { glyph: 0, flags: { txt: true } },
220
+ "\\gcd": { glyph: 0, flags: { txt: true, big: true } },
221
+ "\\max": { glyph: 0, flags: { txt: true, big: true } },
222
+ "\\min": { glyph: 0, flags: { txt: true, big: true } },
223
+ "\\sup": { glyph: 0, flags: { txt: true, big: true } },
224
+ "\\inf": { glyph: 0, flags: { txt: true, big: true } },
225
+ "\\limsup": { glyph: 0, text: "lim sup", flags: { txt: true, big: true } },
226
+ "\\liminf": { glyph: 0, text: "lim inf", flags: { txt: true, big: true } },
227
+ "\\arg": { glyph: 0, flags: { txt: true } },
228
+ "\\ker": { glyph: 0, flags: { txt: true } },
229
+ "\\dim": { glyph: 0, flags: { txt: true } },
230
+ "\\deg": { glyph: 0, flags: { txt: true } },
231
+ "\\Pr": { glyph: 0, flags: { txt: true, big: true } },
232
+ "\\sin": { glyph: 0, arity: 0, flags: { txt: true } },
233
+ "\\cos": { glyph: 0, arity: 0, flags: { txt: true } },
234
+ "\\tan": { glyph: 0, arity: 0, flags: { txt: true } },
235
+ "\\csc": { glyph: 0, arity: 0, flags: { txt: true } },
236
+ "\\sec": { glyph: 0, arity: 0, flags: { txt: true } },
237
+ "\\cot": { glyph: 0, arity: 0, flags: { txt: true } },
238
+ "\\sinh": { glyph: 0, arity: 0, flags: { txt: true } },
239
+ "\\cosh": { glyph: 0, arity: 0, flags: { txt: true } },
240
+ "\\tanh": { glyph: 0, arity: 0, flags: { txt: true } },
241
+ "\\csch": { glyph: 0, arity: 0, flags: { txt: true } },
242
+ "\\sech": { glyph: 0, arity: 0, flags: { txt: true } },
243
+ "\\coth": { glyph: 0, arity: 0, flags: { txt: true } },
244
+ "\\arcsin": { glyph: 0, arity: 0, flags: { txt: true } },
245
+ "\\arccos": { glyph: 0, arity: 0, flags: { txt: true } },
246
+ "\\arctan": { glyph: 0, arity: 0, flags: { txt: true } },
247
+ "\\arccsc": { glyph: 0, arity: 0, flags: { txt: true } },
248
+ "\\arcsec": { glyph: 0, arity: 0, flags: { txt: true } },
249
+ "\\arccot": { glyph: 0, arity: 0, flags: { txt: true } },
250
+ /* font modes*/
251
+ "\\text": { glyph: 0, arity: 1, flags: {} },
252
+ "\\mathnormal": { glyph: 0, arity: 1, flags: {} },
253
+ "\\mathrm": { glyph: 0, arity: 1, flags: {} },
254
+ "\\mathit": { glyph: 0, arity: 1, flags: {} },
255
+ "\\mathbf": { glyph: 0, arity: 1, flags: {} },
256
+ "\\mathsf": { glyph: 0, arity: 1, flags: {} },
257
+ "\\mathtt": { glyph: 0, arity: 1, flags: {} },
258
+ "\\mathfrak": { glyph: 0, arity: 1, flags: {} },
259
+ "\\mathcal": { glyph: 0, arity: 1, flags: {} },
260
+ "\\mathbb": { glyph: 0, arity: 1, flags: {} },
261
+ "\\mathscr": { glyph: 0, arity: 1, flags: {} },
262
+ "\\rm": { glyph: 0, arity: 1, flags: {} },
263
+ "\\it": { glyph: 0, arity: 1, flags: {} },
264
+ "\\bf": { glyph: 0, arity: 1, flags: {} },
265
+ "\\sf": { glyph: 0, arity: 1, flags: {} },
266
+ "\\tt": { glyph: 0, arity: 1, flags: {} },
267
+ "\\frak": { glyph: 0, arity: 1, flags: {} },
268
+ "\\cal": { glyph: 0, arity: 1, flags: {} },
269
+ "\\bb": { glyph: 0, arity: 1, flags: {} },
270
+ "\\scr": { glyph: 0, arity: 1, flags: {} },
271
+ "\\quad": { glyph: 0, arity: 0, flags: {} },
272
+ "\\qquad": { glyph: 0, flags: {} },
273
+ "\\enspace": { glyph: 0, flags: {} },
274
+ "\\enskip": { glyph: 0, flags: {} },
275
+ "\\thinspace": { glyph: 0, flags: {} },
276
+ "\\medspace": { glyph: 0, flags: {} },
277
+ "\\thickspace": { glyph: 0, flags: {} },
278
+ "\\negthinspace": { glyph: 0, flags: {} },
279
+ "\\,": { glyph: 0, arity: 0, flags: {} },
280
+ "\\.": { glyph: 0, arity: 0, flags: {} },
281
+ "\\;": { glyph: 0, arity: 0, flags: {} },
282
+ "\\!": { glyph: 0, arity: 0, flags: {} },
283
+ /* greek letters*/
284
+ "\\alpha": { glyph: 2127, flags: {} },
285
+ "\\beta": { glyph: 2128, flags: {} },
286
+ "\\gamma": { glyph: 2129, flags: {} },
287
+ "\\delta": { glyph: 2130, flags: {} },
288
+ "\\varepsilon": { glyph: 2131, flags: {} },
289
+ "\\zeta": { glyph: 2132, flags: {} },
290
+ "\\eta": { glyph: 2133, flags: {} },
291
+ "\\vartheta": { glyph: 2134, flags: {} },
292
+ "\\iota": { glyph: 2135, flags: {} },
293
+ "\\kappa": { glyph: 2136, flags: {} },
294
+ "\\lambda": { glyph: 2137, flags: {} },
295
+ "\\mu": { glyph: 2138, flags: {} },
296
+ "\\nu": { glyph: 2139, flags: {} },
297
+ "\\xi": { glyph: 2140, flags: {} },
298
+ "\\omicron": { glyph: 2141, flags: {} },
299
+ "\\pi": { glyph: 2142, flags: {} },
300
+ "\\rho": { glyph: 2143, flags: {} },
301
+ "\\sigma": { glyph: 2144, flags: {} },
302
+ "\\tau": { glyph: 2145, flags: {} },
303
+ "\\upsilon": { glyph: 2146, flags: {} },
304
+ "\\varphi": { glyph: 2147, flags: {} },
305
+ "\\chi": { glyph: 2148, flags: {} },
306
+ "\\psi": { glyph: 2149, flags: {} },
307
+ "\\omega": { glyph: 2150, flags: {} },
308
+ "\\epsilon": { glyph: 2184, flags: {} },
309
+ "\\theta": { glyph: 2185, flags: {} },
310
+ "\\phi": { glyph: 2186, flags: {} },
311
+ "\\varsigma": { glyph: 2187, flags: {} },
312
+ "\\Alpha": { glyph: 2027, flags: {} },
313
+ "\\Beta": { glyph: 2028, flags: {} },
314
+ "\\Gamma": { glyph: 2029, flags: {} },
315
+ "\\Delta": { glyph: 2030, flags: {} },
316
+ "\\Epsilon": { glyph: 2031, flags: {} },
317
+ "\\Zeta": { glyph: 2032, flags: {} },
318
+ "\\Eta": { glyph: 2033, flags: {} },
319
+ "\\Theta": { glyph: 2034, flags: {} },
320
+ "\\Iota": { glyph: 2035, flags: {} },
321
+ "\\Kappa": { glyph: 2036, flags: {} },
322
+ "\\Lambda": { glyph: 2037, flags: {} },
323
+ "\\Mu": { glyph: 2038, flags: {} },
324
+ "\\Nu": { glyph: 2039, flags: {} },
325
+ "\\Xi": { glyph: 2040, flags: {} },
326
+ "\\Omicron": { glyph: 2041, flags: {} },
327
+ "\\Pi": { glyph: 2042, flags: {} },
328
+ "\\Rho": { glyph: 2043, flags: {} },
329
+ "\\Sigma": { glyph: 2044, flags: {} },
330
+ "\\Tau": { glyph: 2045, flags: {} },
331
+ "\\Upsilon": { glyph: 2046, flags: {} },
332
+ "\\Phi": { glyph: 2047, flags: {} },
333
+ "\\Chi": { glyph: 2048, flags: {} },
334
+ "\\Psi": { glyph: 2049, flags: {} },
335
+ "\\Omega": { glyph: 2050, flags: {} }
336
+ };
337
+ function asciiMap(x, mode = "math") {
338
+ const c = x.charCodeAt(0);
339
+ if (65 <= c && c <= 90) {
340
+ const d = c - 65;
341
+ if (mode === "text" || mode === "rm") {
342
+ return d + 2001;
343
+ } else if (mode === "tt") {
344
+ return d + 501;
345
+ } else if (mode === "bf" || mode === "bb") {
346
+ return d + 3001;
347
+ } else if (mode === "sf") {
348
+ return d + 2501;
349
+ } else if (mode === "frak") {
350
+ return d + 3301;
351
+ } else if (mode === "scr" || mode === "cal") {
352
+ return d + 2551;
353
+ }
354
+ return d + 2051;
355
+ }
356
+ if (97 <= c && c <= 122) {
357
+ const d = c - 97;
358
+ if (mode === "text" || mode === "rm") {
359
+ return d + 2101;
360
+ } else if (mode === "tt") {
361
+ return d + 601;
362
+ } else if (mode === "bf" || mode === "bb") {
363
+ return d + 3101;
364
+ } else if (mode === "sf") {
365
+ return d + 2601;
366
+ } else if (mode === "frak") {
367
+ return d + 3401;
368
+ } else if (mode === "scr" || mode === "cal") {
369
+ return d + 2651;
370
+ }
371
+ return d + 2151;
372
+ }
373
+ if (48 <= c && c <= 57) {
374
+ const d = c - 48;
375
+ if (mode === "it") {
376
+ return d + 2750;
377
+ } else if (mode === "bf") {
378
+ return d + 3200;
379
+ } else if (mode === "tt") {
380
+ return d + 700;
381
+ }
382
+ return d + 2200;
383
+ }
384
+ return {
385
+ ".": 2210,
386
+ ",": 2211,
387
+ ":": 2212,
388
+ ";": 2213,
389
+ "!": 2214,
390
+ "?": 2215,
391
+ "'": 2216,
392
+ '"': 2217,
393
+ "*": 2219,
394
+ "/": 2220,
395
+ "-": 2231,
396
+ "+": 2232,
397
+ "=": 2238,
398
+ "<": 2241,
399
+ ">": 2242,
400
+ "~": 2246,
401
+ "@": 2273,
402
+ "\\": 804
403
+ }[x];
404
+ }
405
+ export {
406
+ SYMB,
407
+ asciiMap
408
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 浏览器专用 op 适配器:大图压缩。
3
+ *
4
+ * 不进入 core/ops 的分发器;编辑器把 `shrinkImage` 作为
5
+ * `ctx.media.prepareImage` 注入。Node 侧(relay/stdio)不 import 本文件。
6
+ */
7
+ export async function shrinkImage(el) {
8
+ if (typeof document === 'undefined') return el
9
+ const src = String(el.src || '')
10
+ if (!/^data:image\//i.test(src) || src.length < 250000) return el
11
+ try {
12
+ const img = await new Promise((resolve, reject) => {
13
+ const im = new Image()
14
+ im.onload = () => resolve(im)
15
+ im.onerror = reject
16
+ im.src = src
17
+ })
18
+ const maxW = 1600
19
+ const scale = Math.min(1, maxW / (img.width || maxW))
20
+ if (scale >= 1 && src.length < 900000) return el
21
+ const cv = document.createElement('canvas')
22
+ cv.width = Math.max(1, Math.round((img.width || maxW) * scale))
23
+ cv.height = Math.max(1, Math.round((img.height || maxW) * scale))
24
+ cv.getContext('2d').drawImage(img, 0, 0, cv.width, cv.height)
25
+ el.src = cv.toDataURL('image/jpeg', 0.85)
26
+ } catch (e) { /* 压缩失败保留原图 */ }
27
+ return el
28
+ }
@@ -0,0 +1,64 @@
1
+ /** 图表 op:加图表 / 更新图表数据与样式。数据归一化在 core/chart.js。 */
2
+ import { makeChartElement, normalizeChartData, normalizeChartOptions, CHART_TYPES } from '../chart.js'
3
+
4
+ function clone(P, i) {
5
+ const slide = P.getSlides()[i]
6
+ if (!slide) {
7
+ const total = P.getSlides().length
8
+ throw new Error(`页号越界:第 ${i} 页不存在(共 ${total} 页)`)
9
+ }
10
+ return JSON.parse(JSON.stringify(slide))
11
+ }
12
+
13
+ /** 取幻灯片主题色(可选,图表缺省调色兜底)。 */
14
+ function deckThemeColors(P) {
15
+ try {
16
+ const th = typeof P.getTheme === 'function' ? P.getTheme() : null
17
+ return th && Array.isArray(th.themeColors) ? th.themeColors : undefined
18
+ } catch {
19
+ return undefined
20
+ }
21
+ }
22
+
23
+ export const chartOps = {
24
+ 'add-chart': {
25
+ async run(P, c) {
26
+ const i = Number(c.slide != null ? c.slide : 0)
27
+ const s = clone(P, i)
28
+ const el = makeChartElement(c.element || {}, deckThemeColors(P))
29
+ s.elements.push(el)
30
+ P.updateSlide(i, s)
31
+ return el.id
32
+ },
33
+ },
34
+
35
+ 'update-chart': {
36
+ run(P, c) {
37
+ const i = Number(c.slide != null ? c.slide : 0)
38
+ const s = clone(P, i)
39
+ const el = s.elements.find(e => e.id === c.elementId)
40
+ if (!el) throw new Error('update-chart 未命中: ' + c.elementId)
41
+ if (el.type !== 'chart') throw new Error(`元素 ${c.elementId} 不是图表(type=${el.type})`)
42
+ const p = c.props || {}
43
+ if (p.chartType != null) {
44
+ const ct = String(p.chartType)
45
+ if (!CHART_TYPES.includes(ct)) {
46
+ throw new Error(`不支持的 chartType: ${ct}(支持 ${CHART_TYPES.join(' / ')})`)
47
+ }
48
+ el.chartType = ct
49
+ }
50
+ if (p.data != null) el.data = normalizeChartData(p.data, el.chartType)
51
+ if (p.options !== undefined) {
52
+ const options = normalizeChartOptions(p.options)
53
+ if (options) el.options = options
54
+ else delete el.options
55
+ }
56
+ if (Array.isArray(p.colors) && p.colors.length) el.themeColors = p.colors.map(String)
57
+ if (p.textColor != null) el.textColor = String(p.textColor)
58
+ for (const k of ['left', 'top', 'width', 'height', 'rotate']) {
59
+ if (p[k] != null && isFinite(Number(p[k]))) el[k] = Number(p[k])
60
+ }
61
+ P.updateSlide(i, s)
62
+ },
63
+ },
64
+ }
@@ -0,0 +1,21 @@
1
+ /** deck 级 op:整副替换 / 标题 / 主题。 */
2
+ export const deckOps = {
3
+ load: {
4
+ run(P, c) { return P.load(c.deck) },
5
+ },
6
+ title: {
7
+ run(P, c) { P.setTitle(String(c.title || '')) },
8
+ },
9
+ theme: {
10
+ run(P, c) {
11
+ const th = P.getTheme() || {}
12
+ Object.assign(th, c.theme || {})
13
+ P.setTheme(th)
14
+ },
15
+ },
16
+ /* 只压一条服务端历史快照,不改 deck。导入这类“绕过 op 内核”的
17
+ * 编辑器级操作前调用,保证 ppt_history undo 能回到导入前。 */
18
+ snapshot: {
19
+ run() {},
20
+ },
21
+ }
@@ -0,0 +1,2 @@
1
+ /** 兼容层:op 分发器的通用实现位于 dsh-document-workbench/ops。 */
2
+ export { createOpDispatcher } from 'dsh-document-workbench/ops'
@@ -0,0 +1,55 @@
1
+ /** 元素 op:加/改/删元素。图片预压缩由编辑器通过 ctx.media.prepareImage 注入。 */
2
+ import { makeElement, patchElement } from '../text.js'
3
+
4
+ function clone(P, i) {
5
+ const slide = P.getSlides()[i]
6
+ if (!slide) {
7
+ const total = P.getSlides().length
8
+ throw new Error(`页号越界:第 ${i} 页不存在(共 ${total} 页)`)
9
+ }
10
+ return JSON.parse(JSON.stringify(slide))
11
+ }
12
+
13
+ export const elementOps = {
14
+ 'add-element': {
15
+ async run(P, c, ctx) {
16
+ const i = Number(c.slide != null ? c.slide : 0)
17
+ const s = clone(P, i)
18
+ const el = makeElement(c.element || {})
19
+ /* 完全在画布外的元素自动放回画布内(2026-10-22:曾有图片被放到
20
+ x=1080 / 画布宽 1000,工具报成功但用户看不到) */
21
+ if ((el.left != null && el.left >= 1000) || (el.top != null && el.top >= 563) ||
22
+ (el.left != null && el.width != null && el.left + el.width <= 0)) {
23
+ el.left = Math.max(0, Math.round((1000 - (el.width || 400)) / 2))
24
+ el.top = Math.max(0, Math.round((562.5 - (el.height || 300)) / 2))
25
+ }
26
+ if (el.type === 'image' && ctx.media && typeof ctx.media.prepareImage === 'function') {
27
+ await ctx.media.prepareImage(el)
28
+ }
29
+ s.elements.push(el)
30
+ P.updateSlide(i, s)
31
+ },
32
+ },
33
+
34
+ 'set-element': {
35
+ run(P, c) {
36
+ const i = Number(c.slide != null ? c.slide : c.id)
37
+ const s = clone(P, i)
38
+ const el = s.elements.find(e => e.id === c.elementId)
39
+ if (!el) throw new Error('set-element 未命中: ' + c.elementId)
40
+ patchElement(el, c.props || {})
41
+ P.updateSlide(i, s)
42
+ },
43
+ },
44
+
45
+ 'remove-element': {
46
+ run(P, c) {
47
+ const i = Number(c.slide != null ? c.slide : 0)
48
+ const s = clone(P, i)
49
+ const n = s.elements.length
50
+ s.elements = s.elements.filter(e => e.id !== c.elementId)
51
+ if (s.elements.length === n) throw new Error('remove-element 未命中: ' + c.elementId)
52
+ P.updateSlide(i, s)
53
+ },
54
+ },
55
+ }
@@ -0,0 +1,11 @@
1
+ /** 历史 op:撤销/重做(不再 snapshot)。 */
2
+ export const historyOps = {
3
+ undo: {
4
+ mutates: false,
5
+ run(P) { return P.undo() },
6
+ },
7
+ redo: {
8
+ mutates: false,
9
+ run(P) { return P.redo() },
10
+ },
11
+ }