@s8fy/emf2svg 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.
- package/LICENSE +8 -0
- package/README.md +118 -0
- package/dist/index.cjs +3756 -0
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +3752 -0
- package/dist/index.umd.js +3760 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
PolyForm Noncommercial License 1.0.0
|
|
2
|
+
https://polyformproject.org/licenses/noncommercial/1.0.0
|
|
3
|
+
|
|
4
|
+
Required Notice: Copyright (c) 2025-PRESENT hustcer
|
|
5
|
+
|
|
6
|
+
This package is source-available, not open source. No commercial use is granted
|
|
7
|
+
to third parties under this package's default license unless separately
|
|
8
|
+
licensed.
|
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# @s8fy/emf2svg
|
|
2
|
+
|
|
3
|
+
Pure TypeScript EMF (Enhanced Metafile) and WMF (Windows Metafile) to SVG converter. It has zero runtime dependencies and runs in browsers and Node.js.
|
|
4
|
+
|
|
5
|
+
The package declares Node.js **22.12+**, provides ESM/CommonJS TypeScript declarations, and needs no DOM for conversion. All four exported functions are synchronous.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @s8fy/emf2svg
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @s8fy/emf2svg
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Basic conversion
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { emf2svg, isEmf, isWmf, wmf2svg } from '@s8fy/emf2svg'
|
|
21
|
+
|
|
22
|
+
export function convertMetafile(buffer: ArrayBuffer | Uint8Array): string {
|
|
23
|
+
if (isEmf(buffer)) return emf2svg(buffer)
|
|
24
|
+
if (isWmf(buffer)) return wmf2svg(buffer)
|
|
25
|
+
throw new Error('Unsupported metafile header')
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Node.js
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { readFileSync, writeFileSync } from 'node:fs'
|
|
33
|
+
import { emf2svg } from '@s8fy/emf2svg'
|
|
34
|
+
|
|
35
|
+
const emfData = readFileSync('diagram.emf')
|
|
36
|
+
const svg = emf2svg(emfData)
|
|
37
|
+
writeFileSync('diagram.svg', svg)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Browser (fetch)
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { emf2svg } from '@s8fy/emf2svg'
|
|
44
|
+
|
|
45
|
+
const res = await fetch('/assets/chart.emf')
|
|
46
|
+
if (!res.ok) throw new Error(`Metafile request failed: ${res.status}`)
|
|
47
|
+
const buffer = await res.arrayBuffer()
|
|
48
|
+
const svg = emf2svg(buffer)
|
|
49
|
+
const image = document.createElement('img')
|
|
50
|
+
image.alt = 'Converted chart'
|
|
51
|
+
const url = URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }))
|
|
52
|
+
image.onload = image.onerror = () => URL.revokeObjectURL(url)
|
|
53
|
+
image.src = url
|
|
54
|
+
document.body.append(image)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## API
|
|
58
|
+
|
|
59
|
+
### `emf2svg(buffer: ArrayBuffer | Uint8Array): string`
|
|
60
|
+
|
|
61
|
+
Convert an EMF buffer to a complete SVG XML string.
|
|
62
|
+
|
|
63
|
+
- **buffer** — EMF file data
|
|
64
|
+
- **Returns** — SVG string with `xmlns`, `viewBox`, and all rendered elements
|
|
65
|
+
- **Throws** — `Error` if the buffer is not a valid EMF file or has zero-size bounds
|
|
66
|
+
|
|
67
|
+
### `isEmf(buffer: ArrayBuffer | Uint8Array): boolean`
|
|
68
|
+
|
|
69
|
+
Check the minimum 88-byte header, magic number (`' EMF'` at offset 40), and record type. This is a format probe, not validation of every record; conversion may still fail or return partial output.
|
|
70
|
+
|
|
71
|
+
### `wmf2svg(buffer: ArrayBuffer | Uint8Array): string`
|
|
72
|
+
|
|
73
|
+
Convert a standard or Aldus placeable WMF buffer to SVG. The WMF path covers the common vector records used by legacy Office clipart and templates, including lines, rectangles, ellipses, polygons, text, pens, and brushes.
|
|
74
|
+
|
|
75
|
+
### `isWmf(buffer: ArrayBuffer | Uint8Array): boolean`
|
|
76
|
+
|
|
77
|
+
Check whether a buffer has a supported standard or Aldus placeable WMF header.
|
|
78
|
+
|
|
79
|
+
Pass a Node `Buffer` directly: it is a `Uint8Array`, and its offset/length are respected. Do not pass `buffer.buffer` alone for a sliced Buffer, which may include unrelated bytes. Catch conversion errors for invalid/truncated input; format detection does not guarantee complete rendering.
|
|
80
|
+
|
|
81
|
+
## Supported EMF Records
|
|
82
|
+
|
|
83
|
+
| Category | Records |
|
|
84
|
+
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
85
|
+
| Control | `HEADER`, `EOF`, `COMMENT` |
|
|
86
|
+
| State | `SAVEDC`, `RESTOREDC`, `SETWINDOWEXTEX`, `SETWINDOWORGEX`, `SETVIEWPORTEXTEX`, `SETVIEWPORTORGEX`, `SETTEXTCOLOR`, `SETTEXTALIGN`, `SETBKMODE`, `SETBKCOLOR`, `SETPOLYFILLMODE`, `SETMITERLIMIT`, `SETMAPMODE` |
|
|
87
|
+
| Object | `SELECTOBJECT`, `DELETEOBJECT`, `CREATEBRUSHINDIRECT`, `CREATEPEN`, `EXTCREATEPEN`, `EXTCREATEFONTINDIRECTW` |
|
|
88
|
+
| Transform | `SETWORLDTRANSFORM`, `MODIFYWORLDTRANSFORM` |
|
|
89
|
+
| Drawing | `MOVETOEX`, `LINETO`, `RECTANGLE`, `ELLIPSE`, `ROUNDRECT`, `POLYGON16`, `POLYLINE16`, `POLYBEZIER16`, `POLYBEZIERTO16`, `POLYLINETO16`, `POLYPOLYGON16`, `POLYGON`, `POLYLINE`, `POLYBEZIER`, `POLYBEZIERTO`, `POLYLINETO` |
|
|
90
|
+
| Path | `BEGINPATH`, `ENDPATH`, `CLOSEFIGURE`, `FILLPATH`, `STROKEPATH`, `STROKEANDFILLPATH`, `SELECTCLIPPATH` |
|
|
91
|
+
| Text | `EXTTEXTOUTW` |
|
|
92
|
+
| Bitmap | `STRETCHDIBITS`, `BITBLT`, `ALPHABLEND`, `TRANSPARENTBLT` |
|
|
93
|
+
| Arc | `ARC`, `ARCTO`, `ANGLEARC`, `PIE`, `CHORD`, `SETARCDIRECTION` |
|
|
94
|
+
| Gradient | `GRADIENTFILL` |
|
|
95
|
+
|
|
96
|
+
The table summarizes implemented record families, not full GDI compatibility. Path abort and rectangle clipping are also handled (`ABORTPATH`, `INTERSECTCLIPRECT`). Unrecognized/unimplemented records are skipped, so files with unsupported records can produce partial output.
|
|
97
|
+
|
|
98
|
+
## Build Formats
|
|
99
|
+
|
|
100
|
+
| Format | File | Global |
|
|
101
|
+
| ------ | ------------------- | ---------------- |
|
|
102
|
+
| ESM | `dist/index.js` | — |
|
|
103
|
+
| CJS | `dist/index.cjs` | — |
|
|
104
|
+
| UMD | `dist/index.umd.js` | `window.emf2svg` |
|
|
105
|
+
|
|
106
|
+
Production packages do not include source maps.
|
|
107
|
+
|
|
108
|
+
## Limitations
|
|
109
|
+
|
|
110
|
+
- **EMF+ records** are detected but not rendered (treated as comments)
|
|
111
|
+
- **WMF** support targets common legacy Office vector records; unsupported records are skipped and may produce partial output
|
|
112
|
+
- **GDI raster operations** (`dwRop`) are ignored; bitmaps are rendered as-is
|
|
113
|
+
- **Complex clipping** (region-based) is only partially supported
|
|
114
|
+
- Embedded **DIB bitmaps** are repacked as BMP data URIs; PNG/JPEG payloads are detected and passed through directly
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
The default license is `PolyForm-Noncommercial-1.0.0`. Commercial use requires a separate commercial license.
|