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
|
@@ -56,10 +56,10 @@ body {
|
|
|
56
56
|
font-family: var(--rirekisho-font-family);
|
|
57
57
|
font-size: var(--rirekisho-font-size-base);
|
|
58
58
|
color: var(--rirekisho-color-text);
|
|
59
|
-
background:
|
|
59
|
+
background: transparent;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/* Layout */
|
|
62
|
+
/* Layout - landscape orientation */
|
|
63
63
|
.spread {
|
|
64
64
|
width: ${mm(paper.width)};
|
|
65
65
|
height: ${mm(paper.height)};
|
|
@@ -68,6 +68,7 @@ body {
|
|
|
68
68
|
padding: ${mm(margin)} ${mm(margin)} ${mm(marginBottom)} ${mm(margin)};
|
|
69
69
|
overflow: hidden;
|
|
70
70
|
background: var(--rirekisho-color-background);
|
|
71
|
+
box-shadow: 0 2mm 12mm rgba(0, 0, 0, 0.5);
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
.spread-content {
|
|
@@ -352,26 +353,20 @@ td, th {
|
|
|
352
353
|
.spread {
|
|
353
354
|
page-break-after: always;
|
|
354
355
|
page-break-before: avoid;
|
|
356
|
+
box-shadow: none;
|
|
355
357
|
}
|
|
356
358
|
}
|
|
357
359
|
|
|
358
360
|
@media screen {
|
|
359
361
|
html {
|
|
360
|
-
height: 100%;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
body {
|
|
364
362
|
background: #888;
|
|
365
|
-
min-height: 100%;
|
|
366
|
-
display: flex;
|
|
367
|
-
align-items: center;
|
|
368
|
-
justify-content: center;
|
|
369
|
-
padding: 20mm;
|
|
370
363
|
}
|
|
371
364
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
365
|
+
body {
|
|
366
|
+
background: transparent;
|
|
367
|
+
display: inline-block;
|
|
368
|
+
margin: 0;
|
|
369
|
+
padding: 0;
|
|
375
370
|
}
|
|
376
371
|
}
|
|
377
372
|
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../src/generator/rirekisho/styles.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,SAAS,EAAE,CAAC,KAAa;IACvB,OAAO,GAAG,KAAK,IAAI,CAAC;AACtB,CAAC;AAED,SAAS,EAAE,CAAC,KAAa;IACvB,OAAO,GAAG,KAAK,IAAI,CAAC;AACtB,CAAC;AAED,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAAwB;IAClD,MAAM,EACJ,KAAK,EACL,KAAK,EACL,MAAM,EACN,YAAY,EACZ,SAAS,EACT,SAAS,EACT,UAAU,EACV,YAAY,GACb,GAAG,MAAM,CAAC;IAEX,yCAAyC;IACzC,MAAM,aAAa,GAAG,UAAU,GAAG,YAAY,CAAC;IAEhD,OAAO;;;;gCAIuB,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;iCACb,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;gCACf,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;mCACX,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;kCACf,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;iCACf,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;8BAChB,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;+BACZ,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;;;;;;;;;UASlC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;WAqBlC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC;YACd,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;;;aAGf,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../src/generator/rirekisho/styles.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,SAAS,EAAE,CAAC,KAAa;IACvB,OAAO,GAAG,KAAK,IAAI,CAAC;AACtB,CAAC;AAED,SAAS,EAAE,CAAC,KAAa;IACvB,OAAO,GAAG,KAAK,IAAI,CAAC;AACtB,CAAC;AAED,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAAwB;IAClD,MAAM,EACJ,KAAK,EACL,KAAK,EACL,MAAM,EACN,YAAY,EACZ,SAAS,EACT,SAAS,EACT,UAAU,EACV,YAAY,GACb,GAAG,MAAM,CAAC;IAEX,yCAAyC;IACzC,MAAM,aAAa,GAAG,UAAU,GAAG,YAAY,CAAC;IAEhD,OAAO;;;;gCAIuB,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;iCACb,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;gCACf,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;mCACX,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;kCACf,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;iCACf,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;8BAChB,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;+BACZ,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;;;;;;;;;UASlC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;WAqBlC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC;YACd,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;;;aAGf,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;;;;;;;;;YAS3D,EAAE,CAAC,aAAa,CAAC;;;;YAIjB,EAAE,CAAC,YAAY,CAAC;;;;;;;;WAQjB,EAAE,CAAC,SAAS,CAAC;YACZ,EAAE,CAAC,aAAa,CAAC;;;;;;;kBAOX,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC;;;;iBAIlB,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;oBAuBd,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA4DpB,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;;;;aAI9B,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;;;;gBAIV,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAkD3B,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC;;;;WAI1B,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC;;;;;;;;gBAQtB,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;;;;WAIlB,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;;;;;;;;;;;;aAYZ,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;;;;;WAKhC,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;YACb,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;;;;;;;;;iBAST,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;aAsBjB,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;;;;;;;aAOb,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA6Bb,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC;cACd,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;;kBAEZ,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BjC,CAAC;AACF,CAAC"}
|
|
@@ -12,9 +12,9 @@ export interface RirekishoOptions {
|
|
|
12
12
|
readonly chronologicalOrder?: ChronologicalOrder;
|
|
13
13
|
readonly hideMotivation?: boolean;
|
|
14
14
|
/** Base64 encoded photo data URI (e.g., "data:image/png;base64,...") */
|
|
15
|
-
readonly photoDataUri?: string
|
|
15
|
+
readonly photoDataUri?: string;
|
|
16
16
|
/** Custom CSS stylesheet content to append after default styles */
|
|
17
|
-
readonly customStylesheet?: string
|
|
17
|
+
readonly customStylesheet?: string;
|
|
18
18
|
}
|
|
19
19
|
/** Input data for the Rirekisho generator */
|
|
20
20
|
export interface RirekishoInput {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/generator/rirekisho/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAG7D,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAMvD,uCAAuC;AACvC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/generator/rirekisho/types.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
* md2cv - CV/Resume Generator
|
|
3
3
|
* Transforms Markdown CVs into PDF and HTML
|
|
4
4
|
*/
|
|
5
|
-
export { createCLIProgram, main } from './cli/index.js';
|
|
5
|
+
export { createCLIProgram, main, runInit } from './cli/index.js';
|
|
6
6
|
export * from './generator/index.js';
|
|
7
7
|
export * from './parser/index.js';
|
|
8
|
+
export * from './parser/lsp.js';
|
|
9
|
+
export * from './template/index.js';
|
|
8
10
|
export * from './types/index.js';
|
|
9
11
|
export * from './validator/index.js';
|
|
10
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACjE,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
* md2cv - CV/Resume Generator
|
|
3
3
|
* Transforms Markdown CVs into PDF and HTML
|
|
4
4
|
*/
|
|
5
|
-
export { createCLIProgram, main } from './cli/index.js';
|
|
5
|
+
export { createCLIProgram, main, runInit } from './cli/index.js';
|
|
6
6
|
export * from './generator/index.js';
|
|
7
7
|
export * from './parser/index.js';
|
|
8
|
+
export * from './parser/lsp.js';
|
|
9
|
+
export * from './template/index.js';
|
|
8
10
|
export * from './types/index.js';
|
|
9
11
|
export * from './validator/index.js';
|
|
10
12
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACjE,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,MAAM,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAOL,KAAK,aAAa,EAMnB,MAAM,sBAAsB,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AA4zBD;;GAEG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,CAqChC;AAED,eAAe,aAAa,CAAC"}
|
package/dist/parser/index.js
CHANGED
|
@@ -34,11 +34,43 @@ function extractText(node) {
|
|
|
34
34
|
}
|
|
35
35
|
return '';
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Remove HTML comments from the beginning of content
|
|
39
|
+
* This allows templates to have comments before frontmatter
|
|
40
|
+
* Note: This handles nested comment markers within comments
|
|
41
|
+
*/
|
|
42
|
+
function stripLeadingHtmlComments(content) {
|
|
43
|
+
let result = content.trimStart();
|
|
44
|
+
// Keep removing HTML comments from the beginning
|
|
45
|
+
while (result.startsWith('<!--')) {
|
|
46
|
+
// Find the matching closing --> by counting nesting
|
|
47
|
+
let depth = 0;
|
|
48
|
+
let endIndex = -1;
|
|
49
|
+
for (let i = 0; i < result.length - 2; i++) {
|
|
50
|
+
if (result.substring(i, i + 4) === '<!--') {
|
|
51
|
+
depth++;
|
|
52
|
+
i += 3; // Skip past <!--
|
|
53
|
+
}
|
|
54
|
+
else if (result.substring(i, i + 3) === '-->') {
|
|
55
|
+
depth--;
|
|
56
|
+
if (depth === 0) {
|
|
57
|
+
endIndex = i;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
i += 2; // Skip past -->
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (endIndex === -1)
|
|
64
|
+
break;
|
|
65
|
+
result = result.substring(endIndex + 3).trimStart();
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
37
69
|
/**
|
|
38
70
|
* Parse frontmatter delimiter type
|
|
39
71
|
*/
|
|
40
72
|
function parseFrontmatterDelimiter(content) {
|
|
41
|
-
const trimmed = content
|
|
73
|
+
const trimmed = stripLeadingHtmlComments(content);
|
|
42
74
|
if (trimmed.startsWith('---'))
|
|
43
75
|
return '---';
|
|
44
76
|
if (trimmed.startsWith('+++'))
|
|
@@ -55,7 +87,9 @@ function validateFrontmatterDelimiters(content, errors) {
|
|
|
55
87
|
if (!delimiter) {
|
|
56
88
|
return true;
|
|
57
89
|
}
|
|
58
|
-
|
|
90
|
+
// Strip leading HTML comments before checking delimiters
|
|
91
|
+
const strippedContent = stripLeadingHtmlComments(content);
|
|
92
|
+
const lines = strippedContent.split('\n');
|
|
59
93
|
let foundStart = false;
|
|
60
94
|
let foundEnd = false;
|
|
61
95
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -125,7 +159,9 @@ function parseListItems(listNode) {
|
|
|
125
159
|
const items = [];
|
|
126
160
|
for (const item of listNode.children) {
|
|
127
161
|
if (item.type === 'listItem' && item.children) {
|
|
128
|
-
const text = item.children
|
|
162
|
+
const text = item.children
|
|
163
|
+
.map((child) => extractText(child))
|
|
164
|
+
.join('');
|
|
129
165
|
items.push(text.trim());
|
|
130
166
|
}
|
|
131
167
|
}
|
|
@@ -273,22 +309,107 @@ function parseEducationBlock(code) {
|
|
|
273
309
|
const parsed = parseYaml(code);
|
|
274
310
|
// Handle both single object and array
|
|
275
311
|
const items = Array.isArray(parsed) ? parsed : [parsed];
|
|
276
|
-
return items
|
|
312
|
+
return items
|
|
313
|
+
.map((item) => {
|
|
277
314
|
const obj = item;
|
|
315
|
+
const school = safeString(obj.school);
|
|
316
|
+
const degree = safeOptionalString(obj.degree);
|
|
317
|
+
const start = parseYearMonth(safeOptionalString(obj.start));
|
|
318
|
+
const end = parseYearMonth(safeOptionalString(obj.end));
|
|
319
|
+
// Skip entries missing required fields (degree is optional for rirekisho format)
|
|
320
|
+
if (!school || !start || !end) {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
const location = safeOptionalString(obj.location);
|
|
324
|
+
const details = Array.isArray(obj.details)
|
|
325
|
+
? obj.details.map((d) => {
|
|
326
|
+
// Handle YAML parsing objects like { "GPA": "3.8/4.0" } as "GPA: 3.8/4.0"
|
|
327
|
+
if (typeof d === 'object' && d !== null) {
|
|
328
|
+
const entries = Object.entries(d);
|
|
329
|
+
if (entries.length > 0) {
|
|
330
|
+
return entries
|
|
331
|
+
.map(([k, v]) => `${k}: ${safeString(v)}`)
|
|
332
|
+
.join(', ');
|
|
333
|
+
}
|
|
334
|
+
return '';
|
|
335
|
+
}
|
|
336
|
+
return safeString(d);
|
|
337
|
+
})
|
|
338
|
+
: undefined;
|
|
278
339
|
return {
|
|
279
|
-
school
|
|
280
|
-
degree
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
340
|
+
school,
|
|
341
|
+
degree,
|
|
342
|
+
start,
|
|
343
|
+
end,
|
|
344
|
+
...(location !== undefined && { location }),
|
|
345
|
+
...(details !== undefined && {
|
|
346
|
+
details: details,
|
|
347
|
+
}),
|
|
285
348
|
};
|
|
286
|
-
})
|
|
349
|
+
})
|
|
350
|
+
.filter((entry) => entry !== null);
|
|
287
351
|
}
|
|
288
352
|
catch {
|
|
289
353
|
return [];
|
|
290
354
|
}
|
|
291
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* Parse a project entry from YAML
|
|
358
|
+
*/
|
|
359
|
+
function parseProjectEntry(proj) {
|
|
360
|
+
const name = safeString(proj.name);
|
|
361
|
+
const start = parseYearMonth(safeOptionalString(proj.start));
|
|
362
|
+
const end = parseYearMonth(safeOptionalString(proj.end));
|
|
363
|
+
// Skip entries missing required fields
|
|
364
|
+
if (!name || !start || !end) {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
const bullets = Array.isArray(proj.bullets)
|
|
368
|
+
? proj.bullets.map((b) => safeString(b))
|
|
369
|
+
: undefined;
|
|
370
|
+
return {
|
|
371
|
+
name,
|
|
372
|
+
start,
|
|
373
|
+
end,
|
|
374
|
+
...(bullets !== undefined && { bullets }),
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Parse a role entry from YAML
|
|
379
|
+
*/
|
|
380
|
+
function parseRoleEntry(role) {
|
|
381
|
+
const title = safeString(role.title || role.role);
|
|
382
|
+
const start = parseYearMonth(safeOptionalString(role.start));
|
|
383
|
+
const end = parseEndDate(safeOptionalString(role.end));
|
|
384
|
+
// Skip entries missing required fields
|
|
385
|
+
if (!title || !start || !end) {
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
const team = safeOptionalString(role.team);
|
|
389
|
+
const summary = parseSummary(role.summary);
|
|
390
|
+
const highlights = Array.isArray(role.highlights)
|
|
391
|
+
? role.highlights.map((h) => safeString(h))
|
|
392
|
+
: undefined;
|
|
393
|
+
const projects = [];
|
|
394
|
+
if (Array.isArray(role.projects)) {
|
|
395
|
+
for (const projItem of role.projects) {
|
|
396
|
+
const proj = projItem;
|
|
397
|
+
const projectEntry = parseProjectEntry(proj);
|
|
398
|
+
if (projectEntry) {
|
|
399
|
+
projects.push(projectEntry);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
title,
|
|
405
|
+
start,
|
|
406
|
+
end,
|
|
407
|
+
...(team !== undefined && { team }),
|
|
408
|
+
...(summary !== undefined && { summary }),
|
|
409
|
+
...(highlights !== undefined && { highlights }),
|
|
410
|
+
...(projects.length > 0 && { projects }),
|
|
411
|
+
};
|
|
412
|
+
}
|
|
292
413
|
/**
|
|
293
414
|
* Parse resume:experience code block
|
|
294
415
|
*/
|
|
@@ -297,74 +418,40 @@ function parseExperienceBlock(code) {
|
|
|
297
418
|
const parsed = parseYaml(code);
|
|
298
419
|
// Handle both single object and array
|
|
299
420
|
const items = Array.isArray(parsed) ? parsed : [parsed];
|
|
300
|
-
|
|
421
|
+
const entries = [];
|
|
422
|
+
for (const item of items) {
|
|
301
423
|
const obj = item;
|
|
424
|
+
const company = safeString(obj.company);
|
|
302
425
|
const roles = [];
|
|
303
426
|
// Support both nested roles array and flat role definition
|
|
304
427
|
if (Array.isArray(obj.roles)) {
|
|
305
428
|
for (const roleItem of obj.roles) {
|
|
306
429
|
const role = roleItem;
|
|
307
|
-
const
|
|
308
|
-
if (
|
|
309
|
-
|
|
310
|
-
const proj = projItem;
|
|
311
|
-
projects.push({
|
|
312
|
-
name: safeString(proj.name),
|
|
313
|
-
start: parseYearMonth(safeOptionalString(proj.start)),
|
|
314
|
-
end: parseYearMonth(safeOptionalString(proj.end)),
|
|
315
|
-
bullets: Array.isArray(proj.bullets)
|
|
316
|
-
? proj.bullets.map((b) => safeString(b))
|
|
317
|
-
: undefined,
|
|
318
|
-
});
|
|
319
|
-
}
|
|
430
|
+
const roleEntry = parseRoleEntry(role);
|
|
431
|
+
if (roleEntry) {
|
|
432
|
+
roles.push(roleEntry);
|
|
320
433
|
}
|
|
321
|
-
roles.push({
|
|
322
|
-
title: safeString(role.title),
|
|
323
|
-
team: safeOptionalString(role.team),
|
|
324
|
-
start: parseYearMonth(safeOptionalString(role.start)),
|
|
325
|
-
end: parseEndDate(safeOptionalString(role.end)),
|
|
326
|
-
summary: parseSummary(role.summary),
|
|
327
|
-
highlights: Array.isArray(role.highlights)
|
|
328
|
-
? role.highlights.map((h) => safeString(h))
|
|
329
|
-
: undefined,
|
|
330
|
-
projects: projects.length > 0 ? projects : undefined,
|
|
331
|
-
});
|
|
332
434
|
}
|
|
333
435
|
}
|
|
334
|
-
else if (obj.role) {
|
|
335
|
-
// Flat role definition (role, team, start, end at top level)
|
|
336
|
-
const
|
|
337
|
-
if (
|
|
338
|
-
|
|
339
|
-
const proj = projItem;
|
|
340
|
-
projects.push({
|
|
341
|
-
name: safeString(proj.name),
|
|
342
|
-
start: parseYearMonth(safeOptionalString(proj.start)),
|
|
343
|
-
end: parseYearMonth(safeOptionalString(proj.end)),
|
|
344
|
-
bullets: Array.isArray(proj.bullets)
|
|
345
|
-
? proj.bullets.map((b) => safeString(b))
|
|
346
|
-
: undefined,
|
|
347
|
-
});
|
|
348
|
-
}
|
|
436
|
+
else if (obj.role || obj.title) {
|
|
437
|
+
// Flat role definition (role/title, team, start, end at top level)
|
|
438
|
+
const roleEntry = parseRoleEntry(obj);
|
|
439
|
+
if (roleEntry) {
|
|
440
|
+
roles.push(roleEntry);
|
|
349
441
|
}
|
|
350
|
-
roles.push({
|
|
351
|
-
title: safeString(obj.role),
|
|
352
|
-
team: safeOptionalString(obj.team),
|
|
353
|
-
start: parseYearMonth(safeOptionalString(obj.start)),
|
|
354
|
-
end: parseEndDate(safeOptionalString(obj.end)),
|
|
355
|
-
summary: parseSummary(obj.summary),
|
|
356
|
-
highlights: Array.isArray(obj.highlights)
|
|
357
|
-
? obj.highlights.map((h) => safeString(h))
|
|
358
|
-
: undefined,
|
|
359
|
-
projects: projects.length > 0 ? projects : undefined,
|
|
360
|
-
});
|
|
361
442
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
443
|
+
// Skip entries missing required fields
|
|
444
|
+
if (!company || roles.length === 0) {
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
const location = safeOptionalString(obj.location);
|
|
448
|
+
entries.push({
|
|
449
|
+
company,
|
|
450
|
+
roles: roles,
|
|
451
|
+
...(location !== undefined && { location }),
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
return entries;
|
|
368
455
|
}
|
|
369
456
|
catch {
|
|
370
457
|
return [];
|
|
@@ -378,67 +465,80 @@ function parseCertificationsBlock(code) {
|
|
|
378
465
|
const parsed = parseYaml(code);
|
|
379
466
|
// Handle both single object and array
|
|
380
467
|
const items = Array.isArray(parsed) ? parsed : [parsed];
|
|
381
|
-
return items
|
|
468
|
+
return items
|
|
469
|
+
.map((item) => {
|
|
382
470
|
const obj = item;
|
|
471
|
+
const name = safeString(obj.name);
|
|
472
|
+
const date = parseYearMonth(safeOptionalString(obj.date));
|
|
473
|
+
// Skip entries missing required fields
|
|
474
|
+
if (!name || !date) {
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
const issuer = safeOptionalString(obj.issuer);
|
|
478
|
+
const url = safeOptionalString(obj.url);
|
|
383
479
|
return {
|
|
384
|
-
name
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
url
|
|
480
|
+
name,
|
|
481
|
+
date,
|
|
482
|
+
...(issuer !== undefined && { issuer }),
|
|
483
|
+
...(url !== undefined && { url }),
|
|
388
484
|
};
|
|
389
|
-
})
|
|
485
|
+
})
|
|
486
|
+
.filter((entry) => entry !== null);
|
|
390
487
|
}
|
|
391
488
|
catch {
|
|
392
489
|
return [];
|
|
393
490
|
}
|
|
394
491
|
}
|
|
492
|
+
function parseSkillEntry(catObj) {
|
|
493
|
+
const category = safeString(catObj.category);
|
|
494
|
+
const items = Array.isArray(catObj.items)
|
|
495
|
+
? catObj.items.map((i) => safeString(i))
|
|
496
|
+
: undefined;
|
|
497
|
+
const description = safeOptionalString(catObj.description);
|
|
498
|
+
const level = safeOptionalString(catObj.level);
|
|
499
|
+
return {
|
|
500
|
+
category,
|
|
501
|
+
...(items !== undefined && { items }),
|
|
502
|
+
...(description !== undefined && { description }),
|
|
503
|
+
...(level !== undefined && { level }),
|
|
504
|
+
};
|
|
505
|
+
}
|
|
395
506
|
function parseSkillsBlock(code) {
|
|
507
|
+
const defaultResult = {
|
|
508
|
+
entries: [],
|
|
509
|
+
columns: 3,
|
|
510
|
+
format: 'grid',
|
|
511
|
+
};
|
|
396
512
|
try {
|
|
397
513
|
const parsed = parseYaml(code);
|
|
398
514
|
// Check if it's the new format with columns and items at top level
|
|
399
515
|
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
400
516
|
const obj = parsed;
|
|
517
|
+
const columns = typeof obj.columns === 'number' ? obj.columns : 3;
|
|
401
518
|
// Format 1: Simple items list (grid format)
|
|
402
|
-
if (Array.isArray(obj.items) &&
|
|
403
|
-
|
|
519
|
+
if (Array.isArray(obj.items) &&
|
|
520
|
+
obj.items.every((i) => typeof i === 'string')) {
|
|
404
521
|
const items = obj.items.map((i) => safeString(i));
|
|
405
522
|
// Convert to single SkillEntry with empty category
|
|
406
523
|
return {
|
|
407
|
-
entries: [{ category: '', items
|
|
524
|
+
entries: [{ category: '', items }],
|
|
408
525
|
columns,
|
|
409
526
|
format: 'grid',
|
|
410
527
|
};
|
|
411
528
|
}
|
|
412
529
|
// Format 2 & 3: Categorized skills
|
|
413
530
|
if (Array.isArray(obj.categories)) {
|
|
414
|
-
const
|
|
415
|
-
const entries = obj.categories.map((cat) => {
|
|
416
|
-
const catObj = cat;
|
|
417
|
-
return {
|
|
418
|
-
category: safeString(catObj.category),
|
|
419
|
-
items: Array.isArray(catObj.items) ? catObj.items.map((i) => safeString(i)) : [],
|
|
420
|
-
description: safeOptionalString(catObj.description),
|
|
421
|
-
level: safeOptionalString(catObj.level),
|
|
422
|
-
};
|
|
423
|
-
});
|
|
531
|
+
const entries = obj.categories.map((cat) => parseSkillEntry(cat));
|
|
424
532
|
return { entries, columns, format: 'categorized' };
|
|
425
533
|
}
|
|
426
534
|
}
|
|
427
535
|
// Legacy format: array of { category, items, level }
|
|
428
536
|
const items = Array.isArray(parsed) ? parsed : [parsed];
|
|
429
|
-
const entries = items.map((item) =>
|
|
430
|
-
|
|
431
|
-
return {
|
|
432
|
-
category: safeString(obj.category),
|
|
433
|
-
items: Array.isArray(obj.items) ? obj.items.map((i) => safeString(i)) : [],
|
|
434
|
-
description: safeOptionalString(obj.description),
|
|
435
|
-
level: safeOptionalString(obj.level),
|
|
436
|
-
};
|
|
437
|
-
});
|
|
438
|
-
return { entries, columns: undefined, format: undefined };
|
|
537
|
+
const entries = items.map((item) => parseSkillEntry(item));
|
|
538
|
+
return { entries, columns: 3, format: 'categorized' };
|
|
439
539
|
}
|
|
440
540
|
catch {
|
|
441
|
-
return
|
|
541
|
+
return defaultResult;
|
|
442
542
|
}
|
|
443
543
|
}
|
|
444
544
|
/**
|
|
@@ -469,13 +569,18 @@ function parseLanguagesBlock(code) {
|
|
|
469
569
|
const parsed = parseYaml(code);
|
|
470
570
|
// Handle both single object and array
|
|
471
571
|
const items = Array.isArray(parsed) ? parsed : [parsed];
|
|
472
|
-
return items
|
|
572
|
+
return items
|
|
573
|
+
.map((item) => {
|
|
473
574
|
const obj = item;
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
575
|
+
const language = safeString(obj.language);
|
|
576
|
+
const level = safeOptionalString(obj.level);
|
|
577
|
+
// Skip entries missing required fields
|
|
578
|
+
if (!language || !level) {
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
return { language, level };
|
|
582
|
+
})
|
|
583
|
+
.filter((entry) => entry !== null);
|
|
479
584
|
}
|
|
480
585
|
catch {
|
|
481
586
|
return [];
|
|
@@ -535,7 +640,14 @@ function parseSectionContent(nodes) {
|
|
|
535
640
|
return { type: 'certifications', entries: certificationEntries };
|
|
536
641
|
}
|
|
537
642
|
if (skillEntries.length > 0) {
|
|
538
|
-
return {
|
|
643
|
+
return {
|
|
644
|
+
type: 'skills',
|
|
645
|
+
entries: skillEntries,
|
|
646
|
+
options: {
|
|
647
|
+
columns: skillsColumns ?? 3,
|
|
648
|
+
format: skillsFormat ?? 'grid',
|
|
649
|
+
},
|
|
650
|
+
};
|
|
539
651
|
}
|
|
540
652
|
if (competencyEntries.length > 0) {
|
|
541
653
|
return { type: 'competencies', entries: competencyEntries };
|
|
@@ -586,7 +698,9 @@ function parseSections(tree) {
|
|
|
586
698
|
}
|
|
587
699
|
}
|
|
588
700
|
// Start new section
|
|
589
|
-
currentTitle = node.children
|
|
701
|
+
currentTitle = node.children
|
|
702
|
+
.map((c) => extractText(c))
|
|
703
|
+
.join('');
|
|
590
704
|
currentNodes = [];
|
|
591
705
|
}
|
|
592
706
|
else if (currentTitle !== null) {
|
|
@@ -615,9 +729,12 @@ export function parseMarkdown(markdown) {
|
|
|
615
729
|
if (!validateFrontmatterDelimiters(markdown, errors)) {
|
|
616
730
|
return failure(errors);
|
|
617
731
|
}
|
|
732
|
+
// Strip leading HTML comments before parsing
|
|
733
|
+
// This allows templates to have comments before frontmatter
|
|
734
|
+
const processedMarkdown = stripLeadingHtmlComments(markdown);
|
|
618
735
|
try {
|
|
619
736
|
const processor = createProcessor();
|
|
620
|
-
const tree = processor.parse(
|
|
737
|
+
const tree = processor.parse(processedMarkdown);
|
|
621
738
|
// Extract metadata
|
|
622
739
|
const metadata = extractMetadata(tree, errors);
|
|
623
740
|
if (!metadata) {
|