p-spore 0.1.3 → 0.1.42

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 (396) hide show
  1. package/README.md +110 -15
  2. package/dist/agents/agent-manager.d.ts +3 -3
  3. package/dist/agents/agent-manager.d.ts.map +1 -1
  4. package/dist/agents/agent-manager.js +3 -2
  5. package/dist/agents/agent-manager.js.map +1 -1
  6. package/dist/application/agent-application.d.ts +29 -5
  7. package/dist/application/agent-application.d.ts.map +1 -1
  8. package/dist/application/agent-application.js +444 -14
  9. package/dist/application/agent-application.js.map +1 -1
  10. package/dist/articles/diff.d.ts +70 -0
  11. package/dist/articles/diff.d.ts.map +1 -0
  12. package/dist/articles/diff.js +330 -0
  13. package/dist/articles/diff.js.map +1 -0
  14. package/dist/articles/docx.d.ts +10 -0
  15. package/dist/articles/docx.d.ts.map +1 -0
  16. package/dist/articles/docx.js +219 -0
  17. package/dist/articles/docx.js.map +1 -0
  18. package/dist/articles/draft.d.ts +18 -0
  19. package/dist/articles/draft.d.ts.map +1 -0
  20. package/dist/articles/draft.js +88 -0
  21. package/dist/articles/draft.js.map +1 -0
  22. package/dist/articles/edits.d.ts +24 -0
  23. package/dist/articles/edits.d.ts.map +1 -0
  24. package/dist/articles/edits.js +54 -0
  25. package/dist/articles/edits.js.map +1 -0
  26. package/dist/articles/html.d.ts +10 -0
  27. package/dist/articles/html.d.ts.map +1 -0
  28. package/dist/articles/html.js +122 -0
  29. package/dist/articles/html.js.map +1 -0
  30. package/dist/articles/plain.d.ts +8 -0
  31. package/dist/articles/plain.d.ts.map +1 -0
  32. package/dist/articles/plain.js +69 -0
  33. package/dist/articles/plain.js.map +1 -0
  34. package/dist/articles/preview.d.ts +43 -0
  35. package/dist/articles/preview.d.ts.map +1 -0
  36. package/dist/articles/preview.js +90 -0
  37. package/dist/articles/preview.js.map +1 -0
  38. package/dist/articles/publish.d.ts +10 -0
  39. package/dist/articles/publish.d.ts.map +1 -0
  40. package/dist/articles/publish.js +54 -0
  41. package/dist/articles/publish.js.map +1 -0
  42. package/dist/articles/receipt.d.ts +16 -0
  43. package/dist/articles/receipt.d.ts.map +1 -0
  44. package/dist/articles/receipt.js +27 -0
  45. package/dist/articles/receipt.js.map +1 -0
  46. package/dist/articles/store.d.ts +78 -0
  47. package/dist/articles/store.d.ts.map +1 -0
  48. package/dist/articles/store.js +308 -0
  49. package/dist/articles/store.js.map +1 -0
  50. package/dist/articles/tool.d.ts +14 -0
  51. package/dist/articles/tool.d.ts.map +1 -0
  52. package/dist/articles/tool.js +175 -0
  53. package/dist/articles/tool.js.map +1 -0
  54. package/dist/articles/writer-context.d.ts +5 -0
  55. package/dist/articles/writer-context.d.ts.map +1 -0
  56. package/dist/articles/writer-context.js +56 -0
  57. package/dist/articles/writer-context.js.map +1 -0
  58. package/dist/articles/writer.d.ts +18 -0
  59. package/dist/articles/writer.d.ts.map +1 -0
  60. package/dist/articles/writer.js +79 -0
  61. package/dist/articles/writer.js.map +1 -0
  62. package/dist/articles/zip-write.d.ts +11 -0
  63. package/dist/articles/zip-write.d.ts.map +1 -0
  64. package/dist/articles/zip-write.js +63 -0
  65. package/dist/articles/zip-write.js.map +1 -0
  66. package/dist/bundled-skills/README.md +17 -0
  67. package/dist/bundled-skills/aegis-search/SKILL.md +59 -0
  68. package/dist/bundled-skills/aegis-search/bin/.gitkeep +0 -0
  69. package/dist/bundled-skills/article-canvas/SKILL.md +28 -0
  70. package/dist/bundled-skills/binaries.json +23 -0
  71. package/dist/bundled-skills/doc-extract/SKILL.md +56 -0
  72. package/dist/cli/main.d.ts.map +1 -1
  73. package/dist/cli/main.js +407 -54
  74. package/dist/cli/main.js.map +1 -1
  75. package/dist/config/config.d.ts +43 -0
  76. package/dist/config/config.d.ts.map +1 -1
  77. package/dist/config/config.js +150 -6
  78. package/dist/config/config.js.map +1 -1
  79. package/dist/daemon/daemon.d.ts.map +1 -1
  80. package/dist/daemon/daemon.js +80 -11
  81. package/dist/daemon/daemon.js.map +1 -1
  82. package/dist/desktop/application.d.ts +4 -0
  83. package/dist/desktop/application.d.ts.map +1 -0
  84. package/dist/desktop/application.js +1688 -0
  85. package/dist/desktop/application.js.map +1 -0
  86. package/dist/desktop/article-export.d.ts +12 -0
  87. package/dist/desktop/article-export.d.ts.map +1 -0
  88. package/dist/desktop/article-export.js +87 -0
  89. package/dist/desktop/article-export.js.map +1 -0
  90. package/dist/desktop/assets/pspore.png +0 -0
  91. package/dist/desktop/assets/pspore.svg +24 -0
  92. package/dist/desktop/conversation-smoke.d.ts +5 -0
  93. package/dist/desktop/conversation-smoke.d.ts.map +1 -0
  94. package/dist/desktop/conversation-smoke.js +93 -0
  95. package/dist/desktop/conversation-smoke.js.map +1 -0
  96. package/dist/desktop/daemon-bridge.d.ts.map +1 -1
  97. package/dist/desktop/daemon-bridge.js +62 -17
  98. package/dist/desktop/daemon-bridge.js.map +1 -1
  99. package/dist/desktop/ipc-contract.d.ts +124 -0
  100. package/dist/desktop/ipc-contract.d.ts.map +1 -1
  101. package/dist/desktop/ipc-contract.js +191 -12
  102. package/dist/desktop/ipc-contract.js.map +1 -1
  103. package/dist/desktop/local-path.d.ts +15 -0
  104. package/dist/desktop/local-path.d.ts.map +1 -0
  105. package/dist/desktop/local-path.js +59 -0
  106. package/dist/desktop/local-path.js.map +1 -0
  107. package/dist/desktop/main.d.ts +10 -1
  108. package/dist/desktop/main.d.ts.map +1 -1
  109. package/dist/desktop/main.js +122 -530
  110. package/dist/desktop/main.js.map +1 -1
  111. package/dist/desktop/native-startup.d.ts +4 -0
  112. package/dist/desktop/native-startup.d.ts.map +1 -0
  113. package/dist/desktop/native-startup.js +57 -0
  114. package/dist/desktop/native-startup.js.map +1 -0
  115. package/dist/desktop/preload.cjs +28 -1
  116. package/dist/desktop/renderer/article-panel.d.ts +45 -0
  117. package/dist/desktop/renderer/article-panel.d.ts.map +1 -0
  118. package/dist/desktop/renderer/article-panel.js +1126 -0
  119. package/dist/desktop/renderer/article-panel.js.map +1 -0
  120. package/dist/desktop/renderer/article-split.d.ts +32 -0
  121. package/dist/desktop/renderer/article-split.d.ts.map +1 -0
  122. package/dist/desktop/renderer/article-split.js +48 -0
  123. package/dist/desktop/renderer/article-split.js.map +1 -0
  124. package/dist/desktop/renderer/composer-file-references.d.ts +23 -0
  125. package/dist/desktop/renderer/composer-file-references.d.ts.map +1 -0
  126. package/dist/desktop/renderer/composer-file-references.js +51 -0
  127. package/dist/desktop/renderer/composer-file-references.js.map +1 -0
  128. package/dist/desktop/renderer/conversation.d.ts +23 -0
  129. package/dist/desktop/renderer/conversation.d.ts.map +1 -0
  130. package/dist/desktop/renderer/conversation.js +66 -0
  131. package/dist/desktop/renderer/conversation.js.map +1 -0
  132. package/dist/desktop/renderer/dom-reconcile.d.ts +15 -0
  133. package/dist/desktop/renderer/dom-reconcile.d.ts.map +1 -0
  134. package/dist/desktop/renderer/dom-reconcile.js +33 -0
  135. package/dist/desktop/renderer/dom-reconcile.js.map +1 -0
  136. package/dist/desktop/renderer/index.html +211 -34
  137. package/dist/desktop/renderer/indexing-view.d.ts +22 -0
  138. package/dist/desktop/renderer/indexing-view.d.ts.map +1 -0
  139. package/dist/desktop/renderer/indexing-view.js +115 -0
  140. package/dist/desktop/renderer/indexing-view.js.map +1 -0
  141. package/dist/desktop/renderer/markdown-view.d.ts +23 -0
  142. package/dist/desktop/renderer/markdown-view.d.ts.map +1 -0
  143. package/dist/desktop/renderer/markdown-view.js +436 -0
  144. package/dist/desktop/renderer/markdown-view.js.map +1 -0
  145. package/dist/desktop/renderer/motion.d.ts +67 -0
  146. package/dist/desktop/renderer/motion.d.ts.map +1 -0
  147. package/dist/desktop/renderer/motion.js +296 -0
  148. package/dist/desktop/renderer/motion.js.map +1 -0
  149. package/dist/desktop/renderer/renderer.js +1793 -155
  150. package/dist/desktop/renderer/renderer.js.map +1 -1
  151. package/dist/desktop/renderer/session-find.d.ts +18 -0
  152. package/dist/desktop/renderer/session-find.d.ts.map +1 -0
  153. package/dist/desktop/renderer/session-find.js +29 -0
  154. package/dist/desktop/renderer/session-find.js.map +1 -0
  155. package/dist/desktop/renderer/session-search.d.ts +30 -0
  156. package/dist/desktop/renderer/session-search.d.ts.map +1 -0
  157. package/dist/desktop/renderer/session-search.js +296 -0
  158. package/dist/desktop/renderer/session-search.js.map +1 -0
  159. package/dist/desktop/renderer/store.d.ts +35 -8
  160. package/dist/desktop/renderer/store.d.ts.map +1 -1
  161. package/dist/desktop/renderer/store.js +95 -78
  162. package/dist/desktop/renderer/store.js.map +1 -1
  163. package/dist/desktop/renderer/styles.css +910 -268
  164. package/dist/desktop/renderer/vendor/gsap.min.js +11 -0
  165. package/dist/desktop/renderer-diagnostics.d.ts +5 -0
  166. package/dist/desktop/renderer-diagnostics.d.ts.map +1 -0
  167. package/dist/desktop/renderer-diagnostics.js +47 -0
  168. package/dist/desktop/renderer-diagnostics.js.map +1 -0
  169. package/dist/desktop/security.d.ts +26 -1
  170. package/dist/desktop/security.d.ts.map +1 -1
  171. package/dist/desktop/security.js +26 -6
  172. package/dist/desktop/security.js.map +1 -1
  173. package/dist/desktop/smoke-fixture.d.ts.map +1 -1
  174. package/dist/desktop/smoke-fixture.js +77 -3
  175. package/dist/desktop/smoke-fixture.js.map +1 -1
  176. package/dist/desktop/splash/index.html +25 -0
  177. package/dist/desktop/splash/splash.d.ts +2 -0
  178. package/dist/desktop/splash/splash.d.ts.map +1 -0
  179. package/dist/desktop/splash/splash.js +8 -0
  180. package/dist/desktop/splash/splash.js.map +1 -0
  181. package/dist/desktop/splash/styles.css +24 -0
  182. package/dist/desktop/system-open.d.ts +16 -0
  183. package/dist/desktop/system-open.d.ts.map +1 -0
  184. package/dist/desktop/system-open.js +90 -0
  185. package/dist/desktop/system-open.js.map +1 -0
  186. package/dist/desktop/validation.d.ts.map +1 -1
  187. package/dist/desktop/validation.js +99 -21
  188. package/dist/desktop/validation.js.map +1 -1
  189. package/dist/desktop/window-security.d.ts +4 -0
  190. package/dist/desktop/window-security.d.ts.map +1 -0
  191. package/dist/desktop/window-security.js +26 -0
  192. package/dist/desktop/window-security.js.map +1 -0
  193. package/dist/documents/errors.d.ts +12 -0
  194. package/dist/documents/errors.d.ts.map +1 -0
  195. package/dist/documents/errors.js +12 -0
  196. package/dist/documents/errors.js.map +1 -0
  197. package/dist/documents/extract.d.ts +37 -0
  198. package/dist/documents/extract.d.ts.map +1 -0
  199. package/dist/documents/extract.js +90 -0
  200. package/dist/documents/extract.js.map +1 -0
  201. package/dist/documents/legacy-office.d.ts +23 -0
  202. package/dist/documents/legacy-office.d.ts.map +1 -0
  203. package/dist/documents/legacy-office.js +439 -0
  204. package/dist/documents/legacy-office.js.map +1 -0
  205. package/dist/documents/ole.d.ts +20 -0
  206. package/dist/documents/ole.d.ts.map +1 -0
  207. package/dist/documents/ole.js +189 -0
  208. package/dist/documents/ole.js.map +1 -0
  209. package/dist/documents/ooxml.d.ts +23 -0
  210. package/dist/documents/ooxml.d.ts.map +1 -0
  211. package/dist/documents/ooxml.js +197 -0
  212. package/dist/documents/ooxml.js.map +1 -0
  213. package/dist/documents/pdf.d.ts +20 -0
  214. package/dist/documents/pdf.d.ts.map +1 -0
  215. package/dist/documents/pdf.js +95 -0
  216. package/dist/documents/pdf.js.map +1 -0
  217. package/dist/documents/plain-text.d.ts +22 -0
  218. package/dist/documents/plain-text.d.ts.map +1 -0
  219. package/dist/documents/plain-text.js +57 -0
  220. package/dist/documents/plain-text.js.map +1 -0
  221. package/dist/documents/zip.d.ts +15 -0
  222. package/dist/documents/zip.d.ts.map +1 -0
  223. package/dist/documents/zip.js +137 -0
  224. package/dist/documents/zip.js.map +1 -0
  225. package/dist/domain/indexing.d.ts +60 -0
  226. package/dist/domain/indexing.d.ts.map +1 -0
  227. package/dist/domain/indexing.js +13 -0
  228. package/dist/domain/indexing.js.map +1 -0
  229. package/dist/domain/runtime.d.ts +133 -5
  230. package/dist/domain/runtime.d.ts.map +1 -1
  231. package/dist/gateway/local-gateway.d.ts +8 -0
  232. package/dist/gateway/local-gateway.d.ts.map +1 -1
  233. package/dist/gateway/local-gateway.js +105 -21
  234. package/dist/gateway/local-gateway.js.map +1 -1
  235. package/dist/indexing/index-service.d.ts +56 -0
  236. package/dist/indexing/index-service.d.ts.map +1 -0
  237. package/dist/indexing/index-service.js +262 -0
  238. package/dist/indexing/index-service.js.map +1 -0
  239. package/dist/kernel/loop.d.ts +10 -0
  240. package/dist/kernel/loop.d.ts.map +1 -1
  241. package/dist/kernel/loop.js +6 -2
  242. package/dist/kernel/loop.js.map +1 -1
  243. package/dist/kernel/reducer.d.ts.map +1 -1
  244. package/dist/kernel/reducer.js +17 -1
  245. package/dist/kernel/reducer.js.map +1 -1
  246. package/dist/kernel/state.d.ts +17 -4
  247. package/dist/kernel/state.d.ts.map +1 -1
  248. package/dist/kernel/state.js +2 -0
  249. package/dist/kernel/state.js.map +1 -1
  250. package/dist/memory/memory-tools.d.ts.map +1 -1
  251. package/dist/memory/memory-tools.js +25 -5
  252. package/dist/memory/memory-tools.js.map +1 -1
  253. package/dist/pi/context-budget.d.ts +8 -0
  254. package/dist/pi/context-budget.d.ts.map +1 -0
  255. package/dist/pi/context-budget.js +62 -0
  256. package/dist/pi/context-budget.js.map +1 -0
  257. package/dist/pi/pi-runtime-adapter.d.ts +38 -3
  258. package/dist/pi/pi-runtime-adapter.d.ts.map +1 -1
  259. package/dist/pi/pi-runtime-adapter.js +551 -56
  260. package/dist/pi/pi-runtime-adapter.js.map +1 -1
  261. package/dist/plugins/bundled-skills.d.ts +56 -0
  262. package/dist/plugins/bundled-skills.d.ts.map +1 -0
  263. package/dist/plugins/bundled-skills.js +243 -0
  264. package/dist/plugins/bundled-skills.js.map +1 -0
  265. package/dist/plugins/extension-manager.d.ts +23 -1
  266. package/dist/plugins/extension-manager.d.ts.map +1 -1
  267. package/dist/plugins/extension-manager.js +117 -0
  268. package/dist/plugins/extension-manager.js.map +1 -1
  269. package/dist/plugins/types.d.ts +29 -0
  270. package/dist/plugins/types.d.ts.map +1 -1
  271. package/dist/plugins/workspace-skills.d.ts +36 -0
  272. package/dist/plugins/workspace-skills.d.ts.map +1 -0
  273. package/dist/plugins/workspace-skills.js +309 -0
  274. package/dist/plugins/workspace-skills.js.map +1 -0
  275. package/dist/policy/policy.d.ts.map +1 -1
  276. package/dist/policy/policy.js +26 -4
  277. package/dist/policy/policy.js.map +1 -1
  278. package/dist/protocol/client.d.ts +1 -0
  279. package/dist/protocol/client.d.ts.map +1 -1
  280. package/dist/protocol/client.js +49 -24
  281. package/dist/protocol/client.js.map +1 -1
  282. package/dist/protocol/limits.d.ts +69 -0
  283. package/dist/protocol/limits.d.ts.map +1 -0
  284. package/dist/protocol/limits.js +166 -0
  285. package/dist/protocol/limits.js.map +1 -0
  286. package/dist/protocol/schema.d.ts +6 -0
  287. package/dist/protocol/schema.d.ts.map +1 -1
  288. package/dist/protocol/schema.js.map +1 -1
  289. package/dist/protocol/server-frame-codec.d.ts +18 -0
  290. package/dist/protocol/server-frame-codec.d.ts.map +1 -0
  291. package/dist/protocol/server-frame-codec.js +211 -0
  292. package/dist/protocol/server-frame-codec.js.map +1 -0
  293. package/dist/service/legacy-daemon.d.ts +6 -0
  294. package/dist/service/legacy-daemon.d.ts.map +1 -0
  295. package/dist/service/legacy-daemon.js +42 -0
  296. package/dist/service/legacy-daemon.js.map +1 -0
  297. package/dist/service/service-launch.d.ts +10 -0
  298. package/dist/service/service-launch.d.ts.map +1 -0
  299. package/dist/service/service-launch.js +56 -0
  300. package/dist/service/service-launch.js.map +1 -0
  301. package/dist/service/system-service.d.ts +57 -0
  302. package/dist/service/system-service.d.ts.map +1 -0
  303. package/dist/service/system-service.js +263 -0
  304. package/dist/service/system-service.js.map +1 -0
  305. package/dist/sessions/session-catalog.d.ts +45 -0
  306. package/dist/sessions/session-catalog.d.ts.map +1 -0
  307. package/dist/sessions/session-catalog.js +270 -0
  308. package/dist/sessions/session-catalog.js.map +1 -0
  309. package/dist/sessions/session-file.d.ts +12 -0
  310. package/dist/sessions/session-file.d.ts.map +1 -0
  311. package/dist/sessions/session-file.js +47 -0
  312. package/dist/sessions/session-file.js.map +1 -0
  313. package/dist/settings/compaction-settings.d.ts +10 -0
  314. package/dist/settings/compaction-settings.d.ts.map +1 -0
  315. package/dist/settings/compaction-settings.js +8 -0
  316. package/dist/settings/compaction-settings.js.map +1 -0
  317. package/dist/settings/indexing-settings-service.d.ts +16 -0
  318. package/dist/settings/indexing-settings-service.d.ts.map +1 -0
  319. package/dist/settings/indexing-settings-service.js +57 -0
  320. package/dist/settings/indexing-settings-service.js.map +1 -0
  321. package/dist/settings/indexing-settings.d.ts +30 -0
  322. package/dist/settings/indexing-settings.d.ts.map +1 -0
  323. package/dist/settings/indexing-settings.js +58 -0
  324. package/dist/settings/indexing-settings.js.map +1 -0
  325. package/dist/settings/llm-settings-service.d.ts +6 -0
  326. package/dist/settings/llm-settings-service.d.ts.map +1 -1
  327. package/dist/settings/llm-settings-service.js +137 -12
  328. package/dist/settings/llm-settings-service.js.map +1 -1
  329. package/dist/settings/llm-settings.d.ts +68 -2
  330. package/dist/settings/llm-settings.d.ts.map +1 -1
  331. package/dist/settings/llm-settings.js +119 -17
  332. package/dist/settings/llm-settings.js.map +1 -1
  333. package/dist/settings/model-api.d.ts +10 -0
  334. package/dist/settings/model-api.d.ts.map +1 -0
  335. package/dist/settings/model-api.js +10 -0
  336. package/dist/settings/model-api.js.map +1 -0
  337. package/dist/storage/home.d.ts +1 -0
  338. package/dist/storage/home.d.ts.map +1 -1
  339. package/dist/storage/home.js +37 -2
  340. package/dist/storage/home.js.map +1 -1
  341. package/dist/tools/core-tools.d.ts +2 -0
  342. package/dist/tools/core-tools.d.ts.map +1 -1
  343. package/dist/tools/core-tools.js +91 -1
  344. package/dist/tools/core-tools.js.map +1 -1
  345. package/dist/ui/shared/activity.d.ts +27 -0
  346. package/dist/ui/shared/activity.d.ts.map +1 -0
  347. package/dist/ui/shared/activity.js +384 -0
  348. package/dist/ui/shared/activity.js.map +1 -0
  349. package/dist/ui/shared/full-message.d.ts +22 -0
  350. package/dist/ui/shared/full-message.d.ts.map +1 -0
  351. package/dist/ui/shared/full-message.js +40 -0
  352. package/dist/ui/shared/full-message.js.map +1 -0
  353. package/dist/ui/shared/local-links.d.ts +7 -0
  354. package/dist/ui/shared/local-links.d.ts.map +1 -0
  355. package/dist/ui/shared/local-links.js +24 -0
  356. package/dist/ui/shared/local-links.js.map +1 -0
  357. package/dist/ui/shared/markdown-stream.d.ts +25 -0
  358. package/dist/ui/shared/markdown-stream.d.ts.map +1 -0
  359. package/dist/ui/shared/markdown-stream.js +35 -0
  360. package/dist/ui/shared/markdown-stream.js.map +1 -0
  361. package/dist/ui/shared/markdown.d.ts +70 -0
  362. package/dist/ui/shared/markdown.d.ts.map +1 -0
  363. package/dist/ui/shared/markdown.js +434 -0
  364. package/dist/ui/shared/markdown.js.map +1 -0
  365. package/dist/ui/shared/presentation.d.ts +10 -2
  366. package/dist/ui/shared/presentation.d.ts.map +1 -1
  367. package/dist/ui/shared/presentation.js +83 -22
  368. package/dist/ui/shared/presentation.js.map +1 -1
  369. package/dist/ui/shared/protocol-state.d.ts +19 -0
  370. package/dist/ui/shared/protocol-state.d.ts.map +1 -1
  371. package/dist/ui/shared/protocol-state.js +188 -26
  372. package/dist/ui/shared/protocol-state.js.map +1 -1
  373. package/dist/ui/shared/virtual-list.d.ts +34 -0
  374. package/dist/ui/shared/virtual-list.d.ts.map +1 -0
  375. package/dist/ui/shared/virtual-list.js +143 -0
  376. package/dist/ui/shared/virtual-list.js.map +1 -0
  377. package/dist/ui/tui/commands.d.ts +1 -1
  378. package/dist/ui/tui/commands.d.ts.map +1 -1
  379. package/dist/ui/tui/commands.js +9 -3
  380. package/dist/ui/tui/commands.js.map +1 -1
  381. package/dist/ui/tui/store.d.ts +26 -0
  382. package/dist/ui/tui/store.d.ts.map +1 -1
  383. package/dist/ui/tui/store.js +67 -3
  384. package/dist/ui/tui/store.js.map +1 -1
  385. package/dist/ui/tui/tui-app.d.ts.map +1 -1
  386. package/dist/ui/tui/tui-app.js +316 -38
  387. package/dist/ui/tui/tui-app.js.map +1 -1
  388. package/dist/ui/tui/view.d.ts +10 -0
  389. package/dist/ui/tui/view.d.ts.map +1 -1
  390. package/dist/ui/tui/view.js +253 -49
  391. package/dist/ui/tui/view.js.map +1 -1
  392. package/dist/version.d.ts +1 -1
  393. package/dist/version.d.ts.map +1 -1
  394. package/dist/version.js +1 -1
  395. package/dist/version.js.map +1 -1
  396. package/package.json +13 -2
@@ -0,0 +1,189 @@
1
+ /**
2
+ * The container every pre-2007 Office file is written in.
3
+ *
4
+ * A `.doc`, `.xls` or `.ppt` is a Compound File Binary document: a FAT-style
5
+ * filesystem inside one file, whose named streams hold the actual format. The
6
+ * reader is here so the three legacy parsers share one implementation of the
7
+ * container and only differ in how they read their own stream.
8
+ */
9
+ const SIGNATURE = Buffer.from([0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1]);
10
+ /** Sector chain terminators; anything below them is a real sector number. */
11
+ const MAX_REGULAR_SECTOR = 0xfffffffa;
12
+ const FREE_SECTOR = 0xffffffff;
13
+ const END_OF_CHAIN = 0xfffffffe;
14
+ const DIRECTORY_ENTRY_BYTES = 128;
15
+ const STREAM_TYPE = 2;
16
+ /** DIFAT entries stored in the header before the chain of DIFAT sectors starts. */
17
+ const HEADER_DIFAT_ENTRIES = 109;
18
+ /**
19
+ * Ceiling on how many sectors one chain may visit. A crafted file can point a
20
+ * chain at itself and read forever, and these documents are untrusted.
21
+ */
22
+ const MAX_CHAIN_SECTORS = 1 << 22;
23
+ export class OleDocument {
24
+ #buffer;
25
+ #sectorSize;
26
+ #miniSectorSize;
27
+ #miniStreamCutoff;
28
+ #fat;
29
+ #miniFat;
30
+ #streams;
31
+ #miniStream;
32
+ constructor(buffer) {
33
+ this.#buffer = buffer;
34
+ this.#sectorSize = 1 << buffer.readUInt16LE(30);
35
+ this.#miniSectorSize = 1 << buffer.readUInt16LE(32);
36
+ this.#miniStreamCutoff = buffer.readUInt32LE(56);
37
+ if (this.#sectorSize < 128 || this.#sectorSize > 1 << 20) {
38
+ throw new Error("Compound document declares an unusable sector size");
39
+ }
40
+ this.#fat = this.#readFat();
41
+ this.#miniFat = this.#readChainValues(buffer.readUInt32LE(60), buffer.readUInt32LE(64));
42
+ const directory = this.#readDirectory();
43
+ this.#miniStream = directory.miniStream;
44
+ this.#streams = directory.streams;
45
+ }
46
+ static open(buffer) {
47
+ if (!looksLikeOle(buffer))
48
+ throw new Error("Not a compound document");
49
+ return new OleDocument(buffer);
50
+ }
51
+ /** Stream names present in the document, for diagnostics and format sniffing. */
52
+ names() {
53
+ return [...this.#streams.keys()];
54
+ }
55
+ has(name) {
56
+ return this.#streams.has(name);
57
+ }
58
+ /** Reads a whole named stream, or undefined when the document has no such stream. */
59
+ read(name) {
60
+ const entry = this.#streams.get(name);
61
+ if (!entry)
62
+ return undefined;
63
+ // Short streams live packed inside the mini stream rather than in sectors of
64
+ // their own, which is why the cutoff has to be consulted before reading.
65
+ return entry.size < this.#miniStreamCutoff
66
+ ? this.#readMini(entry.start, entry.size)
67
+ : this.#readSectors(entry.start, entry.size);
68
+ }
69
+ #readFat() {
70
+ const count = this.#buffer.readUInt32LE(44);
71
+ const sectors = [];
72
+ for (let index = 0; index < Math.min(count, HEADER_DIFAT_ENTRIES); index += 1) {
73
+ const sector = this.#buffer.readUInt32LE(76 + index * 4);
74
+ if (sector <= MAX_REGULAR_SECTOR)
75
+ sectors.push(sector);
76
+ }
77
+ // Documents with more than 109 FAT sectors continue the list in a chain of
78
+ // DIFAT sectors, each ending with a pointer to the next.
79
+ let difat = this.#buffer.readUInt32LE(68);
80
+ const difatCount = this.#buffer.readUInt32LE(72);
81
+ const perSector = this.#sectorSize / 4 - 1;
82
+ for (let visited = 0; difat <= MAX_REGULAR_SECTOR && visited < difatCount + 1; visited += 1) {
83
+ const offset = this.#sectorOffset(difat);
84
+ for (let index = 0; index < perSector; index += 1) {
85
+ const sector = this.#buffer.readUInt32LE(offset + index * 4);
86
+ if (sector <= MAX_REGULAR_SECTOR)
87
+ sectors.push(sector);
88
+ }
89
+ difat = this.#buffer.readUInt32LE(offset + perSector * 4);
90
+ }
91
+ const fat = [];
92
+ for (const sector of sectors) {
93
+ const offset = this.#sectorOffset(sector);
94
+ for (let index = 0; index < this.#sectorSize / 4; index += 1) {
95
+ fat.push(this.#buffer.readUInt32LE(offset + index * 4));
96
+ }
97
+ }
98
+ return fat;
99
+ }
100
+ /** Follows a chain and returns every 32-bit value the visited sectors hold. */
101
+ #readChainValues(start, expectedSectors) {
102
+ const values = [];
103
+ let sector = start;
104
+ for (let visited = 0; sector <= MAX_REGULAR_SECTOR && visited <= expectedSectors; visited += 1) {
105
+ const offset = this.#sectorOffset(sector);
106
+ for (let index = 0; index < this.#sectorSize / 4; index += 1) {
107
+ values.push(this.#buffer.readUInt32LE(offset + index * 4));
108
+ }
109
+ sector = this.#fat[sector] ?? END_OF_CHAIN;
110
+ }
111
+ return values;
112
+ }
113
+ #readDirectory() {
114
+ const directory = this.#readSectors(this.#buffer.readUInt32LE(48), Number.POSITIVE_INFINITY);
115
+ const streams = new Map();
116
+ let miniStreamStart = END_OF_CHAIN;
117
+ let miniStreamSize = 0;
118
+ for (let offset = 0; offset + DIRECTORY_ENTRY_BYTES <= directory.length; offset += DIRECTORY_ENTRY_BYTES) {
119
+ const nameBytes = directory.readUInt16LE(offset + 64);
120
+ if (nameBytes < 2 || nameBytes > 64)
121
+ continue;
122
+ // The stored length counts the terminating NUL, and names are UTF-16LE.
123
+ const name = directory.subarray(offset + 0, offset + nameBytes - 2).toString("utf16le");
124
+ const type = directory.readUInt8(offset + 66);
125
+ const start = directory.readUInt32LE(offset + 116);
126
+ const size = Number(directory.readBigUInt64LE(offset + 120));
127
+ // Entry zero is the root, and its "stream" is where mini sectors live.
128
+ if (offset === 0) {
129
+ miniStreamStart = start;
130
+ miniStreamSize = size;
131
+ continue;
132
+ }
133
+ if (type !== STREAM_TYPE || size <= 0)
134
+ continue;
135
+ if (!streams.has(name))
136
+ streams.set(name, { start, size });
137
+ }
138
+ const miniStream = miniStreamStart <= MAX_REGULAR_SECTOR
139
+ ? this.#readSectors(miniStreamStart, miniStreamSize)
140
+ : Buffer.alloc(0);
141
+ return { streams, miniStream };
142
+ }
143
+ #readSectors(start, size) {
144
+ const chunks = [];
145
+ let sector = start;
146
+ let remaining = size;
147
+ for (let visited = 0; sector <= MAX_REGULAR_SECTOR && remaining > 0 && visited < MAX_CHAIN_SECTORS; visited += 1) {
148
+ const offset = this.#sectorOffset(sector);
149
+ const take = Math.min(this.#sectorSize, remaining);
150
+ chunks.push(this.#buffer.subarray(offset, offset + take));
151
+ remaining -= take;
152
+ const next = this.#fat[sector];
153
+ if (next === undefined || next === FREE_SECTOR)
154
+ break;
155
+ sector = next;
156
+ }
157
+ return Buffer.concat(chunks);
158
+ }
159
+ #readMini(start, size) {
160
+ const chunks = [];
161
+ let sector = start;
162
+ let remaining = size;
163
+ for (let visited = 0; sector <= MAX_REGULAR_SECTOR && remaining > 0 && visited < MAX_CHAIN_SECTORS; visited += 1) {
164
+ const offset = sector * this.#miniSectorSize;
165
+ if (offset >= this.#miniStream.length)
166
+ break;
167
+ const take = Math.min(this.#miniSectorSize, remaining);
168
+ chunks.push(this.#miniStream.subarray(offset, offset + take));
169
+ remaining -= take;
170
+ const next = this.#miniFat[sector];
171
+ if (next === undefined || next === FREE_SECTOR)
172
+ break;
173
+ sector = next;
174
+ }
175
+ return Buffer.concat(chunks);
176
+ }
177
+ /** Sector numbering starts after the 512-byte header, whatever the sector size. */
178
+ #sectorOffset(sector) {
179
+ const offset = 512 + sector * this.#sectorSize;
180
+ if (offset < 0 || offset + this.#sectorSize > this.#buffer.length) {
181
+ throw new Error("Compound document points past the end of the file");
182
+ }
183
+ return offset;
184
+ }
185
+ }
186
+ export function looksLikeOle(buffer) {
187
+ return buffer.length >= 512 && buffer.subarray(0, 8).equals(SIGNATURE);
188
+ }
189
+ //# sourceMappingURL=ole.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ole.js","sourceRoot":"","sources":["../../src/documents/ole.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { ZipArchive } from "./zip.js";
2
+ /**
3
+ * Text out of Office Open XML packages: `.docx`, `.xlsx` and `.pptx`, plus
4
+ * anything WPS wrote in the same containers under a different extension.
5
+ *
6
+ * These are read with a scanner rather than a DOM: only character data and a
7
+ * handful of break elements matter, the parts are machine-generated, and a
8
+ * general XML parser would be a dependency handling untrusted documents.
9
+ */
10
+ export type OoxmlKind = "docx" | "xlsx" | "pptx";
11
+ export interface OoxmlDocument {
12
+ kind: OoxmlKind;
13
+ text: string;
14
+ /** One entry per worksheet or slide; empty for a word-processing document. */
15
+ sections: readonly {
16
+ name: string;
17
+ text: string;
18
+ }[];
19
+ }
20
+ /** Which OOXML format a package holds, decided by the parts it carries. */
21
+ export declare function detectOoxmlKind(archive: ZipArchive): OoxmlKind | undefined;
22
+ export declare function extractOoxml(archive: ZipArchive, kind: OoxmlKind): OoxmlDocument;
23
+ //# sourceMappingURL=ooxml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ooxml.d.ts","sourceRoot":"","sources":["../../src/documents/ooxml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC;;;;;;;GAOG;AAEH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,QAAQ,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACrD;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAK1E;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,GAAG,aAAa,CAIhF"}
@@ -0,0 +1,197 @@
1
+ import { ZipArchive } from "./zip.js";
2
+ /** Which OOXML format a package holds, decided by the parts it carries. */
3
+ export function detectOoxmlKind(archive) {
4
+ if (archive.has("word/document.xml"))
5
+ return "docx";
6
+ if (archive.has("xl/workbook.xml"))
7
+ return "xlsx";
8
+ if (archive.has("ppt/presentation.xml"))
9
+ return "pptx";
10
+ return undefined;
11
+ }
12
+ export function extractOoxml(archive, kind) {
13
+ if (kind === "docx")
14
+ return { kind, text: extractWord(archive), sections: [] };
15
+ if (kind === "pptx")
16
+ return extractSlides(archive);
17
+ return extractSheets(archive);
18
+ }
19
+ /**
20
+ * Word body text. Paragraphs end a line, `w:tab` and `w:br` keep the breaks the
21
+ * author typed, and everything else is markup the reader does not need.
22
+ */
23
+ function extractWord(archive) {
24
+ const xml = archive.readText("word/document.xml") ?? "";
25
+ return collapseBlankLines(harvestText(xml, {
26
+ text: /^w:t$/,
27
+ lineBreak: /^w:(?:br|cr)$/,
28
+ tab: /^w:tab$/,
29
+ paragraph: /^w:p$/,
30
+ }));
31
+ }
32
+ /**
33
+ * Slide text in slide order, with each slide named so a reader can cite one.
34
+ * Speaker notes are deliberately left out: they are not what is on the slide.
35
+ */
36
+ function extractSlides(archive) {
37
+ const sections = archive.matching(/^ppt\/slides\/slide\d+\.xml$/).map((part, index) => ({
38
+ name: `幻灯片 ${index + 1}`,
39
+ text: collapseBlankLines(harvestText(archive.readText(part) ?? "", {
40
+ text: /^a:t$/,
41
+ lineBreak: /^a:br$/,
42
+ tab: /^a:tab$/,
43
+ paragraph: /^a:p$/,
44
+ })),
45
+ }));
46
+ return { kind: "pptx", sections, text: joinSections(sections) };
47
+ }
48
+ /**
49
+ * Worksheet cells as tab-separated rows, which keeps a table readable without
50
+ * inventing a layout. Values live in the shared string table often enough that
51
+ * a sheet read on its own would come back as a page of integers.
52
+ */
53
+ function extractSheets(archive) {
54
+ const sharedStrings = readSharedStrings(archive);
55
+ const names = readSheetNames(archive);
56
+ const parts = archive.matching(/^xl\/worksheets\/sheet\d+\.xml$/);
57
+ const sections = parts.map((part, index) => ({
58
+ name: names[index] ?? `工作表 ${index + 1}`,
59
+ text: readSheet(archive.readText(part) ?? "", sharedStrings),
60
+ }));
61
+ return { kind: "xlsx", sections, text: joinSections(sections) };
62
+ }
63
+ function readSharedStrings(archive) {
64
+ const xml = archive.readText("xl/sharedStrings.xml");
65
+ if (xml === undefined)
66
+ return [];
67
+ // Each <si> is one string, possibly split across runs that only differ in
68
+ // formatting, so the runs inside one entry are concatenated without a break.
69
+ return [...xml.matchAll(/<si\b[^>]*>([\s\S]*?)<\/si>/g)]
70
+ .map((match) => harvestText(match[1] ?? "", { text: /^t$/ }).replace(/\n/g, ""));
71
+ }
72
+ function readSheetNames(archive) {
73
+ const xml = archive.readText("xl/workbook.xml") ?? "";
74
+ return [...xml.matchAll(/<sheet\b[^>]*\bname="([^"]*)"/g)].map((match) => decodeEntities(match[1] ?? ""));
75
+ }
76
+ function readSheet(xml, sharedStrings) {
77
+ const lines = [];
78
+ for (const rowMatch of xml.matchAll(/<row\b[^>]*>([\s\S]*?)<\/row>/g)) {
79
+ const cells = [];
80
+ for (const cellMatch of (rowMatch[1] ?? "").matchAll(/<c\b([^>]*)>([\s\S]*?)<\/c>/g)) {
81
+ cells.push(readCell(cellMatch[1] ?? "", cellMatch[2] ?? "", sharedStrings));
82
+ }
83
+ // A row of empty cells carries no information once the layout is gone.
84
+ if (cells.some((cell) => cell !== ""))
85
+ lines.push(cells.join("\t"));
86
+ }
87
+ return lines.join("\n");
88
+ }
89
+ function readCell(attributes, body, sharedStrings) {
90
+ const type = /\bt="([^"]*)"/.exec(attributes)?.[1];
91
+ if (type === "s") {
92
+ const index = Number(/<v>([\s\S]*?)<\/v>/.exec(body)?.[1] ?? Number.NaN);
93
+ return Number.isInteger(index) ? sharedStrings[index] ?? "" : "";
94
+ }
95
+ if (type === "inlineStr")
96
+ return harvestText(body, { text: /^t$/ }).replace(/\n/g, "");
97
+ // A formula cell keeps its cached result: the formula itself is not the value
98
+ // the document is showing anyone.
99
+ return decodeEntities(/<v>([\s\S]*?)<\/v>/.exec(body)?.[1] ?? "").trim();
100
+ }
101
+ /**
102
+ * Walks the markup once, emitting character data from the elements that carry
103
+ * text and a break wherever the format says a line ends.
104
+ *
105
+ * Written as a scanner because these parts are large, machine-generated and
106
+ * untrusted: it never builds a tree, so a deeply nested document costs no more
107
+ * than a flat one.
108
+ */
109
+ function harvestText(xml, rules) {
110
+ let out = "";
111
+ let cursor = 0;
112
+ let capturing = 0;
113
+ while (cursor < xml.length) {
114
+ const open = xml.indexOf("<", cursor);
115
+ if (open < 0)
116
+ break;
117
+ if (capturing > 0 && open > cursor)
118
+ out += decodeEntities(xml.slice(cursor, open));
119
+ const close = xml.indexOf(">", open);
120
+ if (close < 0)
121
+ break;
122
+ const tag = xml.slice(open + 1, close);
123
+ cursor = close + 1;
124
+ // Comments, CDATA, processing instructions and doctypes carry no text.
125
+ if (tag.startsWith("!") || tag.startsWith("?"))
126
+ continue;
127
+ const selfClosing = tag.endsWith("/");
128
+ const closing = tag.startsWith("/");
129
+ const name = elementName(tag);
130
+ // A break is written either way round: `<w:br/>` and `<w:br></w:br>` are the
131
+ // same instruction, and only one of them may appear in a given document.
132
+ if (selfClosing || closing) {
133
+ if (rules.lineBreak?.test(name))
134
+ out += "\n";
135
+ else if (rules.tab?.test(name))
136
+ out += "\t";
137
+ }
138
+ if (selfClosing) {
139
+ // An empty paragraph is written `<w:p/>`, and it is still a blank line.
140
+ if (rules.paragraph?.test(name))
141
+ out += "\n";
142
+ continue;
143
+ }
144
+ if (closing) {
145
+ if (rules.text.test(name) && capturing > 0)
146
+ capturing -= 1;
147
+ if (rules.paragraph?.test(name))
148
+ out += "\n";
149
+ continue;
150
+ }
151
+ if (rules.text.test(name))
152
+ capturing += 1;
153
+ }
154
+ return out;
155
+ }
156
+ function elementName(tag) {
157
+ const body = tag.replace(/^\//, "").replace(/\/$/, "").trim();
158
+ const end = body.search(/[\s/]/);
159
+ return end < 0 ? body : body.slice(0, end);
160
+ }
161
+ const NAMED_ENTITIES = {
162
+ amp: "&",
163
+ lt: "<",
164
+ gt: ">",
165
+ quot: '"',
166
+ apos: "'",
167
+ };
168
+ function decodeEntities(value) {
169
+ if (!value.includes("&"))
170
+ return value;
171
+ return value.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (match, entity) => {
172
+ if (entity.startsWith("#")) {
173
+ const code = entity.startsWith("#x") || entity.startsWith("#X")
174
+ ? Number.parseInt(entity.slice(2), 16)
175
+ : Number.parseInt(entity.slice(1), 10);
176
+ // A reference outside Unicode, or to a lone surrogate, stays as written
177
+ // rather than becoming a character no reader asked for.
178
+ if (!Number.isInteger(code) || code < 0 || code > 0x10ffff)
179
+ return match;
180
+ if (code >= 0xd800 && code <= 0xdfff)
181
+ return match;
182
+ return String.fromCodePoint(code);
183
+ }
184
+ return NAMED_ENTITIES[entity] ?? match;
185
+ });
186
+ }
187
+ function joinSections(sections) {
188
+ return sections
189
+ .filter((section) => section.text.trim() !== "")
190
+ .map((section) => `## ${section.name}\n${section.text}`)
191
+ .join("\n\n");
192
+ }
193
+ /** Office writes a paragraph per line break, so runs of empty ones pile up. */
194
+ function collapseBlankLines(value) {
195
+ return value.replace(/\n{3,}/g, "\n\n").trim();
196
+ }
197
+ //# sourceMappingURL=ooxml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ooxml.js","sourceRoot":"","sources":["../../src/documents/ooxml.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * PDF text through pdf.js.
3
+ *
4
+ * A PDF does not contain text so much as instructions for placing glyphs, and a
5
+ * Chinese one places them through an embedded CID font whose codes mean nothing
6
+ * without the font's own ToUnicode table. Reimplementing that is how extraction
7
+ * ends up returning confident mojibake, so this is the one format that leans on
8
+ * a library — used for text only, with no rendering and no network fetches.
9
+ */
10
+ export interface PdfDocument {
11
+ text: string;
12
+ pageCount: number;
13
+ sections: readonly {
14
+ name: string;
15
+ text: string;
16
+ }[];
17
+ }
18
+ export declare function extractPdf(data: Buffer): Promise<PdfDocument>;
19
+ export declare function looksLikePdf(buffer: Buffer): boolean;
20
+ //# sourceMappingURL=pdf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdf.d.ts","sourceRoot":"","sources":["../../src/documents/pdf.ts"],"names":[],"mappings":"AAOA;;;;;;;;GAQG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACrD;AA+DD,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAwCnE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAIpD"}
@@ -0,0 +1,95 @@
1
+ import { existsSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { dirname, join } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { UnsupportedDocumentError } from "./errors.js";
6
+ /** Loaded on first use: pdf.js is large, and most documents are not PDFs. */
7
+ let engine;
8
+ async function loadEngine() {
9
+ try {
10
+ // Resolved rather than imported by specifier so the same code works from the
11
+ // build output and from an Electron package, where the package sits in
12
+ // different places relative to this module.
13
+ const entry = createRequire(import.meta.url).resolve("pdfjs-dist/legacy/build/pdf.mjs");
14
+ return await import(pathToFileURL(entry).href);
15
+ }
16
+ catch (error) {
17
+ // The standalone CLI is one bundled file with no package tree beside it, so
18
+ // it cannot reach pdf.js. Every other format still works there, and saying
19
+ // which build this is beats reporting a module resolution failure.
20
+ throw new UnsupportedDocumentError(`本次运行的 pSpore 构建中没有 PDF 解析引擎(${error instanceof Error ? error.message : String(error)})。`
21
+ + "桌面版与服务进程支持 PDF;独立 CLI 二进制不支持,请改用桌面端或先把 PDF 转成文本。");
22
+ }
23
+ }
24
+ /**
25
+ * Data directories pdf.js loads from disk rather than from its own bundle.
26
+ *
27
+ * `cmaps` is what makes a Chinese PDF readable: one that names a predefined
28
+ * CMap such as `UniGB-UCS2-H` maps its glyph codes through that table, and
29
+ * without it the page comes back empty or as the wrong characters. Under Node
30
+ * these are read with `fs`, so they are plain paths — a `file://` URL fails.
31
+ */
32
+ function dataDirectories() {
33
+ try {
34
+ const require = createRequire(import.meta.url);
35
+ const root = dirname(dirname(dirname(require.resolve("pdfjs-dist/legacy/build/pdf.mjs"))));
36
+ const cmaps = join(root, "cmaps");
37
+ const fonts = join(root, "standard_fonts");
38
+ return {
39
+ ...(existsSync(cmaps) ? { cMapUrl: `${cmaps}/` } : {}),
40
+ ...(existsSync(fonts) ? { standardFontDataUrl: `${fonts}/` } : {}),
41
+ };
42
+ }
43
+ catch {
44
+ // A build that ships pdf.js without its data files still reads any document
45
+ // whose fonts are embedded, which is most of them.
46
+ return {};
47
+ }
48
+ }
49
+ export async function extractPdf(data) {
50
+ engine ??= loadEngine();
51
+ const pdfjs = await engine;
52
+ const task = pdfjs.getDocument({
53
+ // pdf.js takes ownership of the array it is given, so it gets its own copy.
54
+ data: new Uint8Array(data),
55
+ // Nothing here should reach the network or the font system, and no document
56
+ // should be able to talk this process into evaluating its own code.
57
+ isEvalSupported: false,
58
+ disableFontFace: true,
59
+ useSystemFonts: false,
60
+ cMapPacked: true,
61
+ ...dataDirectories(),
62
+ });
63
+ const document = await task.promise;
64
+ try {
65
+ const sections = [];
66
+ for (let page = 1; page <= document.numPages; page += 1) {
67
+ const content = await (await document.getPage(page)).getTextContent();
68
+ // Items are glyph runs, not lines; pdf.js marks the ones that end a line.
69
+ const text = content.items
70
+ .map((item) => `${item.str ?? ""}${item.hasEOL ? "\n" : ""}`)
71
+ .join("")
72
+ .replace(/[ \t]+\n/g, "\n")
73
+ .replace(/\n{3,}/g, "\n\n")
74
+ .trim();
75
+ sections.push({ name: `第 ${page} 页`, text });
76
+ }
77
+ return {
78
+ pageCount: document.numPages,
79
+ sections,
80
+ text: sections
81
+ .filter((section) => section.text !== "")
82
+ .map((section) => `## ${section.name}\n${section.text}`)
83
+ .join("\n\n"),
84
+ };
85
+ }
86
+ finally {
87
+ await task.destroy().catch(() => undefined);
88
+ }
89
+ }
90
+ export function looksLikePdf(buffer) {
91
+ // The header may sit behind a few junk bytes; readers tolerate that, and a
92
+ // file that only reaches here because of its extension should too.
93
+ return buffer.subarray(0, 1024).includes("%PDF-");
94
+ }
95
+ //# sourceMappingURL=pdf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdf.js","sourceRoot":"","sources":["../../src/documents/pdf.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Decoding for files that are already text.
3
+ *
4
+ * Encoding cannot be assumed to be UTF-8 here. Documents that reach this agent
5
+ * are the user's own, written on Windows or by WPS, where a Chinese plain-text
6
+ * file is routinely GB18030; decoding one as UTF-8 yields a page of replacement
7
+ * characters that reads as corruption rather than as a wrong guess.
8
+ */
9
+ export interface DecodedText {
10
+ text: string;
11
+ /** Encoding the bytes were read as, so a reader can see what was assumed. */
12
+ encoding: string;
13
+ }
14
+ export declare function decodeText(buffer: Buffer): DecodedText;
15
+ /**
16
+ * True when the bytes hold no NUL, which is the standard test for text.
17
+ *
18
+ * It is also the test that matters downstream: a NUL is the one character
19
+ * clients refuse, and `read` rejects files carrying one for the same reason.
20
+ */
21
+ export declare function looksLikeText(buffer: Buffer): boolean;
22
+ //# sourceMappingURL=plain-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plain-text.d.ts","sourceRoot":"","sources":["../../src/documents/plain-text.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAYtD;AAwBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Decoding for files that are already text.
3
+ *
4
+ * Encoding cannot be assumed to be UTF-8 here. Documents that reach this agent
5
+ * are the user's own, written on Windows or by WPS, where a Chinese plain-text
6
+ * file is routinely GB18030; decoding one as UTF-8 yields a page of replacement
7
+ * characters that reads as corruption rather than as a wrong guess.
8
+ */
9
+ /** Legacy encoding tried when the bytes are not valid UTF-8. */
10
+ const CHINESE_FALLBACK = "gb18030";
11
+ export function decodeText(buffer) {
12
+ const withBom = decodeByteOrderMark(buffer);
13
+ if (withBom)
14
+ return withBom;
15
+ // UTF-8 is self-verifying: a byte sequence that decodes without producing a
16
+ // replacement character is UTF-8 in practice, so it is tried before guessing.
17
+ const utf8 = decodeStrict(buffer, "utf-8");
18
+ if (utf8 !== undefined)
19
+ return { text: utf8, encoding: "utf-8" };
20
+ const legacy = decodeStrict(buffer, CHINESE_FALLBACK);
21
+ if (legacy !== undefined)
22
+ return { text: legacy, encoding: CHINESE_FALLBACK };
23
+ // Nothing decoded cleanly. UTF-8 with replacement characters is the honest
24
+ // result: it keeps the ASCII structure a reader can still use.
25
+ return { text: buffer.toString("utf8"), encoding: "utf-8 (有无法解码的字节)" };
26
+ }
27
+ function decodeByteOrderMark(buffer) {
28
+ if (buffer.length >= 3 && buffer[0] === 0xef && buffer[1] === 0xbb && buffer[2] === 0xbf) {
29
+ return { text: buffer.subarray(3).toString("utf8"), encoding: "utf-8" };
30
+ }
31
+ if (buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xfe) {
32
+ return { text: new TextDecoder("utf-16le").decode(buffer.subarray(2)), encoding: "utf-16le" };
33
+ }
34
+ if (buffer.length >= 2 && buffer[0] === 0xfe && buffer[1] === 0xff) {
35
+ return { text: new TextDecoder("utf-16be").decode(buffer.subarray(2)), encoding: "utf-16be" };
36
+ }
37
+ return undefined;
38
+ }
39
+ /** Decodes only when every byte was representable; otherwise reports failure. */
40
+ function decodeStrict(buffer, encoding) {
41
+ try {
42
+ return new TextDecoder(encoding, { fatal: true }).decode(buffer);
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ }
48
+ /**
49
+ * True when the bytes hold no NUL, which is the standard test for text.
50
+ *
51
+ * It is also the test that matters downstream: a NUL is the one character
52
+ * clients refuse, and `read` rejects files carrying one for the same reason.
53
+ */
54
+ export function looksLikeText(buffer) {
55
+ return !buffer.includes(0);
56
+ }
57
+ //# sourceMappingURL=plain-text.js.map