@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.
- package/LICENSE +21 -0
- package/README.md +667 -0
- package/dist/applescript/account-repository.d.ts +30 -0
- package/dist/applescript/account-repository.d.ts.map +1 -0
- package/dist/applescript/account-repository.js +38 -0
- package/dist/applescript/account-repository.js.map +1 -0
- package/dist/applescript/account-scripts.d.ts +21 -0
- package/dist/applescript/account-scripts.d.ts.map +1 -0
- package/dist/applescript/account-scripts.js +180 -0
- package/dist/applescript/account-scripts.js.map +1 -0
- package/dist/applescript/calendar-manager.d.ts +44 -0
- package/dist/applescript/calendar-manager.d.ts.map +1 -0
- package/dist/applescript/calendar-manager.js +92 -0
- package/dist/applescript/calendar-manager.js.map +1 -0
- package/dist/applescript/calendar-writer.d.ts +36 -0
- package/dist/applescript/calendar-writer.d.ts.map +1 -0
- package/dist/applescript/calendar-writer.js +94 -0
- package/dist/applescript/calendar-writer.js.map +1 -0
- package/dist/applescript/content-readers.d.ts +114 -0
- package/dist/applescript/content-readers.d.ts.map +1 -0
- package/dist/applescript/content-readers.js +328 -0
- package/dist/applescript/content-readers.js.map +1 -0
- package/dist/applescript/executor.d.ts +60 -0
- package/dist/applescript/executor.d.ts.map +1 -0
- package/dist/applescript/executor.js +173 -0
- package/dist/applescript/executor.js.map +1 -0
- package/dist/applescript/index.d.ts +20 -0
- package/dist/applescript/index.d.ts.map +1 -0
- package/dist/applescript/index.js +29 -0
- package/dist/applescript/index.js.map +1 -0
- package/dist/applescript/mail-sender.d.ts +38 -0
- package/dist/applescript/mail-sender.d.ts.map +1 -0
- package/dist/applescript/mail-sender.js +67 -0
- package/dist/applescript/mail-sender.js.map +1 -0
- package/dist/applescript/parser.d.ts +235 -0
- package/dist/applescript/parser.d.ts.map +1 -0
- package/dist/applescript/parser.js +496 -0
- package/dist/applescript/parser.js.map +1 -0
- package/dist/applescript/repository.d.ts +64 -0
- package/dist/applescript/repository.d.ts.map +1 -0
- package/dist/applescript/repository.js +444 -0
- package/dist/applescript/repository.js.map +1 -0
- package/dist/applescript/scripts.d.ts +265 -0
- package/dist/applescript/scripts.d.ts.map +1 -0
- package/dist/applescript/scripts.js +1483 -0
- package/dist/applescript/scripts.js.map +1 -0
- package/dist/approval/hash.d.ts +87 -0
- package/dist/approval/hash.d.ts.map +1 -0
- package/dist/approval/hash.js +102 -0
- package/dist/approval/hash.js.map +1 -0
- package/dist/approval/index.d.ts +13 -0
- package/dist/approval/index.d.ts.map +1 -0
- package/dist/approval/index.js +7 -0
- package/dist/approval/index.js.map +1 -0
- package/dist/approval/token-manager.d.ts +51 -0
- package/dist/approval/token-manager.d.ts.map +1 -0
- package/dist/approval/token-manager.js +111 -0
- package/dist/approval/token-manager.js.map +1 -0
- package/dist/approval/types.d.ts +44 -0
- package/dist/approval/types.d.ts.map +1 -0
- package/dist/approval/types.js +6 -0
- package/dist/approval/types.js.map +1 -0
- package/dist/cli.d.ts +30 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +143 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +27 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +42 -0
- package/dist/config.js.map +1 -0
- package/dist/database/connection.d.ts +77 -0
- package/dist/database/connection.d.ts.map +1 -0
- package/dist/database/connection.js +130 -0
- package/dist/database/connection.js.map +1 -0
- package/dist/database/index.d.ts +11 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +11 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/queries.d.ts +93 -0
- package/dist/database/queries.d.ts.map +1 -0
- package/dist/database/queries.js +430 -0
- package/dist/database/queries.js.map +1 -0
- package/dist/database/repository.d.ts +198 -0
- package/dist/database/repository.d.ts.map +1 -0
- package/dist/database/repository.js +199 -0
- package/dist/database/repository.js.map +1 -0
- package/dist/graph/attachments.d.ts +72 -0
- package/dist/graph/attachments.d.ts.map +1 -0
- package/dist/graph/attachments.js +207 -0
- package/dist/graph/attachments.js.map +1 -0
- package/dist/graph/auth/config.d.ts +34 -0
- package/dist/graph/auth/config.d.ts.map +1 -0
- package/dist/graph/auth/config.js +78 -0
- package/dist/graph/auth/config.js.map +1 -0
- package/dist/graph/auth/device-code-flow.d.ts +55 -0
- package/dist/graph/auth/device-code-flow.d.ts.map +1 -0
- package/dist/graph/auth/device-code-flow.js +180 -0
- package/dist/graph/auth/device-code-flow.js.map +1 -0
- package/dist/graph/auth/index.d.ts +13 -0
- package/dist/graph/auth/index.d.ts.map +1 -0
- package/dist/graph/auth/index.js +13 -0
- package/dist/graph/auth/index.js.map +1 -0
- package/dist/graph/auth/token-cache.d.ts +41 -0
- package/dist/graph/auth/token-cache.d.ts.map +1 -0
- package/dist/graph/auth/token-cache.js +105 -0
- package/dist/graph/auth/token-cache.js.map +1 -0
- package/dist/graph/client/batch.d.ts +38 -0
- package/dist/graph/client/batch.d.ts.map +1 -0
- package/dist/graph/client/batch.js +33 -0
- package/dist/graph/client/batch.js.map +1 -0
- package/dist/graph/client/cache.d.ts +64 -0
- package/dist/graph/client/cache.d.ts.map +1 -0
- package/dist/graph/client/cache.js +108 -0
- package/dist/graph/client/cache.js.map +1 -0
- package/dist/graph/client/graph-client.d.ts +630 -0
- package/dist/graph/client/graph-client.d.ts.map +1 -0
- package/dist/graph/client/graph-client.js +1771 -0
- package/dist/graph/client/graph-client.js.map +1 -0
- package/dist/graph/client/index.d.ts +12 -0
- package/dist/graph/client/index.d.ts.map +1 -0
- package/dist/graph/client/index.js +12 -0
- package/dist/graph/client/index.js.map +1 -0
- package/dist/graph/content-readers.d.ts +106 -0
- package/dist/graph/content-readers.d.ts.map +1 -0
- package/dist/graph/content-readers.js +321 -0
- package/dist/graph/content-readers.js.map +1 -0
- package/dist/graph/index.d.ts +18 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +23 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/mailbox-adapter.d.ts +30 -0
- package/dist/graph/mailbox-adapter.d.ts.map +1 -0
- package/dist/graph/mailbox-adapter.js +59 -0
- package/dist/graph/mailbox-adapter.js.map +1 -0
- package/dist/graph/mappers/contact-mapper.d.ts +14 -0
- package/dist/graph/mappers/contact-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/contact-mapper.js +20 -0
- package/dist/graph/mappers/contact-mapper.js.map +1 -0
- package/dist/graph/mappers/email-mapper.d.ts +14 -0
- package/dist/graph/mappers/email-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/email-mapper.js +44 -0
- package/dist/graph/mappers/email-mapper.js.map +1 -0
- package/dist/graph/mappers/event-mapper.d.ts +14 -0
- package/dist/graph/mappers/event-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/event-mapper.js +31 -0
- package/dist/graph/mappers/event-mapper.js.map +1 -0
- package/dist/graph/mappers/folder-mapper.d.ts +22 -0
- package/dist/graph/mappers/folder-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/folder-mapper.js +51 -0
- package/dist/graph/mappers/folder-mapper.js.map +1 -0
- package/dist/graph/mappers/index.d.ts +16 -0
- package/dist/graph/mappers/index.d.ts.map +1 -0
- package/dist/graph/mappers/index.js +16 -0
- package/dist/graph/mappers/index.js.map +1 -0
- package/dist/graph/mappers/task-mapper.d.ts +20 -0
- package/dist/graph/mappers/task-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/task-mapper.js +27 -0
- package/dist/graph/mappers/task-mapper.js.map +1 -0
- package/dist/graph/mappers/utils.d.ts +97 -0
- package/dist/graph/mappers/utils.d.ts.map +1 -0
- package/dist/graph/mappers/utils.js +186 -0
- package/dist/graph/mappers/utils.js.map +1 -0
- package/dist/graph/repository.d.ts +1104 -0
- package/dist/graph/repository.d.ts.map +1 -0
- package/dist/graph/repository.js +2999 -0
- package/dist/graph/repository.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6052 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/html-stripper.d.ts +41 -0
- package/dist/parsers/html-stripper.d.ts.map +1 -0
- package/dist/parsers/html-stripper.js +179 -0
- package/dist/parsers/html-stripper.js.map +1 -0
- package/dist/parsers/index.d.ts +12 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +12 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/olk15.d.ts +87 -0
- package/dist/parsers/olk15.d.ts.map +1 -0
- package/dist/parsers/olk15.js +368 -0
- package/dist/parsers/olk15.js.map +1 -0
- package/dist/signature.d.ts +22 -0
- package/dist/signature.d.ts.map +1 -0
- package/dist/signature.js +89 -0
- package/dist/signature.js.map +1 -0
- package/dist/tools/calendar-permissions.d.ts +79 -0
- package/dist/tools/calendar-permissions.d.ts.map +1 -0
- package/dist/tools/calendar-permissions.js +121 -0
- package/dist/tools/calendar-permissions.js.map +1 -0
- package/dist/tools/calendar.d.ts +208 -0
- package/dist/tools/calendar.d.ts.map +1 -0
- package/dist/tools/calendar.js +247 -0
- package/dist/tools/calendar.js.map +1 -0
- package/dist/tools/categories.d.ts +94 -0
- package/dist/tools/categories.d.ts.map +1 -0
- package/dist/tools/categories.js +117 -0
- package/dist/tools/categories.js.map +1 -0
- package/dist/tools/checklist-items.d.ts +89 -0
- package/dist/tools/checklist-items.d.ts.map +1 -0
- package/dist/tools/checklist-items.js +140 -0
- package/dist/tools/checklist-items.js.map +1 -0
- package/dist/tools/contacts.d.ts +94 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +134 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/excel.d.ts +96 -0
- package/dist/tools/excel.d.ts.map +1 -0
- package/dist/tools/excel.js +165 -0
- package/dist/tools/excel.js.map +1 -0
- package/dist/tools/focused-overrides.d.ts +70 -0
- package/dist/tools/focused-overrides.d.ts.map +1 -0
- package/dist/tools/focused-overrides.js +117 -0
- package/dist/tools/focused-overrides.js.map +1 -0
- package/dist/tools/index.d.ts +22 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +34 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/linked-resources.d.ts +74 -0
- package/dist/tools/linked-resources.d.ts.map +1 -0
- package/dist/tools/linked-resources.js +122 -0
- package/dist/tools/linked-resources.js.map +1 -0
- package/dist/tools/mail-rules.d.ts +98 -0
- package/dist/tools/mail-rules.d.ts.map +1 -0
- package/dist/tools/mail-rules.js +169 -0
- package/dist/tools/mail-rules.js.map +1 -0
- package/dist/tools/mail-send.d.ts +314 -0
- package/dist/tools/mail-send.d.ts.map +1 -0
- package/dist/tools/mail-send.js +555 -0
- package/dist/tools/mail-send.js.map +1 -0
- package/dist/tools/mail.d.ts +127 -0
- package/dist/tools/mail.d.ts.map +1 -0
- package/dist/tools/mail.js +311 -0
- package/dist/tools/mail.js.map +1 -0
- package/dist/tools/mailbox-organization.d.ts +301 -0
- package/dist/tools/mailbox-organization.d.ts.map +1 -0
- package/dist/tools/mailbox-organization.js +541 -0
- package/dist/tools/mailbox-organization.js.map +1 -0
- package/dist/tools/meetings.d.ts +114 -0
- package/dist/tools/meetings.d.ts.map +1 -0
- package/dist/tools/meetings.js +110 -0
- package/dist/tools/meetings.js.map +1 -0
- package/dist/tools/notes.d.ts +74 -0
- package/dist/tools/notes.d.ts.map +1 -0
- package/dist/tools/notes.js +136 -0
- package/dist/tools/notes.js.map +1 -0
- package/dist/tools/onedrive.d.ts +194 -0
- package/dist/tools/onedrive.d.ts.map +1 -0
- package/dist/tools/onedrive.js +257 -0
- package/dist/tools/onedrive.js.map +1 -0
- package/dist/tools/people.d.ts +129 -0
- package/dist/tools/people.d.ts.map +1 -0
- package/dist/tools/people.js +195 -0
- package/dist/tools/people.js.map +1 -0
- package/dist/tools/planner-visualization.d.ts +91 -0
- package/dist/tools/planner-visualization.d.ts.map +1 -0
- package/dist/tools/planner-visualization.js +192 -0
- package/dist/tools/planner-visualization.js.map +1 -0
- package/dist/tools/planner.d.ts +288 -0
- package/dist/tools/planner.d.ts.map +1 -0
- package/dist/tools/planner.js +368 -0
- package/dist/tools/planner.js.map +1 -0
- package/dist/tools/scheduling.d.ts +49 -0
- package/dist/tools/scheduling.d.ts.map +1 -0
- package/dist/tools/scheduling.js +115 -0
- package/dist/tools/scheduling.js.map +1 -0
- package/dist/tools/sharepoint.d.ts +115 -0
- package/dist/tools/sharepoint.d.ts.map +1 -0
- package/dist/tools/sharepoint.js +99 -0
- package/dist/tools/sharepoint.js.map +1 -0
- package/dist/tools/task-attachments.d.ts +74 -0
- package/dist/tools/task-attachments.d.ts.map +1 -0
- package/dist/tools/task-attachments.js +122 -0
- package/dist/tools/task-attachments.js.map +1 -0
- package/dist/tools/tasks.d.ts +74 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +126 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/teams.d.ts +389 -0
- package/dist/tools/teams.d.ts.map +1 -0
- package/dist/tools/teams.js +546 -0
- package/dist/tools/teams.js.map +1 -0
- package/dist/types/calendar.d.ts +60 -0
- package/dist/types/calendar.d.ts.map +1 -0
- package/dist/types/calendar.js +15 -0
- package/dist/types/calendar.js.map +1 -0
- package/dist/types/contacts.d.ts +96 -0
- package/dist/types/contacts.d.ts.map +1 -0
- package/dist/types/contacts.js +41 -0
- package/dist/types/contacts.js.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +16 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mail.d.ts +108 -0
- package/dist/types/mail.d.ts.map +1 -0
- package/dist/types/mail.js +40 -0
- package/dist/types/mail.js.map +1 -0
- package/dist/types/notes.d.ts +26 -0
- package/dist/types/notes.d.ts.map +1 -0
- package/dist/types/notes.js +6 -0
- package/dist/types/notes.js.map +1 -0
- package/dist/types/tasks.d.ts +31 -0
- package/dist/types/tasks.d.ts.map +1 -0
- package/dist/types/tasks.js +6 -0
- package/dist/types/tasks.js.map +1 -0
- package/dist/utils/dates.d.ts +66 -0
- package/dist/utils/dates.d.ts.map +1 -0
- package/dist/utils/dates.js +94 -0
- package/dist/utils/dates.js.map +1 -0
- package/dist/utils/errors.d.ts +218 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +306 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +10 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/visualization/html.d.ts +26 -0
- package/dist/visualization/html.d.ts.map +1 -0
- package/dist/visualization/html.js +306 -0
- package/dist/visualization/html.js.map +1 -0
- package/dist/visualization/markdown.d.ts +25 -0
- package/dist/visualization/markdown.d.ts.map +1 -0
- package/dist/visualization/markdown.js +186 -0
- package/dist/visualization/markdown.js.map +1 -0
- package/dist/visualization/mermaid.d.ts +25 -0
- package/dist/visualization/mermaid.d.ts.map +1 -0
- package/dist/visualization/mermaid.js +158 -0
- package/dist/visualization/mermaid.js.map +1 -0
- package/dist/visualization/svg.d.ts +25 -0
- package/dist/visualization/svg.d.ts.map +1 -0
- package/dist/visualization/svg.js +282 -0
- package/dist/visualization/svg.js.map +1 -0
- package/dist/visualization/types.d.ts +43 -0
- package/dist/visualization/types.d.ts.map +1 -0
- package/dist/visualization/types.js +34 -0
- package/dist/visualization/types.js.map +1 -0
- 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
|
+
'<': '<',
|
|
18
|
+
'>': '>',
|
|
19
|
+
'"': '"',
|
|
20
|
+
''': "'",
|
|
21
|
+
''': "'",
|
|
22
|
+
'©': '\u00A9',
|
|
23
|
+
'®': '\u00AE',
|
|
24
|
+
'™': '\u2122',
|
|
25
|
+
'—': '\u2014',
|
|
26
|
+
'–': '\u2013',
|
|
27
|
+
'…': '\u2026',
|
|
28
|
+
'‘': '\u2018',
|
|
29
|
+
'’': '\u2019',
|
|
30
|
+
'“': '\u201C',
|
|
31
|
+
'”': '\u201D',
|
|
32
|
+
'•': '\u2022',
|
|
33
|
+
'·': '\u00B7',
|
|
34
|
+
'€': '\u20AC',
|
|
35
|
+
'£': '\u00A3',
|
|
36
|
+
'¥': '\u00A5',
|
|
37
|
+
'¢': '\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
|