md2pdf2 0.2.0 → 0.2.2

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/README.md CHANGED
@@ -29,6 +29,16 @@ md2pdf2 convert input.md --template my-template.hbs -o output.pdf
29
29
  md2pdf2 dev input.md
30
30
  ```
31
31
 
32
+ ## Agent Skill
33
+
34
+ Install the md2pdf2 skill for Claude Code, Amp, OpenCode etc:
35
+
36
+ ```bash
37
+ npx skills add areai51/md2pdf2
38
+ ```
39
+
40
+ This adds the skill to your Claude Code environment, enabling intelligent PDF generation with automatic template selection and markdown formatting.
41
+
32
42
  ## Dev Mode
33
43
 
34
44
  Start a live preview server to see your markdown rendered in different templates:
@@ -292,7 +292,7 @@ function getDevHTML(port) {
292
292
  <div class="toast" id="toast"><span class="toast-dot"></span><span id="toastMsg">Reloading...</span></div>
293
293
  <div class="sidebar">
294
294
  <div class="sidebar-header">
295
- <h1>Templates</h1>
295
+ <h1>md2pdf2</h1>
296
296
  <p id="currentTemplate"><span style="color: #22c55e;">●</span> Watching for changes</p>
297
297
  </div>
298
298
  <div class="template-list" id="templateList"></div>
@@ -1 +1 @@
1
- {"version":3,"file":"template-engine.d.ts","sourceRoot":"","sources":["../src/template-engine.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,QAAQ,CAAkD;gBAEtD,MAAM,EAAE,YAAY;IAUhC,OAAO,CAAC,eAAe;YAST,sBAAsB;IAW9B,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvD,mBAAmB,IAAI,IAAI;IAiD3B,OAAO,CAAC,eAAe;IAIvB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAIpD,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;CAQlF"}
1
+ {"version":3,"file":"template-engine.d.ts","sourceRoot":"","sources":["../src/template-engine.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,QAAQ,CAAkD;gBAEtD,MAAM,EAAE,YAAY;IAUhC,OAAO,CAAC,eAAe;YAaT,sBAAsB;IAW9B,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvD,mBAAmB,IAAI,IAAI;IAiD3B,OAAO,CAAC,eAAe;IAIvB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAIpD,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;CASlF"}
@@ -18,6 +18,11 @@ export class TemplateEngine {
18
18
  Handlebars.registerHelper('currentDate', () => {
19
19
  return new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
20
20
  });
21
+ Handlebars.registerHelper('slice', (str, start, end) => {
22
+ if (typeof str !== 'string')
23
+ return '';
24
+ return str.slice(start, end);
25
+ });
21
26
  }
22
27
  async loadPartialsFromConfig(partialsConfig) {
23
28
  for (const [name, path] of Object.entries(partialsConfig)) {
@@ -93,7 +98,8 @@ export class TemplateEngine {
93
98
  content,
94
99
  frontMatter,
95
100
  styles,
96
- partials: this.partials
101
+ partials: this.partials,
102
+ ...frontMatter
97
103
  });
98
104
  }
99
105
  }
@@ -1 +1 @@
1
- {"version":3,"file":"template-engine.js","sourceRoot":"","sources":["../src/template-engine.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3C,MAAM,OAAO,cAAc;IACjB,QAAQ,CAA8B;IACtC,QAAQ,GAA+C,EAAE,CAAC;IAElE,YAAY,MAAoB;QAC9B,4BAA4B;QAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,wCAAwC;QACxC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAEO,eAAe;QACrB,UAAU,CAAC,cAAc,CAAC,YAAY,EAAE,CAAC,IAAY,EAAE,EAAE;YACvD,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QACH,UAAU,CAAC,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE;YAC5C,OAAO,IAAI,IAAI,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QACpG,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAAC,cAAsC;QACzE,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;gBAC1C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACpD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,oCAAoC,IAAI,UAAU,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,YAAoB;QACrC,MAAM,eAAe,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;IACxD,CAAC;IAED,mBAAmB;QACjB,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4CpB,CAAC;QACL,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;IACxD,CAAC;IAEO,eAAe,CAAC,OAAe;QACrC,OAAO,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,eAAe,CAAC,IAAY,EAAE,OAAe;QAC3C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,CAAC,OAAe,EAAE,WAAgC,EAAE,MAAc;QACtE,OAAO,IAAI,CAAC,QAAQ,CAAC;YACnB,OAAO;YACP,WAAW;YACX,MAAM;YACN,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;IACL,CAAC;CACF"}
1
+ {"version":3,"file":"template-engine.js","sourceRoot":"","sources":["../src/template-engine.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3C,MAAM,OAAO,cAAc;IACjB,QAAQ,CAA8B;IACtC,QAAQ,GAA+C,EAAE,CAAC;IAElE,YAAY,MAAoB;QAC9B,4BAA4B;QAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,wCAAwC;QACxC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAEO,eAAe;QACrB,UAAU,CAAC,cAAc,CAAC,YAAY,EAAE,CAAC,IAAY,EAAE,EAAE;YACvD,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QACH,UAAU,CAAC,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE;YAC5C,OAAO,IAAI,IAAI,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QACpG,CAAC,CAAC,CAAC;QACH,UAAU,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,GAAW,EAAE,KAAa,EAAE,GAAY,EAAE,EAAE;YAC9E,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,OAAO,EAAE,CAAC;YACvC,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAAC,cAAsC;QACzE,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;gBAC1C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACpD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,oCAAoC,IAAI,UAAU,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,YAAoB;QACrC,MAAM,eAAe,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;IACxD,CAAC;IAED,mBAAmB;QACjB,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4CpB,CAAC;QACL,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;IACxD,CAAC;IAEO,eAAe,CAAC,OAAe;QACrC,OAAO,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,eAAe,CAAC,IAAY,EAAE,OAAe;QAC3C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,CAAC,OAAe,EAAE,WAAgC,EAAE,MAAc;QACtE,OAAO,IAAI,CAAC,QAAQ,CAAC;YACnB,OAAO;YACP,WAAW;YACX,MAAM;YACN,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,GAAG,WAAW;SACf,CAAC,CAAC;IACL,CAAC;CACF"}
package/package.json CHANGED
@@ -1,12 +1,20 @@
1
1
  {
2
2
  "name": "md2pdf2",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Convert Markdown to PDF using customizable templates",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",
7
7
  "bin": {
8
8
  "md2pdf2": "dist/cli.js"
9
9
  },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "start": "node dist/cli.js",
14
+ "test": "node dist/cli.js convert examples/demo.md -o demo.pdf",
15
+ "lint": "eslint src --ext .ts",
16
+ "prepublishOnly": "npm run build"
17
+ },
10
18
  "keywords": [
11
19
  "markdown",
12
20
  "pdf",
@@ -45,12 +53,5 @@
45
53
  "files": [
46
54
  "dist",
47
55
  "templates"
48
- ],
49
- "scripts": {
50
- "build": "tsc",
51
- "dev": "tsc --watch",
52
- "start": "node dist/cli.js",
53
- "test": "node dist/cli.js convert examples/demo.md -o demo.pdf",
54
- "lint": "eslint src --ext .ts"
55
- }
56
- }
56
+ ]
57
+ }
@@ -2,118 +2,215 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>{{#if frontMatter.title}}{{frontMatter.title}}{{else}}Newsletter{{/if}}</title>
5
+ <title>{{title}}</title>
7
6
  <style>
7
+ * { box-sizing: border-box; margin: 0; padding: 0; }
8
+
8
9
  body {
9
- font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
10
- line-height: 1.65;
11
- color: #1a1a1a;
12
- max-width: 600px;
13
- margin: 0 auto;
14
- padding: 0;
15
- background: #f9f9f9;
16
- }
17
- .container {
18
- background: #ffffff;
19
- padding: 40px 50px;
20
- margin: 20px 0;
21
- border-radius: 8px;
22
- }
23
- .header {
24
- text-align: center;
25
- padding-bottom: 30px;
26
- border-bottom: 1px solid #eee;
27
- margin-bottom: 30px;
28
- }
29
- .header h1 {
30
- font-size: 1.75rem;
31
- margin: 0 0 8px 0;
32
- color: #111;
33
- }
34
- .header .date {
35
- font-size: 0.85rem;
36
- color: #888;
37
- }
38
- .content h2 {
39
- font-size: 1.35rem;
40
- margin-top: 2rem;
41
- margin-bottom: 0.75rem;
42
- color: #111;
43
- }
44
- .content h3 {
45
- font-size: 1.1rem;
46
- margin-top: 1.5rem;
47
- margin-bottom: 0.5rem;
48
- }
49
- .content p {
50
- margin-bottom: 1rem;
10
+ font-family: Georgia, 'Times New Roman', serif;
11
+ font-size: 11pt;
12
+ line-height: 1.8;
51
13
  color: #333;
52
- }
53
- .content a {
54
- color: #0066cc;
55
- text-decoration: underline;
56
- }
57
- .content code {
58
- background: #f0f0f0;
59
- padding: 0.15em 0.4em;
60
- border-radius: 3px;
61
- font-size: 0.9em;
62
- font-family: 'SF Mono', Monaco, monospace;
63
- }
64
- .content pre {
65
- background: #f5f5f5;
66
- padding: 1rem;
67
- border-radius: 6px;
68
- overflow-x: auto;
69
- font-size: 0.85rem;
70
- line-height: 1.5;
71
- }
72
- .content pre code { background: none; padding: 0; }
73
- .content blockquote {
74
- border-left: 3px solid #0066cc;
75
- margin: 1.25rem 0;
76
- padding: 0.25rem 0 0.25rem 1rem;
77
- color: #555;
14
+ background: #f0ebe3;
15
+ }
16
+
17
+ /* ── WRAPPER ── */
18
+ .wrapper {
19
+ max-width: 680px;
20
+ margin: 32px auto;
21
+ background: #fff;
22
+ border: 1px solid #ddd;
23
+ box-shadow: 0 2px 20px rgba(0,0,0,0.08);
24
+ }
25
+
26
+ /* ── MASTHEAD ── */
27
+ .masthead {
28
+ background: #1a1a1a;
29
+ color: white;
30
+ padding: 48px 56px 36px;
31
+ text-align: center;
32
+ position: relative;
33
+ overflow: hidden;
34
+ }
35
+
36
+ .masthead::before {
37
+ content: '';
38
+ position: absolute;
39
+ top: 0; left: 0; right: 0;
40
+ height: 4px;
41
+ background: linear-gradient(90deg, #d4a437, #e8c46a, #d4a437);
42
+ }
43
+
44
+ .masthead-label {
45
+ font-family: -apple-system, 'Helvetica Neue', sans-serif;
46
+ font-size: 8pt;
47
+ letter-spacing: 4px;
48
+ text-transform: uppercase;
49
+ color: #d4a437;
50
+ margin-bottom: 14px;
51
+ }
52
+
53
+ .masthead h1 {
54
+ font-size: 30pt;
55
+ font-weight: 700;
56
+ letter-spacing: -0.5px;
57
+ line-height: 1.1;
58
+ margin-bottom: 10px;
59
+ color: white;
60
+ }
61
+
62
+ .masthead-meta {
63
+ font-family: -apple-system, 'Helvetica Neue', sans-serif;
64
+ font-size: 9pt;
65
+ color: rgba(255,255,255,0.5);
66
+ letter-spacing: 0.5px;
67
+ }
68
+
69
+ /* ── BODY ── */
70
+ .body {
71
+ padding: 48px 56px;
72
+ }
73
+
74
+ h1 { display: none; } /* Used in masthead */
75
+
76
+ h2 {
77
+ font-size: 17pt;
78
+ font-weight: 700;
79
+ color: #1a1a1a;
80
+ margin-top: 2em;
81
+ margin-bottom: 0.5em;
82
+ line-height: 1.2;
83
+ position: relative;
84
+ padding-bottom: 10px;
85
+ }
86
+ h2::after {
87
+ content: '';
88
+ position: absolute;
89
+ bottom: 0; left: 0;
90
+ width: 40px; height: 3px;
91
+ background: #d4a437;
92
+ }
93
+
94
+ h3 {
95
+ font-size: 13pt;
96
+ color: #222;
97
+ margin-top: 1.5em;
98
+ margin-bottom: 0.4em;
99
+ }
100
+
101
+ p { margin-bottom: 1em; }
102
+
103
+ p:first-of-type::first-letter {
104
+ font-size: 3em;
105
+ font-weight: 700;
106
+ float: left;
107
+ line-height: 0.75;
108
+ padding-right: 8px;
109
+ padding-top: 4px;
110
+ color: #d4a437;
111
+ }
112
+
113
+ blockquote {
114
+ border-left: 3px solid #d4a437;
115
+ margin: 1.8em 0;
116
+ padding: 16px 24px;
117
+ background: #fdf8f0;
78
118
  font-style: italic;
119
+ font-size: 12pt;
120
+ color: #555;
79
121
  }
80
- .content ul, .content ol {
81
- padding-left: 1.5rem;
82
- margin-bottom: 1rem;
83
- }
84
- .content li { margin-bottom: 0.5rem; }
85
- .highlight {
86
- background: #fff3cd;
87
- padding: 15px 20px;
88
- border-radius: 6px;
89
- margin: 1.25rem 0;
122
+
123
+ a { color: #b8860b; }
124
+
125
+ ul, ol { margin: 0.8em 0 0.8em 1.6em; }
126
+ li { margin-bottom: 0.4em; }
127
+
128
+ hr {
129
+ border: none;
130
+ text-align: center;
131
+ margin: 2em 0;
132
+ color: #ccc;
133
+ }
134
+ hr::before {
135
+ content: '— ◆ —';
136
+ letter-spacing: 6px;
137
+ color: #ccc;
138
+ font-size: 9pt;
139
+ }
140
+
141
+ table {
142
+ width: 100%;
143
+ border-collapse: collapse;
144
+ margin: 1.5em 0;
145
+ font-size: 10pt;
146
+ }
147
+ th {
148
+ background: #1a1a1a;
149
+ color: white;
150
+ padding: 8px 14px;
151
+ text-align: left;
152
+ font-family: -apple-system, sans-serif;
153
+ font-size: 9pt;
154
+ letter-spacing: 0.5px;
155
+ }
156
+ td {
157
+ padding: 8px 14px;
158
+ border-bottom: 1px solid #eee;
90
159
  }
160
+ tr:nth-child(even) td { background: #fdf8f0; }
161
+
162
+ code {
163
+ font-family: 'SF Mono', monospace;
164
+ font-size: 9pt;
165
+ background: #f5f0e8;
166
+ padding: 1px 5px;
167
+ border-radius: 2px;
168
+ }
169
+
170
+ /* ── FOOTER ── */
91
171
  .footer {
172
+ background: #1a1a1a;
173
+ color: rgba(255,255,255,0.5);
92
174
  text-align: center;
93
- padding-top: 30px;
94
- margin-top: 40px;
95
- border-top: 1px solid #eee;
96
- font-size: 0.85rem;
97
- color: #888;
98
- }
175
+ padding: 28px 56px;
176
+ font-family: -apple-system, 'Helvetica Neue', sans-serif;
177
+ font-size: 8.5pt;
178
+ letter-spacing: 0.3px;
179
+ }
180
+
181
+ .footer a { color: #d4a437; }
182
+
183
+ /* ── PRINT ── */
99
184
  @media print {
100
- body { background: #fff; }
101
- .container { box-shadow: none; margin: 0; }
185
+ body { background: white; }
186
+ .wrapper { box-shadow: none; border: none; margin: 0; }
187
+ .masthead { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
188
+ .footer { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
102
189
  }
103
190
  </style>
104
191
  </head>
105
192
  <body>
106
- <div class="container">
107
- <div class="header">
108
- <h1>{{#if frontMatter.title}}{{frontMatter.title}}{{else}}Newsletter{{/if}}</h1>
109
- <div class="date">{{#if frontMatter.date}}{{frontMatter.date}}{{else}}{{currentDate}}{{/if}}</div>
193
+ <div class="wrapper">
194
+
195
+ <div class="masthead">
196
+ <div class="masthead-label">Newsletter</div>
197
+ <h1>{{#if title}}{{title}}{{else}}The Weekly Brief{{/if}}</h1>
198
+ <div class="masthead-meta">
199
+ {{#if author}}By {{author}} · {{/if}}{{#if date}}{{date}}{{/if}}
200
+ </div>
110
201
  </div>
111
- <div class="content">
202
+
203
+ <div class="body">
112
204
  {{{content}}}
113
205
  </div>
206
+
114
207
  <div class="footer">
115
- Generated with md2pdf2
208
+ {{#if footer_text}}{{footer_text}}{{else}}
209
+ You're receiving this because you subscribed. ·
210
+ <a href="#">Unsubscribe</a>
211
+ {{/if}}
116
212
  </div>
213
+
117
214
  </div>
118
215
  </body>
119
216
  </html>
@@ -0,0 +1,261 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{title}}</title>
7
+ <style>
8
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Playfair+Display:wght@700&display=swap');
9
+
10
+ * { box-sizing: border-box; margin: 0; padding: 0; }
11
+
12
+ body {
13
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
14
+ font-size: 11pt;
15
+ line-height: 1.7;
16
+ color: #1a1a2e;
17
+ background: #fff;
18
+ }
19
+
20
+ /* ── COVER PAGE ── */
21
+ .cover {
22
+ min-height: 100vh;
23
+ display: flex;
24
+ flex-direction: column;
25
+ justify-content: space-between;
26
+ background: linear-gradient(135deg, #0f3460 0%, #16213e 60%, #1a1a2e 100%);
27
+ color: white;
28
+ padding: 80px 72px;
29
+ page-break-after: always;
30
+ position: relative;
31
+ overflow: hidden;
32
+ }
33
+
34
+ .cover::before {
35
+ content: '';
36
+ position: absolute;
37
+ top: -100px; right: -100px;
38
+ width: 500px; height: 500px;
39
+ background: radial-gradient(circle, rgba(233,69,96,0.25) 0%, transparent 70%);
40
+ border-radius: 50%;
41
+ }
42
+
43
+ .cover::after {
44
+ content: '';
45
+ position: absolute;
46
+ bottom: -80px; left: -80px;
47
+ width: 400px; height: 400px;
48
+ background: radial-gradient(circle, rgba(22,158,255,0.2) 0%, transparent 70%);
49
+ border-radius: 50%;
50
+ }
51
+
52
+ .cover-logo {
53
+ font-size: 13pt;
54
+ font-weight: 600;
55
+ letter-spacing: 3px;
56
+ text-transform: uppercase;
57
+ opacity: 0.7;
58
+ z-index: 1;
59
+ }
60
+
61
+ .cover-main { z-index: 1; }
62
+
63
+ .cover-tag {
64
+ display: inline-block;
65
+ background: rgba(233,69,96,0.9);
66
+ color: white;
67
+ font-size: 8pt;
68
+ font-weight: 600;
69
+ letter-spacing: 2px;
70
+ text-transform: uppercase;
71
+ padding: 6px 14px;
72
+ border-radius: 2px;
73
+ margin-bottom: 28px;
74
+ }
75
+
76
+ .cover h1 {
77
+ font-family: 'Playfair Display', Georgia, serif;
78
+ font-size: 42pt;
79
+ font-weight: 700;
80
+ line-height: 1.1;
81
+ margin-bottom: 20px;
82
+ letter-spacing: -0.5px;
83
+ }
84
+
85
+ .cover-subtitle {
86
+ font-size: 14pt;
87
+ font-weight: 300;
88
+ opacity: 0.75;
89
+ max-width: 480px;
90
+ }
91
+
92
+ .cover-footer {
93
+ z-index: 1;
94
+ display: flex;
95
+ justify-content: space-between;
96
+ align-items: flex-end;
97
+ border-top: 1px solid rgba(255,255,255,0.15);
98
+ padding-top: 24px;
99
+ }
100
+
101
+ .cover-meta { font-size: 10pt; opacity: 0.65; }
102
+ .cover-meta strong { display: block; opacity: 1; font-weight: 500; }
103
+
104
+ /* ── CONTENT ── */
105
+ .content {
106
+ max-width: 720px;
107
+ margin: 0 auto;
108
+ padding: 60px 72px;
109
+ }
110
+
111
+ h1, h2, h3, h4, h5, h6 {
112
+ font-weight: 600;
113
+ line-height: 1.25;
114
+ margin-top: 2em;
115
+ margin-bottom: 0.6em;
116
+ color: #0f3460;
117
+ }
118
+
119
+ h1 { font-size: 22pt; border-bottom: 3px solid #e94560; padding-bottom: 10px; }
120
+ h2 { font-size: 16pt; border-bottom: 1px solid #e0e0e0; padding-bottom: 8px; }
121
+ h3 { font-size: 13pt; color: #16213e; }
122
+ h4 { font-size: 11pt; color: #16213e; font-weight: 600; }
123
+
124
+ p { margin-bottom: 1em; }
125
+
126
+ a { color: #e94560; text-decoration: none; }
127
+
128
+ strong { font-weight: 600; color: #0f3460; }
129
+ em { font-style: italic; color: #444; }
130
+
131
+ /* Tables */
132
+ table {
133
+ width: 100%;
134
+ border-collapse: collapse;
135
+ margin: 1.5em 0;
136
+ font-size: 10pt;
137
+ }
138
+ thead {
139
+ background: #0f3460;
140
+ color: white;
141
+ }
142
+ thead th {
143
+ padding: 10px 14px;
144
+ text-align: left;
145
+ font-weight: 500;
146
+ letter-spacing: 0.5px;
147
+ }
148
+ tbody tr:nth-child(even) { background: #f8f9fc; }
149
+ tbody tr:hover { background: #eef1f8; }
150
+ tbody td {
151
+ padding: 9px 14px;
152
+ border-bottom: 1px solid #e5e9f0;
153
+ }
154
+
155
+ /* Code */
156
+ code {
157
+ background: #f0f3f9;
158
+ color: #c7254e;
159
+ font-family: 'SF Mono', 'Fira Code', monospace;
160
+ font-size: 9pt;
161
+ padding: 2px 6px;
162
+ border-radius: 3px;
163
+ }
164
+ pre {
165
+ background: #1a1a2e;
166
+ color: #e2e8f0;
167
+ padding: 20px 24px;
168
+ border-radius: 6px;
169
+ overflow-x: auto;
170
+ margin: 1.5em 0;
171
+ border-left: 4px solid #e94560;
172
+ }
173
+ pre code {
174
+ background: none;
175
+ color: inherit;
176
+ padding: 0;
177
+ font-size: 9pt;
178
+ line-height: 1.6;
179
+ }
180
+
181
+ /* Blockquotes */
182
+ blockquote {
183
+ border-left: 4px solid #e94560;
184
+ margin: 1.5em 0;
185
+ padding: 12px 20px;
186
+ background: #fef5f7;
187
+ color: #555;
188
+ font-style: italic;
189
+ border-radius: 0 4px 4px 0;
190
+ }
191
+
192
+ /* Lists */
193
+ ul, ol {
194
+ margin: 0.8em 0 0.8em 1.5em;
195
+ }
196
+ li { margin-bottom: 0.3em; }
197
+ li::marker { color: #e94560; }
198
+
199
+ /* Callout / Info box using blockquote with > **Note** */
200
+ blockquote strong:first-child {
201
+ display: block;
202
+ color: #0f3460;
203
+ font-style: normal;
204
+ margin-bottom: 4px;
205
+ }
206
+
207
+ /* Horizontal Rule */
208
+ hr {
209
+ border: none;
210
+ border-top: 2px solid #e5e9f0;
211
+ margin: 2em 0;
212
+ }
213
+
214
+ /* Page numbers */
215
+ @page { margin: 0; }
216
+ .page-number {
217
+ position: fixed;
218
+ bottom: 24px;
219
+ right: 48px;
220
+ font-size: 9pt;
221
+ color: #999;
222
+ }
223
+
224
+ /* Print */
225
+ @media print {
226
+ body { font-size: 10.5pt; }
227
+ .cover { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
228
+ pre, blockquote, table { page-break-inside: avoid; }
229
+ h2, h3 { page-break-after: avoid; }
230
+ }
231
+ </style>
232
+ </head>
233
+ <body>
234
+
235
+ <!-- Cover Page -->
236
+ <div class="cover">
237
+ <div class="cover-logo">{{#if author}}{{author}}{{else}}Professional Report{{/if}}</div>
238
+ <div class="cover-main">
239
+ <div class="cover-tag">Report</div>
240
+ <h1>{{#if title}}{{title}}{{else}}Document Title{{/if}}</h1>
241
+ {{#if subtitle}}<p class="cover-subtitle">{{subtitle}}</p>{{/if}}
242
+ </div>
243
+ <div class="cover-footer">
244
+ <div class="cover-meta">
245
+ <strong>Prepared by</strong>
246
+ {{#if author}}{{author}}{{else}}—{{/if}}
247
+ </div>
248
+ <div class="cover-meta" style="text-align:right">
249
+ <strong>Date</strong>
250
+ {{#if date}}{{date}}{{else}}—{{/if}}
251
+ </div>
252
+ </div>
253
+ </div>
254
+
255
+ <!-- Content -->
256
+ <div class="content">
257
+ {{{content}}}
258
+ </div>
259
+
260
+ </body>
261
+ </html>
@@ -2,133 +2,210 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>{{#if frontMatter.name}}{{frontMatter.name}} - Resume{{else}}Resume{{/if}}</title>
5
+ <title>{{title}}</title>
7
6
  <style>
8
7
  * { box-sizing: border-box; margin: 0; padding: 0; }
8
+
9
9
  body {
10
- font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
10
+ font-family: -apple-system, 'Helvetica Neue', Arial, sans-serif;
11
+ font-size: 10pt;
11
12
  line-height: 1.5;
12
- color: #2c3e50;
13
- max-width: 800px;
14
- margin: 0 auto;
15
- padding: 0;
13
+ color: #2d2d2d;
14
+ background: #fff;
15
+ }
16
+
17
+ /* ── HEADER ── */
18
+ .resume-header {
19
+ background: #1b262c;
20
+ color: white;
21
+ padding: 40px 56px;
22
+ display: flex;
23
+ align-items: center;
24
+ gap: 32px;
25
+ }
26
+
27
+ .header-avatar {
28
+ width: 80px; height: 80px;
29
+ border-radius: 50%;
30
+ background: linear-gradient(135deg, #00b4d8, #0077b6);
31
+ display: flex; align-items: center; justify-content: center;
32
+ font-size: 28pt; font-weight: 700; color: white;
33
+ flex-shrink: 0;
34
+ }
35
+
36
+ .header-info h1 {
37
+ font-size: 22pt;
38
+ font-weight: 700;
39
+ letter-spacing: -0.5px;
40
+ color: white;
41
+ margin: 0 0 4px;
42
+ }
43
+
44
+ .header-role {
16
45
  font-size: 11pt;
46
+ color: #00b4d8;
47
+ font-weight: 500;
48
+ margin-bottom: 10px;
17
49
  }
18
- .header {
19
- text-align: center;
20
- padding: 30px 0;
21
- border-bottom: 2px solid #3498db;
22
- }
23
- .header h1 {
24
- font-size: 28pt;
25
- font-weight: 300;
50
+
51
+ .header-contact {
52
+ display: flex;
53
+ flex-wrap: wrap;
54
+ gap: 8px 20px;
55
+ font-size: 9pt;
56
+ color: rgba(255,255,255,0.65);
57
+ }
58
+
59
+ /* ── BODY LAYOUT ── */
60
+ .resume-body {
61
+ display: grid;
62
+ grid-template-columns: 220px 1fr;
63
+ min-height: calc(100vh - 160px);
64
+ }
65
+
66
+ /* ── SIDEBAR ── */
67
+ .sidebar {
68
+ background: #f4f8fb;
69
+ padding: 36px 28px;
70
+ border-right: 1px solid #e0e8ee;
71
+ }
72
+
73
+ .sidebar-section { margin-bottom: 28px; }
74
+
75
+ .sidebar-label {
76
+ font-size: 7.5pt;
77
+ font-weight: 700;
26
78
  letter-spacing: 2px;
27
- margin-bottom: 8px;
28
- color: #2c3e50;
29
- }
30
- .header .contact {
31
- font-size: 10pt;
32
- color: #7f8c8d;
33
- }
34
- .header .contact a {
35
- color: #3498db;
36
- text-decoration: none;
37
- margin: 0 10px;
38
- }
39
- .section {
40
- padding: 20px 0;
41
- border-bottom: 1px solid #eee;
42
- }
43
- .section:last-child { border-bottom: none; }
44
- .section-title {
45
- font-size: 12pt;
46
- font-weight: 600;
47
- color: #3498db;
48
79
  text-transform: uppercase;
49
- letter-spacing: 1px;
50
- margin-bottom: 15px;
51
- }
52
- .section h2 {
53
- font-size: 11pt;
54
- margin-bottom: 4px;
55
- color: #2c3e50;
56
- }
57
- .section h3 {
58
- font-size: 10pt;
59
- font-weight: normal;
60
- color: #7f8c8d;
61
- margin-bottom: 8px;
80
+ color: #0077b6;
81
+ margin-bottom: 10px;
82
+ padding-bottom: 4px;
83
+ border-bottom: 2px solid #00b4d8;
62
84
  }
63
- .section p {
85
+
86
+ .skill-bar {
64
87
  margin-bottom: 8px;
65
- font-size: 10pt;
66
88
  }
67
- .section ul {
68
- padding-left: 20px;
69
- margin-bottom: 15px;
70
- }
71
- .section li {
72
- font-size: 10pt;
73
- margin-bottom: 4px;
74
- }
75
- .skills-grid {
76
- display: flex;
77
- flex-wrap: wrap;
78
- gap: 8px;
79
- }
80
- .skill-tag {
81
- background: #ecf0f1;
82
- padding: 4px 12px;
83
- border-radius: 3px;
89
+ .skill-bar span {
84
90
  font-size: 9pt;
85
- color: #2c3e50;
86
- }
87
- .entry {
88
- margin-bottom: 20px;
89
- }
90
- .entry-header {
91
- display: flex;
92
- justify-content: space-between;
93
- align-items: baseline;
94
- margin-bottom: 5px;
95
- }
96
- .entry-title {
91
+ display: block;
92
+ margin-bottom: 3px;
93
+ color: #333;
94
+ }
95
+ .skill-track {
96
+ height: 4px;
97
+ background: #dde8f0;
98
+ border-radius: 2px;
99
+ overflow: hidden;
100
+ }
101
+ .skill-fill {
102
+ height: 100%;
103
+ background: linear-gradient(90deg, #0077b6, #00b4d8);
104
+ border-radius: 2px;
105
+ }
106
+
107
+ /* ── MAIN CONTENT ── */
108
+ .main {
109
+ padding: 36px 48px;
110
+ }
111
+
112
+ h1 { display: none; } /* Hidden — shown in header */
113
+ h2 {
114
+ font-size: 11pt;
115
+ font-weight: 700;
116
+ letter-spacing: 1.5px;
117
+ text-transform: uppercase;
118
+ color: #0077b6;
119
+ border-bottom: 2px solid #e0e8ee;
120
+ padding-bottom: 6px;
121
+ margin-bottom: 16px;
122
+ margin-top: 28px;
123
+ }
124
+ h2:first-child { margin-top: 0; }
125
+ h3 {
97
126
  font-size: 11pt;
98
127
  font-weight: 600;
128
+ color: #1b262c;
129
+ margin-bottom: 2px;
99
130
  }
100
- .entry-date {
101
- font-size: 9pt;
102
- color: #7f8c8d;
131
+ h4 {
132
+ font-size: 9.5pt;
133
+ font-weight: 400;
134
+ color: #0077b6;
135
+ margin-bottom: 4px;
103
136
  }
104
- .entry-company {
105
- font-size: 10pt;
106
- color: #7f8c8d;
107
- margin-bottom: 8px;
137
+ p { margin-bottom: 0.7em; font-size: 9.5pt; color: #444; }
138
+
139
+ ul {
140
+ margin: 0.3em 0 0.8em 1.2em;
141
+ list-style: none;
142
+ padding: 0;
108
143
  }
109
- a { color: #3498db; text-decoration: none; }
110
- code {
111
- background: #f8f9fa;
112
- padding: 0.15em 0.4em;
113
- border-radius: 3px;
114
- font-size: 0.9em;
144
+ li {
145
+ margin-bottom: 4px;
146
+ font-size: 9.5pt;
147
+ color: #444;
148
+ padding-left: 1em;
149
+ position: relative;
150
+ }
151
+ li::before {
152
+ content: '▸';
153
+ position: absolute;
154
+ left: 0;
155
+ color: #00b4d8;
156
+ font-size: 8pt;
157
+ }
158
+
159
+ .job-meta {
160
+ display: flex;
161
+ justify-content: space-between;
162
+ font-size: 8.5pt;
163
+ color: #888;
164
+ margin-bottom: 6px;
115
165
  }
166
+
167
+ /* ── PRINT ── */
116
168
  @media print {
117
- body { padding: 0.5in; }
118
- .section { page-break-inside: avoid; }
169
+ body { font-size: 9.5pt; }
170
+ .resume-header, .sidebar {
171
+ -webkit-print-color-adjust: exact;
172
+ print-color-adjust: exact;
173
+ }
119
174
  }
120
175
  </style>
121
176
  </head>
122
177
  <body>
123
- <div class="header">
124
- <h1>{{#if frontMatter.name}}{{frontMatter.name}}{{else}}Your Name{{/if}}</h1>
125
- <div class="contact">
126
- {{#if frontMatter.email}}<a href="mailto:{{frontMatter.email}}">{{frontMatter.email}}</a>{{/if}}
127
- {{#if frontMatter.phone}}<a href="tel:{{frontMatter.phone}}">{{frontMatter.phone}}</a>{{/if}}
128
- {{#if frontMatter.linkedin}}<a href="{{frontMatter.linkedin}}">LinkedIn</a>{{/if}}
129
- {{#if frontMatter.github}}<a href="{{frontMatter.github}}">GitHub</a>{{/if}}
178
+
179
+ <div class="resume-header">
180
+ <div class="header-avatar">
181
+ {{#if initials}}{{initials}}{{else}}{{#if title}}{{slice title 0 1}}{{else}}?{{/if}}{{/if}}
182
+ </div>
183
+ <div class="header-info">
184
+ <h1>{{#if title}}{{title}}{{else}}Full Name{{/if}}</h1>
185
+ <div class="header-role">{{#if role}}{{role}}{{else}}Professional Title{{/if}}</div>
186
+ <div class="header-contact">
187
+ {{#if email}}<span>✉ {{email}}</span>{{/if}}
188
+ {{#if phone}}<span>✆ {{phone}}</span>{{/if}}
189
+ {{#if location}}<span>⌖ {{location}}</span>{{/if}}
190
+ {{#if website}}<span>⬡ {{website}}</span>{{/if}}
191
+ </div>
192
+ </div>
193
+ </div>
194
+
195
+ <div class="resume-body">
196
+ <div class="sidebar">
197
+ <!-- Sidebar rendered by separate partial or manually -->
198
+ {{#if skills_sidebar}}
199
+ <div class="sidebar-section">
200
+ <div class="sidebar-label">Skills</div>
201
+ {{{skills_sidebar}}}
202
+ </div>
203
+ {{/if}}
204
+ </div>
205
+ <div class="main">
206
+ {{{content}}}
130
207
  </div>
131
208
  </div>
132
- <main>{{{content}}}</main>
209
+
133
210
  </body>
134
211
  </html>