@hidemikimura/receipt-html-to-pdf 0.2.1 → 0.4.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/CHANGELOG.md +45 -0
- package/README.md +20 -11
- package/dist/receipt-html-to-pdf.min.js +17 -16
- package/dist/receipt-html-to-pdf.min.js.map +4 -4
- package/examples/cdn.html +2 -2
- package/package.json +1 -1
- package/skills/receipt-html-to-pdf/SKILL.md +30 -5
- package/skills/receipt-html-to-pdf/references/receipt-format.md +3 -1
- package/src/font/gsub.js +229 -0
- package/src/index.js +26 -1
- package/src/pacer.js +50 -0
- package/src/page.js +195 -22
- package/src/paginate.js +19 -0
- package/src/pdf/content.js +44 -2
- package/src/pdf/outline.js +103 -0
- package/src/pdf/shading.js +113 -0
- package/src/walker/gradient.js +193 -0
- package/src/walker/image.js +77 -0
- package/src/walker/svg-path.js +342 -0
- package/src/walker/text.js +29 -2
- package/src/walker/walk.js +330 -24
- package/types/font/gsub.d.ts +47 -0
- package/types/index.d.ts +38 -1
- package/types/pacer.d.ts +11 -0
- package/types/page.d.ts +6 -1
- package/types/paginate.d.ts +1 -0
- package/types/pdf/content.d.ts +18 -1
- package/types/pdf/outline.d.ts +41 -0
- package/types/pdf/shading.d.ts +44 -0
- package/types/walker/gradient.d.ts +25 -0
- package/types/walker/image.d.ts +36 -0
- package/types/walker/svg-path.d.ts +31 -0
- package/types/walker/text.d.ts +4 -0
- package/types/walker/walk.d.ts +72 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {{page: number, x: number, y: number}} DestPoint 飛び先(0 始まりのページ番号と、そのページの PDF 座標)
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* リンク注釈を作る。
|
|
6
|
+
* @param {import('./writer.js').PdfWriter} writer
|
|
7
|
+
* @param {{x: number, y: number, w: number, h: number}} rect PDF 座標(左下原点)
|
|
8
|
+
* @param {{uri: string}|{dest: import('./writer.js').PdfValue}} action
|
|
9
|
+
* @returns {import('./writer.js').Ref}
|
|
10
|
+
*/
|
|
11
|
+
export function buildLinkAnnot(writer: import("./writer.js").PdfWriter, rect: {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
w: number;
|
|
15
|
+
h: number;
|
|
16
|
+
}, action: {
|
|
17
|
+
uri: string;
|
|
18
|
+
} | {
|
|
19
|
+
dest: import("./writer.js").PdfValue;
|
|
20
|
+
}): import("./writer.js").Ref;
|
|
21
|
+
/**
|
|
22
|
+
* 見出しの並びから、レベルに応じた木構造のしおりを作り、カタログに入れる参照を返す。
|
|
23
|
+
* 飛び先が解決できない見出しは飛ばす。
|
|
24
|
+
*
|
|
25
|
+
* @param {import('./writer.js').PdfWriter} writer
|
|
26
|
+
* @param {{level: number, text: string, dest: import('./writer.js').PdfValue|null}[]} entries
|
|
27
|
+
* @returns {import('./writer.js').Ref|null}
|
|
28
|
+
*/
|
|
29
|
+
export function buildOutline(writer: import("./writer.js").PdfWriter, entries: {
|
|
30
|
+
level: number;
|
|
31
|
+
text: string;
|
|
32
|
+
dest: import("./writer.js").PdfValue | null;
|
|
33
|
+
}[]): import("./writer.js").Ref | null;
|
|
34
|
+
/**
|
|
35
|
+
* 飛び先(0 始まりのページ番号と、そのページの PDF 座標)
|
|
36
|
+
*/
|
|
37
|
+
export type DestPoint = {
|
|
38
|
+
page: number;
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 軸シェーディングの辞書を作る。座標は PDF 座標(pt)。
|
|
3
|
+
*
|
|
4
|
+
* @param {import('./writer.js').PdfWriter} writer
|
|
5
|
+
* @param {{x0: number, y0: number, x1: number, y1: number}} coords
|
|
6
|
+
* @param {GradientStop[]} stops
|
|
7
|
+
* @param {'rgb'|'gray'} space
|
|
8
|
+
* @returns {import('./writer.js').Ref}
|
|
9
|
+
*/
|
|
10
|
+
export function buildAxialShading(writer: import("./writer.js").PdfWriter, coords: {
|
|
11
|
+
x0: number;
|
|
12
|
+
y0: number;
|
|
13
|
+
x1: number;
|
|
14
|
+
y1: number;
|
|
15
|
+
}, stops: GradientStop[], space: "rgb" | "gray"): import("./writer.js").Ref;
|
|
16
|
+
/**
|
|
17
|
+
* 色止めのアルファが一定ならその値、そうでなければ null。
|
|
18
|
+
* @param {GradientStop[]} stops
|
|
19
|
+
* @returns {number|null}
|
|
20
|
+
*/
|
|
21
|
+
export function uniformAlpha(stops: GradientStop[]): number | null;
|
|
22
|
+
/**
|
|
23
|
+
* アルファが変化するグラデーション用の輝度ソフトマスクを作る。
|
|
24
|
+
* グレースケールのシェーディングを描くフォーム XObject を /SMask に入れた ExtGState を返す。
|
|
25
|
+
*
|
|
26
|
+
* @param {import('./writer.js').PdfWriter} writer
|
|
27
|
+
* @param {{x0: number, y0: number, x1: number, y1: number}} coords PDF 座標
|
|
28
|
+
* @param {GradientStop[]} stops
|
|
29
|
+
* @param {{x: number, y: number, w: number, h: number}} bbox マスクを塗る範囲(PDF 座標)
|
|
30
|
+
* @param {number} groupAlpha 要素から継承した不透明度(グラデーション全体に掛かる)
|
|
31
|
+
* @returns {Promise<import('./writer.js').Ref>} ExtGState の参照
|
|
32
|
+
*/
|
|
33
|
+
export function buildAlphaMaskGState(writer: import("./writer.js").PdfWriter, coords: {
|
|
34
|
+
x0: number;
|
|
35
|
+
y0: number;
|
|
36
|
+
x1: number;
|
|
37
|
+
y1: number;
|
|
38
|
+
}, stops: GradientStop[], bbox: {
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
w: number;
|
|
42
|
+
h: number;
|
|
43
|
+
}, groupAlpha: number): Promise<import("./writer.js").Ref>;
|
|
44
|
+
export type GradientStop = import("../walker/gradient.js").GradientStop;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {{t: number, color: import('../units.js').Rgba}} GradientStop
|
|
3
|
+
* @typedef {{x0: number, y0: number, x1: number, y1: number, stops: GradientStop[]}} LinearGradient
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* computed の background-image が単一の linear-gradient ならそれを解析する。
|
|
7
|
+
* 対応しない書式(repeating / radial / conic / 複数レイヤー)は null。
|
|
8
|
+
*
|
|
9
|
+
* @param {string} value computed の background-image
|
|
10
|
+
* @param {number} width 箱の幅(px)
|
|
11
|
+
* @param {number} height 箱の高さ(px)
|
|
12
|
+
* @returns {LinearGradient|null}
|
|
13
|
+
*/
|
|
14
|
+
export function parseLinearGradient(value: string, width: number, height: number): LinearGradient | null;
|
|
15
|
+
export type GradientStop = {
|
|
16
|
+
t: number;
|
|
17
|
+
color: import("../units.js").Rgba;
|
|
18
|
+
};
|
|
19
|
+
export type LinearGradient = {
|
|
20
|
+
x0: number;
|
|
21
|
+
y0: number;
|
|
22
|
+
x1: number;
|
|
23
|
+
y1: number;
|
|
24
|
+
stops: GradientStop[];
|
|
25
|
+
};
|
package/types/walker/image.d.ts
CHANGED
|
@@ -47,6 +47,42 @@ export function fitImage(box: {
|
|
|
47
47
|
* @returns {string}
|
|
48
48
|
*/
|
|
49
49
|
export function objectFitToSize(fit: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* `background-repeat` の computed 値を軸ごとに分ける。
|
|
52
|
+
* `repeat-x` / `repeat-y` は 2 値表記に展開する。
|
|
53
|
+
* @param {string} value
|
|
54
|
+
* @returns {['repeat'|'no-repeat'|'space'|'round', 'repeat'|'no-repeat'|'space'|'round']}
|
|
55
|
+
*/
|
|
56
|
+
export function splitRepeat(value: string): ["repeat" | "no-repeat" | "space" | "round", "repeat" | "no-repeat" | "space" | "round"];
|
|
57
|
+
/**
|
|
58
|
+
* 1 軸ぶんのタイル位置を求める。
|
|
59
|
+
*
|
|
60
|
+
* - `repeat`: 指定位置を基準に、描画領域を覆うまで両方向へ並べる
|
|
61
|
+
* - `no-repeat`: 指定位置に 1 枚
|
|
62
|
+
* - `round`: 描画領域に整数個収まるようタイルの大きさを調整して並べる(大きさが変わる)
|
|
63
|
+
* - `space`: 整数個を等間隔に置き、余りを隙間に配る。1 枚しか入らないなら先頭に 1 枚
|
|
64
|
+
*
|
|
65
|
+
* @param {'repeat'|'no-repeat'|'space'|'round'} mode
|
|
66
|
+
* @param {number} start 指定位置(background-position の結果)
|
|
67
|
+
* @param {number} size タイルの大きさ
|
|
68
|
+
* @param {number} areaStart 描画領域の開始
|
|
69
|
+
* @param {number} areaEnd 描画領域の終わり
|
|
70
|
+
* @returns {{positions: number[], size: number}}
|
|
71
|
+
*/
|
|
72
|
+
export function tileAxis(mode: "repeat" | "no-repeat" | "space" | "round", start: number, size: number, areaStart: number, areaEnd: number): {
|
|
73
|
+
positions: number[];
|
|
74
|
+
size: number;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* 埋め込みが済んだ画像のピクセルデータを手放す。
|
|
78
|
+
* デコード結果(RGB・アルファ・JPEG のバイト列)は元画像より桁違いに大きいので、
|
|
79
|
+
* PDF に書き出したあとも抱えていると大きな文書でピーク使用量が跳ね上がる。
|
|
80
|
+
*
|
|
81
|
+
* キャッシュからも外すので、次の変換では読み直しになる(速度よりメモリを優先する)。
|
|
82
|
+
*
|
|
83
|
+
* @param {DecodedImage} img
|
|
84
|
+
*/
|
|
85
|
+
export function releasePixels(img: DecodedImage): void;
|
|
50
86
|
export type DecodedImage = {
|
|
51
87
|
/**
|
|
52
88
|
* 重複排除キー(URL)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG のパスデータと基本図形を、PDF に出せる形(絶対座標の M / L / C / Z)へ正規化する。
|
|
3
|
+
*
|
|
4
|
+
* 円弧(A)は 3 次ベジェへ、二次ベジェ(Q / T)も 3 次へ変換する。
|
|
5
|
+
* 座標は要素のユーザー単位のまま(変換行列は描画時に cm で適用する)。
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {['M', number, number]|['L', number, number]|['C', number, number, number, number, number, number]|['Z']} PathSeg
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* `d` 属性を絶対座標の M / L / C / Z 列にする。
|
|
12
|
+
* @param {string} d
|
|
13
|
+
* @returns {PathSeg[]}
|
|
14
|
+
*/
|
|
15
|
+
export function parsePathData(d: string): PathSeg[];
|
|
16
|
+
/**
|
|
17
|
+
* 楕円円弧を 3 次ベジェ列にする(SVG 仕様 F.6 の実装)。
|
|
18
|
+
* @param {number} x1 @param {number} y1 @param {number} x2 @param {number} y2
|
|
19
|
+
* @param {number} rx @param {number} ry @param {number} rotDeg
|
|
20
|
+
* @param {boolean} large @param {boolean} sweep
|
|
21
|
+
* @returns {PathSeg[]}
|
|
22
|
+
*/
|
|
23
|
+
export function arcToCurves(x1: number, y1: number, x2: number, y2: number, rx: number, ry: number, rotDeg: number, large: boolean, sweep: boolean): PathSeg[];
|
|
24
|
+
/**
|
|
25
|
+
* 基本図形をパスにする。対応しない要素は null。
|
|
26
|
+
* @param {Element} el
|
|
27
|
+
* @param {(name: string) => string} attr 属性値(プレゼンテーション属性は computed style を優先しない純粋な幾何属性)
|
|
28
|
+
* @returns {PathSeg[]|null}
|
|
29
|
+
*/
|
|
30
|
+
export function shapeToPath(el: Element, attr: (name: string) => string): PathSeg[] | null;
|
|
31
|
+
export type PathSeg = ["M", number, number] | ["L", number, number] | ["C", number, number, number, number, number, number] | ["Z"];
|
package/types/walker/text.d.ts
CHANGED
|
@@ -33,6 +33,10 @@ export type MeasureOptions = {
|
|
|
33
33
|
*/
|
|
34
34
|
size: number;
|
|
35
35
|
textMeasure: "font" | "measure" | "auto";
|
|
36
|
+
/**
|
|
37
|
+
* ブラウザが有効にしている OpenType 機能タグ(GSUB の単一置換を再現する)
|
|
38
|
+
*/
|
|
39
|
+
features: string[];
|
|
36
40
|
warn: (w: import("../index.js").ConversionWarning) => void;
|
|
37
41
|
element: Element;
|
|
38
42
|
};
|
package/types/walker/walk.d.ts
CHANGED
|
@@ -117,7 +117,43 @@ export type ClipItem = {
|
|
|
117
117
|
z: number;
|
|
118
118
|
seq: number;
|
|
119
119
|
};
|
|
120
|
-
|
|
120
|
+
/**
|
|
121
|
+
* linear-gradient(box はグラデーションの基準領域、clip は描画範囲)
|
|
122
|
+
*/
|
|
123
|
+
export type GradientItem = {
|
|
124
|
+
type: "gradient";
|
|
125
|
+
box: Box;
|
|
126
|
+
clip: Box;
|
|
127
|
+
gradient: import("./gradient.js").LinearGradient;
|
|
128
|
+
alpha: number;
|
|
129
|
+
z: number;
|
|
130
|
+
seq: number;
|
|
131
|
+
};
|
|
132
|
+
export type PathStroke = {
|
|
133
|
+
color: Rgba;
|
|
134
|
+
width: number;
|
|
135
|
+
cap: 0 | 1 | 2;
|
|
136
|
+
join: 0 | 1 | 2;
|
|
137
|
+
miter: number;
|
|
138
|
+
dash: number[] | null;
|
|
139
|
+
dashOffset: number;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* インライン SVG の図形(matrix はユーザー単位 → ドキュメント px)
|
|
143
|
+
*/
|
|
144
|
+
export type PathItem = {
|
|
145
|
+
type: "path";
|
|
146
|
+
segs: import("./svg-path.js").PathSeg[];
|
|
147
|
+
matrix: [number, number, number, number, number, number];
|
|
148
|
+
fill: Rgba | null;
|
|
149
|
+
evenOdd: boolean;
|
|
150
|
+
stroke: PathStroke | null;
|
|
151
|
+
top: number;
|
|
152
|
+
bottom: number;
|
|
153
|
+
z: number;
|
|
154
|
+
seq: number;
|
|
155
|
+
};
|
|
156
|
+
export type DisplayItem = RectItem | LineItem | StrokeRRectItem | ImageItem | TextItem | GroupItem | ClipItem | GradientItem | PathItem;
|
|
121
157
|
/**
|
|
122
158
|
* ページ境界を跨いではいけない縦範囲(行・表の行・画像・break-inside: avoid)
|
|
123
159
|
*/
|
|
@@ -135,11 +171,42 @@ export type TableInfo = {
|
|
|
135
171
|
footBottom: number;
|
|
136
172
|
footItems: DisplayItem[];
|
|
137
173
|
};
|
|
174
|
+
/**
|
|
175
|
+
* break-before/after: avoid — [start, end] に境界を置かず、置きそうなら pullTo まで戻す
|
|
176
|
+
*/
|
|
177
|
+
export type Join = {
|
|
178
|
+
start: number;
|
|
179
|
+
end: number;
|
|
180
|
+
pullTo: number;
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* <a href> の 1 行ぶんの当たり判定(ドキュメント px)
|
|
184
|
+
*/
|
|
185
|
+
export type LinkRect = {
|
|
186
|
+
x: number;
|
|
187
|
+
y: number;
|
|
188
|
+
w: number;
|
|
189
|
+
h: number;
|
|
190
|
+
href: string;
|
|
191
|
+
fragment: string | null;
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* しおり用の見出し
|
|
195
|
+
*/
|
|
196
|
+
export type Heading = {
|
|
197
|
+
level: number;
|
|
198
|
+
text: string;
|
|
199
|
+
y: number;
|
|
200
|
+
};
|
|
138
201
|
export type WalkResult = {
|
|
139
202
|
items: DisplayItem[];
|
|
140
203
|
atoms: Atom[];
|
|
141
204
|
breaks: number[];
|
|
205
|
+
joins: Join[];
|
|
142
206
|
tables: TableInfo[];
|
|
207
|
+
links: LinkRect[];
|
|
208
|
+
anchors: Map<string, number>;
|
|
209
|
+
headings: Heading[];
|
|
143
210
|
height: number;
|
|
144
211
|
};
|
|
145
212
|
export type WalkContext = {
|
|
@@ -147,4 +214,8 @@ export type WalkContext = {
|
|
|
147
214
|
fontFallback: string[];
|
|
148
215
|
warn: (w: import("../index.js").ConversionWarning) => void;
|
|
149
216
|
textMeasure: "font" | "measure" | "auto";
|
|
217
|
+
/**
|
|
218
|
+
* 長い走査で途中イベントループへ戻すための譲渡
|
|
219
|
+
*/
|
|
220
|
+
pacer?: import("../pacer.js").Pacer | undefined;
|
|
150
221
|
};
|