resuml 1.2.5 → 1.3.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/README.md CHANGED
@@ -1,6 +1,60 @@
1
- # resuml
1
+ <h1 align="center">✨ Resuml</h1>
2
+ <p align="center"><strong>Write your resume in YAML. Render it beautifully.</strong></p>
2
3
 
3
- A CLI tool for generating JSON resumes from YAML with theme support. This tool helps you maintain your resume in YAML format and convert it to various formats including JSON and HTML with different themes.
4
+ <p align="center">
5
+ <a href="https://www.npmjs.com/package/resuml"><img src="https://img.shields.io/npm/v/resuml.svg" alt="npm version"></a>
6
+ <a href="https://www.npmjs.com/package/resuml"><img src="https://img.shields.io/npm/dm/resuml.svg" alt="npm downloads"></a>
7
+ <a href="https://github.com/phoinixi/resuml/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/resuml.svg" alt="license"></a>
8
+ <a href="https://github.com/phoinixi/resuml"><img src="https://img.shields.io/github/stars/phoinixi/resuml.svg?style=social" alt="GitHub stars"></a>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.buymeacoffee.com/leekbeds55j">
13
+ <img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" width="150" />
14
+ </a>
15
+ </p>
16
+
17
+ ---
18
+
19
+ ### YAML in → Beautiful resume out
20
+
21
+ ```yaml
22
+ # resume.yaml
23
+ basics:
24
+ name: Jane Smith
25
+ label: Senior Software Engineer
26
+ email: jane@example.com
27
+ summary: >-
28
+ Passionate engineer with 8+ years
29
+ building scalable distributed systems.
30
+ work:
31
+ - name: Acme Corp
32
+ position: Lead Engineer
33
+ startDate: 2020-01-15
34
+ highlights:
35
+ - Reduced deploy time by 60%
36
+ - Led team of 12 engineers
37
+ ```
38
+
39
+ ```bash
40
+ resuml render --resume resume.yaml --theme stackoverflow --output resume.html
41
+ ```
42
+
43
+ Your YAML becomes a polished, professional resume — ready to share, print, or export to PDF.
44
+
45
+ ---
46
+
47
+ ## Why YAML?
48
+
49
+ | | YAML | JSON |
50
+ |---|---|---|
51
+ | **Comments** | ✅ `# explain your choices` | ❌ Not supported |
52
+ | **Multi-line strings** | ✅ `summary: >-` block syntax | ❌ Escape everything |
53
+ | **Readability** | ✅ Clean, minimal syntax | ⚠️ Brackets & quotes everywhere |
54
+ | **Diffing** | ✅ Clean git diffs | ⚠️ Noisy diffs |
55
+ | **Compatibility** | ✅ Valid JSON Resume schema | ✅ Native |
56
+
57
+ YAML is a superset of JSON — your resume stays fully compatible with the [JSON Resume](https://jsonresume.org/) ecosystem while being far more pleasant to write and maintain.
4
58
 
5
59
  ## Prerequisites
6
60
 
@@ -29,44 +83,48 @@ npm install -g resuml
29
83
  resuml render --resume resume.yaml --theme stackoverflow --output resume.html
30
84
  ```
31
85
 
32
- ## Usage
86
+ ## Commands
33
87
 
34
- ### Validate resume data
88
+ | Command | Description |
89
+ |---------|-------------|
90
+ | `validate` | Validate resume data against the JSON Resume schema |
91
+ | `tojson` | Convert YAML resume data to JSON format |
92
+ | `render` | Render the resume using a specified theme |
93
+ | `dev` | Start a development server with hot-reload |
35
94
 
36
- ```bash
37
- resuml validate --resume resume.yaml
38
- ```
95
+ ## Options
39
96
 
40
- ### Convert YAML to JSON
97
+ | Option | Alias | Description |
98
+ |--------|-------|-------------|
99
+ | `--resume` | `-r` | Input YAML file(s) or directory |
100
+ | `--output` | `-o` | Output file path |
101
+ | `--theme` | `-t` | Theme to use for rendering |
102
+ | `--port` | `-p` | Port for dev server (default: 3000) |
103
+ | `--language` | | Language code for localization (default: `en`) |
104
+ | `--debug` | | Enable debug mode for detailed errors |
41
105
 
42
- ```bash
43
- resuml tojson --resume resume.yaml --output resume.json
44
- ```
106
+ ## Compatible Themes
45
107
 
46
- ### Render resume with theme
108
+ Resuml supports themes from the JSON Resume ecosystem. Install a theme, then pass its name to `--theme`:
47
109
 
48
110
  ```bash
49
- resuml render --resume resume.yaml --theme stackoverflow --output resume.html
111
+ npm install jsonresume-theme-stackoverflow
112
+ resuml render --resume resume.yaml --theme stackoverflow
50
113
  ```
51
114
 
52
- ## Examples
53
-
54
- For detailed examples and usage instructions, see the [examples/README.md](examples/README.md) file.
115
+ | Theme | Install | Style |
116
+ |-------|---------|-------|
117
+ | [stackoverflow](https://github.com/francoislaberge/jsonresume-theme-stackoverflow) | `npm i jsonresume-theme-stackoverflow` | Clean, professional |
118
+ | [elegant](https://github.com/mudassir0909/jsonresume-theme-elegant) | `npm i jsonresume-theme-elegant` | Modern, elegant |
119
+ | [kendall](https://github.com/LinuxBozo/jsonresume-theme-kendall) | `npm i jsonresume-theme-kendall` | Minimal, classic |
120
+ | [flat](https://github.com/erming/jsonresume-theme-flat) | `npm i jsonresume-theme-flat` | Flat design |
121
+ | [onepage](https://github.com/aonemd/jsonresume-theme-onepage) | `npm i jsonresume-theme-onepage` | Single page |
55
122
 
56
- ## Commands
123
+ > Browse all themes at [jsonresume.org/themes](https://jsonresume.org/themes/) — any `jsonresume-theme-*` package works with resuml.
57
124
 
58
- - `validate` - Validates resume data against the JSON Resume schema
59
- - `tojson` - Converts YAML resume data to JSON format
60
- - `render` - Renders the resume using a specified theme
61
- - `dev` - Starts a development server with hot-reload
62
-
63
- ## Options
125
+ ## Examples
64
126
 
65
- - `--resume, -r` - Input YAML file(s) or directory
66
- - `--output, -o` - Output file path
67
- - `--theme, -t` - Theme to use for rendering
68
- - `--port, -p` - Port for development server (default: 3000)
69
- - `--debug` - Enable debug mode for detailed error messages
127
+ For detailed examples and usage instructions, see the [examples/README.md](examples/README.md) file.
70
128
 
71
129
  ## Example YAML Structure
72
130
 
@@ -91,24 +149,76 @@ work:
91
149
  summary: Led development of...
92
150
  ```
93
151
 
94
- ## Available Themes
152
+ ## CI/CD: Auto-build on Push
95
153
 
96
- - `stackoverflow` - Clean and professional theme based on Stack Overflow's style
97
- - `react` - Modern React-based theme with interactive features
98
- - More themes coming soon...
154
+ Use GitHub Actions to automatically rebuild your resume when you push changes:
155
+
156
+ ```yaml
157
+ # .github/workflows/resume.yml
158
+ name: Build Resume
159
+
160
+ on:
161
+ push:
162
+ paths: ['resume.yaml', 'resume/*.yaml']
163
+
164
+ jobs:
165
+ build:
166
+ runs-on: ubuntu-latest
167
+ steps:
168
+ - uses: actions/checkout@v4
169
+
170
+ - uses: actions/setup-node@v4
171
+ with:
172
+ node-version: 20
173
+
174
+ - run: npm install -g resuml
175
+ - run: npm install jsonresume-theme-stackoverflow
176
+
177
+ - run: resuml render --resume resume.yaml --theme stackoverflow --output resume.html
178
+ - run: resuml tojson --resume resume.yaml --output resume.json
179
+
180
+ - uses: actions/upload-artifact@v4
181
+ with:
182
+ name: resume
183
+ path: |
184
+ resume.html
185
+ resume.json
186
+ ```
187
+
188
+ ## Node.js API Usage
189
+
190
+ You can use resuml programmatically from Node.js:
191
+
192
+ ```js
193
+ import {
194
+ processResumeData,
195
+ loadResumeFiles,
196
+ loadTheme,
197
+ themeRender
198
+ } from 'resuml';
199
+
200
+ // Load YAML files
201
+ const { yamlContents } = await loadResumeFiles('resume.yaml');
202
+ // Validate and merge
203
+ const resume = await processResumeData(yamlContents);
204
+ // Load a theme
205
+ const theme = await loadTheme('stackoverflow');
206
+ // Render HTML
207
+ const html = await theme.render(resume, { locale: 'en' });
208
+ ```
209
+
210
+ See the CLI and API for more details.
99
211
 
100
212
  ## Troubleshooting
101
213
 
102
214
  ### Common Issues
103
215
 
104
216
  1. **Validation Errors**
105
-
106
217
  - Ensure your YAML follows the JSON Resume schema
107
218
  - Check for proper indentation in your YAML file
108
219
  - Verify all required fields are present
109
220
 
110
221
  2. **Theme Rendering Issues**
111
-
112
222
  - Make sure the theme is properly installed
113
223
  - Check if all required theme dependencies are installed
114
224
  - Try running with `--debug` flag for more information
@@ -125,27 +235,3 @@ Contributions are welcome! Please feel free to submit a Pull Request.
125
235
  ## License
126
236
 
127
237
  ISC
128
-
129
- ## Node.js API Usage
130
-
131
- You can use resuml programmatically from Node.js:
132
-
133
- ```js
134
- import {
135
- processResumeData,
136
- loadResumeFiles,
137
- loadTheme,
138
- themeRender
139
- } from 'resuml';
140
-
141
- // Load YAML files
142
- const { yamlContents } = await loadResumeFiles('resume.yaml');
143
- // Validate and merge
144
- const resume = await processResumeData(yamlContents);
145
- // Load a theme
146
- const theme = await loadTheme('stackoverflow');
147
- // Render HTML
148
- const html = await theme.render(resume, { locale: 'en' });
149
- ```
150
-
151
- See the CLI and API for more details.
package/dist/api.js CHANGED
@@ -38,7 +38,7 @@ var getImportMetaUrl, importMetaUrl;
38
38
  var init_cjs_shims = __esm({
39
39
  "node_modules/tsup/assets/cjs_shims.js"() {
40
40
  "use strict";
41
- getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
41
+ getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
42
42
  importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
43
43
  }
44
44
  });
@@ -180,7 +180,7 @@ var require_brace_expansion = __commonJS({
180
180
  var isSequence = isNumericSequence || isAlphaSequence;
181
181
  var isOptions = m.body.indexOf(",") >= 0;
182
182
  if (!isSequence && !isOptions) {
183
- if (m.post.match(/,.*\}/)) {
183
+ if (m.post.match(/,(?!,).*\}/)) {
184
184
  str = m.pre + "{" + m.body + escClose + m.post;
185
185
  return expand2(str);
186
186
  }
@@ -261,7 +261,7 @@ __export(themeLoader_exports, {
261
261
  });
262
262
  async function installTheme(packageName) {
263
263
  try {
264
- (0, import_child_process.execSync)(`npm install ${packageName}`, {
264
+ (0, import_child_process.execFileSync)("npm", ["install", packageName], {
265
265
  stdio: ["inherit", "pipe", "pipe"],
266
266
  encoding: "utf8"
267
267
  });
@@ -1066,7 +1066,7 @@ var path = {
1066
1066
  };
1067
1067
  var sep = defaultPlatform === "win32" ? path.win32.sep : path.posix.sep;
1068
1068
  minimatch.sep = sep;
1069
- var GLOBSTAR = Symbol("globstar **");
1069
+ var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
1070
1070
  minimatch.GLOBSTAR = GLOBSTAR;
1071
1071
  var qmark2 = "[^/]";
1072
1072
  var star2 = qmark2 + "*?";
@@ -1771,7 +1771,6 @@ if (typeof AC === "undefined") {
1771
1771
  };
1772
1772
  }
1773
1773
  var shouldWarn = (code) => !warned.has(code);
1774
- var TYPE = Symbol("type");
1775
1774
  var isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n);
1776
1775
  var getUintArray = (max) => !isPosInt(max) ? null : max <= Math.pow(2, 8) ? Uint8Array : max <= Math.pow(2, 16) ? Uint16Array : max <= Math.pow(2, 32) ? Uint32Array : max <= Number.MAX_SAFE_INTEGER ? ZeroArray : null;
1777
1776
  var ZeroArray = class extends Array {
@@ -3116,37 +3115,37 @@ var isStream = (s) => !!s && typeof s === "object" && (s instanceof Minipass ||
3116
3115
  var isReadable = (s) => !!s && typeof s === "object" && s instanceof import_node_events.EventEmitter && typeof s.pipe === "function" && // node core Writable streams have a pipe() method, but it throws
3117
3116
  s.pipe !== import_node_stream.default.Writable.prototype.pipe;
3118
3117
  var isWritable = (s) => !!s && typeof s === "object" && s instanceof import_node_events.EventEmitter && typeof s.write === "function" && typeof s.end === "function";
3119
- var EOF = Symbol("EOF");
3120
- var MAYBE_EMIT_END = Symbol("maybeEmitEnd");
3121
- var EMITTED_END = Symbol("emittedEnd");
3122
- var EMITTING_END = Symbol("emittingEnd");
3123
- var EMITTED_ERROR = Symbol("emittedError");
3124
- var CLOSED = Symbol("closed");
3125
- var READ = Symbol("read");
3126
- var FLUSH = Symbol("flush");
3127
- var FLUSHCHUNK = Symbol("flushChunk");
3128
- var ENCODING = Symbol("encoding");
3129
- var DECODER = Symbol("decoder");
3130
- var FLOWING = Symbol("flowing");
3131
- var PAUSED = Symbol("paused");
3132
- var RESUME = Symbol("resume");
3133
- var BUFFER = Symbol("buffer");
3134
- var PIPES = Symbol("pipes");
3135
- var BUFFERLENGTH = Symbol("bufferLength");
3136
- var BUFFERPUSH = Symbol("bufferPush");
3137
- var BUFFERSHIFT = Symbol("bufferShift");
3138
- var OBJECTMODE = Symbol("objectMode");
3139
- var DESTROYED = Symbol("destroyed");
3140
- var ERROR = Symbol("error");
3141
- var EMITDATA = Symbol("emitData");
3142
- var EMITEND = Symbol("emitEnd");
3143
- var EMITEND2 = Symbol("emitEnd2");
3144
- var ASYNC = Symbol("async");
3145
- var ABORT = Symbol("abort");
3146
- var ABORTED = Symbol("aborted");
3147
- var SIGNAL = Symbol("signal");
3148
- var DATALISTENERS = Symbol("dataListeners");
3149
- var DISCARDED = Symbol("discarded");
3118
+ var EOF = /* @__PURE__ */ Symbol("EOF");
3119
+ var MAYBE_EMIT_END = /* @__PURE__ */ Symbol("maybeEmitEnd");
3120
+ var EMITTED_END = /* @__PURE__ */ Symbol("emittedEnd");
3121
+ var EMITTING_END = /* @__PURE__ */ Symbol("emittingEnd");
3122
+ var EMITTED_ERROR = /* @__PURE__ */ Symbol("emittedError");
3123
+ var CLOSED = /* @__PURE__ */ Symbol("closed");
3124
+ var READ = /* @__PURE__ */ Symbol("read");
3125
+ var FLUSH = /* @__PURE__ */ Symbol("flush");
3126
+ var FLUSHCHUNK = /* @__PURE__ */ Symbol("flushChunk");
3127
+ var ENCODING = /* @__PURE__ */ Symbol("encoding");
3128
+ var DECODER = /* @__PURE__ */ Symbol("decoder");
3129
+ var FLOWING = /* @__PURE__ */ Symbol("flowing");
3130
+ var PAUSED = /* @__PURE__ */ Symbol("paused");
3131
+ var RESUME = /* @__PURE__ */ Symbol("resume");
3132
+ var BUFFER = /* @__PURE__ */ Symbol("buffer");
3133
+ var PIPES = /* @__PURE__ */ Symbol("pipes");
3134
+ var BUFFERLENGTH = /* @__PURE__ */ Symbol("bufferLength");
3135
+ var BUFFERPUSH = /* @__PURE__ */ Symbol("bufferPush");
3136
+ var BUFFERSHIFT = /* @__PURE__ */ Symbol("bufferShift");
3137
+ var OBJECTMODE = /* @__PURE__ */ Symbol("objectMode");
3138
+ var DESTROYED = /* @__PURE__ */ Symbol("destroyed");
3139
+ var ERROR = /* @__PURE__ */ Symbol("error");
3140
+ var EMITDATA = /* @__PURE__ */ Symbol("emitData");
3141
+ var EMITEND = /* @__PURE__ */ Symbol("emitEnd");
3142
+ var EMITEND2 = /* @__PURE__ */ Symbol("emitEnd2");
3143
+ var ASYNC = /* @__PURE__ */ Symbol("async");
3144
+ var ABORT = /* @__PURE__ */ Symbol("abort");
3145
+ var ABORTED = /* @__PURE__ */ Symbol("aborted");
3146
+ var SIGNAL = /* @__PURE__ */ Symbol("signal");
3147
+ var DATALISTENERS = /* @__PURE__ */ Symbol("dataListeners");
3148
+ var DISCARDED = /* @__PURE__ */ Symbol("discarded");
3150
3149
  var defer = (fn) => Promise.resolve().then(fn);
3151
3150
  var nodefer = (fn) => fn();
3152
3151
  var isEndish = (ev) => ev === "end" || ev === "finish" || ev === "prefinish";
@@ -4059,7 +4058,7 @@ var ChildrenCache = class extends LRUCache {
4059
4058
  });
4060
4059
  }
4061
4060
  };
4062
- var setAsCwd = Symbol("PathScurry setAsCwd");
4061
+ var setAsCwd = /* @__PURE__ */ Symbol("PathScurry setAsCwd");
4063
4062
  var PathBase = class {
4064
4063
  /**
4065
4064
  * the basename of this path