hwpkit-dev 0.0.3 → 0.0.5
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/ .npmignore +1 -0
- package/README.md +8 -8
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +573 -230
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +573 -230
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/decoders/hwp/HwpScanner.ts +174 -57
- package/src/decoders/hwpx/HwpxDecoder.ts +23 -12
- package/src/encoders/docx/DocxEncoder.ts +49 -4
- package/src/encoders/hwp/HwpEncoder.ts +309 -163
- package/src/encoders/hwpx/HwpxEncoder.ts +249 -103
- package/src/model/doc-props.ts +5 -5
- package/src/model/doc-tree.ts +2 -2
- package/test-styling.ts +0 -210
package/src/model/doc-props.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type Align = 'left' | 'center' | 'right' | 'justify';
|
|
1
|
+
export type Align = 'left' | 'center' | 'right' | 'justify' | 'distribute' | 'distribute_space';
|
|
2
2
|
|
|
3
3
|
// ─── 이미지 배치 ────────────────────────────────────────────
|
|
4
4
|
export type ImgWrap = 'inline' | 'square' | 'tight' | 'through' | 'none' | 'behind' | 'front' | 'topAndBottom';
|
|
@@ -37,12 +37,11 @@ export interface TextProps {
|
|
|
37
37
|
pt?: number;
|
|
38
38
|
color?: string;
|
|
39
39
|
bg?: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface ParaProps {
|
|
40
|
+
}export interface ParaProps {
|
|
43
41
|
align?: Align;
|
|
44
42
|
heading?: Heading;
|
|
45
43
|
styleId?: string; // DOCX pStyle styleId (e.g. "Heading1", "TOC1")
|
|
44
|
+
hwpStyleId?: number; // HWP native style index (0=바탕글, 1=본문, ...)
|
|
46
45
|
indentPt?: number; // 문단 왼쪽 전체 들여쓰기 (pt) — OWPML hc:left
|
|
47
46
|
indentRightPt?: number; // 문단 오른쪽 전체 들여쓰기 (pt) — OWPML hc:right
|
|
48
47
|
firstLineIndentPt?: number; // 첫 줄 들여쓰기 (pt, 음수=내어쓰기) — OWPML hc:indent
|
|
@@ -54,8 +53,9 @@ export interface ParaProps {
|
|
|
54
53
|
listLv?: number;
|
|
55
54
|
listOrd?: boolean;
|
|
56
55
|
listMark?: string;
|
|
56
|
+
verAlign?: 'baseline' | 'top' | 'center' | 'bottom';
|
|
57
|
+
lineWrap?: 'break' | 'squeeze' | 'keep';
|
|
57
58
|
}
|
|
58
|
-
|
|
59
59
|
export interface Stroke {
|
|
60
60
|
kind: StrokeKind;
|
|
61
61
|
pt: number;
|
package/src/model/doc-tree.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface PbNode { tag: 'pb' }
|
|
|
14
14
|
|
|
15
15
|
export interface PageNumNode {
|
|
16
16
|
tag: 'pagenum';
|
|
17
|
-
format?: 'decimal' | 'roman' | 'romanCaps';
|
|
17
|
+
format?: 'decimal' | 'roman' | 'romanCaps' | 'total';
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface ImgNode {
|
|
@@ -44,7 +44,7 @@ export interface LinkNode {
|
|
|
44
44
|
export interface ParaNode {
|
|
45
45
|
tag: 'para';
|
|
46
46
|
props: ParaProps;
|
|
47
|
-
kids: (SpanNode | ImgNode | LinkNode | GridNode)[];
|
|
47
|
+
kids: (SpanNode | ImgNode | LinkNode | GridNode | PageNumNode)[];
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// ─── 표(Grid) 노드 ─────────────────────────────────────────
|
package/test-styling.ts
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HWP 인코더 스타일 기능 테스트
|
|
3
|
-
*
|
|
4
|
-
* 테스트 항목:
|
|
5
|
-
* 1. 표 위치 배치 (align: left/center/right)
|
|
6
|
-
* 2. 표 선 스타일 (각 변별 선 종류, 굵기, 색상)
|
|
7
|
-
* 3. 텍스트 스타일 (글꼴, bold, italic, underline, 글색, 형광펜)
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { buildRoot, buildSheet, buildGrid, buildRow, buildCell, buildPara, buildSpan } from './src/model/builders';
|
|
11
|
-
import { HwpEncoder } from './src/encoders/hwp/HwpEncoder';
|
|
12
|
-
import { HwpxEncoder } from './src/encoders/hwpx/HwpxEncoder';
|
|
13
|
-
import fs from 'fs';
|
|
14
|
-
|
|
15
|
-
// 표 정렬 및 선 스타일 테스트 문서
|
|
16
|
-
const doc = buildRoot(
|
|
17
|
-
{ title: 'HWP 인코더 스타일 테스트 문서' },
|
|
18
|
-
[
|
|
19
|
-
buildSheet([
|
|
20
|
-
// 제목
|
|
21
|
-
buildPara([
|
|
22
|
-
buildSpan('HWP 인코더 스타일 기능 테스트', { b: true, pt: 18 }),
|
|
23
|
-
]),
|
|
24
|
-
|
|
25
|
-
// 1. 표 정렬 테스트 - 왼쪽 정렬
|
|
26
|
-
buildPara([buildSpan('1. 표 정렬: 왼쪽 정렬', { b: true })]),
|
|
27
|
-
buildGrid(
|
|
28
|
-
[
|
|
29
|
-
buildRow([
|
|
30
|
-
buildCell([buildPara([buildSpan('왼쪽 정렬 표', { b: true })])]),
|
|
31
|
-
buildCell([buildPara([buildSpan('데이터', {})])]),
|
|
32
|
-
]),
|
|
33
|
-
buildRow([
|
|
34
|
-
buildCell([buildPara([buildSpan('셀 1', {})])]),
|
|
35
|
-
buildCell([buildPara([buildSpan('셀 2', {})])]),
|
|
36
|
-
]),
|
|
37
|
-
],
|
|
38
|
-
{
|
|
39
|
-
align: 'left',
|
|
40
|
-
defaultStroke: { kind: 'solid', pt: 1, color: '000000' },
|
|
41
|
-
colWidths: [100, 100]
|
|
42
|
-
}
|
|
43
|
-
),
|
|
44
|
-
|
|
45
|
-
// 2. 표 정렬 테스트 - 중앙 정렬
|
|
46
|
-
buildPara([buildSpan('2. 표 정렬: 중앙 정렬', { b: true })]),
|
|
47
|
-
buildGrid(
|
|
48
|
-
[
|
|
49
|
-
buildRow([
|
|
50
|
-
buildCell([buildPara([buildSpan('중앙 정렬 표', { b: true })])]),
|
|
51
|
-
buildCell([buildPara([buildSpan('데이터', {})])]),
|
|
52
|
-
]),
|
|
53
|
-
buildRow([
|
|
54
|
-
buildCell([buildPara([buildSpan('셀 1', {})])]),
|
|
55
|
-
buildCell([buildPara([buildSpan('셀 2', {})])]),
|
|
56
|
-
]),
|
|
57
|
-
],
|
|
58
|
-
{
|
|
59
|
-
align: 'center',
|
|
60
|
-
defaultStroke: { kind: 'solid', pt: 1, color: '000000' },
|
|
61
|
-
colWidths: [100, 100]
|
|
62
|
-
}
|
|
63
|
-
),
|
|
64
|
-
|
|
65
|
-
// 3. 표 정렬 테스트 - 오른쪽 정렬
|
|
66
|
-
buildPara([buildSpan('3. 표 정렬: 오른쪽 정렬', { b: true })]),
|
|
67
|
-
buildGrid(
|
|
68
|
-
[
|
|
69
|
-
buildRow([
|
|
70
|
-
buildCell([buildPara([buildSpan('오른쪽 정렬 표', { b: true })])]),
|
|
71
|
-
buildCell([buildPara([buildSpan('데이터', {})])]),
|
|
72
|
-
]),
|
|
73
|
-
buildRow([
|
|
74
|
-
buildCell([buildPara([buildSpan('셀 1', {})])]),
|
|
75
|
-
buildCell([buildPara([buildSpan('셀 2', {})])]),
|
|
76
|
-
]),
|
|
77
|
-
],
|
|
78
|
-
{
|
|
79
|
-
align: 'right',
|
|
80
|
-
defaultStroke: { kind: 'solid', pt: 1, color: '000000' },
|
|
81
|
-
colWidths: [100, 100]
|
|
82
|
-
}
|
|
83
|
-
),
|
|
84
|
-
|
|
85
|
-
// 4. 표 선 스타일 테스트 - 각 변별 다른 스타일
|
|
86
|
-
buildPara([buildSpan('4. 표 선 스타일: 각 변별 다른 스타일', { b: true })]),
|
|
87
|
-
buildGrid(
|
|
88
|
-
[
|
|
89
|
-
buildRow([
|
|
90
|
-
buildCell([buildPara([buildSpan('상단', {})])], {
|
|
91
|
-
top: { kind: 'double', pt: 2, color: '0000FF' }
|
|
92
|
-
}),
|
|
93
|
-
buildCell([buildPara([buildSpan('하단', {})])], {
|
|
94
|
-
bot: { kind: 'dash', pt: 1.5, color: 'FF0000' }
|
|
95
|
-
}),
|
|
96
|
-
]),
|
|
97
|
-
buildRow([
|
|
98
|
-
buildCell([buildPara([buildSpan('좌측', {})])], {
|
|
99
|
-
left: { kind: 'dot', pt: 1, color: '00FF00' }
|
|
100
|
-
}),
|
|
101
|
-
buildCell([buildPara([buildSpan('우측', {})])], {
|
|
102
|
-
right: { kind: 'solid', pt: 3, color: 'FFFF00' }
|
|
103
|
-
}),
|
|
104
|
-
]),
|
|
105
|
-
],
|
|
106
|
-
{ defaultStroke: { kind: 'solid', pt: 0.5, color: '808080' } }
|
|
107
|
-
),
|
|
108
|
-
|
|
109
|
-
// 5. 텍스트 스타일 테스트 - 글꼴
|
|
110
|
-
buildPara([buildSpan('5. 글꼴 테스트', { b: true })]),
|
|
111
|
-
buildPara([
|
|
112
|
-
buildSpan('배탕체', { font: 'Batang' }),
|
|
113
|
-
buildSpan(' + ', {}),
|
|
114
|
-
buildSpan('맑은고딕', { font: 'Malgun Gothic' }),
|
|
115
|
-
buildSpan(' + ', {}),
|
|
116
|
-
buildSpan('굴림체', { font: 'GulimChe' }),
|
|
117
|
-
]),
|
|
118
|
-
|
|
119
|
-
// 6. 텍스트 스타일 테스트 - 글자 모양
|
|
120
|
-
buildPara([buildSpan('6. 글자 모양 테스트', { b: true })]),
|
|
121
|
-
buildPara([
|
|
122
|
-
buildSpan('볼드', { b: true }),
|
|
123
|
-
buildSpan(' + ', {}),
|
|
124
|
-
buildSpan('이탤릭', { i: true }),
|
|
125
|
-
buildSpan(' + ', {}),
|
|
126
|
-
buildSpan('밑줄', { u: true }),
|
|
127
|
-
buildSpan(' + ', {}),
|
|
128
|
-
buildSpan('취소선', { s: true }),
|
|
129
|
-
]),
|
|
130
|
-
|
|
131
|
-
// 7. 텍스트 스타일 테스트 - 글색
|
|
132
|
-
buildPara([buildSpan('7. 글색 테스트', { b: true })]),
|
|
133
|
-
buildPara([
|
|
134
|
-
buildSpan('빨강', { color: 'FF0000' }),
|
|
135
|
-
buildSpan(' + ', {}),
|
|
136
|
-
buildSpan('파랑', { color: '0000FF' }),
|
|
137
|
-
buildSpan(' + ', {}),
|
|
138
|
-
buildSpan('초록', { color: '008000' }),
|
|
139
|
-
]),
|
|
140
|
-
|
|
141
|
-
// 8. 텍스트 스타일 테스트 - 형광펜 (배경색)
|
|
142
|
-
buildPara([buildSpan('8. 형광펜 테스트', { b: true })]),
|
|
143
|
-
buildPara([
|
|
144
|
-
buildSpan('노란 형광펜', { bg: 'FFFF00' }),
|
|
145
|
-
buildSpan(' + ', {}),
|
|
146
|
-
buildSpan('초록 형광펜', { bg: 'CCFFCC' }),
|
|
147
|
-
buildSpan(' + ', {}),
|
|
148
|
-
buildSpan('파랑 형광펜', { bg: 'CCCCFF' }),
|
|
149
|
-
]),
|
|
150
|
-
|
|
151
|
-
// 9. 복합 스타일 테스트
|
|
152
|
-
buildPara([buildSpan('9. 복합 스타일 테스트', { b: true })]),
|
|
153
|
-
buildPara([
|
|
154
|
-
buildSpan('볼드 + 빨강 + 노란 형광펜', {
|
|
155
|
-
b: true,
|
|
156
|
-
color: 'FF0000',
|
|
157
|
-
bg: 'FFFF00'
|
|
158
|
-
}),
|
|
159
|
-
]),
|
|
160
|
-
buildPara([
|
|
161
|
-
buildSpan('이탤릭 + 파랑 + 굴림체', {
|
|
162
|
-
i: true,
|
|
163
|
-
color: '0000FF',
|
|
164
|
-
font: 'GulimChe'
|
|
165
|
-
}),
|
|
166
|
-
]),
|
|
167
|
-
]),
|
|
168
|
-
]
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
async function runTest() {
|
|
172
|
-
console.log('=== HWP 인코더 스타일 테스트 ===\n');
|
|
173
|
-
|
|
174
|
-
// HWP 인코딩
|
|
175
|
-
console.log('HWP 인코딩 중...');
|
|
176
|
-
const hwpEncoder = new HwpEncoder();
|
|
177
|
-
const hwpOutcome = await hwpEncoder.encode(doc);
|
|
178
|
-
if (hwpOutcome.ok) {
|
|
179
|
-
fs.writeFileSync('test-styling.hwp', hwpOutcome.data);
|
|
180
|
-
console.log('✓ HWP 파일 생성 완료: test-styling.hwp');
|
|
181
|
-
console.log(` 파일 크기: ${hwpOutcome.data.length} bytes\n`);
|
|
182
|
-
} else {
|
|
183
|
-
console.error('✗ HWP 인코딩 실패:', hwpOutcome.err);
|
|
184
|
-
process.exit(1);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// HWPX 인코딩
|
|
188
|
-
console.log('HWPX 인코딩 중...');
|
|
189
|
-
const hwpxEncoder = new HwpxEncoder();
|
|
190
|
-
const hwpxOutcome = await hwpxEncoder.encode(doc);
|
|
191
|
-
if (hwpxOutcome.ok) {
|
|
192
|
-
fs.writeFileSync('test-styling.hwpx', hwpxOutcome.data);
|
|
193
|
-
console.log('✓ HWPX 파일 생성 완료: test-styling.hwpx');
|
|
194
|
-
console.log(` 파일 크기: ${hwpxOutcome.data.length} bytes\n`);
|
|
195
|
-
} else {
|
|
196
|
-
console.error('✗ HWPX 인코딩 실패:', hwpxOutcome.err);
|
|
197
|
-
process.exit(1);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
console.log('=== 테스트 완료 ===');
|
|
201
|
-
console.log('생성된 파일을 HWP 뷰어로 열어 다음을 확인하세요:');
|
|
202
|
-
console.log(' 1. 표 정렬: 왼쪽/중앙/오른쪽 정렬이 적용되는지');
|
|
203
|
-
console.log(' 2. 표 선 스타일: 각 변별 다른 선 종류/굵기/색상이 적용되는지');
|
|
204
|
-
console.log(' 3. 글꼴: 배탕체/맑은고딕/굴림체가 적용되는지');
|
|
205
|
-
console.log(' 4. 글자 모양: bold/italic/underline/strikethrough 가 적용되는지');
|
|
206
|
-
console.log(' 5. 글색: 빨강/파랑/초록이 적용되는지');
|
|
207
|
-
console.log(' 6. 형광펜: 노랑/초록/파랑 배경색이 적용되는지');
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
runTest().catch(console.error);
|