md2cv 1.1.1 → 1.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 +21 -0
- package/README.ja.md +69 -1
- package/README.md +77 -11
- package/dist/cli/index.d.ts +17 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +140 -34
- package/dist/cli/index.js.map +1 -1
- package/dist/generator/common.d.ts +86 -0
- package/dist/generator/common.d.ts.map +1 -0
- package/dist/generator/common.js +326 -0
- package/dist/generator/common.js.map +1 -0
- package/dist/generator/index.d.ts +39 -12
- package/dist/generator/index.d.ts.map +1 -1
- package/dist/generator/index.js +65 -41
- package/dist/generator/index.js.map +1 -1
- package/dist/generator/resume_en.d.ts +4 -15
- package/dist/generator/resume_en.d.ts.map +1 -1
- package/dist/generator/resume_en.js +23 -319
- package/dist/generator/resume_en.js.map +1 -1
- package/dist/generator/resume_ja.d.ts +4 -15
- package/dist/generator/resume_ja.d.ts.map +1 -1
- package/dist/generator/resume_ja.js +18 -260
- package/dist/generator/resume_ja.js.map +1 -1
- package/dist/generator/rirekisho/components.d.ts.map +1 -1
- package/dist/generator/rirekisho/components.js +1 -1
- package/dist/generator/rirekisho/components.js.map +1 -1
- package/dist/generator/rirekisho/index.js.map +1 -1
- package/dist/generator/rirekisho/layout.d.ts.map +1 -1
- package/dist/generator/rirekisho/layout.js +16 -7
- package/dist/generator/rirekisho/layout.js.map +1 -1
- package/dist/generator/rirekisho/styles.d.ts.map +1 -1
- package/dist/generator/rirekisho/styles.js +9 -14
- package/dist/generator/rirekisho/styles.js.map +1 -1
- package/dist/generator/rirekisho/types.d.ts +2 -2
- package/dist/generator/rirekisho/types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +224 -107
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/lsp.d.ts +58 -0
- package/dist/parser/lsp.d.ts.map +1 -0
- package/dist/parser/lsp.js +265 -0
- package/dist/parser/lsp.js.map +1 -0
- package/dist/template/definitions/en.d.ts +17 -0
- package/dist/template/definitions/en.d.ts.map +1 -0
- package/dist/template/definitions/en.js +204 -0
- package/dist/template/definitions/en.js.map +1 -0
- package/dist/template/definitions/index.d.ts +6 -0
- package/dist/template/definitions/index.d.ts.map +1 -0
- package/dist/template/definitions/index.js +6 -0
- package/dist/template/definitions/index.js.map +1 -0
- package/dist/template/definitions/ja.d.ts +17 -0
- package/dist/template/definitions/ja.d.ts.map +1 -0
- package/dist/template/definitions/ja.js +243 -0
- package/dist/template/definitions/ja.js.map +1 -0
- package/dist/template/generator.d.ts +61 -0
- package/dist/template/generator.d.ts.map +1 -0
- package/dist/template/generator.js +219 -0
- package/dist/template/generator.js.map +1 -0
- package/dist/template/index.d.ts +6 -0
- package/dist/template/index.d.ts.map +1 -0
- package/dist/template/index.js +6 -0
- package/dist/template/index.js.map +1 -0
- package/dist/types/config.d.ts +126 -15
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +94 -1
- package/dist/types/config.js.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/position.d.ts +42 -0
- package/dist/types/position.d.ts.map +1 -0
- package/dist/types/position.js +32 -0
- package/dist/types/position.js.map +1 -0
- package/dist/types/result.d.ts.map +1 -1
- package/dist/types/result.js.map +1 -1
- package/dist/types/sections.d.ts +39 -24
- package/dist/types/sections.d.ts.map +1 -1
- package/dist/types/sections.js +30 -2
- package/dist/types/sections.js.map +1 -1
- package/dist/types/template.d.ts +68 -0
- package/dist/types/template.d.ts.map +1 -0
- package/dist/types/template.js +12 -0
- package/dist/types/template.js.map +1 -0
- package/dist/validator/index.d.ts.map +1 -1
- package/dist/validator/index.js +1 -2
- package/dist/validator/index.js.map +1 -1
- package/examples/example-cv-ja.md +1 -1
- package/package.json +53 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/generator/common.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,eAAe,EACf,aAAa,EACb,aAAa,EACb,cAAc,EACd,UAAU,EACV,aAAa,EACd,MAAM,sBAAsB,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;CAC7C;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAOzE,CAAC;AAEJ;;GAEG;AACH,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ/C;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,MAAM,CAAC;IAC3C,aAAa,CAAC,GAAG,EAAE,IAAI,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IACzD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,aAyB7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,aAW7B,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,IAAI,GAAG,SAAS,EACvB,GAAG,EAAE,IAAI,GAAG,SAAS,GAAG,SAAS,EACjC,SAAS,EAAE,aAAa,GACvB,MAAM,CAMR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,SAAS,EAAE,aAAa,GACvB,MAAM,CAoCR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,SAAS,kBAAkB,EAAE,EACtC,SAAS,EAAE,aAAa,GACvB,MAAM,CAWR;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,aAAa,GACvB,MAAM,CA0CR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,GAAE,MAA+B,GACvC,MAAM,CAcR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAWzE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,SAAS,eAAe,EAAE,GAClC,MAAM,CAMR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,SAAS,EAAE,aAAa,EACxB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7D,MAAM,CAwER;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,aAAa,GACvB,MAAM,CAoCR"}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common utilities for CV/Resume generators
|
|
3
|
+
* Shared between English and Japanese CV generators
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Page size dimensions in mm
|
|
7
|
+
* CV uses portrait orientation (width < height)
|
|
8
|
+
*/
|
|
9
|
+
export const PAGE_SIZES = {
|
|
10
|
+
a3: { width: 297, height: 420 },
|
|
11
|
+
a4: { width: 210, height: 297 },
|
|
12
|
+
b4: { width: 257, height: 364 },
|
|
13
|
+
b5: { width: 182, height: 257 },
|
|
14
|
+
letter: { width: 215.9, height: 279.4 },
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Default number of columns for skills grid
|
|
18
|
+
*/
|
|
19
|
+
export const DEFAULT_SKILLS_COLUMNS = 3;
|
|
20
|
+
/**
|
|
21
|
+
* Escape HTML special characters
|
|
22
|
+
*/
|
|
23
|
+
export function escapeHtml(text) {
|
|
24
|
+
if (text == null)
|
|
25
|
+
return '';
|
|
26
|
+
return text
|
|
27
|
+
.replace(/&/g, '&')
|
|
28
|
+
.replace(/</g, '<')
|
|
29
|
+
.replace(/>/g, '>')
|
|
30
|
+
.replace(/"/g, '"')
|
|
31
|
+
.replace(/'/g, ''');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* English date formatter
|
|
35
|
+
*/
|
|
36
|
+
export const enDateFormatter = {
|
|
37
|
+
formatDate(date) {
|
|
38
|
+
if (!date)
|
|
39
|
+
return '';
|
|
40
|
+
const months = [
|
|
41
|
+
'Jan',
|
|
42
|
+
'Feb',
|
|
43
|
+
'Mar',
|
|
44
|
+
'Apr',
|
|
45
|
+
'May',
|
|
46
|
+
'Jun',
|
|
47
|
+
'Jul',
|
|
48
|
+
'Aug',
|
|
49
|
+
'Sep',
|
|
50
|
+
'Oct',
|
|
51
|
+
'Nov',
|
|
52
|
+
'Dec',
|
|
53
|
+
];
|
|
54
|
+
return `${months[date.getMonth()]} ${date.getFullYear()}`;
|
|
55
|
+
},
|
|
56
|
+
formatEndDate(end) {
|
|
57
|
+
if (!end)
|
|
58
|
+
return '';
|
|
59
|
+
if (end === 'present')
|
|
60
|
+
return 'Present';
|
|
61
|
+
return this.formatDate(end);
|
|
62
|
+
},
|
|
63
|
+
itemSeparator: ', ',
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Japanese date formatter
|
|
67
|
+
*/
|
|
68
|
+
export const jaDateFormatter = {
|
|
69
|
+
formatDate(date) {
|
|
70
|
+
if (!date)
|
|
71
|
+
return '';
|
|
72
|
+
return `${date.getFullYear()}年${date.getMonth() + 1}月`;
|
|
73
|
+
},
|
|
74
|
+
formatEndDate(end) {
|
|
75
|
+
if (!end)
|
|
76
|
+
return '';
|
|
77
|
+
if (end === 'present')
|
|
78
|
+
return '現在';
|
|
79
|
+
return this.formatDate(end);
|
|
80
|
+
},
|
|
81
|
+
itemSeparator: '、',
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Format date range using the provided formatter
|
|
85
|
+
*/
|
|
86
|
+
export function formatDateRange(start, end, formatter) {
|
|
87
|
+
const startStr = formatter.formatDate(start);
|
|
88
|
+
const endStr = formatter.formatEndDate(end);
|
|
89
|
+
if (startStr && endStr)
|
|
90
|
+
return `${startStr} - ${endStr}`;
|
|
91
|
+
if (startStr)
|
|
92
|
+
return startStr;
|
|
93
|
+
return '';
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Render education section
|
|
97
|
+
*/
|
|
98
|
+
export function renderEducation(entries, formatter) {
|
|
99
|
+
return entries
|
|
100
|
+
.map((entry) => {
|
|
101
|
+
const dateRange = formatDateRange(entry.start, entry.end, formatter);
|
|
102
|
+
let html = '<div class="entry">';
|
|
103
|
+
html += '<div class="entry-header">';
|
|
104
|
+
html += `<span class="entry-title">${escapeHtml(entry.school)}</span>`;
|
|
105
|
+
if (dateRange) {
|
|
106
|
+
html += `<span class="entry-date">${escapeHtml(dateRange)}</span>`;
|
|
107
|
+
}
|
|
108
|
+
html += '</div>';
|
|
109
|
+
const subtitleParts = [];
|
|
110
|
+
if (entry.degree) {
|
|
111
|
+
subtitleParts.push(escapeHtml(entry.degree));
|
|
112
|
+
}
|
|
113
|
+
if (entry.location) {
|
|
114
|
+
subtitleParts.push(escapeHtml(entry.location));
|
|
115
|
+
}
|
|
116
|
+
if (subtitleParts.length > 0) {
|
|
117
|
+
html += `<div class="entry-subtitle">${subtitleParts.join(' — ')}</div>`;
|
|
118
|
+
}
|
|
119
|
+
const nonEmptyDetails = entry.details?.filter((d) => d && d.trim()) ?? [];
|
|
120
|
+
if (nonEmptyDetails.length > 0) {
|
|
121
|
+
html += '<ul>';
|
|
122
|
+
for (const detail of nonEmptyDetails) {
|
|
123
|
+
html += `<li>${escapeHtml(detail)}</li>`;
|
|
124
|
+
}
|
|
125
|
+
html += '</ul>';
|
|
126
|
+
}
|
|
127
|
+
html += '</div>';
|
|
128
|
+
return html;
|
|
129
|
+
})
|
|
130
|
+
.join('\n');
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Render certifications section
|
|
134
|
+
*/
|
|
135
|
+
export function renderCertifications(entries, formatter) {
|
|
136
|
+
return entries
|
|
137
|
+
.map((entry) => {
|
|
138
|
+
let html = `<div class="cert-item">• ${escapeHtml(entry.name)}`;
|
|
139
|
+
if (entry.date) {
|
|
140
|
+
html += ` (${escapeHtml(formatter.formatDate(entry.date))})`;
|
|
141
|
+
}
|
|
142
|
+
html += '</div>';
|
|
143
|
+
return html;
|
|
144
|
+
})
|
|
145
|
+
.join('\n');
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Render skills section - supports grid and categorized formats
|
|
149
|
+
*/
|
|
150
|
+
export function renderSkills(entries, options, formatter) {
|
|
151
|
+
const isCategorized = options.format === 'categorized' ||
|
|
152
|
+
entries.some((e) => e.category && (e.description || (e.items && e.items.length > 0)));
|
|
153
|
+
if (isCategorized && entries.some((e) => e.category)) {
|
|
154
|
+
return entries
|
|
155
|
+
.filter((e) => e.category)
|
|
156
|
+
.map((entry) => {
|
|
157
|
+
const content = entry.description ||
|
|
158
|
+
(entry.items?.join(formatter.itemSeparator) ?? '');
|
|
159
|
+
return `<div class="skill-category">• <span class="skill-category-name">${escapeHtml(entry.category)}:</span> ${escapeHtml(content)}</div>`;
|
|
160
|
+
})
|
|
161
|
+
.join('\n');
|
|
162
|
+
}
|
|
163
|
+
const allItems = [];
|
|
164
|
+
for (const entry of entries) {
|
|
165
|
+
if (entry.items) {
|
|
166
|
+
for (const item of entry.items) {
|
|
167
|
+
allItems.push(item);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (allItems.length === 0) {
|
|
172
|
+
return '';
|
|
173
|
+
}
|
|
174
|
+
const columns = options.columns ?? DEFAULT_SKILLS_COLUMNS;
|
|
175
|
+
const colsClass = columns === 3 ? 'skills-grid--cols-3' : '';
|
|
176
|
+
const colsStyle = columns !== 3 ? `grid-template-columns: repeat(${columns}, 1fr);` : '';
|
|
177
|
+
let html = `<div class="skills-grid ${colsClass}"${colsStyle ? ` style="${colsStyle}"` : ''}>`;
|
|
178
|
+
for (const item of allItems) {
|
|
179
|
+
html += `<div class="skill-item">• ${escapeHtml(item)}</div>`;
|
|
180
|
+
}
|
|
181
|
+
html += '</div>';
|
|
182
|
+
return html;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Render skills from list content as grid
|
|
186
|
+
*/
|
|
187
|
+
export function renderSkillsList(items, columns = DEFAULT_SKILLS_COLUMNS) {
|
|
188
|
+
if (items.length === 0) {
|
|
189
|
+
return '';
|
|
190
|
+
}
|
|
191
|
+
const colsClass = columns === 3 ? 'skills-grid--cols-3' : '';
|
|
192
|
+
const colsStyle = columns !== 3 ? `grid-template-columns: repeat(${columns}, 1fr);` : '';
|
|
193
|
+
let html = `<div class="skills-grid ${colsClass}"${colsStyle ? ` style="${colsStyle}"` : ''}>`;
|
|
194
|
+
for (const item of items) {
|
|
195
|
+
html += `<div class="skill-item">• ${escapeHtml(item)}</div>`;
|
|
196
|
+
}
|
|
197
|
+
html += '</div>';
|
|
198
|
+
return html;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Render languages section
|
|
202
|
+
*/
|
|
203
|
+
export function renderLanguages(entries) {
|
|
204
|
+
return entries
|
|
205
|
+
.map((entry) => {
|
|
206
|
+
let html = `<span class="lang-item">${escapeHtml(entry.language)}`;
|
|
207
|
+
if (entry.level) {
|
|
208
|
+
html += ` (${escapeHtml(entry.level)})`;
|
|
209
|
+
}
|
|
210
|
+
html += '</span>';
|
|
211
|
+
return html;
|
|
212
|
+
})
|
|
213
|
+
.join(' • ');
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Render core competencies section
|
|
217
|
+
*/
|
|
218
|
+
export function renderCompetencies(entries) {
|
|
219
|
+
return entries
|
|
220
|
+
.map((entry) => {
|
|
221
|
+
return `<div class="competency-entry"><span class="competency-header">${escapeHtml(entry.header)}:</span> ${escapeHtml(entry.description)}</div>`;
|
|
222
|
+
})
|
|
223
|
+
.join('\n');
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Render experience section
|
|
227
|
+
*/
|
|
228
|
+
export function renderExperience(entries, formatter, options) {
|
|
229
|
+
const includeTeam = options?.includeTeam ?? true;
|
|
230
|
+
const includeProjects = options?.includeProjects ?? true;
|
|
231
|
+
return entries
|
|
232
|
+
.flatMap((entry) => {
|
|
233
|
+
return entry.roles.map((role) => {
|
|
234
|
+
const dateRange = formatDateRange(role.start, role.end, formatter);
|
|
235
|
+
let html = '<div class="entry">';
|
|
236
|
+
html += '<div class="entry-header">';
|
|
237
|
+
html += `<span class="entry-title">${escapeHtml(entry.company)} —— ${escapeHtml(role.title)}</span>`;
|
|
238
|
+
if (dateRange) {
|
|
239
|
+
html += `<span class="entry-date">${escapeHtml(dateRange)}</span>`;
|
|
240
|
+
}
|
|
241
|
+
html += '</div>';
|
|
242
|
+
if (includeTeam) {
|
|
243
|
+
const subtitleParts = [];
|
|
244
|
+
if (role.team) {
|
|
245
|
+
subtitleParts.push(escapeHtml(role.team));
|
|
246
|
+
}
|
|
247
|
+
if (entry.location) {
|
|
248
|
+
subtitleParts.push(escapeHtml(entry.location));
|
|
249
|
+
}
|
|
250
|
+
if (subtitleParts.length > 0) {
|
|
251
|
+
html += `<div class="entry-subtitle">${subtitleParts.join(' — ')}</div>`;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (role.summary && role.summary.length > 0) {
|
|
255
|
+
html += '<div class="entry-summary">';
|
|
256
|
+
html += role.summary.map((s) => escapeHtml(s)).join(' ');
|
|
257
|
+
html += '</div>';
|
|
258
|
+
}
|
|
259
|
+
if (role.highlights && role.highlights.length > 0) {
|
|
260
|
+
html += '<ul>';
|
|
261
|
+
for (const highlight of role.highlights) {
|
|
262
|
+
html += `<li>${escapeHtml(highlight)}</li>`;
|
|
263
|
+
}
|
|
264
|
+
html += '</ul>';
|
|
265
|
+
}
|
|
266
|
+
if (includeProjects && role.projects && role.projects.length > 0) {
|
|
267
|
+
for (const project of role.projects) {
|
|
268
|
+
const projDateRange = formatDateRange(project.start, project.end, formatter);
|
|
269
|
+
html += '<div class="project">';
|
|
270
|
+
html += `<span class="project-name">${escapeHtml(project.name)}</span>`;
|
|
271
|
+
if (projDateRange) {
|
|
272
|
+
html += ` <span class="entry-date">(${escapeHtml(projDateRange)})</span>`;
|
|
273
|
+
}
|
|
274
|
+
if (project.bullets && project.bullets.length > 0) {
|
|
275
|
+
html += '<ul>';
|
|
276
|
+
for (const bullet of project.bullets) {
|
|
277
|
+
html += `<li>${escapeHtml(bullet)}</li>`;
|
|
278
|
+
}
|
|
279
|
+
html += '</ul>';
|
|
280
|
+
}
|
|
281
|
+
html += '</div>';
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
html += '</div>';
|
|
285
|
+
return html;
|
|
286
|
+
});
|
|
287
|
+
})
|
|
288
|
+
.join('\n');
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Render section content
|
|
292
|
+
*/
|
|
293
|
+
export function renderSectionContent(content, sectionId, formatter) {
|
|
294
|
+
switch (content.type) {
|
|
295
|
+
case 'text':
|
|
296
|
+
return `<p>${escapeHtml(content.text)}</p>`;
|
|
297
|
+
case 'list':
|
|
298
|
+
if (sectionId === 'skills') {
|
|
299
|
+
return renderSkillsList(content.items);
|
|
300
|
+
}
|
|
301
|
+
return ('<ul>' +
|
|
302
|
+
content.items.map((item) => `<li>${escapeHtml(item)}</li>`).join('\n') +
|
|
303
|
+
'</ul>');
|
|
304
|
+
case 'education':
|
|
305
|
+
return renderEducation(content.entries, formatter);
|
|
306
|
+
case 'experience':
|
|
307
|
+
return renderExperience(content.entries, formatter);
|
|
308
|
+
case 'certifications':
|
|
309
|
+
return renderCertifications(content.entries, formatter);
|
|
310
|
+
case 'skills':
|
|
311
|
+
return renderSkills(content.entries, content.options, formatter);
|
|
312
|
+
case 'competencies':
|
|
313
|
+
return renderCompetencies(content.entries);
|
|
314
|
+
case 'languages':
|
|
315
|
+
return renderLanguages(content.entries);
|
|
316
|
+
case 'table':
|
|
317
|
+
return ('<ul>' +
|
|
318
|
+
content.rows
|
|
319
|
+
.map((row) => `<li>${escapeHtml(row.content)}</li>`)
|
|
320
|
+
.join('\n') +
|
|
321
|
+
'</ul>');
|
|
322
|
+
default:
|
|
323
|
+
return '';
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/generator/common.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,30 +4,57 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { Logger } from '../cli/index.js';
|
|
6
6
|
import type { PaperSize, ResolvedConfig } from '../types/config.js';
|
|
7
|
-
import type {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import { generateCVJaHTML } from './resume_ja.js';
|
|
7
|
+
import type { CVInput } from './common.js';
|
|
8
|
+
import { generateEnHtml } from './resume_en.js';
|
|
9
|
+
import { generateJaHtml } from './resume_ja.js';
|
|
11
10
|
import { generateRirekishoHTML } from './rirekisho/index.js';
|
|
12
|
-
export {
|
|
11
|
+
export { generateEnHtml, generateJaHtml, generateRirekishoHTML };
|
|
13
12
|
/**
|
|
14
|
-
*
|
|
13
|
+
* Page size dimensions in mm (portrait orientation for CV)
|
|
15
14
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
15
|
+
export declare const PAGE_SIZES: Record<PaperSize, {
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
}>;
|
|
20
19
|
/**
|
|
21
|
-
* Page size dimensions in mm
|
|
20
|
+
* Page size dimensions in mm (landscape orientation for Rirekisho)
|
|
22
21
|
*/
|
|
23
|
-
export declare const
|
|
22
|
+
export declare const PAGE_SIZES_LANDSCAPE: Record<PaperSize, {
|
|
24
23
|
width: number;
|
|
25
24
|
height: number;
|
|
26
25
|
}>;
|
|
26
|
+
/**
|
|
27
|
+
* MIME types for supported image formats
|
|
28
|
+
*/
|
|
29
|
+
export declare const IMAGE_MIME_TYPES: Record<string, string>;
|
|
30
|
+
/**
|
|
31
|
+
* Supported image file extensions (without leading dot)
|
|
32
|
+
*/
|
|
33
|
+
export declare const SUPPORTED_IMAGE_EXTENSIONS: readonly string[];
|
|
34
|
+
/**
|
|
35
|
+
* Read image file and convert to base64 data URI
|
|
36
|
+
*/
|
|
37
|
+
export declare function readPhotoAsDataUri(photoPath: string): string;
|
|
27
38
|
/**
|
|
28
39
|
* Escape HTML special characters
|
|
29
40
|
*/
|
|
30
41
|
export declare function escapeHtml(text: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Input type for detectLanguage function
|
|
44
|
+
*/
|
|
45
|
+
export interface DetectLanguageInput {
|
|
46
|
+
readonly metadata: {
|
|
47
|
+
name_ja?: string;
|
|
48
|
+
};
|
|
49
|
+
readonly sections: readonly {
|
|
50
|
+
title: string;
|
|
51
|
+
}[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Detect language from CV content
|
|
55
|
+
* Checks for Japanese name or Japanese section titles
|
|
56
|
+
*/
|
|
57
|
+
export declare function detectLanguage(cv: DetectLanguageInput): 'en' | 'ja';
|
|
31
58
|
/**
|
|
32
59
|
* Generate output files
|
|
33
60
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAKV,SAAS,EACT,cAAc,EACf,MAAM,oBAAoB,CAAC;AAM5B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,qBAAqB,EAAE,CAAC;AAEjE;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAOzE,CAAC;AAEJ;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CACvC,SAAS,EACT;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAOlC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMnD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAE5B,CAAC;AAE7B;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAY5D;AASD;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO/C;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,mBAAmB,GAAG,IAAI,GAAG,IAAI,CAgBnE;AA8OD;;GAEG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,OAAO,EACX,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,EAAE,CAAC,CAsFnB;AAED,eAAe,cAAc,CAAC"}
|
package/dist/generator/index.js
CHANGED
|
@@ -5,36 +5,50 @@
|
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import puppeteer from 'puppeteer';
|
|
8
|
-
import { findSectionByTag, isSectionValidForFormat } from '../types/sections.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { findSectionByTag, isSectionValidForFormat, } from '../types/sections.js';
|
|
9
|
+
import { generateEnHtml } from './resume_en.js';
|
|
10
|
+
import { generateJaHtml } from './resume_ja.js';
|
|
11
11
|
import { generateRirekishoHTML } from './rirekisho/index.js';
|
|
12
12
|
// Re-export generators
|
|
13
|
-
export {
|
|
13
|
+
export { generateEnHtml, generateJaHtml, generateRirekishoHTML };
|
|
14
14
|
/**
|
|
15
|
-
* Page size dimensions in mm
|
|
15
|
+
* Page size dimensions in mm (portrait orientation for CV)
|
|
16
16
|
*/
|
|
17
17
|
export const PAGE_SIZES = {
|
|
18
|
-
a3: { width:
|
|
18
|
+
a3: { width: 297, height: 420 },
|
|
19
19
|
a4: { width: 210, height: 297 },
|
|
20
|
-
b4: { width:
|
|
21
|
-
b5: { width:
|
|
20
|
+
b4: { width: 257, height: 364 },
|
|
21
|
+
b5: { width: 182, height: 257 },
|
|
22
22
|
letter: { width: 215.9, height: 279.4 },
|
|
23
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Page size dimensions in mm (landscape orientation for Rirekisho)
|
|
26
|
+
*/
|
|
27
|
+
export const PAGE_SIZES_LANDSCAPE = {
|
|
28
|
+
a3: { width: 420, height: 297 },
|
|
29
|
+
a4: { width: 297, height: 210 },
|
|
30
|
+
b4: { width: 364, height: 257 },
|
|
31
|
+
b5: { width: 257, height: 182 },
|
|
32
|
+
letter: { width: 279.4, height: 215.9 },
|
|
33
|
+
};
|
|
24
34
|
/**
|
|
25
35
|
* MIME types for supported image formats
|
|
26
36
|
*/
|
|
27
|
-
const IMAGE_MIME_TYPES = {
|
|
37
|
+
export const IMAGE_MIME_TYPES = {
|
|
28
38
|
'.png': 'image/png',
|
|
29
39
|
'.jpg': 'image/jpeg',
|
|
30
40
|
'.jpeg': 'image/jpeg',
|
|
31
41
|
'.tiff': 'image/tiff',
|
|
32
42
|
'.tif': 'image/tiff',
|
|
33
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Supported image file extensions (without leading dot)
|
|
46
|
+
*/
|
|
47
|
+
export const SUPPORTED_IMAGE_EXTENSIONS = Object.keys(IMAGE_MIME_TYPES).map((ext) => ext.slice(1));
|
|
34
48
|
/**
|
|
35
49
|
* Read image file and convert to base64 data URI
|
|
36
50
|
*/
|
|
37
|
-
function readPhotoAsDataUri(photoPath) {
|
|
51
|
+
export function readPhotoAsDataUri(photoPath) {
|
|
38
52
|
const ext = path.extname(photoPath).toLowerCase();
|
|
39
53
|
const mimeType = IMAGE_MIME_TYPES[ext];
|
|
40
54
|
if (!mimeType) {
|
|
@@ -63,14 +77,17 @@ export function escapeHtml(text) {
|
|
|
63
77
|
}
|
|
64
78
|
/**
|
|
65
79
|
* Detect language from CV content
|
|
80
|
+
* Checks for Japanese name or Japanese section titles
|
|
66
81
|
*/
|
|
67
|
-
function detectLanguage(cv) {
|
|
82
|
+
export function detectLanguage(cv) {
|
|
83
|
+
// Import isJapaneseText from sections to avoid duplication
|
|
84
|
+
const isJapanese = (text) => /[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FAF]/.test(text);
|
|
68
85
|
// Check if name_ja exists or if sections have Japanese titles
|
|
69
86
|
if (cv.metadata.name_ja)
|
|
70
87
|
return 'ja';
|
|
71
88
|
for (const section of cv.sections) {
|
|
72
89
|
// Check for Japanese characters in title
|
|
73
|
-
if (
|
|
90
|
+
if (isJapanese(section.title)) {
|
|
74
91
|
return 'ja';
|
|
75
92
|
}
|
|
76
93
|
}
|
|
@@ -79,19 +96,28 @@ function detectLanguage(cv) {
|
|
|
79
96
|
/**
|
|
80
97
|
* Default section order for CV format
|
|
81
98
|
*/
|
|
82
|
-
const DEFAULT_CV_SECTION_ORDER = [
|
|
99
|
+
const DEFAULT_CV_SECTION_ORDER = [
|
|
100
|
+
'summary',
|
|
101
|
+
'experience',
|
|
102
|
+
'education',
|
|
103
|
+
'skills',
|
|
104
|
+
'certifications',
|
|
105
|
+
'languages',
|
|
106
|
+
'competencies',
|
|
107
|
+
'motivation',
|
|
108
|
+
];
|
|
83
109
|
/**
|
|
84
110
|
* Resolve section ID from tag or ID
|
|
85
111
|
* Returns the section ID if input matches a tag or is already an ID
|
|
86
112
|
*/
|
|
87
113
|
function resolveSectionId(input, sections) {
|
|
88
114
|
// First check if it's a direct section ID match
|
|
89
|
-
const directMatch = sections.find(s => s.id === input);
|
|
115
|
+
const directMatch = sections.find((s) => s.id === input);
|
|
90
116
|
if (directMatch) {
|
|
91
117
|
return directMatch.id;
|
|
92
118
|
}
|
|
93
119
|
// Then check if it matches a section title (case-insensitive)
|
|
94
|
-
const titleMatch = sections.find(s => s.title.toLowerCase() === input.toLowerCase());
|
|
120
|
+
const titleMatch = sections.find((s) => s.title.toLowerCase() === input.toLowerCase());
|
|
95
121
|
if (titleMatch) {
|
|
96
122
|
return titleMatch.id;
|
|
97
123
|
}
|
|
@@ -99,7 +125,7 @@ function resolveSectionId(input, sections) {
|
|
|
99
125
|
const def = findSectionByTag(input);
|
|
100
126
|
if (def) {
|
|
101
127
|
// Check if this section exists in the input
|
|
102
|
-
const sectionExists = sections.find(s => s.id === def.id);
|
|
128
|
+
const sectionExists = sections.find((s) => s.id === def.id);
|
|
103
129
|
if (sectionExists) {
|
|
104
130
|
return def.id;
|
|
105
131
|
}
|
|
@@ -111,12 +137,12 @@ function resolveSectionId(input, sections) {
|
|
|
111
137
|
* If sectionOrder is provided, only include sections in that order
|
|
112
138
|
* If not provided, use default order for CV or include all sections for rirekisho
|
|
113
139
|
*/
|
|
114
|
-
function filterAndOrderSections(sections, format,
|
|
140
|
+
function filterAndOrderSections(sections, format, logger, sectionOrder) {
|
|
115
141
|
// Get all section IDs from input
|
|
116
|
-
const allSectionIds = sections.map(s => s.id);
|
|
142
|
+
const allSectionIds = sections.map((s) => s.id);
|
|
117
143
|
// Determine which sections are valid for this format
|
|
118
|
-
const validSectionIds = allSectionIds.filter(id => isSectionValidForFormat(id, format));
|
|
119
|
-
const invalidSectionIds = allSectionIds.filter(id => !isSectionValidForFormat(id, format));
|
|
144
|
+
const validSectionIds = allSectionIds.filter((id) => isSectionValidForFormat(id, format));
|
|
145
|
+
const invalidSectionIds = allSectionIds.filter((id) => !isSectionValidForFormat(id, format));
|
|
120
146
|
let includedSectionIds;
|
|
121
147
|
let skippedSectionIds;
|
|
122
148
|
if (format === 'cv') {
|
|
@@ -125,13 +151,15 @@ function filterAndOrderSections(sections, format, sectionOrder, logger) {
|
|
|
125
151
|
const resolvedOrder = [];
|
|
126
152
|
for (const input of sectionOrder) {
|
|
127
153
|
const resolvedId = resolveSectionId(input, sections);
|
|
128
|
-
if (resolvedId &&
|
|
154
|
+
if (resolvedId &&
|
|
155
|
+
validSectionIds.includes(resolvedId) &&
|
|
156
|
+
!resolvedOrder.includes(resolvedId)) {
|
|
129
157
|
resolvedOrder.push(resolvedId);
|
|
130
158
|
}
|
|
131
159
|
}
|
|
132
160
|
// Use custom order - only include sections that are in sectionOrder AND valid for format
|
|
133
161
|
includedSectionIds = resolvedOrder;
|
|
134
|
-
skippedSectionIds = validSectionIds.filter(id => !resolvedOrder.includes(id));
|
|
162
|
+
skippedSectionIds = validSectionIds.filter((id) => !resolvedOrder.includes(id));
|
|
135
163
|
}
|
|
136
164
|
else {
|
|
137
165
|
// Use default order for CV
|
|
@@ -166,7 +194,7 @@ function filterAndOrderSections(sections, format, sectionOrder, logger) {
|
|
|
166
194
|
logger.info({ sections: invalidSectionIds }, `Sections skipped (not valid for ${format} format)`);
|
|
167
195
|
}
|
|
168
196
|
// Build ordered section list
|
|
169
|
-
const sectionMap = new Map(sections.map(s => [s.id, s]));
|
|
197
|
+
const sectionMap = new Map(sections.map((s) => [s.id, s]));
|
|
170
198
|
const orderedSections = [];
|
|
171
199
|
for (const id of includedSectionIds) {
|
|
172
200
|
const section = sectionMap.get(id);
|
|
@@ -178,20 +206,24 @@ function filterAndOrderSections(sections, format, sectionOrder, logger) {
|
|
|
178
206
|
}
|
|
179
207
|
/**
|
|
180
208
|
* Generate HTML for CV format
|
|
209
|
+
* Note: chronologicalOrder is not yet implemented for CV format.
|
|
210
|
+
* CV format currently uses the order as defined in the markdown file.
|
|
181
211
|
*/
|
|
182
|
-
function
|
|
212
|
+
function generateHtml(cv, paperSize, sectionOrder, logger, customStylesheet) {
|
|
183
213
|
const language = detectLanguage(cv);
|
|
184
|
-
// TODO: Add chronological order support for CV format
|
|
185
214
|
// Filter and order sections if logger is provided
|
|
186
215
|
let sections = cv.sections;
|
|
187
216
|
if (logger) {
|
|
188
|
-
sections = filterAndOrderSections(cv.sections, 'cv',
|
|
217
|
+
sections = filterAndOrderSections(cv.sections, 'cv', logger, sectionOrder);
|
|
189
218
|
}
|
|
190
219
|
const filteredCv = { ...cv, sections };
|
|
220
|
+
const options = customStylesheet
|
|
221
|
+
? { paperSize, customStylesheet }
|
|
222
|
+
: { paperSize };
|
|
191
223
|
if (language === 'ja') {
|
|
192
|
-
return
|
|
224
|
+
return generateJaHtml(filteredCv, options);
|
|
193
225
|
}
|
|
194
|
-
return
|
|
226
|
+
return generateEnHtml(filteredCv, options);
|
|
195
227
|
}
|
|
196
228
|
/**
|
|
197
229
|
* Generate PDF from HTML
|
|
@@ -208,15 +240,7 @@ async function generatePDF(html, paperSize, isRirekisho) {
|
|
|
208
240
|
let pdfOptions;
|
|
209
241
|
if (isRirekisho) {
|
|
210
242
|
// Rirekisho uses landscape orientation with the specified paper size
|
|
211
|
-
|
|
212
|
-
const rirekishoSizes = {
|
|
213
|
-
a3: { width: 420, height: 297 },
|
|
214
|
-
a4: { width: 297, height: 210 },
|
|
215
|
-
b4: { width: 364, height: 257 },
|
|
216
|
-
b5: { width: 257, height: 182 },
|
|
217
|
-
letter: { width: 279.4, height: 215.9 },
|
|
218
|
-
};
|
|
219
|
-
const rirekishoSize = rirekishoSizes[paperSize];
|
|
243
|
+
const rirekishoSize = PAGE_SIZES_LANDSCAPE[paperSize];
|
|
220
244
|
await page.setViewport({
|
|
221
245
|
width: Math.round(rirekishoSize.width * 3.78),
|
|
222
246
|
height: Math.round(rirekishoSize.height * 3.78),
|
|
@@ -274,7 +298,7 @@ export async function generateOutput(cv, config, logger) {
|
|
|
274
298
|
let html;
|
|
275
299
|
if (format === 'rirekisho') {
|
|
276
300
|
// Log sections for rirekisho
|
|
277
|
-
const sections = filterAndOrderSections(cv.sections, 'rirekisho',
|
|
301
|
+
const sections = filterAndOrderSections(cv.sections, 'rirekisho', logger);
|
|
278
302
|
const filteredCv = { ...cv, sections };
|
|
279
303
|
// Read photo file if provided (only for rirekisho)
|
|
280
304
|
let photoDataUri;
|
|
@@ -286,12 +310,12 @@ export async function generateOutput(cv, config, logger) {
|
|
|
286
310
|
paperSize: config.paperSize,
|
|
287
311
|
chronologicalOrder,
|
|
288
312
|
hideMotivation: config.hideMotivation,
|
|
289
|
-
photoDataUri,
|
|
290
|
-
customStylesheet,
|
|
313
|
+
...(photoDataUri !== undefined && { photoDataUri }),
|
|
314
|
+
...(customStylesheet !== undefined && { customStylesheet }),
|
|
291
315
|
});
|
|
292
316
|
}
|
|
293
317
|
else {
|
|
294
|
-
html =
|
|
318
|
+
html = generateHtml(cv, config.paperSize, config.sectionOrder, logger, customStylesheet);
|
|
295
319
|
}
|
|
296
320
|
const baseName = path.basename(config.output);
|
|
297
321
|
const suffix = format === 'rirekisho' ? '_rirekisho' : '_cv';
|