udf-cli 0.1.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 (50) hide show
  1. package/README.md +308 -0
  2. package/dist/bin/udf-cli.d.ts +2 -0
  3. package/dist/bin/udf-cli.js +122 -0
  4. package/dist/bin/udf-cli.js.map +1 -0
  5. package/dist/src/converters/html-to-udf.d.ts +1 -0
  6. package/dist/src/converters/html-to-udf.js +7 -0
  7. package/dist/src/converters/html-to-udf.js.map +1 -0
  8. package/dist/src/converters/markdown-to-udf.d.ts +1 -0
  9. package/dist/src/converters/markdown-to-udf.js +7 -0
  10. package/dist/src/converters/markdown-to-udf.js.map +1 -0
  11. package/dist/src/converters/udf-to-html.d.ts +1 -0
  12. package/dist/src/converters/udf-to-html.js +7 -0
  13. package/dist/src/converters/udf-to-html.js.map +1 -0
  14. package/dist/src/converters/udf-to-markdown.d.ts +1 -0
  15. package/dist/src/converters/udf-to-markdown.js +7 -0
  16. package/dist/src/converters/udf-to-markdown.js.map +1 -0
  17. package/dist/src/html/markdown-parser.d.ts +2 -0
  18. package/dist/src/html/markdown-parser.js +172 -0
  19. package/dist/src/html/markdown-parser.js.map +1 -0
  20. package/dist/src/html/markdown-serializer.d.ts +2 -0
  21. package/dist/src/html/markdown-serializer.js +146 -0
  22. package/dist/src/html/markdown-serializer.js.map +1 -0
  23. package/dist/src/html/parser.d.ts +2 -0
  24. package/dist/src/html/parser.js +517 -0
  25. package/dist/src/html/parser.js.map +1 -0
  26. package/dist/src/html/serializer.d.ts +6 -0
  27. package/dist/src/html/serializer.js +259 -0
  28. package/dist/src/html/serializer.js.map +1 -0
  29. package/dist/src/index.d.ts +6 -0
  30. package/dist/src/index.js +6 -0
  31. package/dist/src/index.js.map +1 -0
  32. package/dist/src/model/document.d.ts +99 -0
  33. package/dist/src/model/document.js +88 -0
  34. package/dist/src/model/document.js.map +1 -0
  35. package/dist/src/udf/cdata-builder.d.ts +14 -0
  36. package/dist/src/udf/cdata-builder.js +59 -0
  37. package/dist/src/udf/cdata-builder.js.map +1 -0
  38. package/dist/src/udf/parser.d.ts +2 -0
  39. package/dist/src/udf/parser.js +293 -0
  40. package/dist/src/udf/parser.js.map +1 -0
  41. package/dist/src/udf/serializer.d.ts +5 -0
  42. package/dist/src/udf/serializer.js +228 -0
  43. package/dist/src/udf/serializer.js.map +1 -0
  44. package/dist/src/utils/color.d.ts +9 -0
  45. package/dist/src/utils/color.js +87 -0
  46. package/dist/src/utils/color.js.map +1 -0
  47. package/dist/src/utils/style.d.ts +18 -0
  48. package/dist/src/utils/style.js +55 -0
  49. package/dist/src/utils/style.js.map +1 -0
  50. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,308 @@
1
+ # udf-cli
2
+
3
+ Convert between HTML and UYAP UDF file format. Designed for AI agents that need to read and write UDF documents programmatically.
4
+
5
+ ## What is UDF?
6
+
7
+ UDF is the document format used by UYAP (Turkey's National Judiciary Informatics System). A UDF file is a ZIP archive containing a single `content.xml` file with text content, formatting, images, and tables encoded in a custom XML schema.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install udf-cli
13
+ ```
14
+
15
+ Or run directly:
16
+
17
+ ```bash
18
+ npx udf-cli html2udf input.html output.udf
19
+ ```
20
+
21
+ ## CLI Usage
22
+
23
+ ### HTML to UDF
24
+
25
+ ```bash
26
+ udf-cli html2udf <input> [output]
27
+ ```
28
+
29
+ Input accepts a file path, raw HTML string, or `-` for stdin. If input contains `<` it is treated as raw HTML. Output is optional — omit it to write to stdout.
30
+
31
+ ```bash
32
+ # File to file
33
+ udf-cli html2udf input.html output.udf
34
+
35
+ # Raw HTML string to file
36
+ udf-cli html2udf '<p><strong>Merhaba</strong> dünya</p>' output.udf
37
+
38
+ # Raw HTML string to stdout
39
+ udf-cli html2udf '<p>Test</p>' > output.udf
40
+
41
+ # Stdin to file
42
+ cat input.html | udf-cli html2udf - output.udf
43
+
44
+ # Stdin to stdout (pipe-friendly)
45
+ echo '<p>Merhaba</p>' | udf-cli html2udf - > output.udf
46
+ ```
47
+
48
+ ### UDF to HTML
49
+
50
+ ```bash
51
+ udf-cli udf2html <input> [output]
52
+ ```
53
+
54
+ Input accepts a file path or `-` for stdin. Output is optional — omit it to print HTML to stdout.
55
+
56
+ ```bash
57
+ # File to file
58
+ udf-cli udf2html input.udf output.html
59
+
60
+ # File to stdout (agent-friendly — read UDF content directly)
61
+ udf-cli udf2html input.udf
62
+
63
+ # Stdin to stdout
64
+ cat input.udf | udf-cli udf2html -
65
+
66
+ # Full roundtrip via pipes
67
+ echo '<p>Test</p>' | udf-cli html2udf - | udf-cli udf2html -
68
+ ```
69
+
70
+ ### Markdown to UDF
71
+
72
+ ```bash
73
+ udf-cli md2udf <input> [output]
74
+ ```
75
+
76
+ Input accepts a file path, raw Markdown string, or `-` for stdin.
77
+
78
+ ```bash
79
+ # File to file
80
+ udf-cli md2udf input.md output.udf
81
+
82
+ # Stdin to file
83
+ cat input.md | udf-cli md2udf - output.udf
84
+
85
+ # Raw Markdown via stdin
86
+ echo '**Merhaba** dünya' | udf-cli md2udf - output.udf
87
+ ```
88
+
89
+ Supported Markdown syntax for input:
90
+
91
+ - `**bold**` and `*italic*`, `***bold italic***`
92
+ - `# Heading 1` through `###### Heading 6`
93
+ - `1. Numbered list` and `- Bulleted list` (with nesting via indentation)
94
+ - Markdown tables (`| col1 | col2 |` with separator row)
95
+ - `![alt](data:image/png;base64,...)` images
96
+
97
+ ### UDF to Markdown
98
+
99
+ ```bash
100
+ udf-cli udf2md <input> [output]
101
+ ```
102
+
103
+ Converts UDF to Markdown — ideal for AI agents that work better with Markdown than HTML. Tables become Markdown tables, bold/italic use `**`/`*` syntax, lists become `1.`/`-` items.
104
+
105
+ ```bash
106
+ # Read a UDF file as Markdown (agent-friendly)
107
+ udf-cli udf2md input.udf
108
+
109
+ # Save as Markdown file
110
+ udf-cli udf2md input.udf output.md
111
+ ```
112
+
113
+ Example output:
114
+
115
+ ```markdown
116
+ **T.C.**
117
+ **ANTALYA 3. ASLİYE HUKUK MAHKEMESİ**
118
+
119
+ **ESAS NO:** 2024/463
120
+ **DAVACI:** Mehmet Yılmaz
121
+
122
+ | **Sıra No** | **Açıklama** | **Toplam (TL)** |
123
+ | --- | --- | --- |
124
+ | 1 | Arsa değeri | 1.250.000,00 |
125
+ | 2 | Bina değeri | 990.000,00 |
126
+
127
+ 1. Taşınmazın konumu
128
+ 2. Yapının fiziksel durumu
129
+
130
+ - Dış cephe boyasında dökülme
131
+ - Çatı izolasyonunda bozulma
132
+ ```
133
+
134
+ ## Library Usage
135
+
136
+ ```typescript
137
+ import { htmlToUdf, udfToHtml, udfToMarkdown, markdownToUdf } from 'udf-cli';
138
+
139
+ // HTML string → UDF buffer
140
+ const udfBuffer = await htmlToUdf('<p><strong>Mahkeme kararı</strong></p>');
141
+ fs.writeFileSync('document.udf', udfBuffer);
142
+
143
+ // UDF buffer → HTML string
144
+ const udf = fs.readFileSync('document.udf');
145
+ const html = await udfToHtml(udf);
146
+
147
+ // UDF buffer → Markdown string
148
+ const md = await udfToMarkdown(udf);
149
+
150
+ // Markdown string → UDF buffer
151
+ const udfFromMd = await markdownToUdf('**Başlık**\n\nParagraf metni');
152
+ ```
153
+
154
+ ## Supported HTML Elements
155
+
156
+ | HTML | UDF Mapping |
157
+ |------|-------------|
158
+ | `<p>` | Paragraph |
159
+ | `<h1>` - `<h6>` | Paragraph with bold, sizes 24/20/16/14/12/10 pt |
160
+ | `<strong>`, `<b>` | Bold text |
161
+ | `<em>`, `<i>` | Italic text |
162
+ | `<u>` | Underlined text |
163
+ | `<span style="...">` | Styled text (font, size, color, background) |
164
+ | `<br>` | Paragraph break |
165
+ | `<img src="data:...">` | Embedded image (base64 data URI) |
166
+ | `<table>`, `<tr>`, `<td>`, `<th>` | Table with borders (nested tables supported) |
167
+ | `<ul>`, `<ol>`, `<li>` | Bulleted / numbered lists |
168
+ | `<div>` | Block container |
169
+
170
+ ## Supported CSS Properties
171
+
172
+ These inline styles are recognized on `<p>`, `<span>`, `<td>`:
173
+
174
+ - `font-family` — mapped to UDF font family
175
+ - `font-size` — supports `px` (converted to pt) and `pt`
176
+ - `font-weight: bold` — bold text
177
+ - `font-style: italic` — italic text
178
+ - `text-decoration: underline` — underlined text
179
+ - `color` — text color (hex, rgb, named colors)
180
+ - `background-color` — text/cell background
181
+ - `text-align` — left, center, right, justify
182
+ - `vertical-align` — top, middle, bottom (table cells)
183
+ - `line-height` — paragraph line spacing
184
+
185
+ ## Writing HTML for UDF Conversion
186
+
187
+ When generating HTML that will be converted to UDF, follow these guidelines:
188
+
189
+ ### Text Formatting
190
+
191
+ ```html
192
+ <p>Normal text</p>
193
+ <p><strong>Bold text</strong></p>
194
+ <p><em>Italic text</em></p>
195
+ <p><strong><em>Bold and italic</em></strong></p>
196
+ <p><span style="font-family:Arial; font-size:14pt; color:#FF0000">Custom styled text</span></p>
197
+ ```
198
+
199
+ ### Images
200
+
201
+ Images must use base64 data URIs. Specify width and height in points:
202
+
203
+ ```html
204
+ <img src="data:image/png;base64,iVBORw0KGgo..." width="200" height="100">
205
+ ```
206
+
207
+ ### Tables
208
+
209
+ ```html
210
+ <table>
211
+ <tr>
212
+ <td>Cell 1</td>
213
+ <td>Cell 2</td>
214
+ </tr>
215
+ <tr>
216
+ <td colspan="2">Merged cell</td>
217
+ </tr>
218
+ </table>
219
+ ```
220
+
221
+ Nested tables are supported:
222
+
223
+ ```html
224
+ <table>
225
+ <tr>
226
+ <td>
227
+ <table>
228
+ <tr><td>Inner cell</td></tr>
229
+ </table>
230
+ </td>
231
+ </tr>
232
+ </table>
233
+ ```
234
+
235
+ ### Lists
236
+
237
+ ```html
238
+ <ol>
239
+ <li>First item</li>
240
+ <li>Second item</li>
241
+ </ol>
242
+
243
+ <ul>
244
+ <li>Bullet point</li>
245
+ <li>Another point</li>
246
+ </ul>
247
+ ```
248
+
249
+ ### Centered / Aligned Text
250
+
251
+ ```html
252
+ <p style="text-align:center">Centered paragraph</p>
253
+ <p style="text-align:right">Right-aligned paragraph</p>
254
+ <p style="text-align:justify">Justified paragraph</p>
255
+ ```
256
+
257
+ ## UDF Format Reference
258
+
259
+ UDF files have this internal structure:
260
+
261
+ ```
262
+ document.udf (ZIP archive)
263
+ └── content.xml
264
+ ```
265
+
266
+ The XML schema:
267
+
268
+ ```xml
269
+ <?xml version="1.0" encoding="UTF-8" ?>
270
+ <template format_id="1.8">
271
+ <content><![CDATA[All document text here]]></content>
272
+ <properties>
273
+ <pageFormat mediaSizeName="1" leftMargin="42.52" rightMargin="28.35"
274
+ topMargin="14.17" bottomMargin="14.17" paperOrientation="1" />
275
+ </properties>
276
+ <elements resolver="hvl-default">
277
+ <paragraph Alignment="0">
278
+ <content startOffset="0" length="5" family="Times New Roman"
279
+ size="12" bold="true" foreground="-16777216" background="-1" />
280
+ </paragraph>
281
+ <table tableName="Sabit" columnCount="2" columnSpans="150,150" border="borderCell">
282
+ <row rowName="row1" rowType="dataRow" border="borderCell">
283
+ <cell colspan="1" align="top" fillColor="16777215"
284
+ border="borderCell" borderSpec="15">
285
+ <paragraph>...</paragraph>
286
+ </cell>
287
+ </row>
288
+ </table>
289
+ </elements>
290
+ </template>
291
+ ```
292
+
293
+ Key details:
294
+
295
+ - **Text offsets** are rune-based (Unicode codepoints), not byte-based
296
+ - **Colors** are signed 32-bit ARGB integers (black = -16777216, white = -1)
297
+ - **Alignment**: 0 = left, 1 = center, 2 = right, 3 = justify
298
+ - **Border spec**: bitmask (top=1, right=2, bottom=4, left=8; all sides=15)
299
+ - **Images**: base64-encoded in `imageData` attribute, `\uFFFC` placeholder in text
300
+ - **Empty paragraphs**: `\u200B` (zero-width space) placeholder in text
301
+
302
+ ## Development
303
+
304
+ ```bash
305
+ npm install
306
+ npm test # run tests
307
+ npm run build # compile TypeScript
308
+ ```
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
4
+ import { htmlToUdf } from '../src/converters/html-to-udf.js';
5
+ import { udfToHtml } from '../src/converters/udf-to-html.js';
6
+ import { udfToMarkdown } from '../src/converters/udf-to-markdown.js';
7
+ import { markdownToUdf } from '../src/converters/markdown-to-udf.js';
8
+ const program = new Command();
9
+ program
10
+ .name('udf-cli')
11
+ .description('Convert between HTML and UYAP UDF file format')
12
+ .version('0.1.0');
13
+ program
14
+ .command('html2udf')
15
+ .description('Convert HTML to UDF format')
16
+ .argument('<input>', 'HTML input file, - for stdin, or raw HTML string')
17
+ .argument('[output]', 'UDF output file (omit for stdout)')
18
+ .action(async (input, output) => {
19
+ try {
20
+ let html;
21
+ if (input === '-') {
22
+ html = readFileSync(0, 'utf-8');
23
+ }
24
+ else if (input.includes('<') || !existsSync(input)) {
25
+ // Treat as raw HTML string if it contains '<' or doesn't exist as a file
26
+ html = input;
27
+ }
28
+ else {
29
+ html = readFileSync(input, 'utf-8');
30
+ }
31
+ const udf = await htmlToUdf(html);
32
+ if (output) {
33
+ writeFileSync(output, udf);
34
+ }
35
+ else {
36
+ process.stdout.write(udf);
37
+ }
38
+ }
39
+ catch (err) {
40
+ console.error(`Error: ${err instanceof Error ? err.message : err}`);
41
+ process.exit(1);
42
+ }
43
+ });
44
+ program
45
+ .command('udf2html')
46
+ .description('Convert UDF to HTML format')
47
+ .argument('<input>', 'UDF input file (use - for stdin)')
48
+ .argument('[output]', 'HTML output file (omit for stdout)')
49
+ .action(async (input, output) => {
50
+ try {
51
+ const udf = input === '-'
52
+ ? readFileSync(0)
53
+ : readFileSync(input);
54
+ const html = await udfToHtml(Buffer.from(udf));
55
+ if (output) {
56
+ writeFileSync(output, html, 'utf-8');
57
+ }
58
+ else {
59
+ process.stdout.write(html);
60
+ }
61
+ }
62
+ catch (err) {
63
+ console.error(`Error: ${err instanceof Error ? err.message : err}`);
64
+ process.exit(1);
65
+ }
66
+ });
67
+ program
68
+ .command('udf2md')
69
+ .description('Convert UDF to Markdown format')
70
+ .argument('<input>', 'UDF input file (use - for stdin)')
71
+ .argument('[output]', 'Markdown output file (omit for stdout)')
72
+ .action(async (input, output) => {
73
+ try {
74
+ const udf = input === '-'
75
+ ? readFileSync(0)
76
+ : readFileSync(input);
77
+ const md = await udfToMarkdown(Buffer.from(udf));
78
+ if (output) {
79
+ writeFileSync(output, md, 'utf-8');
80
+ }
81
+ else {
82
+ process.stdout.write(md);
83
+ }
84
+ }
85
+ catch (err) {
86
+ console.error(`Error: ${err instanceof Error ? err.message : err}`);
87
+ process.exit(1);
88
+ }
89
+ });
90
+ program
91
+ .command('md2udf')
92
+ .description('Convert Markdown to UDF format')
93
+ .argument('<input>', 'Markdown input file, - for stdin, or raw Markdown string')
94
+ .argument('[output]', 'UDF output file (omit for stdout)')
95
+ .action(async (input, output) => {
96
+ try {
97
+ let md;
98
+ if (input === '-') {
99
+ md = readFileSync(0, 'utf-8');
100
+ }
101
+ else if (existsSync(input) && !input.includes('\n')) {
102
+ md = readFileSync(input, 'utf-8');
103
+ }
104
+ else {
105
+ // Treat as raw Markdown string
106
+ md = input;
107
+ }
108
+ const udf = await markdownToUdf(md);
109
+ if (output) {
110
+ writeFileSync(output, udf);
111
+ }
112
+ else {
113
+ process.stdout.write(udf);
114
+ }
115
+ }
116
+ catch (err) {
117
+ console.error(`Error: ${err instanceof Error ? err.message : err}`);
118
+ process.exit(1);
119
+ }
120
+ });
121
+ program.parse();
122
+ //# sourceMappingURL=udf-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"udf-cli.js","sourceRoot":"","sources":["../../bin/udf-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function htmlToUdf(html: string): Promise<Buffer>;
@@ -0,0 +1,7 @@
1
+ import { parseHtml } from '../html/parser.js';
2
+ import { serializeUdf } from '../udf/serializer.js';
3
+ export async function htmlToUdf(html) {
4
+ const doc = parseHtml(html);
5
+ return serializeUdf(doc);
6
+ }
7
+ //# sourceMappingURL=html-to-udf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-to-udf.js","sourceRoot":"","sources":["../../../src/converters/html-to-udf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY;IAC1C,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function markdownToUdf(md: string): Promise<Buffer>;
@@ -0,0 +1,7 @@
1
+ import { parseMarkdown } from '../html/markdown-parser.js';
2
+ import { serializeUdf } from '../udf/serializer.js';
3
+ export async function markdownToUdf(md) {
4
+ const doc = parseMarkdown(md);
5
+ return serializeUdf(doc);
6
+ }
7
+ //# sourceMappingURL=markdown-to-udf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-to-udf.js","sourceRoot":"","sources":["../../../src/converters/markdown-to-udf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAU;IAC5C,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;IAC9B,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function udfToHtml(udf: Buffer): Promise<string>;
@@ -0,0 +1,7 @@
1
+ import { parseUdf } from '../udf/parser.js';
2
+ import { serializeHtml } from '../html/serializer.js';
3
+ export async function udfToHtml(udf) {
4
+ const doc = await parseUdf(udf);
5
+ return serializeHtml(doc);
6
+ }
7
+ //# sourceMappingURL=udf-to-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"udf-to-html.js","sourceRoot":"","sources":["../../../src/converters/udf-to-html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACzC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function udfToMarkdown(udf: Buffer): Promise<string>;
@@ -0,0 +1,7 @@
1
+ import { parseUdf } from '../udf/parser.js';
2
+ import { serializeMarkdown } from '../html/markdown-serializer.js';
3
+ export async function udfToMarkdown(udf) {
4
+ const doc = await parseUdf(udf);
5
+ return serializeMarkdown(doc);
6
+ }
7
+ //# sourceMappingURL=udf-to-markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"udf-to-markdown.js","sourceRoot":"","sources":["../../../src/converters/udf-to-markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Document } from '../model/document.js';
2
+ export declare function parseMarkdown(md: string): Document;
@@ -0,0 +1,172 @@
1
+ import { Alignment, DEFAULT_TEXT_STYLE, createParagraph, createTextRun, createTable, createTableRow, createTableCell, } from '../model/document.js';
2
+ import { DEFAULT_PAGE_FORMAT } from '../model/document.js';
3
+ export function parseMarkdown(md) {
4
+ const lines = md.split('\n');
5
+ const state = { body: [], pos: 0, lines };
6
+ while (state.pos < state.lines.length) {
7
+ const line = state.lines[state.pos];
8
+ // Blank line
9
+ if (line.trim() === '') {
10
+ state.pos++;
11
+ continue;
12
+ }
13
+ // Table (starts with |)
14
+ if (line.trimStart().startsWith('|')) {
15
+ parseTable(state);
16
+ continue;
17
+ }
18
+ // Unordered list
19
+ if (/^\s*[-*+]\s/.test(line)) {
20
+ parseList(state, 'bulleted');
21
+ continue;
22
+ }
23
+ // Ordered list
24
+ if (/^\s*\d+\.\s/.test(line)) {
25
+ parseList(state, 'numbered');
26
+ continue;
27
+ }
28
+ // Heading
29
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
30
+ if (headingMatch) {
31
+ const level = headingMatch[1].length;
32
+ const sizes = { 1: 24, 2: 20, 3: 16, 4: 14, 5: 12, 6: 10 };
33
+ const runs = parseInline(headingMatch[2], { ...DEFAULT_TEXT_STYLE, bold: true, fontSize: sizes[level] || 12 });
34
+ state.body.push(createParagraph({ runs, alignment: Alignment.Left }));
35
+ state.pos++;
36
+ continue;
37
+ }
38
+ // Regular paragraph
39
+ const runs = parseInline(line, { ...DEFAULT_TEXT_STYLE });
40
+ state.body.push(createParagraph({ runs }));
41
+ state.pos++;
42
+ }
43
+ return { pages: { ...DEFAULT_PAGE_FORMAT }, body: state.body };
44
+ }
45
+ function parseInline(text, baseStyle) {
46
+ const runs = [];
47
+ let remaining = text;
48
+ while (remaining.length > 0) {
49
+ // Bold + italic: ***text***
50
+ const boldItalicMatch = remaining.match(/^\*\*\*(.+?)\*\*\*/);
51
+ if (boldItalicMatch) {
52
+ runs.push(createTextRun(boldItalicMatch[1], { ...baseStyle, bold: true, italic: true }));
53
+ remaining = remaining.slice(boldItalicMatch[0].length);
54
+ continue;
55
+ }
56
+ // Bold: **text**
57
+ const boldMatch = remaining.match(/^\*\*(.+?)\*\*/);
58
+ if (boldMatch) {
59
+ runs.push(createTextRun(boldMatch[1], { ...baseStyle, bold: true }));
60
+ remaining = remaining.slice(boldMatch[0].length);
61
+ continue;
62
+ }
63
+ // Italic: *text*
64
+ const italicMatch = remaining.match(/^\*(.+?)\*/);
65
+ if (italicMatch) {
66
+ runs.push(createTextRun(italicMatch[1], { ...baseStyle, italic: true }));
67
+ remaining = remaining.slice(italicMatch[0].length);
68
+ continue;
69
+ }
70
+ // Image: ![alt](data:...)
71
+ const imgMatch = remaining.match(/^!\[([^\]]*)\]\(data:image\/[^;]+;base64,([^)]+)\)/);
72
+ if (imgMatch) {
73
+ runs.push({ type: 'image', data: imgMatch[2], width: 200, height: 150 });
74
+ remaining = remaining.slice(imgMatch[0].length);
75
+ continue;
76
+ }
77
+ // Plain text until next special char
78
+ const plainMatch = remaining.match(/^[^*!\[\\]+/);
79
+ if (plainMatch) {
80
+ runs.push(createTextRun(plainMatch[0], baseStyle));
81
+ remaining = remaining.slice(plainMatch[0].length);
82
+ continue;
83
+ }
84
+ // Escaped char or single special char
85
+ if (remaining.startsWith('\\') && remaining.length > 1) {
86
+ runs.push(createTextRun(remaining[1], baseStyle));
87
+ remaining = remaining.slice(2);
88
+ continue;
89
+ }
90
+ // Consume single char
91
+ runs.push(createTextRun(remaining[0], baseStyle));
92
+ remaining = remaining.slice(1);
93
+ }
94
+ // Merge adjacent runs with same style
95
+ return mergeRuns(runs);
96
+ }
97
+ function mergeRuns(runs) {
98
+ if (runs.length <= 1)
99
+ return runs;
100
+ const merged = [runs[0]];
101
+ for (let i = 1; i < runs.length; i++) {
102
+ const prev = merged[merged.length - 1];
103
+ const curr = runs[i];
104
+ if (prev.type === 'text' && curr.type === 'text' && stylesEqual(prev.style, curr.style)) {
105
+ merged[merged.length - 1] = createTextRun(prev.text + curr.text, prev.style);
106
+ }
107
+ else {
108
+ merged.push(curr);
109
+ }
110
+ }
111
+ return merged;
112
+ }
113
+ function stylesEqual(a, b) {
114
+ return a.fontFamily === b.fontFamily && a.fontSize === b.fontSize &&
115
+ a.bold === b.bold && a.italic === b.italic && a.underline === b.underline &&
116
+ a.color === b.color && a.backgroundColor === b.backgroundColor;
117
+ }
118
+ function parseList(state, type) {
119
+ const pattern = type === 'numbered' ? /^(\s*)\d+\.\s(.+)$/ : /^(\s*)[-*+]\s(.+)$/;
120
+ let listId = 1;
121
+ while (state.pos < state.lines.length) {
122
+ const line = state.lines[state.pos];
123
+ const match = line.match(pattern);
124
+ if (!match)
125
+ break;
126
+ const indent = match[1].length;
127
+ const level = Math.floor(indent / 2);
128
+ const content = match[2];
129
+ const runs = parseInline(content, { ...DEFAULT_TEXT_STYLE });
130
+ const list = {
131
+ type,
132
+ level,
133
+ listId,
134
+ ...(type === 'numbered' ? { numberType: 'NUMBER_TYPE_NUMBER_DOT' } : { bulletType: 'BULLET_TYPE_ELLIPSE' }),
135
+ };
136
+ state.body.push(createParagraph({ runs, list }));
137
+ state.pos++;
138
+ }
139
+ }
140
+ function parseTable(state) {
141
+ const rows = [];
142
+ while (state.pos < state.lines.length) {
143
+ const line = state.lines[state.pos].trim();
144
+ if (!line.startsWith('|'))
145
+ break;
146
+ // Parse cells: split by | and trim
147
+ const cells = line.split('|').slice(1, -1).map(c => c.trim());
148
+ // Skip separator row (| --- | :---: | etc.)
149
+ if (cells.every(c => /^:?-{2,}:?$/.test(c))) {
150
+ state.pos++;
151
+ continue;
152
+ }
153
+ rows.push(cells);
154
+ state.pos++;
155
+ }
156
+ if (rows.length === 0)
157
+ return;
158
+ const columnCount = Math.max(...rows.map(r => r.length));
159
+ const columnWidths = Array(columnCount).fill(Math.round(300 / columnCount));
160
+ const tableRows = rows.map((cells, rowIdx) => {
161
+ const tableCells = [];
162
+ for (let i = 0; i < columnCount; i++) {
163
+ const cellText = cells[i] || '';
164
+ const runs = parseInline(cellText, { ...DEFAULT_TEXT_STYLE });
165
+ const para = createParagraph({ runs });
166
+ tableCells.push(createTableCell([para]));
167
+ }
168
+ return createTableRow(tableCells, { name: `row${rowIdx + 1}` });
169
+ });
170
+ state.body.push(createTable(tableRows, columnWidths));
171
+ }
172
+ //# sourceMappingURL=markdown-parser.js.map