opensentinel 2.1.1 → 3.1.1

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 (268) hide show
  1. package/README.md +354 -283
  2. package/dist/archiver-AVNBYCKQ.js +15340 -0
  3. package/dist/archiver-AVNBYCKQ.js.map +1 -0
  4. package/dist/audit-logger-OBPR7CRO.js +22 -0
  5. package/dist/auth-UOX5K2BE.js +18 -0
  6. package/dist/autonomy-ZXDBDQUJ.js +86 -0
  7. package/dist/autonomy-ZXDBDQUJ.js.map +1 -0
  8. package/dist/aws-s3-Q4LLZZPD.js +146 -0
  9. package/dist/aws-s3-Q4LLZZPD.js.map +1 -0
  10. package/dist/backup-restore-PZ7CYYB7.js +16 -0
  11. package/dist/blocks-R3PODY47.js +23 -0
  12. package/dist/bot-QRARP4UN.js +36 -0
  13. package/dist/brain-7XLLM3KC.js +56 -0
  14. package/dist/camera-monitor-M5CYKUU4.js +335 -0
  15. package/dist/camera-monitor-M5CYKUU4.js.map +1 -0
  16. package/dist/{charts-MMXM6BWW.js → charts-V7ARZNKF.js} +2 -2
  17. package/dist/chunk-22VGGA7S.js +330 -0
  18. package/dist/chunk-22VGGA7S.js.map +1 -0
  19. package/dist/chunk-35WYTA3C.js +382 -0
  20. package/dist/chunk-35WYTA3C.js.map +1 -0
  21. package/dist/chunk-3E2PSU2C.js +146 -0
  22. package/dist/chunk-3E2PSU2C.js.map +1 -0
  23. package/dist/{chunk-L3F43VPB.js → chunk-4GLYY4NN.js} +2 -2
  24. package/dist/{chunk-L3F43VPB.js.map → chunk-4GLYY4NN.js.map} +1 -1
  25. package/dist/{chunk-L3PDU3XN.js → chunk-4UOE5TUZ.js} +4 -4
  26. package/dist/{chunk-6SNHU3CY.js → chunk-66OJ3WB4.js} +2 -2
  27. package/dist/chunk-6KONMXQ6.js +297 -0
  28. package/dist/chunk-6KONMXQ6.js.map +1 -0
  29. package/dist/chunk-6PMVAAA7.js +196 -0
  30. package/dist/chunk-6PMVAAA7.js.map +1 -0
  31. package/dist/chunk-766ASQWE.js +32620 -0
  32. package/dist/chunk-766ASQWE.js.map +1 -0
  33. package/dist/chunk-7WQO5J2M.js +29 -0
  34. package/dist/chunk-7WQO5J2M.js.map +1 -0
  35. package/dist/chunk-APHSRMBS.js +148 -0
  36. package/dist/chunk-APHSRMBS.js.map +1 -0
  37. package/dist/{chunk-4LVWXUNC.js → chunk-AYUKPTSM.js} +57 -39
  38. package/dist/chunk-AYUKPTSM.js.map +1 -0
  39. package/dist/chunk-BIPYADGB.js +84 -0
  40. package/dist/chunk-BIPYADGB.js.map +1 -0
  41. package/dist/chunk-BRBWNV65.js +457 -0
  42. package/dist/chunk-BRBWNV65.js.map +1 -0
  43. package/dist/chunk-BXZ6EA52.js +382 -0
  44. package/dist/chunk-BXZ6EA52.js.map +1 -0
  45. package/dist/chunk-EVE7MIIY.js +290 -0
  46. package/dist/chunk-EVE7MIIY.js.map +1 -0
  47. package/dist/chunk-F3TTNID2.js +138 -0
  48. package/dist/chunk-F3TTNID2.js.map +1 -0
  49. package/dist/chunk-H5RQOFO2.js +190 -0
  50. package/dist/chunk-H5RQOFO2.js.map +1 -0
  51. package/dist/chunk-HN3F4WSW.js +145 -0
  52. package/dist/chunk-HN3F4WSW.js.map +1 -0
  53. package/dist/{chunk-6DRDKB45.js → chunk-I6BDYQIG.js} +20 -9
  54. package/dist/chunk-I6BDYQIG.js.map +1 -0
  55. package/dist/chunk-IZJMVV7O.js +347 -0
  56. package/dist/chunk-IZJMVV7O.js.map +1 -0
  57. package/dist/chunk-KM22GV7G.js +211 -0
  58. package/dist/chunk-KM22GV7G.js.map +1 -0
  59. package/dist/chunk-MGFBLVR7.js +103 -0
  60. package/dist/chunk-MGFBLVR7.js.map +1 -0
  61. package/dist/chunk-MQJ2ECQT.js +228 -0
  62. package/dist/chunk-MQJ2ECQT.js.map +1 -0
  63. package/dist/{chunk-F6QUZQGI.js → chunk-MXAPLSJ5.js} +2 -2
  64. package/dist/{chunk-GK3E2I7A.js → chunk-NHMBTUMW.js} +2 -2
  65. package/dist/chunk-NPRTSZIF.js +131 -0
  66. package/dist/chunk-NPRTSZIF.js.map +1 -0
  67. package/dist/chunk-O7IH7JTI.js +1898 -0
  68. package/dist/chunk-O7IH7JTI.js.map +1 -0
  69. package/dist/chunk-OCVQGBJK.js +293 -0
  70. package/dist/chunk-OCVQGBJK.js.map +1 -0
  71. package/dist/chunk-P6QINGFL.js +332 -0
  72. package/dist/chunk-P6QINGFL.js.map +1 -0
  73. package/dist/chunk-PHDZKPNE.js +91 -0
  74. package/dist/chunk-PHDZKPNE.js.map +1 -0
  75. package/dist/chunk-PLDDJCW6.js +49 -0
  76. package/dist/chunk-PTGTGXV2.js +164 -0
  77. package/dist/chunk-PTGTGXV2.js.map +1 -0
  78. package/dist/chunk-REMIY4U2.js +171 -0
  79. package/dist/chunk-REMIY4U2.js.map +1 -0
  80. package/dist/chunk-RZ4YESBG.js +141 -0
  81. package/dist/chunk-RZ4YESBG.js.map +1 -0
  82. package/dist/chunk-SAX5MHK4.js +111 -0
  83. package/dist/chunk-SAX5MHK4.js.map +1 -0
  84. package/dist/{chunk-GVJVEWHI.js → chunk-SJSUSJ47.js} +2 -2
  85. package/dist/chunk-SPPMCAKG.js +777 -0
  86. package/dist/chunk-SPPMCAKG.js.map +1 -0
  87. package/dist/chunk-SVAPX2XN.js +2441 -0
  88. package/dist/chunk-SVAPX2XN.js.map +1 -0
  89. package/dist/chunk-TVEWKIK3.js +452 -0
  90. package/dist/chunk-TVEWKIK3.js.map +1 -0
  91. package/dist/{chunk-HH2HBTQM.js → chunk-TYAGMJNV.js} +5 -5
  92. package/dist/{chunk-JXUP2X7V.js → chunk-VEHFVBLI.js} +2 -2
  93. package/dist/chunk-VNX5GMTN.js +128 -0
  94. package/dist/chunk-VNX5GMTN.js.map +1 -0
  95. package/dist/chunk-VRD5CYRL.js +1568 -0
  96. package/dist/chunk-VRD5CYRL.js.map +1 -0
  97. package/dist/chunk-WLUHNG6X.js +122 -0
  98. package/dist/chunk-WLUHNG6X.js.map +1 -0
  99. package/dist/chunk-WRAKK6K6.js +265 -0
  100. package/dist/chunk-WRAKK6K6.js.map +1 -0
  101. package/dist/chunk-XKYRH4FM.js +681 -0
  102. package/dist/chunk-XKYRH4FM.js.map +1 -0
  103. package/dist/{chunk-GUBEEYDW.js → chunk-XMCVRVTF.js} +2 -2
  104. package/dist/{chunk-GUBEEYDW.js.map → chunk-XMCVRVTF.js.map} +1 -1
  105. package/dist/chunk-ZLZKF2PM.js +310 -0
  106. package/dist/chunk-ZLZKF2PM.js.map +1 -0
  107. package/dist/cli.js +5 -1
  108. package/dist/cli.js.map +1 -1
  109. package/dist/client-ZQSFPMOB.js +21 -0
  110. package/dist/clipboard-manager-TEO2GEDN.js +24 -0
  111. package/dist/commands/setup.js +3 -3
  112. package/dist/commands/setup.js.map +1 -1
  113. package/dist/commands/start.js +3 -3
  114. package/dist/commands/status.js +2 -2
  115. package/dist/commands/stop.js +2 -2
  116. package/dist/commands/utils.js +2 -2
  117. package/dist/cron-explain-HHQKPD3M.js +16 -0
  118. package/dist/crypto-4AP47IKC.js +14 -0
  119. package/dist/crypto-4AP47IKC.js.map +1 -0
  120. package/dist/databases-37X4CI2Y.js +21 -0
  121. package/dist/databases-37X4CI2Y.js.map +1 -0
  122. package/dist/discord-B3HUPGQ6.js +70 -0
  123. package/dist/discord-B3HUPGQ6.js.map +1 -0
  124. package/dist/dist-UISMLMFN.js +21847 -0
  125. package/dist/dist-UISMLMFN.js.map +1 -0
  126. package/dist/email-K7LO2IPB.js +268 -0
  127. package/dist/email-K7LO2IPB.js.map +1 -0
  128. package/dist/enhanced-retrieval-DNLLEM4Z.js +753 -0
  129. package/dist/enhanced-retrieval-DNLLEM4Z.js.map +1 -0
  130. package/dist/enrichment-pipeline-MNHNW65K.js +13 -0
  131. package/dist/enrichment-pipeline-MNHNW65K.js.map +1 -0
  132. package/dist/entity-resolution-Y3IUWEAT.js +24 -0
  133. package/dist/entity-resolution-Y3IUWEAT.js.map +1 -0
  134. package/dist/env-IWXUVTCB.js +12 -0
  135. package/dist/env-IWXUVTCB.js.map +1 -0
  136. package/dist/google-workspace-DKWUVNGC.js +169 -0
  137. package/dist/google-workspace-DKWUVNGC.js.map +1 -0
  138. package/dist/hash-tool-ULQYD7B5.js +22 -0
  139. package/dist/hash-tool-ULQYD7B5.js.map +1 -0
  140. package/dist/heartbeat-monitor-GCISLXI3.js +22 -0
  141. package/dist/heartbeat-monitor-GCISLXI3.js.map +1 -0
  142. package/dist/image-generation-OSU7FP6F.js +486 -0
  143. package/dist/image-generation-OSU7FP6F.js.map +1 -0
  144. package/dist/imessage-NGA2XF2V.js +35 -0
  145. package/dist/imessage-NGA2XF2V.js.map +1 -0
  146. package/dist/inbox-summarizer-NRI4S7IF.js +47 -0
  147. package/dist/inbox-summarizer-NRI4S7IF.js.map +1 -0
  148. package/dist/incident-response-C5J7Q6DT.js +244 -0
  149. package/dist/incident-response-C5J7Q6DT.js.map +1 -0
  150. package/dist/inventory-manager-352OHXWD.js +24 -0
  151. package/dist/inventory-manager-352OHXWD.js.map +1 -0
  152. package/dist/jira-GSGDBMIG.js +199 -0
  153. package/dist/jira-GSGDBMIG.js.map +1 -0
  154. package/dist/json-tool-QE2SYHEG.js +26 -0
  155. package/dist/json-tool-QE2SYHEG.js.map +1 -0
  156. package/dist/key-rotation-DPHU4ZTB.js +18 -0
  157. package/dist/key-rotation-DPHU4ZTB.js.map +1 -0
  158. package/dist/lib.d.ts +603 -11
  159. package/dist/lib.js +161 -35
  160. package/dist/lib.js.map +1 -1
  161. package/dist/mailchimp-KKNF6QJ7.js +152 -0
  162. package/dist/mailchimp-KKNF6QJ7.js.map +1 -0
  163. package/dist/matrix-QVHG76I7.js +279 -0
  164. package/dist/matrix-QVHG76I7.js.map +1 -0
  165. package/dist/{mcp-LS7Q3Z5W.js → mcp-3JI6W7ZE.js} +3 -3
  166. package/dist/mcp-3JI6W7ZE.js.map +1 -0
  167. package/dist/microsoft365-UCBKJHNX.js +164 -0
  168. package/dist/microsoft365-UCBKJHNX.js.map +1 -0
  169. package/dist/ocr-AC7NPX33.js +22 -0
  170. package/dist/ocr-AC7NPX33.js.map +1 -0
  171. package/dist/ollama-BOAMSPLJ.js +8 -0
  172. package/dist/ollama-BOAMSPLJ.js.map +1 -0
  173. package/dist/pages-MI523RB7.js +26 -0
  174. package/dist/pages-MI523RB7.js.map +1 -0
  175. package/dist/pair-JDFTERIK.js +24 -0
  176. package/dist/pair-JDFTERIK.js.map +1 -0
  177. package/dist/pairing-IFQYCPNS.js +10 -0
  178. package/dist/pairing-IFQYCPNS.js.map +1 -0
  179. package/dist/pdf-ALQVOEJR.js +17 -0
  180. package/dist/pdf-ALQVOEJR.js.map +1 -0
  181. package/dist/presentations-DSV5IHG5.js +1002 -0
  182. package/dist/presentations-DSV5IHG5.js.map +1 -0
  183. package/dist/prometheus-JNT2BD4L.js +10 -0
  184. package/dist/prometheus-JNT2BD4L.js.map +1 -0
  185. package/dist/providers-J4LYPHDR.js +19 -0
  186. package/dist/providers-J4LYPHDR.js.map +1 -0
  187. package/dist/qr-code-WIX4PB4U.js +16 -0
  188. package/dist/qr-code-WIX4PB4U.js.map +1 -0
  189. package/dist/quickbooks-XB4NII2S.js +190 -0
  190. package/dist/quickbooks-XB4NII2S.js.map +1 -0
  191. package/dist/regex-tool-W4ABRKGK.js +24 -0
  192. package/dist/regex-tool-W4ABRKGK.js.map +1 -0
  193. package/dist/scheduler-VK4WFERV.js +63 -0
  194. package/dist/scheduler-VK4WFERV.js.map +1 -0
  195. package/dist/search-BCLBO5E3.js +25 -0
  196. package/dist/search-BCLBO5E3.js.map +1 -0
  197. package/dist/sendgrid-RNXCAFKM.js +152 -0
  198. package/dist/sendgrid-RNXCAFKM.js.map +1 -0
  199. package/dist/shopify-NCXYJB4R.js +171 -0
  200. package/dist/shopify-NCXYJB4R.js.map +1 -0
  201. package/dist/signal-6CGDFYL2.js +35 -0
  202. package/dist/signal-6CGDFYL2.js.map +1 -0
  203. package/dist/slack-IZQWIKOH.js +75 -0
  204. package/dist/slack-IZQWIKOH.js.map +1 -0
  205. package/dist/sms-M3JIOTCW.js +23 -0
  206. package/dist/sms-M3JIOTCW.js.map +1 -0
  207. package/dist/{src-K7GASHRH.js → src-VYUE6LRA.js} +138 -32
  208. package/dist/src-VYUE6LRA.js.map +1 -0
  209. package/dist/stocks-XXWBPOCU.js +14 -0
  210. package/dist/stocks-XXWBPOCU.js.map +1 -0
  211. package/dist/text-transform-6SGUA5Z4.js +22 -0
  212. package/dist/text-transform-6SGUA5Z4.js.map +1 -0
  213. package/dist/tools-2RLEI2N6.js +38 -0
  214. package/dist/tools-2RLEI2N6.js.map +1 -0
  215. package/dist/tunnel-IWMXUML4.js +301 -0
  216. package/dist/tunnel-IWMXUML4.js.map +1 -0
  217. package/dist/twilio-53GEW5JT.js +139 -0
  218. package/dist/twilio-53GEW5JT.js.map +1 -0
  219. package/dist/unit-converter-ZYXMEZOE.js +14 -0
  220. package/dist/unit-converter-ZYXMEZOE.js.map +1 -0
  221. package/dist/whatsapp-LFX6YKCM.js +35 -0
  222. package/dist/whatsapp-LFX6YKCM.js.map +1 -0
  223. package/dist/word-document-7B6SJMAY.js +902 -0
  224. package/dist/word-document-7B6SJMAY.js.map +1 -0
  225. package/dist/xero-QYO66D45.js +162 -0
  226. package/dist/xero-QYO66D45.js.map +1 -0
  227. package/dist/zapier-webhook-TBZ5YF2A.js +106 -0
  228. package/dist/zapier-webhook-TBZ5YF2A.js.map +1 -0
  229. package/drizzle/0002_mushy_master_mold.sql +140 -0
  230. package/drizzle/meta/0002_snapshot.json +3637 -0
  231. package/drizzle/meta/_journal.json +7 -0
  232. package/package.json +100 -98
  233. package/dist/bot-KJ26BG56.js +0 -15
  234. package/dist/chunk-4LVWXUNC.js.map +0 -1
  235. package/dist/chunk-4TG2IG5K.js +0 -5249
  236. package/dist/chunk-4TG2IG5K.js.map +0 -1
  237. package/dist/chunk-6DRDKB45.js.map +0 -1
  238. package/dist/chunk-CI6Q63MM.js +0 -1613
  239. package/dist/chunk-CI6Q63MM.js.map +0 -1
  240. package/dist/chunk-KHNYJY2Z.js +0 -178
  241. package/dist/chunk-KHNYJY2Z.js.map +0 -1
  242. package/dist/chunk-NSBPE2FW.js +0 -17
  243. package/dist/discord-ZOJFTVTB.js +0 -49
  244. package/dist/imessage-JFRB6EJ7.js +0 -14
  245. package/dist/scheduler-EZ7CZMCS.js +0 -42
  246. package/dist/signal-T3MCSULM.js +0 -14
  247. package/dist/slack-N2M4FHAJ.js +0 -54
  248. package/dist/src-K7GASHRH.js.map +0 -1
  249. package/dist/tools-24GZHYRF.js +0 -16
  250. package/dist/whatsapp-VCRUPAO5.js +0 -14
  251. /package/dist/{bot-KJ26BG56.js.map → audit-logger-OBPR7CRO.js.map} +0 -0
  252. /package/dist/{chunk-NSBPE2FW.js.map → auth-UOX5K2BE.js.map} +0 -0
  253. /package/dist/{discord-ZOJFTVTB.js.map → backup-restore-PZ7CYYB7.js.map} +0 -0
  254. /package/dist/{imessage-JFRB6EJ7.js.map → blocks-R3PODY47.js.map} +0 -0
  255. /package/dist/{mcp-LS7Q3Z5W.js.map → bot-QRARP4UN.js.map} +0 -0
  256. /package/dist/{scheduler-EZ7CZMCS.js.map → brain-7XLLM3KC.js.map} +0 -0
  257. /package/dist/{charts-MMXM6BWW.js.map → charts-V7ARZNKF.js.map} +0 -0
  258. /package/dist/{chunk-L3PDU3XN.js.map → chunk-4UOE5TUZ.js.map} +0 -0
  259. /package/dist/{chunk-6SNHU3CY.js.map → chunk-66OJ3WB4.js.map} +0 -0
  260. /package/dist/{chunk-F6QUZQGI.js.map → chunk-MXAPLSJ5.js.map} +0 -0
  261. /package/dist/{chunk-GK3E2I7A.js.map → chunk-NHMBTUMW.js.map} +0 -0
  262. /package/dist/{signal-T3MCSULM.js.map → chunk-PLDDJCW6.js.map} +0 -0
  263. /package/dist/{chunk-GVJVEWHI.js.map → chunk-SJSUSJ47.js.map} +0 -0
  264. /package/dist/{chunk-HH2HBTQM.js.map → chunk-TYAGMJNV.js.map} +0 -0
  265. /package/dist/{chunk-JXUP2X7V.js.map → chunk-VEHFVBLI.js.map} +0 -0
  266. /package/dist/{slack-N2M4FHAJ.js.map → client-ZQSFPMOB.js.map} +0 -0
  267. /package/dist/{tools-24GZHYRF.js.map → clipboard-manager-TEO2GEDN.js.map} +0 -0
  268. /package/dist/{whatsapp-VCRUPAO5.js.map → cron-explain-HHQKPD3M.js.map} +0 -0
@@ -0,0 +1,1002 @@
1
+ import {
2
+ isPathAllowed
3
+ } from "./chunk-CQ4JURG7.js";
4
+ import "./chunk-PLDDJCW6.js";
5
+
6
+ // src/tools/file-generation/presentations.ts
7
+ import { join } from "path";
8
+ import { tmpdir } from "os";
9
+ import { randomBytes } from "crypto";
10
+ import { writeFile, mkdir } from "fs/promises";
11
+ import { dirname } from "path";
12
+ var DEFAULT_THEME = {
13
+ backgroundColor: "FFFFFF",
14
+ titleColor: "2F5496",
15
+ textColor: "333333",
16
+ accentColor: "4472C4",
17
+ titleFont: "Calibri Light",
18
+ bodyFont: "Calibri"
19
+ };
20
+ var DEFAULT_OPTIONS = {
21
+ layout: "LAYOUT_16x9",
22
+ theme: DEFAULT_THEME
23
+ };
24
+ function getTempPath() {
25
+ const id = randomBytes(8).toString("hex");
26
+ return join(tmpdir(), `sentinel-presentation-${id}.pptx`);
27
+ }
28
+ function escapeXml(str) {
29
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
30
+ }
31
+ function percentToEmuX(percent, layout = "LAYOUT_16x9") {
32
+ const slideWidth = layout === "LAYOUT_4x3" ? 9144e3 : 12192e3;
33
+ return Math.round(percent / 100 * slideWidth);
34
+ }
35
+ function percentToEmuY(percent, layout = "LAYOUT_16x9") {
36
+ const slideHeight = layout === "LAYOUT_4x3" ? 6858e3 : 6858e3;
37
+ return Math.round(percent / 100 * slideHeight);
38
+ }
39
+ function normalizeColor(color) {
40
+ return color.replace("#", "").toUpperCase();
41
+ }
42
+ function generateContentTypesXml(slideCount) {
43
+ let overrides = "";
44
+ for (let i = 1; i <= slideCount; i++) {
45
+ overrides += `<Override PartName="/ppt/slides/slide${i}.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/>`;
46
+ }
47
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
48
+ <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
49
+ <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
50
+ <Default Extension="xml" ContentType="application/xml"/>
51
+ <Default Extension="jpeg" ContentType="image/jpeg"/>
52
+ <Default Extension="jpg" ContentType="image/jpeg"/>
53
+ <Default Extension="png" ContentType="image/png"/>
54
+ <Override PartName="/ppt/presentation.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"/>
55
+ <Override PartName="/ppt/slideMasters/slideMaster1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"/>
56
+ <Override PartName="/ppt/slideLayouts/slideLayout1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"/>
57
+ <Override PartName="/ppt/slideLayouts/slideLayout2.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"/>
58
+ <Override PartName="/ppt/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
59
+ ${overrides}
60
+ <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
61
+ <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
62
+ </Types>`;
63
+ }
64
+ function generateRootRelsXml() {
65
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
66
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
67
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="ppt/presentation.xml"/>
68
+ <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
69
+ <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
70
+ </Relationships>`;
71
+ }
72
+ function generatePresentationXml(slideCount, options) {
73
+ let slideIdList = "";
74
+ let slideRelIds = "";
75
+ for (let i = 1; i <= slideCount; i++) {
76
+ slideIdList += `<p:sldId id="${255 + i}" r:id="rId${i + 2}"/>`;
77
+ }
78
+ const layout = options.layout || "LAYOUT_16x9";
79
+ const slideWidth = layout === "LAYOUT_4x3" ? "9144000" : "12192000";
80
+ const slideHeight = "6858000";
81
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
82
+ <p:presentation xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
83
+ xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
84
+ xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"
85
+ saveSubsetFonts="1">
86
+ <p:sldMasterIdLst>
87
+ <p:sldMasterId id="2147483648" r:id="rId1"/>
88
+ </p:sldMasterIdLst>
89
+ <p:sldIdLst>
90
+ ${slideIdList}
91
+ </p:sldIdLst>
92
+ <p:sldSz cx="${slideWidth}" cy="${slideHeight}"/>
93
+ <p:notesSz cx="${slideHeight}" cy="${slideWidth}"/>
94
+ </p:presentation>`;
95
+ }
96
+ function generatePresentationRelsXml(slideCount) {
97
+ let slideRels = "";
98
+ for (let i = 1; i <= slideCount; i++) {
99
+ slideRels += `<Relationship Id="rId${i + 2}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="slides/slide${i}.xml"/>`;
100
+ }
101
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
102
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
103
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster" Target="slideMasters/slideMaster1.xml"/>
104
+ <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
105
+ ${slideRels}
106
+ </Relationships>`;
107
+ }
108
+ function generateThemeXml(theme) {
109
+ const t = { ...DEFAULT_THEME, ...theme };
110
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
111
+ <a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="OpenSentinel Theme">
112
+ <a:themeElements>
113
+ <a:clrScheme name="OpenSentinel">
114
+ <a:dk1><a:srgbClr val="000000"/></a:dk1>
115
+ <a:lt1><a:srgbClr val="${normalizeColor(t.backgroundColor)}"/></a:lt1>
116
+ <a:dk2><a:srgbClr val="${normalizeColor(t.titleColor)}"/></a:dk2>
117
+ <a:lt2><a:srgbClr val="EEECE1"/></a:lt2>
118
+ <a:accent1><a:srgbClr val="${normalizeColor(t.accentColor)}"/></a:accent1>
119
+ <a:accent2><a:srgbClr val="C0504D"/></a:accent2>
120
+ <a:accent3><a:srgbClr val="9BBB59"/></a:accent3>
121
+ <a:accent4><a:srgbClr val="8064A2"/></a:accent4>
122
+ <a:accent5><a:srgbClr val="4BACC6"/></a:accent5>
123
+ <a:accent6><a:srgbClr val="F79646"/></a:accent6>
124
+ <a:hlink><a:srgbClr val="0000FF"/></a:hlink>
125
+ <a:folHlink><a:srgbClr val="800080"/></a:folHlink>
126
+ </a:clrScheme>
127
+ <a:fontScheme name="OpenSentinel">
128
+ <a:majorFont>
129
+ <a:latin typeface="${t.titleFont}"/>
130
+ <a:ea typeface=""/>
131
+ <a:cs typeface=""/>
132
+ </a:majorFont>
133
+ <a:minorFont>
134
+ <a:latin typeface="${t.bodyFont}"/>
135
+ <a:ea typeface=""/>
136
+ <a:cs typeface=""/>
137
+ </a:minorFont>
138
+ </a:fontScheme>
139
+ <a:fmtScheme name="OpenSentinel">
140
+ <a:fillStyleLst>
141
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
142
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
143
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
144
+ </a:fillStyleLst>
145
+ <a:lnStyleLst>
146
+ <a:ln w="9525"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:ln>
147
+ <a:ln w="25400"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:ln>
148
+ <a:ln w="38100"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:ln>
149
+ </a:lnStyleLst>
150
+ <a:effectStyleLst>
151
+ <a:effectStyle><a:effectLst/></a:effectStyle>
152
+ <a:effectStyle><a:effectLst/></a:effectStyle>
153
+ <a:effectStyle><a:effectLst/></a:effectStyle>
154
+ </a:effectStyleLst>
155
+ <a:bgFillStyleLst>
156
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
157
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
158
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
159
+ </a:bgFillStyleLst>
160
+ </a:fmtScheme>
161
+ </a:themeElements>
162
+ </a:theme>`;
163
+ }
164
+ function generateSlideMasterXml(theme, layout) {
165
+ const t = { ...DEFAULT_THEME, ...theme };
166
+ const slideWidth = layout === "LAYOUT_4x3" ? 9144e3 : 12192e3;
167
+ const slideHeight = 6858e3;
168
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
169
+ <p:sldMaster xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
170
+ xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
171
+ xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
172
+ <p:cSld>
173
+ <p:bg>
174
+ <p:bgPr>
175
+ <a:solidFill>
176
+ <a:srgbClr val="${normalizeColor(t.backgroundColor)}"/>
177
+ </a:solidFill>
178
+ <a:effectLst/>
179
+ </p:bgPr>
180
+ </p:bg>
181
+ <p:spTree>
182
+ <p:nvGrpSpPr>
183
+ <p:cNvPr id="1" name=""/>
184
+ <p:cNvGrpSpPr/>
185
+ <p:nvPr/>
186
+ </p:nvGrpSpPr>
187
+ <p:grpSpPr>
188
+ <a:xfrm>
189
+ <a:off x="0" y="0"/>
190
+ <a:ext cx="0" cy="0"/>
191
+ <a:chOff x="0" y="0"/>
192
+ <a:chExt cx="0" cy="0"/>
193
+ </a:xfrm>
194
+ </p:grpSpPr>
195
+ </p:spTree>
196
+ </p:cSld>
197
+ <p:clrMap bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2" accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4" accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/>
198
+ <p:sldLayoutIdLst>
199
+ <p:sldLayoutId id="2147483649" r:id="rId1"/>
200
+ <p:sldLayoutId id="2147483650" r:id="rId2"/>
201
+ </p:sldLayoutIdLst>
202
+ </p:sldMaster>`;
203
+ }
204
+ function generateSlideMasterRelsXml() {
205
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
206
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
207
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout1.xml"/>
208
+ <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout2.xml"/>
209
+ <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="../theme/theme1.xml"/>
210
+ </Relationships>`;
211
+ }
212
+ function generateSlideLayoutXml(layoutType) {
213
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
214
+ <p:sldLayout xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
215
+ xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
216
+ xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"
217
+ type="${layoutType === "title" ? "title" : "obj"}">
218
+ <p:cSld name="${layoutType === "title" ? "Title Slide" : "Title and Content"}">
219
+ <p:spTree>
220
+ <p:nvGrpSpPr>
221
+ <p:cNvPr id="1" name=""/>
222
+ <p:cNvGrpSpPr/>
223
+ <p:nvPr/>
224
+ </p:nvGrpSpPr>
225
+ <p:grpSpPr/>
226
+ </p:spTree>
227
+ </p:cSld>
228
+ <p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr>
229
+ </p:sldLayout>`;
230
+ }
231
+ function generateSlideLayoutRelsXml() {
232
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
233
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
234
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster" Target="../slideMasters/slideMaster1.xml"/>
235
+ </Relationships>`;
236
+ }
237
+ function generateSlideXml(slide, slideIndex, options) {
238
+ const theme = { ...DEFAULT_THEME, ...options.theme };
239
+ const layout = options.layout || "LAYOUT_16x9";
240
+ const slideWidth = layout === "LAYOUT_4x3" ? 9144e3 : 12192e3;
241
+ const slideHeight = 6858e3;
242
+ let shapesXml = "";
243
+ let shapeId = 2;
244
+ let bgXml = "";
245
+ if (slide.backgroundColor) {
246
+ bgXml = `<p:bg>
247
+ <p:bgPr>
248
+ <a:solidFill><a:srgbClr val="${normalizeColor(slide.backgroundColor)}"/></a:solidFill>
249
+ <a:effectLst/>
250
+ </p:bgPr>
251
+ </p:bg>`;
252
+ }
253
+ if (slide.title) {
254
+ const titleY = slide.layout === "title" ? 30 : 5;
255
+ const titleFontSize = slide.layout === "title" ? 4400 : 3200;
256
+ shapesXml += `<p:sp>
257
+ <p:nvSpPr>
258
+ <p:cNvPr id="${shapeId++}" name="Title"/>
259
+ <p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr>
260
+ <p:nvPr><p:ph type="title"/></p:nvPr>
261
+ </p:nvSpPr>
262
+ <p:spPr>
263
+ <a:xfrm>
264
+ <a:off x="${Math.round(slideWidth * 0.05)}" y="${Math.round(slideHeight * titleY / 100)}"/>
265
+ <a:ext cx="${Math.round(slideWidth * 0.9)}" cy="${Math.round(slideHeight * 0.15)}"/>
266
+ </a:xfrm>
267
+ </p:spPr>
268
+ <p:txBody>
269
+ <a:bodyPr anchor="ctr"/>
270
+ <a:lstStyle/>
271
+ <a:p>
272
+ <a:pPr algn="ctr"/>
273
+ <a:r>
274
+ <a:rPr lang="en-US" sz="${titleFontSize}" b="1">
275
+ <a:solidFill><a:srgbClr val="${normalizeColor(theme.titleColor)}"/></a:solidFill>
276
+ <a:latin typeface="${theme.titleFont}"/>
277
+ </a:rPr>
278
+ <a:t>${escapeXml(slide.title)}</a:t>
279
+ </a:r>
280
+ </a:p>
281
+ </p:txBody>
282
+ </p:sp>`;
283
+ }
284
+ if (slide.subtitle && slide.layout === "title") {
285
+ shapesXml += `<p:sp>
286
+ <p:nvSpPr>
287
+ <p:cNvPr id="${shapeId++}" name="Subtitle"/>
288
+ <p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr>
289
+ <p:nvPr><p:ph type="subTitle"/></p:nvPr>
290
+ </p:nvSpPr>
291
+ <p:spPr>
292
+ <a:xfrm>
293
+ <a:off x="${Math.round(slideWidth * 0.1)}" y="${Math.round(slideHeight * 0.55)}"/>
294
+ <a:ext cx="${Math.round(slideWidth * 0.8)}" cy="${Math.round(slideHeight * 0.15)}"/>
295
+ </a:xfrm>
296
+ </p:spPr>
297
+ <p:txBody>
298
+ <a:bodyPr anchor="t"/>
299
+ <a:lstStyle/>
300
+ <a:p>
301
+ <a:pPr algn="ctr"/>
302
+ <a:r>
303
+ <a:rPr lang="en-US" sz="2400">
304
+ <a:solidFill><a:srgbClr val="${normalizeColor(theme.textColor)}"/></a:solidFill>
305
+ <a:latin typeface="${theme.bodyFont}"/>
306
+ </a:rPr>
307
+ <a:t>${escapeXml(slide.subtitle)}</a:t>
308
+ </a:r>
309
+ </a:p>
310
+ </p:txBody>
311
+ </p:sp>`;
312
+ }
313
+ if (slide.content) {
314
+ for (const element of slide.content) {
315
+ shapesXml += generateContentElementXml(element, shapeId++, options, theme);
316
+ }
317
+ }
318
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
319
+ <p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
320
+ xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
321
+ xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
322
+ <p:cSld>
323
+ ${bgXml}
324
+ <p:spTree>
325
+ <p:nvGrpSpPr>
326
+ <p:cNvPr id="1" name=""/>
327
+ <p:cNvGrpSpPr/>
328
+ <p:nvPr/>
329
+ </p:nvGrpSpPr>
330
+ <p:grpSpPr>
331
+ <a:xfrm>
332
+ <a:off x="0" y="0"/>
333
+ <a:ext cx="0" cy="0"/>
334
+ <a:chOff x="0" y="0"/>
335
+ <a:chExt cx="0" cy="0"/>
336
+ </a:xfrm>
337
+ </p:grpSpPr>
338
+ ${shapesXml}
339
+ </p:spTree>
340
+ </p:cSld>
341
+ <p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr>
342
+ </p:sld>`;
343
+ }
344
+ function generateContentElementXml(element, shapeId, options, theme) {
345
+ const layout = options.layout || "LAYOUT_16x9";
346
+ const slideWidth = layout === "LAYOUT_4x3" ? 9144e3 : 12192e3;
347
+ const slideHeight = 6858e3;
348
+ const x = element.x !== void 0 ? percentToEmuX(element.x, layout) : Math.round(slideWidth * 0.05);
349
+ const y = element.y !== void 0 ? percentToEmuY(element.y, layout) : Math.round(slideHeight * 0.25);
350
+ const width = element.width !== void 0 ? percentToEmuX(element.width, layout) : Math.round(slideWidth * 0.9);
351
+ const height = element.height !== void 0 ? percentToEmuY(element.height, layout) : Math.round(slideHeight * 0.65);
352
+ switch (element.type) {
353
+ case "text":
354
+ return generateTextElementXml(element, shapeId, x, y, width, height, theme);
355
+ case "bullet-list":
356
+ return generateBulletListElementXml(element, shapeId, x, y, width, height, theme);
357
+ case "numbered-list":
358
+ return generateNumberedListElementXml(element, shapeId, x, y, width, height, theme);
359
+ case "table":
360
+ return generateTableElementXml(element, shapeId, x, y, width, height, theme);
361
+ case "shape":
362
+ return generateShapeElementXml(element, shapeId, x, y, width, height);
363
+ case "image":
364
+ return generateImagePlaceholderXml(element, shapeId, x, y, width, height);
365
+ case "chart":
366
+ return generateChartPlaceholderXml(element, shapeId, x, y, width, height, theme);
367
+ default:
368
+ return "";
369
+ }
370
+ }
371
+ function generateTextElementXml(element, shapeId, x, y, width, height, theme) {
372
+ const fontSize = (element.fontSize || 18) * 100;
373
+ const color = element.color ? normalizeColor(element.color) : normalizeColor(theme.textColor);
374
+ const font = element.fontFace || theme.bodyFont;
375
+ const align = element.align || "left";
376
+ const valign = element.valign || "top";
377
+ let rPr = `<a:rPr lang="en-US" sz="${fontSize}"`;
378
+ if (element.bold) rPr += ' b="1"';
379
+ if (element.italic) rPr += ' i="1"';
380
+ if (element.underline) rPr += ' u="sng"';
381
+ rPr += `><a:solidFill><a:srgbClr val="${color}"/></a:solidFill><a:latin typeface="${font}"/></a:rPr>`;
382
+ return `<p:sp>
383
+ <p:nvSpPr>
384
+ <p:cNvPr id="${shapeId}" name="TextBox ${shapeId}"/>
385
+ <p:cNvSpPr txBox="1"/>
386
+ <p:nvPr/>
387
+ </p:nvSpPr>
388
+ <p:spPr>
389
+ <a:xfrm><a:off x="${x}" y="${y}"/><a:ext cx="${width}" cy="${height}"/></a:xfrm>
390
+ <a:prstGeom prst="rect"><a:avLst/></a:prstGeom>
391
+ <a:noFill/>
392
+ </p:spPr>
393
+ <p:txBody>
394
+ <a:bodyPr anchor="${valign === "middle" ? "ctr" : valign === "bottom" ? "b" : "t"}"/>
395
+ <a:lstStyle/>
396
+ <a:p>
397
+ <a:pPr algn="${align === "center" ? "ctr" : align === "right" ? "r" : "l"}"/>
398
+ <a:r>${rPr}<a:t>${escapeXml(element.text)}</a:t></a:r>
399
+ </a:p>
400
+ </p:txBody>
401
+ </p:sp>`;
402
+ }
403
+ function generateBulletListElementXml(element, shapeId, x, y, width, height, theme) {
404
+ const fontSize = (element.fontSize || 18) * 100;
405
+ const color = element.color ? normalizeColor(element.color) : normalizeColor(theme.textColor);
406
+ const bulletColor = element.bulletColor ? normalizeColor(element.bulletColor) : normalizeColor(theme.accentColor);
407
+ let paragraphs = "";
408
+ for (const item of element.items) {
409
+ paragraphs += `<a:p>
410
+ <a:pPr marL="457200" indent="-457200">
411
+ <a:buFont typeface="Arial"/>
412
+ <a:buChar char="\u2022"/>
413
+ <a:buClr><a:srgbClr val="${bulletColor}"/></a:buClr>
414
+ </a:pPr>
415
+ <a:r>
416
+ <a:rPr lang="en-US" sz="${fontSize}">
417
+ <a:solidFill><a:srgbClr val="${color}"/></a:solidFill>
418
+ <a:latin typeface="${theme.bodyFont}"/>
419
+ </a:rPr>
420
+ <a:t>${escapeXml(item)}</a:t>
421
+ </a:r>
422
+ </a:p>`;
423
+ }
424
+ return `<p:sp>
425
+ <p:nvSpPr>
426
+ <p:cNvPr id="${shapeId}" name="Content ${shapeId}"/>
427
+ <p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr>
428
+ <p:nvPr><p:ph idx="1"/></p:nvPr>
429
+ </p:nvSpPr>
430
+ <p:spPr>
431
+ <a:xfrm><a:off x="${x}" y="${y}"/><a:ext cx="${width}" cy="${height}"/></a:xfrm>
432
+ </p:spPr>
433
+ <p:txBody>
434
+ <a:bodyPr/>
435
+ <a:lstStyle/>
436
+ ${paragraphs}
437
+ </p:txBody>
438
+ </p:sp>`;
439
+ }
440
+ function generateNumberedListElementXml(element, shapeId, x, y, width, height, theme) {
441
+ const fontSize = (element.fontSize || 18) * 100;
442
+ const color = element.color ? normalizeColor(element.color) : normalizeColor(theme.textColor);
443
+ const startNum = element.startNumber || 1;
444
+ let paragraphs = "";
445
+ for (let i = 0; i < element.items.length; i++) {
446
+ paragraphs += `<a:p>
447
+ <a:pPr marL="457200" indent="-457200">
448
+ <a:buFont typeface="Arial"/>
449
+ <a:buAutoNum type="arabicPeriod" startAt="${startNum}"/>
450
+ </a:pPr>
451
+ <a:r>
452
+ <a:rPr lang="en-US" sz="${fontSize}">
453
+ <a:solidFill><a:srgbClr val="${color}"/></a:solidFill>
454
+ <a:latin typeface="${theme.bodyFont}"/>
455
+ </a:rPr>
456
+ <a:t>${escapeXml(element.items[i])}</a:t>
457
+ </a:r>
458
+ </a:p>`;
459
+ }
460
+ return `<p:sp>
461
+ <p:nvSpPr>
462
+ <p:cNvPr id="${shapeId}" name="Content ${shapeId}"/>
463
+ <p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr>
464
+ <p:nvPr><p:ph idx="1"/></p:nvPr>
465
+ </p:nvSpPr>
466
+ <p:spPr>
467
+ <a:xfrm><a:off x="${x}" y="${y}"/><a:ext cx="${width}" cy="${height}"/></a:xfrm>
468
+ </p:spPr>
469
+ <p:txBody>
470
+ <a:bodyPr/>
471
+ <a:lstStyle/>
472
+ ${paragraphs}
473
+ </p:txBody>
474
+ </p:sp>`;
475
+ }
476
+ function generateTableElementXml(element, shapeId, x, y, width, height, theme) {
477
+ const colCount = element.headers?.length || element.rows[0]?.length || 1;
478
+ const rowCount = (element.headers ? 1 : 0) + element.rows.length;
479
+ const colWidth = Math.round(width / colCount);
480
+ const rowHeight = Math.round(height / rowCount);
481
+ const headerColor = element.headerColor ? normalizeColor(element.headerColor) : normalizeColor(theme.accentColor);
482
+ const headerTextColor = element.headerTextColor ? normalizeColor(element.headerTextColor) : "FFFFFF";
483
+ const borderColor = element.borderColor ? normalizeColor(element.borderColor) : "CCCCCC";
484
+ const altRowColor = element.alternateRowColor ? normalizeColor(element.alternateRowColor) : "F5F5F5";
485
+ let gridCols = "";
486
+ for (let i = 0; i < colCount; i++) {
487
+ gridCols += `<a:gridCol w="${colWidth}"/>`;
488
+ }
489
+ let rowsXml = "";
490
+ if (element.headers) {
491
+ let cells = "";
492
+ for (const header of element.headers) {
493
+ cells += `<a:tc>
494
+ <a:txBody>
495
+ <a:bodyPr/>
496
+ <a:lstStyle/>
497
+ <a:p>
498
+ <a:pPr algn="ctr"/>
499
+ <a:r>
500
+ <a:rPr lang="en-US" sz="1400" b="1">
501
+ <a:solidFill><a:srgbClr val="${headerTextColor}"/></a:solidFill>
502
+ </a:rPr>
503
+ <a:t>${escapeXml(header)}</a:t>
504
+ </a:r>
505
+ </a:p>
506
+ </a:txBody>
507
+ <a:tcPr>
508
+ <a:solidFill><a:srgbClr val="${headerColor}"/></a:solidFill>
509
+ </a:tcPr>
510
+ </a:tc>`;
511
+ }
512
+ rowsXml += `<a:tr h="${rowHeight}">${cells}</a:tr>`;
513
+ }
514
+ for (let rowIdx = 0; rowIdx < element.rows.length; rowIdx++) {
515
+ const row = element.rows[rowIdx];
516
+ const rowBg = rowIdx % 2 === 1 ? altRowColor : "FFFFFF";
517
+ let cells = "";
518
+ for (const cell of row) {
519
+ cells += `<a:tc>
520
+ <a:txBody>
521
+ <a:bodyPr/>
522
+ <a:lstStyle/>
523
+ <a:p>
524
+ <a:r>
525
+ <a:rPr lang="en-US" sz="1200">
526
+ <a:solidFill><a:srgbClr val="${normalizeColor(theme.textColor)}"/></a:solidFill>
527
+ </a:rPr>
528
+ <a:t>${escapeXml(cell)}</a:t>
529
+ </a:r>
530
+ </a:p>
531
+ </a:txBody>
532
+ <a:tcPr>
533
+ <a:solidFill><a:srgbClr val="${rowBg}"/></a:solidFill>
534
+ </a:tcPr>
535
+ </a:tc>`;
536
+ }
537
+ rowsXml += `<a:tr h="${rowHeight}">${cells}</a:tr>`;
538
+ }
539
+ return `<p:graphicFrame>
540
+ <p:nvGraphicFramePr>
541
+ <p:cNvPr id="${shapeId}" name="Table ${shapeId}"/>
542
+ <p:cNvGraphicFramePr><a:graphicFrameLocks noGrp="1"/></p:cNvGraphicFramePr>
543
+ <p:nvPr/>
544
+ </p:nvGraphicFramePr>
545
+ <p:xfrm><a:off x="${x}" y="${y}"/><a:ext cx="${width}" cy="${height}"/></p:xfrm>
546
+ <a:graphic>
547
+ <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/table">
548
+ <a:tbl>
549
+ <a:tblPr firstRow="1" bandRow="1">
550
+ <a:tableStyleId>{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}</a:tableStyleId>
551
+ </a:tblPr>
552
+ <a:tblGrid>${gridCols}</a:tblGrid>
553
+ ${rowsXml}
554
+ </a:tbl>
555
+ </a:graphicData>
556
+ </a:graphic>
557
+ </p:graphicFrame>`;
558
+ }
559
+ function generateShapeElementXml(element, shapeId, x, y, width, height) {
560
+ const shapeTypeMap = {
561
+ rectangle: "rect",
562
+ ellipse: "ellipse",
563
+ triangle: "triangle",
564
+ arrow: "rightArrow",
565
+ line: "line"
566
+ };
567
+ const prstGeom = shapeTypeMap[element.shapeType] || "rect";
568
+ const fill = element.fill ? normalizeColor(element.fill) : "4472C4";
569
+ const stroke = element.stroke ? normalizeColor(element.stroke) : fill;
570
+ const strokeWidth = (element.strokeWidth || 1) * 12700;
571
+ let textXml = "";
572
+ if (element.text) {
573
+ const textColor = element.textColor ? normalizeColor(element.textColor) : "FFFFFF";
574
+ textXml = `<p:txBody>
575
+ <a:bodyPr anchor="ctr"/>
576
+ <a:lstStyle/>
577
+ <a:p>
578
+ <a:pPr algn="ctr"/>
579
+ <a:r>
580
+ <a:rPr lang="en-US" sz="1400">
581
+ <a:solidFill><a:srgbClr val="${textColor}"/></a:solidFill>
582
+ </a:rPr>
583
+ <a:t>${escapeXml(element.text)}</a:t>
584
+ </a:r>
585
+ </a:p>
586
+ </p:txBody>`;
587
+ }
588
+ return `<p:sp>
589
+ <p:nvSpPr>
590
+ <p:cNvPr id="${shapeId}" name="Shape ${shapeId}"/>
591
+ <p:cNvSpPr/>
592
+ <p:nvPr/>
593
+ </p:nvSpPr>
594
+ <p:spPr>
595
+ <a:xfrm><a:off x="${x}" y="${y}"/><a:ext cx="${width}" cy="${height}"/></a:xfrm>
596
+ <a:prstGeom prst="${prstGeom}"><a:avLst/></a:prstGeom>
597
+ <a:solidFill><a:srgbClr val="${fill}"/></a:solidFill>
598
+ <a:ln w="${strokeWidth}"><a:solidFill><a:srgbClr val="${stroke}"/></a:solidFill></a:ln>
599
+ </p:spPr>
600
+ ${textXml}
601
+ </p:sp>`;
602
+ }
603
+ function generateImagePlaceholderXml(element, shapeId, x, y, width, height) {
604
+ return `<p:sp>
605
+ <p:nvSpPr>
606
+ <p:cNvPr id="${shapeId}" name="Image Placeholder ${shapeId}"/>
607
+ <p:cNvSpPr/>
608
+ <p:nvPr/>
609
+ </p:nvSpPr>
610
+ <p:spPr>
611
+ <a:xfrm><a:off x="${x}" y="${y}"/><a:ext cx="${width}" cy="${height}"/></a:xfrm>
612
+ <a:prstGeom prst="rect"><a:avLst/></a:prstGeom>
613
+ <a:solidFill><a:srgbClr val="E0E0E0"/></a:solidFill>
614
+ <a:ln><a:solidFill><a:srgbClr val="CCCCCC"/></a:solidFill></a:ln>
615
+ </p:spPr>
616
+ <p:txBody>
617
+ <a:bodyPr anchor="ctr"/>
618
+ <a:lstStyle/>
619
+ <a:p>
620
+ <a:pPr algn="ctr"/>
621
+ <a:r>
622
+ <a:rPr lang="en-US" sz="1200" i="1">
623
+ <a:solidFill><a:srgbClr val="666666"/></a:solidFill>
624
+ </a:rPr>
625
+ <a:t>[Image: ${escapeXml(element.path)}]</a:t>
626
+ </a:r>
627
+ </a:p>
628
+ </p:txBody>
629
+ </p:sp>`;
630
+ }
631
+ function generateChartPlaceholderXml(element, shapeId, x, y, width, height, theme) {
632
+ const title = element.title || `${element.chartType.charAt(0).toUpperCase() + element.chartType.slice(1)} Chart`;
633
+ return `<p:sp>
634
+ <p:nvSpPr>
635
+ <p:cNvPr id="${shapeId}" name="Chart Placeholder ${shapeId}"/>
636
+ <p:cNvSpPr/>
637
+ <p:nvPr/>
638
+ </p:nvSpPr>
639
+ <p:spPr>
640
+ <a:xfrm><a:off x="${x}" y="${y}"/><a:ext cx="${width}" cy="${height}"/></a:xfrm>
641
+ <a:prstGeom prst="rect"><a:avLst/></a:prstGeom>
642
+ <a:solidFill><a:srgbClr val="F5F5F5"/></a:solidFill>
643
+ <a:ln><a:solidFill><a:srgbClr val="${normalizeColor(theme.accentColor)}"/></a:solidFill></a:ln>
644
+ </p:spPr>
645
+ <p:txBody>
646
+ <a:bodyPr anchor="ctr"/>
647
+ <a:lstStyle/>
648
+ <a:p>
649
+ <a:pPr algn="ctr"/>
650
+ <a:r>
651
+ <a:rPr lang="en-US" sz="1400" b="1">
652
+ <a:solidFill><a:srgbClr val="${normalizeColor(theme.textColor)}"/></a:solidFill>
653
+ </a:rPr>
654
+ <a:t>${escapeXml(title)}</a:t>
655
+ </a:r>
656
+ </a:p>
657
+ <a:p>
658
+ <a:pPr algn="ctr"/>
659
+ <a:r>
660
+ <a:rPr lang="en-US" sz="1000" i="1">
661
+ <a:solidFill><a:srgbClr val="666666"/></a:solidFill>
662
+ </a:rPr>
663
+ <a:t>[Chart placeholder - Labels: ${element.labels.join(", ")}]</a:t>
664
+ </a:r>
665
+ </a:p>
666
+ </p:txBody>
667
+ </p:sp>`;
668
+ }
669
+ function generateSlideRelsXml(slideIndex) {
670
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
671
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
672
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout2.xml"/>
673
+ </Relationships>`;
674
+ }
675
+ function generateCorePropsXml(options) {
676
+ const now = (/* @__PURE__ */ new Date()).toISOString();
677
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
678
+ <cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
679
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
680
+ xmlns:dcterms="http://purl.org/dc/terms/"
681
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
682
+ ${options.title ? `<dc:title>${escapeXml(options.title)}</dc:title>` : ""}
683
+ ${options.author ? `<dc:creator>${escapeXml(options.author)}</dc:creator>` : "<dc:creator>OpenSentinel</dc:creator>"}
684
+ ${options.subject ? `<dc:subject>${escapeXml(options.subject)}</dc:subject>` : ""}
685
+ <dcterms:created xsi:type="dcterms:W3CDTF">${now}</dcterms:created>
686
+ <dcterms:modified xsi:type="dcterms:W3CDTF">${now}</dcterms:modified>
687
+ </cp:coreProperties>`;
688
+ }
689
+ function generateAppPropsXml(options, slideCount) {
690
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
691
+ <Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties">
692
+ <Application>OpenSentinel Presentation Generator</Application>
693
+ <AppVersion>1.0</AppVersion>
694
+ ${options.company ? `<Company>${escapeXml(options.company)}</Company>` : ""}
695
+ <Slides>${slideCount}</Slides>
696
+ <HiddenSlides>0</HiddenSlides>
697
+ </Properties>`;
698
+ }
699
+ async function generatePresentation(slides, filename, options = {}) {
700
+ const filePath = filename ? isPathAllowed(filename) ? filename : join(tmpdir(), filename) : getTempPath();
701
+ if (slides.length === 0) {
702
+ return { success: false, error: "No slides provided" };
703
+ }
704
+ try {
705
+ await mkdir(dirname(filePath), { recursive: true });
706
+ try {
707
+ const PptxGenJS = await import("pptxgenjs");
708
+ return await generateWithPptxGenJs(slides, filePath, options, PptxGenJS.default);
709
+ } catch {
710
+ console.log("[Presentations] pptxgenjs library not available, using raw OOXML generation");
711
+ return await generateRawPptx(slides, filePath, options);
712
+ }
713
+ } catch (error) {
714
+ return {
715
+ success: false,
716
+ error: error instanceof Error ? error.message : String(error)
717
+ };
718
+ }
719
+ }
720
+ async function generateWithPptxGenJs(slides, filePath, options, PptxGenJS) {
721
+ const pptx = new PptxGenJS();
722
+ if (options.title) pptx.title = options.title;
723
+ if (options.author) pptx.author = options.author;
724
+ if (options.subject) pptx.subject = options.subject;
725
+ if (options.company) pptx.company = options.company;
726
+ if (options.layout === "LAYOUT_4x3") {
727
+ pptx.layout = "LAYOUT_4x3";
728
+ } else {
729
+ pptx.layout = "LAYOUT_16x9";
730
+ }
731
+ const theme = { ...DEFAULT_THEME, ...options.theme };
732
+ for (const slideData of slides) {
733
+ const slide = pptx.addSlide();
734
+ if (slideData.backgroundColor) {
735
+ slide.background = { color: slideData.backgroundColor.replace("#", "") };
736
+ }
737
+ if (slideData.title) {
738
+ const titleY = slideData.layout === "title" ? "40%" : "5%";
739
+ const fontSize = slideData.layout === "title" ? 44 : 32;
740
+ slide.addText(slideData.title, {
741
+ x: "5%",
742
+ y: titleY,
743
+ w: "90%",
744
+ h: "15%",
745
+ fontSize,
746
+ bold: true,
747
+ color: theme.titleColor?.replace("#", ""),
748
+ fontFace: theme.titleFont,
749
+ align: "center",
750
+ valign: "middle"
751
+ });
752
+ }
753
+ if (slideData.subtitle && slideData.layout === "title") {
754
+ slide.addText(slideData.subtitle, {
755
+ x: "10%",
756
+ y: "55%",
757
+ w: "80%",
758
+ h: "15%",
759
+ fontSize: 24,
760
+ color: theme.textColor?.replace("#", ""),
761
+ fontFace: theme.bodyFont,
762
+ align: "center",
763
+ valign: "top"
764
+ });
765
+ }
766
+ if (slideData.content) {
767
+ for (const element of slideData.content) {
768
+ addContentElementToPptx(slide, element, theme);
769
+ }
770
+ }
771
+ if (slideData.notes) {
772
+ slide.addNotes(slideData.notes);
773
+ }
774
+ }
775
+ await pptx.writeFile({ fileName: filePath });
776
+ return { success: true, filePath };
777
+ }
778
+ function addContentElementToPptx(slide, element, theme) {
779
+ const x = element.x !== void 0 ? `${element.x}%` : "5%";
780
+ const y = element.y !== void 0 ? `${element.y}%` : "25%";
781
+ const w = element.width !== void 0 ? `${element.width}%` : "90%";
782
+ const h = element.height !== void 0 ? `${element.height}%` : "65%";
783
+ switch (element.type) {
784
+ case "text":
785
+ slide.addText(element.text, {
786
+ x,
787
+ y,
788
+ w,
789
+ h,
790
+ fontSize: element.fontSize || 18,
791
+ fontFace: element.fontFace || theme.bodyFont,
792
+ color: element.color?.replace("#", "") || theme.textColor?.replace("#", ""),
793
+ bold: element.bold,
794
+ italic: element.italic,
795
+ underline: element.underline ? { style: "sng" } : void 0,
796
+ align: element.align,
797
+ valign: element.valign
798
+ });
799
+ break;
800
+ case "bullet-list":
801
+ slide.addText(
802
+ element.items.map((item) => ({
803
+ text: item,
804
+ options: { bullet: { type: "bullet" } }
805
+ })),
806
+ {
807
+ x,
808
+ y,
809
+ w,
810
+ h,
811
+ fontSize: element.fontSize || 18,
812
+ color: element.color?.replace("#", "") || theme.textColor?.replace("#", "")
813
+ }
814
+ );
815
+ break;
816
+ case "numbered-list":
817
+ slide.addText(
818
+ element.items.map((item, idx) => ({
819
+ text: item,
820
+ options: { bullet: { type: "number", numberStartAt: element.startNumber || 1 } }
821
+ })),
822
+ {
823
+ x,
824
+ y,
825
+ w,
826
+ h,
827
+ fontSize: element.fontSize || 18,
828
+ color: element.color?.replace("#", "") || theme.textColor?.replace("#", "")
829
+ }
830
+ );
831
+ break;
832
+ case "table":
833
+ const tableData = [];
834
+ if (element.headers) {
835
+ tableData.push(element.headers);
836
+ }
837
+ tableData.push(...element.rows);
838
+ slide.addTable(tableData, {
839
+ x,
840
+ y,
841
+ w,
842
+ h,
843
+ border: { color: element.borderColor?.replace("#", "") || "CCCCCC" },
844
+ fill: { color: "FFFFFF" },
845
+ fontFace: theme.bodyFont,
846
+ fontSize: 12
847
+ });
848
+ break;
849
+ case "shape":
850
+ const shapeTypeMap = {
851
+ rectangle: "rect",
852
+ ellipse: "ellipse",
853
+ triangle: "triangle",
854
+ arrow: "rightArrow",
855
+ line: "line"
856
+ };
857
+ slide.addShape(shapeTypeMap[element.shapeType] || "rect", {
858
+ x,
859
+ y,
860
+ w,
861
+ h,
862
+ fill: { color: element.fill?.replace("#", "") || theme.accentColor?.replace("#", "") },
863
+ line: {
864
+ color: element.stroke?.replace("#", "") || element.fill?.replace("#", "") || theme.accentColor?.replace("#", ""),
865
+ width: element.strokeWidth || 1
866
+ }
867
+ });
868
+ if (element.text) {
869
+ slide.addText(element.text, {
870
+ x,
871
+ y,
872
+ w,
873
+ h,
874
+ align: "center",
875
+ valign: "middle",
876
+ color: element.textColor?.replace("#", "") || "FFFFFF"
877
+ });
878
+ }
879
+ break;
880
+ case "image":
881
+ slide.addText(`[Image: ${element.path}]`, {
882
+ x,
883
+ y,
884
+ w,
885
+ h,
886
+ align: "center",
887
+ valign: "middle",
888
+ italic: true,
889
+ color: "666666",
890
+ fill: { color: "E0E0E0" }
891
+ });
892
+ break;
893
+ case "chart":
894
+ slide.addText(`[${element.chartType} Chart: ${element.title || "Data"}]`, {
895
+ x,
896
+ y,
897
+ w,
898
+ h,
899
+ align: "center",
900
+ valign: "middle",
901
+ italic: true,
902
+ color: "666666",
903
+ fill: { color: "F5F5F5" }
904
+ });
905
+ break;
906
+ }
907
+ }
908
+ async function generateRawPptx(slides, filePath, options) {
909
+ const finalOptions = { ...DEFAULT_OPTIONS, ...options };
910
+ const theme = { ...DEFAULT_THEME, ...finalOptions.theme };
911
+ try {
912
+ const archiver = await import("./archiver-AVNBYCKQ.js");
913
+ const fs = await import("fs");
914
+ const output = fs.createWriteStream(filePath);
915
+ const archive = archiver.default("zip", { zlib: { level: 9 } });
916
+ return new Promise((resolve) => {
917
+ output.on("close", () => {
918
+ resolve({ success: true, filePath });
919
+ });
920
+ archive.on("error", (err) => {
921
+ resolve({ success: false, error: err.message });
922
+ });
923
+ archive.pipe(output);
924
+ archive.append(generateContentTypesXml(slides.length), { name: "[Content_Types].xml" });
925
+ archive.append(generateRootRelsXml(), { name: "_rels/.rels" });
926
+ archive.append(generatePresentationXml(slides.length, finalOptions), { name: "ppt/presentation.xml" });
927
+ archive.append(generatePresentationRelsXml(slides.length), { name: "ppt/_rels/presentation.xml.rels" });
928
+ archive.append(generateThemeXml(theme), { name: "ppt/theme/theme1.xml" });
929
+ archive.append(generateSlideMasterXml(theme, finalOptions.layout || "LAYOUT_16x9"), { name: "ppt/slideMasters/slideMaster1.xml" });
930
+ archive.append(generateSlideMasterRelsXml(), { name: "ppt/slideMasters/_rels/slideMaster1.xml.rels" });
931
+ archive.append(generateSlideLayoutXml("title"), { name: "ppt/slideLayouts/slideLayout1.xml" });
932
+ archive.append(generateSlideLayoutXml("content"), { name: "ppt/slideLayouts/slideLayout2.xml" });
933
+ archive.append(generateSlideLayoutRelsXml(), { name: "ppt/slideLayouts/_rels/slideLayout1.xml.rels" });
934
+ archive.append(generateSlideLayoutRelsXml(), { name: "ppt/slideLayouts/_rels/slideLayout2.xml.rels" });
935
+ for (let i = 0; i < slides.length; i++) {
936
+ archive.append(generateSlideXml(slides[i], i + 1, finalOptions), { name: `ppt/slides/slide${i + 1}.xml` });
937
+ archive.append(generateSlideRelsXml(i + 1), { name: `ppt/slides/_rels/slide${i + 1}.xml.rels` });
938
+ }
939
+ archive.append(generateCorePropsXml(finalOptions), { name: "docProps/core.xml" });
940
+ archive.append(generateAppPropsXml(finalOptions, slides.length), { name: "docProps/app.xml" });
941
+ archive.finalize();
942
+ });
943
+ } catch {
944
+ const txtPath = filePath.replace(".pptx", ".txt");
945
+ let content = `Presentation: ${options.title || "Untitled"}
946
+ ${"=".repeat(50)}
947
+
948
+ `;
949
+ for (let i = 0; i < slides.length; i++) {
950
+ const slide = slides[i];
951
+ content += `--- Slide ${i + 1} ---
952
+ `;
953
+ if (slide.title) content += `Title: ${slide.title}
954
+ `;
955
+ if (slide.subtitle) content += `Subtitle: ${slide.subtitle}
956
+ `;
957
+ if (slide.content) {
958
+ content += "Content:\n";
959
+ for (const element of slide.content) {
960
+ if ("text" in element && element.type === "text") content += ` ${element.text}
961
+ `;
962
+ if ("items" in element) content += element.items.map((item) => ` - ${item}`).join("\n") + "\n";
963
+ }
964
+ }
965
+ content += "\n";
966
+ }
967
+ await writeFile(txtPath, content, "utf-8");
968
+ return { success: true, filePath: txtPath };
969
+ }
970
+ }
971
+ async function quickPresentation(title, outline, filename, options) {
972
+ const slides = [
973
+ {
974
+ layout: "title",
975
+ title,
976
+ subtitle: options?.author ? `By ${options.author}` : void 0
977
+ }
978
+ ];
979
+ for (const section of outline) {
980
+ slides.push({
981
+ layout: "title-content",
982
+ title: section.title,
983
+ content: section.bullets ? [{ type: "bullet-list", items: section.bullets }] : void 0
984
+ });
985
+ }
986
+ return generatePresentation(slides, filename, options);
987
+ }
988
+ async function generatePPTX(slides, filename, options) {
989
+ return generatePresentation(slides, filename, options);
990
+ }
991
+ var presentations_default = {
992
+ generatePresentation,
993
+ generatePPTX,
994
+ quickPresentation
995
+ };
996
+ export {
997
+ presentations_default as default,
998
+ generatePPTX,
999
+ generatePresentation,
1000
+ quickPresentation
1001
+ };
1002
+ //# sourceMappingURL=presentations-DSV5IHG5.js.map