diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 00000000..330ddccd --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,17 @@ +env: + es6: true + node: true +extends: 'eslint:recommended' +rules: + # indent: + # - error + # - 4 + linebreak-style: + - error + - unix + quotes: + - error + - single + semi: + - error + - always diff --git a/.gitattributes b/.gitattributes index f2525802..bb6568d5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,9 +1,11 @@ # Auto detect text files and perform LF normalization + * text=auto *.js text eol=lf *.json text eol=lf # Standard to msysgit + *.doc diff=astextplain *.DOC diff=astextplain *.docx diff=astextplain @@ -14,3 +16,7 @@ *.PDF diff=astextplain *.rtf diff=astextplain *.RTF diff=astextplain + +# Git LFS + +*.ai filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index ce751fe4..7f353760 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,40 @@ node_modules/ -tests/sandbox/ +doc/ docs/ +local/ +npm-debug.log +*.map + +# Emacs detritus +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..e313bb9c --- /dev/null +++ b/.npmignore @@ -0,0 +1,13 @@ +assets/ +test/ +doc/ +.travis.yml +.eslintrc.yml +Gruntfile.js +.gitattributes +ROADMAP.md +BUILDING.md +CONTRIBUTING.md +CHANGELOG.md +FAQ.md +*.map diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..7e83a1e6 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,23 @@ +sudo: required +before_install: + # Prevents a shared object .so error when running wkhtmltopdf on certain + # platforms (e.g., vanilla Ubuntu 16.04 LTS). Not necessary on current Travis. + # - sudo apt-get install libxrender1 +install: + # Install & link HackMyResume + - npm install && npm link + # Download and extract the latest wkhtmltopdf binaries + - mkdir tmp && wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz -O tmp/wk.tar.xz + - tar -xf tmp/wk.tar.xz -C ./tmp + # Copy wkhtmltopdf binaries to /usr/bin (also makes them path-accessible) + - sudo cp -R ./tmp/wkhtmltox/bin/* /usr/bin/ + # Now you can invoke "wkhtmltopdf" and "wkhtmltoimage" safely in tests. + - wkhtmltopdf -V + - wkhtmltoimage -V +language: node_js +node_js: + - "6" + - "7" + - "8" + - "9" + - "lts/*" diff --git a/BUILDING.md b/BUILDING.md new file mode 100644 index 00000000..1e95434a --- /dev/null +++ b/BUILDING.md @@ -0,0 +1,50 @@ +Building +======== + +*See [CONTRIBUTING.md][contrib] for more information on contributing to the +HackMyResume or FluentCV projects.* + +HackMyResume is a standard Node.js command line app implemented in a mix of +CoffeeScript and JavaScript. Setting up a build environment is easy: + + +## Prerequisites ## + +1. OS: Linux, OS X, or Windows + +2. Install [Node.js][node] and [Grunt][grunt]. + + +## Set up a build environment ### + +1. Fork [hacksalot/HackMyResume][hmr] to your GitHub account. + +2. Clone your fork locally. + +3. From within the top-level HackMyResume folder, run `npm install` to install +project dependencies. + +4. Create a new branch, based on the latest HackMyResume `dev` branch, to +contain your work. + +5. Run `npm link` in the HackMyResume folder so that the `hackmyresume` command +will reference your local installation (you may need to +`npm uninstall -g hackmyresume` first). + +## Making changes + +1. HackMyResume sources live in the [`/src`][src] folder. + +2. When you're ready to submit your changes, run `grunt test` to run the HMR +test suite. Fix any errors that occur. + +3. Commit and push your changes. + +4. Submit a pull request targeting the HackMyResume `dev` branch. + + +[node]: https://nodejs.org/en/ +[grunt]: http://gruntjs.com/ +[hmr]: https://github.com/hacksalot/HackMyResume +[src]: https://github.com/hacksalot/HackMyResume/tree/master/src +[contrib]: https://github.com/hacksalot/HackMyResume/blob/master/CONTRIBUTING.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..8f21ef38 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,503 @@ +CHANGELOG +========= + +## v1.9.0-beta + +*Welcome to the first new version of HackMyResume in over a year. The purpose of +this release is to gather feature enhancements and bug fixes collected over the +past 18 months as we reorganize, rebrand, and prepare for the 2.0 release.* + +### Added + +- Support for **private resume fields**. Mark any non-leaf node in your resume +JSON with the `private` property and it will be omitted from outbound resumes. + + ```json + "employment": { + "history": [ + { + "employer": "Acme Real Estate" + }, + { + "employer": "Area 51 Alien Research Laboratory", + "private": true + }, + { + "employer": "H&R Block" + } + ] + } + ``` +- Support for **PDF generation through WeasyPrint** in addition to the +existing support for wkhtmltopdf and PhantomJS. + +- Theme authors can now develop and package **custom Handlebars theme helpers** +via the `helpers` key of the `theme.json` file (FRESH themes only) (#158). + +- Help system has been updated with a `HELP` command and dedicated help pages +for each command. + +- Theme authors can **relocate theme assets** with the `baseFolder` property in +the FRESH `theme.json`. + +- HackMyResume will now **validate the options file** (if any) loaded with `-o` +or `--options` and warn the user if necessary. + +- Ability to **disable Handlebars encoding/escaping** of resume fields with +`--no-escape`. + +- Introduced the [fresh-test-themes][ftt] project as a repository for simple, +test-only resume themes in the FRESH format. + +### Changed + +- Dropped support for Node 4 and 5. HackMyResume officially runs on Node 6+. + +- The FRESCA project has been renamed to [fresh-resume-schema][fresca]. FRESCA +is still the nickname. + +- The HackMyResume web page has moved to https://fluentdesk.com/hackmyresume. + +### Fixed + +- Fixed an issue that would cause the `convert` command to detect the inbound +resume type (FRESH or JRS) incorrectly (#162). + +- Fixed an issue where generating new JRS resumes would cause a `null` or +`undefined` error (#165). + +- Fixed an issue preventing mixed-case themes from being loaded (#172). + +- Fixed an issue requiring JSON Resume themes contain `json-resume-theme` in the +theme path (#173). + +- Fixed an issue that would cause strange `@@@@` characters to appear in +generated resumes (#207, #168, #198). + +- Fixed an issue that would cause resume generation to hang after a JSON Resume +themed resume was generated (#182). + +- Fixed an issue that would cause nothing to be generated for Markdown (.md) +formats (#179). + +- Fixed an issue that would prevent a JRS resume from being converted to FRESH +via the `convert` command (#180). + +- Fixed an issue that would cause broken styling for JSON Resume themes (#155). + +### Internal + +- Tests: fixed resume duration tests (#181). + +- Style: move to + +## v1.8.0 + +### Added + +- Updated `Awesome` theme to latest version of [Awesome-CV][acv]. + +- Introduced new theme helpers: `pad`, `date`. + +### Fixed + +- Fixed an issue where the `Awesome` theme wouldn't correctly generate LaTeX +outputs (#138). + +- Emit a line number for syntax errors around embedded newlines in JSON strings +(#137). + +- Fix several PDF / PNG generation errors (#132, others). + +- Display a more helpful error message when attempting to generate a PDF or PNG +on a machine where PhantomJS and/or wkhtmltopdf are either not installed or +not path-accessible. + +- Fixed an issue that would cause long-running PDF/PNG generation to fail in +certain environments. + +- Fixed an issue involving an unhelpful spawn-related exception (#136). + +### Internal + +- JSHint will no longer gripe at the use of `== null` and `!= null` in +CoffeeScript transpilation. + +- Introduced [template-friendly Awesome-CV fork][awefork] to isolate template +expansion logic & provide better durability for HackMyResume's `awesome` theme. + +- Fixed a couple temporary regressions (#139, #140) on the dev branch. + +- Additional tests. + +- Minor breaking HackMyResume API changes. + +## v1.7.4 + +### Added + +- [Build instructions](https://github.com/hacksalot/HackMyResume/blob/master/BUILDING.md). + +### Changed + +- More precise date handling. + +### Fixed + +- Issue with incomplete PDF generation (#127). + +- Issue with building JSON Resume themes (#128). + +- Issue with generating `.json` output format by itself (#97). + +## v1.7.3 + +### Fixed + +- Issue with generated PDFs being chopped off and displaying a mysterious sequence of numbers of unknown and possibly alien origin (#127). + +- Unsightly border on Modern:PDF. + +- Modern|Positive:PDF formats now correctly reference their PDF-specific CSS files. + +- `Incorrect helper use` warning in Positive:DOC. + +## v1.7.2 + +### Changed + +- Interim release supporting FluentCV Desktop. + +### Internal + +- Moved [HackMyCore](https://github.com/hacksalot/HackMyCore) dependency to +submodule. + +## v1.7.1 + +### Changed + +- Caffeinate. CoffeeScript now used throughout +[HackMyResume](https://github.com/hacksalot/HackMyResume) and +[HackMyCore](https://github.com/hacksalot/HackMyCore); generated JavaScript +lives in `/dist`. + +### Fixed + +- Issue with generating a single PDF with the `.pdf` extension (#99). + +## v1.7.0 + +### Changed + +- [Internal] Relocated HMR processing code to the +[HackMyCore](https://github.com/hacksalot/HackMyCore) project. Shouldn't affect +normal use. + +## v1.6.0 + +### Major Improvements + +- Better consistency and coverage for all FRESH resumes and themes ([#45][i45]). + +- Initial support for overridable fonts in FRESH themes. Like a particular +theme, but want to change the typography? The specific fonts used by a theme +can now be overridden by the user. (FRESH themes only). + +- New resume sections! Support for `projects` and `affiliation` resume sections +for technical and creative projects and memberships / clubs / associations, +respectively ([#92][i92]). + +- New command! `PEEK` at any arbitrary field or entry on your `.json` resume. + +### Added + +- Improved handling of start and end dates on `employment`, `projects`, +`education`, and other sections with start/end dates. + +- Support for an `.ignore` property on any FRESH or JSON Resume section or field. +Ignored properties will be treated by HackMyResume as if they weren't present. + +- Emit extended status and error info with the `--debug` or `-d` switch. + +- The `-o` or `--options` switch can now handle either the path to a **JSON +settings file** or **raw JSON/JavaScript**. Since the JSON double quote syntax +is a bit cumbersome from the command line, HackMyResume accepts regular +JavaScript object literal syntax: + + hackmyresume build resume.json -o "{ theme: 'compact', silent: 'true' }" + +- Ability to disable sorting of resume sections (employments, projects, etc.) +with the `--no-sort` option. HMR will respect the order of items as they appear +in your resume `.json` file. + +- Improvements to the starter resume emitted by `hackmyresume new`. + +- Theme Authoring: Annotated the HTML and MS Word (XML) formats of the Modern +theme for FRESH theme authors. + +- Theme Authoring: Support for templatized CSS files in FRESH themes. CSS files +are now expanded via Handlebars or Underscore prior to copying to the +destination. + +- Added CHANGELOG.md (this file). + +### Changed + +- Rewrote the HackMyResume man/help page. + +- Minor incremental updates to the [FRESCA][fresca] schema. + +- PDF generation now uses asynchronous `spawn()` which has better compatibility +with old or boutique versions of Node.js. + +- Refactored colors in HackMyResume output. Errors will now display as red, +warnings as yellow, successful operations as green, and informational messages +as cyan. + +- Theme messages and usage tips will no longer display during resume generation +by default. Use the `--tips` option to view them. + +- The `--no-tips` option (default: false) has been replaced with the `--tips` +option, also defaulting to false. + +- Removed the `hello-world` theme from the [prebuilt themes][themes] that ship +with HackMyResume. It can be installed separately from NPM: + + ```bash + npm install fresh-theme-hello-world + hackmyresume resume.json -t node_modules/fresh-theme-hello-world + ``` + +- sd + +### Fixed + +- PDF generation issues on older versions of Node. + +- Stack traces not being emitted correctly. + +- Missing `speaking` section will now appear on generated resumes ([#101][i101]). + +- Incomplete `education` details will now appear on generated resumes ([#65][i65]). + +- Missing employment end date being interpreted as "employment ends today" +([#84][i84]). + +- Merging multiple source resumes during `BUILD` sometimes fails. + +- Document `--pdf` flag in README ([#111][i111]). + +### Internal + +- Logging messages have been moved out of core HackMyResume code ahead of +localization support. + +- All HackMyResume console output is described in `msg.yml`. + +- Relaxed pure JavaScript requirement. CoffeeScript will now start appearing +in HackMyResume and FluentCV sources! + +- Additional tests. + +## v1.5.2 + +### Fixed + +- Tweak stack trace under `--debug`. + +## v1.5.1 + +### Added + +- Preliminary support for `-d` or `--debug` flag. Forces HackMyResume to emit a stack trace under error conditions. + +## v1.5.0 + +### Added + +- HackMyResume now supports **CLI-based generation of PDF formats across multiple engines (Phantom, wkhtmltopdf, etc)**. Instead of talking to these engines over a programmatic API, as in prior versions, HackMyResume 1.5+ speaks to them over the same command-line interface (CLI) you'd use if you were using these tools directly. + +- HackMyResume will now (attempt to) **generate a PDF output for JSON Resume themes** (in addition to HTML). + +- Minor README and FAQ additions. + +### Changed + +- **Cleaner, quicker installs**. Installing HackMyResume with `npm install hackmyresume -g` will no longer trigger a lengthy, potentially error-prone install for Phantom.js and/or wkhtmltopdf for PDF support. Instead, users can install these engines externally and HMR will use them when present. + +- Minor error handling improvements. + +### Fixed + +- Fixed an error with generating specific formats with the `BUILD` command (#97). + +- Fixed numerous latent/undocumented bugs and glitches. + +## v1.4.2 + +### Added + +- Introduced [FAQ](https://github.com/hacksalot/HackMyResume/blob/master/FAQ.md). +- Additional README notes. + +## v1.4.1 + +### Added + +- `hackmyresume new` now generates a [valid starter resume with sample data](https://github.com/fluentdesk/fresh-resume-starter). + +### Fixed + +- Fixed warning message when `hackmyresume new` is run without a filename. + +## v1.4.0 + +### Added + +- **"Projects" support**: FRESH resumes and themes can now store and display +open source, commercial, private, personal, and creative projects. +- **New command: ANALYZE**. Inspect your resume for gaps, keyword counts, and other metrics. (Experimental.) +- **Side-by-side PDF generation** with Phantom and wkhtmltopdf. Use the `--pdf` or `-p` flag to pick between `phantom` and `wkhtmltopdf` generation. +- **Disable PDF generation** with the `--pdf none` switch. +- **Inherit formats between themes**. Themes can now inherit formats (Word, HTML, .txt, etc.) from other themes. (FRESH themes only.) +- **Rename resume sections** to different languages or wordings. +- **Specify complex options via external file**. Use with the `-o` or `--opts` option. +- **Disable colors** with the `--no-color` flag. +- **Theme messages and usage tips** instructions will now appear in the default HackMyResume output for the `build` command. Run `hackmyresume build resume.json -t awesome` for an example. Turn off with the `--no-tips` flag. +- **Treat validation errors as warnings** with the `--assert` switch (VALIDATE command only). + +### Fixed + +- Fixed a minor glitch in the FRESCA schema. +- Fixed encoding issues in the `Highlights` section of certain resumes. +- Fix behavior of `-s` and `--silent` flags. + +### Changed + +- PDF generation now defaults to Phantom for all platforms, with `wkhtmltopdf` +accessible with `--pdf wkhtmltopdf`. +- Resumes are now validated, by default, prior to generation. This +behavior can be disabled with the `--novalidate` or `--force` switch. +- Syntax errors in source FRESH and JSON Resumes are now captured for all +commands. +- Minor updates to README. +- Most themes now inherit Markdown and Plain Text formats from the **Basis** +theme. + +### Internal + +- Switched from color to chalk. +- Command invocations now handled through commander.js. +- Improved FRESH theme infrastructure (more partials, more DRY). + +## v1.3.1 + +### Added + +- Add additional Travis badges. + +### Fixed + +- Fix extraneous console log output when generating a FRESH theme to MS Word. +- Fix Travis tests on `dev`. + +## v1.3.0 + +### Added + +- **Local generation of JSON Resume themes**. To use a JSON Resume theme, first install it with `npm install jsonresume-theme-[blah]` (most JSON Resume themes are on NPM). Then pass it into HackMyResume via the `-t` parameter: + + `hackmyresume BUILD resume.json TO out/somefile.all -t node_modules/jsonresume-theme-classy` +- **Better Markdown support.** HackMyResume will start flowing basic Markdown styles to JSON Resume (HTML) themes. FRESH's existing Markdown support has also been improved. +- **.PNG output formats** will start appearing in themes that declare an HTML output. +- **Tweak CSS embedding / linking via the --css option** (`` vs ``). Only works for HTML (or HTML-driven) formats of FRESH themes. Use `--css=link` to link in CSS assets and `--css=embed` to embed the styles in the HTML document. For example `hackmyresume BUILD resume.json TO out/resume.all --css=link`. +- **Improved Handlebars/Underscore helper support** for FRESH themes. Handlebars themes can access helpers via `{{helperName}}`. Underscore themes can access helpers via the `h` object. + +### Changed + +- **Distinguish between validation errors and syntax errors** when validating a FRESH or JRS resume with `hackmyresume validate `. +- **Emit line and column info** for syntax errors during validation of FRESH and JRS resumes. +- **FRESH themes now embed CSS into HTML formats by default** so that the HTML resume output doesn't have an external CSS file dependency by default. Users can specify normal linked stylesheets by setting `--css=link`. +- **Renamed fluent-themes repo to fresh-themes** in keeping with the other parts of the project. + +### Fixed + +- Fix various encoding errors in MS Word outputs. +- Fix assorted FRESH-to-JRS and JRS-to-FRESH conversion glitches. +- Fix error when running HMR with no parameters. +- Other minor fixes. + +## v1.3.0-beta + +- Numerous changes supporting v1.3.0. + +## v1.2.2 + +### Fixed + +- Various in-passing fixes. + +## v1.2.1 + +### Fixed + +- Fix `require('FRESCA')` error. +- Fix `.history` and `.map` errors on loading incomplete or empty JRS resumes. + +### Added + +- Better test coverage of incomplete/empty resumes. + +## v1.2.0 + +### Fixed + +- Fixed the `new` command: Generate a new FRESH-format resume with `hackmyresume new resume.json` or a new JSON Resume with `hackmyresume new resume.json -f jrs`. + +### Added + +- Introduced CLI tests. + +## v1.1.0 + +### Fixed + +- MS Word formats: Fixed skill coloring/level bug. + +### Changed + +- Make the `TO` keyword optional. If no `TO` keyword is specified (for the `build` and `convert` commands), HMR will assume the last file passed in is the desired output file. So these are equivalent: + + ```shell + hackmyresume BUILD resume.json TO out/resume.all + hackmyresume BUILD resume.json out/resume.all + ``` + + `TO` only needs to be included if you have multipled output files: + + ```shell + hackmyresume BUILD resume.json TO out1.doc out2.html out3.tex + ``` + +## v1.0.1 + +### Fixed + +- Correctly generate MS Word hyperlinks from Markdown source data. + +## v1.0.0 + +- Initial public 1.0 release. + +[i45]: https://github.com/hacksalot/HackMyResume/issues/45 +[i65]: https://github.com/hacksalot/HackMyResume/issues/65 +[i84]: https://github.com/hacksalot/HackMyResume/issues/84 +[i92]: https://github.com/hacksalot/HackMyResume/issues/92 +[i101]: https://github.com/hacksalot/HackMyResume/issues/101 +[i111]: https://github.com/hacksalot/HackMyResume/issues/111 +[fresca]: https://github.com/fresh-standard/fresh-resume-schema +[themes]: https://github.com/fresh-standard/fresh-themes +[awefork]: https://github.com/fluentdesk/Awesome-CV +[acv]: https://github.com/posquit0/Awesome-CV +[ftt]: https://github.com/fresh-standard/fresh-test-themes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..d67446d6 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,53 @@ +Contributing +============ + +*Note: HackMyResume is also available as [FluentCV][fcv]. Contributors are +credited in both.* + +## How To Contribute + +*See [BUILDING.md][building] for instructions on setting up a HackMyResume +development environment.* + +1. Optional: [**open an issue**][iss] identifying the feature or bug you'd like +to implement or fix. This step isn't required — you can start hacking away on +HackMyResume without clearing it with us — but helps avoid duplication of work +and ensures that your changes will be accepted once submitted. +2. **Fork and clone** the HackMyResume project. +3. Ideally, **create a new feature branch** (eg, `feat/new-awesome-feature` or +similar; call it whatever you like) to perform your work in. +4. **Install dependencies** by running `npm install` in the top-level +HackMyResume folder. +5. Make your **commits** as usual. +6. **Verify** your changes locally with `grunt test`. +7. **Push** your commits. +7. **Submit a pull request** from your feature branch to the HackMyResume `dev` +branch. +8. We'll typically **respond** within 24 hours. +9. Your awesome changes will be **merged** after verification. + +## Project Maintainers + +HackMyResume is currently maintained by [hacksalot][ha] with assistance from +[tomheon][th] and our awesome [contributors][awesome]. Please direct all official +or internal inquiries to: + +``` +admin@fluentdesk.com +``` + +You can reach hacksalot directly at: + +``` +hacksalot@indevious.com +``` + +Thanks for your interest in the HackMyResume project. + +[fcv]: https://github.com/fluentdesk/fluentcv +[flow]: https://guides.github.com/introduction/flow/ +[iss]: https://github.com/hacksalot/HackMyResume/issues +[ha]: https://github.com/hacksalot +[th]: https://github.com/tomheon +[awesome]: https://github.com/hacksalot/HackMyResume/graphs/contributors +[building]: https://github.com/hacksalot/HackMyResume/blob/master/BUILDING.md diff --git a/FAQ.md b/FAQ.md new file mode 100644 index 00000000..60f5907f --- /dev/null +++ b/FAQ.md @@ -0,0 +1,228 @@ +Frequently Asked Questions (FAQ) +================================ + +## How do I get started with HackMyResume? + +1. Install with NPM: `[sudo] npm install hackmyresume -g`. + +2. Create a new resume with: `hackmyresume NEW .json`. + +3. Test with `hackmyresume BUILD .json`. Look in the `out/` folder. + +4. Play around with different themes with the `-t` or `--theme` parameter. +You can use any [FRESH](https://github.com/fluentdesk/fresh-themes) or +[JSON Resume](https://jsonresume.org/themes) theme. The latter have to be +installed first. + +## What is FRESH? + +FRESH is the **F**luent **R**esume and **E**mployment **S**ystem for **H**umans. +It's an open-source, user-first workflow, schema, and set of practices for +technical candidates and recruiters. + +## What is FRESCA? + +The **F**RESH **R**esume and **E**mployment **SC**hem**A**—an open-source, +JSON-driven schema for resumes, CVs, and other employment artifacts. FRESCA is +the recommended schema/format for FRESH, with optional support for JSON Resume. + +## What is JSON Resume? + +An [open resume standard](http://jsonresume.org/themes/) sponsored by Hired.com. +Like FRESCA, JSON Resume is JSON-driven and open-source. Unlike FRESCA, JSON +Resume targets a worldwide audience where FRESCA is optimized for technical +candidates. + +## Should I use the FRESH or JSON Resume format/schema for my resume? + +Both! The workflow we like to use: + +1. Create a resume in FRESH format for tooling and analysis. +2. Convert it to JSON Resume format for additional themes/tools. +3. Maintain both versions. + +Both formats are open-source and both formats are JSON-driven. FRESH was +designed as a universal container format and superset of existing formats, where +the JSON Resume format is intended for a generic audience. + +## How do I use a FRESH theme? + +Several FRESH themes come preinstalled with HackMyResume; others can be +installed from NPM and GitHub. + +### To use a preinstalled FRESH theme: + +1. Pass the theme name into HackMyResume via the `--theme` or `-t` parameter: + + ```bash + hackmyresume build resume.json --theme compact + ``` + +### To use an external FRESH theme: + +1. Install the theme locally. The easiest way to do that is with NPM. + + ```bash + npm install fresh-theme-underscore + ``` + +2. Pass the theme folder into HackMyResume: + + ```bash + hackmyresume BUILD resume.json --theme node_modules/fresh-theme-underscore + ``` + +3. Check your output folder. It's best to view HTML formats over a local web +server connection. + +## How do I use a JSON Resume theme? + +JSON Resume (JRS) themes can be installed from NPM and GitHub and passed into +HackMyResume via the `--theme` or `-t` parameter. + +1. Install the theme locally. The easiest way to do that is with NPM. + + ```bash + npm install jsonresume-theme-classy + ``` + +2. Pass the theme folder path into HackMyResume: + + ```bash + hackmyresume BUILD resume.json --theme node_modules/jsonresume-theme-classy + ``` + +3. Check your output folder. It's best to view HTML formats over a local web +server connection. + +## Should I keep my resume in version control? + +Absolutely! As text-based, JSON-driven documents, both FRESH and JSON Resume are +ideal candidates for version control. Future versions of HackMyResume will have +this functionality built in. + +## Can I change the default section titles ("Employment", "Skills", etc.)? + +If you're using a FRESH theme, yes. First, create a HackMyResume options file +mapping resume sections to your preferred section title: + +```javascript +// myoptions.json +{ + "sectionTitles": { + "employment": "empleo", + "skills": "habilidades", + "education": "educación" + } +} +``` + +Then, pass the options file into the `-o` or `--opts` parameter: + +```bash +hackmyresume BUILD resume.json -o myoptions.json +``` + +This ability is currently only supported for FRESH resume themes. + +## How does resume merging work? + +Resume merging is a way of storing your resume in separate files that +HackMyResume will merge into a single "master" resume file prior to generating +specific output formats like HTML or PDF. It's a way of producing flexible, +configurable, targeted resumes with minimal duplication. + +For example, a software developer who moonlights as a game programmer might +create three FRESH or JRS resumes at different levels of specificity: + +- **generic.json**: A generic technical resume, suitable for all audiences. +- **game-developer.json**: Overrides and amendments for game developer +positions. +- **blizzard.json**: Overrides and amendments specific to a hypothetical +position at Blizzard. + +If you run `hackmyresume BUILD generic.json TO out/resume.all`, HMR will +generate all available output formats for the `generic.json` as usual. But if +you instead run... + +```bash +hackmyresume BUILD generic.json game-developer.json TO out/resume.all +``` + +...HackMyResume will notice that multiple source resumes were specified and +merge `game-developer.json` onto `generic.json` before generating, yielding a +resume that's more suitable for game-developer-related positions. + +You can take this a step further. Let's say you want to do a targeted resume +submission to a game developer position at Blizzard, and `blizzard.json` +contains the edits and revisions you'd like to show up in the targeted resume. +In that case, merge again! Feed all three resumes to HackMyResume, in order +from most generic to most specific, and HMR will merge them all prior to +generating the final output format(s) for your resume. + +```bash +# Merge blizzard.json onto game-developer.json onto generic.json, then build +hackmyresume BUILD generic.json game-developer.json blizzard.json TO out/resume.all +``` + +There's no limit to the number of resumes you can merge this way. + +You can also divide your resume into files containing different sections: + +- **resume-a.json**: Contains `info`, `employment`, and `summary` sections. +- **resume-b.json**: Contains all other sections except `references`. +- **references.json**: Contains the private `references` section. + +Under that scenario, `hackmyresume BUILD resume-a.json resume-b.json` would + + +## The HackMyResume terminal color scheme is giving me a headache. Can I disable it? + +Yes. Use the `--no-color` option to disable terminal colors: + +`hackmyresume --no-color` + +## What's the difference between a FRESH theme and a JSON Resume theme? + +FRESH themes are multiformat (HTML, Word, PDF, etc.) and required to support +Markdown formatting, configurable section titles, and various other features. + +JSON Resume themes are typically HTML-driven, but capable of expansion to other +formats through tools. JSON Resume themes don't support Markdown natively, but +HMR does its best to apply your Markdown, when present, to any JSON Resume +themes it encounters. + +## Do I have to have a FRESH resume to use a FRESH theme or a JSON Resume to use a JSON Resume theme? + +No. You can mix and match FRESH and JRS-format themes freely. HackMyResume will +perform the necessary conversions on the fly. + +## Can I build my own custom FRESH theme? + +Yes. The easiest way is to copy an existing FRESH theme, like `modern` or +`compact`, and make your changes there. You can test your theme with: + +```bash +hackmyresume build resume.json --theme path/to/my/theme/folder +``` + +## Can I build my own custom JSON Resume theme? + +Yes. The easiest way is to copy an existing JSON Rsume theme and make your +changes there. You can test your theme with: + +```bash +hackmyresume build resume.json --theme path/to/my/theme/folder +``` + +## Can I build my own tools / services / apps / websites around FRESH / FRESCA? + +Yes! FRESH/FRESCA formats are 100% open source, permissively licensed under MIT, +and 100% free from company-specific, tool-specific, or commercially oriented +lock-in or cruft. These are clean formats designed for users and builders. + +## Can I build my own tools / services / apps / websites around JSON Resume? + +Yes! HackMyResume is not affiliated with JSON Resume, but like FRESH/FRESCA, +JSON Resume is open-source, permissively licensed, and free of proprietary +lock-in. See the JSON Resume website for details. diff --git a/Gruntfile.js b/Gruntfile.js index 45cd6ca9..6152c4a3 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -14,46 +14,39 @@ module.exports = function (grunt) { ui: 'bdd', reporter: 'spec' }, - all: { src: ['tests/*.js'] } + all: { src: ['test/*.js'] } }, - clean: ['tests/sandbox'], - - yuidoc: { - compile: { - name: '<%= pkg.name %>', - description: '<%= pkg.description %>', - version: '<%= pkg.version %>', - url: '<%= pkg.homepage %>', - options: { - paths: 'src/', - //themedir: 'path/to/custom/theme/', - outdir: 'docs/' - } - } + clean: { + test: ['test/sandbox'] }, - jshint: { - options: { - laxcomma: true, - expr: true - }, - all: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'] + eslint: { + target: ['Gruntfile.js', 'src/**/*.js', 'test/*.js'] } }; grunt.initConfig( opts ); - grunt.loadNpmTasks('grunt-simple-mocha'); - grunt.loadNpmTasks('grunt-contrib-yuidoc'); - grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-eslint'); grunt.loadNpmTasks('grunt-contrib-clean'); - grunt.registerTask('test', 'Test the HackMyResume library.', - function( config ) { grunt.task.run( ['clean','simplemocha:all'] ); }); - grunt.registerTask('document', 'Generate HackMyResume library documentation.', - function( config ) { grunt.task.run( ['yuidoc'] ); }); - grunt.registerTask('default', [ 'jshint', 'test', 'yuidoc' ]); + // Use 'grunt test' for local testing + grunt.registerTask('test', 'Test the HackMyResume application.', + function() { + grunt.task.run(['clean:test','build','eslint','simplemocha:all']); + } + ); + + // Use 'grunt build' to build HMR + grunt.registerTask('build', 'Build the HackMyResume application.', + function() { + grunt.task.run( ['eslint'] ); + } + ); + + // Default task does everything + grunt.registerTask('default', [ 'test' ]); }; diff --git a/LICENSE.md b/LICENSE.md index b85e75ac..be0bcba2 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,7 @@ The MIT License =============== -Copyright (c) 2015 James M. Devlin (https://github.com/hacksalot) +Copyright (c) 2015-2018 hacksalot (https://github.com/hacksalot) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a7d2e725..bfef05dd 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,17 @@ HackMyResume -============ +=== + +[![Latest release][img-release]][latest-release] +[![Build status (MASTER)][img-master]][travis-url-master] +[![Build status (DEV)][img-dev]][travis-url-dev] +[![Join the chat at https://gitter.im/hacksalot/HackMyResume][badge]][gh] + *Create polished résumés and CVs in multiple formats from your command line or shell. Author in clean Markdown and JSON, export to Word, HTML, PDF, LaTeX, plain text, and other arbitrary formats. Fight the power, save trees. Compatible with [FRESH][fresca] and [JRS][6] resumes.* -![](assets/resume-bouqet.png) +![](assets/hmr_build.png) HackMyResume is a dev-friendly, local-only Swiss Army knife for resumes and CVs. Use it to: @@ -13,80 +19,149 @@ Use it to: 1. **Generate** HTML, Markdown, LaTeX, MS Word, PDF, plain text, JSON, XML, YAML, print, smoke signal, carrier pigeon, and other arbitrary-format resumes and CVs, from a single source of truth—without violating DRY. -2. **Convert** resumes between [FRESH][fresca] and [JSON Resume][6] formats. -3. **Validate** resumes against either format. +2. **Analyze** your resume for keyword density, gaps/overlaps, and other +metrics. +3. **Convert** resumes between [FRESH][fresca] and [JSON Resume][6] formats. +4. **Validate** resumes against either format. HackMyResume is built with Node.js and runs on recent versions of OS X, Linux, -or Windows. +or Windows. View the [FAQ](FAQ.md). + +![](assets/hmr_analyze.png) ## Features - OS X, Linux, and Windows. +- Choose from dozens of FRESH or JSON Resume themes. +- Private, local-only resume authoring and analysis. +- Analyze your resume for keywords, gaps, and other metrics. - Store your resume data as a durable, versionable JSON or YAML document. - Generate polished resumes in multiple formats without violating [DRY][dry]. - Output to HTML, Markdown, LaTeX, PDF, MS Word, JSON, YAML, plain text, or XML. - Validate resumes against the FRESH or JSON Resume schema. - Support for multiple input and output resumes. +- Convert between FRESH and JSON Resume resumes. - Use from your command line or [desktop][7]. - Free and open-source through the MIT license. +- Updated daily / weekly. Contributions are [welcome](CONTRIBUTING.md). ## Install -Install HackMyResume with NPM: +Install the latest stable version of HackMyResume with NPM: ```bash [sudo] npm install hackmyresume -g ``` -Note: for PDF generation you'll need to install a copy of [wkhtmltopdf][3] for -your platform. For LaTeX generation you'll need a valid LaTeX environment with -access to `xelatex` and similar. +Alternately, install the latest bleeding-edge version (updated daily): + +```bash +[sudo] npm install hacksalot/hackmyresume#dev -g +``` + +## Installing PDF Support (optional) + +HackMyResume tries not to impose a specific PDF engine requirement on +the user, but will instead work with whatever PDF engines you have installed. + +Currently, HackMyResume's PDF generation requires one of [Phantom.js][2], +[wkhtmltopdf][3], or [WeasyPrint][11] to be installed on your system and the +corresponding binary to be accessible on your PATH. This is an optional +requirement for users who care about PDF formats. If you don't care about PDF +formats, skip this step. + +## Installing Themes + +HackMyResume supports both [FRESH][fresh-themes] and [JSON Resume][jrst]-style +résumé themes. + +- FRESH themes currently come preinstalled with HackMyResume. +- JSON Resume themes can be installed from NPM, GitHub, or manually. + +To install a JSON Resume theme, just `cd` to the folder where you want to store +your themes and run one of: + +```bash +# Install with NPM +npm install jsonresume-theme-[theme-name] + +# Install with GitHub +git clone https://github.com/[user-or-org]/[repo-name] +``` + +Then when you're ready to generate your resume, just reference the location of +the theme folder as you installed it: + +```bash +hackmyresume build resume.json TO out/resume.all -t node_modules/jsonresume-theme-classy +``` + +Note: You can use install themes anywhere on your file system. You don't need a +package.json or other NPM/Node infrastructure. ## Getting Started To use HackMyResume you'll need to create a valid resume in either [FRESH][fresca] or [JSON Resume][6] format. Then you can start using the command -line tool. There are four basic commands you should be aware of: +line tool. There are five basic commands you should be aware of: - **build** generates resumes in HTML, Word, Markdown, PDF, and other formats. Use it when you need to submit, upload, print, or email resumes in specific formats. ```bash - # hackmyresume BUILD TO [-t THEME] - hackmyresume BUILD resume.json TO out/resume.all - hackmyresume BUILD r1.json r2.json TO out/rez.html out/rez.md foo/rez.all + # hackmyresume build TO [-t THEME] + hackmyresume build resume.json TO out/resume.all + hackmyresume build r1.json r2.json TO out/rez.html out/rez.md foo/rez.all ``` - **new** creates a new resume in FRESH or JSON Resume format. ```bash - # hackmyresume NEW [-f ] - hackmyresume NEW resume.json - hackmyresume NEW resume.json -f fresh - hackmyresume NEW r1.json r2.json -f jrs + # hackmyresume new [-f ] + hackmyresume new resume.json + hackmyresume new resume.json -f fresh + hackmyresume new r1.json r2.json -f jrs + ``` + +- **analyze** inspects your resume for keywords, duration, and other metrics. + + ```bash + # hackmyresume analyze + hackmyresume analyze resume.json + hackmyresume analyze r1.json r2.json ``` - **convert** converts your source resume between FRESH and JSON Resume -formats. -Use it to convert between the two formats to take advantage of tools and -services. +formats. Use it to convert between the two formats to take advantage of tools +and services. ```bash - # hackmyresume CONVERT TO - hackmyresume CONVERT resume.json TO resume-jrs.json - hackmyresume CONVERT 1.json 2.json 3.json TO out/1.json out/2.json out/3.json + # hackmyresume convert TO + hackmyresume convert resume.json TO resume-jrs.json + hackmyresume convert 1.json 2.json 3.json TO out/1.json out/2.json out/3.json ``` - **validate** validates the specified resume against either the FRESH or JSON Resume schema. Use it to make sure your resume data is sufficient and complete. ```bash - # hackmyresume VALIDATE - hackmyresume VALIDATE resume.json - hackmyresume VALIDATE r1.json r2.json r3.json + # hackmyresume validate + hackmyresume validate resume.json + hackmyresume validate r1.json r2.json r3.json ``` +- **peek** echoes your resume or any field, property, or object path on your +resume to standard output. + + ```bash + # hackmyresume peek [OBJECT-PATH] + hackmyresume peek rez.json # Echo the whole resume + hackmyresume peek rez.json info.brief # Echo the "info.brief" field + hackmyresume peek rez.json employment.history[1] # Echo the 1st job + hackmyresume peek rez.json rez2.json info.brief # Compare value + ``` + ## Supported Output Formats HackMyResume supports these output formats: @@ -95,9 +170,9 @@ Output Format | Ext | Notes ------------- | --- | ----- HTML | .html | A standard HTML 5 + CSS resume format that can be viewed in a browser, deployed to a website, etc. Markdown | .md | A structured Markdown document that can be used as-is or used to generate HTML. -LaTeX | .tex | A structured LaTeX document (or collection of documents). -MS Word | .doc | A Microsoft Word office document. -Adobe Acrobat (PDF) | .pdf | A binary PDF document driven by an HTML theme. +LaTeX | .tex | A structured LaTeX document (or collection of documents) that can be processed with pdflatex, xelatex, and similar tools. +MS Word | .doc | A Microsoft Word office document (XML-driven; WordProcessingML). +Adobe Acrobat (PDF) | .pdf | A binary PDF document driven by an HTML theme (through wkhtmltopdf). plain text | .txt | A formatted plain text document appropriate for emails or copy-paste. JSON | .json | A JSON representation of the resume. YAML | .yml | A YAML representation of the resume. @@ -105,22 +180,13 @@ RTF | .rtf | Forthcoming. Textile | .textile | Forthcoming. image | .png, .bmp | Forthcoming. -## Install - -HackMyResume requires a recent version of [Node.js][4] and [NPM][5]. Then: - -1. Install the latest official [wkhtmltopdf][3] binary for your platform. -2. Optionally install an updated LaTeX environment (LaTeX resumes only). -2. Install **HackMyResume** with `[sudo] npm install hackmyresume -g`. -3. You're ready to go. - ## Use Assuming you've got a JSON-formatted resume handy, generating resumes in -different formats and combinations easy. Just run: +different formats and combinations is easy. Just run: ```bash -hackmyresume BUILD [-t theme]. +hackmyresume build to [-t theme]. ``` Where `` is one or more .json resume files, separated by spaces; @@ -129,7 +195,7 @@ theme (default to Modern). For example: ```bash # Generate all resume formats (HTML, PDF, DOC, TXT, YML, etc.) -hackmyresume build resume.json -o out/resume.all -t modern +hackmyresume build resume.json TO out/resume.all -t modern # Generate a specific resume format hackmyresume build resume.json TO out/resume.html @@ -147,7 +213,7 @@ hackmyresume build in1.json in2.json TO out.html out.doc out.pdf You should see something to the effect of: ``` -*** HackMyResume v0.9.0 *** +*** HackMyResume v1.4.0 *** Reading JSON resume: foo/resume.json Applying MODERN Theme (7 formats) Generating HTML resume: out/resume.html @@ -163,17 +229,36 @@ Generating YAML resume: out/resume.yml ### Applying a theme -You can specify a predefined or custom theme via the optional `-t` parameter. -For a predefined theme, include the theme name. For a custom theme, include the -path to the custom theme's folder. +HackMyResume can work with any FRESH or JSON Resume theme (the latter must be +installed first). To specify a theme when generating your resume, use the `-t` +or `--theme` parameter: + +```bash +hackmyresume build resume.json TO out/rez.all -t [theme] +``` + +The `[theme]` parameter can be the name of a predefined theme OR the path to any +FRESH or JSON Resume theme folder: + +```bash +hackmyresume build resume.json TO out/rez.all -t modern +hackmyresume build resume.json TO OUT.rez.all -t ../some-folder/my-custom-theme/ +hackmyresume build resume.json TO OUT.rez.all -t node_modules/jsonresume-theme-classy +``` + +FRESH themes are currently pre-installed with HackMyResume. JSON Resume themes +can be installed prior to use: ```bash -hackmyresume build resume.json -t modern -hackmyresume build resume.json -t ~/foo/bar/my-custom-theme/ +# Install a JSON Resume theme into a local node_modules subfolder: +npm install jsonresume-theme-[name] +# Use it with HackMyResume +hackmyresume build resume.json -t node_modules/jsonresume-theme-[name] ``` -As of v1.0.0, available predefined themes are `positive`, `modern`, `compact`, -`minimist`, and `hello-world`. +As of v1.6.0, available predefined FRESH themes are `positive`, `modern`, +`compact`, `minimist`, and `hello-world`. For a list of JSON Resume themes, +check the [NPM Registry](https://www.npmjs.com/search?q=jsonresume-theme). ### Merging resumes @@ -182,7 +267,7 @@ most generic to most specific: ```bash # Merge specific.json onto base.json and generate all formats -hackmyresume build base.json specific.json -o resume.all +hackmyresume build base.json specific.json TO resume.all ``` This can be useful for overriding a base (generic) resume with information from @@ -209,14 +294,7 @@ You can specify **multiple output targets** and HackMyResume will build them: ```bash # Generate out1.doc, out1.pdf, and foo.txt from me.json. -hackmyresume build me.json -o out1.doc -o out1.pdf -o foo.txt -``` - -You can also omit the output file(s) and/or theme completely: - -```bash -# Equivalent to "hackmyresume resume.json resume.all -t modern" -hackmyresume build resume.json +hackmyresume build me.json TO out1.doc out1.pdf foo.txt ``` ### Using .all @@ -226,13 +304,144 @@ formats for the given resume. For example, this... ```bash # Generate all resume formats (HTML, PDF, DOC, TXT, etc.) -hackmyresume build me.json -o out/resume.all +hackmyresume build me.json TO out/resume.all ``` ..tells HackMyResume to read `me.json` and generate `out/resume.md`, `out/resume.doc`, `out/resume.html`, `out/resume.txt`, `out/resume.pdf`, and `out/resume.json`. +### Building PDFs + +*Users who don't care about PDFs can turn off PDF generation across all themes +and formats with the `--pdf none` switch.* + +HackMyResume takes a unique approach to PDF generation. Instead of enforcing +a specific PDF engine on users, HackMyResume will attempt to work with whatever +PDF engine you have installed through the engine's command-line interface (CLI). +Currently that means any of... + +- [wkhtmltopdf][3] +- [Phantom.js][2] +- [WeasyPrint][11] + +..with support for other engines planned in the future. But for now, **one or +more of these engines must be installed and accessible on your PATH in order +to generate PDF resumes with HackMyResume**. That means you should be able to +invoke either of these tools directly from your shell or terminal without error: + +```bash +wkhtmltopdf input.html output.pdf +phantomjs script.js input.html output.pdf +weasyprint input.html output.pdf +``` + +Assuming you've installed one or both of these engines on your system, you can +tell HackMyResume which flavor of PDF generation to use via the `--pdf` option +(`-p` for short): + +```bash +hackmyresume build resume.json TO out.all --pdf phantom +hackmyresume build resume.json TO out.all --pdf wkhtmltopdf +hackmyresume build resume.json TO out.all --pdf weasyprint +hackmyresume build resume.json TO out.all --pdf none +``` + +### Analyzing + +HackMyResume can analyze your resume for keywords, employment gaps, and other +metrics. Run: + +```bash +hackmyresume analyze .json +``` + +Depending on the HackMyResume version, you should see output similar to: + + +``` +*** HackMyResume v1.6.0 *** +Reading resume: resume.json +Analyzing FRESH resume: resume.json + +SECTIONS (10): + + employment: 12 + education: 2 + service: 1 + skills: 8 + writing: 1 + recognition: 0 + social: 4 + interests: 2 + references: 1 + languages: 2 + +COVERAGE (61.1%): + + Total Days: 6034 + Employed: 3688 + Gaps: 8 [31, 1065, 273, 153, 671, 61, 61, 31] + Overlaps: 1 [243] + +KEYWORDS (61): + + Node.js: 6 mentions + JavaScript: 9 mentions + SQL Server: 3 mentions + Visual Studio: 6 mentions + Web API: 1 mentions + N-tier / 3-tier: 1 mentions + HTML 5: 1 mentions + JavaScript: 6 mentions + CSS: 2 mentions +Sass / LESS / SCSS: 1 mentions + LAMP: 3 mentions + WISC: 1 mentions + HTTP: 21 mentions + JSON: 1 mentions + XML: 2 mentions + REST: 1 mentions + WebSockets: 2 mentions + Backbone.js: 3 mentions + Angular.js: 1 mentions + Node.js: 4 mentions + NPM: 1 mentions + Bower: 1 mentions + Grunt: 2 mentions + Gulp: 1 mentions + jQuery: 2 mentions + Bootstrap: 3 mentions + Underscore.js: 1 mentions + PhantomJS: 1 mentions + CoffeeScript: 1 mentions + Python: 11 mentions + Perl: 4 mentions + PHP: 7 mentions + MySQL: 12 mentions + PostgreSQL: 4 mentions + NoSQL: 2 mentions + Apache: 2 mentions + AWS: 2 mentions + EC2: 2 mentions + RDS: 3 mentions + S3: 1 mentions + Azure: 1 mentions + Rackspace: 1 mentions + C++: 23 mentions + C++ 11: 1 mentions + Boost: 1 mentions + Xcode: 2 mentions + gcc: 1 mentions + OO&AD: 1 mentions + .NET: 20 mentions + Unity 5: 2 mentions + Mono: 3 mentions + MonoDevelop: 1 mentions + Xamarin: 1 mentions + TOTAL: 180 mentions +``` + ### Validating HackMyResume can also validate your resumes against either the [FRESH / @@ -247,7 +456,7 @@ hackmyresume validate resumeA.json resumeB.json HackMyResume will validate each specified resume in turn: ```bash -*** HackMyResume v0.9.0 *** +*** HackMyResume v1.6.0 *** Validating JSON resume: resumeA.json (INVALID) Validating JSON resume: resumeB.json (VALID) ``` @@ -258,7 +467,7 @@ HackMyResume can convert between the [FRESH][fresca] and [JSON Resume][6] formats. Just run: ```bash -hackmyresume CONVERT +hackmyresume convert ``` where is one or more resumes in FRESH or JSON Resume format, and @@ -266,14 +475,52 @@ where is one or more resumes in FRESH or JSON Resume format, and autodetect the format (FRESH or JRS) of each input resume and convert it to the other format (JRS or FRESH). +### File-based Options + +You can pass options into HackMyResume via an external options or ".hackmyrc" +file with the `--options` or `-o` switch: + +```bash +hackmyresume build resume.json -o path/to/options.json +``` + +The options file can contain any documented HackMyResume option, including +`theme`, `silent`, `debug`, `pdf`, `css`, and other settings. + +```json +{ + "theme": "compact", + + "sectionTitles": { + "employment": "Work" + }, + + "wkhtmltopdf": { + "margin-top": "20mm" + } +} +``` + +If an option is specified on both the command line and in an external options +file, the command-line option wins. + +```bash +# path/to/options.json specifes the POSITIVE theme +# -t parameter specifies the COMPACT theme +# The -t parameter wins. +hackmyresume build resume.json -o path/to/options.json -t compact +> Reading resume: resume.json +> Applying COMPACT theme (7 formats) +``` + ### Prettifying HackMyResume applies [js-beautify][10]-style HTML prettification by default to -HTML-formatted resumes. To disable prettification, the `--nopretty` or `-n` flag -can be used: +HTML-formatted resumes. To disable prettification, the `--no-prettify` or `-n` +flag can be used: ```bash -hackmyresume generate resume.json out.all --nopretty +hackmyresume build resume.json out.all --no-prettify ``` ### Silent Mode @@ -281,10 +528,91 @@ hackmyresume generate resume.json out.all --nopretty Use `-s` or `--silent` to run in silent mode: ```bash -hackmyresume generate resume.json -o someFile.all -s -hackmyresume generate resume.json -o someFile.all --silent +hackmyresume build resume.json -o someFile.all -s +hackmyresume build resume.json -o someFile.all --silent ``` +### Debug Mode + +Use `-d` or `--debug` to force HMR to emit a call stack when errors occur. In +the future, this option will emit detailed error logging. + +```bash +hackmyresume build resume.json -d +hackmyresume analyze resume.json --debug +``` + +### Disable Encoding + +Use the `--no-escape` option to disable encoding in Handlebars themes. Note: +this option has no effect for non-Handlebars themes. + +```bash +hackmyresume build resume.json --no-escape +``` + +### Private Resume Fields + +Have a gig, education stint, membership, or other relevant history that you'd +like to hide from *most* (e.g. public) resumes but sometimes show on others? Tag it with +`"private": true` to omit it from outbound generated resumes by default. + + +```json +"employment": { + "history": [ + { + "employer": "Acme Real Estate" + }, + { + "employer": "Area 51 Alien Research Laboratory", + "private": true + }, + { + "employer": "H&R Block" + } + ] +} +``` + +Then, when you want a copy of your resume that includes the private gig / stint +/ etc., tell HackMyResume that it's OK to emit private fields. The way you do +that is with the `--private` switch. + +```bash +hackmyresume build resume.json private-resume.all --private +``` + + +### Custom theme helpers + +You can attach your own custom Handlebars helpers to a FRESH theme with the +`helpers` key of your theme's `theme.json` file. + +```js +{ + "title": "my-cool-theme", + + // ... + + "helpers": [ + "../path/to/helpers/*.js", + "some-other-helper.js" + ] +} +``` + +HackMyResume will attempt to load each path or glob and register any specified +files with [Handlebars.registerHelper][hrh], making them available to your +theme. + + +## Contributing + +HackMyResume is a community-driven free and open source project under the MIT +License. Contributions are encouraged and we respond to all PRs and issues in +time. See [CONTRIBUTING.md][contribute] for details. + ## License MIT. Go crazy. See [LICENSE.md][1] for details. @@ -299,6 +627,19 @@ MIT. Go crazy. See [LICENSE.md][1] for details. [8]: https://youtu.be/N9wsjroVlu8 [9]: https://api.jquery.com/jquery.extend/ [10]: https://github.com/beautify-web/js-beautify +[11]: http://weasyprint.org/ [fresh]: https://github.com/fluentdesk/FRESH -[fresca]: https://github.com/fluentdesk/FRESCA +[fresca]: https://github.com/fresh-standard/fresh-resume-schema [dry]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself +[img-release]: https://img.shields.io/github/release/hacksalot/HackMyResume.svg?label=version +[img-master]: https://img.shields.io/travis/hacksalot/HackMyResume/master.svg +[img-dev]: https://img.shields.io/travis/hacksalot/HackMyResume/dev.svg?label=dev +[travis-url-master]: https://travis-ci.org/hacksalot/HackMyResume?branch=master +[travis-url-dev]: https://travis-ci.org/hacksalot/HackMyResume?branch=dev +[latest-release]: https://github.com/hacksalot/HackMyResume/releases/latest +[contribute]: CONTRIBUTING.md +[fresh-themes]: https://github.com/fluentdesk/fresh-themes +[jrst]: https://www.npmjs.com/search?q=jsonresume-theme +[gh]: https://gitter.im/hacksalot/HackMyResume?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge +[badge]: https://badges.gitter.im/hacksalot/HackMyResume.svg +[hrh]: http://handlebarsjs.com/reference.html#base-registerHelper diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 00000000..c8424c85 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,107 @@ +Development Roadmap +=================== + +## Short-Term + +### FluentCV Desktop: Beta 1 + +The **FluentCV Desktop 1.0 beta release** will present HackMyResume +functionality in a cross-platform desktop application for OS X, Linux, and +Windows. + +### GitHub Integration + +HackMyResume will offer GitHub integration for versioned resume storage and +retrieval via the `COMMIT` or `STORE` command(s) starting in 1.7.0 or 1.8.0. + +### fresh-themes 1.0.0 + +The **fresh-themes 1.0** release will bring 100% coverage of the FRESH and JRS +object models—all resume sections and fields—along with +documentation, theme developer's guide, new themes, and a freeze to the FRESH +theme structure. + +### Better LaTeX support + +Including Markdown-to-LaTeX translation and more LaTeX-driven themes / formats. + +### StackOverflow and LinkedIn support + +Will start appearing in v1.7.0, with incremental improvements in 1.8.0 and +beyond. + +### Improved resume sorting and arranging + +**Better resume sorting** of items and sections: ascending, descending, by +date or other criteria ([#67][i67]). + +### Remote resume / theme loading + +Support remote loading of themes and resumes over `http`, `https`, and +`git://`. Enable these usage patterns: + + ```bash + hackmyresume build https://somesite.com/my-resume.json -t informatic + + hackmyresume build resume.json -t npm:fresh-theme-ergonomic + + hackmyresume analyze https://github.com/foo/my-resume + ``` + +### 100% code coverage + +Should reduce certain classes of errors and allow HMR to display a nifty 100% +code coverage badge. + +### Improved **documentation and samples** + +Expanded documentation and samples throughout. + +## Mid-Term + +### Cover letters and job descriptions + +Add support for schema-driven **cover letters** and **job descriptions**. + +### Character Sheets + +HackMyResume 2.0 will ship with support for, yes, RPG-style character sheets. +This will demonstrate the tool's ability to flow arbitrary JSON to concrete +document(s) and provide unique albeit niche functionality around various games +([#117][i117]). + +### Rich text (.rtf) output formats + +Basic support for **rich text** `.rtf` output formats. + +### Investigate: groff support + +Investigate adding [**groff**][groff] support, because that would, indeed, be +[dope][d] ([#37][i37]). + +### Investigate: org-mode support + +Investigate adding [**org mode**][om] support ([#38][i38]). + +### Investigate: Scribus + +Investigate adding [**Scribus SLA**][scri] support ([#54][i54]). + +### Support JSON Resume 1.0.0 + +When released. + +## Long-Term + +- TBD + +[groff]: http://www.gnu.org/software/groff/ +[om]: http://orgmode.org/ +[scri]: https://en.wikipedia.org/wiki/Scribus +[d]: https://github.com/hacksalot/HackMyResume/issues/37#issue-123818674 +[i37]: https://github.com/hacksalot/HackMyResume/issues/37 +[i38]: https://github.com/hacksalot/HackMyResume/issues/38 +[i54]: https://github.com/hacksalot/HackMyResume/issues/54 +[i67]: https://github.com/hacksalot/HackMyResume/issues/67 +[i107]: https://github.com/hacksalot/HackMyResume/issues/107 +[i117]: https://github.com/hacksalot/HackMyResume/issues/117 diff --git a/assets/hackmyresume_cli.png b/assets/hackmyresume_cli.png deleted file mode 100644 index 2110109d..00000000 Binary files a/assets/hackmyresume_cli.png and /dev/null differ diff --git a/assets/hmr_analyze.png b/assets/hmr_analyze.png new file mode 100644 index 00000000..e0243a7e Binary files /dev/null and b/assets/hmr_analyze.png differ diff --git a/assets/hmr_build.png b/assets/hmr_build.png new file mode 100644 index 00000000..47a5a96a Binary files /dev/null and b/assets/hmr_build.png differ diff --git a/assets/logo/hackmyresume-logo.ai b/assets/logo/hackmyresume-logo.ai new file mode 100644 index 00000000..a775f896 --- /dev/null +++ b/assets/logo/hackmyresume-logo.ai @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a476ee59e7d86b5a7599780b5efca57ee6b6d60e1a722343277057ea793703b6 +size 1642116 diff --git a/assets/logo/hackmyresume-logo.png b/assets/logo/hackmyresume-logo.png new file mode 100644 index 00000000..84214a32 Binary files /dev/null and b/assets/logo/hackmyresume-logo.png differ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json new file mode 100644 index 00000000..fa739589 --- /dev/null +++ b/npm-shrinkwrap.json @@ -0,0 +1,2800 @@ +{ + "name": "hackmyresume", + "version": "1.9.0-beta", + "dependencies": { + "abbrev": { + "version": "1.1.1", + "from": "abbrev@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "dev": true + }, + "acorn": { + "version": "5.4.1", + "from": "acorn@>=5.4.0 <6.0.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "from": "acorn-jsx@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "dev": true, + "dependencies": { + "acorn": { + "version": "3.3.0", + "from": "acorn@>=3.0.4 <4.0.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "from": "ajv@>=5.3.0 <6.0.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "dev": true + }, + "ajv-keywords": { + "version": "2.1.1", + "from": "ajv-keywords@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "from": "align-text@>=0.1.3 <0.2.0", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "dependencies": { + "kind-of": { + "version": "3.2.2", + "from": "kind-of@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + } + } + }, + "amdefine": { + "version": "1.0.1", + "from": "amdefine@>=0.0.4", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" + }, + "ansi-escapes": { + "version": "3.0.0", + "from": "ansi-escapes@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "dev": true + }, + "ansi-green": { + "version": "0.1.1", + "from": "ansi-green@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/ansi-green/-/ansi-green-0.1.1.tgz" + }, + "ansi-regex": { + "version": "2.1.1", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "from": "ansi-styles@>=3.2.0 <4.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz" + }, + "ansi-wrap": { + "version": "0.1.0", + "from": "ansi-wrap@0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz" + }, + "argparse": { + "version": "1.0.9", + "from": "argparse@>=1.0.7 <2.0.0", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz" + }, + "arr-union": { + "version": "3.1.0", + "from": "arr-union@>=3.1.0 <4.0.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz" + }, + "array-find-index": { + "version": "1.0.2", + "from": "array-find-index@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "from": "array-union@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "from": "array-uniq@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "from": "arrify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "from": "asn1@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "dev": true + }, + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "from": "assertion-error@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "dev": true + }, + "async": { + "version": "1.5.2", + "from": "async@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz" + }, + "async-array-reduce": { + "version": "0.2.1", + "from": "async-array-reduce@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/async-array-reduce/-/async-array-reduce-0.2.1.tgz" + }, + "async-each": { + "version": "1.0.1", + "from": "async-each@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz" + }, + "asynckit": { + "version": "0.4.0", + "from": "asynckit@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "from": "aws-sign2@>=0.7.0 <0.8.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "from": "aws4@>=1.6.0 <2.0.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "from": "babel-code-frame@>=6.22.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "from": "ansi-styles@>=2.2.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.3 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "from": "supports-color@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "dev": true + } + } + }, + "balanced-match": { + "version": "1.0.0", + "from": "balanced-match@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "from": "bcrypt-pbkdf@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "dev": true, + "optional": true + }, + "bluebird": { + "version": "3.5.1", + "from": "bluebird@>=3.4.1 <4.0.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz" + }, + "blueimp-md5": { + "version": "2.10.0", + "from": "blueimp-md5@>=2.3.0 <3.0.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.10.0.tgz", + "dev": true + }, + "boom": { + "version": "4.3.1", + "from": "boom@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "from": "brace-expansion@>=1.1.7 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + }, + "browser-stdout": { + "version": "1.3.0", + "from": "browser-stdout@1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "dev": true + }, + "buffer-equal": { + "version": "1.0.0", + "from": "buffer-equal@1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "from": "builtin-modules@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "from": "caller-path@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "dev": true + }, + "callsites": { + "version": "0.2.0", + "from": "callsites@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "from": "camelcase@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "optional": true + }, + "camelcase-keys": { + "version": "2.1.0", + "from": "camelcase-keys@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "dev": true, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "from": "camelcase@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "dev": true + } + } + }, + "caseless": { + "version": "0.12.0", + "from": "caseless@>=0.12.0 <0.13.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "from": "center-align@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "optional": true, + "dependencies": { + "lazy-cache": { + "version": "1.0.4", + "from": "lazy-cache@>=1.0.3 <2.0.0", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "optional": true + } + } + }, + "chai": { + "version": "4.1.2", + "from": "chai@*", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "dev": true + }, + "chai-as-promised": { + "version": "7.1.1", + "from": "chai-as-promised@>=7.1.1 <8.0.0", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "dev": true + }, + "chalk": { + "version": "2.3.1", + "from": "chalk@>=2.3.1 <3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz" + }, + "chardet": { + "version": "0.4.2", + "from": "chardet@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "dev": true + }, + "check-error": { + "version": "1.0.2", + "from": "check-error@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "dev": true + }, + "chownr": { + "version": "1.0.1", + "from": "chownr@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "dev": true + }, + "circular-json": { + "version": "0.3.3", + "from": "circular-json@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "from": "cli-cursor@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "dev": true + }, + "cli-width": { + "version": "2.2.0", + "from": "cli-width@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "from": "cliui@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "optional": true, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "from": "wordwrap@0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "optional": true + } + } + }, + "clone": { + "version": "1.0.3", + "from": "clone@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz" + }, + "clone-stats": { + "version": "0.0.1", + "from": "clone-stats@>=0.0.1 <0.0.2", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" + }, + "co": { + "version": "4.6.0", + "from": "co@>=4.6.0 <5.0.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "from": "code-point-at@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "dev": true + }, + "coffeescript": { + "version": "1.10.0", + "from": "coffeescript@>=1.10.0 <1.11.0", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", + "dev": true + }, + "color-convert": { + "version": "1.9.1", + "from": "color-convert@>=1.9.0 <2.0.0", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" + }, + "color-name": { + "version": "1.1.3", + "from": "color-name@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + }, + "colors": { + "version": "1.0.3", + "from": "colors@1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "from": "combined-stream@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "dev": true + }, + "commander": { + "version": "2.14.1", + "from": "commander@>=2.9.0 <3.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + }, + "concat-stream": { + "version": "1.6.0", + "from": "concat-stream@>=1.4.7 <2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz" + }, + "copy": { + "version": "0.3.1", + "from": "copy@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/copy/-/copy-0.3.1.tgz" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "cross-spawn": { + "version": "5.1.0", + "from": "cross-spawn@>=5.1.0 <6.0.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "dev": true + }, + "cryptiles": { + "version": "3.1.2", + "from": "cryptiles@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "dev": true, + "dependencies": { + "boom": { + "version": "5.2.0", + "from": "boom@>=5.0.0 <6.0.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "dev": true + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "from": "currently-unhandled@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "from": "dashdash@>=1.12.0 <2.0.0", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "dev": true + }, + "dateformat": { + "version": "1.0.12", + "from": "dateformat@>=1.0.12 <1.1.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "dev": true + }, + "debug": { + "version": "3.1.0", + "from": "debug@>=3.1.0 <4.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "from": "decamelize@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + }, + "deep-eql": { + "version": "3.0.1", + "from": "deep-eql@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "from": "deep-is@>=0.1.3 <0.2.0", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "dev": true + }, + "define-property": { + "version": "0.2.5", + "from": "define-property@>=0.2.5 <0.3.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" + }, + "del": { + "version": "2.2.2", + "from": "del@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "from": "delayed-stream@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "dev": true + }, + "diff": { + "version": "3.3.1", + "from": "diff@3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "dev": true + }, + "dir-compare": { + "version": "1.4.0", + "from": "dir-compare@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-1.4.0.tgz", + "dev": true, + "dependencies": { + "bluebird": { + "version": "3.4.1", + "from": "bluebird@3.4.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.1.tgz", + "dev": true + }, + "commander": { + "version": "2.9.0", + "from": "commander@2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "dev": true + }, + "minimatch": { + "version": "3.0.2", + "from": "minimatch@3.0.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", + "dev": true + } + } + }, + "doctrine": { + "version": "2.1.0", + "from": "doctrine@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "from": "ecc-jsbn@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "dev": true, + "optional": true + }, + "email-validator": { + "version": "1.1.1", + "from": "email-validator@>=1.0.7 <2.0.0", + "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-1.1.1.tgz", + "dev": true + }, + "error-ex": { + "version": "1.3.1", + "from": "error-ex@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "dev": true + }, + "escape-latex": { + "version": "1.0.0", + "from": "escape-latex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.0.0.tgz" + }, + "escape-string-regexp": { + "version": "1.0.5", + "from": "escape-string-regexp@>=1.0.5 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + }, + "eslint": { + "version": "4.17.0", + "from": "eslint@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.17.0.tgz", + "dev": true, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "from": "ansi-regex@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "dev": true + }, + "esprima": { + "version": "4.0.0", + "from": "esprima@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "from": "js-yaml@>=3.9.1 <4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "from": "strip-ansi@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "dev": true + } + } + }, + "eslint-scope": { + "version": "3.7.1", + "from": "eslint-scope@>=3.7.1 <4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "from": "eslint-visitor-keys@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "dev": true + }, + "espree": { + "version": "3.5.3", + "from": "espree@>=3.5.2 <4.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "from": "esprima@>=2.6.0 <3.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "from": "esquery@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "dev": true + }, + "esrecurse": { + "version": "4.2.0", + "from": "esrecurse@>=4.1.0 <5.0.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "dev": true + }, + "estraverse": { + "version": "4.2.0", + "from": "estraverse@>=4.1.1 <5.0.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "from": "esutils@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "from": "eventemitter2@>=0.4.13 <0.5.0", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "dev": true + }, + "exit": { + "version": "0.1.2", + "from": "exit@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "dev": true + }, + "expand-tilde": { + "version": "1.2.2", + "from": "expand-tilde@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz" + }, + "extend": { + "version": "3.0.1", + "from": "extend@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz" + }, + "extend-shallow": { + "version": "2.0.1", + "from": "extend-shallow@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + }, + "external-editor": { + "version": "2.1.0", + "from": "external-editor@>=2.0.4 <3.0.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "dev": true + }, + "extsprintf": { + "version": "1.3.0", + "from": "extsprintf@1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "dev": true + }, + "fast-deep-equal": { + "version": "1.0.0", + "from": "fast-deep-equal@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "from": "fast-json-stable-stringify@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "from": "fast-levenshtein@>=2.0.4 <2.1.0", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "dev": true + }, + "figures": { + "version": "2.0.0", + "from": "figures@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "dev": true + }, + "file-contents": { + "version": "0.3.2", + "from": "file-contents@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/file-contents/-/file-contents-0.3.2.tgz" + }, + "file-entry-cache": { + "version": "2.0.0", + "from": "file-entry-cache@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "dev": true + }, + "file-stat": { + "version": "0.2.3", + "from": "file-stat@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/file-stat/-/file-stat-0.2.3.tgz" + }, + "file-sync-cmp": { + "version": "0.1.1", + "from": "file-sync-cmp@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "from": "find-up@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "dev": true, + "dependencies": { + "path-exists": { + "version": "2.1.0", + "from": "path-exists@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "dev": true + } + } + }, + "findup-sync": { + "version": "0.3.0", + "from": "findup-sync@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "dev": true, + "dependencies": { + "glob": { + "version": "5.0.15", + "from": "glob@>=5.0.0 <5.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "dev": true + } + } + }, + "flat-cache": { + "version": "1.3.0", + "from": "flat-cache@>=1.2.1 <2.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "from": "forever-agent@>=0.6.1 <0.7.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "dev": true + }, + "form-data": { + "version": "2.3.1", + "from": "form-data@>=2.3.1 <2.4.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "dev": true + }, + "fresh-jrs-converter": { + "version": "1.0.0", + "from": "fresh-jrs-converter@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fresh-jrs-converter/-/fresh-jrs-converter-1.0.0.tgz" + }, + "fresh-resume-schema": { + "version": "1.0.0-beta", + "from": "fresh-resume-schema@>=1.0.0-beta <2.0.0", + "resolved": "https://registry.npmjs.org/fresh-resume-schema/-/fresh-resume-schema-1.0.0-beta.tgz" + }, + "fresh-resume-starter": { + "version": "0.3.1", + "from": "fresh-resume-starter@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/fresh-resume-starter/-/fresh-resume-starter-0.3.1.tgz" + }, + "fresh-resume-validator": { + "version": "0.2.0", + "from": "fresh-resume-validator@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/fresh-resume-validator/-/fresh-resume-validator-0.2.0.tgz" + }, + "fresh-test-resumes": { + "version": "0.9.2", + "from": "fresh-test-resumes@>=0.9.2 <0.10.0", + "resolved": "https://registry.npmjs.org/fresh-test-resumes/-/fresh-test-resumes-0.9.2.tgz", + "dev": true + }, + "fresh-test-themes": { + "version": "0.2.0", + "from": "fresh-test-themes@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/fresh-test-themes/-/fresh-test-themes-0.2.0.tgz", + "dev": true + }, + "fresh-theme-hello-world": { + "version": "0.1.0", + "from": "fresh-theme-hello-world@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/fresh-theme-hello-world/-/fresh-theme-hello-world-0.1.0.tgz", + "dev": true + }, + "fresh-theme-underscore": { + "version": "0.1.1", + "from": "fresh-theme-underscore@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/fresh-theme-underscore/-/fresh-theme-underscore-0.1.1.tgz", + "dev": true + }, + "fresh-themes": { + "version": "0.17.0-beta", + "from": "fresh-themes@>=0.17.0-beta <0.18.0", + "resolved": "https://registry.npmjs.org/fresh-themes/-/fresh-themes-0.17.0-beta.tgz" + }, + "fs-exists-sync": { + "version": "0.1.0", + "from": "fs-exists-sync@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz" + }, + "fs-extra": { + "version": "5.0.0", + "from": "fs-extra@>=5.0.0 <6.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz" + }, + "fs-minipass": { + "version": "1.2.5", + "from": "fs-minipass@>=1.2.3 <2.0.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "from": "fs.realpath@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "from": "functional-red-black-tree@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "dev": true + }, + "generate-function": { + "version": "2.0.0", + "from": "generate-function@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" + }, + "generate-object-property": { + "version": "1.2.0", + "from": "generate-object-property@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz" + }, + "get-caller-file": { + "version": "1.0.2", + "from": "get-caller-file@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "from": "get-func-name@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "from": "get-stdin@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "dev": true + }, + "getobject": { + "version": "0.1.0", + "from": "getobject@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "from": "getpass@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "dev": true + }, + "glob": { + "version": "7.1.2", + "from": "glob@>=7.1.2 <8.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" + }, + "glob-parent": { + "version": "2.0.0", + "from": "glob-parent@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz" + }, + "global-modules": { + "version": "0.2.3", + "from": "global-modules@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz" + }, + "global-prefix": { + "version": "0.1.5", + "from": "global-prefix@>=0.1.4 <0.2.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz" + }, + "globals": { + "version": "11.3.0", + "from": "globals@>=11.0.1 <12.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", + "dev": true + }, + "globby": { + "version": "5.0.0", + "from": "globby@>=5.0.0 <6.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "from": "graceful-fs@>=4.1.4 <5.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" + }, + "graceful-readlink": { + "version": "1.0.1", + "from": "graceful-readlink@>=1.0.0", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "dev": true + }, + "gravatar": { + "version": "1.6.0", + "from": "gravatar@>=1.0.6 <2.0.0", + "resolved": "https://registry.npmjs.org/gravatar/-/gravatar-1.6.0.tgz", + "dev": true, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "from": "camelcase@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "from": "cliui@>=3.2.0 <4.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "from": "string-width@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dev": true + }, + "yargs": { + "version": "6.6.0", + "from": "yargs@>=6.0.0 <7.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "dev": true + } + } + }, + "growl": { + "version": "1.10.3", + "from": "growl@1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "dev": true + }, + "grunt": { + "version": "1.0.2", + "from": "grunt@*", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.2.tgz", + "dev": true, + "dependencies": { + "glob": { + "version": "7.0.6", + "from": "glob@>=7.0.0 <7.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "dev": true + }, + "grunt-cli": { + "version": "1.2.0", + "from": "grunt-cli@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "dev": true + } + } + }, + "grunt-contrib-clean": { + "version": "1.1.0", + "from": "grunt-contrib-clean@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.1.0.tgz", + "dev": true, + "dependencies": { + "rimraf": { + "version": "2.6.2", + "from": "rimraf@>=2.5.1 <3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "dev": true + } + } + }, + "grunt-contrib-coffee": { + "version": "2.0.0", + "from": "grunt-contrib-coffee@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-coffee/-/grunt-contrib-coffee-2.0.0.tgz", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "from": "ansi-styles@>=2.2.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dev": true + }, + "coffeescript": { + "version": "2.2.1", + "from": "coffeescript@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.2.1.tgz", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "from": "supports-color@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "dev": true + } + } + }, + "grunt-contrib-copy": { + "version": "1.0.0", + "from": "grunt-contrib-copy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "from": "ansi-styles@>=2.2.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "from": "supports-color@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "dev": true + } + } + }, + "grunt-eslint": { + "version": "20.1.0", + "from": "grunt-eslint@>=20.1.0 <21.0.0", + "resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-20.1.0.tgz", + "dev": true + }, + "grunt-known-options": { + "version": "1.1.0", + "from": "grunt-known-options@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz", + "dev": true + }, + "grunt-legacy-log": { + "version": "1.0.0", + "from": "grunt-legacy-log@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-1.0.0.tgz", + "dev": true, + "dependencies": { + "colors": { + "version": "1.1.2", + "from": "colors@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "dev": true + }, + "lodash": { + "version": "3.10.1", + "from": "lodash@>=3.10.1 <3.11.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "dev": true + } + } + }, + "grunt-legacy-log-utils": { + "version": "1.0.0", + "from": "grunt-legacy-log-utils@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "from": "ansi-styles@>=2.2.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.1 <1.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dev": true + }, + "lodash": { + "version": "4.3.0", + "from": "lodash@>=4.3.0 <4.4.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "from": "supports-color@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "dev": true + } + } + }, + "grunt-legacy-util": { + "version": "1.0.0", + "from": "grunt-legacy-util@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz", + "dev": true, + "dependencies": { + "lodash": { + "version": "4.3.0", + "from": "lodash@>=4.3.0 <4.4.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "dev": true + }, + "which": { + "version": "1.2.14", + "from": "which@>=1.2.1 <1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "dev": true + } + } + }, + "grunt-simple-mocha": { + "version": "0.4.1", + "from": "grunt-simple-mocha@*", + "resolved": "https://registry.npmjs.org/grunt-simple-mocha/-/grunt-simple-mocha-0.4.1.tgz", + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "from": "handlebars@>=4.0.5 <5.0.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz" + }, + "har-schema": { + "version": "2.0.0", + "from": "har-schema@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "dev": true + }, + "har-validator": { + "version": "5.0.3", + "from": "har-validator@>=5.0.3 <5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "from": "has-ansi@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "dev": true + }, + "has-color": { + "version": "0.1.7", + "from": "has-color@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz" + }, + "has-flag": { + "version": "3.0.0", + "from": "has-flag@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + }, + "has-glob": { + "version": "0.1.1", + "from": "has-glob@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/has-glob/-/has-glob-0.1.1.tgz" + }, + "hawk": { + "version": "6.0.2", + "from": "hawk@>=6.0.2 <6.1.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "dev": true + }, + "he": { + "version": "1.1.1", + "from": "he@1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "dev": true + }, + "hoek": { + "version": "4.2.0", + "from": "hoek@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "from": "homedir-polyfill@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz" + }, + "hooker": { + "version": "0.2.3", + "from": "hooker@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "from": "hosted-git-info@>=2.1.4 <3.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "dev": true + }, + "html": { + "version": "1.0.0", + "from": "html@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/html/-/html-1.0.0.tgz" + }, + "http-signature": { + "version": "1.2.0", + "from": "http-signature@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "dev": true + }, + "iconv-lite": { + "version": "0.4.19", + "from": "iconv-lite@>=0.4.13 <0.5.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "dev": true + }, + "ignore": { + "version": "3.3.7", + "from": "ignore@>=3.3.3 <4.0.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "from": "imurmurhash@>=0.1.4 <0.2.0", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "from": "indent-string@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + }, + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.3 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + }, + "ini": { + "version": "1.3.5", + "from": "ini@>=1.3.4 <2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz" + }, + "inquirer": { + "version": "3.3.0", + "from": "inquirer@>=3.0.6 <4.0.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "dev": true, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "from": "ansi-regex@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "from": "strip-ansi@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "dev": true + } + } + }, + "invert-kv": { + "version": "1.0.0", + "from": "invert-kv@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "dev": true + }, + "is-absolute": { + "version": "0.2.6", + "from": "is-absolute@>=0.2.5 <0.3.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "from": "is-accessor-descriptor@>=0.1.6 <0.2.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "dependencies": { + "kind-of": { + "version": "3.2.2", + "from": "kind-of@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "from": "is-arrayish@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "from": "is-buffer@>=1.1.3 <2.0.0", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + }, + "is-builtin-module": { + "version": "1.0.0", + "from": "is-builtin-module@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "from": "is-data-descriptor@>=0.1.4 <0.2.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "dependencies": { + "kind-of": { + "version": "3.2.2", + "from": "kind-of@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "from": "is-descriptor@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" + }, + "is-extendable": { + "version": "0.1.1", + "from": "is-extendable@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + }, + "is-extglob": { + "version": "1.0.0", + "from": "is-extglob@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" + }, + "is-finite": { + "version": "1.0.2", + "from": "is-finite@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "from": "is-fullwidth-code-point@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "from": "is-glob@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" + }, + "is-my-json-valid": { + "version": "2.17.1", + "from": "is-my-json-valid@>=2.12.4 <3.0.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz" + }, + "is-path-cwd": { + "version": "1.0.0", + "from": "is-path-cwd@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "from": "is-path-in-cwd@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "dev": true + }, + "is-path-inside": { + "version": "1.0.1", + "from": "is-path-inside@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "from": "is-promise@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "from": "is-property@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" + }, + "is-relative": { + "version": "0.2.1", + "from": "is-relative@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz" + }, + "is-resolvable": { + "version": "1.1.0", + "from": "is-resolvable@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "from": "is-typedarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "dev": true + }, + "is-unc-path": { + "version": "0.1.2", + "from": "is-unc-path@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz" + }, + "is-utf8": { + "version": "0.2.1", + "from": "is-utf8@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + }, + "is-valid-glob": { + "version": "0.3.0", + "from": "is-valid-glob@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz" + }, + "is-windows": { + "version": "0.2.0", + "from": "is-windows@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "isexe": { + "version": "2.0.0", + "from": "isexe@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + }, + "isobject": { + "version": "2.1.0", + "from": "isobject@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" + }, + "isstream": { + "version": "0.1.2", + "from": "isstream@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "from": "js-tokens@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "dev": true + }, + "js-yaml": { + "version": "3.5.5", + "from": "js-yaml@>=3.5.2 <3.6.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "from": "jsbn@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "dev": true, + "optional": true + }, + "json-lint": { + "version": "0.1.0", + "from": "json-lint@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/json-lint/-/json-lint-0.1.0.tgz" + }, + "json-schema": { + "version": "0.2.3", + "from": "json-schema@0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "from": "json-schema-traverse@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "from": "json-stable-stringify-without-jsonify@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "from": "json-stringify-safe@>=5.0.1 <5.1.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "from": "jsonfile@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" + }, + "jsonlint": { + "version": "1.6.2", + "from": "jsonlint@>=1.6.2 <2.0.0", + "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.2.tgz" + }, + "jsonpointer": { + "version": "4.0.1", + "from": "jsonpointer@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz" + }, + "jsonresume-theme-boilerplate": { + "version": "0.1.2", + "from": "jsonresume-theme-boilerplate@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/jsonresume-theme-boilerplate/-/jsonresume-theme-boilerplate-0.1.2.tgz", + "dev": true, + "dependencies": { + "async": { + "version": "0.2.10", + "from": "async@>=0.2.6 <0.3.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "dev": true, + "optional": true + }, + "handlebars": { + "version": "2.0.0", + "from": "handlebars@>=2.0.0-alpha.4 <3.0.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-2.0.0.tgz", + "dev": true + }, + "optimist": { + "version": "0.3.7", + "from": "optimist@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "dev": true + }, + "source-map": { + "version": "0.1.43", + "from": "source-map@>=0.1.7 <0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "dev": true, + "optional": true + }, + "uglify-js": { + "version": "2.3.6", + "from": "uglify-js@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.6.tgz", + "dev": true, + "optional": true + } + } + }, + "jsonresume-theme-classy": { + "version": "1.0.9", + "from": "jsonresume-theme-classy@>=1.0.9 <2.0.0", + "resolved": "https://registry.npmjs.org/jsonresume-theme-classy/-/jsonresume-theme-classy-1.0.9.tgz", + "dev": true, + "dependencies": { + "lodash": { + "version": "2.4.2", + "from": "lodash@>=2.4.1 <3.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "dev": true + } + } + }, + "jsonresume-theme-modern": { + "version": "0.0.18", + "from": "jsonresume-theme-modern@0.0.18", + "resolved": "https://registry.npmjs.org/jsonresume-theme-modern/-/jsonresume-theme-modern-0.0.18.tgz", + "dev": true, + "dependencies": { + "lodash": { + "version": "2.4.2", + "from": "lodash@>=2.4.1 <3.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "dev": true + } + } + }, + "jsonresume-theme-sceptile": { + "version": "1.0.5", + "from": "jsonresume-theme-sceptile@>=1.0.5 <2.0.0", + "resolved": "https://registry.npmjs.org/jsonresume-theme-sceptile/-/jsonresume-theme-sceptile-1.0.5.tgz", + "dev": true, + "dependencies": { + "lodash": { + "version": "2.4.2", + "from": "lodash@>=2.4.1 <3.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "dev": true + } + } + }, + "jsprim": { + "version": "1.4.1", + "from": "jsprim@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "dev": true + }, + "JSV": { + "version": "4.0.2", + "from": "JSV@>=4.0.0", + "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz" + }, + "kind-of": { + "version": "5.1.0", + "from": "kind-of@>=5.0.0 <6.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" + }, + "lazy-cache": { + "version": "2.0.2", + "from": "lazy-cache@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz" + }, + "lcid": { + "version": "1.0.0", + "from": "lcid@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "dev": true + }, + "levn": { + "version": "0.3.0", + "from": "levn@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "from": "load-json-file@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "dev": true + }, + "lodash": { + "version": "4.17.5", + "from": "lodash@>=4.17.5 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz" + }, + "log-ok": { + "version": "0.1.1", + "from": "log-ok@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/log-ok/-/log-ok-0.1.1.tgz" + }, + "longest": { + "version": "1.0.1", + "from": "longest@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz" + }, + "loud-rejection": { + "version": "1.6.0", + "from": "loud-rejection@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "dev": true + }, + "lru-cache": { + "version": "4.1.1", + "from": "lru-cache@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "from": "map-cache@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" + }, + "map-obj": { + "version": "1.0.1", + "from": "map-obj@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "dev": true + }, + "marked": { + "version": "0.3.12", + "from": "marked@>=0.3.5 <0.4.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.12.tgz" + }, + "matched": { + "version": "0.4.4", + "from": "matched@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/matched/-/matched-0.4.4.tgz" + }, + "meow": { + "version": "3.7.0", + "from": "meow@>=3.3.0 <4.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "dev": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "from": "minimist@>=1.1.3 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "dev": true + } + } + }, + "mime-db": { + "version": "1.30.0", + "from": "mime-db@>=1.30.0 <1.31.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "dev": true + }, + "mime-types": { + "version": "2.1.17", + "from": "mime-types@>=2.1.17 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "dev": true + }, + "mimic-fn": { + "version": "1.2.0", + "from": "mimic-fn@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "from": "minimatch@>=3.0.4 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + }, + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + }, + "minipass": { + "version": "2.2.1", + "from": "minipass@>=2.2.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.1.tgz", + "dev": true, + "dependencies": { + "yallist": { + "version": "3.0.2", + "from": "yallist@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "dev": true + } + } + }, + "minizlib": { + "version": "1.1.0", + "from": "minizlib@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" + }, + "mocha": { + "version": "5.0.0", + "from": "mocha@*", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.0.0.tgz", + "dev": true, + "dependencies": { + "commander": { + "version": "2.11.0", + "from": "commander@2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "dev": true + }, + "has-flag": { + "version": "2.0.0", + "from": "has-flag@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "from": "supports-color@4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "dev": true + } + } + }, + "moment": { + "version": "2.20.1", + "from": "moment@>=2.11.1 <3.0.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz" + }, + "ms": { + "version": "2.0.0", + "from": "ms@2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "dev": true + }, + "mustache": { + "version": "0.8.2", + "from": "mustache@>=0.8.2 <0.9.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-0.8.2.tgz", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "from": "mute-stream@0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "from": "natural-compare@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "dev": true + }, + "nomnom": { + "version": "1.8.1", + "from": "nomnom@>=1.5.0", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "from": "ansi-styles@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz" + }, + "chalk": { + "version": "0.4.0", + "from": "chalk@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz" + }, + "underscore": { + "version": "1.6.0", + "from": "underscore@>=1.6.0 <1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" + } + } + }, + "nopt": { + "version": "3.0.6", + "from": "nopt@>=3.0.6 <3.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "from": "normalize-package-data@>=2.3.4 <3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "from": "number-is-nan@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "from": "oauth-sign@>=0.8.2 <0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "from": "object-assign@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "dev": true + }, + "once": { + "version": "1.4.0", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + }, + "onetime": { + "version": "2.0.1", + "from": "onetime@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "from": "optimist@>=0.6.1 <0.7.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz" + }, + "optionator": { + "version": "0.8.2", + "from": "optionator@>=0.8.2 <0.9.0", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "dev": true, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "from": "wordwrap@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "dev": true + } + } + }, + "os-homedir": { + "version": "1.0.2", + "from": "os-homedir@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" + }, + "os-locale": { + "version": "1.4.0", + "from": "os-locale@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "from": "os-tmpdir@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "dev": true + }, + "parse-filepath": { + "version": "1.0.2", + "from": "parse-filepath@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "dependencies": { + "is-absolute": { + "version": "1.0.0", + "from": "is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz" + }, + "is-relative": { + "version": "1.0.0", + "from": "is-relative@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz" + }, + "is-unc-path": { + "version": "1.0.0", + "from": "is-unc-path@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz" + }, + "is-windows": { + "version": "1.0.1", + "from": "is-windows@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz" + } + } + }, + "parse-json": { + "version": "2.2.0", + "from": "parse-json@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "from": "parse-passwd@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz" + }, + "path-exists": { + "version": "3.0.0", + "from": "path-exists@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + }, + "path-is-absolute": { + "version": "1.0.1", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + }, + "path-is-inside": { + "version": "1.0.2", + "from": "path-is-inside@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "from": "path-root@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz" + }, + "path-root-regex": { + "version": "0.1.2", + "from": "path-root-regex@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz" + }, + "path-type": { + "version": "1.1.0", + "from": "path-type@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "dev": true + }, + "pathval": { + "version": "1.1.0", + "from": "pathval@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "from": "performance-now@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "dev": true + }, + "pify": { + "version": "2.3.0", + "from": "pify@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "from": "pinkie@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + }, + "pinkie-promise": { + "version": "2.0.1", + "from": "pinkie-promise@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + }, + "pluralize": { + "version": "7.0.0", + "from": "pluralize@>=7.0.0 <8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "from": "prelude-ls@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "dev": true + }, + "printf": { + "version": "0.2.5", + "from": "printf@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/printf/-/printf-0.2.5.tgz" + }, + "process-nextick-args": { + "version": "2.0.0", + "from": "process-nextick-args@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz" + }, + "progress": { + "version": "2.0.0", + "from": "progress@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "from": "pseudomap@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "from": "punycode@>=1.4.1 <2.0.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "dev": true + }, + "qs": { + "version": "6.5.1", + "from": "qs@>=6.5.1 <6.6.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "from": "querystring@0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "from": "read-pkg@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "dev": true + }, + "read-pkg-up": { + "version": "1.0.1", + "from": "read-pkg-up@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "dev": true + }, + "readable-stream": { + "version": "2.3.4", + "from": "readable-stream@>=2.1.5 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz" + }, + "recursive-readdir-sync": { + "version": "1.0.6", + "from": "recursive-readdir-sync@>=1.0.6 <2.0.0", + "resolved": "https://registry.npmjs.org/recursive-readdir-sync/-/recursive-readdir-sync-1.0.6.tgz" + }, + "redent": { + "version": "1.0.0", + "from": "redent@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "from": "repeat-string@>=1.5.2 <2.0.0", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + }, + "repeating": { + "version": "2.0.1", + "from": "repeating@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "from": "replace-ext@0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" + }, + "request": { + "version": "2.83.0", + "from": "request@>=2.39.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "from": "require-directory@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "from": "require-main-filename@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "from": "require-uncached@>=1.0.3 <2.0.0", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "from": "resolve@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "dev": true + }, + "resolve-dir": { + "version": "0.1.1", + "from": "resolve-dir@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz" + }, + "resolve-from": { + "version": "1.0.1", + "from": "resolve-from@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "from": "restore-cursor@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "dev": true + }, + "resume-schema": { + "version": "0.0.15", + "from": "resume-schema@0.0.15", + "resolved": "https://registry.npmjs.org/resume-schema/-/resume-schema-0.0.15.tgz", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "from": "right-align@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "optional": true + }, + "rimraf": { + "version": "2.2.8", + "from": "rimraf@>=2.2.8 <2.3.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "dev": true + }, + "run-async": { + "version": "2.3.0", + "from": "run-async@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "dev": true + }, + "rx-lite": { + "version": "4.0.8", + "from": "rx-lite@>=4.0.8 <5.0.0", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "from": "rx-lite-aggregates@>=4.0.8 <5.0.0", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "from": "safe-buffer@>=5.1.1 <5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + }, + "semver": { + "version": "5.5.0", + "from": "semver@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0||>=4.0.0 <5.0.0||>=5.0.0 <6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "from": "set-blocking@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "dev": true + }, + "set-getter": { + "version": "0.1.0", + "from": "set-getter@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz" + }, + "shebang-command": { + "version": "1.2.0", + "from": "shebang-command@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "dev": true + }, + "shebang-regex": { + "version": "1.0.0", + "from": "shebang-regex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "from": "signal-exit@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "dev": true + }, + "simple-html-tokenizer": { + "version": "0.4.3", + "from": "simple-html-tokenizer@>=0.4.3 <0.5.0", + "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.4.3.tgz" + }, + "slash": { + "version": "1.0.0", + "from": "slash@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz" + }, + "slice-ansi": { + "version": "1.0.0", + "from": "slice-ansi@1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "dev": true + }, + "sntp": { + "version": "2.1.0", + "from": "sntp@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "from": "source-map@>=0.4.4 <0.5.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz" + }, + "spdx-correct": { + "version": "1.0.2", + "from": "spdx-correct@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "dev": true + }, + "spdx-expression-parse": { + "version": "1.0.4", + "from": "spdx-expression-parse@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "from": "spdx-license-ids@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "from": "sprintf-js@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + }, + "sshpk": { + "version": "1.13.1", + "from": "sshpk@>=1.7.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "from": "string_decoder@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz" + }, + "string-padding": { + "version": "1.0.2", + "from": "string-padding@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/string-padding/-/string-padding-1.0.2.tgz" + }, + "string-width": { + "version": "2.1.1", + "from": "string-width@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "dev": true, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "from": "ansi-regex@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "from": "strip-ansi@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "dev": true + } + } + }, + "string.prototype.endswith": { + "version": "0.2.0", + "from": "string.prototype.endswith@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/string.prototype.endswith/-/string.prototype.endswith-0.2.0.tgz" + }, + "string.prototype.startswith": { + "version": "0.2.0", + "from": "string.prototype.startswith@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/string.prototype.startswith/-/string.prototype.startswith-0.2.0.tgz" + }, + "stringstream": { + "version": "0.0.5", + "from": "stringstream@>=0.0.5 <0.1.0", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "dev": true + }, + "strip-ansi": { + "version": "0.1.1", + "from": "strip-ansi@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz" + }, + "strip-bom": { + "version": "2.0.0", + "from": "strip-bom@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "dev": true + }, + "strip-bom-buffer": { + "version": "0.1.1", + "from": "strip-bom-buffer@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/strip-bom-buffer/-/strip-bom-buffer-0.1.1.tgz" + }, + "strip-bom-string": { + "version": "0.1.2", + "from": "strip-bom-string@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-0.1.2.tgz" + }, + "strip-indent": { + "version": "1.0.1", + "from": "strip-indent@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "from": "strip-json-comments@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "dev": true + }, + "stripcolorcodes": { + "version": "0.1.0", + "from": "stripcolorcodes@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/stripcolorcodes/-/stripcolorcodes-0.1.0.tgz", + "dev": true + }, + "success-symbol": { + "version": "0.1.0", + "from": "success-symbol@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/success-symbol/-/success-symbol-0.1.0.tgz" + }, + "supports-color": { + "version": "5.2.0", + "from": "supports-color@>=5.2.0 <6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz" + }, + "table": { + "version": "4.0.2", + "from": "table@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "dev": true + }, + "tar": { + "version": "4.3.3", + "from": "tar@*", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.3.3.tgz", + "dev": true, + "dependencies": { + "yallist": { + "version": "3.0.2", + "from": "yallist@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "dev": true + } + } + }, + "tarball-extract": { + "version": "0.0.3", + "from": "tarball-extract@0.0.3", + "resolved": "https://registry.npmjs.org/tarball-extract/-/tarball-extract-0.0.3.tgz", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "from": "text-table@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "dev": true + }, + "through": { + "version": "2.3.8", + "from": "through@>=2.3.6 <3.0.0", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "dev": true + }, + "through2": { + "version": "2.0.3", + "from": "through2@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" + }, + "tmp": { + "version": "0.0.33", + "from": "tmp@>=0.0.33 <0.0.34", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "dev": true + }, + "to-file": { + "version": "0.2.0", + "from": "to-file@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/to-file/-/to-file-0.2.0.tgz", + "dependencies": { + "file-contents": { + "version": "0.2.4", + "from": "file-contents@>=0.2.4 <0.3.0", + "resolved": "https://registry.npmjs.org/file-contents/-/file-contents-0.2.4.tgz", + "dependencies": { + "lazy-cache": { + "version": "0.2.7", + "from": "lazy-cache@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz" + } + } + }, + "file-stat": { + "version": "0.1.3", + "from": "file-stat@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/file-stat/-/file-stat-0.1.3.tgz", + "dependencies": { + "lazy-cache": { + "version": "0.2.7", + "from": "lazy-cache@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz" + } + } + } + } + }, + "to-object-path": { + "version": "0.3.0", + "from": "to-object-path@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "dependencies": { + "kind-of": { + "version": "3.2.2", + "from": "kind-of@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + } + } + }, + "tough-cookie": { + "version": "2.3.3", + "from": "tough-cookie@>=2.3.3 <2.4.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "dev": true + }, + "traverse": { + "version": "0.6.6", + "from": "traverse@>=0.6.6 <0.7.0", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz" + }, + "trim-newlines": { + "version": "1.0.0", + "from": "trim-newlines@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "dev": true + }, + "tunnel": { + "version": "0.0.2", + "from": "tunnel@0.0.2", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.2.tgz", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "from": "tunnel-agent@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "dev": true + }, + "tweetnacl": { + "version": "0.14.5", + "from": "tweetnacl@>=0.14.0 <0.15.0", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "from": "type-check@>=0.3.2 <0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "dev": true + }, + "type-detect": { + "version": "4.0.8", + "from": "type-detect@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "from": "typedarray@>=0.0.6 <0.0.7", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + }, + "uglify-js": { + "version": "2.8.29", + "from": "uglify-js@>=2.6.0 <3.0.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "optional": true, + "dependencies": { + "source-map": { + "version": "0.5.7", + "from": "source-map@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "optional": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "from": "uglify-to-browserify@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "optional": true + }, + "unc-path-regex": { + "version": "0.1.2", + "from": "unc-path-regex@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz" + }, + "underscore": { + "version": "1.8.3", + "from": "underscore@>=1.8.3 <2.0.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz" + }, + "underscore.string": { + "version": "3.2.3", + "from": "underscore.string@>=3.2.3 <3.3.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz", + "dev": true + }, + "universalify": { + "version": "0.1.1", + "from": "universalify@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz" + }, + "uri-path": { + "version": "1.0.0", + "from": "uri-path@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + }, + "uuid": { + "version": "3.2.1", + "from": "uuid@>=3.1.0 <4.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "from": "validate-npm-package-license@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "dev": true + }, + "verror": { + "version": "1.10.0", + "from": "verror@1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "from": "vinyl@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz" + }, + "wget": { + "version": "0.0.1", + "from": "wget@*", + "resolved": "https://registry.npmjs.org/wget/-/wget-0.0.1.tgz", + "dev": true + }, + "which": { + "version": "1.3.0", + "from": "which@>=1.2.12 <2.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" + }, + "which-module": { + "version": "1.0.0", + "from": "which-module@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "from": "window-size@0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "optional": true + }, + "word-wrap": { + "version": "1.2.3", + "from": "word-wrap@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" + }, + "wordwrap": { + "version": "0.0.3", + "from": "wordwrap@>=0.0.2 <0.1.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" + }, + "wrap-ansi": { + "version": "2.1.0", + "from": "wrap-ansi@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "from": "string-width@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + }, + "write": { + "version": "0.2.1", + "from": "write@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "dev": true + }, + "xml-escape": { + "version": "1.1.0", + "from": "xml-escape@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/xml-escape/-/xml-escape-1.1.0.tgz" + }, + "xtend": { + "version": "4.0.1", + "from": "xtend@>=4.0.1 <4.1.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + }, + "y18n": { + "version": "3.2.1", + "from": "y18n@>=3.2.1 <4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "from": "yallist@>=2.1.2 <3.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "dev": true + }, + "yamljs": { + "version": "0.3.0", + "from": "yamljs@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz" + }, + "yargs": { + "version": "3.10.0", + "from": "yargs@>=3.10.0 <3.11.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "optional": true + }, + "yargs-parser": { + "version": "4.2.1", + "from": "yargs-parser@>=4.2.0 <5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "dev": true, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "from": "camelcase@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "dev": true + } + } + }, + "z-schema": { + "version": "2.4.10", + "from": "z-schema@>=2.4.8 <2.5.0", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-2.4.10.tgz", + "dev": true + } + } +} diff --git a/package.json b/package.json index e8539e25..886b0f16 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,15 @@ { "name": "hackmyresume", - "version": "1.2.2", + "version": "1.9.0-beta", "description": "Generate polished résumés and CVs in HTML, Markdown, LaTeX, MS Word, PDF, plain text, JSON, XML, YAML, smoke signal, and carrier pigeon.", "repository": { "type": "git", "url": "https://github.com/hacksalot/HackMyResume.git" }, + "scripts": { + "test": "grunt clean:test && mocha --exit", + "grunt": "grunt" + }, "keywords": [ "resume", "CV", @@ -25,48 +29,81 @@ "template" ], "author": "hacksalot (https://github.com/hacksalot)", + "contributors": [ + "aruberto (https://github.com/aruberto)", + "daniele-rapagnani (https://github.com/daniele-rapagnani)", + "jjanusch (https://github.com/driftdev)", + "robertmain (https://github.com/robertmain)", + "tomheon (https://github.com/tomheon)", + "zhuangya (https://github.com/zhuangya)", + "hacksalot (https://github.com/hacksalot)" + ], "license": "MIT", "preferGlobal": "true", "bugs": { "url": "https://github.com/hacksalot/HackMyResume/issues" }, - "main": "src/hackmycmd.js", "bin": { - "hackmyresume": "src/index.js" + "hackmyresume": "src/cli/index.js" }, + "main": "src/index.js", "homepage": "https://github.com/hacksalot/HackMyResume", "dependencies": { - "colors": "^1.1.2", - "fluent-themes": "~0.7.1-beta", - "fresca": "~0.2.2", - "fs-extra": "^0.24.0", + "chalk": "^2.3.1", + "commander": "^2.9.0", + "copy": "^0.3.1", + "escape-latex": "^1.0.0", + "extend": "^3.0.0", + "fresh-jrs-converter": "^1.0.0", + "fresh-resume-schema": "^1.0.0-beta", + "fresh-resume-starter": "^0.3.1", + "fresh-resume-validator": "^0.2.0", + "fresh-themes": "^0.17.0-beta", + "fs-extra": "^5.0.0", + "glob": "^7.1.2", "handlebars": "^4.0.5", - "html": "0.0.10", - "is-my-json-valid": "^2.12.2", - "jst": "0.0.13", - "lodash": "^3.10.1", + "html": "^1.0.0", + "is-my-json-valid": "^2.12.4", + "json-lint": "^0.1.0", + "jsonlint": "^1.6.2", + "lodash": "^4.17.5", "marked": "^0.3.5", - "minimist": "^1.2.0", "mkdirp": "^0.5.1", - "moment": "^2.10.6", - "parse-filepath": "^0.6.3", - "path-exists": "^2.1.0", + "moment": "^2.11.1", + "parse-filepath": "^1.0.2", + "path-exists": "^3.0.0", + "pinkie-promise": "^2.0.0", + "printf": "^0.2.3", "recursive-readdir-sync": "^1.0.6", - "simple-html-tokenizer": "^0.2.0", + "simple-html-tokenizer": "^0.4.3", + "slash": "^1.0.0", + "string-padding": "^1.0.2", + "string.prototype.endswith": "^0.2.0", + "string.prototype.startswith": "^0.2.0", + "traverse": "^0.6.6", "underscore": "^1.8.3", - "wkhtmltopdf": "^0.1.5", + "word-wrap": "^1.1.0", "xml-escape": "^1.0.0", - "yamljs": "^0.2.4" + "yamljs": "^0.3.0" }, "devDependencies": { "chai": "*", + "chai-as-promised": "^7.1.1", + "dir-compare": "^1.4.0", + "fresh-test-resumes": "^0.9.2", + "fresh-test-themes": "^0.2.0", + "fresh-theme-underscore": "^0.1.1", "grunt": "*", - "grunt-contrib-clean": "^0.7.0", - "grunt-contrib-jshint": "^0.11.3", - "grunt-contrib-yuidoc": "^0.10.0", + "grunt-contrib-clean": "^1.1.0", + "grunt-contrib-coffee": "^2.0.0", + "grunt-contrib-copy": "^1.0.0", + "grunt-eslint": "^20.1.0", "grunt-simple-mocha": "*", - "jane-q-fullstacker": "fluentdesk/jane-q-fullstacker", + "jsonresume-theme-boilerplate": "^0.1.2", + "jsonresume-theme-classy": "^1.0.9", + "jsonresume-theme-modern": "0.0.18", + "jsonresume-theme-sceptile": "^1.0.5", "mocha": "*", - "resample": "fluentdesk/resample" + "stripcolorcodes": "^0.1.0" } } diff --git a/src/cli/analyze.hbs b/src/cli/analyze.hbs new file mode 100644 index 00000000..124aa5c2 --- /dev/null +++ b/src/cli/analyze.hbs @@ -0,0 +1,30 @@ + +{{style "SECTIONS (" "bold"}}{{style totals.numSections "white" }}{{style ")" "bold"}} + + employment: {{v totals.totals.employment "-" 2 "bold" }} + projects: {{v totals.totals.projects "-" 2 "bold" }} + education: {{v totals.totals.education "-" 2 "bold" }} + service: {{v totals.totals.service "-" 2 "bold" }} + skills: {{v totals.totals.skills "-" 2 "bold" }} + writing: {{v totals.totals.writing "-" 2 "bold" }} + speaking: {{v totals.totals.speaking "-" 2 "bold" }} + reading: {{v totals.totals.reading "-" 2 "bold" }} + social: {{v totals.totals.social "-" 2 "bold" }} + references: {{v totals.totals.references "-" 2 "bold" }} + testimonials: {{v totals.totals.testimonials "-" 2 "bold" }} + languages: {{v totals.totals.languages "-" 2 "bold" }} + interests: {{v totals.totals.interests "-" 2 "bold" }} + +{{style "COVERAGE (" "bold"}}{{style coverage.pct "white"}}{{style ")" "bold"}} + + Total Days: {{v coverage.duration.total "-" 5 "bold" }} + Employed: {{v coverage.duration.work "-" 5 "bold" }} + Gaps: {{v coverage.gaps.length "-" 5 "bold" }} [{{#if coverage.gaps.length }}{{#each coverage.gaps }}{{#unless @first}} {{/unless}}{{gapLength duration }}{{/each}}{{/if}}] + Overlaps: {{v coverage.overlaps.length "-" 5 "bold" }} [{{#if coverage.overlaps.length }}{{#each coverage.overlaps }}{{#unless @first}} {{/unless}}{{gapLength duration }}{{/each}}{{/if}}] + +{{style "KEYWORDS (" "bold"}}{{style keywords.length "white" }}{{style ")" "bold"}} + +{{#each keywords }}{{{pad name 18}}}: {{v count "-" 5 "bold"}} mention{{#isPlural count}}s{{/isPlural}} +{{/each}} + ------------------------------- +{{v keywords.length "0" 9 "bold"}} {{style "KEYWORDS" "bold"}} {{v keywords.totalKeywords "0" 5 "bold"}} {{style "mentions" "bold"}} diff --git a/src/cli/error.js b/src/cli/error.js new file mode 100644 index 00000000..bea97c45 --- /dev/null +++ b/src/cli/error.js @@ -0,0 +1,328 @@ +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +/** +Error-handling routines for HackMyResume. +@module cli/error +@license MIT. See LICENSE.md for details. +*/ + + + +const HMSTATUS = require('../core/status-codes'); +const FS = require('fs'); +const PATH = require('path'); +const WRAP = require('word-wrap'); +const M2C = require('../utils/md2chalk'); +const chalk = require('chalk'); +const extend = require('extend'); +const printf = require('printf'); +const SyntaxErrorEx = require('../utils/syntax-error-ex'); +require('string.prototype.startswith'); + + + +/** Error handler for HackMyResume. All errors are handled here. +@class ErrorHandler */ +module.exports = { + + init( debug, assert, silent ) { + this.debug = debug; + this.assert = assert; + this.silent = silent; + this.msgs = require('./msg').errors; + return this; + }, + + err( ex, shouldExit ) { + + // Short-circuit logging output if --silent is on + let stack; + const o = this.silent ? function() {} : _defaultLog; + + // Special case; can probably be removed. + if (ex.pass) { throw ex; } + + // Load error messages + this.msgs = this.msgs || require('./msg').errors; + + // Handle packaged HMR exceptions + if (ex.fluenterror) { + + // Output the error message + const objError = assembleError.call(this, ex); + o( this[ `format_${objError.etype}` ]( objError.msg )); + + // Output the stack (sometimes) + if (objError.withStack) { + stack = ex.stack || (ex.inner && ex.inner.stack); + stack && o( chalk.gray( stack ) ); + } + + // Quit if necessary + if (shouldExit || ex.exit) { + if (this.debug) { + o(chalk.cyan(`Exiting with error code ${ex.fluenterror.toString()}`)); + } + if (this.assert) { + ex.pass = true; + throw ex; + } + return process.exit(ex.fluenterror); + } + + // Handle raw exceptions + } else { + o(ex); + const stackTrace = ex.stack || (ex.inner && ex.inner.stack); + if (stackTrace && this.debug) { + return o(M2C(ex.stack || ex.inner.stack, 'gray')); + } + } + }, + + + + format_error( msg ) { + msg = msg || ''; + return chalk.red.bold( msg.toUpperCase().startsWith('ERROR:') ? msg : `Error: ${msg}` ); + }, + + + format_warning( brief, msg ) { + return chalk.yellow(brief) + chalk.yellow(msg || ''); + }, + + + format_custom( msg ) { return msg; } +}; + + +var _defaultLog = function() { return console.log.apply(console.log, arguments); }; // eslint-disable-line no-console + + + + +var assembleError = function( ex ) { + + let se; + let msg = ''; + let withStack = false; + let quit = false; + let etype = 'warning'; + if (this.debug) { withStack = true; } + + switch (ex.fluenterror) { + + case HMSTATUS.themeNotFound: + msg = printf( M2C( this.msgs.themeNotFound.msg, 'yellow' ), ex.data); + break; + + case HMSTATUS.copyCSS: + msg = M2C( this.msgs.copyCSS.msg, 'red' ); + quit = false; + break; + + case HMSTATUS.resumeNotFound: + //msg = M2C( this.msgs.resumeNotFound.msg, 'yellow' ); + msg += M2C(FS.readFileSync( + PATH.resolve(__dirname, `help/${ex.verb}.txt`), 'utf8' ), 'white', 'yellow'); + break; + + case HMSTATUS.missingCommand: + // msg = M2C( this.msgs.missingCommand.msg + " (", 'yellow'); + // msg += Object.keys( FCMD.verbs ).map( (v, idx, ar) -> + // return ( if idx == ar.length - 1 then chalk.yellow('or ') else '') + + // chalk.yellow.bold(v.toUpperCase()); + // ).join( chalk.yellow(', ')) + chalk.yellow(").\n\n"); + + msg += M2C(FS.readFileSync( + PATH.resolve(__dirname, 'help/use.txt'), 'utf8' ), 'white', 'yellow'); + break; + + case HMSTATUS.invalidCommand: + msg = printf( M2C( this.msgs.invalidCommand.msg, 'yellow'), ex.attempted ); + break; + + case HMSTATUS.resumeNotFoundAlt: + msg = M2C( this.msgs.resumeNotFoundAlt.msg, 'yellow' ); + break; + + case HMSTATUS.inputOutputParity: + msg = M2C( this.msgs.inputOutputParity.msg ); + break; + + case HMSTATUS.createNameMissing: + msg = M2C( this.msgs.createNameMissing.msg ); + break; + + case HMSTATUS.pdfGeneration: + msg = M2C( this.msgs.pdfGeneration.msg, 'bold' ); + if (ex.inner) { msg += chalk.red(`\n${ex.inner}`); } + quit = false; + etype = 'error'; + break; + + case HMSTATUS.invalid: + msg = M2C( this.msgs.invalid.msg, 'red' ); + etype = 'error'; + break; + + case HMSTATUS.generateError: + msg = (ex.inner && ex.inner.toString()) || ex; + quit = false; + etype = 'error'; + break; + + case HMSTATUS.fileSaveError: + msg = printf( M2C( this.msgs.fileSaveError.msg ), (ex.inner || ex).toString() ); + etype = 'error'; + quit = false; + break; + + case HMSTATUS.invalidFormat: + ex.data.forEach( function(d) { + return msg += printf( M2C( this.msgs.invalidFormat.msg, 'bold' ), + ex.theme.name.toUpperCase(), d.format.toUpperCase()); + } + , this); + break; + + case HMSTATUS.missingParam: + msg = printf(M2C( this.msgs.missingParam.msg ), ex.expected, ex.helper); + break; + + case HMSTATUS.invalidHelperUse: + msg = printf( M2C( this.msgs.invalidHelperUse.msg ), ex.helper ); + if (ex.error) { + msg += `\n--> ${assembleError.call( this, extend( true, {}, ex, {fluenterror: ex.error} )).msg}`; + } + //msg += printf( '\n--> ' + M2C( this.msgs.invalidParamCount.msg ), ex.expected ); + quit = false; + etype = 'warning'; + break; + + case HMSTATUS.notOnPath: + msg = printf( M2C(this.msgs.notOnPath.msg, 'bold'), ex.engine); + quit = false; + etype = 'error'; + break; + + case HMSTATUS.readError: + if (!ex.quiet) { + // eslint-disable-next-line no-console + console.error(printf( M2C(this.msgs.readError.msg, 'red'), ex.file)); + } + msg = ex.inner.toString(); + etype = 'error'; + break; + + case HMSTATUS.mixedMerge: + msg = M2C(this.msgs.mixedMerge.msg); + quit = false; + break; + + case HMSTATUS.invokeTemplate: + msg = M2C(this.msgs.invokeTemplate.msg, 'red'); + msg += M2C( `\n${WRAP(ex.inner.toString(), { width: 60, indent: ' ' })}`, 'gray' ); + etype = 'custom'; + break; + + case HMSTATUS.compileTemplate: + etype = 'error'; + break; + + case HMSTATUS.themeLoad: + msg = M2C( printf( this.msgs.themeLoad.msg, ex.attempted.toUpperCase() ), 'red'); + if (ex.inner && ex.inner.fluenterror) { + msg += M2C('\nError: ', 'red') + assembleError.call( this, ex.inner ).msg; + } + quit = true; + etype = 'custom'; + break; + + case HMSTATUS.parseError: + if (SyntaxErrorEx.is(ex.inner)) { + // eslint-disable-next-line no-console + console.error(printf( M2C(this.msgs.readError.msg, 'red'), ex.file )); + se = new SyntaxErrorEx(ex, ex.raw); + if ((se.line != null) && (se.col != null)) { + msg = printf(M2C( this.msgs.parseError.msg[0], 'red' ), se.line, se.col); + } else if (se.line != null) { + msg = printf(M2C( this.msgs.parseError.msg[1], 'red' ), se.line); + } else { + msg = M2C(this.msgs.parseError.msg[2], 'red'); + } + } else if (ex.inner && (ex.inner.line != null) && (ex.inner.col != null)) { + msg = printf( M2C( this.msgs.parseError.msg[0], 'red' ), ex.inner.line, ex.inner.col); + } else { + msg = ex; + } + etype = 'error'; + break; + + case HMSTATUS.createError: + // inner.code could be EPERM, EACCES, etc + msg = printf(M2C( this.msgs.createError.msg ), ex.inner.path); + etype = 'error'; + break; + + case HMSTATUS.validateError: + msg = printf(M2C( this.msgs.validateError.msg ), ex.inner.toString()); + etype = 'error'; + break; + + case HMSTATUS.invalidOptionsFile: + msg = M2C(this.msgs.invalidOptionsFile.msg[0]); + if (SyntaxErrorEx.is(ex.inner)) { + // eslint-disable-next-line no-console + console.error(printf( M2C(this.msgs.readError.msg, 'red'), ex.file )); + se = new SyntaxErrorEx(ex, ex.raw); + if ((se.line != null) && (se.col != null)) { + msg += printf(M2C( this.msgs.parseError.msg[0], 'red' ), se.line, se.col); + } else if (se.line != null) { + msg += printf(M2C( this.msgs.parseError.msg[1], 'red' ), se.line); + } else { + msg += M2C(this.msgs.parseError.msg[2], 'red'); + } + } else if (ex.inner && (ex.inner.line != null) && (ex.inner.col != null)) { + msg += printf( M2C( this.msgs.parseError.msg[0], 'red' ), ex.inner.line, ex.inner.col); + } else { + msg += ex; + } + msg += this.msgs.invalidOptionsFile.msg[1]; + etype = 'error'; + break; + + case HMSTATUS.optionsFileNotFound: + msg = M2C( this.msgs.optionsFileNotFound.msg ); + etype = 'error'; + break; + + case HMSTATUS.unknownSchema: + msg = M2C( this.msgs.unknownSchema.msg[0] ); + //msg += "\n" + M2C( @msgs.unknownSchema.msg[1], 'yellow' ) + etype = 'error'; + break; + + case HMSTATUS.themeHelperLoad: + msg = printf(M2C( this.msgs.themeHelperLoad.msg ), ex.glob); + etype = 'error'; + break; + + case HMSTATUS.invalidSchemaVersion: + msg = printf(M2C( this.msgs.invalidSchemaVersion.msg ), ex.data); + etype = 'error'; + break; + } + + return { + msg, // The error message to display + withStack, // Whether to include the stack + quit, + etype + }; +}; diff --git a/src/cli/help/analyze.txt b/src/cli/help/analyze.txt new file mode 100644 index 00000000..8e7187e0 --- /dev/null +++ b/src/cli/help/analyze.txt @@ -0,0 +1,25 @@ +**analyze** | Analyze a resume for statistical insight + +Usage: + + **hackmyresume ANALYZE ** + + The ANALYZE command evaluates the specified resume(s) for + coverage, duration, gaps, keywords, and other metrics. + + This command can be run against multiple resumes. Each + will be analyzed in turn. + +Parameters: + + **** + + Path to a FRESH or JRS resume. Multiple resumes can be + specified, separated by spaces. + + hackmyresume ANALYZE resume.json + hackmyresume ANALYZE r1.json r2.json r3.json + +Options: + + **None.** diff --git a/src/cli/help/build.txt b/src/cli/help/build.txt new file mode 100644 index 00000000..6a1d2288 --- /dev/null +++ b/src/cli/help/build.txt @@ -0,0 +1,69 @@ +**build** | Generate themed resumes in multiple formats + +Usage: + + **hackmyresume BUILD TO [--theme]** + **[--pdf] [--no-escape] [--private]** + + The BUILD command generates themed resumes and CVs in + multiple formats. Use it to create outbound resumes in + specific formats such HTML, MS Word, and PDF. + +Parameters: + + **** + + Path to a FRESH or JRS resume (*.json) containing your + resume data. Multiple resumes may be specified. + + If multiple resumes are specified, they will be merged + into a single resume prior to transformation. + + **** + + Path to the desired output resume. Multiple resumes + may be specified. The file extension will determine + the format. + + .all Generate all supported formats + .html HTML 5 + .doc MS Word + .pdf Adobe Acrobat PDF + .txt plain text + .md Markdown + .png PNG Image + .latex LaTeX + + Note: not all formats are supported by all themes! + Check the theme's documentation for details or use + the .all extension to build all available formats. + +Options: + + **--theme -t ** + + Path to a FRESH or JSON Resume theme OR the name of a + built-in theme. Valid theme names are 'modern', + 'positive', 'compact', 'awesome', and 'basis'. + + **--pdf -p ** + + Specify the PDF engine to use. Legal values are + 'none', 'wkhtmltopdf', 'phantom', or 'weasyprint'. + + **--no-escape** + + Disable escaping / encoding of resume data during + resume generation. Handlebars themes only. + + **--private** + + Include resume fields marked as private. + +Notes: + +The BUILD command can be run against multiple source as well +as multiple target resumes. If multiple source resumes are +provided, they will be merged into a single source resume +before generation. If multiple output resumes are provided, +each will be generated in turn. diff --git a/src/cli/help/convert.txt b/src/cli/help/convert.txt new file mode 100644 index 00000000..1a065d64 --- /dev/null +++ b/src/cli/help/convert.txt @@ -0,0 +1,33 @@ +**convert** | Convert resumes between FRESH and JRS formats + +Usage: + + **hackmyresume CONVERT TO [--format]** + + The CONVERT command converts one or more resume documents + between the FRESH Resume Schema and JSON Resume formats. + +Parameters: + + **** + + Path to a FRESH or JRS resume. Multiple resumes can be + specified. + + **** + + The path of the converted resume. Multiple resumes can + be specified, one per provided input resume. + +Options: + + **--format -f ** + + The desired format for the new resume(s). Valid values + are 'FRESH', 'JRS', or, to target the latest edge + version of the JSON Resume Schema, 'JRS@1'. + + If this parameter is omitted, the destination format + will be inferred from the source resume's format. If + the source format is FRESH, the destination format + will be JSON Resume, and vice-versa. diff --git a/src/cli/help/help.txt b/src/cli/help/help.txt new file mode 100644 index 00000000..9b11cf32 --- /dev/null +++ b/src/cli/help/help.txt @@ -0,0 +1,23 @@ +**help** | View help on a specific HackMyResume command + +Usage: + + **hackmyresume HELP []** + + The HELP command displays help information for a specific + HackMyResume command, including the HELP command itself. + +Parameters: + + **** + + The HackMyResume command to view help information for. + Must be BUILD, NEW, CONVERT, ANALYZE, VALIDATE, PEEK, + or HELP. + + hackmyresume help convert + hackmyresume help help + +Options: + + **None.** diff --git a/src/cli/help/new.txt b/src/cli/help/new.txt new file mode 100644 index 00000000..9487793e --- /dev/null +++ b/src/cli/help/new.txt @@ -0,0 +1,29 @@ +**new** | Create a new FRESH or JRS resume document + +Usage: + + **hackmyresume NEW [--format]** + + The NEW command generates a new resume document in FRESH + or JSON Resume format. This document can serve as an + official source of truth for your resume and career data + as well an input to tools like HackMyResume. + +Parameters: + + **** + + The filename (relative or absolute path) of the resume + to be created. Multiple resume paths can be specified, + and each will be created in turn. + + hackmyresume NEW resume.json + hackmyresume NEW r1.json foo/r2.json ../r3.json + +Options: + + **--format -f ** + + The desired format for the new resume(s). Valid values + are 'FRESH', 'JRS', or, to target the latest edge + version of the JSON Resume Schema, 'JRS@1'. diff --git a/src/cli/help/peek.txt b/src/cli/help/peek.txt new file mode 100644 index 00000000..81fe6acf --- /dev/null +++ b/src/cli/help/peek.txt @@ -0,0 +1,31 @@ +**peek** | View portions of a resume from the command line + +Usage: + + **hackmyresume PEEK ** + + The PEEK command displays a specific piece or part of the + resume without requiring the resume to be opened in an + editor. + +Parameters: + + **** + + Path to a FRESH or JRS resume. Multiple resumes can be + specified, separated by spaces. + + hackmyresume PEEK r1.json r2.json r3.json "employment.history[2]" + + **** + + The resume property or field to be displayed. Can be + any valid resume path, for example: + + education[0] + info.name + employment.history[3].start + +Options: + + **None.** diff --git a/src/cli/help/use.txt b/src/cli/help/use.txt new file mode 100644 index 00000000..8ece4fc1 --- /dev/null +++ b/src/cli/help/use.txt @@ -0,0 +1,70 @@ +**HackMyResume** | A Swiss Army knife for resumes and CVs + +Usage: + + **hackmyresume [--version] [--help] [--silent] [--debug]** + **[--options] [--no-colors] []** + +Commands: (type "hackmyresume help COMMAND" for details) + + **BUILD** Build your resume to the destination format(s). + **ANALYZE** Analyze your resume for keywords, gaps, and metrics. + **VALIDATE** Validate your resume for errors and typos. + **NEW** Create a new resume in FRESH or JSON Resume format. + **CONVERT** Convert your resume between FRESH and JSON Resume. + **PEEK** View a specific field or element on your resume. + **HELP** View help on a specific HackMyResume command. + +Common Tasks: + + Generate a resume in a specific format (HTML, Word, PDF, etc.) + + **hackmyresume build rez.json to out/rez.html** + **hackmyresume build rez.json to out/rez.doc** + **hackmyresume build rez.json to out/rez.pdf** + **hackmyresume build rez.json to out/rez.txt** + **hackmyresume build rez.json to out/rez.md** + **hackmyresume build rez.json to out/rez.png** + **hackmyresume build rez.json to out/rez.tex** + + Build a resume to ALL available formats: + + **hackmyresume build rez.json to out/rez.all** + + Build a resume with a specific theme: + + **hackmyresume build rez.json to out/rez.all -t themeName** + + Create a new empty resume: + + **hackmyresume new rez.json** + + Convert a resume between FRESH and JRS formats: + + **hackmyresume convert rez.json converted.json** + + Analyze a resume for important metrics + + **hackmyresume analyze rez.json** + + Find more resume themes: + + **https://www.npmjs.com/search?q=jsonresume-theme** + **https://www.npmjs.com/search?q=fresh-theme** + **https://github.com/fresh-standard/fresh-themes** + + Validate a resume's structure and syntax: + + **hackmyresume validate resume.json** + + View help on a specific command: + + **hackmyresume help [build|convert|new|analyze|validate|peek|help]** + + Submit a bug or request: + + **https://githut.com/hacksalot/HackMyResume/issues** + +HackMyResume is free and open source software published +under the MIT license. For more information, visit the +HackMyResume website or GitHub project page. diff --git a/src/cli/help/validate.txt b/src/cli/help/validate.txt new file mode 100644 index 00000000..9bc12896 --- /dev/null +++ b/src/cli/help/validate.txt @@ -0,0 +1,26 @@ +**validate** | Validate a resume for correctness + +Usage: + + **hackmyresume VALIDATE [--assert]** + + The VALIDATE command validates a FRESH or JRS document + against its governing schema, verifying that the resume + is correctly structured and formatted. + +Parameters: + + **** + + Path to a FRESH or JRS resume. Multiple resumes can be + specified. + + hackmyresume ANALYZE resume.json + hackmyresume ANALYZE r1.json r2.json r3.json + +Options: + + **--assert -a** + + Tell HackMyResume to return a non-zero process exit + code if a resume fails to validate. diff --git a/src/cli/index.js b/src/cli/index.js new file mode 100644 index 00000000..b6ce89fb --- /dev/null +++ b/src/cli/index.js @@ -0,0 +1,22 @@ +#! /usr/bin/env node + + + +/** +Command-line interface (CLI) for HackMyResume. +@license MIT. See LICENSE.md for details. +@module index.js +*/ + + + +try { + + require('./main')( process.argv ); + +} +catch( ex ) { + + require('./error').err( ex, true ); + +} diff --git a/src/cli/main.js b/src/cli/main.js new file mode 100644 index 00000000..9126b2a8 --- /dev/null +++ b/src/cli/main.js @@ -0,0 +1,421 @@ +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +/** +Definition of the `main` function. +@module cli/main +@license MIT. See LICENSE.md for details. +*/ + + + +const HMR = require('../index'); +const PKG = require('../../package.json'); +const FS = require('fs'); +const EXTEND = require('extend'); +const chalk = require('chalk'); +const PATH = require('path'); +const HMSTATUS = require('../core/status-codes'); +const safeLoadJSON = require('../utils/safe-json-loader'); +//StringUtils = require '../utils/string.js' +const _ = require('underscore'); +const OUTPUT = require('./out'); +const PAD = require('string-padding'); +const { Command } = require('commander'); +const M2C = require('../utils/md2chalk'); +const printf = require('printf'); +const _opts = { }; +const _title = chalk.white.bold(`\n*** HackMyResume v${PKG.version} ***`); +const _out = new OUTPUT( _opts ); +const _err = require('./error'); +let _exitCallback = null; + + + +/* +A callable implementation of the HackMyResume CLI. Encapsulates the command +line interface as a single method accepting a parameter array. +@alias module:cli/main.main +@param rawArgs {Array} An array of command-line parameters. Will either be +process.argv (in production) or custom parameters (in test). +*/ +module.exports = function( rawArgs, exitCallback ) { + + const initInfo = initialize( rawArgs, exitCallback ); + if (initInfo === null) { + return; + } + + const { args } = initInfo; + + // Create the top-level (application) command... + const program = new Command('hackmyresume') + .version(PKG.version) + .description(chalk.yellow.bold('*** HackMyResume ***')) + .option('-s --silent', 'Run in silent mode') + .option('--no-color', 'Disable colors') + .option('--color', 'Enable colors') + .option('-d --debug', 'Enable diagnostics', false) + .option('-a --assert', 'Treat warnings as errors', false) + .option('-v --version', 'Show the version') + .allowUnknownOption(); + program.jsonArgs = initInfo.options; + + // Create the NEW command + program + .command('new') + .arguments('') + .option('-f --format ', 'FRESH or JRS format', 'FRESH') + .alias('create') + .description('Create resume(s) in FRESH or JSON RESUME format.') + .action((function( sources ) { + execute.call( this, sources, [], this.opts(), logMsg); + }) + ); + + // Create the VALIDATE command + program + .command('validate') + .arguments('') + .description('Validate a resume in FRESH or JSON RESUME format.') + .action(function(sources) { + execute.call( this, sources, [], this.opts(), logMsg); + }); + + // Create the CONVERT command + program + .command('convert') + .description('Convert a resume to/from FRESH or JSON RESUME format.') + .option('-f --format ', 'FRESH or JRS format and optional version', undefined) + .action(function() { + const x = splitSrcDest.call( this ); + execute.call( this, x.src, x.dst, this.opts(), logMsg); + }); + + // Create the ANALYZE command + program + .command('analyze') + .arguments('') + .option('--private', 'Include resume fields marked as private', false) + .description('Analyze one or more resumes.') + .action(function( sources ) { + execute.call( this, sources, [], this.opts(), logMsg); + }); + + // Create the PEEK command + program + .command('peek') + .arguments('') + .description('Peek at a resume field or section') + //.action(( sources, sectionOrField ) -> + .action(function( sources ) { + const dst = (sources && (sources.length > 1)) ? [sources.pop()] : []; + execute.call( this, sources, dst, this.opts(), logMsg); + }); + + // Create the BUILD command + program + .command('build') + .alias('generate') + .option('-t --theme ', 'Theme name or path') + .option('-n --no-prettify', 'Disable HTML prettification', true) + .option('-c --css