cvdl-ts 1.0.12 → 1.0.14
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/dist/AnyLayout.d.ts +1 -1
- package/dist/AnyLayout.js +9 -26
- package/dist/DataSchema.d.ts +37 -25
- package/dist/DataSchema.js +79 -4
- package/dist/Elem.d.ts +23 -6
- package/dist/Elem.js +110 -15
- package/dist/Layout.d.ts +6 -3
- package/dist/Layout.js +39 -21
- package/dist/PdfLayout.d.ts +3 -1
- package/dist/PdfLayout.js +59 -37
- package/dist/Row.d.ts +1 -4
- package/dist/Row.js +1 -9
- package/dist/Stack.d.ts +1 -4
- package/dist/Stack.js +1 -9
- package/dist/Utils.d.ts +5 -0
- package/dist/Utils.js +8 -0
- package/package.json +9 -3
package/dist/AnyLayout.d.ts
CHANGED
|
@@ -34,4 +34,4 @@ export declare class FontDict {
|
|
|
34
34
|
load_fonts_from_schema(schema: LayoutSchema, storage: Storage): Promise<void>;
|
|
35
35
|
get_font(name: string): fontkit.Font;
|
|
36
36
|
}
|
|
37
|
-
export declare function render({ resume, layout_schemas, data_schemas, resume_layout, storage, fontDict }: RenderProps): Promise<
|
|
37
|
+
export declare function render({ resume, layout_schemas, data_schemas, resume_layout, storage, fontDict }: RenderProps): Promise<Layout.RenderedLayout[]>;
|
package/dist/AnyLayout.js
CHANGED
|
@@ -54,8 +54,6 @@ class FontDict {
|
|
|
54
54
|
}
|
|
55
55
|
exports.FontDict = FontDict;
|
|
56
56
|
async function render({ resume, layout_schemas, data_schemas, resume_layout, storage, fontDict }) {
|
|
57
|
-
// Each box contains a set of elements(positioned by 0x0 and projected into its bounding box)
|
|
58
|
-
const font_dict = fontDict !== null && fontDict !== void 0 ? fontDict : new FontDict();
|
|
59
57
|
// Compute the total usable width by subtracting the margins from the document width
|
|
60
58
|
const width = resume_layout.width - (resume_layout.margin.left + resume_layout.margin.right);
|
|
61
59
|
// If the resume is double column, then the usable width is halved
|
|
@@ -65,7 +63,6 @@ async function render({ resume, layout_schemas, data_schemas, resume_layout, sto
|
|
|
65
63
|
const layouts = [];
|
|
66
64
|
console.error("Rendering sections...");
|
|
67
65
|
for (const section of resume.sections) {
|
|
68
|
-
console.error("Print section:", section);
|
|
69
66
|
// Render Section Header
|
|
70
67
|
// 1. Find the layout schema for the section
|
|
71
68
|
console.info("Computing section: ", section.section_name);
|
|
@@ -75,48 +72,34 @@ async function render({ resume, layout_schemas, data_schemas, resume_layout, sto
|
|
|
75
72
|
throw new Error(`Could not find layout schema ${section.layout_schema}`);
|
|
76
73
|
}
|
|
77
74
|
let start_time = Date.now();
|
|
78
|
-
await
|
|
75
|
+
await fontDict.load_fonts_from_schema(layout_schema, storage);
|
|
79
76
|
let end_time = Date.now();
|
|
80
77
|
console.info(`Font loading time: ${end_time - start_time}ms for section ${section.section_name}`);
|
|
81
78
|
// 2. Find the data schema for the section
|
|
82
|
-
const
|
|
83
|
-
if (
|
|
79
|
+
const data_schema = data_schemas.find(s => s.schema_name === section.data_schema);
|
|
80
|
+
if (data_schema === undefined) {
|
|
84
81
|
throw new Error(`Could not find data schema ${section.data_schema}`);
|
|
85
82
|
}
|
|
86
83
|
start_time = Date.now();
|
|
87
84
|
// 3. Render the header
|
|
88
|
-
const layout = _1.Layout.computeBoxes(_1.Layout.normalize(_1.Layout.instantiate(layout_schema.header_layout_schema, section.data), column_width,
|
|
89
|
-
|
|
85
|
+
const layout = _1.Layout.computeBoxes(_1.Layout.normalize(_1.Layout.instantiate(layout_schema.header_layout_schema, section.data, data_schema.header_schema), column_width, fontDict), fontDict);
|
|
86
|
+
layout.path = { tag: 'section', section: section.section_name };
|
|
87
|
+
console.info("Header is computed");
|
|
90
88
|
layouts.push(layout);
|
|
91
89
|
end_time = Date.now();
|
|
92
90
|
console.info(`Header rendering time: ${end_time - start_time}ms for section ${section.section_name}`);
|
|
93
91
|
start_time = Date.now();
|
|
94
92
|
// Render Section Items
|
|
95
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
96
|
-
// @ts-nocheck
|
|
97
93
|
for (const [index, item] of section.items.entries()) {
|
|
98
|
-
console.log("Computing item");
|
|
99
|
-
console.error("Item:", item);
|
|
100
|
-
// 1. Find the layout schema for the section
|
|
101
|
-
const layout_schema = layout_schemas
|
|
102
|
-
.find((s) => s.schema_name == section.layout_schema);
|
|
103
|
-
if (layout_schema == undefined) {
|
|
104
|
-
throw new Error(`Could not find layout schema ${section.layout_schema}`);
|
|
105
|
-
}
|
|
106
|
-
await font_dict.load_fonts_from_schema(layout_schema, storage);
|
|
107
|
-
console.log("Fonts are loaded");
|
|
108
|
-
// 2. Find the data schema for the section
|
|
109
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
110
|
-
const _data_schema = data_schemas
|
|
111
|
-
.find((s) => s.schema_name == section.data_schema);
|
|
112
94
|
// 3. Render the item
|
|
113
|
-
const layout = _1.Layout.computeBoxes(_1.Layout.normalize(_1.Layout.instantiate(layout_schema.item_layout_schema, item.fields), column_width,
|
|
95
|
+
const layout = _1.Layout.computeBoxes(_1.Layout.normalize(_1.Layout.instantiate(layout_schema.item_layout_schema, item.fields, data_schema.item_schema), column_width, fontDict), fontDict);
|
|
96
|
+
layout.path = { tag: 'item', section: section.section_name, item: index };
|
|
114
97
|
layouts.push(layout);
|
|
115
98
|
}
|
|
116
99
|
end_time = Date.now();
|
|
117
100
|
console.info(`Item rendering time: ${end_time - start_time}ms for section ${section.section_name}`);
|
|
118
101
|
}
|
|
119
102
|
console.log("Position calculations are completed.");
|
|
120
|
-
return
|
|
103
|
+
return layouts;
|
|
121
104
|
}
|
|
122
105
|
exports.render = render;
|
package/dist/DataSchema.d.ts
CHANGED
|
@@ -1,32 +1,44 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} | {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} | {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
export declare namespace DocumentDataType {
|
|
2
|
+
type t = {
|
|
3
|
+
tag: "Date";
|
|
4
|
+
} | {
|
|
5
|
+
tag: "String";
|
|
6
|
+
} | {
|
|
7
|
+
tag: "MarkdownString";
|
|
8
|
+
} | {
|
|
9
|
+
tag: "Number";
|
|
10
|
+
} | {
|
|
11
|
+
tag: "Type";
|
|
12
|
+
value: string;
|
|
13
|
+
} | {
|
|
14
|
+
tag: "List";
|
|
15
|
+
value: t;
|
|
16
|
+
} | {
|
|
17
|
+
tag: "Types";
|
|
18
|
+
value: t[];
|
|
19
|
+
};
|
|
20
|
+
type DocumentDataType = t;
|
|
21
|
+
function parse(s: string): DocumentDataType;
|
|
22
|
+
function print(d: DocumentDataType): string;
|
|
23
|
+
}
|
|
24
|
+
export declare namespace Field {
|
|
25
|
+
type t = {
|
|
26
|
+
name: string;
|
|
27
|
+
type: DocumentDataType.t;
|
|
28
|
+
};
|
|
29
|
+
type Field = t;
|
|
30
|
+
function fromJson(json: unknown): Field;
|
|
31
|
+
function toJson(f: Field): unknown;
|
|
32
|
+
}
|
|
21
33
|
export declare class DataSchema {
|
|
22
34
|
schema_name: string;
|
|
23
|
-
header_schema: Field[];
|
|
24
|
-
item_schema: Field[];
|
|
25
|
-
constructor(schema_name: string, header_schema: Field[], item_schema: Field[]);
|
|
35
|
+
header_schema: Field.t[];
|
|
36
|
+
item_schema: Field.t[];
|
|
37
|
+
constructor(schema_name: string, header_schema: Field.t[], item_schema: Field.t[]);
|
|
26
38
|
static fromJson(json: unknown): DataSchema;
|
|
27
39
|
toJson(): {
|
|
28
40
|
schema_name: string;
|
|
29
|
-
header_schema:
|
|
30
|
-
item_schema:
|
|
41
|
+
header_schema: unknown[];
|
|
42
|
+
item_schema: unknown[];
|
|
31
43
|
};
|
|
32
44
|
}
|
package/dist/DataSchema.js
CHANGED
|
@@ -1,6 +1,81 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DataSchema = void 0;
|
|
3
|
+
exports.DataSchema = exports.Field = exports.DocumentDataType = void 0;
|
|
4
|
+
var DocumentDataType;
|
|
5
|
+
(function (DocumentDataType) {
|
|
6
|
+
function parse(s) {
|
|
7
|
+
if (s === "Date") {
|
|
8
|
+
return { tag: "Date" };
|
|
9
|
+
}
|
|
10
|
+
else if (s === "String") {
|
|
11
|
+
return { tag: "String" };
|
|
12
|
+
}
|
|
13
|
+
else if (s === "MarkdownString") {
|
|
14
|
+
return { tag: "MarkdownString" };
|
|
15
|
+
}
|
|
16
|
+
else if (s === "Number") {
|
|
17
|
+
return { tag: "Number" };
|
|
18
|
+
}
|
|
19
|
+
else if (s.startsWith("List")) {
|
|
20
|
+
return { tag: "List", value: parse(s.slice(5, -1).trim()) };
|
|
21
|
+
}
|
|
22
|
+
else if (s.includes("|")) {
|
|
23
|
+
return { tag: "Types", value: s.split("|").map((s) => s.trim()).map(parse) };
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
throw new Error("Invalid DocumentDataType: " + s);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
DocumentDataType.parse = parse;
|
|
30
|
+
function print(d) {
|
|
31
|
+
switch (d.tag) {
|
|
32
|
+
case "Date":
|
|
33
|
+
return "Date";
|
|
34
|
+
case "String":
|
|
35
|
+
return "String";
|
|
36
|
+
case "MarkdownString":
|
|
37
|
+
return "MarkdownString";
|
|
38
|
+
case "Number":
|
|
39
|
+
return "Number";
|
|
40
|
+
case "Type":
|
|
41
|
+
return d.value;
|
|
42
|
+
case "List":
|
|
43
|
+
return "List<" + print(d.value) + ">";
|
|
44
|
+
case "Types":
|
|
45
|
+
return d.value.map(print).join(" | ");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
DocumentDataType.print = print;
|
|
49
|
+
})(DocumentDataType || (exports.DocumentDataType = DocumentDataType = {}));
|
|
50
|
+
var Field;
|
|
51
|
+
(function (Field) {
|
|
52
|
+
function fromJson(json) {
|
|
53
|
+
if (typeof json !== "object" || json === null) {
|
|
54
|
+
throw new Error("Field must be an object");
|
|
55
|
+
}
|
|
56
|
+
if (!("name" in json) || !("type" in json)) {
|
|
57
|
+
throw new Error("Field must have a name and type");
|
|
58
|
+
}
|
|
59
|
+
if (typeof json.name !== "string") {
|
|
60
|
+
throw new Error("Field name must be a string");
|
|
61
|
+
}
|
|
62
|
+
if (typeof json.type !== "string") {
|
|
63
|
+
throw new Error("Field type must be a string");
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
name: json.name,
|
|
67
|
+
type: DocumentDataType.parse(json.type),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
Field.fromJson = fromJson;
|
|
71
|
+
function toJson(f) {
|
|
72
|
+
return {
|
|
73
|
+
name: f.name,
|
|
74
|
+
type: DocumentDataType.print(f.type),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
Field.toJson = toJson;
|
|
78
|
+
})(Field || (exports.Field = Field = {}));
|
|
4
79
|
class DataSchema {
|
|
5
80
|
constructor(schema_name, header_schema, item_schema) {
|
|
6
81
|
this.schema_name = schema_name;
|
|
@@ -14,13 +89,13 @@ class DataSchema {
|
|
|
14
89
|
if (!("schema_name" in json) || !("header_schema" in json) || !("item_schema" in json)) {
|
|
15
90
|
throw new Error("DataSchema must have a schema_name, header_schema, and item_schema");
|
|
16
91
|
}
|
|
17
|
-
return new DataSchema(json.schema_name, json.header_schema, json.item_schema);
|
|
92
|
+
return new DataSchema(json.schema_name, json.header_schema.map(Field.fromJson), json.item_schema.map(Field.fromJson));
|
|
18
93
|
}
|
|
19
94
|
toJson() {
|
|
20
95
|
return {
|
|
21
96
|
schema_name: this.schema_name,
|
|
22
|
-
header_schema: this.header_schema,
|
|
23
|
-
item_schema: this.item_schema,
|
|
97
|
+
header_schema: this.header_schema.map(Field.toJson),
|
|
98
|
+
item_schema: this.item_schema.map(Field.toJson),
|
|
24
99
|
};
|
|
25
100
|
}
|
|
26
101
|
}
|
package/dist/Elem.d.ts
CHANGED
|
@@ -4,12 +4,29 @@ import { Color } from "./Layout";
|
|
|
4
4
|
import { FontDict } from "./AnyLayout";
|
|
5
5
|
import * as Row from "./Row";
|
|
6
6
|
import { ItemContent } from "./Resume";
|
|
7
|
+
import { Field } from "./DataSchema";
|
|
8
|
+
import { Optional } from "./Utils";
|
|
9
|
+
import { Box } from "./Box";
|
|
10
|
+
export type Span = {
|
|
11
|
+
is_italic: boolean;
|
|
12
|
+
is_bold: boolean;
|
|
13
|
+
is_code: boolean;
|
|
14
|
+
text: string;
|
|
15
|
+
link: string | null;
|
|
16
|
+
font?: Font.t;
|
|
17
|
+
width?: number;
|
|
18
|
+
line?: number;
|
|
19
|
+
bbox?: Box;
|
|
20
|
+
};
|
|
7
21
|
export type t = {
|
|
8
22
|
tag: "Elem";
|
|
9
23
|
item: string;
|
|
24
|
+
text?: string;
|
|
25
|
+
spans?: Span[];
|
|
10
26
|
url: string | null;
|
|
11
27
|
is_ref: boolean;
|
|
12
28
|
is_fill: boolean;
|
|
29
|
+
is_markdown: boolean;
|
|
13
30
|
text_width: Width.t;
|
|
14
31
|
font: Font.t;
|
|
15
32
|
margin: Margin.t;
|
|
@@ -18,13 +35,16 @@ export type t = {
|
|
|
18
35
|
background_color: Color;
|
|
19
36
|
};
|
|
20
37
|
type Elem = t;
|
|
21
|
-
export declare function elem(item: string, url: string | null, is_ref: boolean, is_fill: boolean, text_width: Width.t, font: Font.t, margin: Margin.t, alignment: Alignment.t, width: Width.t, background_color: Color): Elem;
|
|
38
|
+
export declare function elem(item: string, url: string | null, is_ref: boolean, is_fill: boolean, is_markdown: boolean, text_width: Width.t, font: Font.t, margin: Margin.t, alignment: Alignment.t, width: Width.t, background_color: Color): Elem;
|
|
22
39
|
export declare function copy(e: Elem): {
|
|
23
40
|
tag: "Elem";
|
|
24
41
|
item: string;
|
|
42
|
+
text?: string;
|
|
43
|
+
spans?: Span[];
|
|
25
44
|
url: string;
|
|
26
45
|
is_ref: boolean;
|
|
27
46
|
is_fill: boolean;
|
|
47
|
+
is_markdown: boolean;
|
|
28
48
|
text_width: Width.t;
|
|
29
49
|
font: Font.t;
|
|
30
50
|
margin: Margin.t;
|
|
@@ -33,10 +53,6 @@ export declare function copy(e: Elem): {
|
|
|
33
53
|
background_color: Layout.Color;
|
|
34
54
|
};
|
|
35
55
|
export declare function default_(): Elem;
|
|
36
|
-
export type Optional<T> = {
|
|
37
|
-
[P in keyof T]?: T[P];
|
|
38
|
-
};
|
|
39
|
-
export declare function with_(e: Elem, w: Optional<Elem>): Elem;
|
|
40
56
|
export declare function from(w: Optional<Elem>): Elem;
|
|
41
57
|
export declare function withItem(e: Elem, item: string): Elem;
|
|
42
58
|
export declare function withUrl(e: Elem, url: string | null): Elem;
|
|
@@ -50,9 +66,10 @@ export declare function withAlignment(e: Elem, alignment: Alignment.t): Elem;
|
|
|
50
66
|
export declare function withWidth(e: Elem, width: Width.t): Elem;
|
|
51
67
|
export declare function withBackgroundColor(e: Elem, background_color: Color): Elem;
|
|
52
68
|
export declare function scaleWidth(e: Elem, scale: number): Elem;
|
|
69
|
+
export declare function parseMarkdownItem(item: string): Span[];
|
|
53
70
|
export declare function fillFonts(e: Elem, fonts: FontDict): Elem;
|
|
54
71
|
export declare function justifiedLines(e: Elem, lines: Elem[], font_dict: FontDict): Row.t[];
|
|
55
72
|
export declare function break_lines(e: Elem, font_dict: FontDict): Layout.t[];
|
|
56
73
|
export declare function boundWidth(e: Elem, width: number): Elem;
|
|
57
|
-
export declare function instantiate(e: Elem, section: Map<string, ItemContent
|
|
74
|
+
export declare function instantiate(e: Elem, section: Map<string, ItemContent>, fields: Field.t[]): Elem;
|
|
58
75
|
export {};
|
package/dist/Elem.js
CHANGED
|
@@ -23,18 +23,30 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.instantiate = exports.boundWidth = exports.break_lines = exports.justifiedLines = exports.fillFonts = exports.scaleWidth = exports.withBackgroundColor = exports.withWidth = exports.withAlignment = exports.withMargin = exports.withFont = exports.withTextWidth = exports.withIsFill = exports.asRef = exports.withIsRef = exports.withUrl = exports.withItem = exports.from = exports.
|
|
26
|
+
exports.instantiate = exports.boundWidth = exports.break_lines = exports.justifiedLines = exports.fillFonts = exports.parseMarkdownItem = exports.scaleWidth = exports.withBackgroundColor = exports.withWidth = exports.withAlignment = exports.withMargin = exports.withFont = exports.withTextWidth = exports.withIsFill = exports.asRef = exports.withIsRef = exports.withUrl = exports.withItem = exports.from = exports.default_ = exports.copy = exports.elem = void 0;
|
|
27
27
|
const Font = __importStar(require("./Font"));
|
|
28
28
|
const _1 = require(".");
|
|
29
29
|
const Row_1 = require("./Row");
|
|
30
30
|
const Resume_1 = require("./Resume");
|
|
31
|
-
|
|
31
|
+
const marked = __importStar(require("marked"));
|
|
32
|
+
const ts_pattern_1 = require("ts-pattern");
|
|
33
|
+
const Utils_1 = require("./Utils");
|
|
34
|
+
function defaultSpanProps() {
|
|
35
|
+
return {
|
|
36
|
+
is_italic: false,
|
|
37
|
+
is_bold: false,
|
|
38
|
+
is_code: false,
|
|
39
|
+
is_link: false,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function elem(item, url, is_ref, is_fill, is_markdown, text_width, font, margin, alignment, width, background_color) {
|
|
32
43
|
return {
|
|
33
44
|
tag: "Elem",
|
|
34
45
|
item,
|
|
35
46
|
url,
|
|
36
47
|
is_ref,
|
|
37
48
|
is_fill,
|
|
49
|
+
is_markdown,
|
|
38
50
|
text_width,
|
|
39
51
|
font,
|
|
40
52
|
margin,
|
|
@@ -55,6 +67,7 @@ function default_() {
|
|
|
55
67
|
url: null,
|
|
56
68
|
is_ref: false,
|
|
57
69
|
is_fill: false,
|
|
70
|
+
is_markdown: false,
|
|
58
71
|
text_width: _1.Width.default_(),
|
|
59
72
|
font: Font.default_(),
|
|
60
73
|
margin: _1.Margin.default_(),
|
|
@@ -64,10 +77,6 @@ function default_() {
|
|
|
64
77
|
};
|
|
65
78
|
}
|
|
66
79
|
exports.default_ = default_;
|
|
67
|
-
function with_(e, w) {
|
|
68
|
-
return { ...e, ...w };
|
|
69
|
-
}
|
|
70
|
-
exports.with_ = with_;
|
|
71
80
|
function from(w) {
|
|
72
81
|
return { ...default_(), ...w };
|
|
73
82
|
}
|
|
@@ -120,13 +129,94 @@ function scaleWidth(e, scale) {
|
|
|
120
129
|
return withWidth(e, _1.Width.scale(e.width, scale));
|
|
121
130
|
}
|
|
122
131
|
exports.scaleWidth = scaleWidth;
|
|
132
|
+
function flatten(ts, sp) {
|
|
133
|
+
const spans = [];
|
|
134
|
+
for (const t of ts) {
|
|
135
|
+
spans.push(...flattenToken(t, sp));
|
|
136
|
+
}
|
|
137
|
+
return spans;
|
|
138
|
+
}
|
|
139
|
+
function flattenToken(t, sp) {
|
|
140
|
+
return (0, ts_pattern_1.match)(t)
|
|
141
|
+
.returnType()
|
|
142
|
+
.with({ type: "paragraph", tokens: ts_pattern_1.P.select("tokens") }, ({ tokens }) => {
|
|
143
|
+
return flatten(tokens, sp);
|
|
144
|
+
})
|
|
145
|
+
.with({ type: "strong", tokens: ts_pattern_1.P.select("tokens") }, ({ tokens }) => {
|
|
146
|
+
return flatten(tokens, { ...sp, is_bold: true });
|
|
147
|
+
})
|
|
148
|
+
.with({ type: "em", tokens: ts_pattern_1.P.select("tokens") }, ({ tokens }) => {
|
|
149
|
+
return flatten(tokens, { ...sp, is_italic: true });
|
|
150
|
+
})
|
|
151
|
+
.with({ type: "codespan", text: ts_pattern_1.P.select("text") }, ({ text }) => {
|
|
152
|
+
return [{ ...sp, is_code: true, text, link: null }];
|
|
153
|
+
})
|
|
154
|
+
.with({ type: "text", tokens: ts_pattern_1.P.select("tokens") }, ({ tokens }) => {
|
|
155
|
+
return flatten(tokens, sp);
|
|
156
|
+
})
|
|
157
|
+
.with({ type: "text", text: ts_pattern_1.P.select("text") }, ({ text }) => {
|
|
158
|
+
const result = [];
|
|
159
|
+
if (text.startsWith(" ")) {
|
|
160
|
+
result.push({ ...sp, text: " ", link: null });
|
|
161
|
+
}
|
|
162
|
+
result.push({ ...sp, text: text.trim(), link: null });
|
|
163
|
+
if (text.endsWith(" ")) {
|
|
164
|
+
result.push({ ...sp, text: " ", link: null });
|
|
165
|
+
}
|
|
166
|
+
else if (text.endsWith("\n")) {
|
|
167
|
+
result.push({ ...sp, text: "\n", link: null });
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
})
|
|
171
|
+
.otherwise((e) => {
|
|
172
|
+
// console.log(`Unknown token type: ${JSON.stringify(e)}`);
|
|
173
|
+
return [{ ...defaultSpanProps(), text: e.raw, link: null }];
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function parseMarkdownItem(item) {
|
|
177
|
+
const spans = [];
|
|
178
|
+
for (const token of marked.lexer(item)) {
|
|
179
|
+
spans.push(...flatten([token], defaultSpanProps()));
|
|
180
|
+
}
|
|
181
|
+
return spans;
|
|
182
|
+
}
|
|
183
|
+
exports.parseMarkdownItem = parseMarkdownItem;
|
|
123
184
|
function fillFonts(e, fonts) {
|
|
124
|
-
const
|
|
185
|
+
const simpleSpans = e.is_markdown ? parseMarkdownItem(e.text) : [{ ...defaultSpanProps(), text: e.text, font: e.font, link: null }];
|
|
186
|
+
const spans = [];
|
|
187
|
+
for (const span of simpleSpans) {
|
|
188
|
+
const font = e.is_markdown ? (0, Utils_1.with_)(e.font, ({
|
|
189
|
+
// style: span.is_italic ? "Italic" : "Normal",
|
|
190
|
+
weight: span.is_bold ? "Bold" : "Medium",
|
|
191
|
+
})) : e.font;
|
|
192
|
+
if (span.text === " ") {
|
|
193
|
+
const width = Font.get_width(font, "-", fonts);
|
|
194
|
+
spans.push({ ...span, font, width });
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (span.text === "\n\n") {
|
|
198
|
+
spans.push({ ...span, font, width: 0 });
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
const words = span.text.split(/\s+/);
|
|
202
|
+
words.forEach((word, index) => {
|
|
203
|
+
const width = Font.get_width(font, word, fonts);
|
|
204
|
+
spans.push({ ...span, text: word, font, width });
|
|
205
|
+
if (index < words.length - 1) {
|
|
206
|
+
spans.push({ ...span, text: " ", font, width: Font.get_width(font, " ", fonts) });
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
const text_width = spans.reduce((acc, span) => acc + span.width, 0);
|
|
125
211
|
if (e.is_fill) {
|
|
126
|
-
return
|
|
212
|
+
return (0, Utils_1.with_)(e, {
|
|
213
|
+
width: _1.Width.absolute(Math.min(_1.Width.get_fixed_unchecked(e.width), text_width)),
|
|
214
|
+
text_width: _1.Width.absolute(text_width),
|
|
215
|
+
spans
|
|
216
|
+
});
|
|
127
217
|
}
|
|
128
218
|
else {
|
|
129
|
-
return
|
|
219
|
+
return (0, Utils_1.with_)(e, { text_width: _1.Width.absolute(text_width), spans });
|
|
130
220
|
}
|
|
131
221
|
}
|
|
132
222
|
exports.fillFonts = fillFonts;
|
|
@@ -137,7 +227,7 @@ function justifiedLines(e, lines, font_dict) {
|
|
|
137
227
|
const r = (0, Row_1.row)([], line.margin, line.alignment, line.width, false, false);
|
|
138
228
|
words.forEach(word => {
|
|
139
229
|
const word_width = Font.get_width(e.font, word, font_dict);
|
|
140
|
-
r.elements.push(elem(word, null, false, false, _1.Width.absolute(word_width), this.font, _1.Margin.default_(), _1.Alignment.default_(), _1.Width.absolute(word_width), this.background_color));
|
|
230
|
+
r.elements.push(elem(word, null, false, false, false, _1.Width.absolute(word_width), this.font, _1.Margin.default_(), _1.Alignment.default_(), _1.Width.absolute(word_width), this.background_color));
|
|
141
231
|
});
|
|
142
232
|
rowLines.push(Row_1.row);
|
|
143
233
|
}
|
|
@@ -152,7 +242,7 @@ function break_lines(e, font_dict) {
|
|
|
152
242
|
const lines = [];
|
|
153
243
|
// todo: I'm sure this implementation is pretty buggy. Note to future me, fix
|
|
154
244
|
// this.
|
|
155
|
-
const words = e.
|
|
245
|
+
const words = e.text.split(/\s+/);
|
|
156
246
|
const widths = words.map((word) => Font.get_width(e.font, word, font_dict));
|
|
157
247
|
const space_width = Font.get_width(e.font, " ", font_dict);
|
|
158
248
|
let start = 0;
|
|
@@ -189,20 +279,25 @@ function boundWidth(e, width) {
|
|
|
189
279
|
}
|
|
190
280
|
}
|
|
191
281
|
exports.boundWidth = boundWidth;
|
|
192
|
-
function instantiate(e, section) {
|
|
282
|
+
function instantiate(e, section, fields) {
|
|
193
283
|
if (!e.is_ref) {
|
|
194
284
|
return e;
|
|
195
285
|
}
|
|
286
|
+
const itemType = fields.find(f => f.name === e.item);
|
|
287
|
+
if (itemType.type.tag === "MarkdownString") {
|
|
288
|
+
e.is_markdown = true;
|
|
289
|
+
}
|
|
196
290
|
const text = section.get(e.item);
|
|
291
|
+
console.log(`Instantiating ${e.item} with ${JSON.stringify(text)}`);
|
|
197
292
|
if (text === undefined) {
|
|
198
|
-
return
|
|
293
|
+
return (0, Utils_1.with_)(e, { is_ref: false, text: "" });
|
|
199
294
|
}
|
|
200
295
|
else {
|
|
201
296
|
if (text.tag === "Url") {
|
|
202
|
-
return
|
|
297
|
+
return (0, Utils_1.with_)(e, { is_ref: false, text: text.value.text, url: text.value.url });
|
|
203
298
|
}
|
|
204
299
|
else {
|
|
205
|
-
return
|
|
300
|
+
return (0, Utils_1.with_)(e, { is_ref: false, text: Resume_1.ItemContent.toString(text) });
|
|
206
301
|
}
|
|
207
302
|
}
|
|
208
303
|
}
|
package/dist/Layout.d.ts
CHANGED
|
@@ -4,11 +4,12 @@ import * as Width from "./Width";
|
|
|
4
4
|
import * as Font from "./Font";
|
|
5
5
|
import { ItemContent } from "./Resume";
|
|
6
6
|
import { Box } from "./Box";
|
|
7
|
-
import { FontDict } from "./AnyLayout";
|
|
7
|
+
import { ElementPath, FontDict } from "./AnyLayout";
|
|
8
8
|
import { Point } from "./Point";
|
|
9
9
|
import * as Stack from "./Stack";
|
|
10
10
|
import * as Row from "./Row";
|
|
11
11
|
import * as Elem from "./Elem";
|
|
12
|
+
import { Field } from "./DataSchema";
|
|
12
13
|
export type Container = Stack.t | Row.t;
|
|
13
14
|
export type t = Stack.t | Row.t | Elem.t;
|
|
14
15
|
type Layout = t;
|
|
@@ -23,7 +24,9 @@ export type RenderedRow = Row.t & {
|
|
|
23
24
|
export type RenderedElem = Elem.t & {
|
|
24
25
|
bounding_box: Box;
|
|
25
26
|
};
|
|
26
|
-
export type RenderedLayout = RenderedStack | RenderedRow | RenderedElem
|
|
27
|
+
export type RenderedLayout = (RenderedStack | RenderedRow | RenderedElem) & {
|
|
28
|
+
path?: ElementPath;
|
|
29
|
+
};
|
|
27
30
|
export declare function default_(tag: string): Stack.t | Row.t | Elem.t;
|
|
28
31
|
export declare function empty(): Layout;
|
|
29
32
|
export declare function fromJson(json: unknown): Layout;
|
|
@@ -39,7 +42,7 @@ export declare function withAlignment(l: Layout, alignment: Alignment.t): Layout
|
|
|
39
42
|
export declare function withWidth(l: Layout, width: Width.t): Layout;
|
|
40
43
|
export declare function totalElementsWidth(l: Layout): number;
|
|
41
44
|
export declare function isInstantiated(l: Layout): boolean;
|
|
42
|
-
export declare function instantiate(l: Layout, section: Map<string, ItemContent
|
|
45
|
+
export declare function instantiate(l: Layout, section: Map<string, ItemContent>, fields: Field.t[]): Layout;
|
|
43
46
|
export declare function boundWidth(l: Layout, width: number): Layout;
|
|
44
47
|
export declare function scaleWidth(l: Layout, document_width: number): Layout;
|
|
45
48
|
export declare function normalize(l: Layout, width: number, font_dict: FontDict): Layout;
|
package/dist/Layout.js
CHANGED
|
@@ -63,6 +63,7 @@ function fromJson(json) {
|
|
|
63
63
|
case 'Text': {
|
|
64
64
|
const inner = default_(key);
|
|
65
65
|
inner.item = json[key].item;
|
|
66
|
+
inner.text = json[key].item;
|
|
66
67
|
inner.margin = json[key].margin;
|
|
67
68
|
inner.alignment = json[key].alignment;
|
|
68
69
|
inner.width = Width.fromJson(json[key].width);
|
|
@@ -209,14 +210,14 @@ function isInstantiated(l) {
|
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
212
|
exports.isInstantiated = isInstantiated;
|
|
212
|
-
function instantiate(l, section) {
|
|
213
|
+
function instantiate(l, section, fields) {
|
|
213
214
|
switch (l.tag) {
|
|
214
215
|
case "Stack":
|
|
215
|
-
return Stack.
|
|
216
|
+
return Stack.withElements(l, l.elements.map(e => instantiate(e, section, fields)));
|
|
216
217
|
case "Row":
|
|
217
|
-
return Row.
|
|
218
|
+
return Row.withElements(l, l.elements.map(e => instantiate(e, section, fields)));
|
|
218
219
|
case "Elem":
|
|
219
|
-
return Elem.instantiate(l, section);
|
|
220
|
+
return Elem.instantiate(l, section, fields);
|
|
220
221
|
}
|
|
221
222
|
}
|
|
222
223
|
exports.instantiate = instantiate;
|
|
@@ -266,9 +267,10 @@ function normalize(l, width, font_dict) {
|
|
|
266
267
|
console.debug("Widths are bounded. Filling fonts...");
|
|
267
268
|
const font_filled_layout = fillFonts(bounded_layout, font_dict);
|
|
268
269
|
console.debug("Fonts filled. Breaking lines...");
|
|
269
|
-
const broken_layout = breakLines(font_filled_layout, font_dict);
|
|
270
|
+
// const broken_layout = breakLines(font_filled_layout, font_dict);
|
|
270
271
|
console.debug("Lines broken.");
|
|
271
|
-
return broken_layout;
|
|
272
|
+
// return broken_layout;
|
|
273
|
+
return font_filled_layout;
|
|
272
274
|
}
|
|
273
275
|
exports.normalize = normalize;
|
|
274
276
|
function fillFonts(l, font_dict) {
|
|
@@ -354,7 +356,11 @@ function computeTextboxPositions(l, top_left, font_dict) {
|
|
|
354
356
|
top_left = top_left.move_y_to(depth);
|
|
355
357
|
renderedElements.push(result.renderedLayout);
|
|
356
358
|
}
|
|
357
|
-
return {
|
|
359
|
+
return {
|
|
360
|
+
depth, renderedLayout: {
|
|
361
|
+
...l, bounding_box: new Box_1.Box(originalTopLeft, top_left.move_x_by(Width.get_fixed_unchecked(stack.width))), elements: renderedElements
|
|
362
|
+
}
|
|
363
|
+
};
|
|
358
364
|
}
|
|
359
365
|
case "Row": {
|
|
360
366
|
const row = l;
|
|
@@ -380,29 +386,41 @@ function computeTextboxPositions(l, top_left, font_dict) {
|
|
|
380
386
|
top_left.move_x_by(Width.get_fixed_unchecked(element.width) + per_elem_space);
|
|
381
387
|
renderedElements.push(result.renderedLayout);
|
|
382
388
|
}
|
|
383
|
-
return {
|
|
389
|
+
return {
|
|
390
|
+
depth, renderedLayout: {
|
|
391
|
+
...l, bounding_box: new Box_1.Box(originalTopLeft, originalTopLeft.move_y_by(depth).move_x_by(Width.get_fixed_unchecked(row.width))), elements: renderedElements
|
|
392
|
+
}
|
|
393
|
+
};
|
|
384
394
|
}
|
|
385
395
|
case "Elem": {
|
|
386
396
|
const elem = l;
|
|
387
397
|
if (elem.is_ref) {
|
|
388
398
|
throw new Error("Cannot compute textbox positions of uninstantiated layout");
|
|
389
399
|
}
|
|
390
|
-
if (elem.item === "") {
|
|
391
|
-
return { depth, renderedLayout: { ...l, bounding_box: new Box_1.Box(top_left, top_left) } };
|
|
392
|
-
}
|
|
393
400
|
const height = Font.get_height(elem.font, font_dict);
|
|
394
401
|
const width = Width.get_fixed_unchecked(elem.text_width);
|
|
395
402
|
top_left = top_left.move_y_by(elem.margin.top).move_x_by(elem.margin.left);
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
403
|
+
let line = 1;
|
|
404
|
+
let cursor = top_left.x;
|
|
405
|
+
elem.spans.forEach(span => {
|
|
406
|
+
if (cursor - top_left.x + span.width > Width.get_fixed_unchecked(elem.width) - elem.margin.right || span.text === "\n\n") {
|
|
407
|
+
cursor = top_left.x;
|
|
408
|
+
line += 1;
|
|
409
|
+
}
|
|
410
|
+
span.bbox = new Box_1.Box(new Point_1.Point(cursor - top_left.x, (line - 1) * height), new Point_1.Point(cursor + span.width, line * height));
|
|
411
|
+
span.line = line;
|
|
412
|
+
cursor += span.width;
|
|
413
|
+
});
|
|
414
|
+
// switch (elem.alignment) {
|
|
415
|
+
// case "Center":
|
|
416
|
+
// top_left = top_left.move_x_by((Width.get_fixed_unchecked(elem.width) - width) / 2.0);
|
|
417
|
+
// break;
|
|
418
|
+
// case "Right":
|
|
419
|
+
// top_left = top_left.move_x_by(Width.get_fixed_unchecked(elem.width) - width);
|
|
420
|
+
// break;
|
|
421
|
+
// }
|
|
422
|
+
const textbox = new Box_1.Box(top_left, top_left.move_x_by(width).move_y_by(height * line));
|
|
423
|
+
return { depth: top_left.y + height * line, renderedLayout: { ...l, bounding_box: textbox } };
|
|
406
424
|
}
|
|
407
425
|
}
|
|
408
426
|
}
|
package/dist/PdfLayout.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { DataSchema } from "./DataSchema";
|
|
|
5
5
|
import { LayoutSchema } from "./LayoutSchema";
|
|
6
6
|
import { ResumeLayout } from "./ResumeLayout";
|
|
7
7
|
import { Storage } from "./Storage";
|
|
8
|
+
import * as Elem from "./Elem";
|
|
8
9
|
import { Layout } from ".";
|
|
9
10
|
export type RenderResult = {
|
|
10
11
|
blob: Blob;
|
|
@@ -20,5 +21,6 @@ export type RenderProps = {
|
|
|
20
21
|
fontDict?: FontDict;
|
|
21
22
|
debug: boolean;
|
|
22
23
|
};
|
|
23
|
-
export declare const render: ({ resume_name, resume, data_schemas, layout_schemas, resume_layout, storage, fontDict
|
|
24
|
+
export declare const render: ({ resume_name, resume, data_schemas, layout_schemas, resume_layout, storage, fontDict }: RenderProps) => Promise<RenderResult>;
|
|
25
|
+
export declare const mergeSpans: (spans: Elem.Span[]) => Elem.Span[];
|
|
24
26
|
export declare const renderSectionLayout: (layout: Layout.RenderedLayout, resume_layout: ResumeLayout, current_height: number, doc: PDFKit.PDFDocument) => void;
|
package/dist/PdfLayout.js
CHANGED
|
@@ -3,12 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.renderSectionLayout = exports.render = void 0;
|
|
6
|
+
exports.renderSectionLayout = exports.mergeSpans = exports.render = void 0;
|
|
7
7
|
const blob_stream_1 = __importDefault(require("blob-stream"));
|
|
8
8
|
const AnyLayout_1 = require("./AnyLayout");
|
|
9
9
|
const pdfkit_1 = __importDefault(require("pdfkit"));
|
|
10
10
|
const _1 = require(".");
|
|
11
|
-
const render = async ({ resume_name, resume, data_schemas, layout_schemas, resume_layout, storage, fontDict
|
|
11
|
+
const render = async ({ resume_name, resume, data_schemas, layout_schemas, resume_layout, storage, fontDict }) => {
|
|
12
12
|
let start_time = Date.now();
|
|
13
13
|
if (!resume && !resume_name) {
|
|
14
14
|
throw "Rendering requires either resume_name or resume";
|
|
@@ -37,7 +37,7 @@ const render = async ({ resume_name, resume, data_schemas, layout_schemas, resum
|
|
|
37
37
|
// doc.pipe(fs.createWriteStream('output.pdf'));
|
|
38
38
|
const stream = doc.pipe((0, blob_stream_1.default)());
|
|
39
39
|
start_time = Date.now();
|
|
40
|
-
const
|
|
40
|
+
const layouts = await (0, AnyLayout_1.render)({ layout_schemas, resume, data_schemas, resume_layout, storage, fontDict });
|
|
41
41
|
end_time = Date.now();
|
|
42
42
|
console.info(`Rendering time: ${end_time - start_time}ms`);
|
|
43
43
|
console.log("Constructing printpdf font dictionary...");
|
|
@@ -46,7 +46,7 @@ const render = async ({ resume_name, resume, data_schemas, layout_schemas, resum
|
|
|
46
46
|
// "/Users/akeles/Programming/projects/cvdl/cvdl/assets/Exo/static/Exo-Medium.ttf");
|
|
47
47
|
try {
|
|
48
48
|
console.log("Registering fonts...");
|
|
49
|
-
for (const [font_name, font] of
|
|
49
|
+
for (const [font_name, font] of fontDict.fonts.entries()) {
|
|
50
50
|
console.log(`Registering font ${font_name}`);
|
|
51
51
|
// @ts-ignore
|
|
52
52
|
doc.registerFont(font_name, font.stream.buffer);
|
|
@@ -56,36 +56,16 @@ const render = async ({ resume_name, resume, data_schemas, layout_schemas, resum
|
|
|
56
56
|
console.error(e);
|
|
57
57
|
}
|
|
58
58
|
console.log("Rendering the document...");
|
|
59
|
-
// Render the boxes
|
|
60
|
-
// for (const [index, boxes] of pages.entries()) {
|
|
61
|
-
// if (index > 0) {
|
|
62
|
-
// doc.addPage();
|
|
63
|
-
// }
|
|
64
|
-
// boxes.forEach((box) => {
|
|
65
|
-
// const elements = box.elements;
|
|
66
|
-
// // if (debug) {
|
|
67
|
-
// // doc.rect(box.bounding_box.top_left.x, box.bounding_box.top_left.y, box.bounding_box.width(), box.bounding_box.height()).stroke();
|
|
68
|
-
// // }
|
|
69
|
-
// for (const [box_, element] of elements) {
|
|
70
|
-
// console.log(
|
|
71
|
-
// `(${box_.top_left.x}, ${box_.top_left.y})(${box_.bottom_right.x}, ${box_.bottom_right.y}): ${element.item}`
|
|
72
|
-
// );
|
|
73
|
-
// if (element.background_color !== "Transparent") {
|
|
74
|
-
// doc.rect(box_.top_left.x, box_.top_left.y, box_.width(), box_.height()).fillAndStroke(ColorMap[element.background_color], ColorMap[element.background_color]);
|
|
75
|
-
// }
|
|
76
|
-
// // Make this more generic
|
|
77
|
-
// doc.fillColor("black");
|
|
78
|
-
// doc.
|
|
79
|
-
// font(element.font.full_name()).
|
|
80
|
-
// fontSize(element.font.size).
|
|
81
|
-
// text(element.item, box_.top_left.x, box_.top_left.y, { lineBreak: false });
|
|
82
|
-
// if (debug) {
|
|
83
|
-
// // doc.rect(box_.top_left.x, box_.top_left.y, box_.width(), box_.height()).stroke();
|
|
84
|
-
// }
|
|
85
|
-
// }
|
|
86
|
-
// });
|
|
87
|
-
// }
|
|
88
59
|
let current_height = 0;
|
|
60
|
+
// Add rulers to the document at every 10 pixels
|
|
61
|
+
doc.strokeColor("grey");
|
|
62
|
+
for (let i = 0; i < resume_layout.height; i += 10) {
|
|
63
|
+
doc.moveTo(0, i).lineTo(resume_layout.width, i).stroke();
|
|
64
|
+
}
|
|
65
|
+
for (let i = 0; i < resume_layout.width; i += 10) {
|
|
66
|
+
doc.moveTo(i, 0).lineTo(i, resume_layout.height).stroke();
|
|
67
|
+
}
|
|
68
|
+
doc.strokeColor("black");
|
|
89
69
|
for (const layout of layouts) {
|
|
90
70
|
(0, exports.renderSectionLayout)(layout, resume_layout, current_height, doc);
|
|
91
71
|
current_height += layout.bounding_box.height() + layout.margin.top + layout.margin.bottom;
|
|
@@ -103,6 +83,27 @@ const render = async ({ resume_name, resume, data_schemas, layout_schemas, resum
|
|
|
103
83
|
});
|
|
104
84
|
};
|
|
105
85
|
exports.render = render;
|
|
86
|
+
const mergeSpans = (spans) => {
|
|
87
|
+
const merged_spans = [];
|
|
88
|
+
let currentSpan = spans[0];
|
|
89
|
+
for (let i = 1; i < spans.length; i++) {
|
|
90
|
+
if (currentSpan.bbox.top_left.y === spans[i].bbox.top_left.y
|
|
91
|
+
&& currentSpan.font === spans[i].font
|
|
92
|
+
&& currentSpan.is_code === spans[i].is_code
|
|
93
|
+
&& currentSpan.is_bold === spans[i].is_bold
|
|
94
|
+
&& currentSpan.is_italic === spans[i].is_italic) {
|
|
95
|
+
currentSpan.text += spans[i].text;
|
|
96
|
+
currentSpan.bbox.bottom_right = spans[i].bbox.bottom_right;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
merged_spans.push(currentSpan);
|
|
100
|
+
currentSpan = spans[i];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
merged_spans.push(currentSpan);
|
|
104
|
+
return merged_spans;
|
|
105
|
+
};
|
|
106
|
+
exports.mergeSpans = mergeSpans;
|
|
106
107
|
const renderSectionLayout = (layout, resume_layout, current_height, doc) => {
|
|
107
108
|
switch (layout.tag) {
|
|
108
109
|
case "Stack": {
|
|
@@ -121,10 +122,31 @@ const renderSectionLayout = (layout, resume_layout, current_height, doc) => {
|
|
|
121
122
|
}
|
|
122
123
|
case "Elem": {
|
|
123
124
|
const elem = layout;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
elem.spans.forEach((span) => {
|
|
126
|
+
console.log("Rendering span:", span);
|
|
127
|
+
doc.
|
|
128
|
+
font(_1.Font.full_name(span.font)).
|
|
129
|
+
fontSize(span.font.size).
|
|
130
|
+
text(span.text, layout.bounding_box.top_left.x
|
|
131
|
+
+ resume_layout.margin.left
|
|
132
|
+
+ span.bbox.top_left.x, layout.bounding_box.top_left.y
|
|
133
|
+
+ resume_layout.margin.top
|
|
134
|
+
+ current_height
|
|
135
|
+
+ span.bbox.top_left.y, { lineBreak: false });
|
|
136
|
+
if (span.is_code) {
|
|
137
|
+
// Add a rounded rectangle around the code
|
|
138
|
+
doc.roundedRect(layout.bounding_box.top_left.x + resume_layout.margin.left + span.bbox.top_left.x - span.font.size / 5, layout.bounding_box.top_left.y + resume_layout.margin.top + current_height + span.bbox.top_left.y, span.bbox.width() + span.font.size / 5 * 2, span.bbox.height(), 5).stroke();
|
|
139
|
+
// Add a background color to the code
|
|
140
|
+
doc.fillColor("black");
|
|
141
|
+
doc.fillOpacity(0.05);
|
|
142
|
+
doc.rect(layout.bounding_box.top_left.x + resume_layout.margin.left + span.bbox.top_left.x - span.font.size / 5, layout.bounding_box.top_left.y + resume_layout.margin.top + current_height + span.bbox.top_left.y, span.bbox.width() + span.font.size / 5 * 2, span.bbox.height()).fill();
|
|
143
|
+
doc.fillOpacity(1);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
// doc.
|
|
147
|
+
// font(Font.full_name(elem.font)).
|
|
148
|
+
// fontSize(elem.font.size).
|
|
149
|
+
// text(elem.item, layout.bounding_box.top_left.x + resume_layout.margin.left, layout.bounding_box.top_left.y + resume_layout.margin.top + current_height, { lineBreak: false });
|
|
128
150
|
break;
|
|
129
151
|
}
|
|
130
152
|
}
|
package/dist/Row.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Alignment, Margin, Width } from ".";
|
|
2
2
|
import { FontDict } from "./AnyLayout";
|
|
3
|
-
import { Optional } from "./
|
|
3
|
+
import { Optional } from "./Utils";
|
|
4
4
|
import * as Layout from "./Layout";
|
|
5
|
-
import { ItemContent } from "./Resume";
|
|
6
5
|
export type t = {
|
|
7
6
|
tag: "Row";
|
|
8
7
|
elements: Layout.t[];
|
|
@@ -13,12 +12,10 @@ export type t = {
|
|
|
13
12
|
is_fill: boolean;
|
|
14
13
|
};
|
|
15
14
|
type Row = t;
|
|
16
|
-
export declare function with_(e: Row, w: Optional<Row>): Row;
|
|
17
15
|
export declare function from(w: Optional<Row>): Row;
|
|
18
16
|
export declare function row(elements: Layout.t[], margin: Margin.t, alignment: Alignment.t, width: Width.t, is_frozen: boolean, is_fill: boolean): Row;
|
|
19
17
|
export declare function copy(r: Row): Row;
|
|
20
18
|
export declare function default_(): Row;
|
|
21
|
-
export declare function instantiate(r: Row, section: Map<string, ItemContent>): Row;
|
|
22
19
|
export declare function withElements(r: Row, elements: Layout.t[]): Row;
|
|
23
20
|
export declare function withMargin(r: Row, margin: Margin.t): Row;
|
|
24
21
|
export declare function withAlignment(r: Row, alignment: Alignment.t): Row;
|
package/dist/Row.js
CHANGED
|
@@ -23,13 +23,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.breakLines = exports.scaleWidth = exports.boundWidth = exports.elementsWidth = exports.withFill = exports.withFrozen = exports.withWidth = exports.withAlignment = exports.withMargin = exports.withElements = exports.
|
|
26
|
+
exports.breakLines = exports.scaleWidth = exports.boundWidth = exports.elementsWidth = exports.withFill = exports.withFrozen = exports.withWidth = exports.withAlignment = exports.withMargin = exports.withElements = exports.default_ = exports.copy = exports.row = exports.from = void 0;
|
|
27
27
|
const _1 = require(".");
|
|
28
28
|
const Layout = __importStar(require("./Layout"));
|
|
29
|
-
function with_(e, w) {
|
|
30
|
-
return { ...e, ...w };
|
|
31
|
-
}
|
|
32
|
-
exports.with_ = with_;
|
|
33
29
|
function from(w) {
|
|
34
30
|
return { ...default_(), ...w };
|
|
35
31
|
}
|
|
@@ -64,10 +60,6 @@ function default_() {
|
|
|
64
60
|
};
|
|
65
61
|
}
|
|
66
62
|
exports.default_ = default_;
|
|
67
|
-
function instantiate(r, section) {
|
|
68
|
-
return withElements(r, r.elements.map(e => Layout.instantiate(e, section)));
|
|
69
|
-
}
|
|
70
|
-
exports.instantiate = instantiate;
|
|
71
63
|
function withElements(r, elements) {
|
|
72
64
|
return {
|
|
73
65
|
...r,
|
package/dist/Stack.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Alignment, Layout, Margin, Width } from ".";
|
|
2
|
-
import { Optional } from "./
|
|
3
|
-
import { ItemContent } from "./Resume";
|
|
2
|
+
import { Optional } from "./Utils";
|
|
4
3
|
export type t = {
|
|
5
4
|
tag: "Stack";
|
|
6
5
|
elements: Layout.t[];
|
|
@@ -10,12 +9,10 @@ export type t = {
|
|
|
10
9
|
is_fill: boolean;
|
|
11
10
|
};
|
|
12
11
|
type Stack = t;
|
|
13
|
-
export declare function with_(e: Stack, w: Optional<Stack>): Stack;
|
|
14
12
|
export declare function from(w: Optional<Stack>): Stack;
|
|
15
13
|
export declare function stack(elements: Layout.t[], margin: Margin.t, alignment: Alignment.t, width: Width.t, is_fill: boolean): Stack;
|
|
16
14
|
export declare function copy(s: Stack): Stack;
|
|
17
15
|
export declare function default_(): Stack;
|
|
18
|
-
export declare function instantiate(s: Stack, section: Map<string, ItemContent>): Stack;
|
|
19
16
|
export declare function withElements(s: Stack, elements: Layout.t[]): Stack;
|
|
20
17
|
export declare function withMargin(s: Stack, margin: Margin.t): Stack;
|
|
21
18
|
export declare function withAlignment(s: Stack, alignment: Alignment.t): Stack;
|
package/dist/Stack.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.scaleWidth = exports.boundWidth = exports.withIsFill = exports.withWidth = exports.withAlignment = exports.withMargin = exports.withElements = exports.
|
|
3
|
+
exports.scaleWidth = exports.boundWidth = exports.withIsFill = exports.withWidth = exports.withAlignment = exports.withMargin = exports.withElements = exports.default_ = exports.copy = exports.stack = exports.from = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
|
-
function with_(e, w) {
|
|
6
|
-
return { ...e, ...w };
|
|
7
|
-
}
|
|
8
|
-
exports.with_ = with_;
|
|
9
5
|
function from(w) {
|
|
10
6
|
return { ...default_(), ...w };
|
|
11
7
|
}
|
|
@@ -38,10 +34,6 @@ function default_() {
|
|
|
38
34
|
};
|
|
39
35
|
}
|
|
40
36
|
exports.default_ = default_;
|
|
41
|
-
function instantiate(s, section) {
|
|
42
|
-
return withElements(s, s.elements.map(e => _1.Layout.instantiate(e, section)));
|
|
43
|
-
}
|
|
44
|
-
exports.instantiate = instantiate;
|
|
45
37
|
function withElements(s, elements) {
|
|
46
38
|
return {
|
|
47
39
|
...s,
|
package/dist/Utils.d.ts
ADDED
package/dist/Utils.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cvdl-ts",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "Typescript Implementation of CVDL Compiler",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -13,13 +13,19 @@
|
|
|
13
13
|
"@types/pdfkit": "^0.13.1",
|
|
14
14
|
"blob-stream": "^0.1.3",
|
|
15
15
|
"fontkit": "^2.0.2",
|
|
16
|
-
"
|
|
16
|
+
"marked": "^13.0.2",
|
|
17
|
+
"pdfkit": "^0.13.0",
|
|
18
|
+
"ts-pattern": "^5.2.0"
|
|
17
19
|
},
|
|
18
20
|
"devDependencies": {
|
|
21
|
+
"@eslint/compat": "^1.1.1",
|
|
22
|
+
"@eslint/js": "^9.7.0",
|
|
19
23
|
"@types/node": "^20.8.7",
|
|
20
24
|
"@typescript-eslint/eslint-plugin": "^6.8.0",
|
|
21
25
|
"@typescript-eslint/parser": "^6.8.0",
|
|
22
|
-
"eslint": "^
|
|
26
|
+
"eslint-plugin-react": "^7.34.4",
|
|
27
|
+
"globals": "^15.8.0",
|
|
28
|
+
"typescript-eslint": "^7.16.1"
|
|
23
29
|
},
|
|
24
30
|
"scripts": {
|
|
25
31
|
"lint": "eslint . --ext .ts",
|