formatferry 0.1.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/commands/auth.d.ts +17 -0
  2. package/dist/commands/auth.d.ts.map +1 -0
  3. package/dist/commands/auth.js +102 -0
  4. package/dist/commands/auth.js.map +1 -0
  5. package/dist/commands/batch.d.ts +10 -0
  6. package/dist/commands/batch.d.ts.map +1 -0
  7. package/dist/commands/batch.js +92 -0
  8. package/dist/commands/batch.js.map +1 -0
  9. package/dist/commands/convert.d.ts +26 -0
  10. package/dist/commands/convert.d.ts.map +1 -0
  11. package/dist/commands/convert.js +198 -0
  12. package/dist/commands/convert.js.map +1 -0
  13. package/dist/config-store.d.ts +27 -0
  14. package/dist/config-store.d.ts.map +1 -0
  15. package/dist/config-store.js +58 -0
  16. package/dist/config-store.js.map +1 -0
  17. package/dist/entitlement.d.ts +11 -0
  18. package/dist/entitlement.d.ts.map +1 -0
  19. package/dist/entitlement.js +91 -0
  20. package/dist/entitlement.js.map +1 -0
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +10 -9
  24. package/dist/index.js.map +1 -0
  25. package/dist/packages/cli/src/commands/auth.d.ts +17 -0
  26. package/dist/packages/cli/src/commands/auth.d.ts.map +1 -0
  27. package/dist/packages/cli/src/commands/auth.js +102 -0
  28. package/dist/packages/cli/src/commands/auth.js.map +1 -0
  29. package/dist/packages/cli/src/commands/batch.d.ts +10 -0
  30. package/dist/packages/cli/src/commands/batch.d.ts.map +1 -0
  31. package/dist/packages/cli/src/commands/batch.js +92 -0
  32. package/dist/packages/cli/src/commands/batch.js.map +1 -0
  33. package/dist/packages/cli/src/commands/convert.d.ts +26 -0
  34. package/dist/packages/cli/src/commands/convert.d.ts.map +1 -0
  35. package/dist/packages/cli/src/commands/convert.js +198 -0
  36. package/dist/packages/cli/src/commands/convert.js.map +1 -0
  37. package/dist/packages/cli/src/config-store.d.ts +27 -0
  38. package/dist/packages/cli/src/config-store.d.ts.map +1 -0
  39. package/dist/packages/cli/src/config-store.js +58 -0
  40. package/dist/packages/cli/src/config-store.js.map +1 -0
  41. package/dist/packages/cli/src/entitlement.d.ts +11 -0
  42. package/dist/packages/cli/src/entitlement.d.ts.map +1 -0
  43. package/dist/packages/cli/src/entitlement.js +91 -0
  44. package/dist/packages/cli/src/entitlement.js.map +1 -0
  45. package/dist/packages/cli/src/index.d.ts +2 -0
  46. package/dist/packages/cli/src/index.d.ts.map +1 -0
  47. package/dist/packages/cli/src/index.js +28 -0
  48. package/dist/packages/cli/src/index.js.map +1 -0
  49. package/dist/packages/cli/src/shim.d.ts +2 -0
  50. package/dist/packages/cli/src/shim.d.ts.map +1 -0
  51. package/dist/packages/cli/src/shim.js +21 -0
  52. package/dist/packages/cli/src/shim.js.map +1 -0
  53. package/dist/shim.d.ts +2 -0
  54. package/dist/shim.d.ts.map +1 -0
  55. package/dist/shim.js +21 -0
  56. package/dist/shim.js.map +1 -0
  57. package/dist/src/shared/adapters/docx-adapter.d.ts +85 -0
  58. package/dist/src/shared/adapters/docx-adapter.d.ts.map +1 -0
  59. package/dist/src/shared/adapters/docx-adapter.js +164 -0
  60. package/dist/src/shared/adapters/docx-adapter.js.map +1 -0
  61. package/dist/src/shared/adapters/pdf-adapter.d.ts +94 -0
  62. package/dist/src/shared/adapters/pdf-adapter.d.ts.map +1 -0
  63. package/dist/src/shared/adapters/pdf-adapter.js +322 -0
  64. package/dist/src/shared/adapters/pdf-adapter.js.map +1 -0
  65. package/dist/src/shared/adapters/spreadsheet-adapter.d.ts +98 -0
  66. package/dist/src/shared/adapters/spreadsheet-adapter.d.ts.map +1 -0
  67. package/dist/src/shared/adapters/spreadsheet-adapter.js +424 -0
  68. package/dist/src/shared/adapters/spreadsheet-adapter.js.map +1 -0
  69. package/dist/src/shared/atlassian-detector.d.ts +6 -0
  70. package/dist/src/shared/atlassian-detector.d.ts.map +1 -0
  71. package/dist/src/shared/atlassian-detector.js +23 -0
  72. package/dist/src/shared/atlassian-detector.js.map +1 -0
  73. package/dist/src/shared/conversion-engine.d.ts +114 -0
  74. package/dist/src/shared/conversion-engine.d.ts.map +1 -0
  75. package/dist/src/shared/conversion-engine.js +790 -0
  76. package/dist/src/shared/conversion-engine.js.map +1 -0
  77. package/dist/src/shared/entitlement-service.d.ts +42 -0
  78. package/dist/src/shared/entitlement-service.d.ts.map +1 -0
  79. package/dist/src/shared/entitlement-service.js +38 -0
  80. package/dist/src/shared/entitlement-service.js.map +1 -0
  81. package/dist/src/shared/input-sanitizer.d.ts +93 -0
  82. package/dist/src/shared/input-sanitizer.d.ts.map +1 -0
  83. package/dist/src/shared/input-sanitizer.js +527 -0
  84. package/dist/src/shared/input-sanitizer.js.map +1 -0
  85. package/package.json +6 -2
@@ -0,0 +1,527 @@
1
+ import DOMPurify from 'dompurify';
2
+ // Default configuration
3
+ export const DEFAULT_SANITIZATION_CONFIG = {
4
+ level: 'moderate',
5
+ maxInputSize: 1024 * 1024, // 1MB
6
+ timeoutMs: 5000, // 5 seconds
7
+ };
8
+ // Input sanitizer class
9
+ export class InputSanitizer {
10
+ config;
11
+ domEnv;
12
+ purifyConfig;
13
+ constructor(config = {}, domEnv) {
14
+ this.config = { ...DEFAULT_SANITIZATION_CONFIG, ...config };
15
+ // Fall back to browser globals if no injection (Req 14.2)
16
+ this.domEnv = domEnv ?? {
17
+ DOMParser: globalThis.DOMParser,
18
+ DOMPurify: DOMPurify,
19
+ };
20
+ this.purifyConfig = this.createPurifyConfig();
21
+ }
22
+ /**
23
+ * Sanitize HTML content to prevent XSS attacks
24
+ */
25
+ sanitizeHTML(html) {
26
+ if (!html || typeof html !== 'string') {
27
+ return '';
28
+ }
29
+ try {
30
+ // Use injected DOMPurify instead of direct import (Req 14.1)
31
+ const sanitized = this.domEnv.DOMPurify.sanitize(html, {
32
+ ALLOWED_TAGS: this.purifyConfig.ALLOWED_TAGS,
33
+ ALLOWED_ATTR: this.purifyConfig.ALLOWED_ATTR,
34
+ FORBID_TAGS: this.purifyConfig.FORBID_TAGS,
35
+ FORBID_ATTR: this.purifyConfig.FORBID_ATTR,
36
+ });
37
+ return sanitized;
38
+ }
39
+ catch (error) {
40
+ console.warn('HTML sanitization failed:', error);
41
+ // Return empty string if sanitization fails
42
+ return '';
43
+ }
44
+ }
45
+ /**
46
+ * Validate input content structure and size
47
+ */
48
+ validateInput(input) {
49
+ const warnings = [];
50
+ let isValid = true;
51
+ // Check input size
52
+ if (input.length > this.config.maxInputSize) {
53
+ warnings.push({
54
+ type: 'size',
55
+ message: `Input size (${input.length} chars) exceeds limit (${this.config.maxInputSize} chars)`,
56
+ severity: 'high'
57
+ });
58
+ isValid = false;
59
+ }
60
+ // Check for potentially large content that might cause performance issues
61
+ if (input.length > 100000) { // 100KB
62
+ warnings.push({
63
+ type: 'performance',
64
+ message: `Large content detected (${Math.round(input.length / 1000)}KB). Processing may be slow.`,
65
+ severity: 'medium'
66
+ });
67
+ }
68
+ // Check for suspicious patterns that might indicate XSS attempts
69
+ // Only flag truly dangerous patterns, not normal HTML content
70
+ const highRiskPatterns = [
71
+ /<script[^>]*>.*?<\/script>/i, // Only flag actual script tags with content
72
+ /javascript:\s*[^;]/i, // javascript: with actual code
73
+ /on\w+\s*=\s*["'][^"']*[<>]/i, // Event handlers with suspicious content
74
+ ];
75
+ const mediumRiskPatterns = [
76
+ /<iframe[^>]*>/i,
77
+ /<object[^>]*>/i,
78
+ /<embed[^>]*>/i,
79
+ ];
80
+ // Check high risk patterns first
81
+ for (const pattern of highRiskPatterns) {
82
+ if (pattern.test(input)) {
83
+ warnings.push({
84
+ type: 'security',
85
+ message: 'Potentially malicious content detected and will be sanitized',
86
+ severity: 'high'
87
+ });
88
+ break; // Only add one security warning
89
+ }
90
+ }
91
+ // Check medium risk patterns if no high risk found
92
+ if (warnings.length === 0) {
93
+ for (const pattern of mediumRiskPatterns) {
94
+ if (pattern.test(input)) {
95
+ warnings.push({
96
+ type: 'security',
97
+ message: 'Embedded content detected and will be sanitized',
98
+ severity: 'medium'
99
+ });
100
+ break; // Only add one security warning
101
+ }
102
+ }
103
+ }
104
+ // Check for malformed HTML
105
+ try {
106
+ const parser = new this.domEnv.DOMParser();
107
+ const doc = parser.parseFromString(input, 'text/html');
108
+ const parserErrors = doc.querySelectorAll('parsererror');
109
+ if (parserErrors.length > 0) {
110
+ warnings.push({
111
+ type: 'content',
112
+ message: 'Malformed HTML detected. Content will be cleaned during processing.',
113
+ severity: 'low'
114
+ });
115
+ }
116
+ }
117
+ catch {
118
+ warnings.push({
119
+ type: 'content',
120
+ message: 'Invalid HTML structure detected',
121
+ severity: 'medium'
122
+ });
123
+ }
124
+ return {
125
+ isValid,
126
+ warnings,
127
+ sanitizedContent: isValid ? this.sanitizeHTML(input) : undefined
128
+ };
129
+ }
130
+ /**
131
+ * Process clipboard content with sanitization and validation
132
+ */
133
+ processClipboardContent(htmlContent, plainText) {
134
+ const warnings = [];
135
+ let processedHTML = '';
136
+ let processedText = plainText || '';
137
+ let shouldUseHTML = false;
138
+ // Validate and sanitize HTML content if present
139
+ if (htmlContent) {
140
+ // Restructure Slack's flat indent-attributed lists into proper nesting
141
+ // before DOMPurify strips the non-standard `indent` attributes
142
+ const normalizedHTML = normalizeSlackHTML(htmlContent, new this.domEnv.DOMParser());
143
+ const htmlValidation = this.validateInput(normalizedHTML);
144
+ warnings.push(...htmlValidation.warnings);
145
+ if (htmlValidation.isValid && htmlValidation.sanitizedContent) {
146
+ processedHTML = htmlValidation.sanitizedContent;
147
+ shouldUseHTML = true;
148
+ }
149
+ else if (htmlValidation.sanitizedContent) {
150
+ // Even if validation failed, we might still use sanitized content
151
+ processedHTML = htmlValidation.sanitizedContent;
152
+ shouldUseHTML = processedHTML.length > 0;
153
+ }
154
+ }
155
+ // Validate plain text as fallback
156
+ if (plainText) {
157
+ const textValidation = this.validateInput(plainText);
158
+ warnings.push(...textValidation.warnings);
159
+ // Plain text doesn't need sanitization, but we still validate size
160
+ if (!textValidation.isValid) {
161
+ processedText = plainText.substring(0, this.config.maxInputSize);
162
+ warnings.push({
163
+ type: 'size',
164
+ message: 'Plain text content was truncated due to size limits',
165
+ severity: 'medium'
166
+ });
167
+ }
168
+ }
169
+ return {
170
+ processedHTML,
171
+ processedText,
172
+ warnings,
173
+ shouldUseHTML
174
+ };
175
+ }
176
+ /**
177
+ * Create DOMPurify configuration based on sanitization level
178
+ */
179
+ createPurifyConfig() {
180
+ const baseConfig = {
181
+ // Always remove script tags and event handlers
182
+ FORBID_TAGS: ['script', 'object', 'embed', 'applet', 'meta', 'link'],
183
+ FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover', 'onfocus', 'onblur'],
184
+ // Keep formatting tags that are useful for conversion
185
+ ALLOWED_TAGS: [
186
+ 'p', 'br', 'div', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
187
+ 'strong', 'b', 'em', 'i', 'u', 's', 'strike', 'del', 'ins',
188
+ 'ul', 'ol', 'li', 'blockquote', 'pre', 'code',
189
+ 'table', 'thead', 'tbody', 'tr', 'td', 'th',
190
+ 'a', 'img',
191
+ 'sup', 'sub', 'input' // For superscript, subscript, and task list support
192
+ ],
193
+ // Include data-page-marker for PDF page break markers (Req 3.5)
194
+ // Include type and checked for task list checkbox support
195
+ ALLOWED_ATTR: ['href', 'src', 'alt', 'title', 'style', 'class', 'data-page-marker', 'type', 'checked', 'data-math'],
196
+ };
197
+ switch (this.config.level) {
198
+ case 'strict':
199
+ return {
200
+ ...baseConfig,
201
+ ALLOWED_TAGS: [
202
+ 'p', 'br', 'div', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
203
+ 'strong', 'b', 'em', 'i', 'ul', 'ol', 'li', 'blockquote', 'pre', 'code'
204
+ ],
205
+ ALLOWED_ATTR: ['style'], // Only allow style for formatting detection
206
+ FORBID_ATTR: [...(baseConfig.FORBID_ATTR || []), 'href', 'src', 'class'],
207
+ };
208
+ case 'permissive':
209
+ return {
210
+ ...baseConfig,
211
+ ALLOWED_TAGS: [
212
+ ...baseConfig.ALLOWED_TAGS,
213
+ 'figure', 'figcaption', 'caption', 'colgroup', 'col',
214
+ 'dl', 'dt', 'dd', 'address', 'time'
215
+ ],
216
+ ALLOWED_ATTR: [
217
+ ...baseConfig.ALLOWED_ATTR,
218
+ 'id', 'data-*', 'role', 'aria-*'
219
+ ],
220
+ };
221
+ case 'moderate':
222
+ default:
223
+ return baseConfig;
224
+ }
225
+ }
226
+ /**
227
+ * Update sanitization configuration
228
+ */
229
+ updateConfig(newConfig) {
230
+ this.config = { ...this.config, ...newConfig };
231
+ this.purifyConfig = this.createPurifyConfig();
232
+ }
233
+ /**
234
+ * Get current configuration
235
+ */
236
+ getConfig() {
237
+ return { ...this.config };
238
+ }
239
+ }
240
+ // Export a default instance
241
+ export const defaultSanitizer = new InputSanitizer();
242
+ /**
243
+ * Normalize Slack's non-standard flat list HTML into proper nested structure.
244
+ *
245
+ * Slack serializes nested lists as a flat <ul>/<ol> where each <li> carries an
246
+ * `indent="N"` attribute instead of using actual DOM nesting. DOMPurify strips
247
+ * those non-standard attributes, destroying the only nesting signal. This
248
+ * function reconstructs proper nesting before sanitization runs.
249
+ *
250
+ * Runs entirely client-side via DOMParser — no network calls, no storage.
251
+ *
252
+ * @param html - The HTML string to normalize
253
+ * @param domParser - Optional DOMParser instance; falls back to `new globalThis.DOMParser()`
254
+ */
255
+ export function normalizeSlackHTML(html, domParser) {
256
+ if (!html || !html.includes('indent='))
257
+ return html;
258
+ const doc = (domParser ?? new globalThis.DOMParser()).parseFromString(html, 'text/html');
259
+ const body = doc.body;
260
+ const getIndent = (li) => {
261
+ const raw = li.getAttribute('indent');
262
+ const parsed = raw !== null ? parseInt(raw, 10) : NaN;
263
+ return isNaN(parsed) ? 0 : parsed; // default 0 to preserve relative differences
264
+ };
265
+ const restructureList = (flatList) => {
266
+ const allLis = Array.from(flatList.children);
267
+ const baseIndent = Math.min(...allLis.map(getIndent));
268
+ const root = doc.createElement(flatList.tagName);
269
+ // stack[i] = the <ul>/<ol> container at relative depth i
270
+ const stack = [root];
271
+ for (const li of allLis) {
272
+ const relDepth = getIndent(li) - baseIndent; // always >= 0
273
+ const cleanLi = li.cloneNode(true);
274
+ cleanLi.removeAttribute('indent');
275
+ // Grow stack: add nested list containers as needed
276
+ while (stack.length <= relDepth) {
277
+ const parentList = stack[stack.length - 1];
278
+ const lastLi = parentList.lastElementChild;
279
+ const nested = doc.createElement(flatList.tagName);
280
+ (lastLi ?? parentList).appendChild(nested);
281
+ stack.push(nested);
282
+ }
283
+ // Shrink stack: pop back to the target depth
284
+ stack.length = relDepth + 1;
285
+ stack[relDepth].appendChild(cleanLi);
286
+ }
287
+ return root;
288
+ };
289
+ const isListEl = (n) => n.nodeType === Node.ELEMENT_NODE &&
290
+ (n.nodeName === 'UL' || n.nodeName === 'OL');
291
+ // Snapshot children before mutations; handle runs of consecutive list
292
+ // elements separated by paragraphs independently (flushRun pattern)
293
+ const snapshot = Array.from(body.childNodes);
294
+ let runStart = -1;
295
+ const flushRun = (endIdx) => {
296
+ if (runStart === -1)
297
+ return;
298
+ const run = snapshot.slice(runStart, endIdx);
299
+ runStart = -1;
300
+ const tagName = run[0].tagName;
301
+ const virtual = doc.createElement(tagName);
302
+ for (const listEl of run) {
303
+ for (const li of Array.from(listEl.children)) {
304
+ virtual.appendChild(li.cloneNode(true));
305
+ }
306
+ }
307
+ // Only restructure if any LI actually has an indent attribute
308
+ if (!Array.from(virtual.children).some(li => li.hasAttribute('indent')))
309
+ return;
310
+ const nested = restructureList(virtual);
311
+ run[0].parentNode.insertBefore(nested, run[0]);
312
+ for (const el of run)
313
+ el.parentNode?.removeChild(el);
314
+ };
315
+ snapshot.forEach((node, i) => {
316
+ if (isListEl(node)) {
317
+ if (runStart === -1)
318
+ runStart = i;
319
+ }
320
+ else {
321
+ flushRun(i);
322
+ }
323
+ });
324
+ flushRun(snapshot.length);
325
+ return body.innerHTML;
326
+ }
327
+ // Utility functions for common operations
328
+ export function sanitizeHTML(html, config) {
329
+ if (config) {
330
+ const sanitizer = new InputSanitizer(config);
331
+ return sanitizer.sanitizeHTML(html);
332
+ }
333
+ return defaultSanitizer.sanitizeHTML(html);
334
+ }
335
+ export function validateInput(input, config) {
336
+ if (config) {
337
+ const sanitizer = new InputSanitizer(config);
338
+ return sanitizer.validateInput(input);
339
+ }
340
+ return defaultSanitizer.validateInput(input);
341
+ }
342
+ export function processClipboardContent(htmlContent, plainText, config) {
343
+ if (config) {
344
+ const sanitizer = new InputSanitizer(config);
345
+ return sanitizer.processClipboardContent(htmlContent, plainText);
346
+ }
347
+ return defaultSanitizer.processClipboardContent(htmlContent, plainText);
348
+ }
349
+ // ─────────────────────────────────────────────────────────────────────────────
350
+ // §5.2 — Atlassian HTML normalizer (Task 8)
351
+ // Converts Confluence/Jira proprietary markup to standard HTML before
352
+ // DOMPurify sanitization and Turndown conversion.
353
+ // ─────────────────────────────────────────────────────────────────────────────
354
+ const PANEL_EMOJI = {
355
+ info: 'ℹ️ Info:',
356
+ warning: '⚠️ Warning:',
357
+ note: '📝 Note:',
358
+ tip: '💡 Tip:',
359
+ };
360
+ /**
361
+ * 8.1 — Convert Atlassian info/warning/note/tip panels to <blockquote> elements.
362
+ * `<ac:structured-macro ac:name="info|warning|note|tip">` →
363
+ * `<blockquote><p>EMOJI Label:</p>...body...</blockquote>`
364
+ */
365
+ function normalizePanels(doc) {
366
+ const macros = Array.from(doc.querySelectorAll('ac\\:structured-macro, [ac\\:name]')).filter(el => {
367
+ const name = el.getAttribute('ac:name') ?? '';
368
+ return name in PANEL_EMOJI;
369
+ });
370
+ // Also query by tag name directly (DOMParser may lowercase or namespace differently)
371
+ const allMacros = Array.from(doc.getElementsByTagName('*')).filter(el => {
372
+ const tag = el.tagName.toLowerCase();
373
+ const name = el.getAttribute('ac:name') ?? '';
374
+ return (tag === 'ac:structured-macro' || tag.includes('structured-macro')) &&
375
+ name in PANEL_EMOJI;
376
+ });
377
+ const combined = [...new Set([...macros, ...allMacros])];
378
+ for (const macro of combined) {
379
+ const name = (macro.getAttribute('ac:name') ?? '').toLowerCase();
380
+ const label = PANEL_EMOJI[name];
381
+ if (!label)
382
+ continue;
383
+ // Extract body from <ac:rich-text-body>
384
+ const bodyEl = macro.querySelector('ac\\:rich-text-body') ??
385
+ Array.from(macro.getElementsByTagName('*')).find(el => el.tagName.toLowerCase() === 'ac:rich-text-body');
386
+ const blockquote = doc.createElement('blockquote');
387
+ const labelP = doc.createElement('p');
388
+ labelP.textContent = label;
389
+ blockquote.appendChild(labelP);
390
+ if (bodyEl) {
391
+ while (bodyEl.firstChild) {
392
+ blockquote.appendChild(bodyEl.firstChild);
393
+ }
394
+ }
395
+ macro.parentNode?.replaceChild(blockquote, macro);
396
+ }
397
+ }
398
+ /**
399
+ * 8.2 — Convert Atlassian code macros to <pre><code> elements.
400
+ * `<ac:structured-macro ac:name="code">` →
401
+ * `<pre><code class="language-{lang}">...content...</code></pre>`
402
+ */
403
+ function normalizeCodeBlocks(doc) {
404
+ const codeMacros = Array.from(doc.getElementsByTagName('*')).filter(el => {
405
+ const tag = el.tagName.toLowerCase();
406
+ return (tag === 'ac:structured-macro' || tag.includes('structured-macro')) &&
407
+ el.getAttribute('ac:name') === 'code';
408
+ });
409
+ for (const macro of codeMacros) {
410
+ // Find language parameter
411
+ const langParam = Array.from(macro.getElementsByTagName('*')).find(el => {
412
+ const tag = el.tagName.toLowerCase();
413
+ return (tag === 'ac:parameter' || tag.includes(':parameter')) &&
414
+ el.getAttribute('ac:name') === 'language';
415
+ });
416
+ const lang = langParam?.textContent?.trim() ?? '';
417
+ // Find plain-text body
418
+ const bodyEl = Array.from(macro.getElementsByTagName('*')).find(el => {
419
+ const tag = el.tagName.toLowerCase();
420
+ return tag === 'ac:plain-text-body' || tag.includes('plain-text-body');
421
+ });
422
+ const content = bodyEl?.textContent ?? '';
423
+ const pre = doc.createElement('pre');
424
+ const code = doc.createElement('code');
425
+ if (lang) {
426
+ code.className = `language-${lang}`;
427
+ }
428
+ code.textContent = content;
429
+ pre.appendChild(code);
430
+ macro.parentNode?.replaceChild(pre, macro);
431
+ }
432
+ }
433
+ /**
434
+ * 8.3 — Convert Atlassian user mentions to plain text.
435
+ * `<a class="user-hover" ...>Display Name</a>` → plain text node
436
+ */
437
+ function normalizeMentions(doc) {
438
+ const mentions = Array.from(doc.querySelectorAll('a.user-hover'));
439
+ for (const mention of mentions) {
440
+ const displayName = mention.textContent ?? '';
441
+ const textNode = doc.createTextNode(displayName);
442
+ mention.parentNode?.replaceChild(textNode, mention);
443
+ }
444
+ }
445
+ /**
446
+ * 8.4 — Strip Confluence-specific CSS classes from table elements.
447
+ * `<table class="confluenceTable">` → `<table>`
448
+ * `<td class="confluenceTd">` → `<td>`
449
+ * `<th class="confluenceTh">` → `<th>`
450
+ */
451
+ function normalizeAtlassianTables(doc) {
452
+ for (const table of Array.from(doc.querySelectorAll('table.confluenceTable'))) {
453
+ table.removeAttribute('class');
454
+ }
455
+ for (const td of Array.from(doc.querySelectorAll('td.confluenceTd'))) {
456
+ td.removeAttribute('class');
457
+ }
458
+ for (const th of Array.from(doc.querySelectorAll('th.confluenceTh'))) {
459
+ th.removeAttribute('class');
460
+ }
461
+ }
462
+ /**
463
+ * 8.5 — Recursively walk the DOM tree and replace ac:* / ri:* wrapper elements
464
+ * with their children, preserving all inline formatting.
465
+ * Uses numeric constant 1 for Node.ELEMENT_NODE to avoid browser-global dependency.
466
+ *
467
+ * After unwrapping a macro, the newly inserted children are re-processed so
468
+ * that nested ac: and ri: wrappers (e.g. ac:layout > ac:layout-section) are
469
+ * also stripped in the same pass.
470
+ */
471
+ function stripUnrecognizedMacros(node) {
472
+ const ELEMENT_NODE = 1;
473
+ // Re-snapshot after each mutation so newly inserted ac:* children are caught
474
+ let i = 0;
475
+ while (i < node.childNodes.length) {
476
+ const child = node.childNodes[i];
477
+ if (child.nodeType === ELEMENT_NODE) {
478
+ const el = child;
479
+ const tagName = el.tagName.toLowerCase();
480
+ if (tagName.startsWith('ac:') || tagName.startsWith('ri:')) {
481
+ // Collect children before moving them
482
+ const insertedCount = el.childNodes.length;
483
+ // Replace wrapper with its children (preserving innerHTML)
484
+ while (el.firstChild) {
485
+ node.insertBefore(el.firstChild, el);
486
+ }
487
+ node.removeChild(el);
488
+ // Do NOT advance i — re-process from the same position so newly
489
+ // inserted ac:*/ri:* children are handled in the next iteration(s).
490
+ // insertedCount === 0 means nothing was inserted; advance to avoid loop.
491
+ if (insertedCount === 0)
492
+ i++;
493
+ }
494
+ else {
495
+ stripUnrecognizedMacros(el);
496
+ i++;
497
+ }
498
+ }
499
+ else {
500
+ i++;
501
+ }
502
+ }
503
+ }
504
+ /**
505
+ * 8.6 — Main entry point: normalize Atlassian HTML to standard HTML.
506
+ *
507
+ * Parses the HTML via DOMParser, applies all normalizations in order,
508
+ * and serializes back to a string. This is immune to ReDoS attacks
509
+ * (no regex on HTML) and handles arbitrary nesting natively.
510
+ *
511
+ * @param html - Raw Atlassian HTML string (Confluence/Jira clipboard)
512
+ * @param domParser - Optional DOMParser instance; falls back to globalThis.DOMParser
513
+ * @returns Normalized HTML string with standard elements only
514
+ */
515
+ export function normalizeAtlassianHTML(html, domParser) {
516
+ if (!html)
517
+ return html;
518
+ const parser = domParser ?? new globalThis.DOMParser();
519
+ const doc = parser.parseFromString(html, 'text/html');
520
+ normalizePanels(doc);
521
+ normalizeCodeBlocks(doc);
522
+ normalizeMentions(doc);
523
+ normalizeAtlassianTables(doc);
524
+ stripUnrecognizedMacros(doc.body);
525
+ return doc.body.innerHTML;
526
+ }
527
+ //# sourceMappingURL=input-sanitizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-sanitizer.js","sourceRoot":"","sources":["../../../../../src/shared/input-sanitizer.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "formatferry",
3
- "version": "0.1.4",
3
+ "version": "1.0.0",
4
4
  "description": "FormatFerry CLI — Convert HTML, DOCX, PDF, XLSX, CSV to Markdown",
5
5
  "keywords": [
6
6
  "markdown",
@@ -30,7 +30,11 @@
30
30
  "dompurify": "^3.3.1",
31
31
  "env-paths": "^3.0.0",
32
32
  "fast-glob": "^3.3.3",
33
- "linkedom": "^0.18.10"
33
+ "jszip": "^3.10.1",
34
+ "linkedom": "^0.18.10",
35
+ "mammoth": "^1.11.0",
36
+ "pdfjs-dist": "^5.4.530",
37
+ "xlsx": "^0.18.5"
34
38
  },
35
39
  "devDependencies": {
36
40
  "@types/dompurify": "^3.0.5",