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.
- package/README.md +308 -0
- package/dist/bin/udf-cli.d.ts +2 -0
- package/dist/bin/udf-cli.js +122 -0
- package/dist/bin/udf-cli.js.map +1 -0
- package/dist/src/converters/html-to-udf.d.ts +1 -0
- package/dist/src/converters/html-to-udf.js +7 -0
- package/dist/src/converters/html-to-udf.js.map +1 -0
- package/dist/src/converters/markdown-to-udf.d.ts +1 -0
- package/dist/src/converters/markdown-to-udf.js +7 -0
- package/dist/src/converters/markdown-to-udf.js.map +1 -0
- package/dist/src/converters/udf-to-html.d.ts +1 -0
- package/dist/src/converters/udf-to-html.js +7 -0
- package/dist/src/converters/udf-to-html.js.map +1 -0
- package/dist/src/converters/udf-to-markdown.d.ts +1 -0
- package/dist/src/converters/udf-to-markdown.js +7 -0
- package/dist/src/converters/udf-to-markdown.js.map +1 -0
- package/dist/src/html/markdown-parser.d.ts +2 -0
- package/dist/src/html/markdown-parser.js +172 -0
- package/dist/src/html/markdown-parser.js.map +1 -0
- package/dist/src/html/markdown-serializer.d.ts +2 -0
- package/dist/src/html/markdown-serializer.js +146 -0
- package/dist/src/html/markdown-serializer.js.map +1 -0
- package/dist/src/html/parser.d.ts +2 -0
- package/dist/src/html/parser.js +517 -0
- package/dist/src/html/parser.js.map +1 -0
- package/dist/src/html/serializer.d.ts +6 -0
- package/dist/src/html/serializer.js +259 -0
- package/dist/src/html/serializer.js.map +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/model/document.d.ts +99 -0
- package/dist/src/model/document.js +88 -0
- package/dist/src/model/document.js.map +1 -0
- package/dist/src/udf/cdata-builder.d.ts +14 -0
- package/dist/src/udf/cdata-builder.js +59 -0
- package/dist/src/udf/cdata-builder.js.map +1 -0
- package/dist/src/udf/parser.d.ts +2 -0
- package/dist/src/udf/parser.js +293 -0
- package/dist/src/udf/parser.js.map +1 -0
- package/dist/src/udf/serializer.d.ts +5 -0
- package/dist/src/udf/serializer.js +228 -0
- package/dist/src/udf/serializer.js.map +1 -0
- package/dist/src/utils/color.d.ts +9 -0
- package/dist/src/utils/color.js +87 -0
- package/dist/src/utils/color.js.map +1 -0
- package/dist/src/utils/style.d.ts +18 -0
- package/dist/src/utils/style.js +55 -0
- package/dist/src/utils/style.js.map +1 -0
- 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
|
+
- `` 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,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 @@
|
|
|
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 @@
|
|
|
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,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: 
|
|
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
|