@jbctechsolutions/mcp-office365 2.5.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 (339) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +667 -0
  3. package/dist/applescript/account-repository.d.ts +30 -0
  4. package/dist/applescript/account-repository.d.ts.map +1 -0
  5. package/dist/applescript/account-repository.js +38 -0
  6. package/dist/applescript/account-repository.js.map +1 -0
  7. package/dist/applescript/account-scripts.d.ts +21 -0
  8. package/dist/applescript/account-scripts.d.ts.map +1 -0
  9. package/dist/applescript/account-scripts.js +180 -0
  10. package/dist/applescript/account-scripts.js.map +1 -0
  11. package/dist/applescript/calendar-manager.d.ts +44 -0
  12. package/dist/applescript/calendar-manager.d.ts.map +1 -0
  13. package/dist/applescript/calendar-manager.js +92 -0
  14. package/dist/applescript/calendar-manager.js.map +1 -0
  15. package/dist/applescript/calendar-writer.d.ts +36 -0
  16. package/dist/applescript/calendar-writer.d.ts.map +1 -0
  17. package/dist/applescript/calendar-writer.js +94 -0
  18. package/dist/applescript/calendar-writer.js.map +1 -0
  19. package/dist/applescript/content-readers.d.ts +114 -0
  20. package/dist/applescript/content-readers.d.ts.map +1 -0
  21. package/dist/applescript/content-readers.js +328 -0
  22. package/dist/applescript/content-readers.js.map +1 -0
  23. package/dist/applescript/executor.d.ts +60 -0
  24. package/dist/applescript/executor.d.ts.map +1 -0
  25. package/dist/applescript/executor.js +173 -0
  26. package/dist/applescript/executor.js.map +1 -0
  27. package/dist/applescript/index.d.ts +20 -0
  28. package/dist/applescript/index.d.ts.map +1 -0
  29. package/dist/applescript/index.js +29 -0
  30. package/dist/applescript/index.js.map +1 -0
  31. package/dist/applescript/mail-sender.d.ts +38 -0
  32. package/dist/applescript/mail-sender.d.ts.map +1 -0
  33. package/dist/applescript/mail-sender.js +67 -0
  34. package/dist/applescript/mail-sender.js.map +1 -0
  35. package/dist/applescript/parser.d.ts +235 -0
  36. package/dist/applescript/parser.d.ts.map +1 -0
  37. package/dist/applescript/parser.js +496 -0
  38. package/dist/applescript/parser.js.map +1 -0
  39. package/dist/applescript/repository.d.ts +64 -0
  40. package/dist/applescript/repository.d.ts.map +1 -0
  41. package/dist/applescript/repository.js +444 -0
  42. package/dist/applescript/repository.js.map +1 -0
  43. package/dist/applescript/scripts.d.ts +265 -0
  44. package/dist/applescript/scripts.d.ts.map +1 -0
  45. package/dist/applescript/scripts.js +1483 -0
  46. package/dist/applescript/scripts.js.map +1 -0
  47. package/dist/approval/hash.d.ts +87 -0
  48. package/dist/approval/hash.d.ts.map +1 -0
  49. package/dist/approval/hash.js +102 -0
  50. package/dist/approval/hash.js.map +1 -0
  51. package/dist/approval/index.d.ts +13 -0
  52. package/dist/approval/index.d.ts.map +1 -0
  53. package/dist/approval/index.js +7 -0
  54. package/dist/approval/index.js.map +1 -0
  55. package/dist/approval/token-manager.d.ts +51 -0
  56. package/dist/approval/token-manager.d.ts.map +1 -0
  57. package/dist/approval/token-manager.js +111 -0
  58. package/dist/approval/token-manager.js.map +1 -0
  59. package/dist/approval/types.d.ts +44 -0
  60. package/dist/approval/types.d.ts.map +1 -0
  61. package/dist/approval/types.js +6 -0
  62. package/dist/approval/types.js.map +1 -0
  63. package/dist/cli.d.ts +30 -0
  64. package/dist/cli.d.ts.map +1 -0
  65. package/dist/cli.js +143 -0
  66. package/dist/cli.js.map +1 -0
  67. package/dist/config.d.ts +27 -0
  68. package/dist/config.d.ts.map +1 -0
  69. package/dist/config.js +42 -0
  70. package/dist/config.js.map +1 -0
  71. package/dist/database/connection.d.ts +77 -0
  72. package/dist/database/connection.d.ts.map +1 -0
  73. package/dist/database/connection.js +130 -0
  74. package/dist/database/connection.js.map +1 -0
  75. package/dist/database/index.d.ts +11 -0
  76. package/dist/database/index.d.ts.map +1 -0
  77. package/dist/database/index.js +11 -0
  78. package/dist/database/index.js.map +1 -0
  79. package/dist/database/queries.d.ts +93 -0
  80. package/dist/database/queries.d.ts.map +1 -0
  81. package/dist/database/queries.js +430 -0
  82. package/dist/database/queries.js.map +1 -0
  83. package/dist/database/repository.d.ts +198 -0
  84. package/dist/database/repository.d.ts.map +1 -0
  85. package/dist/database/repository.js +199 -0
  86. package/dist/database/repository.js.map +1 -0
  87. package/dist/graph/attachments.d.ts +72 -0
  88. package/dist/graph/attachments.d.ts.map +1 -0
  89. package/dist/graph/attachments.js +207 -0
  90. package/dist/graph/attachments.js.map +1 -0
  91. package/dist/graph/auth/config.d.ts +34 -0
  92. package/dist/graph/auth/config.d.ts.map +1 -0
  93. package/dist/graph/auth/config.js +78 -0
  94. package/dist/graph/auth/config.js.map +1 -0
  95. package/dist/graph/auth/device-code-flow.d.ts +55 -0
  96. package/dist/graph/auth/device-code-flow.d.ts.map +1 -0
  97. package/dist/graph/auth/device-code-flow.js +180 -0
  98. package/dist/graph/auth/device-code-flow.js.map +1 -0
  99. package/dist/graph/auth/index.d.ts +13 -0
  100. package/dist/graph/auth/index.d.ts.map +1 -0
  101. package/dist/graph/auth/index.js +13 -0
  102. package/dist/graph/auth/index.js.map +1 -0
  103. package/dist/graph/auth/token-cache.d.ts +41 -0
  104. package/dist/graph/auth/token-cache.d.ts.map +1 -0
  105. package/dist/graph/auth/token-cache.js +105 -0
  106. package/dist/graph/auth/token-cache.js.map +1 -0
  107. package/dist/graph/client/batch.d.ts +38 -0
  108. package/dist/graph/client/batch.d.ts.map +1 -0
  109. package/dist/graph/client/batch.js +33 -0
  110. package/dist/graph/client/batch.js.map +1 -0
  111. package/dist/graph/client/cache.d.ts +64 -0
  112. package/dist/graph/client/cache.d.ts.map +1 -0
  113. package/dist/graph/client/cache.js +108 -0
  114. package/dist/graph/client/cache.js.map +1 -0
  115. package/dist/graph/client/graph-client.d.ts +630 -0
  116. package/dist/graph/client/graph-client.d.ts.map +1 -0
  117. package/dist/graph/client/graph-client.js +1771 -0
  118. package/dist/graph/client/graph-client.js.map +1 -0
  119. package/dist/graph/client/index.d.ts +12 -0
  120. package/dist/graph/client/index.d.ts.map +1 -0
  121. package/dist/graph/client/index.js +12 -0
  122. package/dist/graph/client/index.js.map +1 -0
  123. package/dist/graph/content-readers.d.ts +106 -0
  124. package/dist/graph/content-readers.d.ts.map +1 -0
  125. package/dist/graph/content-readers.js +321 -0
  126. package/dist/graph/content-readers.js.map +1 -0
  127. package/dist/graph/index.d.ts +18 -0
  128. package/dist/graph/index.d.ts.map +1 -0
  129. package/dist/graph/index.js +23 -0
  130. package/dist/graph/index.js.map +1 -0
  131. package/dist/graph/mailbox-adapter.d.ts +30 -0
  132. package/dist/graph/mailbox-adapter.d.ts.map +1 -0
  133. package/dist/graph/mailbox-adapter.js +59 -0
  134. package/dist/graph/mailbox-adapter.js.map +1 -0
  135. package/dist/graph/mappers/contact-mapper.d.ts +14 -0
  136. package/dist/graph/mappers/contact-mapper.d.ts.map +1 -0
  137. package/dist/graph/mappers/contact-mapper.js +20 -0
  138. package/dist/graph/mappers/contact-mapper.js.map +1 -0
  139. package/dist/graph/mappers/email-mapper.d.ts +14 -0
  140. package/dist/graph/mappers/email-mapper.d.ts.map +1 -0
  141. package/dist/graph/mappers/email-mapper.js +44 -0
  142. package/dist/graph/mappers/email-mapper.js.map +1 -0
  143. package/dist/graph/mappers/event-mapper.d.ts +14 -0
  144. package/dist/graph/mappers/event-mapper.d.ts.map +1 -0
  145. package/dist/graph/mappers/event-mapper.js +31 -0
  146. package/dist/graph/mappers/event-mapper.js.map +1 -0
  147. package/dist/graph/mappers/folder-mapper.d.ts +22 -0
  148. package/dist/graph/mappers/folder-mapper.d.ts.map +1 -0
  149. package/dist/graph/mappers/folder-mapper.js +51 -0
  150. package/dist/graph/mappers/folder-mapper.js.map +1 -0
  151. package/dist/graph/mappers/index.d.ts +16 -0
  152. package/dist/graph/mappers/index.d.ts.map +1 -0
  153. package/dist/graph/mappers/index.js +16 -0
  154. package/dist/graph/mappers/index.js.map +1 -0
  155. package/dist/graph/mappers/task-mapper.d.ts +20 -0
  156. package/dist/graph/mappers/task-mapper.d.ts.map +1 -0
  157. package/dist/graph/mappers/task-mapper.js +27 -0
  158. package/dist/graph/mappers/task-mapper.js.map +1 -0
  159. package/dist/graph/mappers/utils.d.ts +97 -0
  160. package/dist/graph/mappers/utils.d.ts.map +1 -0
  161. package/dist/graph/mappers/utils.js +186 -0
  162. package/dist/graph/mappers/utils.js.map +1 -0
  163. package/dist/graph/repository.d.ts +1104 -0
  164. package/dist/graph/repository.d.ts.map +1 -0
  165. package/dist/graph/repository.js +2999 -0
  166. package/dist/graph/repository.js.map +1 -0
  167. package/dist/index.d.ts +21 -0
  168. package/dist/index.d.ts.map +1 -0
  169. package/dist/index.js +6052 -0
  170. package/dist/index.js.map +1 -0
  171. package/dist/parsers/html-stripper.d.ts +41 -0
  172. package/dist/parsers/html-stripper.d.ts.map +1 -0
  173. package/dist/parsers/html-stripper.js +179 -0
  174. package/dist/parsers/html-stripper.js.map +1 -0
  175. package/dist/parsers/index.d.ts +12 -0
  176. package/dist/parsers/index.d.ts.map +1 -0
  177. package/dist/parsers/index.js +12 -0
  178. package/dist/parsers/index.js.map +1 -0
  179. package/dist/parsers/olk15.d.ts +87 -0
  180. package/dist/parsers/olk15.d.ts.map +1 -0
  181. package/dist/parsers/olk15.js +368 -0
  182. package/dist/parsers/olk15.js.map +1 -0
  183. package/dist/signature.d.ts +22 -0
  184. package/dist/signature.d.ts.map +1 -0
  185. package/dist/signature.js +89 -0
  186. package/dist/signature.js.map +1 -0
  187. package/dist/tools/calendar-permissions.d.ts +79 -0
  188. package/dist/tools/calendar-permissions.d.ts.map +1 -0
  189. package/dist/tools/calendar-permissions.js +121 -0
  190. package/dist/tools/calendar-permissions.js.map +1 -0
  191. package/dist/tools/calendar.d.ts +208 -0
  192. package/dist/tools/calendar.d.ts.map +1 -0
  193. package/dist/tools/calendar.js +247 -0
  194. package/dist/tools/calendar.js.map +1 -0
  195. package/dist/tools/categories.d.ts +94 -0
  196. package/dist/tools/categories.d.ts.map +1 -0
  197. package/dist/tools/categories.js +117 -0
  198. package/dist/tools/categories.js.map +1 -0
  199. package/dist/tools/checklist-items.d.ts +89 -0
  200. package/dist/tools/checklist-items.d.ts.map +1 -0
  201. package/dist/tools/checklist-items.js +140 -0
  202. package/dist/tools/checklist-items.js.map +1 -0
  203. package/dist/tools/contacts.d.ts +94 -0
  204. package/dist/tools/contacts.d.ts.map +1 -0
  205. package/dist/tools/contacts.js +134 -0
  206. package/dist/tools/contacts.js.map +1 -0
  207. package/dist/tools/excel.d.ts +96 -0
  208. package/dist/tools/excel.d.ts.map +1 -0
  209. package/dist/tools/excel.js +165 -0
  210. package/dist/tools/excel.js.map +1 -0
  211. package/dist/tools/focused-overrides.d.ts +70 -0
  212. package/dist/tools/focused-overrides.d.ts.map +1 -0
  213. package/dist/tools/focused-overrides.js +117 -0
  214. package/dist/tools/focused-overrides.js.map +1 -0
  215. package/dist/tools/index.d.ts +22 -0
  216. package/dist/tools/index.d.ts.map +1 -0
  217. package/dist/tools/index.js +34 -0
  218. package/dist/tools/index.js.map +1 -0
  219. package/dist/tools/linked-resources.d.ts +74 -0
  220. package/dist/tools/linked-resources.d.ts.map +1 -0
  221. package/dist/tools/linked-resources.js +122 -0
  222. package/dist/tools/linked-resources.js.map +1 -0
  223. package/dist/tools/mail-rules.d.ts +98 -0
  224. package/dist/tools/mail-rules.d.ts.map +1 -0
  225. package/dist/tools/mail-rules.js +169 -0
  226. package/dist/tools/mail-rules.js.map +1 -0
  227. package/dist/tools/mail-send.d.ts +314 -0
  228. package/dist/tools/mail-send.d.ts.map +1 -0
  229. package/dist/tools/mail-send.js +555 -0
  230. package/dist/tools/mail-send.js.map +1 -0
  231. package/dist/tools/mail.d.ts +127 -0
  232. package/dist/tools/mail.d.ts.map +1 -0
  233. package/dist/tools/mail.js +311 -0
  234. package/dist/tools/mail.js.map +1 -0
  235. package/dist/tools/mailbox-organization.d.ts +301 -0
  236. package/dist/tools/mailbox-organization.d.ts.map +1 -0
  237. package/dist/tools/mailbox-organization.js +541 -0
  238. package/dist/tools/mailbox-organization.js.map +1 -0
  239. package/dist/tools/meetings.d.ts +114 -0
  240. package/dist/tools/meetings.d.ts.map +1 -0
  241. package/dist/tools/meetings.js +110 -0
  242. package/dist/tools/meetings.js.map +1 -0
  243. package/dist/tools/notes.d.ts +74 -0
  244. package/dist/tools/notes.d.ts.map +1 -0
  245. package/dist/tools/notes.js +136 -0
  246. package/dist/tools/notes.js.map +1 -0
  247. package/dist/tools/onedrive.d.ts +194 -0
  248. package/dist/tools/onedrive.d.ts.map +1 -0
  249. package/dist/tools/onedrive.js +257 -0
  250. package/dist/tools/onedrive.js.map +1 -0
  251. package/dist/tools/people.d.ts +129 -0
  252. package/dist/tools/people.d.ts.map +1 -0
  253. package/dist/tools/people.js +195 -0
  254. package/dist/tools/people.js.map +1 -0
  255. package/dist/tools/planner-visualization.d.ts +91 -0
  256. package/dist/tools/planner-visualization.d.ts.map +1 -0
  257. package/dist/tools/planner-visualization.js +192 -0
  258. package/dist/tools/planner-visualization.js.map +1 -0
  259. package/dist/tools/planner.d.ts +288 -0
  260. package/dist/tools/planner.d.ts.map +1 -0
  261. package/dist/tools/planner.js +368 -0
  262. package/dist/tools/planner.js.map +1 -0
  263. package/dist/tools/scheduling.d.ts +49 -0
  264. package/dist/tools/scheduling.d.ts.map +1 -0
  265. package/dist/tools/scheduling.js +115 -0
  266. package/dist/tools/scheduling.js.map +1 -0
  267. package/dist/tools/sharepoint.d.ts +115 -0
  268. package/dist/tools/sharepoint.d.ts.map +1 -0
  269. package/dist/tools/sharepoint.js +99 -0
  270. package/dist/tools/sharepoint.js.map +1 -0
  271. package/dist/tools/task-attachments.d.ts +74 -0
  272. package/dist/tools/task-attachments.d.ts.map +1 -0
  273. package/dist/tools/task-attachments.js +122 -0
  274. package/dist/tools/task-attachments.js.map +1 -0
  275. package/dist/tools/tasks.d.ts +74 -0
  276. package/dist/tools/tasks.d.ts.map +1 -0
  277. package/dist/tools/tasks.js +126 -0
  278. package/dist/tools/tasks.js.map +1 -0
  279. package/dist/tools/teams.d.ts +389 -0
  280. package/dist/tools/teams.d.ts.map +1 -0
  281. package/dist/tools/teams.js +546 -0
  282. package/dist/tools/teams.js.map +1 -0
  283. package/dist/types/calendar.d.ts +60 -0
  284. package/dist/types/calendar.d.ts.map +1 -0
  285. package/dist/types/calendar.js +15 -0
  286. package/dist/types/calendar.js.map +1 -0
  287. package/dist/types/contacts.d.ts +96 -0
  288. package/dist/types/contacts.d.ts.map +1 -0
  289. package/dist/types/contacts.js +41 -0
  290. package/dist/types/contacts.js.map +1 -0
  291. package/dist/types/index.d.ts +15 -0
  292. package/dist/types/index.d.ts.map +1 -0
  293. package/dist/types/index.js +16 -0
  294. package/dist/types/index.js.map +1 -0
  295. package/dist/types/mail.d.ts +108 -0
  296. package/dist/types/mail.d.ts.map +1 -0
  297. package/dist/types/mail.js +40 -0
  298. package/dist/types/mail.js.map +1 -0
  299. package/dist/types/notes.d.ts +26 -0
  300. package/dist/types/notes.d.ts.map +1 -0
  301. package/dist/types/notes.js +6 -0
  302. package/dist/types/notes.js.map +1 -0
  303. package/dist/types/tasks.d.ts +31 -0
  304. package/dist/types/tasks.d.ts.map +1 -0
  305. package/dist/types/tasks.js +6 -0
  306. package/dist/types/tasks.js.map +1 -0
  307. package/dist/utils/dates.d.ts +66 -0
  308. package/dist/utils/dates.d.ts.map +1 -0
  309. package/dist/utils/dates.js +94 -0
  310. package/dist/utils/dates.js.map +1 -0
  311. package/dist/utils/errors.d.ts +218 -0
  312. package/dist/utils/errors.d.ts.map +1 -0
  313. package/dist/utils/errors.js +306 -0
  314. package/dist/utils/errors.js.map +1 -0
  315. package/dist/utils/index.d.ts +10 -0
  316. package/dist/utils/index.d.ts.map +1 -0
  317. package/dist/utils/index.js +10 -0
  318. package/dist/utils/index.js.map +1 -0
  319. package/dist/visualization/html.d.ts +26 -0
  320. package/dist/visualization/html.d.ts.map +1 -0
  321. package/dist/visualization/html.js +306 -0
  322. package/dist/visualization/html.js.map +1 -0
  323. package/dist/visualization/markdown.d.ts +25 -0
  324. package/dist/visualization/markdown.d.ts.map +1 -0
  325. package/dist/visualization/markdown.js +186 -0
  326. package/dist/visualization/markdown.js.map +1 -0
  327. package/dist/visualization/mermaid.d.ts +25 -0
  328. package/dist/visualization/mermaid.d.ts.map +1 -0
  329. package/dist/visualization/mermaid.js +158 -0
  330. package/dist/visualization/mermaid.js.map +1 -0
  331. package/dist/visualization/svg.d.ts +25 -0
  332. package/dist/visualization/svg.d.ts.map +1 -0
  333. package/dist/visualization/svg.js +282 -0
  334. package/dist/visualization/svg.js.map +1 -0
  335. package/dist/visualization/types.d.ts +43 -0
  336. package/dist/visualization/types.d.ts.map +1 -0
  337. package/dist/visualization/types.js +34 -0
  338. package/dist/visualization/types.js.map +1 -0
  339. package/package.json +88 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Copyright (c) 2026 JBC Tech Solutions, LLC
3
+ * Licensed under the MIT License. See LICENSE file in the project root.
4
+ */
5
+ /**
6
+ * Simple HTML to plain text converter.
7
+ *
8
+ * Uses regex-based approach to avoid heavy dependencies.
9
+ * Handles common HTML patterns found in emails.
10
+ */
11
+ /**
12
+ * Named HTML entities and their text equivalents.
13
+ */
14
+ const HTML_ENTITIES = {
15
+ ' ': ' ',
16
+ '&': '&',
17
+ '&lt;': '<',
18
+ '&gt;': '>',
19
+ '&quot;': '"',
20
+ '&apos;': "'",
21
+ '&#39;': "'",
22
+ '&copy;': '\u00A9',
23
+ '&reg;': '\u00AE',
24
+ '&trade;': '\u2122',
25
+ '&mdash;': '\u2014',
26
+ '&ndash;': '\u2013',
27
+ '&hellip;': '\u2026',
28
+ '&lsquo;': '\u2018',
29
+ '&rsquo;': '\u2019',
30
+ '&ldquo;': '\u201C',
31
+ '&rdquo;': '\u201D',
32
+ '&bull;': '\u2022',
33
+ '&middot;': '\u00B7',
34
+ '&euro;': '\u20AC',
35
+ '&pound;': '\u00A3',
36
+ '&yen;': '\u00A5',
37
+ '&cent;': '\u00A2',
38
+ };
39
+ /**
40
+ * Tags that should add a newline when stripped.
41
+ */
42
+ const BLOCK_TAGS = new Set([
43
+ 'p',
44
+ 'div',
45
+ 'br',
46
+ 'hr',
47
+ 'h1',
48
+ 'h2',
49
+ 'h3',
50
+ 'h4',
51
+ 'h5',
52
+ 'h6',
53
+ 'li',
54
+ 'tr',
55
+ 'blockquote',
56
+ 'pre',
57
+ 'article',
58
+ 'section',
59
+ 'header',
60
+ 'footer',
61
+ 'nav',
62
+ 'aside',
63
+ 'table',
64
+ 'thead',
65
+ 'tbody',
66
+ 'tfoot',
67
+ ]);
68
+ /**
69
+ * Tags whose content should be completely removed.
70
+ */
71
+ const INVISIBLE_TAGS = new Set(['script', 'style', 'head', 'meta', 'link', 'noscript']);
72
+ /**
73
+ * Strips HTML tags and converts to plain text.
74
+ *
75
+ * @param html - The HTML string to convert
76
+ * @param options - Optional configuration
77
+ * @returns Plain text string
78
+ */
79
+ export function stripHtml(html, options = {}) {
80
+ if (html == null || html === '') {
81
+ return '';
82
+ }
83
+ const { preserveWhitespace = false, maxLength = 0 } = options;
84
+ let text = html;
85
+ // Remove invisible tag content (script, style, etc.)
86
+ for (const tag of INVISIBLE_TAGS) {
87
+ const regex = new RegExp(`<${tag}[^>]*>[\\s\\S]*?</${tag}>`, 'gi');
88
+ text = text.replace(regex, '');
89
+ }
90
+ // Remove HTML comments
91
+ text = text.replace(/<!--[\s\S]*?-->/g, '');
92
+ // Remove CDATA sections
93
+ text = text.replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, '');
94
+ // Handle list items with bullets (before block element processing)
95
+ text = text.replace(/<li[^>]*>/gi, '\n\u2022 ');
96
+ text = text.replace(/<\/li>/gi, '');
97
+ // Add newlines for block elements (excluding li which is handled above)
98
+ for (const tag of BLOCK_TAGS) {
99
+ if (tag === 'li')
100
+ continue;
101
+ // Opening tags
102
+ text = text.replace(new RegExp(`<${tag}[^>]*>`, 'gi'), '\n');
103
+ // Self-closing tags (like <br />)
104
+ text = text.replace(new RegExp(`<${tag}[^>]*/>`, 'gi'), '\n');
105
+ // Closing tags
106
+ text = text.replace(new RegExp(`</${tag}>`, 'gi'), '\n');
107
+ }
108
+ // Remove all remaining HTML tags
109
+ text = text.replace(/<[^>]+>/g, '');
110
+ // Decode numeric HTML entities
111
+ text = text.replace(/&#(\d+);/g, (_, code) => {
112
+ const num = parseInt(code, 10);
113
+ return String.fromCharCode(num);
114
+ });
115
+ // Decode hex HTML entities
116
+ text = text.replace(/&#x([a-fA-F0-9]+);/g, (_, code) => {
117
+ const num = parseInt(code, 16);
118
+ return String.fromCharCode(num);
119
+ });
120
+ // Decode named HTML entities
121
+ for (const [entity, replacement] of Object.entries(HTML_ENTITIES)) {
122
+ text = text.split(entity).join(replacement);
123
+ }
124
+ if (!preserveWhitespace) {
125
+ // Normalize whitespace
126
+ text = text
127
+ // Replace tabs with spaces
128
+ .replace(/\t/g, ' ')
129
+ // Replace multiple spaces with single space
130
+ .replace(/ +/g, ' ')
131
+ // Replace multiple newlines with double newline (preserve paragraphs)
132
+ .replace(/\n\s*\n/g, '\n\n')
133
+ // Remove leading/trailing whitespace from lines
134
+ .replace(/^[ \t]+/gm, '')
135
+ .replace(/[ \t]+$/gm, '')
136
+ // Trim overall
137
+ .trim();
138
+ }
139
+ // Apply max length if specified
140
+ if (maxLength > 0 && text.length > maxLength) {
141
+ text = text.substring(0, maxLength - 3) + '...';
142
+ }
143
+ return text;
144
+ }
145
+ /**
146
+ * Checks if a string appears to contain HTML.
147
+ *
148
+ * @param text - The string to check
149
+ * @returns True if the string appears to contain HTML tags
150
+ */
151
+ export function containsHtml(text) {
152
+ if (text == null || text === '') {
153
+ return false;
154
+ }
155
+ // Check for common HTML patterns
156
+ return /<[a-zA-Z][^>]*>/.test(text);
157
+ }
158
+ /**
159
+ * Extracts plain text from an email body, detecting HTML automatically.
160
+ *
161
+ * @param body - The email body (HTML or plain text)
162
+ * @param options - Optional configuration
163
+ * @returns Plain text string
164
+ */
165
+ export function extractPlainText(body, options = {}) {
166
+ if (body == null || body === '') {
167
+ return '';
168
+ }
169
+ if (containsHtml(body)) {
170
+ return stripHtml(body, options);
171
+ }
172
+ // Already plain text, just apply max length if needed
173
+ const { maxLength = 0 } = options;
174
+ if (maxLength > 0 && body.length > maxLength) {
175
+ return body.substring(0, maxLength - 3) + '...';
176
+ }
177
+ return body;
178
+ }
179
+ //# sourceMappingURL=html-stripper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-stripper.js","sourceRoot":"","sources":["../../src/parsers/html-stripper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) 2026 JBC Tech Solutions, LLC
3
+ * Licensed under the MIT License. See LICENSE file in the project root.
4
+ */
5
+ /**
6
+ * Parsers for Outlook content.
7
+ *
8
+ * Re-exports all parsers for convenient importing.
9
+ */
10
+ export { stripHtml, containsHtml, extractPlainText, type StripHtmlOptions, } from './html-stripper.js';
11
+ export { parseOlk15File, getDefaultDataPath, Olk15EmailContentReader, Olk15EventContentReader, Olk15ContactContentReader, Olk15TaskContentReader, Olk15NoteContentReader, createContentReaders, createDefaultContentReaders, type Olk15ParseResult, type ContentReaders, } from './olk15.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AAEH,OAAO,EACL,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,2BAA2B,EAC3B,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) 2026 JBC Tech Solutions, LLC
3
+ * Licensed under the MIT License. See LICENSE file in the project root.
4
+ */
5
+ /**
6
+ * Parsers for Outlook content.
7
+ *
8
+ * Re-exports all parsers for convenient importing.
9
+ */
10
+ export { stripHtml, containsHtml, extractPlainText, } from './html-stripper.js';
11
+ export { parseOlk15File, getDefaultDataPath, Olk15EmailContentReader, Olk15EventContentReader, Olk15ContactContentReader, Olk15TaskContentReader, Olk15NoteContentReader, createContentReaders, createDefaultContentReaders, } from './olk15.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AAEH,OAAO,EACL,SAAS,EACT,YAAY,EACZ,gBAAgB,GAEjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,2BAA2B,GAG5B,MAAM,YAAY,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Copyright (c) 2026 JBC Tech Solutions, LLC
3
+ * Licensed under the MIT License. See LICENSE file in the project root.
4
+ */
5
+ import type { IContentReader } from '../tools/mail.js';
6
+ import type { IEventContentReader, EventDetails } from '../tools/calendar.js';
7
+ import type { IContactContentReader, ContactDetails } from '../tools/contacts.js';
8
+ import type { ITaskContentReader, TaskDetails } from '../tools/tasks.js';
9
+ import type { INoteContentReader, NoteDetails } from '../tools/notes.js';
10
+ /**
11
+ * Default profile data directory path.
12
+ */
13
+ export declare function getDefaultDataPath(profileName?: string): string;
14
+ /**
15
+ * Result of parsing an OLK15 file.
16
+ */
17
+ export interface Olk15ParseResult {
18
+ readonly success: boolean;
19
+ readonly text: string | null;
20
+ readonly html: string | null;
21
+ readonly error?: string;
22
+ }
23
+ /**
24
+ * Parses an OLK15 file and extracts text content.
25
+ */
26
+ export declare function parseOlk15File(filePath: string): Olk15ParseResult;
27
+ /**
28
+ * OLK15 content reader for email bodies.
29
+ */
30
+ export declare class Olk15EmailContentReader implements IContentReader {
31
+ private readonly dataPath;
32
+ constructor(dataPath: string);
33
+ readEmailBody(dataFilePath: string | null): string | null;
34
+ }
35
+ /**
36
+ * OLK15 content reader for calendar events.
37
+ */
38
+ export declare class Olk15EventContentReader implements IEventContentReader {
39
+ private readonly dataPath;
40
+ constructor(dataPath: string);
41
+ readEventDetails(dataFilePath: string | null): EventDetails | null;
42
+ private extractTitle;
43
+ private extractField;
44
+ }
45
+ /**
46
+ * OLK15 content reader for contacts.
47
+ */
48
+ export declare class Olk15ContactContentReader implements IContactContentReader {
49
+ private readonly dataPath;
50
+ constructor(dataPath: string);
51
+ readContactDetails(dataFilePath: string | null): ContactDetails | null;
52
+ }
53
+ /**
54
+ * OLK15 content reader for tasks.
55
+ */
56
+ export declare class Olk15TaskContentReader implements ITaskContentReader {
57
+ private readonly dataPath;
58
+ constructor(dataPath: string);
59
+ readTaskDetails(dataFilePath: string | null): TaskDetails | null;
60
+ }
61
+ /**
62
+ * OLK15 content reader for notes.
63
+ */
64
+ export declare class Olk15NoteContentReader implements INoteContentReader {
65
+ private readonly dataPath;
66
+ constructor(dataPath: string);
67
+ readNoteDetails(dataFilePath: string | null): NoteDetails | null;
68
+ }
69
+ /**
70
+ * Creates all content readers for a given data path.
71
+ */
72
+ export interface ContentReaders {
73
+ readonly email: IContentReader;
74
+ readonly event: IEventContentReader;
75
+ readonly contact: IContactContentReader;
76
+ readonly task: ITaskContentReader;
77
+ readonly note: INoteContentReader;
78
+ }
79
+ /**
80
+ * Creates content readers for all Outlook data types.
81
+ */
82
+ export declare function createContentReaders(dataPath: string): ContentReaders;
83
+ /**
84
+ * Creates content readers using the default profile path.
85
+ */
86
+ export declare function createDefaultContentReaders(profileName?: string): ContentReaders;
87
+ //# sourceMappingURL=olk15.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"olk15.d.ts","sourceRoot":"","sources":["../../src/parsers/olk15.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAMzE;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,GAAE,MAAuB,GAAG,MAAM,CAQ/E;AAqJD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAiCjE;AAMD;;GAEG;AACH,qBAAa,uBAAwB,YAAW,cAAc;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAE7C,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI;CAc1D;AAED;;GAEG;AACH,qBAAa,uBAAwB,YAAW,mBAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAE7C,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI;IAwBlE,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,YAAY;CAKrB;AAED;;GAEG;AACH,qBAAa,yBAA0B,YAAW,qBAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAE7C,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,GAAG,IAAI;CA4BvE;AAED;;GAEG;AACH,qBAAa,sBAAuB,YAAW,kBAAkB;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAE7C,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI;CAmBjE;AAED;;GAEG;AACH,qBAAa,sBAAuB,YAAW,kBAAkB;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAE7C,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI;CAuBjE;AAMD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;CACnC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAQrE;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,cAAc,CAGhF"}
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Copyright (c) 2026 JBC Tech Solutions, LLC
3
+ * Licensed under the MIT License. See LICENSE file in the project root.
4
+ */
5
+ /**
6
+ * OLK15 binary file parser.
7
+ *
8
+ * Parses Outlook for Mac's proprietary binary content files.
9
+ * These files contain email bodies, event details, contact information, etc.
10
+ *
11
+ * File types:
12
+ * - .olk15MsgSource / .olk15Message - Email content
13
+ * - .olk15Event - Calendar event details
14
+ * - .olk15Contact - Contact information
15
+ * - .olk15Note - Note content
16
+ * - .olk15Task - Task details
17
+ *
18
+ * The format is proprietary and not documented. This parser uses heuristics
19
+ * to extract text content and provides graceful fallbacks when parsing fails.
20
+ */
21
+ import { readFileSync, existsSync } from 'node:fs';
22
+ import { join } from 'node:path';
23
+ // =============================================================================
24
+ // Configuration
25
+ // =============================================================================
26
+ /**
27
+ * Default profile data directory path.
28
+ */
29
+ export function getDefaultDataPath(profileName = 'Main Profile') {
30
+ const home = process.env.HOME ?? '';
31
+ return join(home, 'Library/Group Containers/UBF8T346G9.Office/Outlook/Outlook 15 Profiles', profileName, 'Data');
32
+ }
33
+ // =============================================================================
34
+ // Binary Parsing Utilities
35
+ // =============================================================================
36
+ /**
37
+ * Finds UTF-16LE encoded text in binary data.
38
+ * OLK15 files often store text as UTF-16LE.
39
+ */
40
+ function findUtf16Text(buffer, minLength = 10) {
41
+ const results = [];
42
+ let start = -1;
43
+ let chars = [];
44
+ for (let i = 0; i < buffer.length - 1; i += 2) {
45
+ const char = buffer.readUInt16LE(i);
46
+ // Check if it's a printable character or common whitespace
47
+ if ((char >= 0x20 && char < 0x7f) || char === 0x0a || char === 0x0d || char === 0x09) {
48
+ if (start === -1)
49
+ start = i;
50
+ chars.push(String.fromCharCode(char));
51
+ }
52
+ else if (char === 0) {
53
+ // Null character - end of string
54
+ if (chars.length >= minLength) {
55
+ results.push(chars.join(''));
56
+ }
57
+ chars = [];
58
+ start = -1;
59
+ }
60
+ else {
61
+ // Non-printable, non-null - might be end of text section
62
+ if (chars.length >= minLength) {
63
+ results.push(chars.join(''));
64
+ }
65
+ chars = [];
66
+ start = -1;
67
+ }
68
+ }
69
+ // Don't forget the last string
70
+ if (chars.length >= minLength) {
71
+ results.push(chars.join(''));
72
+ }
73
+ return results;
74
+ }
75
+ /**
76
+ * Finds UTF-8 encoded text in binary data.
77
+ */
78
+ function findUtf8Text(buffer, minLength = 10) {
79
+ const results = [];
80
+ let start = -1;
81
+ let chars = [];
82
+ for (let i = 0; i < buffer.length; i++) {
83
+ const byte = buffer[i];
84
+ if (byte !== undefined) {
85
+ // Check if it's a printable ASCII or common whitespace
86
+ if ((byte >= 0x20 && byte < 0x7f) || byte === 0x0a || byte === 0x0d || byte === 0x09) {
87
+ if (start === -1)
88
+ start = i;
89
+ chars.push(byte);
90
+ }
91
+ else if (byte === 0) {
92
+ // Null terminator
93
+ if (chars.length >= minLength) {
94
+ results.push(Buffer.from(chars).toString('utf8'));
95
+ }
96
+ chars = [];
97
+ start = -1;
98
+ }
99
+ else if (byte >= 0x80) {
100
+ // UTF-8 multi-byte - try to include
101
+ chars.push(byte);
102
+ }
103
+ else {
104
+ // Control character - end of text
105
+ if (chars.length >= minLength) {
106
+ results.push(Buffer.from(chars).toString('utf8'));
107
+ }
108
+ chars = [];
109
+ start = -1;
110
+ }
111
+ }
112
+ }
113
+ if (chars.length >= minLength) {
114
+ results.push(Buffer.from(chars).toString('utf8'));
115
+ }
116
+ return results;
117
+ }
118
+ /**
119
+ * Extracts the longest text block that looks like content.
120
+ */
121
+ function extractPrimaryText(buffer) {
122
+ // Try UTF-16LE first (common in OLK15)
123
+ const utf16Texts = findUtf16Text(buffer, 20);
124
+ // Try UTF-8 as fallback
125
+ const utf8Texts = findUtf8Text(buffer, 20);
126
+ // Combine and find the longest meaningful text
127
+ const allTexts = [...utf16Texts, ...utf8Texts]
128
+ .filter((t) => t.trim().length > 0)
129
+ // eslint-disable-next-line no-control-regex
130
+ .filter((t) => !t.match(/^[\x00-\x1f\x7f-\x9f]+$/)) // Filter control chars
131
+ .sort((a, b) => b.length - a.length);
132
+ return allTexts[0] ?? null;
133
+ }
134
+ /**
135
+ * Checks if text looks like HTML content.
136
+ */
137
+ function looksLikeHtml(text) {
138
+ return /<\/?[a-z][\s\S]*>/i.test(text);
139
+ }
140
+ /**
141
+ * Finds HTML content in buffer.
142
+ */
143
+ function findHtmlContent(buffer) {
144
+ const text = buffer.toString('utf8', 0, Math.min(buffer.length, 1024 * 1024));
145
+ // Look for HTML patterns
146
+ const htmlStart = text.search(/<html[^>]*>/i);
147
+ if (htmlStart >= 0) {
148
+ const htmlEnd = text.indexOf('</html>', htmlStart);
149
+ if (htmlEnd > htmlStart) {
150
+ return text.substring(htmlStart, htmlEnd + 7);
151
+ }
152
+ }
153
+ // Look for body content
154
+ const bodyStart = text.search(/<body[^>]*>/i);
155
+ if (bodyStart >= 0) {
156
+ const bodyEnd = text.indexOf('</body>', bodyStart);
157
+ if (bodyEnd > bodyStart) {
158
+ return text.substring(bodyStart, bodyEnd + 7);
159
+ }
160
+ }
161
+ return null;
162
+ }
163
+ /**
164
+ * Parses an OLK15 file and extracts text content.
165
+ */
166
+ export function parseOlk15File(filePath) {
167
+ try {
168
+ if (!existsSync(filePath)) {
169
+ return { success: false, text: null, html: null, error: 'File not found' };
170
+ }
171
+ const buffer = readFileSync(filePath);
172
+ if (buffer.length === 0) {
173
+ return { success: false, text: null, html: null, error: 'Empty file' };
174
+ }
175
+ // Try to find HTML content first
176
+ const html = findHtmlContent(buffer);
177
+ if (html != null) {
178
+ return { success: true, text: null, html };
179
+ }
180
+ // Extract text content
181
+ const text = extractPrimaryText(buffer);
182
+ if (text != null) {
183
+ // Check if the text is actually HTML
184
+ if (looksLikeHtml(text)) {
185
+ return { success: true, text: null, html: text };
186
+ }
187
+ return { success: true, text, html: null };
188
+ }
189
+ return { success: false, text: null, html: null, error: 'No text content found' };
190
+ }
191
+ catch (error) {
192
+ const message = error instanceof Error ? error.message : 'Unknown error';
193
+ return { success: false, text: null, html: null, error: message };
194
+ }
195
+ }
196
+ // =============================================================================
197
+ // Content Reader Implementations
198
+ // =============================================================================
199
+ /**
200
+ * OLK15 content reader for email bodies.
201
+ */
202
+ export class Olk15EmailContentReader {
203
+ dataPath;
204
+ constructor(dataPath) {
205
+ this.dataPath = dataPath;
206
+ }
207
+ readEmailBody(dataFilePath) {
208
+ if (dataFilePath == null) {
209
+ return null;
210
+ }
211
+ const fullPath = join(this.dataPath, dataFilePath);
212
+ const result = parseOlk15File(fullPath);
213
+ if (result.success) {
214
+ return result.html ?? result.text;
215
+ }
216
+ return null;
217
+ }
218
+ }
219
+ /**
220
+ * OLK15 content reader for calendar events.
221
+ */
222
+ export class Olk15EventContentReader {
223
+ dataPath;
224
+ constructor(dataPath) {
225
+ this.dataPath = dataPath;
226
+ }
227
+ readEventDetails(dataFilePath) {
228
+ if (dataFilePath == null) {
229
+ return null;
230
+ }
231
+ const fullPath = join(this.dataPath, dataFilePath);
232
+ const result = parseOlk15File(fullPath);
233
+ if (!result.success) {
234
+ return null;
235
+ }
236
+ const text = result.text ?? result.html ?? '';
237
+ // Basic extraction - can be improved with format knowledge
238
+ return {
239
+ title: this.extractTitle(text),
240
+ location: this.extractField(text, 'Location'),
241
+ description: text,
242
+ organizer: this.extractField(text, 'Organizer'),
243
+ attendees: [],
244
+ };
245
+ }
246
+ extractTitle(text) {
247
+ // Try to find a subject/title line
248
+ const subjectMatch = text.match(/Subject:\s*(.+?)(?:\r?\n|$)/i);
249
+ if (subjectMatch?.[1] != null && subjectMatch[1].length > 0) {
250
+ return subjectMatch[1].trim();
251
+ }
252
+ // Use first line as title
253
+ const firstLine = text.split(/\r?\n/)[0]?.trim();
254
+ return firstLine != null && firstLine.length > 0 ? firstLine : null;
255
+ }
256
+ extractField(text, fieldName) {
257
+ const regex = new RegExp(`${fieldName}:\\s*(.+?)(?:\\r?\\n|$)`, 'i');
258
+ const match = text.match(regex);
259
+ return match?.[1]?.trim() ?? null;
260
+ }
261
+ }
262
+ /**
263
+ * OLK15 content reader for contacts.
264
+ */
265
+ export class Olk15ContactContentReader {
266
+ dataPath;
267
+ constructor(dataPath) {
268
+ this.dataPath = dataPath;
269
+ }
270
+ readContactDetails(dataFilePath) {
271
+ if (dataFilePath == null) {
272
+ return null;
273
+ }
274
+ const fullPath = join(this.dataPath, dataFilePath);
275
+ const result = parseOlk15File(fullPath);
276
+ if (!result.success) {
277
+ return null;
278
+ }
279
+ // Contact parsing would require understanding the binary format
280
+ // For now, return a basic structure
281
+ return {
282
+ firstName: null,
283
+ lastName: null,
284
+ middleName: null,
285
+ nickname: null,
286
+ company: null,
287
+ jobTitle: null,
288
+ department: null,
289
+ emails: [],
290
+ phones: [],
291
+ addresses: [],
292
+ notes: result.text,
293
+ };
294
+ }
295
+ }
296
+ /**
297
+ * OLK15 content reader for tasks.
298
+ */
299
+ export class Olk15TaskContentReader {
300
+ dataPath;
301
+ constructor(dataPath) {
302
+ this.dataPath = dataPath;
303
+ }
304
+ readTaskDetails(dataFilePath) {
305
+ if (dataFilePath == null) {
306
+ return null;
307
+ }
308
+ const fullPath = join(this.dataPath, dataFilePath);
309
+ const result = parseOlk15File(fullPath);
310
+ if (!result.success) {
311
+ return null;
312
+ }
313
+ return {
314
+ body: result.text ?? result.html,
315
+ completedDate: null,
316
+ reminderDate: null,
317
+ categories: [],
318
+ };
319
+ }
320
+ }
321
+ /**
322
+ * OLK15 content reader for notes.
323
+ */
324
+ export class Olk15NoteContentReader {
325
+ dataPath;
326
+ constructor(dataPath) {
327
+ this.dataPath = dataPath;
328
+ }
329
+ readNoteDetails(dataFilePath) {
330
+ if (dataFilePath == null) {
331
+ return null;
332
+ }
333
+ const fullPath = join(this.dataPath, dataFilePath);
334
+ const result = parseOlk15File(fullPath);
335
+ if (!result.success) {
336
+ return null;
337
+ }
338
+ const body = result.text ?? result.html ?? '';
339
+ const lines = body.split(/\r?\n/).filter((l) => l.trim().length > 0);
340
+ return {
341
+ title: lines[0] ?? null,
342
+ body,
343
+ preview: body.substring(0, 200),
344
+ createdDate: null,
345
+ categories: [],
346
+ };
347
+ }
348
+ }
349
+ /**
350
+ * Creates content readers for all Outlook data types.
351
+ */
352
+ export function createContentReaders(dataPath) {
353
+ return {
354
+ email: new Olk15EmailContentReader(dataPath),
355
+ event: new Olk15EventContentReader(dataPath),
356
+ contact: new Olk15ContactContentReader(dataPath),
357
+ task: new Olk15TaskContentReader(dataPath),
358
+ note: new Olk15NoteContentReader(dataPath),
359
+ };
360
+ }
361
+ /**
362
+ * Creates content readers using the default profile path.
363
+ */
364
+ export function createDefaultContentReaders(profileName) {
365
+ const dataPath = getDefaultDataPath(profileName);
366
+ return createContentReaders(dataPath);
367
+ }
368
+ //# sourceMappingURL=olk15.js.map