mirror of
				https://github.com/JuanCanham/HackMyResume.git
				synced 2025-11-03 22:37:27 +00:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			v1.9.0-bet
			...
			juan-canha
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					901659cc4f | 
@@ -1,17 +0,0 @@
 | 
				
			|||||||
env:
 | 
					 | 
				
			||||||
  es6: true
 | 
					 | 
				
			||||||
  node: true
 | 
					 | 
				
			||||||
extends: 'eslint:recommended'
 | 
					 | 
				
			||||||
rules:
 | 
					 | 
				
			||||||
  # indent:
 | 
					 | 
				
			||||||
  #   - error
 | 
					 | 
				
			||||||
  #   - 4
 | 
					 | 
				
			||||||
  linebreak-style:
 | 
					 | 
				
			||||||
    - error
 | 
					 | 
				
			||||||
    - unix
 | 
					 | 
				
			||||||
  quotes:
 | 
					 | 
				
			||||||
    - error
 | 
					 | 
				
			||||||
    - single
 | 
					 | 
				
			||||||
  semi:
 | 
					 | 
				
			||||||
    - error
 | 
					 | 
				
			||||||
    - always
 | 
					 | 
				
			||||||
							
								
								
									
										6
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							@@ -1,11 +1,9 @@
 | 
				
			|||||||
# Auto detect text files and perform LF normalization
 | 
					# Auto detect text files and perform LF normalization
 | 
				
			||||||
 | 
					 | 
				
			||||||
* text=auto
 | 
					* text=auto
 | 
				
			||||||
*.js text eol=lf
 | 
					*.js text eol=lf
 | 
				
			||||||
*.json text eol=lf
 | 
					*.json text eol=lf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Standard to msysgit
 | 
					# Standard to msysgit
 | 
				
			||||||
 | 
					 | 
				
			||||||
*.doc	 diff=astextplain
 | 
					*.doc	 diff=astextplain
 | 
				
			||||||
*.DOC	 diff=astextplain
 | 
					*.DOC	 diff=astextplain
 | 
				
			||||||
*.docx diff=astextplain
 | 
					*.docx diff=astextplain
 | 
				
			||||||
@@ -16,7 +14,3 @@
 | 
				
			|||||||
*.PDF	 diff=astextplain
 | 
					*.PDF	 diff=astextplain
 | 
				
			||||||
*.rtf	 diff=astextplain
 | 
					*.rtf	 diff=astextplain
 | 
				
			||||||
*.RTF	 diff=astextplain
 | 
					*.RTF	 diff=astextplain
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Git LFS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
*.ai filter=lfs diff=lfs merge=lfs -text
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,5 @@
 | 
				
			|||||||
node_modules/
 | 
					node_modules/
 | 
				
			||||||
 | 
					tests/sandbox/
 | 
				
			||||||
doc/
 | 
					doc/
 | 
				
			||||||
docs/
 | 
					docs/
 | 
				
			||||||
local/
 | 
					local/
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,12 +3,5 @@ assets/
 | 
				
			|||||||
test/
 | 
					test/
 | 
				
			||||||
doc/
 | 
					doc/
 | 
				
			||||||
.travis.yml
 | 
					.travis.yml
 | 
				
			||||||
.eslintrc.yml
 | 
					 | 
				
			||||||
Gruntfile.js
 | 
					Gruntfile.js
 | 
				
			||||||
.gitattributes
 | 
					.gitattributes
 | 
				
			||||||
ROADMAP.md
 | 
					 | 
				
			||||||
BUILDING.md
 | 
					 | 
				
			||||||
CONTRIBUTING.md
 | 
					 | 
				
			||||||
CHANGELOG.md
 | 
					 | 
				
			||||||
FAQ.md
 | 
					 | 
				
			||||||
*.map
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								.travis.yml
									
									
									
									
									
								
							@@ -1,23 +1,9 @@
 | 
				
			|||||||
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
 | 
					language: node_js
 | 
				
			||||||
node_js:
 | 
					node_js:
 | 
				
			||||||
  - "6"
 | 
					  - "0.10"
 | 
				
			||||||
  - "7"
 | 
					  - "0.11"
 | 
				
			||||||
  - "8"
 | 
					  - "0.12"
 | 
				
			||||||
  - "9"
 | 
					  - "4.0"
 | 
				
			||||||
  - "lts/*"
 | 
					  - "4.1"
 | 
				
			||||||
 | 
					  - "4.2"
 | 
				
			||||||
 | 
					  - "5.0"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										96
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -1,96 +1,5 @@
 | 
				
			|||||||
CHANGELOG
 | 
					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
 | 
					## v1.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Added
 | 
					### Added
 | 
				
			||||||
@@ -496,8 +405,7 @@ theme.
 | 
				
			|||||||
[i92]: https://github.com/hacksalot/HackMyResume/issues/92
 | 
					[i92]: https://github.com/hacksalot/HackMyResume/issues/92
 | 
				
			||||||
[i101]: https://github.com/hacksalot/HackMyResume/issues/101
 | 
					[i101]: https://github.com/hacksalot/HackMyResume/issues/101
 | 
				
			||||||
[i111]: https://github.com/hacksalot/HackMyResume/issues/111
 | 
					[i111]: https://github.com/hacksalot/HackMyResume/issues/111
 | 
				
			||||||
[fresca]: https://github.com/fresh-standard/fresh-resume-schema
 | 
					[fresca]: https://github.com/fluentdesk/FRESCA
 | 
				
			||||||
[themes]: https://github.com/fresh-standard/fresh-themes
 | 
					[themes]: https://github.com/fluentdesk/fresh-themes
 | 
				
			||||||
[awefork]: https://github.com/fluentdesk/Awesome-CV
 | 
					[awefork]: https://github.com/fluentdesk/Awesome-CV
 | 
				
			||||||
[acv]: https://github.com/posquit0/Awesome-CV
 | 
					[acv]: https://github.com/posquit0/Awesome-CV
 | 
				
			||||||
[ftt]: https://github.com/fresh-standard/fresh-test-themes
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,7 +33,7 @@ HackMyResume is currently maintained by [hacksalot][ha] with assistance from
 | 
				
			|||||||
or internal inquiries to:
 | 
					or internal inquiries to:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
admin@fluentdesk.com
 | 
					admin@hackmyresume.com
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can reach hacksalot directly at:
 | 
					You can reach hacksalot directly at:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										56
									
								
								Gruntfile.js
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								Gruntfile.js
									
									
									
									
									
								
							@@ -39,13 +39,41 @@ module.exports = function (grunt) {
 | 
				
			|||||||
      all: { src: ['test/*.js'] }
 | 
					      all: { src: ['test/*.js'] }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    jsdoc : {
 | 
				
			||||||
 | 
					      dist : {
 | 
				
			||||||
 | 
					        src: ['src/**/*.js'],
 | 
				
			||||||
 | 
					        options: {
 | 
				
			||||||
 | 
					          private: true,
 | 
				
			||||||
 | 
					          destination: 'doc'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    clean: {
 | 
					    clean: {
 | 
				
			||||||
      test: ['test/sandbox'],
 | 
					      test: ['test/sandbox'],
 | 
				
			||||||
      dist: ['dist']
 | 
					      dist: ['dist']
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    eslint: {
 | 
					    yuidoc: {
 | 
				
			||||||
      target: ['Gruntfile.js', 'dist/cli/**/*.js', 'test/*.js']
 | 
					      compile: {
 | 
				
			||||||
 | 
					        name: '<%= pkg.name %>',
 | 
				
			||||||
 | 
					        description: '<%= pkg.description %>',
 | 
				
			||||||
 | 
					        version: '<%= pkg.version %>',
 | 
				
			||||||
 | 
					        url: '<%= pkg.homepage %>',
 | 
				
			||||||
 | 
					        options: {
 | 
				
			||||||
 | 
					          paths: 'src/',
 | 
				
			||||||
 | 
					          outdir: 'docs/'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    jshint: {
 | 
				
			||||||
 | 
					      options: {
 | 
				
			||||||
 | 
					        laxcomma: true,
 | 
				
			||||||
 | 
					        expr: true,
 | 
				
			||||||
 | 
					        eqnull: true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      all: ['Gruntfile.js', 'dist/cli/**/*.js', 'test/*.js']
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
@@ -54,22 +82,28 @@ module.exports = function (grunt) {
 | 
				
			|||||||
  grunt.loadNpmTasks('grunt-contrib-coffee');
 | 
					  grunt.loadNpmTasks('grunt-contrib-coffee');
 | 
				
			||||||
  grunt.loadNpmTasks('grunt-contrib-copy');
 | 
					  grunt.loadNpmTasks('grunt-contrib-copy');
 | 
				
			||||||
  grunt.loadNpmTasks('grunt-simple-mocha');
 | 
					  grunt.loadNpmTasks('grunt-simple-mocha');
 | 
				
			||||||
  grunt.loadNpmTasks('grunt-eslint');
 | 
					  grunt.loadNpmTasks('grunt-contrib-yuidoc');
 | 
				
			||||||
 | 
					  grunt.loadNpmTasks('grunt-jsdoc');
 | 
				
			||||||
 | 
					  grunt.loadNpmTasks('grunt-contrib-jshint');
 | 
				
			||||||
  grunt.loadNpmTasks('grunt-contrib-clean');
 | 
					  grunt.loadNpmTasks('grunt-contrib-clean');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Use 'grunt test' for local testing
 | 
					  // Use 'grunt test' for local testing
 | 
				
			||||||
  grunt.registerTask('test', 'Test the HackMyResume application.',
 | 
					  grunt.registerTask('test', 'Test the HackMyResume application.',
 | 
				
			||||||
    function() {
 | 
					    function( config ) {
 | 
				
			||||||
      grunt.task.run(['clean:test','build','eslint','simplemocha:all']);
 | 
					      grunt.task.run(['clean:test','build','jshint','simplemocha:all']);
 | 
				
			||||||
    }
 | 
					    });
 | 
				
			||||||
  );
 | 
					
 | 
				
			||||||
 | 
					  // Use 'grunt document' to build docs
 | 
				
			||||||
 | 
					  grunt.registerTask('document', 'Generate HackMyResume documentation.',
 | 
				
			||||||
 | 
					    function( config ) {
 | 
				
			||||||
 | 
					      grunt.task.run( ['jsdoc'] );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Use 'grunt build' to build HMR
 | 
					  // Use 'grunt build' to build HMR
 | 
				
			||||||
  grunt.registerTask('build', 'Build the HackMyResume application.',
 | 
					  grunt.registerTask('build', 'Build the HackMyResume application.',
 | 
				
			||||||
    function() {
 | 
					    function( config ) {
 | 
				
			||||||
      grunt.task.run( ['clean:dist','copy','coffee','eslint'] );
 | 
					      grunt.task.run( ['clean:dist','copy','coffee'] );
 | 
				
			||||||
    }
 | 
					    });
 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Default task does everything
 | 
					  // Default task does everything
 | 
				
			||||||
  grunt.registerTask('default', [ 'test', 'document' ]);
 | 
					  grunt.registerTask('default', [ 'test', 'document' ]);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
The MIT License
 | 
					The MIT License
 | 
				
			||||||
===============
 | 
					===============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Copyright (c) 2015-2018 hacksalot (https://github.com/hacksalot)
 | 
					Copyright (c) 2015-2016 hacksalot (https://github.com/hacksalot)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
of this software and associated documentation files (the "Software"), to deal
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										219
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										219
									
								
								README.md
									
									
									
									
									
								
							@@ -1,17 +1,17 @@
 | 
				
			|||||||
HackMyResume
 | 
					HackMyResume
 | 
				
			||||||
===
 | 
					============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[![Latest release][img-release]][latest-release]
 | 
					[![Latest release][img-release]][latest-release]
 | 
				
			||||||
[![Build status (MASTER)][img-master]][travis-url-master]
 | 
					[![Build status (MASTER)][img-master]][travis-url-master]
 | 
				
			||||||
[![Build status (DEV)][img-dev]][travis-url-dev]
 | 
					[![Build status (DEV)][img-dev]][travis-url-dev]
 | 
				
			||||||
[![Join the chat at https://gitter.im/hacksalot/HackMyResume][badge]][gh]
 | 
					[](https://gitter.im/hacksalot/HackMyResume?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
*Create polished résumés and CVs in multiple formats from your command line or
 | 
					*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,
 | 
					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
 | 
					plain text, and other arbitrary formats. Fight the power, save trees. Compatible
 | 
				
			||||||
with [FRESH][fresca] and [JRS][6] resumes.*
 | 
					with [FRESH][fresca] and [JRS][6] resumes.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||

 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HackMyResume is a dev-friendly, local-only Swiss Army knife for resumes and CVs.
 | 
					HackMyResume is a dev-friendly, local-only Swiss Army knife for resumes and CVs.
 | 
				
			||||||
Use it to:
 | 
					Use it to:
 | 
				
			||||||
@@ -27,8 +27,6 @@ metrics.
 | 
				
			|||||||
HackMyResume is built with Node.js and runs on recent versions of OS X, Linux,
 | 
					HackMyResume is built with Node.js and runs on recent versions of OS X, Linux,
 | 
				
			||||||
or Windows. View the [FAQ](FAQ.md).
 | 
					or Windows. View the [FAQ](FAQ.md).
 | 
				
			||||||
 | 
					
 | 
				
			||||||

 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Features
 | 
					## Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- OS X, Linux, and Windows.
 | 
					- OS X, Linux, and Windows.
 | 
				
			||||||
@@ -64,9 +62,9 @@ Alternately, install the latest bleeding-edge version (updated daily):
 | 
				
			|||||||
HackMyResume tries not to impose a specific PDF engine requirement on
 | 
					HackMyResume tries not to impose a specific PDF engine requirement on
 | 
				
			||||||
the user, but will instead work with whatever PDF engines you have installed.
 | 
					the user, but will instead work with whatever PDF engines you have installed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Currently, HackMyResume's PDF generation requires one of [Phantom.js][2],
 | 
					Currently, HackMyResume's PDF generation requires either [Phantom.js][2] or
 | 
				
			||||||
[wkhtmltopdf][3], or [WeasyPrint][11] to be installed on your system and the
 | 
					[wkhtmltopdf][3] to be installed on your system and the `phantomjs` and/or
 | 
				
			||||||
corresponding binary to be accessible on your PATH. This is an optional
 | 
					`wkhtmltopdf` binaries 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
 | 
					requirement for users who care about PDF formats. If you don't care about PDF
 | 
				
			||||||
formats, skip this step.
 | 
					formats, skip this step.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -93,7 +91,7 @@ Then when you're ready to generate your resume, just reference the location of
 | 
				
			|||||||
the theme folder as you installed it:
 | 
					the theme folder as you installed it:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume build resume.json TO out/resume.all -t node_modules/jsonresume-theme-classy
 | 
					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
 | 
					Note: You can use install themes anywhere on your file system. You don't need a
 | 
				
			||||||
@@ -110,26 +108,26 @@ Use it when you need to submit, upload, print, or email resumes in specific
 | 
				
			|||||||
formats.
 | 
					formats.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ```bash
 | 
					    ```bash
 | 
				
			||||||
    # hackmyresume build <INPUTS...> TO <OUTPUTS...> [-t THEME]
 | 
					    # hackmyresume BUILD <INPUTS...> TO <OUTPUTS...> [-t THEME]
 | 
				
			||||||
    hackmyresume build resume.json TO out/resume.all
 | 
					    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 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.
 | 
					- **new** creates a new resume in FRESH or JSON Resume format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ```bash
 | 
					    ```bash
 | 
				
			||||||
    # hackmyresume new <OUTPUTS...> [-f <FORMAT>]
 | 
					    # hackmyresume NEW <OUTPUTS...> [-f <FORMAT>]
 | 
				
			||||||
    hackmyresume new resume.json
 | 
					    hackmyresume NEW resume.json
 | 
				
			||||||
    hackmyresume new resume.json -f fresh
 | 
					    hackmyresume NEW resume.json -f fresh
 | 
				
			||||||
    hackmyresume new r1.json r2.json -f jrs
 | 
					    hackmyresume NEW r1.json r2.json -f jrs
 | 
				
			||||||
    ```
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- **analyze** inspects your resume for keywords, duration, and other metrics.
 | 
					- **analyze** inspects your resume for keywords, duration, and other metrics.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ```bash
 | 
					    ```bash
 | 
				
			||||||
    # hackmyresume analyze <INPUTS...>
 | 
					    # hackmyresume ANALYZE <INPUTS...>
 | 
				
			||||||
    hackmyresume analyze resume.json
 | 
					    hackmyresume ANALYZE resume.json
 | 
				
			||||||
    hackmyresume analyze r1.json r2.json
 | 
					    hackmyresume ANALYZE r1.json r2.json
 | 
				
			||||||
    ```
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- **convert** converts your source resume between FRESH and JSON Resume
 | 
					- **convert** converts your source resume between FRESH and JSON Resume
 | 
				
			||||||
@@ -137,29 +135,29 @@ formats. Use it to convert between the two formats to take advantage of tools
 | 
				
			|||||||
and services.
 | 
					and services.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ```bash
 | 
					    ```bash
 | 
				
			||||||
    # hackmyresume convert <INPUTS...> TO <OUTPUTS...>
 | 
					    # hackmyresume CONVERT <INPUTS...> TO <OUTPUTS...>
 | 
				
			||||||
    hackmyresume convert resume.json TO resume-jrs.json
 | 
					    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 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
 | 
					- **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.
 | 
					Resume schema. Use it to make sure your resume data is sufficient and complete.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ```bash
 | 
					    ```bash
 | 
				
			||||||
    # hackmyresume validate <INPUTS...>
 | 
					    # hackmyresume VALIDATE <INPUTS...>
 | 
				
			||||||
    hackmyresume validate resume.json
 | 
					    hackmyresume VALIDATE resume.json
 | 
				
			||||||
    hackmyresume validate r1.json r2.json r3.json
 | 
					    hackmyresume VALIDATE r1.json r2.json r3.json
 | 
				
			||||||
    ```
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- **peek** echoes your resume or any field, property, or object path on your
 | 
					- **peek** echoes your resume or any field, property, or object path on your
 | 
				
			||||||
resume to standard output.
 | 
					resume to standard output.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ```bash
 | 
					    ```bash
 | 
				
			||||||
    # hackmyresume peek <INPUTS...> [OBJECT-PATH]
 | 
					    # hackmyresume PEEK <INPUTS...> [OBJECT-PATH]
 | 
				
			||||||
    hackmyresume peek rez.json # Echo the whole resume
 | 
					    hackmyresume PEEK rez.json # Echo the whole resume
 | 
				
			||||||
    hackmyresume peek rez.json info.brief # Echo the "info.brief" field
 | 
					    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 employment.history[1] # Echo the 1st job
 | 
				
			||||||
    hackmyresume peek rez.json rez2.json info.brief # Compare value
 | 
					    hackmyresume PEEK rez.json rez2.json info.brief # Compare value
 | 
				
			||||||
    ```    
 | 
					    ```    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Supported Output Formats
 | 
					## Supported Output Formats
 | 
				
			||||||
@@ -186,7 +184,7 @@ Assuming you've got a JSON-formatted resume handy, generating resumes in
 | 
				
			|||||||
different formats and combinations is easy. Just run:
 | 
					different formats and combinations is easy. Just run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume build <inputs> to <outputs> [-t theme].
 | 
					hackmyresume BUILD <INPUTS> <OUTPUTS> [-t theme].
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Where `<INPUTS>` is one or more .json resume files, separated by spaces;
 | 
					Where `<INPUTS>` is one or more .json resume files, separated by spaces;
 | 
				
			||||||
@@ -195,19 +193,19 @@ theme (default to Modern). For example:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# Generate all resume formats (HTML, PDF, DOC, TXT, YML, etc.)
 | 
					# Generate all resume formats (HTML, PDF, DOC, TXT, YML, etc.)
 | 
				
			||||||
hackmyresume build resume.json TO out/resume.all -t modern
 | 
					hackmyresume BUILD resume.json TO out/resume.all -t modern
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Generate a specific resume format
 | 
					# Generate a specific resume format
 | 
				
			||||||
hackmyresume build resume.json TO out/resume.html
 | 
					hackmyresume BUILD resume.json TO out/resume.html
 | 
				
			||||||
hackmyresume build resume.json TO out/resume.pdf
 | 
					hackmyresume BUILD resume.json TO out/resume.pdf
 | 
				
			||||||
hackmyresume build resume.json TO out/resume.md
 | 
					hackmyresume BUILD resume.json TO out/resume.md
 | 
				
			||||||
hackmyresume build resume.json TO out/resume.doc
 | 
					hackmyresume BUILD resume.json TO out/resume.doc
 | 
				
			||||||
hackmyresume build resume.json TO out/resume.json
 | 
					hackmyresume BUILD resume.json TO out/resume.json
 | 
				
			||||||
hackmyresume build resume.json TO out/resume.txt
 | 
					hackmyresume BUILD resume.json TO out/resume.txt
 | 
				
			||||||
hackmyresume build resume.json TO out/resume.yml
 | 
					hackmyresume BUILD resume.json TO out/resume.yml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Specify 2 inputs and 3 outputs
 | 
					# Specify 2 inputs and 3 outputs
 | 
				
			||||||
hackmyresume build in1.json in2.json TO out.html out.doc out.pdf
 | 
					hackmyresume BUILD in1.json in2.json TO out.html out.doc out.pdf
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You should see something to the effect of:
 | 
					You should see something to the effect of:
 | 
				
			||||||
@@ -234,16 +232,16 @@ installed first). To specify a theme when generating your resume, use the `-t`
 | 
				
			|||||||
or `--theme` parameter:
 | 
					or `--theme` parameter:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume build resume.json TO out/rez.all -t [theme]
 | 
					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
 | 
					The `[theme]` parameter can be the name of a predefined theme OR the path to any
 | 
				
			||||||
FRESH or JSON Resume theme folder:
 | 
					FRESH or JSON Resume theme folder:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume build resume.json TO out/rez.all -t modern
 | 
					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 ../some-folder/my-custom-theme/
 | 
				
			||||||
hackmyresume build resume.json TO OUT.rez.all -t node_modules/jsonresume-theme-classy
 | 
					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
 | 
					FRESH themes are currently pre-installed with HackMyResume. JSON Resume themes
 | 
				
			||||||
@@ -267,7 +265,7 @@ most generic to most specific:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# Merge specific.json onto base.json and generate all formats
 | 
					# Merge specific.json onto base.json and generate all formats
 | 
				
			||||||
hackmyresume build base.json specific.json TO resume.all
 | 
					hackmyresume BUILD base.json specific.json TO resume.all
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This can be useful for overriding a base (generic) resume with information from
 | 
					This can be useful for overriding a base (generic) resume with information from
 | 
				
			||||||
@@ -278,7 +276,7 @@ resume. Merging follows conventional [extend()][9]-style behavior and there's
 | 
				
			|||||||
no arbitrary limit to how many resumes you can merge:
 | 
					no arbitrary limit to how many resumes you can merge:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume build in1.json in2.json in3.json in4.json TO out.html out.doc
 | 
					hackmyresume BUILD in1.json in2.json in3.json in4.json TO out.html out.doc
 | 
				
			||||||
Reading JSON resume: in1.json
 | 
					Reading JSON resume: in1.json
 | 
				
			||||||
Reading JSON resume: in2.json
 | 
					Reading JSON resume: in2.json
 | 
				
			||||||
Reading JSON resume: in3.json
 | 
					Reading JSON resume: in3.json
 | 
				
			||||||
@@ -294,7 +292,7 @@ You can specify **multiple output targets** and HackMyResume will build them:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# Generate out1.doc, out1.pdf, and foo.txt from me.json.
 | 
					# Generate out1.doc, out1.pdf, and foo.txt from me.json.
 | 
				
			||||||
hackmyresume build me.json TO out1.doc out1.pdf foo.txt
 | 
					hackmyresume BUILD me.json TO out1.doc out1.pdf foo.txt
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Using .all
 | 
					### Using .all
 | 
				
			||||||
@@ -304,7 +302,7 @@ formats for the given resume. For example, this...
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# Generate all resume formats (HTML, PDF, DOC, TXT, etc.)
 | 
					# Generate all resume formats (HTML, PDF, DOC, TXT, etc.)
 | 
				
			||||||
hackmyresume build me.json TO out/resume.all
 | 
					hackmyresume BUILD me.json TO out/resume.all
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
..tells HackMyResume to read `me.json` and generate `out/resume.md`,
 | 
					..tells HackMyResume to read `me.json` and generate `out/resume.md`,
 | 
				
			||||||
@@ -319,21 +317,19 @@ and formats with the `--pdf none` switch.*
 | 
				
			|||||||
HackMyResume takes a unique approach to PDF generation. Instead of enforcing
 | 
					HackMyResume takes a unique approach to PDF generation. Instead of enforcing
 | 
				
			||||||
a specific PDF engine on users, HackMyResume will attempt to work with whatever
 | 
					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).
 | 
					PDF engine you have installed through the engine's command-line interface (CLI).
 | 
				
			||||||
Currently that means any of...
 | 
					Currently that means one or both of...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [wkhtmltopdf][3]
 | 
					- [wkhtmltopdf][3]
 | 
				
			||||||
- [Phantom.js][2]
 | 
					- [Phantom.js][3]
 | 
				
			||||||
- [WeasyPrint][11]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
..with support for other engines planned in the future. But for now, **one or
 | 
					..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
 | 
					both of these engines must be installed and accessible on your PATH in order to
 | 
				
			||||||
to generate PDF resumes with HackMyResume**. That means you should be able 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:
 | 
					invoke either of these tools directly from your shell or terminal without error:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
wkhtmltopdf input.html output.pdf
 | 
					wkhtmltopdf input.html output.pdf
 | 
				
			||||||
phantomjs script.js 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
 | 
					Assuming you've installed one or both of these engines on your system, you can
 | 
				
			||||||
@@ -341,10 +337,9 @@ tell HackMyResume which flavor of PDF generation to use via the `--pdf` option
 | 
				
			|||||||
(`-p` for short):
 | 
					(`-p` for short):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume build resume.json TO out.all --pdf phantom
 | 
					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 wkhtmltopdf
 | 
				
			||||||
hackmyresume build resume.json TO out.all --pdf weasyprint
 | 
					hackmyresume BUILD resume.json TO out.all --pdf none
 | 
				
			||||||
hackmyresume build resume.json TO out.all --pdf none
 | 
					 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Analyzing
 | 
					### Analyzing
 | 
				
			||||||
@@ -353,7 +348,7 @@ HackMyResume can analyze your resume for keywords, employment gaps, and other
 | 
				
			|||||||
metrics. Run:
 | 
					metrics. Run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume analyze <my-resume>.json
 | 
					hackmyresume ANALYZE <my-resume>.json
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Depending on the HackMyResume version, you should see output similar to:
 | 
					Depending on the HackMyResume version, you should see output similar to:
 | 
				
			||||||
@@ -450,7 +445,7 @@ resumes, use the `validate` command:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# Validate myresume.json against either the FRESH or JSON Resume schema.
 | 
					# Validate myresume.json against either the FRESH or JSON Resume schema.
 | 
				
			||||||
hackmyresume validate resumeA.json resumeB.json
 | 
					hackmyresume VALIDATE resumeA.json resumeB.json
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HackMyResume will validate each specified resume in turn:
 | 
					HackMyResume will validate each specified resume in turn:
 | 
				
			||||||
@@ -467,7 +462,7 @@ HackMyResume can convert between the [FRESH][fresca] and [JSON Resume][6]
 | 
				
			|||||||
formats. Just run:
 | 
					formats. Just run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume convert <INPUTS> <OUTPUTS>
 | 
					hackmyresume CONVERT <INPUTS> <OUTPUTS>
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
where <INPUTS> is one or more resumes in FRESH or JSON Resume format, and
 | 
					where <INPUTS> is one or more resumes in FRESH or JSON Resume format, and
 | 
				
			||||||
@@ -481,34 +476,31 @@ You can pass options into HackMyResume via an external options or ".hackmyrc"
 | 
				
			|||||||
file with the `--options` or `-o` switch:
 | 
					file with the `--options` or `-o` switch:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume build resume.json -o path/to/options.json
 | 
					hackmyresume BUILD resume.json -o path/to/options.json
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The options file can contain any documented HackMyResume option, including
 | 
					The options file can contain any documented HackMyResume option, including
 | 
				
			||||||
`theme`, `silent`, `debug`, `pdf`, `css`, and other settings.
 | 
					`theme`, `silent`, `debug`, `pdf`, `css`, and other settings.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```json
 | 
					```javascript
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  // Set the default theme to "compact"
 | 
				
			||||||
  "theme": "compact",
 | 
					  "theme": "compact",
 | 
				
			||||||
 | 
					  // Change the "employment" section title text to "Work"
 | 
				
			||||||
  "sectionTitles": {
 | 
					  "sectionTitles": {
 | 
				
			||||||
    "employment": "Work"
 | 
					    "employment": "Work"
 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  "wkhtmltopdf": {
 | 
					 | 
				
			||||||
    "margin-top": "20mm"
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If an option is specified on both the command line and in an external options
 | 
					If a particular option is specified both on the command line and in an external
 | 
				
			||||||
file, the command-line option wins.
 | 
					options file, the explicit command-line option takes precedence.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# path/to/options.json specifes the POSITIVE theme
 | 
					# path/to/options.json specifes the POSITIVE theme
 | 
				
			||||||
# -t parameter specifies the COMPACT theme
 | 
					# -t parameter specifies the COMPACT theme
 | 
				
			||||||
# The -t parameter wins.
 | 
					# The -t parameter wins.
 | 
				
			||||||
hackmyresume build resume.json -o path/to/options.json -t compact
 | 
					hackmyresume BUILD resume.json -o path/to/options.json -t compact
 | 
				
			||||||
> Reading resume: resume.json
 | 
					> Reading resume: resume.json
 | 
				
			||||||
> Applying COMPACT theme (7 formats)
 | 
					> Applying COMPACT theme (7 formats)
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
@@ -520,7 +512,7 @@ HTML-formatted resumes. To disable prettification, the `--no-prettify` or `-n`
 | 
				
			|||||||
flag can be used:
 | 
					flag can be used:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume build resume.json out.all --no-prettify
 | 
					hackmyresume BUILD resume.json out.all --no-prettify
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Silent Mode
 | 
					### Silent Mode
 | 
				
			||||||
@@ -528,8 +520,8 @@ hackmyresume build resume.json out.all --no-prettify
 | 
				
			|||||||
Use `-s` or `--silent` to run in silent mode:
 | 
					Use `-s` or `--silent` to run in silent mode:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume build resume.json -o someFile.all -s
 | 
					hackmyresume BUILD resume.json -o someFile.all -s
 | 
				
			||||||
hackmyresume build resume.json -o someFile.all --silent
 | 
					hackmyresume BUILD resume.json -o someFile.all --silent
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Debug Mode
 | 
					### Debug Mode
 | 
				
			||||||
@@ -538,80 +530,15 @@ 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.
 | 
					the future, this option will emit detailed error logging.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
hackmyresume build resume.json -d
 | 
					hackmyresume BUILD resume.json -d
 | 
				
			||||||
hackmyresume analyze resume.json --debug
 | 
					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
 | 
					## Contributing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HackMyResume is a community-driven free and open source project under the MIT
 | 
					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
 | 
					License. Contributions are encouraged and we respond to all PRs and issues,
 | 
				
			||||||
time. See [CONTRIBUTING.md][contribute] for details.
 | 
					usually within 24 hours. See [CONTRIBUTING.md][contribute] for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## License
 | 
					## License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -627,9 +554,8 @@ MIT. Go crazy. See [LICENSE.md][1] for details.
 | 
				
			|||||||
[8]: https://youtu.be/N9wsjroVlu8
 | 
					[8]: https://youtu.be/N9wsjroVlu8
 | 
				
			||||||
[9]: https://api.jquery.com/jquery.extend/
 | 
					[9]: https://api.jquery.com/jquery.extend/
 | 
				
			||||||
[10]: https://github.com/beautify-web/js-beautify
 | 
					[10]: https://github.com/beautify-web/js-beautify
 | 
				
			||||||
[11]: http://weasyprint.org/
 | 
					 | 
				
			||||||
[fresh]: https://github.com/fluentdesk/FRESH
 | 
					[fresh]: https://github.com/fluentdesk/FRESH
 | 
				
			||||||
[fresca]: https://github.com/fresh-standard/fresh-resume-schema
 | 
					[fresca]: https://github.com/fluentdesk/FRESCA
 | 
				
			||||||
[dry]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
 | 
					[dry]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
 | 
				
			||||||
[img-release]: https://img.shields.io/github/release/hacksalot/HackMyResume.svg?label=version
 | 
					[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-master]: https://img.shields.io/travis/hacksalot/HackMyResume/master.svg
 | 
				
			||||||
@@ -640,6 +566,3 @@ MIT. Go crazy. See [LICENSE.md][1] for details.
 | 
				
			|||||||
[contribute]: CONTRIBUTING.md
 | 
					[contribute]: CONTRIBUTING.md
 | 
				
			||||||
[fresh-themes]: https://github.com/fluentdesk/fresh-themes
 | 
					[fresh-themes]: https://github.com/fluentdesk/fresh-themes
 | 
				
			||||||
[jrst]: https://www.npmjs.com/search?q=jsonresume-theme
 | 
					[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
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								assets/hackmyresume.cli.1.6.0.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/hackmyresume.cli.1.6.0.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 83 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/hackmyresume_cli.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/hackmyresume_cli.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 83 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 20 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 18 KiB  | 
@@ -1,3 +0,0 @@
 | 
				
			|||||||
version https://git-lfs.github.com/spec/v1
 | 
					 | 
				
			||||||
oid sha256:a476ee59e7d86b5a7599780b5efca57ee6b6d60e1a722343277057ea793703b6
 | 
					 | 
				
			||||||
size 1642116
 | 
					 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 39 KiB  | 
							
								
								
									
										97
									
								
								dist/cli/error.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										97
									
								
								dist/cli/error.js
									
									
									
									
										vendored
									
									
								
							@@ -1,15 +1,21 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Error-handling routines for HackMyResume.
 | 
				
			||||||
 | 
					@module cli/error
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var ErrorHandler, FCMD, FS, HMSTATUS, M2C, PATH, PKG, SyntaxErrorEx, WRAP, YAML, _defaultLog, assembleError, chalk, extend, printf;
 | 
				
			||||||
  Error-handling routines for HackMyResume.
 | 
					 | 
				
			||||||
  @module cli/error
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FS, HMSTATUS, M2C, PATH, SyntaxErrorEx, WRAP, _defaultLog, assembleError, chalk, extend, printf;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HMSTATUS = require('../core/status-codes');
 | 
					  HMSTATUS = require('../core/status-codes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  PKG = require('../../package.json');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FS = require('fs');
 | 
					  FS = require('fs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  FCMD = require('../index');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PATH = require('path');
 | 
					  PATH = require('path');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  WRAP = require('word-wrap');
 | 
					  WRAP = require('word-wrap');
 | 
				
			||||||
@@ -20,15 +26,20 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  extend = require('extend');
 | 
					  extend = require('extend');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  YAML = require('yamljs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  printf = require('printf');
 | 
					  printf = require('printf');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SyntaxErrorEx = require('../utils/syntax-error-ex');
 | 
					  SyntaxErrorEx = require('../utils/syntax-error-ex');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  require('string.prototype.startswith');
 | 
					  require('string.prototype.startswith');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Error handler for HackMyResume. All errors are handled here.
 | 
					  /** Error handler for HackMyResume. All errors are handled here.
 | 
				
			||||||
  @class ErrorHandler */
 | 
					  @class ErrorHandler
 | 
				
			||||||
  module.exports = {
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ErrorHandler = module.exports = {
 | 
				
			||||||
    init: function(debug, assert, silent) {
 | 
					    init: function(debug, assert, silent) {
 | 
				
			||||||
      this.debug = debug;
 | 
					      this.debug = debug;
 | 
				
			||||||
      this.assert = assert;
 | 
					      this.assert = assert;
 | 
				
			||||||
@@ -38,25 +49,19 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    err: function(ex, shouldExit) {
 | 
					    err: function(ex, shouldExit) {
 | 
				
			||||||
      var o, objError, stack, stackTrace;
 | 
					      var o, objError, stack, stackTrace;
 | 
				
			||||||
      // Short-circuit logging output if --silent is on
 | 
					 | 
				
			||||||
      o = this.silent ? function() {} : _defaultLog;
 | 
					      o = this.silent ? function() {} : _defaultLog;
 | 
				
			||||||
      if (ex.pass) {
 | 
					      if (ex.pass) {
 | 
				
			||||||
        // Special case; can probably be removed.
 | 
					 | 
				
			||||||
        throw ex;
 | 
					        throw ex;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // Load error messages
 | 
					 | 
				
			||||||
      this.msgs = this.msgs || require('./msg').errors;
 | 
					      this.msgs = this.msgs || require('./msg').errors;
 | 
				
			||||||
      // Handle packaged HMR exceptions
 | 
					 | 
				
			||||||
      if (ex.fluenterror) {
 | 
					      if (ex.fluenterror) {
 | 
				
			||||||
        // Output the error message
 | 
					 | 
				
			||||||
        objError = assembleError.call(this, ex);
 | 
					        objError = assembleError.call(this, ex);
 | 
				
			||||||
        o(this['format_' + objError.etype](objError.msg));
 | 
					        o(this['format_' + objError.etype](objError.msg));
 | 
				
			||||||
        // Output the stack (sometimes)
 | 
					 | 
				
			||||||
        if (objError.withStack) {
 | 
					        if (objError.withStack) {
 | 
				
			||||||
          stack = ex.stack || (ex.inner && ex.inner.stack);
 | 
					          stack = ex.stack || (ex.inner && ex.inner.stack);
 | 
				
			||||||
          stack && o(chalk.gray(stack));
 | 
					          stack && o(chalk.gray(stack));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (shouldExit || ex.exit) {
 | 
					        if (shouldExit) {
 | 
				
			||||||
          if (this.debug) {
 | 
					          if (this.debug) {
 | 
				
			||||||
            o(chalk.cyan('Exiting with error code ' + ex.fluenterror.toString()));
 | 
					            o(chalk.cyan('Exiting with error code ' + ex.fluenterror.toString()));
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@@ -67,7 +72,6 @@
 | 
				
			|||||||
          return process.exit(ex.fluenterror);
 | 
					          return process.exit(ex.fluenterror);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        // Handle raw exceptions
 | 
					 | 
				
			||||||
        o(ex);
 | 
					        o(ex);
 | 
				
			||||||
        stackTrace = ex.stack || (ex.inner && ex.inner.stack);
 | 
					        stackTrace = ex.stack || (ex.inner && ex.inner.stack);
 | 
				
			||||||
        if (stackTrace && this.debug) {
 | 
					        if (stackTrace && this.debug) {
 | 
				
			||||||
@@ -88,7 +92,7 @@
 | 
				
			|||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _defaultLog = function() {
 | 
					  _defaultLog = function() {
 | 
				
			||||||
    return console.log.apply(console.log, arguments); // eslint-disable-line no-console
 | 
					    return console.log.apply(console.log, arguments);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  assembleError = function(ex) {
 | 
					  assembleError = function(ex) {
 | 
				
			||||||
@@ -109,16 +113,14 @@
 | 
				
			|||||||
        quit = false;
 | 
					        quit = false;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case HMSTATUS.resumeNotFound:
 | 
					      case HMSTATUS.resumeNotFound:
 | 
				
			||||||
        //msg = M2C( this.msgs.resumeNotFound.msg, 'yellow' );
 | 
					        msg = M2C(this.msgs.resumeNotFound.msg, 'yellow');
 | 
				
			||||||
        msg += M2C(FS.readFileSync(PATH.resolve(__dirname, 'help/' + ex.verb + '.txt'), 'utf8'), 'white', 'yellow');
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case HMSTATUS.missingCommand:
 | 
					      case HMSTATUS.missingCommand:
 | 
				
			||||||
        // msg = M2C( this.msgs.missingCommand.msg + " (", 'yellow');
 | 
					        msg = M2C(this.msgs.missingCommand.msg + " (", 'yellow');
 | 
				
			||||||
        // msg += Object.keys( FCMD.verbs ).map( (v, idx, ar) ->
 | 
					        msg += Object.keys(FCMD.verbs).map(function(v, idx, ar) {
 | 
				
			||||||
        //   return ( if idx == ar.length - 1 then chalk.yellow('or ') else '') +
 | 
					          return (idx === ar.length - 1 ? chalk.yellow('or ') : '') + chalk.yellow.bold(v.toUpperCase());
 | 
				
			||||||
        //     chalk.yellow.bold(v.toUpperCase());
 | 
					        }).join(chalk.yellow(', ')) + chalk.yellow(").\n\n");
 | 
				
			||||||
        // ).join( chalk.yellow(', ')) + chalk.yellow(").\n\n");
 | 
					        msg += chalk.gray(FS.readFileSync(PATH.resolve(__dirname, '../cli/use.txt'), 'utf8'));
 | 
				
			||||||
        msg += M2C(FS.readFileSync(PATH.resolve(__dirname, 'help/use.txt'), 'utf8'), 'white', 'yellow');
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case HMSTATUS.invalidCommand:
 | 
					      case HMSTATUS.invalidCommand:
 | 
				
			||||||
        msg = printf(M2C(this.msgs.invalidCommand.msg, 'yellow'), ex.attempted);
 | 
					        msg = printf(M2C(this.msgs.invalidCommand.msg, 'yellow'), ex.attempted);
 | 
				
			||||||
@@ -179,7 +181,6 @@
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case HMSTATUS.readError:
 | 
					      case HMSTATUS.readError:
 | 
				
			||||||
        if (!ex.quiet) {
 | 
					        if (!ex.quiet) {
 | 
				
			||||||
          // eslint-disable-next-line no-console
 | 
					 | 
				
			||||||
          console.error(printf(M2C(this.msgs.readError.msg, 'red'), ex.file));
 | 
					          console.error(printf(M2C(this.msgs.readError.msg, 'red'), ex.file));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        msg = ex.inner.toString();
 | 
					        msg = ex.inner.toString();
 | 
				
			||||||
@@ -210,7 +211,6 @@
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case HMSTATUS.parseError:
 | 
					      case HMSTATUS.parseError:
 | 
				
			||||||
        if (SyntaxErrorEx.is(ex.inner)) {
 | 
					        if (SyntaxErrorEx.is(ex.inner)) {
 | 
				
			||||||
          // eslint-disable-next-line no-console
 | 
					 | 
				
			||||||
          console.error(printf(M2C(this.msgs.readError.msg, 'red'), ex.file));
 | 
					          console.error(printf(M2C(this.msgs.readError.msg, 'red'), ex.file));
 | 
				
			||||||
          se = new SyntaxErrorEx(ex, ex.raw);
 | 
					          se = new SyntaxErrorEx(ex, ex.raw);
 | 
				
			||||||
          if ((se.line != null) && (se.col != null)) {
 | 
					          if ((se.line != null) && (se.col != null)) {
 | 
				
			||||||
@@ -228,55 +228,16 @@
 | 
				
			|||||||
        etype = 'error';
 | 
					        etype = 'error';
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case HMSTATUS.createError:
 | 
					      case HMSTATUS.createError:
 | 
				
			||||||
        // inner.code could be EPERM, EACCES, etc
 | 
					 | 
				
			||||||
        msg = printf(M2C(this.msgs.createError.msg), ex.inner.path);
 | 
					        msg = printf(M2C(this.msgs.createError.msg), ex.inner.path);
 | 
				
			||||||
        etype = 'error';
 | 
					        etype = 'error';
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case HMSTATUS.validateError:
 | 
					      case HMSTATUS.validateError:
 | 
				
			||||||
        msg = printf(M2C(this.msgs.validateError.msg), ex.inner.toString());
 | 
					        msg = printf(M2C(this.msgs.validateError.msg), ex.inner.toString());
 | 
				
			||||||
        etype = 'error';
 | 
					        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';
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      msg: msg, // The error message to display
 | 
					      msg: msg,
 | 
				
			||||||
      withStack: withStack, // Whether to include the stack
 | 
					      withStack: withStack,
 | 
				
			||||||
      quit: quit,
 | 
					      quit: quit,
 | 
				
			||||||
      etype: etype
 | 
					      etype: etype
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								dist/cli/help/analyze.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								dist/cli/help/analyze.txt
									
									
									
									
										vendored
									
									
								
							@@ -1,25 +0,0 @@
 | 
				
			|||||||
**analyze** | Analyze a resume for statistical insight
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume ANALYZE <resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   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:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.**
 | 
					 | 
				
			||||||
							
								
								
									
										69
									
								
								dist/cli/help/build.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										69
									
								
								dist/cli/help/build.txt
									
									
									
									
										vendored
									
									
								
							@@ -1,69 +0,0 @@
 | 
				
			|||||||
**build** | Generate themed resumes in multiple formats
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume BUILD <resume> TO <target> [--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:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<target>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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 <theme-name-or-path>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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 <engine>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.
 | 
					 | 
				
			||||||
							
								
								
									
										33
									
								
								dist/cli/help/convert.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								dist/cli/help/convert.txt
									
									
									
									
										vendored
									
									
								
							@@ -1,33 +0,0 @@
 | 
				
			|||||||
**convert** | Convert resumes between FRESH and JRS formats
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume CONVERT <resume> TO <target> [--format]**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   The CONVERT command converts one or more resume documents
 | 
					 | 
				
			||||||
   between the FRESH Resume Schema and JSON Resume formats.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Parameters:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Path to a FRESH or JRS resume. Multiple resumes can be
 | 
					 | 
				
			||||||
      specified.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<targets>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      The path of the converted resume. Multiple resumes can
 | 
					 | 
				
			||||||
      be specified, one per provided input resume.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Options:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **--format -f <fmt>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.
 | 
					 | 
				
			||||||
							
								
								
									
										23
									
								
								dist/cli/help/help.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								dist/cli/help/help.txt
									
									
									
									
										vendored
									
									
								
							@@ -1,23 +0,0 @@
 | 
				
			|||||||
**help** | View help on a specific HackMyResume command
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume HELP [<command>]**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   The HELP command displays help information for a specific
 | 
					 | 
				
			||||||
   HackMyResume command, including the HELP command itself.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Parameters:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<command>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.**
 | 
					 | 
				
			||||||
							
								
								
									
										29
									
								
								dist/cli/help/new.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								dist/cli/help/new.txt
									
									
									
									
										vendored
									
									
								
							@@ -1,29 +0,0 @@
 | 
				
			|||||||
**new** | Create a new FRESH or JRS resume document
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume NEW <fileName> [--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:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<fileName>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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 <fmt>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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'.
 | 
					 | 
				
			||||||
							
								
								
									
										31
									
								
								dist/cli/help/peek.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								dist/cli/help/peek.txt
									
									
									
									
										vendored
									
									
								
							@@ -1,31 +0,0 @@
 | 
				
			|||||||
**peek** | View portions of a resume from the command line
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume PEEK <resume> <at>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   The PEEK command displays a specific piece or part of the
 | 
					 | 
				
			||||||
   resume without requiring the resume to be opened in an
 | 
					 | 
				
			||||||
   editor.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Parameters:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
     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]"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<at>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.**
 | 
					 | 
				
			||||||
							
								
								
									
										70
									
								
								dist/cli/help/use.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								dist/cli/help/use.txt
									
									
									
									
										vendored
									
									
								
							@@ -1,70 +0,0 @@
 | 
				
			|||||||
**HackMyResume** | A Swiss Army knife for resumes and CVs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume [--version] [--help] [--silent] [--debug]**
 | 
					 | 
				
			||||||
      **[--options] [--no-colors] <command> [<args>]**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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.
 | 
					 | 
				
			||||||
							
								
								
									
										26
									
								
								dist/cli/help/validate.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								dist/cli/help/validate.txt
									
									
									
									
										vendored
									
									
								
							@@ -1,26 +0,0 @@
 | 
				
			|||||||
**validate** | Validate a resume for correctness
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume VALIDATE <resume> [--assert]**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   The VALIDATE command validates a FRESH or JRS document
 | 
					 | 
				
			||||||
   against its governing schema, verifying that the resume
 | 
					 | 
				
			||||||
   is correctly structured and formatted.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Parameters:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.
 | 
					 | 
				
			||||||
							
								
								
									
										187
									
								
								dist/cli/main.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										187
									
								
								dist/cli/main.js
									
									
									
									
										vendored
									
									
								
							@@ -1,22 +1,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the `main` function.
 | 
				
			||||||
 | 
					@module cli/main
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var Command, EXTEND, FS, HME, HMR, HMSTATUS, M2C, OUTPUT, PAD, PATH, PKG, StringUtils, _, _err, _exitCallback, _opts, _out, _title, chalk, execute, executeFail, executeSuccess, initOptions, initialize, loadOptions, logMsg, main, printf, safeLoadJSON, splitSrcDest;
 | 
				
			||||||
  Definition of the `main` function.
 | 
					 | 
				
			||||||
  @module cli/main
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /* Invoke a HackMyResume verb. */
 | 
					 | 
				
			||||||
  /* Success handler for verb invocations. Calls process.exit by default */
 | 
					 | 
				
			||||||
  /* Init options prior to setting up command infrastructure. */
 | 
					 | 
				
			||||||
  /* Massage command-line args and setup Commander.js. */
 | 
					 | 
				
			||||||
  /*
 | 
					 | 
				
			||||||
  Initialize HackMyResume options.
 | 
					 | 
				
			||||||
  TODO: Options loading is a little hacky, for two reasons:
 | 
					 | 
				
			||||||
  - Commander.js idiosyncracies
 | 
					 | 
				
			||||||
  - Need to accept JSON inputs from the command line.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /* Simple logging placeholder. */
 | 
					 | 
				
			||||||
  /* Split multiple command-line filenames by the 'TO' keyword */
 | 
					 | 
				
			||||||
  var Command, EXTEND, FS, HMR, HMSTATUS, M2C, OUTPUT, PAD, PATH, PKG, _, _err, _exitCallback, _opts, _out, _title, chalk, execute, executeFail, executeSuccess, initOptions, initialize, loadOptions, logMsg, printf, safeLoadJSON, splitSrcDest;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HMR = require('../index');
 | 
					  HMR = require('../index');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,9 +22,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  HMSTATUS = require('../core/status-codes');
 | 
					  HMSTATUS = require('../core/status-codes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  HME = require('../core/event-codes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  safeLoadJSON = require('../utils/safe-json-loader');
 | 
					  safeLoadJSON = require('../utils/safe-json-loader');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //StringUtils = require '../utils/string.js'
 | 
					  StringUtils = require('../utils/string.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  OUTPUT = require('./out');
 | 
					  OUTPUT = require('./out');
 | 
				
			||||||
@@ -57,62 +50,45 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  _exitCallback = null;
 | 
					  _exitCallback = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
  A callable implementation of the HackMyResume CLI. Encapsulates the command
 | 
					  A callable implementation of the HackMyResume CLI. Encapsulates the command
 | 
				
			||||||
  line interface as a single method accepting a parameter array.
 | 
					  line interface as a single method accepting a parameter array.
 | 
				
			||||||
  @alias module:cli/main.main
 | 
					  @alias module:cli/main.main
 | 
				
			||||||
  @param rawArgs {Array} An array of command-line parameters. Will either be
 | 
					  @param rawArgs {Array} An array of command-line parameters. Will either be
 | 
				
			||||||
  process.argv (in production) or custom parameters (in test).
 | 
					  process.argv (in production) or custom parameters (in test).
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = function(rawArgs, exitCallback) {
 | 
					
 | 
				
			||||||
 | 
					  main = module.exports = function(rawArgs, exitCallback) {
 | 
				
			||||||
    var args, initInfo, program;
 | 
					    var args, initInfo, program;
 | 
				
			||||||
    initInfo = initialize(rawArgs, exitCallback);
 | 
					    initInfo = initialize(rawArgs, exitCallback);
 | 
				
			||||||
    if (initInfo === null) {
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    args = initInfo.args;
 | 
					    args = initInfo.args;
 | 
				
			||||||
    // Create the top-level (application) command...
 | 
					 | 
				
			||||||
    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 = 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;
 | 
					    program.jsonArgs = initInfo.options;
 | 
				
			||||||
    // Create the NEW command
 | 
					    program.command('new')["arguments"]('<sources...>').option('-f --format <fmt>', 'FRESH or JRS format', 'FRESH').alias('create').description('Create resume(s) in FRESH or JSON RESUME format.').action((function(sources) {
 | 
				
			||||||
    program.command('new').arguments('<sources...>').option('-f --format <fmt>', '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);
 | 
					      execute.call(this, sources, [], this.opts(), logMsg);
 | 
				
			||||||
    }));
 | 
					    }));
 | 
				
			||||||
    // Create the VALIDATE command
 | 
					    program.command('validate')["arguments"]('<sources...>').description('Validate a resume in FRESH or JSON RESUME format.').action(function(sources) {
 | 
				
			||||||
    program.command('validate').arguments('<sources...>').description('Validate a resume in FRESH or JSON RESUME format.').action(function(sources) {
 | 
					 | 
				
			||||||
      execute.call(this, sources, [], this.opts(), logMsg);
 | 
					      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.').action(function() {
 | 
				
			||||||
    program.command('convert').description('Convert a resume to/from FRESH or JSON RESUME format.').option('-f --format <fmt>', 'FRESH or JRS format and optional version', void 0).action(function() {
 | 
					 | 
				
			||||||
      var x;
 | 
					      var x;
 | 
				
			||||||
      x = splitSrcDest.call(this);
 | 
					      x = splitSrcDest.call(this);
 | 
				
			||||||
      execute.call(this, x.src, x.dst, this.opts(), logMsg);
 | 
					      execute.call(this, x.src, x.dst, this.opts(), logMsg);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // Create the ANALYZE command
 | 
					    program.command('analyze')["arguments"]('<sources...>').description('Analyze one or more resumes.').action(function(sources) {
 | 
				
			||||||
    program.command('analyze').arguments('<sources...>').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);
 | 
					      execute.call(this, sources, [], this.opts(), logMsg);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // Create the PEEK command
 | 
					    program.command('peek')["arguments"]('<sources...>').description('Peek at a resume field or section').action(function(sources, sectionOrField) {
 | 
				
			||||||
    //.action(( sources, sectionOrField ) ->
 | 
					 | 
				
			||||||
    program.command('peek').arguments('<sources...>').description('Peek at a resume field or section').action(function(sources) {
 | 
					 | 
				
			||||||
      var dst;
 | 
					      var dst;
 | 
				
			||||||
      dst = (sources && sources.length > 1) ? [sources.pop()] : [];
 | 
					      dst = sources && sources.length > 1 ? [sources.pop()] : [];
 | 
				
			||||||
      execute.call(this, sources, dst, this.opts(), logMsg);
 | 
					      execute.call(this, sources, dst, this.opts(), logMsg);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // Create the BUILD command
 | 
					    program.command('build').alias('generate').option('-t --theme <theme>', 'Theme name or path').option('-n --no-prettify', 'Disable HTML prettification', true).option('-c --css <option>', 'CSS linking / embedding').option('-p --pdf <engine>', 'PDF generation engine').option('--no-sort', 'Sort resume sections by date', false).option('--tips', 'Display theme tips and warnings.', false).description('Generate resume to multiple formats').action(function(sources, targets, options) {
 | 
				
			||||||
    //.action(( sources, targets, options ) ->
 | 
					 | 
				
			||||||
    program.command('build').alias('generate').option('-t --theme <theme>', 'Theme name or path').option('-n --no-prettify', 'Disable HTML prettification', true).option('-c --css <option>', 'CSS linking / embedding').option('-p --pdf <engine>', 'PDF generation engine').option('--no-sort', 'Sort resume sections by date', false).option('--tips', 'Display theme tips and warnings.', false).option('--private', 'Include resume fields marked as private', false).option('--no-escape', 'Turn off encoding in Handlebars themes.', false).description('Generate resume to multiple formats').action(function() {
 | 
					 | 
				
			||||||
      var x;
 | 
					      var x;
 | 
				
			||||||
      x = splitSrcDest.call(this);
 | 
					      x = splitSrcDest.call(this);
 | 
				
			||||||
      execute.call(this, x.src, x.dst, this.opts(), logMsg);
 | 
					      execute.call(this, x.src, x.dst, this.opts(), logMsg);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // Create the HELP command
 | 
					 | 
				
			||||||
    program.command('help').arguments('[command]').description('Get help on a HackMyResume command').action(function(cmd) {
 | 
					 | 
				
			||||||
      var manPage;
 | 
					 | 
				
			||||||
      cmd = cmd || 'use';
 | 
					 | 
				
			||||||
      manPage = FS.readFileSync(PATH.join(__dirname, 'help/' + cmd + '.txt'), 'utf8');
 | 
					 | 
				
			||||||
      _out.log(M2C(manPage, 'white', 'yellow.bold'));
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    program.parse(args);
 | 
					    program.parse(args);
 | 
				
			||||||
    if (!program.args.length) {
 | 
					    if (!program.args.length) {
 | 
				
			||||||
      throw {
 | 
					      throw {
 | 
				
			||||||
@@ -121,29 +97,14 @@
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Massage command-line args and setup Commander.js. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  initialize = function(ar, exitCallback) {
 | 
					  initialize = function(ar, exitCallback) {
 | 
				
			||||||
    var o;
 | 
					    var o;
 | 
				
			||||||
    _exitCallback = exitCallback || process.exit;
 | 
					    _exitCallback = exitCallback || process.exit;
 | 
				
			||||||
    o = initOptions(ar);
 | 
					    o = initOptions(ar);
 | 
				
			||||||
    if (o.ex) {
 | 
					 | 
				
			||||||
      _err.init(false, true, false);
 | 
					 | 
				
			||||||
      if (o.ex.op === 'parse') {
 | 
					 | 
				
			||||||
        _err.err({
 | 
					 | 
				
			||||||
          fluenterror: o.ex.op === 'parse' ? HMSTATUS.invalidOptionsFile : HMSTATUS.optionsFileNotFound,
 | 
					 | 
				
			||||||
          inner: o.ex.inner,
 | 
					 | 
				
			||||||
          quit: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        _err.err({
 | 
					 | 
				
			||||||
          fluenterror: HMSTATUS.optionsFileNotFound,
 | 
					 | 
				
			||||||
          inner: o.ex.inner,
 | 
					 | 
				
			||||||
          quit: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    o.silent || logMsg(_title);
 | 
					    o.silent || logMsg(_title);
 | 
				
			||||||
    // Emit debug prelude if --debug was specified
 | 
					 | 
				
			||||||
    if (o.debug) {
 | 
					    if (o.debug) {
 | 
				
			||||||
      _out.log(chalk.cyan('The -d or --debug switch was specified. DEBUG mode engaged.'));
 | 
					      _out.log(chalk.cyan('The -d or --debug switch was specified. DEBUG mode engaged.'));
 | 
				
			||||||
      _out.log('');
 | 
					      _out.log('');
 | 
				
			||||||
@@ -151,33 +112,25 @@
 | 
				
			|||||||
      _out.log(chalk.cyan(PAD('  Node.js:', 25, null, PAD.RIGHT)) + chalk.cyan.bold(process.version));
 | 
					      _out.log(chalk.cyan(PAD('  Node.js:', 25, null, PAD.RIGHT)) + chalk.cyan.bold(process.version));
 | 
				
			||||||
      _out.log(chalk.cyan(PAD('  HackMyResume:', 25, null, PAD.RIGHT)) + chalk.cyan.bold('v' + PKG.version));
 | 
					      _out.log(chalk.cyan(PAD('  HackMyResume:', 25, null, PAD.RIGHT)) + chalk.cyan.bold('v' + PKG.version));
 | 
				
			||||||
      _out.log(chalk.cyan(PAD('  FRESCA:', 25, null, PAD.RIGHT)) + chalk.cyan.bold(PKG.dependencies.fresca));
 | 
					      _out.log(chalk.cyan(PAD('  FRESCA:', 25, null, PAD.RIGHT)) + chalk.cyan.bold(PKG.dependencies.fresca));
 | 
				
			||||||
      //_out.log(chalk.cyan(PAD('  fresh-themes:',25, null, PAD.RIGHT)) + chalk.cyan.bold( PKG.dependencies['fresh-themes'] ))
 | 
					 | 
				
			||||||
      //_out.log(chalk.cyan(PAD('  fresh-jrs-converter:',25, null, PAD.RIGHT)) + chalk.cyan.bold( PKG.dependencies['fresh-jrs-converter'] ))
 | 
					 | 
				
			||||||
      _out.log('');
 | 
					      _out.log('');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    _err.init(o.debug, o.assert, o.silent);
 | 
					    _err.init(o.debug, o.assert, o.silent);
 | 
				
			||||||
    // Handle invalid verbs here (a bit easier here than in commander.js)...
 | 
					    if (o.verb && !HMR.verbs[o.verb] && !HMR.alias[o.verb]) {
 | 
				
			||||||
    if (o.verb && !HMR.verbs[o.verb] && !HMR.alias[o.verb] && o.verb !== 'help') {
 | 
					 | 
				
			||||||
      _err.err({
 | 
					      _err.err({
 | 
				
			||||||
        fluenterror: HMSTATUS.invalidCommand,
 | 
					        fluenterror: HMSTATUS.invalidCommand,
 | 
				
			||||||
        quit: true,
 | 
					        quit: true,
 | 
				
			||||||
        attempted: o.orgVerb
 | 
					        attempted: o.orgVerb
 | 
				
			||||||
      }, true);
 | 
					      }, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Override the .missingArgument behavior
 | 
					    Command.prototype.missingArgument = function(name) {
 | 
				
			||||||
    Command.prototype.missingArgument = function(/* unused */) {
 | 
					      _err.err({
 | 
				
			||||||
      if (this.name() !== 'help') {
 | 
					        fluenterror: this.name() !== 'new' ? HMSTATUS.resumeNotFound : HMSTATUS.createNameMissing
 | 
				
			||||||
        _err.err({
 | 
					      }, true);
 | 
				
			||||||
          verb: this.name(),
 | 
					 | 
				
			||||||
          fluenterror: HMSTATUS.resumeNotFound
 | 
					 | 
				
			||||||
        }, true);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    // Override the .helpInformation behavior
 | 
					 | 
				
			||||||
    Command.prototype.helpInformation = function() {
 | 
					    Command.prototype.helpInformation = function() {
 | 
				
			||||||
      var manPage;
 | 
					      var manPage;
 | 
				
			||||||
      manPage = FS.readFileSync(PATH.join(__dirname, 'help/use.txt'), 'utf8');
 | 
					      manPage = FS.readFileSync(PATH.join(__dirname, 'use.txt'), 'utf8');
 | 
				
			||||||
      return M2C(manPage, 'white', 'yellow');
 | 
					      return chalk.green.bold(manPage);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      args: o.args,
 | 
					      args: o.args,
 | 
				
			||||||
@@ -185,16 +138,17 @@
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Init options prior to setting up command infrastructure. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  initOptions = function(ar) {
 | 
					  initOptions = function(ar) {
 | 
				
			||||||
    oVerb;
 | 
					    oVerb;
 | 
				
			||||||
    /* jshint ignore:end */
 | 
					    var args, cleanArgs, inf, isAssert, isDebug, isMono, isSilent, oJSON, oVerb, optStr, optsIdx, verb, vidx;
 | 
				
			||||||
    var args, cleanArgs, inf, isAssert, isDebug, isMono, isNoEscape, isSilent, oJSON, oVerb, optStr, optsIdx, verb, vidx;
 | 
					 | 
				
			||||||
    verb = '';
 | 
					    verb = '';
 | 
				
			||||||
    args = ar.slice();
 | 
					    args = ar.slice();
 | 
				
			||||||
    cleanArgs = args.slice(2);
 | 
					    cleanArgs = args.slice(2);
 | 
				
			||||||
    oJSON;
 | 
					    oJSON;
 | 
				
			||||||
    if (cleanArgs.length) {
 | 
					    if (cleanArgs.length) {
 | 
				
			||||||
      // Support case-insensitive sub-commands (build, generate, validate, etc)
 | 
					 | 
				
			||||||
      vidx = _.findIndex(cleanArgs, function(v) {
 | 
					      vidx = _.findIndex(cleanArgs, function(v) {
 | 
				
			||||||
        return v[0] !== '-';
 | 
					        return v[0] !== '-';
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -202,7 +156,6 @@
 | 
				
			|||||||
        oVerb = cleanArgs[vidx];
 | 
					        oVerb = cleanArgs[vidx];
 | 
				
			||||||
        verb = args[vidx + 2] = oVerb.trim().toLowerCase();
 | 
					        verb = args[vidx + 2] = oVerb.trim().toLowerCase();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // Remove --options --opts -o and process separately
 | 
					 | 
				
			||||||
      optsIdx = _.findIndex(cleanArgs, function(v) {
 | 
					      optsIdx = _.findIndex(cleanArgs, function(v) {
 | 
				
			||||||
        return v === '-o' || v === '--options' || v === '--opts';
 | 
					        return v === '-o' || v === '--options' || v === '--opts';
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -210,23 +163,21 @@
 | 
				
			|||||||
        optStr = cleanArgs[optsIdx + 1];
 | 
					        optStr = cleanArgs[optsIdx + 1];
 | 
				
			||||||
        args.splice(optsIdx + 2, 2);
 | 
					        args.splice(optsIdx + 2, 2);
 | 
				
			||||||
        if (optStr && (optStr = optStr.trim())) {
 | 
					        if (optStr && (optStr = optStr.trim())) {
 | 
				
			||||||
          //var myJSON = JSON.parse(optStr);
 | 
					 | 
				
			||||||
          if (optStr[0] === '{') {
 | 
					          if (optStr[0] === '{') {
 | 
				
			||||||
            // TODO: remove use of evil(). - hacksalot
 | 
					
 | 
				
			||||||
            /* jshint ignore:start */
 | 
					            /* jshint ignore:start */
 | 
				
			||||||
            oJSON = eval('(' + optStr + ')'); // jshint ignore:line <-- no worky
 | 
					            oJSON = eval('(' + optStr + ')');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* jshint ignore:end */
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            inf = safeLoadJSON(optStr);
 | 
					            inf = safeLoadJSON(optStr);
 | 
				
			||||||
            if (!inf.ex) {
 | 
					            if (!inf.ex) {
 | 
				
			||||||
              oJSON = inf.json;
 | 
					              oJSON = inf.json;
 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
              return inf;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Grab the --debug flag, --silent, --assert and --no-color flags
 | 
					 | 
				
			||||||
    isDebug = _.some(args, function(v) {
 | 
					    isDebug = _.some(args, function(v) {
 | 
				
			||||||
      return v === '-d' || v === '--debug';
 | 
					      return v === '-d' || v === '--debug';
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -239,15 +190,11 @@
 | 
				
			|||||||
    isMono = _.some(args, function(v) {
 | 
					    isMono = _.some(args, function(v) {
 | 
				
			||||||
      return v === '--no-color';
 | 
					      return v === '--no-color';
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    isNoEscape = _.some(args, function(v) {
 | 
					 | 
				
			||||||
      return v === '--no-escape';
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      color: !isMono,
 | 
					      color: !isMono,
 | 
				
			||||||
      debug: isDebug,
 | 
					      debug: isDebug,
 | 
				
			||||||
      silent: isSilent,
 | 
					      silent: isSilent,
 | 
				
			||||||
      assert: isAssert,
 | 
					      assert: isAssert,
 | 
				
			||||||
      noescape: isNoEscape,
 | 
					 | 
				
			||||||
      orgVerb: oVerb,
 | 
					      orgVerb: oVerb,
 | 
				
			||||||
      verb: verb,
 | 
					      verb: verb,
 | 
				
			||||||
      json: oJSON,
 | 
					      json: oJSON,
 | 
				
			||||||
@@ -255,44 +202,38 @@
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Invoke a HackMyResume verb. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  execute = function(src, dst, opts, log) {
 | 
					  execute = function(src, dst, opts, log) {
 | 
				
			||||||
    var prom, v;
 | 
					    var prom, v;
 | 
				
			||||||
    // Create the verb
 | 
					 | 
				
			||||||
    v = new HMR.verbs[this.name()]();
 | 
					    v = new HMR.verbs[this.name()]();
 | 
				
			||||||
    // Initialize command-specific options
 | 
					 | 
				
			||||||
    loadOptions.call(this, opts, this.parent.jsonArgs);
 | 
					    loadOptions.call(this, opts, this.parent.jsonArgs);
 | 
				
			||||||
    // Set up error/output handling
 | 
					 | 
				
			||||||
    _opts.errHandler = v;
 | 
					    _opts.errHandler = v;
 | 
				
			||||||
    _out.init(_opts);
 | 
					    _out.init(_opts);
 | 
				
			||||||
    // Hook up event notifications
 | 
					 | 
				
			||||||
    v.on('hmr:status', function() {
 | 
					    v.on('hmr:status', function() {
 | 
				
			||||||
      return _out.do.apply(_out, arguments);
 | 
					      return _out["do"].apply(_out, arguments);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    v.on('hmr:error', function() {
 | 
					    v.on('hmr:error', function() {
 | 
				
			||||||
      return _err.err.apply(_err, arguments);
 | 
					      return _err.err.apply(_err, arguments);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // Invoke the verb using promise syntax
 | 
					 | 
				
			||||||
    prom = v.invoke.call(v, src, dst, _opts, log);
 | 
					    prom = v.invoke.call(v, src, dst, _opts, log);
 | 
				
			||||||
    prom.then(executeSuccess, executeFail);
 | 
					    prom.then(executeSuccess, executeFail);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  executeSuccess = function(/*obj*/) {};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Can't call _exitCallback here (process.exit) when PDF is running in BK
 | 
					  /* Success handler for verb invocations. Calls process.exit by default */
 | 
				
			||||||
  //_exitCallback 0; return
 | 
					
 | 
				
			||||||
 | 
					  executeSuccess = function(obj) {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Failure handler for verb invocations. Calls process.exit by default */
 | 
					  /* Failure handler for verb invocations. Calls process.exit by default */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  executeFail = function(err) {
 | 
					  executeFail = function(err) {
 | 
				
			||||||
    var finalErrorCode, msgs;
 | 
					    var finalErrorCode, msgs;
 | 
				
			||||||
    //console.dir err
 | 
					 | 
				
			||||||
    finalErrorCode = -1;
 | 
					    finalErrorCode = -1;
 | 
				
			||||||
    if (err) {
 | 
					    if (err) {
 | 
				
			||||||
      if (err.fluenterror) {
 | 
					      finalErrorCode = err.fluenterror ? err.fluenterror : err;
 | 
				
			||||||
        finalErrorCode = err.fluenterror;
 | 
					 | 
				
			||||||
      } else if (err.length) {
 | 
					 | 
				
			||||||
        finalErrorCode = err[0].fluenterror;
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        finalErrorCode = err;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (_opts.debug) {
 | 
					    if (_opts.debug) {
 | 
				
			||||||
      msgs = require('./msg').errors;
 | 
					      msgs = require('./msg').errors;
 | 
				
			||||||
@@ -304,16 +245,19 @@
 | 
				
			|||||||
    _exitCallback(finalErrorCode);
 | 
					    _exitCallback(finalErrorCode);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  loadOptions = function(o, cmdO) {
 | 
					 | 
				
			||||||
    // o and this.opts() seem to be the same (command-specific options)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Load the specified options file (if any) and apply options
 | 
					  /*
 | 
				
			||||||
 | 
					  Initialize HackMyResume options.
 | 
				
			||||||
 | 
					  TODO: Options loading is a little hacky, for two reasons:
 | 
				
			||||||
 | 
					    - Commander.js idiosyncracies
 | 
				
			||||||
 | 
					    - Need to accept JSON inputs from the command line.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  loadOptions = function(o, cmdO) {
 | 
				
			||||||
    if (cmdO) {
 | 
					    if (cmdO) {
 | 
				
			||||||
      o = EXTEND(true, o, cmdO);
 | 
					      o = EXTEND(true, o, cmdO);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Merge in command-line options
 | 
					 | 
				
			||||||
    o = EXTEND(true, o, this.opts());
 | 
					    o = EXTEND(true, o, this.opts());
 | 
				
			||||||
    // Kludge parent-level options until piping issue is resolved
 | 
					 | 
				
			||||||
    if (this.parent.silent !== void 0 && this.parent.silent !== null) {
 | 
					    if (this.parent.silent !== void 0 && this.parent.silent !== null) {
 | 
				
			||||||
      o.silent = this.parent.silent;
 | 
					      o.silent = this.parent.silent;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -333,6 +277,9 @@
 | 
				
			|||||||
    EXTEND(true, _opts, o);
 | 
					    EXTEND(true, _opts, o);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Split multiple command-line filenames by the 'TO' keyword */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  splitSrcDest = function() {
 | 
					  splitSrcDest = function() {
 | 
				
			||||||
    var params, splitAt;
 | 
					    var params, splitAt;
 | 
				
			||||||
    params = this.parent.args.filter(function(j) {
 | 
					    params = this.parent.args.filter(function(j) {
 | 
				
			||||||
@@ -340,17 +287,13 @@
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
    if (params.length === 0) {
 | 
					    if (params.length === 0) {
 | 
				
			||||||
      throw {
 | 
					      throw {
 | 
				
			||||||
        //tmpName = @name()
 | 
					 | 
				
			||||||
        fluenterror: HMSTATUS.resumeNotFound,
 | 
					        fluenterror: HMSTATUS.resumeNotFound,
 | 
				
			||||||
        verb: this.name(),
 | 
					 | 
				
			||||||
        quit: true
 | 
					        quit: true
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Find the TO keyword, if any
 | 
					 | 
				
			||||||
    splitAt = _.findIndex(params, function(p) {
 | 
					    splitAt = _.findIndex(params, function(p) {
 | 
				
			||||||
      return p.toLowerCase() === 'to';
 | 
					      return p.toLowerCase() === 'to';
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // TO can't be the last keyword
 | 
					 | 
				
			||||||
    if (splitAt === params.length - 1 && splitAt !== -1) {
 | 
					    if (splitAt === params.length - 1 && splitAt !== -1) {
 | 
				
			||||||
      logMsg(chalk.yellow('Please ') + chalk.yellow.bold('specify an output file') + chalk.yellow(' for this operation or ') + chalk.yellow.bold('omit the TO keyword') + chalk.yellow('.'));
 | 
					      logMsg(chalk.yellow('Please ') + chalk.yellow.bold('specify an output file') + chalk.yellow(' for this operation or ') + chalk.yellow.bold('omit the TO keyword') + chalk.yellow('.'));
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
@@ -361,8 +304,10 @@
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Simple logging placeholder. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  logMsg = function() {
 | 
					  logMsg = function() {
 | 
				
			||||||
    // eslint-disable-next-line no-console
 | 
					 | 
				
			||||||
    return _opts.silent || console.log.apply(console.log, arguments);
 | 
					    return _opts.silent || console.log.apply(console.log, arguments);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								dist/cli/msg.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								dist/cli/msg.js
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Message-handling routines for HackMyResume.
 | 
				
			||||||
 | 
					@module cli/msg
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Message-handling routines for HackMyResume.
 | 
					 | 
				
			||||||
  @module cli/msg
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var PATH, YAML;
 | 
					  var PATH, YAML;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PATH = require('path');
 | 
					  PATH = require('path');
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								dist/cli/msg.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								dist/cli/msg.yml
									
									
									
									
										vendored
									
									
								
							@@ -109,33 +109,3 @@ errors:
 | 
				
			|||||||
    msg: Exiting with status code **%s**.
 | 
					    msg: Exiting with status code **%s**.
 | 
				
			||||||
  validateError:
 | 
					  validateError:
 | 
				
			||||||
    msg: "An error occurred during validation:\n%s"
 | 
					    msg: "An error occurred during validation:\n%s"
 | 
				
			||||||
  invalidOptionsFile:
 | 
					 | 
				
			||||||
    msg:
 | 
					 | 
				
			||||||
      - "The specified options file is invalid:\n"
 | 
					 | 
				
			||||||
      - "\nMake sure the options file contains valid JSON."
 | 
					 | 
				
			||||||
  optionsFileNotFound:
 | 
					 | 
				
			||||||
    msg: "The specified options file is missing or inaccessible."
 | 
					 | 
				
			||||||
  unknownSchema:
 | 
					 | 
				
			||||||
    msg:
 | 
					 | 
				
			||||||
      - "Unknown resume schema. Did you specify a valid FRESH or JRS resume?"
 | 
					 | 
				
			||||||
      - |
 | 
					 | 
				
			||||||
          At a minimum, a FRESH resume must include a "name" field and a "meta"
 | 
					 | 
				
			||||||
          property.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          "name": "John Doe",
 | 
					 | 
				
			||||||
          "meta": {
 | 
					 | 
				
			||||||
            "format": "FRESH@0.1.0"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          JRS-format resumes must include a "basics" section with a "name":
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          "basics": {
 | 
					 | 
				
			||||||
            "name": "John Doe"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
  themeHelperLoad:
 | 
					 | 
				
			||||||
    msg: >-
 | 
					 | 
				
			||||||
      An error occurred while attempting to load the '%s' theme helper. Is the
 | 
					 | 
				
			||||||
      theme correctly installed?
 | 
					 | 
				
			||||||
    dummy: dontcare
 | 
					 | 
				
			||||||
  invalidSchemaVersion:
 | 
					 | 
				
			||||||
    msg: "'%s' is not recognized as a valid schema version."
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										55
									
								
								dist/cli/out.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										55
									
								
								dist/cli/out.js
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Output routines for HackMyResume.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module cli/out
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var EXTEND, FS, HANDLEBARS, HME, LO, M2C, OutputHandler, PATH, YAML, _, chalk, dbgStyle, pad, printf;
 | 
				
			||||||
  Output routines for HackMyResume.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module cli/out
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var EXTEND, FS, HANDLEBARS, HME, M2C, OutputHandler, PATH, YAML, _, chalk, dbgStyle, pad, printf;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  chalk = require('chalk');
 | 
					  chalk = require('chalk');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,6 +18,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  PATH = require('path');
 | 
					  PATH = require('path');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  LO = require('lodash');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FS = require('fs');
 | 
					  FS = require('fs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  EXTEND = require('extend');
 | 
					  EXTEND = require('extend');
 | 
				
			||||||
@@ -30,26 +34,30 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  dbgStyle = 'cyan';
 | 
					  dbgStyle = 'cyan';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  OutputHandler = class OutputHandler {
 | 
					
 | 
				
			||||||
    constructor(opts) {
 | 
					  /** A stateful output module. All HMR console output handled here. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  module.exports = OutputHandler = (function() {
 | 
				
			||||||
 | 
					    function OutputHandler(opts) {
 | 
				
			||||||
      this.init(opts);
 | 
					      this.init(opts);
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init(opts) {
 | 
					    OutputHandler.prototype.init = function(opts) {
 | 
				
			||||||
      this.opts = EXTEND(true, this.opts || {}, opts);
 | 
					      this.opts = EXTEND(true, this.opts || {}, opts);
 | 
				
			||||||
      this.msgs = YAML.load(PATH.join(__dirname, 'msg.yml')).events;
 | 
					      this.msgs = YAML.load(PATH.join(__dirname, 'msg.yml')).events;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    log() {
 | 
					    OutputHandler.prototype.log = function(msg) {
 | 
				
			||||||
      var finished;
 | 
					      var finished;
 | 
				
			||||||
 | 
					      msg = msg || '';
 | 
				
			||||||
      printf = require('printf');
 | 
					      printf = require('printf');
 | 
				
			||||||
      finished = printf.apply(printf, arguments);
 | 
					      finished = printf.apply(printf, arguments);
 | 
				
			||||||
      return this.opts.silent || console.log(finished); // eslint-disable-line no-console
 | 
					      return this.opts.silent || console.log(finished);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do(evt) {
 | 
					    OutputHandler.prototype["do"] = function(evt) {
 | 
				
			||||||
      var L, adj, info, msg, msgs, numFormats, output, rawTpl, sty, style, suffix, template, that, themeName, tot;
 | 
					      var L, WRAP, adj, info, msg, msgs, numFormats, output, rawTpl, sty, style, suffix, template, that, themeName, tot;
 | 
				
			||||||
      that = this;
 | 
					      that = this;
 | 
				
			||||||
      L = function() {
 | 
					      L = function() {
 | 
				
			||||||
        return that.log.apply(that, arguments);
 | 
					        return that.log.apply(that, arguments);
 | 
				
			||||||
@@ -57,9 +65,6 @@
 | 
				
			|||||||
      switch (evt.sub) {
 | 
					      switch (evt.sub) {
 | 
				
			||||||
        case HME.begin:
 | 
					        case HME.begin:
 | 
				
			||||||
          return this.opts.debug && L(M2C(this.msgs.begin.msg, dbgStyle), evt.cmd.toUpperCase());
 | 
					          return this.opts.debug && L(M2C(this.msgs.begin.msg, dbgStyle), evt.cmd.toUpperCase());
 | 
				
			||||||
        //when HME.beforeCreate
 | 
					 | 
				
			||||||
        //L( M2C( this.msgs.beforeCreate.msg, 'green' ), evt.fmt, evt.file )
 | 
					 | 
				
			||||||
        //break;
 | 
					 | 
				
			||||||
        case HME.afterCreate:
 | 
					        case HME.afterCreate:
 | 
				
			||||||
          L(M2C(this.msgs.beforeCreate.msg, evt.isError ? 'red' : 'green'), evt.fmt, evt.file);
 | 
					          L(M2C(this.msgs.beforeCreate.msg, evt.isError ? 'red' : 'green'), evt.fmt, evt.file);
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
@@ -81,6 +86,7 @@
 | 
				
			|||||||
          if (evt.cmd === 'build') {
 | 
					          if (evt.cmd === 'build') {
 | 
				
			||||||
            themeName = this.theme.name.toUpperCase();
 | 
					            themeName = this.theme.name.toUpperCase();
 | 
				
			||||||
            if (this.opts.tips && (this.theme.message || this.theme.render)) {
 | 
					            if (this.opts.tips && (this.theme.message || this.theme.render)) {
 | 
				
			||||||
 | 
					              WRAP = require('word-wrap');
 | 
				
			||||||
              if (this.theme.message) {
 | 
					              if (this.theme.message) {
 | 
				
			||||||
                L(M2C(this.msgs.afterBuild.msg[0], 'cyan'), themeName);
 | 
					                L(M2C(this.msgs.afterBuild.msg[0], 'cyan'), themeName);
 | 
				
			||||||
                return L(M2C(this.theme.message, 'white'));
 | 
					                return L(M2C(this.theme.message, 'white'));
 | 
				
			||||||
@@ -122,7 +128,7 @@
 | 
				
			|||||||
          output = template(info);
 | 
					          output = template(info);
 | 
				
			||||||
          return this.log(chalk.cyan(output));
 | 
					          return this.log(chalk.cyan(output));
 | 
				
			||||||
        case HME.beforeConvert:
 | 
					        case HME.beforeConvert:
 | 
				
			||||||
          return L(M2C(this.msgs.beforeConvert.msg, evt.error ? 'red' : 'green'), evt.srcFile, evt.srcFmt, evt.dstFile, evt.dstFmt);
 | 
					          return L(M2C(this.msgs.beforeConvert.msg, 'green'), evt.srcFile, evt.srcFmt, evt.dstFile, evt.dstFmt);
 | 
				
			||||||
        case HME.afterInlineConvert:
 | 
					        case HME.afterInlineConvert:
 | 
				
			||||||
          return L(M2C(this.msgs.afterInlineConvert.msg, 'gray', 'white.dim'), evt.file, evt.fmt);
 | 
					          return L(M2C(this.msgs.afterInlineConvert.msg, 'gray', 'white.dim'), evt.file, evt.fmt);
 | 
				
			||||||
        case HME.afterValidate:
 | 
					        case HME.afterValidate:
 | 
				
			||||||
@@ -153,22 +159,19 @@
 | 
				
			|||||||
          evt.schema = evt.schema.replace('jars', 'JSON Resume').toUpperCase();
 | 
					          evt.schema = evt.schema.replace('jars', 'JSON Resume').toUpperCase();
 | 
				
			||||||
          L(M2C(msgs[0], 'white') + chalk[style].bold(adj), evt.file, evt.schema);
 | 
					          L(M2C(msgs[0], 'white') + chalk[style].bold(adj), evt.file, evt.schema);
 | 
				
			||||||
          if (evt.violations) {
 | 
					          if (evt.violations) {
 | 
				
			||||||
            _.each(evt.violations, function(err) {
 | 
					            _.each(evt.violations, function(err, idx) {
 | 
				
			||||||
              L(chalk.yellow.bold('--> ') + chalk.yellow(err.field.replace('data.', 'resume.').toUpperCase() + ' ' + err.message));
 | 
					              L(chalk.yellow.bold('--> ') + chalk.yellow(err.field.replace('data.', 'resume.').toUpperCase() + ' ' + err.message));
 | 
				
			||||||
            }, this);
 | 
					            }, this);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        case HME.afterPeek:
 | 
					        case HME.afterPeek:
 | 
				
			||||||
          sty = evt.error ? 'red' : (evt.target !== void 0 ? 'green' : 'yellow');
 | 
					          sty = evt.error ? 'red' : (evt.target !== void 0 ? 'green' : 'yellow');
 | 
				
			||||||
          // "Peeking at 'someKey' in 'someFile'."
 | 
					 | 
				
			||||||
          if (evt.requested) {
 | 
					          if (evt.requested) {
 | 
				
			||||||
            L(M2C(this.msgs.beforePeek.msg[0], sty), evt.requested, evt.file);
 | 
					            L(M2C(this.msgs.beforePeek.msg[0], sty), evt.requested, evt.file);
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            L(M2C(this.msgs.beforePeek.msg[1], sty), evt.file);
 | 
					            L(M2C(this.msgs.beforePeek.msg[1], sty), evt.file);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          // If the key was present, print it
 | 
					 | 
				
			||||||
          if (evt.target !== void 0 && !evt.error) {
 | 
					          if (evt.target !== void 0 && !evt.error) {
 | 
				
			||||||
            // eslint-disable-next-line no-console
 | 
					 | 
				
			||||||
            return console.dir(evt.target, {
 | 
					            return console.dir(evt.target, {
 | 
				
			||||||
              depth: null,
 | 
					              depth: null,
 | 
				
			||||||
              colors: true
 | 
					              colors: true
 | 
				
			||||||
@@ -179,11 +182,11 @@
 | 
				
			|||||||
            return L(chalk.red(evt.error.inner.inner));
 | 
					            return L(chalk.red(evt.error.inner.inner));
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return OutputHandler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = OutputHandler;
 | 
					  })();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										51
									
								
								dist/cli/use.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								dist/cli/use.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					Usage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  hackmyresume <command> <sources> [TO <targets>] [<options>]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Available commands:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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.
 | 
				
			||||||
 | 
					  CONVERT       Convert your resume between FRESH and JSON Resume.
 | 
				
			||||||
 | 
					  NEW           Create a new resume in FRESH or JSON Resume format.
 | 
				
			||||||
 | 
					  PEEK          View a specific field or element on your resume.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Available options:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  --theme -t    Path to a FRESH or JSON Resume theme.
 | 
				
			||||||
 | 
					  --pdf -p      Specify the PDF engine to use (wkhtmltopdf or phantom).
 | 
				
			||||||
 | 
					  --options -o  Load options from an external JSON file.
 | 
				
			||||||
 | 
					  --format -f   The format (FRESH or JSON Resume) to use.
 | 
				
			||||||
 | 
					  --debug -d    Emit extended debugging info.
 | 
				
			||||||
 | 
					  --assert -a   Treat resume validation warnings as errors.
 | 
				
			||||||
 | 
					  --no-colors   Disable terminal colors.
 | 
				
			||||||
 | 
					  --tips        Display theme messages and tips.
 | 
				
			||||||
 | 
					  --help -h     Display help documentation.
 | 
				
			||||||
 | 
					  --version -v  Display the current version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Not all options are supported for all commands. For example, the
 | 
				
			||||||
 | 
					--theme option is only supported for the BUILD command.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Examples:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  hackmyresume  BUILD resume.json TO out/resume.all --theme modern
 | 
				
			||||||
 | 
					  hackmyresume  ANALYZE resume.json
 | 
				
			||||||
 | 
					  hackmyresume  NEW my-new-resume.json --format JRS
 | 
				
			||||||
 | 
					  hackmyresume  CONVERT resume-fresh.json TO resume-jrs.json
 | 
				
			||||||
 | 
					  hackmyresume  VALIDATE resume.json
 | 
				
			||||||
 | 
					  hackmyresume  PEEK resume.json employment[2].summary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tips:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - You can specify multiple sources and/or targets for all commands.
 | 
				
			||||||
 | 
					  - You can use any FRESH or JSON Resume theme with HackMyResume.
 | 
				
			||||||
 | 
					  - Specify a file extension of .all to generate your resume to all
 | 
				
			||||||
 | 
					    available formats supported by the theme. (BUILD command.)
 | 
				
			||||||
 | 
					  - The --theme parameter can specify either the name of a preinstalled
 | 
				
			||||||
 | 
					    theme, or the path to a local FRESH or JSON Resume theme.
 | 
				
			||||||
 | 
					  - Visit https://www.npmjs.com/search?q=jsonresume-theme for a full
 | 
				
			||||||
 | 
					    listing of all available JSON Resume themes.
 | 
				
			||||||
 | 
					  - Visit https://github.com/fluentdesk/fresh-themes for a complete
 | 
				
			||||||
 | 
					    listing of all available FRESH themes.
 | 
				
			||||||
 | 
					  - Report bugs to https://githut.com/hacksalot/HackMyResume/issues.
 | 
				
			||||||
@@ -1,13 +1,23 @@
 | 
				
			|||||||
(function() {
 | 
					 | 
				
			||||||
  var FluentDate, _, lo;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FluentDate = require('../core/fluent-date');
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the AbstractResume class.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module core/abstract-resume
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(function() {
 | 
				
			||||||
 | 
					  var AbstractResume, FluentDate, _, __;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  lo = require('lodash');
 | 
					  __ = require('lodash');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  FluentDate = require('./fluent-date');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  AbstractResume = (function() {
 | 
				
			||||||
 | 
					    function AbstractResume() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = {
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Compute the total duration of the work history.
 | 
					    Compute the total duration of the work history.
 | 
				
			||||||
    @returns The total duration of the sheet's work history, that is, the number
 | 
					    @returns The total duration of the sheet's work history, that is, the number
 | 
				
			||||||
@@ -15,23 +25,18 @@
 | 
				
			|||||||
    *latest end date of all jobs in the work history*. This last condition is for
 | 
					    *latest end date of all jobs in the work history*. This last condition is for
 | 
				
			||||||
    sheets that have overlapping jobs.
 | 
					    sheets that have overlapping jobs.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    run: function(rez, collKey, startKey, endKey, unit) {
 | 
					
 | 
				
			||||||
 | 
					    AbstractResume.prototype.duration = function(collKey, startKey, endKey, unit) {
 | 
				
			||||||
      var firstDate, hist, lastDate, new_e;
 | 
					      var firstDate, hist, lastDate, new_e;
 | 
				
			||||||
      unit = unit || 'years';
 | 
					      unit = unit || 'years';
 | 
				
			||||||
      hist = lo.get(rez, collKey);
 | 
					      hist = __.get(this, collKey);
 | 
				
			||||||
      if (!hist || !hist.length) {
 | 
					      if (!hist || !hist.length) {
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // BEGIN CODE DUPLICATION --> src/inspectors/gap-inspector.coffee (TODO)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Convert the candidate's employment history to an array of dates,
 | 
					 | 
				
			||||||
      // where each element in the array is a start date or an end date of a
 | 
					 | 
				
			||||||
      // job -- it doesn't matter which.
 | 
					 | 
				
			||||||
      new_e = hist.map(function(job) {
 | 
					      new_e = hist.map(function(job) {
 | 
				
			||||||
        var obj;
 | 
					        var obj;
 | 
				
			||||||
        obj = _.pick(job, [startKey, endKey]);
 | 
					        obj = _.pick(job, [startKey, endKey]);
 | 
				
			||||||
        if (!_.has(obj, endKey)) {
 | 
					        if (!_.has(obj, endKey)) {
 | 
				
			||||||
          // Synthesize an end date if this is a "current" gig
 | 
					 | 
				
			||||||
          obj[endKey] = 'current';
 | 
					          obj[endKey] = 'current';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (obj && (obj[startKey] || obj[endKey])) {
 | 
					        if (obj && (obj[startKey] || obj[endKey])) {
 | 
				
			||||||
@@ -43,7 +48,6 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return obj;
 | 
					        return obj;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      // Flatten the array, remove empties, and sort
 | 
					 | 
				
			||||||
      new_e = _.filter(_.flatten(new_e, true), function(v) {
 | 
					      new_e = _.filter(_.flatten(new_e, true), function(v) {
 | 
				
			||||||
        return v && v.length && v[0] && v[0].length;
 | 
					        return v && v.length && v[0] && v[0].length;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -53,13 +57,17 @@
 | 
				
			|||||||
      new_e = _.sortBy(new_e, function(elem) {
 | 
					      new_e = _.sortBy(new_e, function(elem) {
 | 
				
			||||||
        return elem[1].unix();
 | 
					        return elem[1].unix();
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      // END CODE DUPLICATION
 | 
					 | 
				
			||||||
      firstDate = _.first(new_e)[1];
 | 
					      firstDate = _.first(new_e)[1];
 | 
				
			||||||
      lastDate = _.last(new_e)[1];
 | 
					      lastDate = _.last(new_e)[1];
 | 
				
			||||||
      return lastDate.diff(firstDate, unit);
 | 
					      return lastDate.diff(firstDate, unit);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
  };
 | 
					
 | 
				
			||||||
 | 
					    return AbstractResume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  module.exports = AbstractResume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//# sourceMappingURL=duration-inspector.js.map
 | 
					//# sourceMappingURL=abstract-resume.js.map
 | 
				
			||||||
							
								
								
									
										40
									
								
								dist/core/default-formats.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								dist/core/default-formats.js
									
									
									
									
										vendored
									
									
								
							@@ -1,59 +1,55 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Event code definitions.
 | 
				
			||||||
 | 
					@module core/default-formats
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Supported resume formats. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /*
 | 
					 | 
				
			||||||
  Event code definitions.
 | 
					 | 
				
			||||||
  @module core/default-formats
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** Supported resume formats. */
 | 
					 | 
				
			||||||
  module.exports = [
 | 
					  module.exports = [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      name: 'html',
 | 
					      name: 'html',
 | 
				
			||||||
      ext: 'html',
 | 
					      ext: 'html',
 | 
				
			||||||
      gen: new (require('../generators/html-generator'))()
 | 
					      gen: new (require('../generators/html-generator'))()
 | 
				
			||||||
    },
 | 
					    }, {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      name: 'txt',
 | 
					      name: 'txt',
 | 
				
			||||||
      ext: 'txt',
 | 
					      ext: 'txt',
 | 
				
			||||||
      gen: new (require('../generators/text-generator'))()
 | 
					      gen: new (require('../generators/text-generator'))()
 | 
				
			||||||
    },
 | 
					    }, {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      name: 'doc',
 | 
					      name: 'doc',
 | 
				
			||||||
      ext: 'doc',
 | 
					      ext: 'doc',
 | 
				
			||||||
      fmt: 'xml',
 | 
					      fmt: 'xml',
 | 
				
			||||||
      gen: new (require('../generators/word-generator'))()
 | 
					      gen: new (require('../generators/word-generator'))()
 | 
				
			||||||
    },
 | 
					    }, {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      name: 'pdf',
 | 
					      name: 'pdf',
 | 
				
			||||||
      ext: 'pdf',
 | 
					      ext: 'pdf',
 | 
				
			||||||
      fmt: 'html',
 | 
					      fmt: 'html',
 | 
				
			||||||
      is: false,
 | 
					      is: false,
 | 
				
			||||||
      gen: new (require('../generators/html-pdf-cli-generator'))()
 | 
					      gen: new (require('../generators/html-pdf-cli-generator'))()
 | 
				
			||||||
    },
 | 
					    }, {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      name: 'png',
 | 
					      name: 'png',
 | 
				
			||||||
      ext: 'png',
 | 
					      ext: 'png',
 | 
				
			||||||
      fmt: 'html',
 | 
					      fmt: 'html',
 | 
				
			||||||
      is: false,
 | 
					      is: false,
 | 
				
			||||||
      gen: new (require('../generators/html-png-generator'))()
 | 
					      gen: new (require('../generators/html-png-generator'))()
 | 
				
			||||||
    },
 | 
					    }, {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      name: 'md',
 | 
					      name: 'md',
 | 
				
			||||||
      ext: 'md',
 | 
					      ext: 'md',
 | 
				
			||||||
      fmt: 'txt',
 | 
					      fmt: 'txt',
 | 
				
			||||||
      gen: new (require('../generators/markdown-generator'))()
 | 
					      gen: new (require('../generators/markdown-generator'))()
 | 
				
			||||||
    },
 | 
					    }, {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      name: 'json',
 | 
					      name: 'json',
 | 
				
			||||||
      ext: 'json',
 | 
					      ext: 'json',
 | 
				
			||||||
      gen: new (require('../generators/json-generator'))()
 | 
					      gen: new (require('../generators/json-generator'))()
 | 
				
			||||||
    },
 | 
					    }, {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      name: 'yml',
 | 
					      name: 'yml',
 | 
				
			||||||
      ext: 'yml',
 | 
					      ext: 'yml',
 | 
				
			||||||
      fmt: 'yml',
 | 
					      fmt: 'yml',
 | 
				
			||||||
      gen: new (require('../generators/json-yaml-generator'))()
 | 
					      gen: new (require('../generators/json-yaml-generator'))()
 | 
				
			||||||
    },
 | 
					    }, {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      name: 'latex',
 | 
					      name: 'latex',
 | 
				
			||||||
      ext: 'tex',
 | 
					      ext: 'tex',
 | 
				
			||||||
      fmt: 'latex',
 | 
					      fmt: 'latex',
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								dist/core/default-options.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								dist/core/default-options.js
									
									
									
									
										vendored
									
									
								
							@@ -1,20 +1,20 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Event code definitions.
 | 
				
			||||||
 | 
					@module core/default-options
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /*
 | 
					 | 
				
			||||||
  Event code definitions.
 | 
					 | 
				
			||||||
  @module core/default-options
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  module.exports = {
 | 
					  module.exports = {
 | 
				
			||||||
    theme: 'modern',
 | 
					    theme: 'modern',
 | 
				
			||||||
    prettify: {
 | 
					    prettify: {
 | 
				
			||||||
      indent_size: 2,
 | 
					      indent_size: 2,
 | 
				
			||||||
      unformatted: ['em', 'strong'],
 | 
					      unformatted: ['em', 'strong'],
 | 
				
			||||||
      max_char: 80 // ← See lib/html.js in above-linked repo
 | 
					      max_char: 80
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // wrap_line_length: 120, ← Don't use this
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//# sourceMappingURL=default-options.js.map
 | 
					//# sourceMappingURL=default-options.js.map
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								dist/core/event-codes.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								dist/core/event-codes.js
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Event code definitions.
 | 
				
			||||||
 | 
					@module core/event-codes
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /*
 | 
					 | 
				
			||||||
  Event code definitions.
 | 
					 | 
				
			||||||
  @module core/event-codes
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  module.exports = {
 | 
					  module.exports = {
 | 
				
			||||||
    error: -1,
 | 
					    error: -1,
 | 
				
			||||||
    success: 0,
 | 
					    success: 0,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										38
									
								
								dist/core/fluent-date.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								dist/core/fluent-date.js
									
									
									
									
										vendored
									
									
								
							@@ -1,15 +1,18 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					The HackMyResume date representation.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module core/fluent-date
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  The HackMyResume date representation.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module core/fluent-date
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FluentDate, abbr, moment, months;
 | 
					  var FluentDate, abbr, moment, months;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  moment = require('moment');
 | 
					  moment = require('moment');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  require('../utils/string');
 | 
					  require('../utils/string');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  Create a FluentDate from a string or Moment date object. There are a few date
 | 
					  Create a FluentDate from a string or Moment date object. There are a few date
 | 
				
			||||||
  formats to be aware of here.
 | 
					  formats to be aware of here.
 | 
				
			||||||
@@ -25,17 +28,20 @@
 | 
				
			|||||||
  deprecation warnings, it's recommended to either a) explicitly specify the date
 | 
					  deprecation warnings, it's recommended to either a) explicitly specify the date
 | 
				
			||||||
  format or b) use an ISO format. For clarity, we handle these cases explicitly.
 | 
					  format or b) use an ISO format. For clarity, we handle these cases explicitly.
 | 
				
			||||||
  @class FluentDate
 | 
					  @class FluentDate
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  FluentDate = class FluentDate {
 | 
					
 | 
				
			||||||
    constructor(dt) {
 | 
					  FluentDate = (function() {
 | 
				
			||||||
 | 
					    function FluentDate(dt) {
 | 
				
			||||||
      this.rep = this.fmt(dt);
 | 
					      this.rep = this.fmt(dt);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static isCurrent(dt) {
 | 
					    FluentDate.isCurrent = function(dt) {
 | 
				
			||||||
      return !dt || (String.is(dt) && /^(present|now|current)$/.test(dt));
 | 
					      return !dt || (String.is(dt) && /^(present|now|current)$/.test(dt));
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return FluentDate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  months = {};
 | 
					  months = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -58,20 +64,20 @@
 | 
				
			|||||||
    throws = (throws === void 0 || throws === null) || throws;
 | 
					    throws = (throws === void 0 || throws === null) || throws;
 | 
				
			||||||
    if (typeof dt === 'string' || dt instanceof String) {
 | 
					    if (typeof dt === 'string' || dt instanceof String) {
 | 
				
			||||||
      dt = dt.toLowerCase().trim();
 | 
					      dt = dt.toLowerCase().trim();
 | 
				
			||||||
      if (/^(present|now|current)$/.test(dt)) { // "Present", "Now"
 | 
					      if (/^(present|now|current)$/.test(dt)) {
 | 
				
			||||||
        return moment();
 | 
					        return moment();
 | 
				
			||||||
      } else if (/^\D+\s+\d{4}$/.test(dt)) { // "Mar 2015"
 | 
					      } else if (/^\D+\s+\d{4}$/.test(dt)) {
 | 
				
			||||||
        parts = dt.split(' ');
 | 
					        parts = dt.split(' ');
 | 
				
			||||||
        month = months[parts[0]] || abbr[parts[0]];
 | 
					        month = months[parts[0]] || abbr[parts[0]];
 | 
				
			||||||
        temp = parts[1] + '-' + ((ref = month < 10) != null ? ref : '0' + {
 | 
					        temp = parts[1] + '-' + ((ref = month < 10) != null ? ref : '0' + {
 | 
				
			||||||
          month: month.toString()
 | 
					          month: month.toString()
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        return moment(temp, 'YYYY-MM');
 | 
					        return moment(temp, 'YYYY-MM');
 | 
				
			||||||
      } else if (/^\d{4}-\d{1,2}$/.test(dt)) { // "2015-03", "1998-4"
 | 
					      } else if (/^\d{4}-\d{1,2}$/.test(dt)) {
 | 
				
			||||||
        return moment(dt, 'YYYY-MM');
 | 
					        return moment(dt, 'YYYY-MM');
 | 
				
			||||||
      } else if (/^\s*\d{4}\s*$/.test(dt)) { // "2015"
 | 
					      } else if (/^\s*\d{4}\s*$/.test(dt)) {
 | 
				
			||||||
        return moment(dt, 'YYYY');
 | 
					        return moment(dt, 'YYYY');
 | 
				
			||||||
      } else if (/^\s*$/.test(dt)) { // "", " "
 | 
					      } else if (/^\s*$/.test(dt)) {
 | 
				
			||||||
        return moment();
 | 
					        return moment();
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        mt = moment(dt);
 | 
					        mt = moment(dt);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										304
									
								
								dist/core/fresh-resume.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										304
									
								
								dist/core/fresh-resume.js
									
									
									
									
										vendored
									
									
								
							@@ -1,17 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the FRESHResume class.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module core/fresh-resume
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var AbstractResume, CONVERTER, FS, FluentDate, FreshResume, JRSResume, MD, PATH, XML, _, __, _parseDates, extend, moment, validator,
 | 
				
			||||||
  Definition of the FRESHResume class.
 | 
					    extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @module core/fresh-resume
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Convert human-friendly dates into formal Moment.js dates for all collections.
 | 
					 | 
				
			||||||
  We don't want to lose the raw textual date as entered by the user, so we store
 | 
					 | 
				
			||||||
  the Moment-ified date as a separate property with a prefix of .safe. For ex:
 | 
					 | 
				
			||||||
  job.startDate is the date as entered by the user. job.safeStartDate is the
 | 
					 | 
				
			||||||
  parsed Moment.js date that we actually use in processing.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var CONVERTER, FS, FluentDate, FreshResume, JRSResume, MD, PATH, XML, _, __, _parseDates, extend, moment, validator;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FS = require('fs');
 | 
					  FS = require('fs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -37,20 +34,33 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  FluentDate = require('./fluent-date');
 | 
					  FluentDate = require('./fluent-date');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  AbstractResume = require('./abstract-resume');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  A FRESH resume or CV. FRESH resumes are backed by JSON, and each FreshResume
 | 
					  A FRESH resume or CV. FRESH resumes are backed by JSON, and each FreshResume
 | 
				
			||||||
  object is an instantiation of that JSON decorated with utility methods.
 | 
					  object is an instantiation of that JSON decorated with utility methods.
 | 
				
			||||||
  @constructor
 | 
					  @constructor
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  FreshResume = class FreshResume { // extends AbstractResume
 | 
					
 | 
				
			||||||
 | 
					  FreshResume = (function(superClass) {
 | 
				
			||||||
 | 
					    extend1(FreshResume, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function FreshResume() {
 | 
				
			||||||
 | 
					      return FreshResume.__super__.constructor.apply(this, arguments);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Initialize the the FreshResume from JSON string data. */
 | 
					    /** Initialize the the FreshResume from JSON string data. */
 | 
				
			||||||
    parse(stringData, opts) {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.parse = function(stringData, opts) {
 | 
				
			||||||
      var ref;
 | 
					      var ref;
 | 
				
			||||||
      this.imp = (ref = this.imp) != null ? ref : {
 | 
					      this.imp = (ref = this.imp) != null ? ref : {
 | 
				
			||||||
        raw: stringData
 | 
					        raw: stringData
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      return this.parseJSON(JSON.parse(stringData), opts);
 | 
					      return this.parseJSON(JSON.parse(stringData), opts);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Initialize the FreshResume from JSON.
 | 
					    Initialize the FreshResume from JSON.
 | 
				
			||||||
@@ -60,22 +70,27 @@
 | 
				
			|||||||
    @param rep {Object} The raw JSON representation.
 | 
					    @param rep {Object} The raw JSON representation.
 | 
				
			||||||
    @param opts {Object} Resume loading and parsing options.
 | 
					    @param opts {Object} Resume loading and parsing options.
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    date: Perform safe date conversion.
 | 
					      date: Perform safe date conversion.
 | 
				
			||||||
    sort: Sort resume items by date.
 | 
					      sort: Sort resume items by date.
 | 
				
			||||||
    compute: Prepare computed resume totals.
 | 
					      compute: Prepare computed resume totals.
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    parseJSON(rep, opts) {
 | 
					
 | 
				
			||||||
      var ignoreList, privateList, ref, scrubbed, scrubber;
 | 
					    FreshResume.prototype.parseJSON = function(rep, opts) {
 | 
				
			||||||
      if (opts && opts.privatize) {
 | 
					      var ignoreList, ref, scrubbed, that, traverse;
 | 
				
			||||||
        // Ignore any element with the 'ignore: true' or 'private: true' designator.
 | 
					      that = this;
 | 
				
			||||||
        scrubber = require('../utils/resume-scrubber');
 | 
					      traverse = require('traverse');
 | 
				
			||||||
        ({scrubbed, ignoreList, privateList} = scrubber.scrubResume(rep, opts));
 | 
					      ignoreList = [];
 | 
				
			||||||
      }
 | 
					      scrubbed = traverse(rep).map(function(x) {
 | 
				
			||||||
      // Now apply the resume representation onto this object
 | 
					        if (!this.isLeaf && this.node.ignore) {
 | 
				
			||||||
      extend(true, this, opts && opts.privatize ? scrubbed : rep);
 | 
					          if (this.node.ignore === true || this.node.ignore === 'true') {
 | 
				
			||||||
 | 
					            ignoreList.push(this.node);
 | 
				
			||||||
 | 
					            return this.remove();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      extend(true, this, scrubbed);
 | 
				
			||||||
      if (!((ref = this.imp) != null ? ref.processed : void 0)) {
 | 
					      if (!((ref = this.imp) != null ? ref.processed : void 0)) {
 | 
				
			||||||
        // Set up metadata TODO: Clean up metadata on the object model.
 | 
					 | 
				
			||||||
        opts = opts || {};
 | 
					        opts = opts || {};
 | 
				
			||||||
        if (opts.imp === void 0 || opts.imp) {
 | 
					        if (opts.imp === void 0 || opts.imp) {
 | 
				
			||||||
          this.imp = this.imp || {};
 | 
					          this.imp = this.imp || {};
 | 
				
			||||||
@@ -85,7 +100,6 @@
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.imp.processed = true;
 | 
					        this.imp.processed = true;
 | 
				
			||||||
        // Parse dates, sort dates, and calculate computed values
 | 
					 | 
				
			||||||
        (opts.date === void 0 || opts.date) && _parseDates.call(this);
 | 
					        (opts.date === void 0 || opts.date) && _parseDates.call(this);
 | 
				
			||||||
        (opts.sort === void 0 || opts.sort) && this.sort();
 | 
					        (opts.sort === void 0 || opts.sort) && this.sort();
 | 
				
			||||||
        (opts.compute === void 0 || opts.compute) && (this.computed = {
 | 
					        (opts.compute === void 0 || opts.compute) && (this.computed = {
 | 
				
			||||||
@@ -94,43 +108,34 @@
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return this;
 | 
					      return this;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Save the sheet to disk (for environments that have disk access). */
 | 
					    /** Save the sheet to disk (for environments that have disk access). */
 | 
				
			||||||
    save(filename) {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.save = function(filename) {
 | 
				
			||||||
      this.imp.file = filename || this.imp.file;
 | 
					      this.imp.file = filename || this.imp.file;
 | 
				
			||||||
      FS.writeFileSync(this.imp.file, this.stringify(), 'utf8');
 | 
					      FS.writeFileSync(this.imp.file, this.stringify(), 'utf8');
 | 
				
			||||||
      return this;
 | 
					      return this;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Save the sheet to disk in a specific format, either FRESH or JSON Resume.
 | 
					    Save the sheet to disk in a specific format, either FRESH or JSON Resume.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    saveAs(filename, format) {
 | 
					
 | 
				
			||||||
      var newRep, parts, safeFormat, useEdgeSchema;
 | 
					    FreshResume.prototype.saveAs = function(filename, format) {
 | 
				
			||||||
      // If format isn't specified, default to FRESH
 | 
					      var newRep;
 | 
				
			||||||
      safeFormat = (format && format.trim()) || 'FRESH';
 | 
					      if (format !== 'JRS') {
 | 
				
			||||||
      // Validate against the FRESH version regex
 | 
					 | 
				
			||||||
      // freshVersionReg = require '../utils/fresh-version-regex'
 | 
					 | 
				
			||||||
      // if (not freshVersionReg().test( safeFormat ))
 | 
					 | 
				
			||||||
      //   throw badVer: safeFormat
 | 
					 | 
				
			||||||
      parts = safeFormat.split('@');
 | 
					 | 
				
			||||||
      if (parts[0] === 'FRESH') {
 | 
					 | 
				
			||||||
        this.imp.file = filename || this.imp.file;
 | 
					        this.imp.file = filename || this.imp.file;
 | 
				
			||||||
        FS.writeFileSync(this.imp.file, this.stringify(), 'utf8');
 | 
					        FS.writeFileSync(this.imp.file, this.stringify(), 'utf8');
 | 
				
			||||||
      } else if (parts[0] === 'JRS') {
 | 
					 | 
				
			||||||
        useEdgeSchema = parts.length > 1 ? parts[1] === '1' : false;
 | 
					 | 
				
			||||||
        newRep = CONVERTER.toJRS(this, {
 | 
					 | 
				
			||||||
          edge: useEdgeSchema
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        FS.writeFileSync(filename, JRSResume.stringify(newRep), 'utf8');
 | 
					 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        throw {
 | 
					        newRep = CONVERTER.toJRS(this);
 | 
				
			||||||
          badVer: safeFormat
 | 
					        FS.writeFileSync(filename, JRSResume.stringify(newRep), 'utf8');
 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return this;
 | 
					      return this;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Duplicate this FreshResume instance.
 | 
					    Duplicate this FreshResume instance.
 | 
				
			||||||
@@ -138,40 +143,47 @@
 | 
				
			|||||||
    and then passes the result into a new FreshResume instance via .parseJSON.
 | 
					    and then passes the result into a new FreshResume instance via .parseJSON.
 | 
				
			||||||
    We do it this way to create a true clone of the object without re-running any
 | 
					    We do it this way to create a true clone of the object without re-running any
 | 
				
			||||||
    of the associated processing.
 | 
					    of the associated processing.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    dupe() {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.dupe = function() {
 | 
				
			||||||
      var jso, rnew;
 | 
					      var jso, rnew;
 | 
				
			||||||
      jso = extend(true, {}, this);
 | 
					      jso = extend(true, {}, this);
 | 
				
			||||||
      rnew = new FreshResume();
 | 
					      rnew = new FreshResume();
 | 
				
			||||||
      rnew.parseJSON(jso, {});
 | 
					      rnew.parseJSON(jso, {});
 | 
				
			||||||
      return rnew;
 | 
					      return rnew;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Convert this object to a JSON string, sanitizing meta-properties along the
 | 
					    Convert this object to a JSON string, sanitizing meta-properties along the
 | 
				
			||||||
    way.
 | 
					    way.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    stringify() {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.stringify = function() {
 | 
				
			||||||
      return FreshResume.stringify(this);
 | 
					      return FreshResume.stringify(this);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Create a copy of this resume in which all string fields have been run through
 | 
					    Create a copy of this resume in which all string fields have been run through
 | 
				
			||||||
    a transformation function (such as a Markdown filter or XML encoder).
 | 
					    a transformation function (such as a Markdown filter or XML encoder).
 | 
				
			||||||
    TODO: Move this out of FRESHResume.
 | 
					    TODO: Move this out of FRESHResume.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    transformStrings(filt, transformer) {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.transformStrings = function(filt, transformer) {
 | 
				
			||||||
      var ret, trx;
 | 
					      var ret, trx;
 | 
				
			||||||
      ret = this.dupe();
 | 
					      ret = this.dupe();
 | 
				
			||||||
      trx = require('../utils/string-transformer');
 | 
					      trx = require('../utils/string-transformer');
 | 
				
			||||||
      return trx(ret, filt, transformer);
 | 
					      return trx(ret, filt, transformer);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Create a copy of this resume in which all fields have been interpreted as
 | 
					    Create a copy of this resume in which all fields have been interpreted as
 | 
				
			||||||
    Markdown.
 | 
					    Markdown.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    markdownify() {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.markdownify = function() {
 | 
				
			||||||
      var MDIN, trx;
 | 
					      var MDIN, trx;
 | 
				
			||||||
      MDIN = function(txt) {
 | 
					      MDIN = function(txt) {
 | 
				
			||||||
        return MD(txt || '').replace(/^\s*<p>|<\/p>\s*$/gi, '');
 | 
					        return MD(txt || '').replace(/^\s*<p>|<\/p>\s*$/gi, '');
 | 
				
			||||||
@@ -183,49 +195,42 @@
 | 
				
			|||||||
        return MDIN(val);
 | 
					        return MDIN(val);
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      return this.transformStrings(['skills', 'url', 'start', 'end', 'date'], trx);
 | 
					      return this.transformStrings(['skills', 'url', 'start', 'end', 'date'], trx);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Create a copy of this resume in which all fields have been interpreted as
 | 
					    Create a copy of this resume in which all fields have been interpreted as
 | 
				
			||||||
    Markdown.
 | 
					    Markdown.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    xmlify() {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.xmlify = function() {
 | 
				
			||||||
      var trx;
 | 
					      var trx;
 | 
				
			||||||
      trx = function(key, val) {
 | 
					      trx = function(key, val) {
 | 
				
			||||||
        return XML(val);
 | 
					        return XML(val);
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      return this.transformStrings([], trx);
 | 
					      return this.transformStrings([], trx);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Return the resume format. */
 | 
					    /** Return the resume format. */
 | 
				
			||||||
    format() {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.format = function() {
 | 
				
			||||||
      return 'FRESH';
 | 
					      return 'FRESH';
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Return internal metadata. Create if it doesn't exist.
 | 
					    Return internal metadata. Create if it doesn't exist.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    i() {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.i = function() {
 | 
				
			||||||
      return this.imp = this.imp || {};
 | 
					      return this.imp = this.imp || {};
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    Return a unique list of all skills declared in the resume.
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    // TODO: Several problems here:
 | 
					 | 
				
			||||||
    // 1) Confusing name. Easily confused with the keyword-inspector module, which
 | 
					 | 
				
			||||||
    // parses resume body text looking for these same keywords. This should probably
 | 
					 | 
				
			||||||
    // be renamed.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 2) Doesn't bother trying to integrate skills.list with skills.sets if they
 | 
					    /** Return a unique list of all keywords across all skills. */
 | 
				
			||||||
    // happen to declare different skills, and if skills.sets declares ONE skill and
 | 
					 | 
				
			||||||
    // skills.list declared 50, only 1 skill will be registered.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 3) In the future, skill.sets should only be able to use skills declared in
 | 
					    FreshResume.prototype.keywords = function() {
 | 
				
			||||||
    // skills.list. That is, skills.list is the official record of a candidate's
 | 
					 | 
				
			||||||
    // declared skills. skills.sets is just a way of grouping those into skillsets
 | 
					 | 
				
			||||||
    // for easier consumption.
 | 
					 | 
				
			||||||
    keywords() {
 | 
					 | 
				
			||||||
      var flatSkills;
 | 
					      var flatSkills;
 | 
				
			||||||
      flatSkills = [];
 | 
					      flatSkills = [];
 | 
				
			||||||
      if (this.skills) {
 | 
					      if (this.skills) {
 | 
				
			||||||
@@ -243,17 +248,19 @@
 | 
				
			|||||||
        flatSkills = _.uniq(flatSkills);
 | 
					        flatSkills = _.uniq(flatSkills);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return flatSkills;
 | 
					      return flatSkills;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Reset the sheet to an empty state. TODO: refactor/review
 | 
					    Reset the sheet to an empty state. TODO: refactor/review
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    clear(clearMeta) {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.clear = function(clearMeta) {
 | 
				
			||||||
      clearMeta = ((clearMeta === void 0) && true) || clearMeta;
 | 
					      clearMeta = ((clearMeta === void 0) && true) || clearMeta;
 | 
				
			||||||
      if (clearMeta) {
 | 
					      if (clearMeta) {
 | 
				
			||||||
        delete this.imp;
 | 
					        delete this.imp;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      delete this.computed; // Don't use Object.keys() here
 | 
					      delete this.computed;
 | 
				
			||||||
      delete this.employment;
 | 
					      delete this.employment;
 | 
				
			||||||
      delete this.service;
 | 
					      delete this.service;
 | 
				
			||||||
      delete this.education;
 | 
					      delete this.education;
 | 
				
			||||||
@@ -263,12 +270,14 @@
 | 
				
			|||||||
      delete this.interests;
 | 
					      delete this.interests;
 | 
				
			||||||
      delete this.skills;
 | 
					      delete this.skills;
 | 
				
			||||||
      return delete this.social;
 | 
					      return delete this.social;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Get a safe count of the number of things in a section.
 | 
					    Get a safe count of the number of things in a section.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    count(obj) {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.count = function(obj) {
 | 
				
			||||||
      if (!obj) {
 | 
					      if (!obj) {
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -279,11 +288,14 @@
 | 
				
			|||||||
        return obj.sets.length;
 | 
					        return obj.sets.length;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return obj.length || 0;
 | 
					      return obj.length || 0;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    add(moniker) {
 | 
					
 | 
				
			||||||
 | 
					    /** Add work experience to the sheet. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.add = function(moniker) {
 | 
				
			||||||
      var defSheet, newObject;
 | 
					      var defSheet, newObject;
 | 
				
			||||||
      defSheet = FreshResume.default();
 | 
					      defSheet = FreshResume["default"]();
 | 
				
			||||||
      newObject = defSheet[moniker].history ? $.extend(true, {}, defSheet[moniker].history[0]) : moniker === 'skills' ? $.extend(true, {}, defSheet.skills.sets[0]) : $.extend(true, {}, defSheet[moniker][0]);
 | 
					      newObject = defSheet[moniker].history ? $.extend(true, {}, defSheet[moniker].history[0]) : moniker === 'skills' ? $.extend(true, {}, defSheet.skills.sets[0]) : $.extend(true, {}, defSheet[moniker][0]);
 | 
				
			||||||
      this[moniker] = this[moniker] || [];
 | 
					      this[moniker] = this[moniker] || [];
 | 
				
			||||||
      if (this[moniker].history) {
 | 
					      if (this[moniker].history) {
 | 
				
			||||||
@@ -294,53 +306,63 @@
 | 
				
			|||||||
        this[moniker].push(newObject);
 | 
					        this[moniker].push(newObject);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return newObject;
 | 
					      return newObject;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Determine if the sheet includes a specific social profile (eg, GitHub).
 | 
					    Determine if the sheet includes a specific social profile (eg, GitHub).
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    hasProfile(socialNetwork) {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.hasProfile = function(socialNetwork) {
 | 
				
			||||||
      socialNetwork = socialNetwork.trim().toLowerCase();
 | 
					      socialNetwork = socialNetwork.trim().toLowerCase();
 | 
				
			||||||
      return this.social && _.some(this.social, function(p) {
 | 
					      return this.social && _.some(this.social, function(p) {
 | 
				
			||||||
        return p.network.trim().toLowerCase() === socialNetwork;
 | 
					        return p.network.trim().toLowerCase() === socialNetwork;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Return the specified network profile. */
 | 
					    /** Return the specified network profile. */
 | 
				
			||||||
    getProfile(socialNetwork) {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.getProfile = function(socialNetwork) {
 | 
				
			||||||
      socialNetwork = socialNetwork.trim().toLowerCase();
 | 
					      socialNetwork = socialNetwork.trim().toLowerCase();
 | 
				
			||||||
      return this.social && _.find(this.social, function(sn) {
 | 
					      return this.social && _.find(this.social, function(sn) {
 | 
				
			||||||
        return sn.network.trim().toLowerCase() === socialNetwork;
 | 
					        return sn.network.trim().toLowerCase() === socialNetwork;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Return an array of profiles for the specified network, for when the user
 | 
					    Return an array of profiles for the specified network, for when the user
 | 
				
			||||||
    has multiple eg. GitHub accounts.
 | 
					    has multiple eg. GitHub accounts.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    getProfiles(socialNetwork) {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.getProfiles = function(socialNetwork) {
 | 
				
			||||||
      socialNetwork = socialNetwork.trim().toLowerCase();
 | 
					      socialNetwork = socialNetwork.trim().toLowerCase();
 | 
				
			||||||
      return this.social && _.filter(this.social, function(sn) {
 | 
					      return this.social && _.filter(this.social, function(sn) {
 | 
				
			||||||
        return sn.network.trim().toLowerCase() === socialNetwork;
 | 
					        return sn.network.trim().toLowerCase() === socialNetwork;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Determine if the sheet includes a specific skill. */
 | 
					    /** Determine if the sheet includes a specific skill. */
 | 
				
			||||||
    hasSkill(skill) {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.hasSkill = function(skill) {
 | 
				
			||||||
      skill = skill.trim().toLowerCase();
 | 
					      skill = skill.trim().toLowerCase();
 | 
				
			||||||
      return this.skills && _.some(this.skills, function(sk) {
 | 
					      return this.skills && _.some(this.skills, function(sk) {
 | 
				
			||||||
        return sk.keywords && _.some(sk.keywords, function(kw) {
 | 
					        return sk.keywords && _.some(sk.keywords, function(kw) {
 | 
				
			||||||
          return kw.trim().toLowerCase() === skill;
 | 
					          return kw.trim().toLowerCase() === skill;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Validate the sheet against the FRESH Resume schema. */
 | 
					    /** Validate the sheet against the FRESH Resume schema. */
 | 
				
			||||||
    isValid(info) {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.isValid = function(info) {
 | 
				
			||||||
      var ret, schemaObj, validate;
 | 
					      var ret, schemaObj, validate;
 | 
				
			||||||
      schemaObj = require('fresh-resume-schema');
 | 
					      schemaObj = require('fresca');
 | 
				
			||||||
      validator = require('is-my-json-valid');
 | 
					      validator = require('is-my-json-valid');
 | 
				
			||||||
      validate = validator(schemaObj, { // See Note [1].
 | 
					      validate = validator(schemaObj, {
 | 
				
			||||||
        formats: {
 | 
					        formats: {
 | 
				
			||||||
          date: /^\d{4}(?:-(?:0[0-9]{1}|1[0-2]{1})(?:-[0-9]{2})?)?$/
 | 
					          date: /^\d{4}(?:-(?:0[0-9]{1}|1[0-2]{1})(?:-[0-9]{2})?)?$/
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -351,19 +373,19 @@
 | 
				
			|||||||
        this.imp.validationErrors = validate.errors;
 | 
					        this.imp.validationErrors = validate.errors;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return ret;
 | 
					      return ret;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.duration = function(unit) {
 | 
				
			||||||
 | 
					      return FreshResume.__super__.duration.call(this, 'employment.history', 'start', 'end', unit);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    duration(unit) {
 | 
					 | 
				
			||||||
      var inspector;
 | 
					 | 
				
			||||||
      inspector = require('../inspectors/duration-inspector');
 | 
					 | 
				
			||||||
      return inspector.run(this, 'employment.history', 'start', 'end', unit);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Sort dated things on the sheet by start date descending. Assumes that dates
 | 
					    Sort dated things on the sheet by start date descending. Assumes that dates
 | 
				
			||||||
    on the sheet have been processed with _parseDates().
 | 
					    on the sheet have been processed with _parseDates().
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    sort() {
 | 
					
 | 
				
			||||||
 | 
					    FreshResume.prototype.sort = function() {
 | 
				
			||||||
      var byDateDesc, sortSection;
 | 
					      var byDateDesc, sortSection;
 | 
				
			||||||
      byDateDesc = function(a, b) {
 | 
					      byDateDesc = function(a, b) {
 | 
				
			||||||
        if (a.safe.start.isBefore(b.safe.start)) {
 | 
					        if (a.safe.start.isBefore(b.safe.start)) {
 | 
				
			||||||
@@ -397,24 +419,30 @@
 | 
				
			|||||||
          return (a.safe.date.isAfter(b.safe.date) && -1) || 0;
 | 
					          return (a.safe.date.isAfter(b.safe.date) && -1) || 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return FreshResume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(AbstractResume);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  Get the default (starter) sheet.
 | 
					  Get the default (starter) sheet.
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  FreshResume.default = function() {
 | 
					
 | 
				
			||||||
 | 
					  FreshResume["default"] = function() {
 | 
				
			||||||
    return new FreshResume().parseJSON(require('fresh-resume-starter').fresh);
 | 
					    return new FreshResume().parseJSON(require('fresh-resume-starter').fresh);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  Convert the supplied FreshResume to a JSON string, sanitizing meta-properties
 | 
					  Convert the supplied FreshResume to a JSON string, sanitizing meta-properties
 | 
				
			||||||
  along the way.
 | 
					  along the way.
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FreshResume.stringify = function(obj) {
 | 
					  FreshResume.stringify = function(obj) {
 | 
				
			||||||
    var replacer;
 | 
					    var replacer;
 | 
				
			||||||
    replacer = function(key, value) { // Exclude these keys from stringification
 | 
					    replacer = function(key, value) {
 | 
				
			||||||
      var exKeys;
 | 
					      var exKeys;
 | 
				
			||||||
      exKeys = ['imp', 'warnings', 'computed', 'filt', 'ctrl', 'index', 'safe', 'result', 'isModified', 'htmlPreview', 'display_progress_bar'];
 | 
					      exKeys = ['imp', 'warnings', 'computed', 'filt', 'ctrl', 'index', 'safe', 'result', 'isModified', 'htmlPreview', 'display_progress_bar'];
 | 
				
			||||||
      if (_.some(exKeys, function(val) {
 | 
					      if (_.some(exKeys, function(val) {
 | 
				
			||||||
@@ -428,11 +456,19 @@
 | 
				
			|||||||
    return JSON.stringify(obj, replacer, 2);
 | 
					    return JSON.stringify(obj, replacer, 2);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Convert human-friendly dates into formal Moment.js dates for all collections.
 | 
				
			||||||
 | 
					  We don't want to lose the raw textual date as entered by the user, so we store
 | 
				
			||||||
 | 
					  the Moment-ified date as a separate property with a prefix of .safe. For ex:
 | 
				
			||||||
 | 
					  job.startDate is the date as entered by the user. job.safeStartDate is the
 | 
				
			||||||
 | 
					  parsed Moment.js date that we actually use in processing.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _parseDates = function() {
 | 
					  _parseDates = function() {
 | 
				
			||||||
    var _fmt, replaceDatesInObject, that;
 | 
					    var _fmt, replaceDatesInObject, that;
 | 
				
			||||||
    _fmt = require('./fluent-date').fmt;
 | 
					    _fmt = require('./fluent-date').fmt;
 | 
				
			||||||
    that = this;
 | 
					    that = this;
 | 
				
			||||||
    // TODO: refactor recursion
 | 
					 | 
				
			||||||
    replaceDatesInObject = function(obj) {
 | 
					    replaceDatesInObject = function(obj) {
 | 
				
			||||||
      if (!obj) {
 | 
					      if (!obj) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
@@ -464,15 +500,11 @@
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Export the Sheet function/ctor. */
 | 
					  /** Export the Sheet function/ctor. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = FreshResume;
 | 
					  module.exports = FreshResume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Note 1: Adjust default date validation to allow YYYY and YYYY-MM formats
 | 
					 | 
				
			||||||
// in addition to YYYY-MM-DD. The original regex:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//     /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//# sourceMappingURL=fresh-resume.js.map
 | 
					//# sourceMappingURL=fresh-resume.js.map
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										125
									
								
								dist/core/fresh-theme.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										125
									
								
								dist/core/fresh-theme.js
									
									
									
									
										vendored
									
									
								
							@@ -1,12 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the FRESHTheme class.
 | 
				
			||||||
 | 
					@module core/fresh-theme
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the FRESHTheme class.
 | 
					 | 
				
			||||||
  @module core/fresh-theme
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /* Load and parse theme source files. */
 | 
					 | 
				
			||||||
  /* Load a single theme file. */
 | 
					 | 
				
			||||||
  /* Return a more friendly name for certain formats. */
 | 
					 | 
				
			||||||
  var EXTEND, FRESHTheme, FS, HMSTATUS, PATH, READFILES, _, _load, _loadOne, friendlyName, loadSafeJson, moment, parsePath, pathExists, validator;
 | 
					  var EXTEND, FRESHTheme, FS, HMSTATUS, PATH, READFILES, _, _load, _loadOne, friendlyName, loadSafeJson, moment, parsePath, pathExists, validator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FS = require('fs');
 | 
					  FS = require('fs');
 | 
				
			||||||
@@ -31,98 +30,82 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  READFILES = require('recursive-readdir-sync');
 | 
					  READFILES = require('recursive-readdir-sync');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* A representation of a FRESH theme asset.
 | 
					  /* A representation of a FRESH theme asset.
 | 
				
			||||||
  @class FRESHTheme */
 | 
					  @class FRESHTheme
 | 
				
			||||||
  FRESHTheme = class FRESHTheme {
 | 
					   */
 | 
				
			||||||
    constructor() {
 | 
					
 | 
				
			||||||
      this.baseFolder = 'src';
 | 
					  FRESHTheme = (function() {
 | 
				
			||||||
      return;
 | 
					    function FRESHTheme() {}
 | 
				
			||||||
    }
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Open and parse the specified theme. */
 | 
					    /* Open and parse the specified theme. */
 | 
				
			||||||
    open(themeFolder) {
 | 
					
 | 
				
			||||||
 | 
					    FRESHTheme.prototype.open = function(themeFolder) {
 | 
				
			||||||
      var cached, formatsHash, pathInfo, that, themeFile, themeInfo;
 | 
					      var cached, formatsHash, pathInfo, that, themeFile, themeInfo;
 | 
				
			||||||
      this.folder = themeFolder;
 | 
					      this.folder = themeFolder;
 | 
				
			||||||
      // Open the [theme-name].json file; should have the same name as folder
 | 
					 | 
				
			||||||
      pathInfo = parsePath(themeFolder);
 | 
					      pathInfo = parsePath(themeFolder);
 | 
				
			||||||
      // Set up a formats hash for the theme
 | 
					 | 
				
			||||||
      formatsHash = {};
 | 
					      formatsHash = {};
 | 
				
			||||||
      // Load the theme
 | 
					 | 
				
			||||||
      themeFile = PATH.join(themeFolder, 'theme.json');
 | 
					      themeFile = PATH.join(themeFolder, 'theme.json');
 | 
				
			||||||
      themeInfo = loadSafeJson(themeFile);
 | 
					      themeInfo = loadSafeJson(themeFile);
 | 
				
			||||||
      if (themeInfo.ex) {
 | 
					      if (themeInfo.ex) {
 | 
				
			||||||
        throw {
 | 
					        throw {
 | 
				
			||||||
          fluenterror: themeInfo.ex.op === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError
 | 
					          fluenterror: themeInfo.ex.operation === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError,
 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        ({
 | 
					 | 
				
			||||||
          inner: themeInfo.ex.inner
 | 
					          inner: themeInfo.ex.inner
 | 
				
			||||||
        });
 | 
					        };
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      that = this;
 | 
					      that = this;
 | 
				
			||||||
      // Move properties from the theme JSON file to the theme object
 | 
					 | 
				
			||||||
      EXTEND(true, this, themeInfo.json);
 | 
					      EXTEND(true, this, themeInfo.json);
 | 
				
			||||||
      // Check for an "inherits" entry in the theme JSON.
 | 
					 | 
				
			||||||
      if (this.inherits) {
 | 
					      if (this.inherits) {
 | 
				
			||||||
        cached = {};
 | 
					        cached = {};
 | 
				
			||||||
        _.each(this.inherits, function(th, key) {
 | 
					        _.each(this.inherits, function(th, key) {
 | 
				
			||||||
          var d, themePath, themesObj;
 | 
					          var d, themePath, themesFolder;
 | 
				
			||||||
          // First, see if this is one of the predefined FRESH themes. There are
 | 
					          themesFolder = require.resolve('fresh-themes');
 | 
				
			||||||
          // only a handful of these, but they may change over time, so we need to
 | 
					          d = parsePath(themeFolder).dirname;
 | 
				
			||||||
          // query the official source of truth: the fresh-themes repository, which
 | 
					          themePath = PATH.join(d, th);
 | 
				
			||||||
          // mounts the themes conveniently by name to the module object, and which
 | 
					 | 
				
			||||||
          // is embedded locally inside the HackMyResume installation.
 | 
					 | 
				
			||||||
          // TODO: merge this code with
 | 
					 | 
				
			||||||
          themesObj = require('fresh-themes');
 | 
					 | 
				
			||||||
          if (_.has(themesObj.themes, th)) {
 | 
					 | 
				
			||||||
            themePath = PATH.join(parsePath(require.resolve('fresh-themes')).dirname, '/themes/', th);
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            d = parsePath(th).dirname;
 | 
					 | 
				
			||||||
            themePath = PATH.join(d, th);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          cached[th] = cached[th] || new FRESHTheme().open(themePath);
 | 
					          cached[th] = cached[th] || new FRESHTheme().open(themePath);
 | 
				
			||||||
          return formatsHash[key] = cached[th].getFormat(key);
 | 
					          return formatsHash[key] = cached[th].getFormat(key);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // Load theme files
 | 
					 | 
				
			||||||
      formatsHash = _load.call(this, formatsHash);
 | 
					      formatsHash = _load.call(this, formatsHash);
 | 
				
			||||||
      // Cache
 | 
					 | 
				
			||||||
      this.formats = formatsHash;
 | 
					      this.formats = formatsHash;
 | 
				
			||||||
      // Set the official theme name
 | 
					 | 
				
			||||||
      this.name = parsePath(this.folder).name;
 | 
					      this.name = parsePath(this.folder).name;
 | 
				
			||||||
      return this;
 | 
					      return this;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Determine if the theme supports the specified output format. */
 | 
					    /* Determine if the theme supports the specified output format. */
 | 
				
			||||||
    hasFormat(fmt) {
 | 
					
 | 
				
			||||||
 | 
					    FRESHTheme.prototype.hasFormat = function(fmt) {
 | 
				
			||||||
      return _.has(this.formats, fmt);
 | 
					      return _.has(this.formats, fmt);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Determine if the theme supports the specified output format. */
 | 
					    /* Determine if the theme supports the specified output format. */
 | 
				
			||||||
    getFormat(fmt) {
 | 
					 | 
				
			||||||
      return this.formats[fmt];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    FRESHTheme.prototype.getFormat = function(fmt) {
 | 
				
			||||||
 | 
					      return this.formats[fmt];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return FRESHTheme;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Load and parse theme source files. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _load = function(formatsHash) {
 | 
					  _load = function(formatsHash) {
 | 
				
			||||||
    var copyOnly, fmts, jsFiles, major, that, tplFolder;
 | 
					    var copyOnly, fmts, major, that, tplFolder;
 | 
				
			||||||
    that = this;
 | 
					    that = this;
 | 
				
			||||||
    major = false;
 | 
					    major = false;
 | 
				
			||||||
    tplFolder = PATH.join(this.folder, this.baseFolder);
 | 
					    tplFolder = PATH.join(this.folder, 'src');
 | 
				
			||||||
    copyOnly = ['.ttf', '.otf', '.png', '.jpg', '.jpeg', '.pdf'];
 | 
					    copyOnly = ['.ttf', '.otf', '.png', '.jpg', '.jpeg', '.pdf'];
 | 
				
			||||||
    // Iterate over all files in the theme folder, producing an array, fmts,
 | 
					 | 
				
			||||||
    // containing info for each file. While we're doing that, also build up
 | 
					 | 
				
			||||||
    // the formatsHash object.
 | 
					 | 
				
			||||||
    fmts = READFILES(tplFolder).map(function(absPath) {
 | 
					    fmts = READFILES(tplFolder).map(function(absPath) {
 | 
				
			||||||
      return _loadOne.call(this, absPath, formatsHash, tplFolder);
 | 
					      return _loadOne.call(this, absPath, formatsHash, tplFolder);
 | 
				
			||||||
    }, this);
 | 
					    }, this);
 | 
				
			||||||
    // Now, get all the CSS files...
 | 
					 | 
				
			||||||
    this.cssFiles = fmts.filter(function(fmt) {
 | 
					    this.cssFiles = fmts.filter(function(fmt) {
 | 
				
			||||||
      return fmt && (fmt.ext === 'css');
 | 
					      return fmt && (fmt.ext === 'css');
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // For each CSS file, get its corresponding HTML file. It's possible that
 | 
					 | 
				
			||||||
    // a theme can have a CSS file but *no* HTML file, as when a theme author
 | 
					 | 
				
			||||||
    // creates a pure CSS override of an existing theme.
 | 
					 | 
				
			||||||
    this.cssFiles.forEach(function(cssf) {
 | 
					    this.cssFiles.forEach(function(cssf) {
 | 
				
			||||||
      var idx;
 | 
					      var idx;
 | 
				
			||||||
      idx = _.findIndex(fmts, function(fmt) {
 | 
					      idx = _.findIndex(fmts, function(fmt) {
 | 
				
			||||||
@@ -134,8 +117,6 @@
 | 
				
			|||||||
        return fmts[idx].cssPath = cssf.path;
 | 
					        return fmts[idx].cssPath = cssf.path;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        if (that.inherits) {
 | 
					        if (that.inherits) {
 | 
				
			||||||
          // Found a CSS file without an HTML file in a theme that inherits
 | 
					 | 
				
			||||||
          // from another theme. This is the override CSS file.
 | 
					 | 
				
			||||||
          return that.overrides = {
 | 
					          return that.overrides = {
 | 
				
			||||||
            file: cssf.path,
 | 
					            file: cssf.path,
 | 
				
			||||||
            data: cssf.data
 | 
					            data: cssf.data
 | 
				
			||||||
@@ -143,28 +124,19 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // Now, save all the javascript file paths to a theme property.
 | 
					 | 
				
			||||||
    jsFiles = fmts.filter(function(fmt) {
 | 
					 | 
				
			||||||
      return fmt && (fmt.ext === 'js');
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    this.jsFiles = jsFiles.map(function(jsf) {
 | 
					 | 
				
			||||||
      return jsf['path'];
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    return formatsHash;
 | 
					    return formatsHash;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Load a single theme file. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _loadOne = function(absPath, formatsHash, tplFolder) {
 | 
					  _loadOne = function(absPath, formatsHash, tplFolder) {
 | 
				
			||||||
    var absPathSafe, act, defFormats, idx, isPrimary, obj, outFmt, pathInfo, portion, ref, ref1, reg, res;
 | 
					    var absPathSafe, act, defFormats, idx, isPrimary, obj, outFmt, pathInfo, portion, ref, ref1, reg, res;
 | 
				
			||||||
    pathInfo = parsePath(absPath);
 | 
					    pathInfo = parsePath(absPath);
 | 
				
			||||||
    if (pathInfo.basename.toLowerCase() === 'theme.json') {
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    absPathSafe = absPath.trim().toLowerCase();
 | 
					    absPathSafe = absPath.trim().toLowerCase();
 | 
				
			||||||
    outFmt = '';
 | 
					    outFmt = '';
 | 
				
			||||||
    act = 'copy';
 | 
					    act = 'copy';
 | 
				
			||||||
    isPrimary = false;
 | 
					    isPrimary = false;
 | 
				
			||||||
    // If this is an "explicit" theme, all files of importance are specified in
 | 
					 | 
				
			||||||
    // the "transform" section of the theme.json file.
 | 
					 | 
				
			||||||
    if (this.explicit) {
 | 
					    if (this.explicit) {
 | 
				
			||||||
      outFmt = _.find(Object.keys(this.formats), function(fmtKey) {
 | 
					      outFmt = _.find(Object.keys(this.formats), function(fmtKey) {
 | 
				
			||||||
        var fmtVal;
 | 
					        var fmtVal;
 | 
				
			||||||
@@ -180,9 +152,6 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!outFmt) {
 | 
					    if (!outFmt) {
 | 
				
			||||||
      // If this file lives in a specific format folder within the theme,
 | 
					 | 
				
			||||||
      // such as "/latex" or "/html", then that format is the implicit output
 | 
					 | 
				
			||||||
      // format for all files within the folder
 | 
					 | 
				
			||||||
      portion = pathInfo.dirname.replace(tplFolder, '');
 | 
					      portion = pathInfo.dirname.replace(tplFolder, '');
 | 
				
			||||||
      if (portion && portion.trim()) {
 | 
					      if (portion && portion.trim()) {
 | 
				
			||||||
        if (portion[1] === '_') {
 | 
					        if (portion[1] === '_') {
 | 
				
			||||||
@@ -218,16 +187,13 @@
 | 
				
			|||||||
        return form.name === outFmt && pathInfo.extname !== '.css';
 | 
					        return form.name === outFmt && pathInfo.extname !== '.css';
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Make sure we have a valid formatsHash
 | 
					 | 
				
			||||||
    formatsHash[outFmt] = formatsHash[outFmt] || {
 | 
					    formatsHash[outFmt] = formatsHash[outFmt] || {
 | 
				
			||||||
      outFormat: outFmt,
 | 
					      outFormat: outFmt,
 | 
				
			||||||
      files: []
 | 
					      files: []
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    // Move symlink descriptions from theme.json to the format
 | 
					 | 
				
			||||||
    if ((ref = this.formats) != null ? (ref1 = ref[outFmt]) != null ? ref1.symLinks : void 0 : void 0) {
 | 
					    if ((ref = this.formats) != null ? (ref1 = ref[outFmt]) != null ? ref1.symLinks : void 0 : void 0) {
 | 
				
			||||||
      formatsHash[outFmt].symLinks = this.formats[outFmt].symLinks;
 | 
					      formatsHash[outFmt].symLinks = this.formats[outFmt].symLinks;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Create the file representation object
 | 
					 | 
				
			||||||
    obj = {
 | 
					    obj = {
 | 
				
			||||||
      action: act,
 | 
					      action: act,
 | 
				
			||||||
      primary: isPrimary,
 | 
					      primary: isPrimary,
 | 
				
			||||||
@@ -236,15 +202,16 @@
 | 
				
			|||||||
      ext: pathInfo.extname.slice(1),
 | 
					      ext: pathInfo.extname.slice(1),
 | 
				
			||||||
      title: friendlyName(outFmt),
 | 
					      title: friendlyName(outFmt),
 | 
				
			||||||
      pre: outFmt,
 | 
					      pre: outFmt,
 | 
				
			||||||
      // outFormat: outFmt || pathInfo.name,
 | 
					 | 
				
			||||||
      data: FS.readFileSync(absPath, 'utf8'),
 | 
					      data: FS.readFileSync(absPath, 'utf8'),
 | 
				
			||||||
      css: null
 | 
					      css: null
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    // Add this file to the list of files for this format type.
 | 
					 | 
				
			||||||
    formatsHash[outFmt].files.push(obj);
 | 
					    formatsHash[outFmt].files.push(obj);
 | 
				
			||||||
    return obj;
 | 
					    return obj;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Return a more friendly name for certain formats. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  friendlyName = function(val) {
 | 
					  friendlyName = function(val) {
 | 
				
			||||||
    var friendly;
 | 
					    var friendly;
 | 
				
			||||||
    val = (val && val.trim().toLowerCase()) || '';
 | 
					    val = (val && val.trim().toLowerCase()) || '';
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										560
									
								
								dist/core/jrs-resume.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										560
									
								
								dist/core/jrs-resume.js
									
									
									
									
										vendored
									
									
								
							@@ -1,17 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the JRSResume class.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module core/jrs-resume
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var AbstractResume, CONVERTER, FS, JRSResume, MD, PATH, _, _parseDates, extend, moment, validator,
 | 
				
			||||||
  Definition of the JRSResume class.
 | 
					    extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @module core/jrs-resume
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Convert human-friendly dates into formal Moment.js dates for all collections.
 | 
					 | 
				
			||||||
  We don't want to lose the raw textual date as entered by the user, so we store
 | 
					 | 
				
			||||||
  the Moment-ified date as a separate property with a prefix of .safe. For ex:
 | 
					 | 
				
			||||||
  job.startDate is the date as entered by the user. job.safeStartDate is the
 | 
					 | 
				
			||||||
  parsed Moment.js date that we actually use in processing.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var CONVERTER, FS, JRSResume, MD, PATH, _, _parseDates, extend, moment, validator;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FS = require('fs');
 | 
					  FS = require('fs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,247 +26,158 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  moment = require('moment');
 | 
					  moment = require('moment');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  JRSResume = (function() {
 | 
					  AbstractResume = require('./abstract-resume');
 | 
				
			||||||
    /** Reset the sheet to an empty state. */
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  A JRS resume or CV. JRS resumes are backed by JSON, and each JRSResume object
 | 
				
			||||||
 | 
					  is an instantiation of that JSON decorated with utility methods.
 | 
				
			||||||
 | 
					  @class JRSResume
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  JRSResume = (function(superClass) {
 | 
				
			||||||
    var clear;
 | 
					    var clear;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    extend1(JRSResume, superClass);
 | 
				
			||||||
    A JRS resume or CV. JRS resumes are backed by JSON, and each JRSResume object
 | 
					 | 
				
			||||||
    is an instantiation of that JSON decorated with utility methods.
 | 
					 | 
				
			||||||
    @class JRSResume
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    class JRSResume { // extends AbstractResume
 | 
					 | 
				
			||||||
      /** Initialize the the JSResume from string. */
 | 
					 | 
				
			||||||
      parse(stringData, opts) {
 | 
					 | 
				
			||||||
        var ref;
 | 
					 | 
				
			||||||
        this.imp = (ref = this.imp) != null ? ref : {
 | 
					 | 
				
			||||||
          raw: stringData
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        return this.parseJSON(JSON.parse(stringData), opts);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      /**
 | 
					    function JRSResume() {
 | 
				
			||||||
      Initialize the JRSResume object from JSON.
 | 
					      return JRSResume.__super__.constructor.apply(this, arguments);
 | 
				
			||||||
      Open and parse the specified JRS resume. Merge the JSON object model onto
 | 
					    }
 | 
				
			||||||
      this Sheet instance with extend() and convert sheet dates to a safe &
 | 
					
 | 
				
			||||||
      consistent format. Then sort each section by startDate descending.
 | 
					
 | 
				
			||||||
      @param rep {Object} The raw JSON representation.
 | 
					    /** Initialize the the JSResume from string. */
 | 
				
			||||||
      @param opts {Object} Resume loading and parsing options.
 | 
					
 | 
				
			||||||
      {
 | 
					    JRSResume.prototype.parse = function(stringData, opts) {
 | 
				
			||||||
 | 
					      var ref;
 | 
				
			||||||
 | 
					      this.imp = (ref = this.imp) != null ? ref : {
 | 
				
			||||||
 | 
					        raw: stringData
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      return this.parseJSON(JSON.parse(stringData), opts);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    Initialize the JRSResume object from JSON.
 | 
				
			||||||
 | 
					    Open and parse the specified JRS resume. Merge the JSON object model onto
 | 
				
			||||||
 | 
					    this Sheet instance with extend() and convert sheet dates to a safe &
 | 
				
			||||||
 | 
					    consistent format. Then sort each section by startDate descending.
 | 
				
			||||||
 | 
					    @param rep {Object} The raw JSON representation.
 | 
				
			||||||
 | 
					    @param opts {Object} Resume loading and parsing options.
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
      date: Perform safe date conversion.
 | 
					      date: Perform safe date conversion.
 | 
				
			||||||
      sort: Sort resume items by date.
 | 
					      sort: Sort resume items by date.
 | 
				
			||||||
      compute: Prepare computed resume totals.
 | 
					      compute: Prepare computed resume totals.
 | 
				
			||||||
      }
 | 
					    }
 | 
				
			||||||
      */
 | 
					     */
 | 
				
			||||||
      parseJSON(rep, opts) {
 | 
					
 | 
				
			||||||
        var ignoreList, privateList, ref, scrubbed, scrubber;
 | 
					    JRSResume.prototype.parseJSON = function(rep, opts) {
 | 
				
			||||||
 | 
					      var ignoreList, ref, scrubbed, that, traverse;
 | 
				
			||||||
 | 
					      opts = opts || {};
 | 
				
			||||||
 | 
					      that = this;
 | 
				
			||||||
 | 
					      traverse = require('traverse');
 | 
				
			||||||
 | 
					      ignoreList = [];
 | 
				
			||||||
 | 
					      scrubbed = traverse(rep).map(function(x) {
 | 
				
			||||||
 | 
					        if (!this.isLeaf && this.node.ignore) {
 | 
				
			||||||
 | 
					          if (this.node.ignore === true || this.node.ignore === 'true') {
 | 
				
			||||||
 | 
					            ignoreList.push(this.node);
 | 
				
			||||||
 | 
					            return this.remove();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      extend(true, this, scrubbed);
 | 
				
			||||||
 | 
					      if (!((ref = this.imp) != null ? ref.processed : void 0)) {
 | 
				
			||||||
        opts = opts || {};
 | 
					        opts = opts || {};
 | 
				
			||||||
        if (opts.privatize) {
 | 
					        if (opts.imp === void 0 || opts.imp) {
 | 
				
			||||||
          scrubber = require('../utils/resume-scrubber');
 | 
					 | 
				
			||||||
          // Ignore any element with the 'ignore: true' or 'private: true' designator.
 | 
					 | 
				
			||||||
          ({scrubbed, ignoreList, privateList} = scrubber.scrubResume(rep, opts));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // Extend resume properties onto ourself.
 | 
					 | 
				
			||||||
        extend(true, this, opts.privatize ? scrubbed : rep);
 | 
					 | 
				
			||||||
        if (!((ref = this.imp) != null ? ref.processed : void 0)) {
 | 
					 | 
				
			||||||
          // Set up metadata TODO: Clean up metadata on the object model.
 | 
					 | 
				
			||||||
          opts = opts || {};
 | 
					 | 
				
			||||||
          if (opts.imp === void 0 || opts.imp) {
 | 
					 | 
				
			||||||
            this.imp = this.imp || {};
 | 
					 | 
				
			||||||
            this.imp.title = (opts.title || this.imp.title) || this.basics.name;
 | 
					 | 
				
			||||||
            if (!this.imp.raw) {
 | 
					 | 
				
			||||||
              this.imp.raw = JSON.stringify(rep);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          this.imp.processed = true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // Parse dates, sort dates, and calculate computed values
 | 
					 | 
				
			||||||
        (opts.date === void 0 || opts.date) && _parseDates.call(this);
 | 
					 | 
				
			||||||
        (opts.sort === void 0 || opts.sort) && this.sort();
 | 
					 | 
				
			||||||
        if (opts.compute === void 0 || opts.compute) {
 | 
					 | 
				
			||||||
          this.basics.computed = {
 | 
					 | 
				
			||||||
            numYears: this.duration(),
 | 
					 | 
				
			||||||
            keywords: this.keywords()
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return this;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      /** Save the sheet to disk (for environments that have disk access). */
 | 
					 | 
				
			||||||
      save(filename) {
 | 
					 | 
				
			||||||
        this.imp.file = filename || this.imp.file;
 | 
					 | 
				
			||||||
        FS.writeFileSync(this.imp.file, this.stringify(this), 'utf8');
 | 
					 | 
				
			||||||
        return this;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      /** Save the sheet to disk in a specific format, either FRESH or JRS. */
 | 
					 | 
				
			||||||
      saveAs(filename, format) {
 | 
					 | 
				
			||||||
        var newRep, stringRep;
 | 
					 | 
				
			||||||
        if (format === 'JRS') {
 | 
					 | 
				
			||||||
          this.imp.file = filename || this.imp.file;
 | 
					 | 
				
			||||||
          FS.writeFileSync(this.imp.file, this.stringify(), 'utf8');
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          newRep = CONVERTER.toFRESH(this);
 | 
					 | 
				
			||||||
          stringRep = CONVERTER.toSTRING(newRep);
 | 
					 | 
				
			||||||
          FS.writeFileSync(filename, stringRep, 'utf8');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return this;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      /** Return the resume format. */
 | 
					 | 
				
			||||||
      format() {
 | 
					 | 
				
			||||||
        return 'JRS';
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      stringify() {
 | 
					 | 
				
			||||||
        return JRSResume.stringify(this);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      /** Return a unique list of all keywords across all skills. */
 | 
					 | 
				
			||||||
      keywords() {
 | 
					 | 
				
			||||||
        var flatSkills;
 | 
					 | 
				
			||||||
        flatSkills = [];
 | 
					 | 
				
			||||||
        if (this.skills && this.skills.length) {
 | 
					 | 
				
			||||||
          this.skills.forEach(function(s) {
 | 
					 | 
				
			||||||
            return flatSkills = _.union(flatSkills, s.keywords);
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return flatSkills;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      /**
 | 
					 | 
				
			||||||
      Return internal metadata. Create if it doesn't exist.
 | 
					 | 
				
			||||||
      JSON Resume v0.0.0 doesn't allow additional properties at the root level,
 | 
					 | 
				
			||||||
      so tuck this into the .basic sub-object.
 | 
					 | 
				
			||||||
      */
 | 
					 | 
				
			||||||
      i() {
 | 
					 | 
				
			||||||
        var ref;
 | 
					 | 
				
			||||||
        return this.imp = (ref = this.imp) != null ? ref : {};
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      /** Add work experience to the sheet. */
 | 
					 | 
				
			||||||
      add(moniker) {
 | 
					 | 
				
			||||||
        var defSheet, newObject;
 | 
					 | 
				
			||||||
        defSheet = JRSResume.default();
 | 
					 | 
				
			||||||
        newObject = $.extend(true, {}, defSheet[moniker][0]);
 | 
					 | 
				
			||||||
        this[moniker] = this[moniker] || [];
 | 
					 | 
				
			||||||
        this[moniker].push(newObject);
 | 
					 | 
				
			||||||
        return newObject;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      /** Determine if the sheet includes a specific social profile (eg, GitHub). */
 | 
					 | 
				
			||||||
      hasProfile(socialNetwork) {
 | 
					 | 
				
			||||||
        socialNetwork = socialNetwork.trim().toLowerCase();
 | 
					 | 
				
			||||||
        return this.basics.profiles && _.some(this.basics.profiles, function(p) {
 | 
					 | 
				
			||||||
          return p.network.trim().toLowerCase() === socialNetwork;
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      /** Determine if the sheet includes a specific skill. */
 | 
					 | 
				
			||||||
      hasSkill(skill) {
 | 
					 | 
				
			||||||
        skill = skill.trim().toLowerCase();
 | 
					 | 
				
			||||||
        return this.skills && _.some(this.skills, function(sk) {
 | 
					 | 
				
			||||||
          return sk.keywords && _.some(sk.keywords, function(kw) {
 | 
					 | 
				
			||||||
            return kw.trim().toLowerCase() === skill;
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      /** Validate the sheet against the JSON Resume schema. */
 | 
					 | 
				
			||||||
      isValid() { // TODO: ↓ fix this path ↓
 | 
					 | 
				
			||||||
        var ret, schema, schemaObj, temp, validate;
 | 
					 | 
				
			||||||
        schema = FS.readFileSync(PATH.join(__dirname, 'resume.json'), 'utf8');
 | 
					 | 
				
			||||||
        schemaObj = JSON.parse(schema);
 | 
					 | 
				
			||||||
        validator = require('is-my-json-valid');
 | 
					 | 
				
			||||||
        validate = validator(schemaObj, { // Note [1]
 | 
					 | 
				
			||||||
          formats: {
 | 
					 | 
				
			||||||
            date: /^\d{4}(?:-(?:0[0-9]{1}|1[0-2]{1})(?:-[0-9]{2})?)?$/
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        temp = this.imp;
 | 
					 | 
				
			||||||
        delete this.imp;
 | 
					 | 
				
			||||||
        ret = validate(this);
 | 
					 | 
				
			||||||
        this.imp = temp;
 | 
					 | 
				
			||||||
        if (!ret) {
 | 
					 | 
				
			||||||
          this.imp = this.imp || {};
 | 
					          this.imp = this.imp || {};
 | 
				
			||||||
          this.imp.validationErrors = validate.errors;
 | 
					          this.imp.title = (opts.title || this.imp.title) || this.basics.name;
 | 
				
			||||||
 | 
					          if (!this.imp.raw) {
 | 
				
			||||||
 | 
					            this.imp.raw = JSON.stringify(rep);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return ret;
 | 
					        this.imp.processed = true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      (opts.date === void 0 || opts.date) && _parseDates.call(this);
 | 
				
			||||||
      duration(unit) {
 | 
					      (opts.sort === void 0 || opts.sort) && this.sort();
 | 
				
			||||||
        var inspector;
 | 
					      if (opts.compute === void 0 || opts.compute) {
 | 
				
			||||||
        inspector = require('../inspectors/duration-inspector');
 | 
					        this.basics.computed = {
 | 
				
			||||||
        return inspector.run(this, 'work', 'startDate', 'endDate', unit);
 | 
					          numYears: this.duration(),
 | 
				
			||||||
      }
 | 
					          keywords: this.keywords()
 | 
				
			||||||
 | 
					 | 
				
			||||||
      /**
 | 
					 | 
				
			||||||
      Sort dated things on the sheet by start date descending. Assumes that dates
 | 
					 | 
				
			||||||
      on the sheet have been processed with _parseDates().
 | 
					 | 
				
			||||||
      */
 | 
					 | 
				
			||||||
      sort() {
 | 
					 | 
				
			||||||
        var byDateDesc;
 | 
					 | 
				
			||||||
        byDateDesc = function(a, b) {
 | 
					 | 
				
			||||||
          if (a.safeStartDate.isBefore(b.safeStartDate)) {
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            return (a.safeStartDate.isAfter(b.safeStartDate) && -1) || 0;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        this.work && this.work.sort(byDateDesc);
 | 
					 | 
				
			||||||
        this.education && this.education.sort(byDateDesc);
 | 
					 | 
				
			||||||
        this.volunteer && this.volunteer.sort(byDateDesc);
 | 
					 | 
				
			||||||
        this.awards && this.awards.sort(function(a, b) {
 | 
					 | 
				
			||||||
          if (a.safeDate.isBefore(b.safeDate)) {
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            return (a.safeDate.isAfter(b.safeDate) && -1) || 0;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        return this.publications && this.publications.sort(function(a, b) {
 | 
					 | 
				
			||||||
          if (a.safeReleaseDate.isBefore(b.safeReleaseDate)) {
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            return (a.safeReleaseDate.isAfter(b.safeReleaseDate) && -1) || 0;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      return this;
 | 
				
			||||||
      dupe() {
 | 
					 | 
				
			||||||
        var rnew;
 | 
					 | 
				
			||||||
        rnew = new JRSResume();
 | 
					 | 
				
			||||||
        rnew.parse(this.stringify(), {});
 | 
					 | 
				
			||||||
        return rnew;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      /**
 | 
					 | 
				
			||||||
      Create a copy of this resume in which all fields have been interpreted as
 | 
					 | 
				
			||||||
      Markdown.
 | 
					 | 
				
			||||||
      */
 | 
					 | 
				
			||||||
      harden() {
 | 
					 | 
				
			||||||
        var HD, HDIN, ret, transformer;
 | 
					 | 
				
			||||||
        ret = this.dupe();
 | 
					 | 
				
			||||||
        HD = function(txt) {
 | 
					 | 
				
			||||||
          return '@@@@~' + txt + '~@@@@';
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        HDIN = function(txt) {
 | 
					 | 
				
			||||||
          //return MD(txt || '' ).replace(/^\s*<p>|<\/p>\s*$/gi, '');
 | 
					 | 
				
			||||||
          return HD(txt);
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        transformer = require('../utils/string-transformer');
 | 
					 | 
				
			||||||
        return transformer(ret, ['skills', 'url', 'website', 'startDate', 'endDate', 'releaseDate', 'date', 'phone', 'email', 'address', 'postalCode', 'city', 'country', 'region', 'safeStartDate', 'safeEndDate'], function(key, val) {
 | 
					 | 
				
			||||||
          return HD(val);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Save the sheet to disk (for environments that have disk access). */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.save = function(filename) {
 | 
				
			||||||
 | 
					      this.imp.file = filename || this.imp.file;
 | 
				
			||||||
 | 
					      FS.writeFileSync(this.imp.file, this.stringify(this), 'utf8');
 | 
				
			||||||
 | 
					      return this;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Save the sheet to disk in a specific format, either FRESH or JRS. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.saveAs = function(filename, format) {
 | 
				
			||||||
 | 
					      var newRep, stringRep;
 | 
				
			||||||
 | 
					      if (format === 'JRS') {
 | 
				
			||||||
 | 
					        this.imp.file = filename || this.imp.file;
 | 
				
			||||||
 | 
					        FS.writeFileSync(this.imp.file, this.stringify(), 'utf8');
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        newRep = CONVERTER.toFRESH(this);
 | 
				
			||||||
 | 
					        stringRep = CONVERTER.toSTRING(newRep);
 | 
				
			||||||
 | 
					        FS.writeFileSync(filename, stringRep, 'utf8');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return this;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Return the resume format. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.format = function() {
 | 
				
			||||||
 | 
					      return 'JRS';
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.stringify = function() {
 | 
				
			||||||
 | 
					      return JRSResume.stringify(this);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Return a unique list of all keywords across all skills. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.keywords = function() {
 | 
				
			||||||
 | 
					      var flatSkills;
 | 
				
			||||||
 | 
					      flatSkills = [];
 | 
				
			||||||
 | 
					      if (this.skills && this.skills.length) {
 | 
				
			||||||
 | 
					        this.skills.forEach(function(s) {
 | 
				
			||||||
 | 
					          return flatSkills = _.union(flatSkills, s.keywords);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return flatSkills;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    Return internal metadata. Create if it doesn't exist.
 | 
				
			||||||
 | 
					    JSON Resume v0.0.0 doesn't allow additional properties at the root level,
 | 
				
			||||||
 | 
					    so tuck this into the .basic sub-object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.i = function() {
 | 
				
			||||||
 | 
					      var ref;
 | 
				
			||||||
 | 
					      return this.imp = (ref = this.imp) != null ? ref : {};
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Reset the sheet to an empty state. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    clear = function(clearMeta) {
 | 
					    clear = function(clearMeta) {
 | 
				
			||||||
      clearMeta = ((clearMeta === void 0) && true) || clearMeta;
 | 
					      clearMeta = ((clearMeta === void 0) && true) || clearMeta;
 | 
				
			||||||
      if (clearMeta) {
 | 
					      if (clearMeta) {
 | 
				
			||||||
        delete this.imp;
 | 
					        delete this.imp;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      delete this.basics.computed; // Don't use Object.keys() here
 | 
					      delete this.basics.computed;
 | 
				
			||||||
      delete this.work;
 | 
					      delete this.work;
 | 
				
			||||||
      delete this.volunteer;
 | 
					      delete this.volunteer;
 | 
				
			||||||
      delete this.education;
 | 
					      delete this.education;
 | 
				
			||||||
@@ -280,22 +188,183 @@
 | 
				
			|||||||
      return delete this.basics.profiles;
 | 
					      return delete this.basics.profiles;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Add work experience to the sheet. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.add = function(moniker) {
 | 
				
			||||||
 | 
					      var defSheet, newObject;
 | 
				
			||||||
 | 
					      defSheet = JRSResume["default"]();
 | 
				
			||||||
 | 
					      newObject = $.extend(true, {}, defSheet[moniker][0]);
 | 
				
			||||||
 | 
					      this[moniker] = this[moniker] || [];
 | 
				
			||||||
 | 
					      this[moniker].push(newObject);
 | 
				
			||||||
 | 
					      return newObject;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Determine if the sheet includes a specific social profile (eg, GitHub). */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.hasProfile = function(socialNetwork) {
 | 
				
			||||||
 | 
					      socialNetwork = socialNetwork.trim().toLowerCase();
 | 
				
			||||||
 | 
					      return this.basics.profiles && _.some(this.basics.profiles, function(p) {
 | 
				
			||||||
 | 
					        return p.network.trim().toLowerCase() === socialNetwork;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Determine if the sheet includes a specific skill. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.hasSkill = function(skill) {
 | 
				
			||||||
 | 
					      skill = skill.trim().toLowerCase();
 | 
				
			||||||
 | 
					      return this.skills && _.some(this.skills, function(sk) {
 | 
				
			||||||
 | 
					        return sk.keywords && _.some(sk.keywords, function(kw) {
 | 
				
			||||||
 | 
					          return kw.trim().toLowerCase() === skill;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Validate the sheet against the JSON Resume schema. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.isValid = function() {
 | 
				
			||||||
 | 
					      var ret, schema, schemaObj, temp, validate;
 | 
				
			||||||
 | 
					      schema = FS.readFileSync(PATH.join(__dirname, 'resume.json'), 'utf8');
 | 
				
			||||||
 | 
					      schemaObj = JSON.parse(schema);
 | 
				
			||||||
 | 
					      validator = require('is-my-json-valid');
 | 
				
			||||||
 | 
					      validate = validator(schemaObj, {
 | 
				
			||||||
 | 
					        formats: {
 | 
				
			||||||
 | 
					          date: /^\d{4}(?:-(?:0[0-9]{1}|1[0-2]{1})(?:-[0-9]{2})?)?$/
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      temp = this.imp;
 | 
				
			||||||
 | 
					      delete this.imp;
 | 
				
			||||||
 | 
					      ret = validate(this);
 | 
				
			||||||
 | 
					      this.imp = temp;
 | 
				
			||||||
 | 
					      if (!ret) {
 | 
				
			||||||
 | 
					        this.imp = this.imp || {};
 | 
				
			||||||
 | 
					        this.imp.validationErrors = validate.errors;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return ret;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.duration = function(unit) {
 | 
				
			||||||
 | 
					      return JRSResume.__super__.duration.call(this, 'work', 'startDate', 'endDate', unit);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    Sort dated things on the sheet by start date descending. Assumes that dates
 | 
				
			||||||
 | 
					    on the sheet have been processed with _parseDates().
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.sort = function() {
 | 
				
			||||||
 | 
					      var byDateDesc;
 | 
				
			||||||
 | 
					      byDateDesc = function(a, b) {
 | 
				
			||||||
 | 
					        if (a.safeStartDate.isBefore(b.safeStartDate)) {
 | 
				
			||||||
 | 
					          return 1;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          return (a.safeStartDate.isAfter(b.safeStartDate) && -1) || 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      this.work && this.work.sort(byDateDesc);
 | 
				
			||||||
 | 
					      this.education && this.education.sort(byDateDesc);
 | 
				
			||||||
 | 
					      this.volunteer && this.volunteer.sort(byDateDesc);
 | 
				
			||||||
 | 
					      this.awards && this.awards.sort(function(a, b) {
 | 
				
			||||||
 | 
					        if (a.safeDate.isBefore(b.safeDate)) {
 | 
				
			||||||
 | 
					          return 1;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          return (a.safeDate.isAfter(b.safeDate) && -1) || 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      return this.publications && this.publications.sort(function(a, b) {
 | 
				
			||||||
 | 
					        if (a.safeReleaseDate.isBefore(b.safeReleaseDate)) {
 | 
				
			||||||
 | 
					          return 1;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          return (a.safeReleaseDate.isAfter(b.safeReleaseDate) && -1) || 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.dupe = function() {
 | 
				
			||||||
 | 
					      var rnew;
 | 
				
			||||||
 | 
					      rnew = new JRSResume();
 | 
				
			||||||
 | 
					      rnew.parse(this.stringify(), {});
 | 
				
			||||||
 | 
					      return rnew;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    Create a copy of this resume in which all fields have been interpreted as
 | 
				
			||||||
 | 
					    Markdown.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JRSResume.prototype.harden = function() {
 | 
				
			||||||
 | 
					      var HD, HDIN, hardenStringsInObject, ret, that;
 | 
				
			||||||
 | 
					      that = this;
 | 
				
			||||||
 | 
					      ret = this.dupe();
 | 
				
			||||||
 | 
					      HD = function(txt) {
 | 
				
			||||||
 | 
					        return '@@@@~' + txt + '~@@@@';
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      HDIN = function(txt) {
 | 
				
			||||||
 | 
					        return HD(txt);
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      hardenStringsInObject = function(obj, inline) {
 | 
				
			||||||
 | 
					        if (!obj) {
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        inline = inline === void 0 || inline;
 | 
				
			||||||
 | 
					        if (Object.prototype.toString.call(obj) === '[object Array]') {
 | 
				
			||||||
 | 
					          return obj.forEach(function(elem, idx, ar) {
 | 
				
			||||||
 | 
					            if (typeof elem === 'string' || elem instanceof String) {
 | 
				
			||||||
 | 
					              return ar[idx] = inline ? HDIN(elem) : HD(elem);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              return hardenStringsInObject(elem);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        } else if (typeof obj === 'object') {
 | 
				
			||||||
 | 
					          return Object.keys(obj).forEach(function(key) {
 | 
				
			||||||
 | 
					            var sub;
 | 
				
			||||||
 | 
					            sub = obj[key];
 | 
				
			||||||
 | 
					            if (typeof sub === 'string' || sub instanceof String) {
 | 
				
			||||||
 | 
					              if (_.contains(['skills', 'url', 'website', 'startDate', 'endDate', 'releaseDate', 'date', 'phone', 'email', 'address', 'postalCode', 'city', 'country', 'region'], key)) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              if (key === 'summary') {
 | 
				
			||||||
 | 
					                return obj[key] = HD(obj[key]);
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                return obj[key] = inline ? HDIN(obj[key]) : HD(obj[key]);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              return hardenStringsInObject(sub);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      Object.keys(ret).forEach(function(member) {
 | 
				
			||||||
 | 
					        return hardenStringsInObject(ret[member]);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      return ret;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return JRSResume;
 | 
					    return JRSResume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  }).call(this);
 | 
					  })(AbstractResume);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Get the default (empty) sheet. */
 | 
					  /** Get the default (empty) sheet. */
 | 
				
			||||||
  JRSResume.default = function() {
 | 
					
 | 
				
			||||||
 | 
					  JRSResume["default"] = function() {
 | 
				
			||||||
    return new JRSResume().parseJSON(require('fresh-resume-starter').jrs);
 | 
					    return new JRSResume().parseJSON(require('fresh-resume-starter').jrs);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  Convert this object to a JSON string, sanitizing meta-properties along the
 | 
					  Convert this object to a JSON string, sanitizing meta-properties along the
 | 
				
			||||||
  way. Don't override .toString().
 | 
					  way. Don't override .toString().
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  JRSResume.stringify = function(obj) {
 | 
					  JRSResume.stringify = function(obj) {
 | 
				
			||||||
    var replacer;
 | 
					    var replacer;
 | 
				
			||||||
    replacer = function(key, value) { // Exclude these keys from stringification
 | 
					    replacer = function(key, value) {
 | 
				
			||||||
      var temp;
 | 
					      var temp;
 | 
				
			||||||
      temp = _.some(['imp', 'warnings', 'computed', 'filt', 'ctrl', 'index', 'safeStartDate', 'safeEndDate', 'safeDate', 'safeReleaseDate', 'result', 'isModified', 'htmlPreview', 'display_progress_bar'], function(val) {
 | 
					      temp = _.some(['imp', 'warnings', 'computed', 'filt', 'ctrl', 'index', 'safeStartDate', 'safeEndDate', 'safeDate', 'safeReleaseDate', 'result', 'isModified', 'htmlPreview', 'display_progress_bar'], function(val) {
 | 
				
			||||||
        return key.trim() === val;
 | 
					        return key.trim() === val;
 | 
				
			||||||
@@ -309,6 +378,15 @@
 | 
				
			|||||||
    return JSON.stringify(obj, replacer, 2);
 | 
					    return JSON.stringify(obj, replacer, 2);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Convert human-friendly dates into formal Moment.js dates for all collections.
 | 
				
			||||||
 | 
					  We don't want to lose the raw textual date as entered by the user, so we store
 | 
				
			||||||
 | 
					  the Moment-ified date as a separate property with a prefix of .safe. For ex:
 | 
				
			||||||
 | 
					  job.startDate is the date as entered by the user. job.safeStartDate is the
 | 
				
			||||||
 | 
					  parsed Moment.js date that we actually use in processing.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _parseDates = function() {
 | 
					  _parseDates = function() {
 | 
				
			||||||
    var _fmt;
 | 
					    var _fmt;
 | 
				
			||||||
    _fmt = require('./fluent-date').fmt;
 | 
					    _fmt = require('./fluent-date').fmt;
 | 
				
			||||||
@@ -332,9 +410,11 @@
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  Export the JRSResume function/ctor.
 | 
					  Export the JRSResume function/ctor.
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = JRSResume;
 | 
					  module.exports = JRSResume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										64
									
								
								dist/core/jrs-theme.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								dist/core/jrs-theme.js
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the JRSTheme class.
 | 
				
			||||||
 | 
					@module core/jrs-theme
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.MD for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var JRSTheme, PATH, _, parsePath, pathExists;
 | 
				
			||||||
  Definition of the JRSTheme class.
 | 
					 | 
				
			||||||
  @module core/jrs-theme
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.MD for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var JRSTheme, PATH, _, errors, parsePath, pathExists;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -14,32 +16,32 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  pathExists = require('path-exists').sync;
 | 
					  pathExists = require('path-exists').sync;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  errors = require('./status-codes');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  The JRSTheme class is a representation of a JSON Resume theme asset.
 | 
					  The JRSTheme class is a representation of a JSON Resume theme asset.
 | 
				
			||||||
  @class JRSTheme
 | 
					  @class JRSTheme
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  JRSTheme = class JRSTheme {
 | 
					
 | 
				
			||||||
 | 
					  JRSTheme = (function() {
 | 
				
			||||||
 | 
					    function JRSTheme() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Open and parse the specified JRS theme.
 | 
					    Open and parse the specified theme.
 | 
				
			||||||
    @method open
 | 
					    @method open
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    open(thFolder) {
 | 
					
 | 
				
			||||||
 | 
					    JRSTheme.prototype.open = function(thFolder) {
 | 
				
			||||||
      var pathInfo, pkgJsonPath, thApi, thPkg;
 | 
					      var pathInfo, pkgJsonPath, thApi, thPkg;
 | 
				
			||||||
      this.folder = thFolder;
 | 
					      this.folder = thFolder;
 | 
				
			||||||
      pathInfo = parsePath(thFolder);
 | 
					      pathInfo = parsePath(thFolder);
 | 
				
			||||||
      // Open and parse the theme's package.json file
 | 
					 | 
				
			||||||
      pkgJsonPath = PATH.join(thFolder, 'package.json');
 | 
					      pkgJsonPath = PATH.join(thFolder, 'package.json');
 | 
				
			||||||
      if (pathExists(pkgJsonPath)) {
 | 
					      if (pathExists(pkgJsonPath)) {
 | 
				
			||||||
        thApi = require(thFolder); // Requiring the folder yields whatever the package.json's "main" is set to
 | 
					        thApi = require(thFolder);
 | 
				
			||||||
        thPkg = require(pkgJsonPath); // Get the package.json as JSON
 | 
					        thPkg = require(pkgJsonPath);
 | 
				
			||||||
        this.name = thPkg.name;
 | 
					        this.name = thPkg.name;
 | 
				
			||||||
        this.render = (thApi && thApi.render) || void 0;
 | 
					        this.render = (thApi && thApi.render) || void 0;
 | 
				
			||||||
        this.engine = 'jrs';
 | 
					        this.engine = 'jrs';
 | 
				
			||||||
        // Create theme formats (HTML and PDF). Just add the bare minimum mix of
 | 
					 | 
				
			||||||
        // properties necessary to allow JSON Resume themes to share a rendering
 | 
					 | 
				
			||||||
        // path with FRESH themes.
 | 
					 | 
				
			||||||
        this.formats = {
 | 
					        this.formats = {
 | 
				
			||||||
          html: {
 | 
					          html: {
 | 
				
			||||||
            outFormat: 'html',
 | 
					            outFormat: 'html',
 | 
				
			||||||
@@ -68,29 +70,35 @@
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        throw {
 | 
					        throw {
 | 
				
			||||||
          fluenterror: errors.missingPackageJSON
 | 
					          fluenterror: HACKMYSTATUS.missingPackageJSON
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return this;
 | 
					      return this;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Determine if the theme supports the output format.
 | 
					    Determine if the theme supports the output format.
 | 
				
			||||||
    @method hasFormat
 | 
					    @method hasFormat
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    hasFormat(fmt) {
 | 
					
 | 
				
			||||||
 | 
					    JRSTheme.prototype.hasFormat = function(fmt) {
 | 
				
			||||||
      return _.has(this.formats, fmt);
 | 
					      return _.has(this.formats, fmt);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Return the requested output format.
 | 
					    Return the requested output format.
 | 
				
			||||||
    @method getFormat
 | 
					    @method getFormat
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    getFormat(fmt) {
 | 
					 | 
				
			||||||
      return this.formats[fmt];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    JRSTheme.prototype.getFormat = function(fmt) {
 | 
				
			||||||
 | 
					      return this.formats[fmt];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return JRSTheme;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = JRSTheme;
 | 
					  module.exports = JRSTheme;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										70
									
								
								dist/core/resume-factory.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								dist/core/resume-factory.js
									
									
									
									
										vendored
									
									
								
							@@ -1,18 +1,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the ResumeFactory class.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module core/resume-factory
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var FS, HACKMYSTATUS, HME, ResumeConverter, ResumeFactory, SyntaxErrorEx, _, _parse, chalk;
 | 
				
			||||||
  Definition of the ResumeFactory class.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module core/resume-factory
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  A simple factory class for FRESH and JSON Resumes.
 | 
					 | 
				
			||||||
  @class ResumeFactory
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FS, HME, HMS, ResumeConverter, ResumeFactory, SyntaxErrorEx, _, _parse, chalk, resumeDetect;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FS = require('fs');
 | 
					  FS = require('fs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HMS = require('./status-codes');
 | 
					  HACKMYSTATUS = require('./status-codes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HME = require('./event-codes');
 | 
					  HME = require('./event-codes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -24,11 +22,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  resumeDetect = require('../utils/resume-detector');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  require('string.prototype.startswith');
 | 
					  require('string.prototype.startswith');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  A simple factory class for FRESH and JSON Resumes.
 | 
				
			||||||
 | 
					  @class ResumeFactory
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ResumeFactory = module.exports = {
 | 
					  ResumeFactory = module.exports = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Load one or more resumes from disk.
 | 
					    Load one or more resumes from disk.
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@@ -42,42 +45,32 @@
 | 
				
			|||||||
            sort: false
 | 
					            sort: false
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    load: function(sources, opts, emitter) {
 | 
					    load: function(sources, opts, emitter) {
 | 
				
			||||||
      return sources.map(function(src) {
 | 
					      return sources.map(function(src) {
 | 
				
			||||||
        return this.loadOne(src, opts, emitter);
 | 
					        return this.loadOne(src, opts, emitter);
 | 
				
			||||||
      }, this);
 | 
					      }, this);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    /** Load a single resume from disk.  */
 | 
					 | 
				
			||||||
    loadOne: function(src, opts, emitter) {
 | 
					 | 
				
			||||||
      var ResumeClass, info, json, orgFormat, reqLib, rez, toFormat;
 | 
					 | 
				
			||||||
      toFormat = opts.format; // Can be null
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Get the destination format. Can be 'fresh', 'jrs', or null/undefined.
 | 
					    /** Load a single resume from disk. */
 | 
				
			||||||
 | 
					    loadOne: function(src, opts, emitter) {
 | 
				
			||||||
 | 
					      var ResumeClass, info, isFRESH, json, objectify, orgFormat, rez, toFormat;
 | 
				
			||||||
 | 
					      toFormat = opts.format;
 | 
				
			||||||
 | 
					      objectify = opts.objectify;
 | 
				
			||||||
      toFormat && (toFormat = toFormat.toLowerCase().trim());
 | 
					      toFormat && (toFormat = toFormat.toLowerCase().trim());
 | 
				
			||||||
      // Load and parse the resume JSON
 | 
					 | 
				
			||||||
      info = _parse(src, opts, emitter);
 | 
					      info = _parse(src, opts, emitter);
 | 
				
			||||||
      if (info.fluenterror) {
 | 
					      if (info.fluenterror) {
 | 
				
			||||||
        return info;
 | 
					        return info;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // Determine the resume format: FRESH or JRS
 | 
					 | 
				
			||||||
      json = info.json;
 | 
					      json = info.json;
 | 
				
			||||||
      orgFormat = resumeDetect(json);
 | 
					      isFRESH = json.meta && json.meta.format && json.meta.format.startsWith('FRESH@');
 | 
				
			||||||
      if (orgFormat === 'unk') {
 | 
					      orgFormat = isFRESH ? 'fresh' : 'jrs';
 | 
				
			||||||
        info.fluenterror = HMS.unknownSchema;
 | 
					 | 
				
			||||||
        return info;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      // Convert between formats if necessary
 | 
					 | 
				
			||||||
      if (toFormat && (orgFormat !== toFormat)) {
 | 
					      if (toFormat && (orgFormat !== toFormat)) {
 | 
				
			||||||
        json = ResumeConverter['to' + toFormat.toUpperCase()](json);
 | 
					        json = ResumeConverter['to' + toFormat.toUpperCase()](json);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // Objectify the resume, that is, convert it from JSON to a FRESHResume
 | 
					 | 
				
			||||||
      // or JRSResume object.
 | 
					 | 
				
			||||||
      rez = null;
 | 
					      rez = null;
 | 
				
			||||||
      if (opts.objectify) {
 | 
					      if (objectify) {
 | 
				
			||||||
        reqLib = '../core/' + (toFormat || orgFormat) + '-resume';
 | 
					        ResumeClass = require('../core/' + (toFormat || orgFormat) + '-resume');
 | 
				
			||||||
        ResumeClass = require(reqLib);
 | 
					 | 
				
			||||||
        rez = new ResumeClass().parseJSON(json, opts.inner);
 | 
					        rez = new ResumeClass().parseJSON(json, opts.inner);
 | 
				
			||||||
        rez.i().file = src;
 | 
					        rez.i().file = src;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -90,10 +83,9 @@
 | 
				
			|||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _parse = function(fileName, opts, eve) {
 | 
					  _parse = function(fileName, opts, eve) {
 | 
				
			||||||
    var err, orgFormat, rawData, ret;
 | 
					    var orgFormat, rawData, ret;
 | 
				
			||||||
    rawData = null;
 | 
					    rawData = null;
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      // Read the file
 | 
					 | 
				
			||||||
      eve && eve.stat(HME.beforeRead, {
 | 
					      eve && eve.stat(HME.beforeRead, {
 | 
				
			||||||
        file: fileName
 | 
					        file: fileName
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -115,12 +107,10 @@
 | 
				
			|||||||
        fmt: orgFormat
 | 
					        fmt: orgFormat
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      return ret;
 | 
					      return ret;
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (_error) {
 | 
				
			||||||
      err = error;
 | 
					 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        // Can be ENOENT, EACCES, SyntaxError, etc.
 | 
					        fluenterror: rawData ? HACKMYSTATUS.parseError : HACKMYSTATUS.readError,
 | 
				
			||||||
        fluenterror: rawData ? HMS.parseError : HMS.readError,
 | 
					        inner: _error,
 | 
				
			||||||
        inner: err,
 | 
					 | 
				
			||||||
        raw: rawData,
 | 
					        raw: rawData,
 | 
				
			||||||
        file: fileName
 | 
					        file: fileName
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								dist/core/status-codes.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								dist/core/status-codes.js
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Status codes for HackMyResume.
 | 
				
			||||||
 | 
					@module core/status-codes
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.MD for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Status codes for HackMyResume.
 | 
					 | 
				
			||||||
  @module core/status-codes
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.MD for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  module.exports = {
 | 
					  module.exports = {
 | 
				
			||||||
    success: 0,
 | 
					    success: 0,
 | 
				
			||||||
    themeNotFound: 1,
 | 
					    themeNotFound: 1,
 | 
				
			||||||
@@ -31,12 +33,7 @@
 | 
				
			|||||||
    invalidParamCount: 23,
 | 
					    invalidParamCount: 23,
 | 
				
			||||||
    missingParam: 24,
 | 
					    missingParam: 24,
 | 
				
			||||||
    createError: 25,
 | 
					    createError: 25,
 | 
				
			||||||
    validateError: 26,
 | 
					    validateError: 26
 | 
				
			||||||
    invalidOptionsFile: 27,
 | 
					 | 
				
			||||||
    optionsFileNotFound: 28,
 | 
					 | 
				
			||||||
    unknownSchema: 29,
 | 
					 | 
				
			||||||
    themeHelperLoad: 30,
 | 
					 | 
				
			||||||
    invalidSchemaVersion: 31
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										38
									
								
								dist/generators/base-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								dist/generators/base-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,33 +1,39 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the BaseGenerator class.
 | 
				
			||||||
 | 
					@module generators/base-generator
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					The BaseGenerator class is the root of the generator hierarchy. Functionality
 | 
				
			||||||
 | 
					common to ALL generators lives here.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the BaseGenerator class.
 | 
					 | 
				
			||||||
  @module generators/base-generator
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var BaseGenerator;
 | 
					  var BaseGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  The BaseGenerator class is the root of the generator hierarchy. Functionality
 | 
					 | 
				
			||||||
  common to ALL generators lives here.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  module.exports = BaseGenerator = (function() {
 | 
					  module.exports = BaseGenerator = (function() {
 | 
				
			||||||
    class BaseGenerator {
 | 
					 | 
				
			||||||
      /** Base-class initialize. */
 | 
					 | 
				
			||||||
      constructor(format) {
 | 
					 | 
				
			||||||
        this.format = format;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    };
 | 
					    /** Base-class initialize. */
 | 
				
			||||||
 | 
					    function BaseGenerator(format) {
 | 
				
			||||||
 | 
					      this.format = format;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Status codes. */
 | 
					    /** Status codes. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    BaseGenerator.prototype.codes = require('../core/status-codes');
 | 
					    BaseGenerator.prototype.codes = require('../core/status-codes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Generator options. */
 | 
					    /** Generator options. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    BaseGenerator.prototype.opts = {};
 | 
					    BaseGenerator.prototype.opts = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return BaseGenerator;
 | 
					    return BaseGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  }).call(this);
 | 
					  })();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								dist/generators/html-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								dist/generators/html-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the HTMLGenerator class.
 | 
				
			||||||
 | 
					@module generators/html-generator
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var FS, HTML, HtmlGenerator, PATH, TemplateGenerator,
 | 
				
			||||||
  Definition of the HTMLGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module generators/html-generator
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FS, HTML, HtmlGenerator, PATH, TemplateGenerator;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TemplateGenerator = require('./template-generator');
 | 
					  TemplateGenerator = require('./template-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,16 +20,20 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  require('string.prototype.endswith');
 | 
					  require('string.prototype.endswith');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = HtmlGenerator = class HtmlGenerator extends TemplateGenerator {
 | 
					  module.exports = HtmlGenerator = (function(superClass) {
 | 
				
			||||||
    constructor() {
 | 
					    extend(HtmlGenerator, superClass);
 | 
				
			||||||
      super('html');
 | 
					
 | 
				
			||||||
 | 
					    function HtmlGenerator() {
 | 
				
			||||||
 | 
					      HtmlGenerator.__super__.constructor.call(this, 'html');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Copy satellite CSS files to the destination and optionally pretty-print
 | 
					    Copy satellite CSS files to the destination and optionally pretty-print
 | 
				
			||||||
    the HTML resume prior to saving.
 | 
					    the HTML resume prior to saving.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    onBeforeSave(info) {
 | 
					
 | 
				
			||||||
 | 
					    HtmlGenerator.prototype.onBeforeSave = function(info) {
 | 
				
			||||||
      if (info.outputFile.endsWith('.css')) {
 | 
					      if (info.outputFile.endsWith('.css')) {
 | 
				
			||||||
        return info.mk;
 | 
					        return info.mk;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -34,9 +42,11 @@
 | 
				
			|||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        return info.mk;
 | 
					        return info.mk;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return HtmlGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(TemplateGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										91
									
								
								dist/generators/html-pdf-cli-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										91
									
								
								dist/generators/html-pdf-cli-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the HtmlPdfCLIGenerator class.
 | 
				
			||||||
 | 
					@module generators/html-pdf-generator.js
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var FS, HMSTATUS, HtmlPdfCLIGenerator, PATH, SLASH, SPAWN, TemplateGenerator, _, engines,
 | 
				
			||||||
  Definition of the HtmlPdfCLIGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module generators/html-pdf-generator.js
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FS, HMSTATUS, HtmlPdfCLIGenerator, PATH, SLASH, SPAWN, TemplateGenerator, _, engines;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TemplateGenerator = require('./template-generator');
 | 
					  TemplateGenerator = require('./template-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -20,21 +24,26 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  SPAWN = require('../utils/safe-spawn');
 | 
					  SPAWN = require('../utils/safe-spawn');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  An HTML-driven PDF resume generator for HackMyResume. Talks to Phantom,
 | 
					  An HTML-driven PDF resume generator for HackMyResume. Talks to Phantom,
 | 
				
			||||||
  wkhtmltopdf, and other PDF engines over a CLI (command-line interface).
 | 
					  wkhtmltopdf, and other PDF engines over a CLI (command-line interface).
 | 
				
			||||||
  If an engine isn't installed for a particular platform, error out gracefully.
 | 
					  If an engine isn't installed for a particular platform, error out gracefully.
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = HtmlPdfCLIGenerator = class HtmlPdfCLIGenerator extends TemplateGenerator {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = HtmlPdfCLIGenerator = (function(superClass) {
 | 
				
			||||||
      super('pdf', 'html');
 | 
					    extend(HtmlPdfCLIGenerator, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function HtmlPdfCLIGenerator() {
 | 
				
			||||||
 | 
					      HtmlPdfCLIGenerator.__super__.constructor.call(this, 'pdf', 'html');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Generate the binary PDF. */
 | 
					    /** Generate the binary PDF. */
 | 
				
			||||||
    onBeforeSave(info) {
 | 
					
 | 
				
			||||||
 | 
					    HtmlPdfCLIGenerator.prototype.onBeforeSave = function(info) {
 | 
				
			||||||
      var safe_eng;
 | 
					      var safe_eng;
 | 
				
			||||||
      if (info.ext !== 'html' && info.ext !== 'pdf') {
 | 
					      if (info.ext !== 'html' && info.ext !== 'pdf') {
 | 
				
			||||||
        //console.dir _.omit( info, 'mk' ), depth: null, colors: true
 | 
					 | 
				
			||||||
        return info.mk;
 | 
					        return info.mk;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      safe_eng = info.opts.pdf || 'wkhtmltopdf';
 | 
					      safe_eng = info.opts.pdf || 'wkhtmltopdf';
 | 
				
			||||||
@@ -43,61 +52,56 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      if (_.has(engines, safe_eng)) {
 | 
					      if (_.has(engines, safe_eng)) {
 | 
				
			||||||
        this.errHandler = info.opts.errHandler;
 | 
					        this.errHandler = info.opts.errHandler;
 | 
				
			||||||
        engines[safe_eng].call(this, info.mk, info.outputFile, info.opts, this.onError);
 | 
					        engines[safe_eng].call(this, info.mk, info.outputFile, this.onError);
 | 
				
			||||||
        return null; // halt further processing
 | 
					        return null;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Low-level error callback for spawn(). May be called after HMR process
 | 
					    /* Low-level error callback for spawn(). May be called after HMR process
 | 
				
			||||||
    termination, so object references may not be valid here. That's okay; if
 | 
					    termination, so object references may not be valid here. That's okay; if
 | 
				
			||||||
    the references are invalid, the error was already logged. We could use
 | 
					    the references are invalid, the error was already logged. We could use
 | 
				
			||||||
    spawn-watch here but that causes issues on legacy Node.js. */
 | 
					    spawn-watch here but that causes issues on legacy Node.js.
 | 
				
			||||||
    onError(ex, param) {
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    HtmlPdfCLIGenerator.prototype.onError = function(ex, param) {
 | 
				
			||||||
      var ref;
 | 
					      var ref;
 | 
				
			||||||
      if ((ref = param.errHandler) != null) {
 | 
					      if ((ref = param.errHandler) != null) {
 | 
				
			||||||
        if (typeof ref.err === "function") {
 | 
					        if (typeof ref.err === "function") {
 | 
				
			||||||
          ref.err(HMSTATUS.pdfGeneration, ex);
 | 
					          ref.err(HMSTATUS.pdfGeneration, ex);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return HtmlPdfCLIGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(TemplateGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: Move each engine to a separate module
 | 
					 | 
				
			||||||
  engines = {
 | 
					  engines = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Generate a PDF from HTML using wkhtmltopdf's CLI interface.
 | 
					    Generate a PDF from HTML using wkhtmltopdf's CLI interface.
 | 
				
			||||||
    Spawns a child process with `wkhtmltopdf <source> <target>`. wkhtmltopdf
 | 
					    Spawns a child process with `wkhtmltopdf <source> <target>`. wkhtmltopdf
 | 
				
			||||||
    must be installed and path-accessible.
 | 
					    must be installed and path-accessible.
 | 
				
			||||||
    TODO: If HTML generation has run, reuse that output
 | 
					    TODO: If HTML generation has run, reuse that output
 | 
				
			||||||
    TODO: Local web server to ease wkhtmltopdf rendering
 | 
					    TODO: Local web server to ease wkhtmltopdf rendering
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    wkhtmltopdf: function(markup, fOut, opts, on_error) {
 | 
					    wkhtmltopdf: function(markup, fOut, on_error) {
 | 
				
			||||||
      var tempFile, wkargs, wkopts;
 | 
					      var tempFile;
 | 
				
			||||||
      // Save the markup to a temporary file
 | 
					 | 
				
			||||||
      tempFile = fOut.replace(/\.pdf$/i, '.pdf.html');
 | 
					      tempFile = fOut.replace(/\.pdf$/i, '.pdf.html');
 | 
				
			||||||
      FS.writeFileSync(tempFile, markup, 'utf8');
 | 
					      FS.writeFileSync(tempFile, markup, 'utf8');
 | 
				
			||||||
      // Prepare wkhtmltopdf arguments.
 | 
					      SPAWN('wkhtmltopdf', [tempFile, fOut], false, on_error, this);
 | 
				
			||||||
      wkopts = _.extend({
 | 
					 | 
				
			||||||
        'margin-top': '10mm',
 | 
					 | 
				
			||||||
        'margin-bottom': '10mm'
 | 
					 | 
				
			||||||
      }, opts.wkhtmltopdf);
 | 
					 | 
				
			||||||
      wkopts = _.flatten(_.map(wkopts, function(v, k) {
 | 
					 | 
				
			||||||
        return ['--' + k, v];
 | 
					 | 
				
			||||||
      }));
 | 
					 | 
				
			||||||
      wkargs = wkopts.concat([tempFile, fOut]);
 | 
					 | 
				
			||||||
      SPAWN('wkhtmltopdf', wkargs, false, on_error, this);
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Generate a PDF from HTML using Phantom's CLI interface.
 | 
					    Generate a PDF from HTML using Phantom's CLI interface.
 | 
				
			||||||
    Spawns a child process with `phantomjs <script> <source> <target>`. Phantom
 | 
					    Spawns a child process with `phantomjs <script> <source> <target>`. Phantom
 | 
				
			||||||
    must be installed and path-accessible.
 | 
					    must be installed and path-accessible.
 | 
				
			||||||
    TODO: If HTML generation has run, reuse that output
 | 
					    TODO: If HTML generation has run, reuse that output
 | 
				
			||||||
    TODO: Local web server to ease Phantom rendering
 | 
					    TODO: Local web server to ease Phantom rendering
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    phantomjs: function(markup, fOut, opts, on_error) {
 | 
					    phantomjs: function(markup, fOut, on_error) {
 | 
				
			||||||
      var destPath, scriptPath, sourcePath, tempFile;
 | 
					      var destPath, scriptPath, sourcePath, tempFile;
 | 
				
			||||||
      // Save the markup to a temporary file
 | 
					 | 
				
			||||||
      tempFile = fOut.replace(/\.pdf$/i, '.pdf.html');
 | 
					      tempFile = fOut.replace(/\.pdf$/i, '.pdf.html');
 | 
				
			||||||
      FS.writeFileSync(tempFile, markup, 'utf8');
 | 
					      FS.writeFileSync(tempFile, markup, 'utf8');
 | 
				
			||||||
      scriptPath = PATH.relative(process.cwd(), PATH.resolve(__dirname, '../utils/rasterize.js'));
 | 
					      scriptPath = PATH.relative(process.cwd(), PATH.resolve(__dirname, '../utils/rasterize.js'));
 | 
				
			||||||
@@ -105,19 +109,6 @@
 | 
				
			|||||||
      sourcePath = SLASH(PATH.relative(process.cwd(), tempFile));
 | 
					      sourcePath = SLASH(PATH.relative(process.cwd(), tempFile));
 | 
				
			||||||
      destPath = SLASH(PATH.relative(process.cwd(), fOut));
 | 
					      destPath = SLASH(PATH.relative(process.cwd(), fOut));
 | 
				
			||||||
      SPAWN('phantomjs', [scriptPath, sourcePath, destPath], false, on_error, this);
 | 
					      SPAWN('phantomjs', [scriptPath, sourcePath, destPath], false, on_error, this);
 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    Generate a PDF from HTML using WeasyPrint's CLI interface.
 | 
					 | 
				
			||||||
    Spawns a child process with `weasyprint <source> <target>`. Weasy Print
 | 
					 | 
				
			||||||
    must be installed and path-accessible.
 | 
					 | 
				
			||||||
    TODO: If HTML generation has run, reuse that output
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    weasyprint: function(markup, fOut, opts, on_error) {
 | 
					 | 
				
			||||||
      var tempFile;
 | 
					 | 
				
			||||||
      // Save the markup to a temporary file
 | 
					 | 
				
			||||||
      tempFile = fOut.replace(/\.pdf$/i, '.pdf.html');
 | 
					 | 
				
			||||||
      FS.writeFileSync(tempFile, markup, 'utf8');
 | 
					 | 
				
			||||||
      SPAWN('weasyprint', [tempFile, fOut], false, on_error, this);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										56
									
								
								dist/generators/html-png-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										56
									
								
								dist/generators/html-png-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,17 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the HtmlPngGenerator class.
 | 
				
			||||||
 | 
					@module generators/html-png-generator
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.MD for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var FS, HTML, HtmlPngGenerator, PATH, SLASH, SPAWN, TemplateGenerator, phantom,
 | 
				
			||||||
  Definition of the HtmlPngGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module generators/html-png-generator
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.MD for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Generate a PDF from HTML using Phantom's CLI interface.
 | 
					 | 
				
			||||||
  Spawns a child process with `phantomjs <script> <source> <target>`. Phantom
 | 
					 | 
				
			||||||
  must be installed and path-accessible.
 | 
					 | 
				
			||||||
  TODO: If HTML generation has run, reuse that output
 | 
					 | 
				
			||||||
  TODO: Local web server to ease Phantom rendering
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FS, HTML, HtmlPngGenerator, PATH, SLASH, SPAWN, TemplateGenerator, phantom;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TemplateGenerator = require('./template-generator');
 | 
					  TemplateGenerator = require('./template-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,18 +22,21 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  PATH = require('path');
 | 
					  PATH = require('path');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  An HTML-based PNG resume generator for HackMyResume.
 | 
					  An HTML-based PNG resume generator for HackMyResume.
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = HtmlPngGenerator = class HtmlPngGenerator extends TemplateGenerator {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = HtmlPngGenerator = (function(superClass) {
 | 
				
			||||||
      super('png', 'html');
 | 
					    extend(HtmlPngGenerator, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function HtmlPngGenerator() {
 | 
				
			||||||
 | 
					      HtmlPngGenerator.__super__.constructor.call(this, 'png', 'html');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    invoke(rez, themeMarkup, cssInfo, opts) {}
 | 
					    HtmlPngGenerator.prototype.invoke = function(rez, themeMarkup, cssInfo, opts) {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: Not currently called or callable.
 | 
					    HtmlPngGenerator.prototype.generate = function(rez, f, opts) {
 | 
				
			||||||
    generate(rez, f, opts) {
 | 
					 | 
				
			||||||
      var htmlFile, htmlResults;
 | 
					      var htmlFile, htmlResults;
 | 
				
			||||||
      htmlResults = opts.targets.filter(function(t) {
 | 
					      htmlResults = opts.targets.filter(function(t) {
 | 
				
			||||||
        return t.fmt.outFormat === 'html';
 | 
					        return t.fmt.outFormat === 'html';
 | 
				
			||||||
@@ -45,13 +45,23 @@
 | 
				
			|||||||
        return fl.info.ext === 'html';
 | 
					        return fl.info.ext === 'html';
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      phantom(htmlFile[0].data, f);
 | 
					      phantom(htmlFile[0].data, f);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return HtmlPngGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(TemplateGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Generate a PDF from HTML using Phantom's CLI interface.
 | 
				
			||||||
 | 
					  Spawns a child process with `phantomjs <script> <source> <target>`. Phantom
 | 
				
			||||||
 | 
					  must be installed and path-accessible.
 | 
				
			||||||
 | 
					  TODO: If HTML generation has run, reuse that output
 | 
				
			||||||
 | 
					  TODO: Local web server to ease Phantom rendering
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  phantom = function(markup, fOut) {
 | 
					  phantom = function(markup, fOut) {
 | 
				
			||||||
    var destPath, info, scriptPath, sourcePath, tempFile;
 | 
					    var destPath, info, scriptPath, sourcePath, tempFile;
 | 
				
			||||||
    // Save the markup to a temporary file
 | 
					 | 
				
			||||||
    tempFile = fOut.replace(/\.png$/i, '.png.html');
 | 
					    tempFile = fOut.replace(/\.png$/i, '.png.html');
 | 
				
			||||||
    FS.writeFileSync(tempFile, markup, 'utf8');
 | 
					    FS.writeFileSync(tempFile, markup, 'utf8');
 | 
				
			||||||
    scriptPath = SLASH(PATH.relative(process.cwd(), PATH.resolve(__dirname, '../utils/rasterize.js')));
 | 
					    scriptPath = SLASH(PATH.relative(process.cwd(), PATH.resolve(__dirname, '../utils/rasterize.js')));
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								dist/generators/json-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								dist/generators/json-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the JsonGenerator class.
 | 
				
			||||||
 | 
					@module generators/json-generator
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var BaseGenerator, FJCV, FS, JsonGenerator, _,
 | 
				
			||||||
  Definition of the JsonGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module generators/json-generator
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var BaseGenerator, FJCV, FS, JsonGenerator, _;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  BaseGenerator = require('./base-generator');
 | 
					  BaseGenerator = require('./base-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -14,24 +18,29 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  FJCV = require('fresh-jrs-converter');
 | 
					  FJCV = require('fresh-jrs-converter');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** The JsonGenerator generates a FRESH or JRS resume as an output. */
 | 
					  /** The JsonGenerator generates a FRESH or JRS resume as an output. */
 | 
				
			||||||
  module.exports = JsonGenerator = class JsonGenerator extends BaseGenerator {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = JsonGenerator = (function(superClass) {
 | 
				
			||||||
      super('json');
 | 
					    extend(JsonGenerator, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function JsonGenerator() {
 | 
				
			||||||
 | 
					      JsonGenerator.__super__.constructor.call(this, 'json');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    invoke(rez) {
 | 
					    JsonGenerator.prototype.invoke = function(rez) {
 | 
				
			||||||
      var altRez;
 | 
					      var altRez;
 | 
				
			||||||
      altRez = FJCV['to' + (rez.format() === 'FRESH' ? 'JRS' : 'FRESH')](rez);
 | 
					      altRez = FJCV['to' + (rez.format() === 'FRESH' ? 'JRS' : 'FRESH')](rez);
 | 
				
			||||||
      return altRez = FJCV.toSTRING(altRez);
 | 
					      return altRez = FJCV.toSTRING(altRez);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //altRez.stringify()
 | 
					    JsonGenerator.prototype.generate = function(rez, f) {
 | 
				
			||||||
    generate(rez, f) {
 | 
					 | 
				
			||||||
      FS.writeFileSync(f, this.invoke(rez), 'utf8');
 | 
					      FS.writeFileSync(f, this.invoke(rez), 'utf8');
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return JsonGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(BaseGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										44
									
								
								dist/generators/json-yaml-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								dist/generators/json-yaml-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the JsonYamlGenerator class.
 | 
				
			||||||
 | 
					@module generators/json-yaml-generator
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var BaseGenerator, FS, JsonYamlGenerator, YAML,
 | 
				
			||||||
  Definition of the JsonYamlGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module generators/json-yaml-generator
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var BaseGenerator, FS, JsonYamlGenerator, YAML;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  BaseGenerator = require('./base-generator');
 | 
					  BaseGenerator = require('./base-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,28 +16,34 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  YAML = require('yamljs');
 | 
					  YAML = require('yamljs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  JsonYamlGenerator takes a JSON resume object and translates it directly to
 | 
					  JsonYamlGenerator takes a JSON resume object and translates it directly to
 | 
				
			||||||
  JSON without a template, producing an equivalent YAML-formatted resume. See
 | 
					  JSON without a template, producing an equivalent YAML-formatted resume. See
 | 
				
			||||||
  also YamlGenerator (yaml-generator.js).
 | 
					  also YamlGenerator (yaml-generator.js).
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = JsonYamlGenerator = class JsonYamlGenerator extends BaseGenerator {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = JsonYamlGenerator = (function(superClass) {
 | 
				
			||||||
      super('yml');
 | 
					    extend(JsonYamlGenerator, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function JsonYamlGenerator() {
 | 
				
			||||||
 | 
					      JsonYamlGenerator.__super__.constructor.call(this, 'yml');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    invoke(rez, themeMarkup, cssInfo, opts) {
 | 
					    JsonYamlGenerator.prototype.invoke = function(rez, themeMarkup, cssInfo, opts) {
 | 
				
			||||||
      return YAML.stringify(JSON.parse(rez.stringify()), 2e308, 2);
 | 
					      return YAML.stringify(JSON.parse(rez.stringify()), Infinity, 2);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    generate(rez, f, opts) {
 | 
					    JsonYamlGenerator.prototype.generate = function(rez, f, opts) {
 | 
				
			||||||
      var data;
 | 
					      var data;
 | 
				
			||||||
      data = YAML.stringify(JSON.parse(rez.stringify()), 2e308, 2);
 | 
					      data = YAML.stringify(JSON.parse(rez.stringify()), Infinity, 2);
 | 
				
			||||||
      FS.writeFileSync(f, data, 'utf8');
 | 
					      FS.writeFileSync(f, data, 'utf8');
 | 
				
			||||||
      return data;
 | 
					      return data;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return JsonYamlGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(BaseGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								dist/generators/latex-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								dist/generators/latex-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,22 +1,32 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the LaTeXGenerator class.
 | 
				
			||||||
 | 
					@module generators/latex-generator
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var LaTeXGenerator, TemplateGenerator,
 | 
				
			||||||
  Definition of the LaTeXGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module generators/latex-generator
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var LaTeXGenerator, TemplateGenerator;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TemplateGenerator = require('./template-generator');
 | 
					  TemplateGenerator = require('./template-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  LaTeXGenerator generates a LaTeX resume via TemplateGenerator.
 | 
					  LaTeXGenerator generates a LaTeX resume via TemplateGenerator.
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = LaTeXGenerator = class LaTeXGenerator extends TemplateGenerator {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = LaTeXGenerator = (function(superClass) {
 | 
				
			||||||
      super('latex', 'tex');
 | 
					    extend(LaTeXGenerator, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function LaTeXGenerator() {
 | 
				
			||||||
 | 
					      LaTeXGenerator.__super__.constructor.call(this, 'latex', 'tex');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return LaTeXGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(TemplateGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								dist/generators/markdown-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								dist/generators/markdown-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,22 +1,32 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the MarkdownGenerator class.
 | 
				
			||||||
 | 
					@module generators/markdown-generator
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var MarkdownGenerator, TemplateGenerator,
 | 
				
			||||||
  Definition of the MarkdownGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module generators/markdown-generator
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var MarkdownGenerator, TemplateGenerator;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TemplateGenerator = require('./template-generator');
 | 
					  TemplateGenerator = require('./template-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  MarkdownGenerator generates a Markdown-formatted resume via TemplateGenerator.
 | 
					  MarkdownGenerator generates a Markdown-formatted resume via TemplateGenerator.
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = MarkdownGenerator = class MarkdownGenerator extends TemplateGenerator {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = MarkdownGenerator = (function(superClass) {
 | 
				
			||||||
      super('md', 'txt');
 | 
					    extend(MarkdownGenerator, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function MarkdownGenerator() {
 | 
				
			||||||
 | 
					      MarkdownGenerator.__super__.constructor.call(this, 'md', 'txt');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return MarkdownGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(TemplateGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										116
									
								
								dist/generators/template-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										116
									
								
								dist/generators/template-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,13 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the TemplateGenerator class. TODO: Refactor
 | 
				
			||||||
 | 
					@module generators/template-generator
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var BaseGenerator, EXTEND, FRESHTheme, FS, JRSTheme, MD, MKDIRP, PATH, TemplateGenerator, XML, _, _defaultOpts, _reg, createSymLinks, freeze, parsePath, unfreeze,
 | 
				
			||||||
  Definition of the TemplateGenerator class. TODO: Refactor
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module generators/template-generator
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** Default template generator options. */
 | 
					 | 
				
			||||||
  /** Freeze newlines for protection against errant JST parsers. */
 | 
					 | 
				
			||||||
  /** Unfreeze newlines when the coast is clear. */
 | 
					 | 
				
			||||||
  var BaseGenerator, EXTEND, FRESHTheme, FS, JRSTheme, MD, MKDIRP, PATH, TemplateGenerator, XML, _, _defaultOpts, _reg, createSymLinks, freeze, parsePath, unfreeze;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FS = require('fs-extra');
 | 
					  FS = require('fs-extra');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -31,38 +32,46 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  JRSTheme = require('../core/jrs-theme');
 | 
					  JRSTheme = require('../core/jrs-theme');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  TemplateGenerator performs resume generation via local Handlebar or Underscore
 | 
					  TemplateGenerator performs resume generation via local Handlebar or Underscore
 | 
				
			||||||
  style template expansion and is appropriate for text-based formats like HTML,
 | 
					  style template expansion and is appropriate for text-based formats like HTML,
 | 
				
			||||||
  plain text, and XML versions of Microsoft Word, Excel, and OpenOffice.
 | 
					  plain text, and XML versions of Microsoft Word, Excel, and OpenOffice.
 | 
				
			||||||
  @class TemplateGenerator
 | 
					  @class TemplateGenerator
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = TemplateGenerator = class TemplateGenerator extends BaseGenerator {
 | 
					
 | 
				
			||||||
 | 
					  module.exports = TemplateGenerator = (function(superClass) {
 | 
				
			||||||
 | 
					    extend(TemplateGenerator, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Constructor. Set the output format and template format for this
 | 
					    /** Constructor. Set the output format and template format for this
 | 
				
			||||||
    generator. Will usually be called by a derived generator such as
 | 
					    generator. Will usually be called by a derived generator such as
 | 
				
			||||||
    HTMLGenerator or MarkdownGenerator. */
 | 
					    HTMLGenerator or MarkdownGenerator.
 | 
				
			||||||
    constructor(outputFormat, templateFormat, cssFile) {
 | 
					     */
 | 
				
			||||||
      super(outputFormat);
 | 
					
 | 
				
			||||||
 | 
					    function TemplateGenerator(outputFormat, templateFormat, cssFile) {
 | 
				
			||||||
 | 
					      TemplateGenerator.__super__.constructor.call(this, outputFormat);
 | 
				
			||||||
      this.tplFormat = templateFormat || outputFormat;
 | 
					      this.tplFormat = templateFormat || outputFormat;
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Generate a resume using string-based inputs and outputs without touching
 | 
					    /** Generate a resume using string-based inputs and outputs without touching
 | 
				
			||||||
    the filesystem.
 | 
					    the filesystem.
 | 
				
			||||||
    @method invoke
 | 
					    @method invoke
 | 
				
			||||||
    @param rez A FreshResume object.
 | 
					    @param rez A FreshResume object.
 | 
				
			||||||
    @param opts Generator options.
 | 
					    @param opts Generator options.
 | 
				
			||||||
    @returns {Array} An array of objects representing the generated output
 | 
					    @returns {Array} An array of objects representing the generated output
 | 
				
			||||||
    files. */
 | 
					    files.
 | 
				
			||||||
    invoke(rez, opts) {
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TemplateGenerator.prototype.invoke = function(rez, opts) {
 | 
				
			||||||
      var curFmt, results;
 | 
					      var curFmt, results;
 | 
				
			||||||
      opts = opts ? (this.opts = EXTEND(true, {}, _defaultOpts, opts)) : this.opts;
 | 
					      opts = opts ? (this.opts = EXTEND(true, {}, _defaultOpts, opts)) : this.opts;
 | 
				
			||||||
      // Sort such that CSS files are processed before others
 | 
					 | 
				
			||||||
      curFmt = opts.themeObj.getFormat(this.format);
 | 
					      curFmt = opts.themeObj.getFormat(this.format);
 | 
				
			||||||
      curFmt.files = _.sortBy(curFmt.files, function(fi) {
 | 
					      curFmt.files = _.sortBy(curFmt.files, function(fi) {
 | 
				
			||||||
        return fi.ext !== 'css';
 | 
					        return fi.ext !== 'css';
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      // Run the transformation!
 | 
					 | 
				
			||||||
      results = curFmt.files.map(function(tplInfo, idx) {
 | 
					      results = curFmt.files.map(function(tplInfo, idx) {
 | 
				
			||||||
        var trx;
 | 
					        var trx;
 | 
				
			||||||
        if (tplInfo.action === 'transform') {
 | 
					        if (tplInfo.action === 'transform') {
 | 
				
			||||||
@@ -86,30 +95,25 @@
 | 
				
			|||||||
      return {
 | 
					      return {
 | 
				
			||||||
        files: results
 | 
					        files: results
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Generate a resume using file-based inputs and outputs. Requires access
 | 
					    /** Generate a resume using file-based inputs and outputs. Requires access
 | 
				
			||||||
    to the local filesystem.
 | 
					    to the local filesystem.
 | 
				
			||||||
    @method generate
 | 
					    @method generate
 | 
				
			||||||
    @param rez A FreshResume object.
 | 
					    @param rez A FreshResume object.
 | 
				
			||||||
    @param f Full path to the output resume file to generate.
 | 
					    @param f Full path to the output resume file to generate.
 | 
				
			||||||
    @param opts Generator options. */
 | 
					    @param opts Generator options.
 | 
				
			||||||
    generate(rez, f, opts) {
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TemplateGenerator.prototype.generate = function(rez, f, opts) {
 | 
				
			||||||
      var curFmt, genInfo, outFolder;
 | 
					      var curFmt, genInfo, outFolder;
 | 
				
			||||||
      // Prepare
 | 
					 | 
				
			||||||
      this.opts = EXTEND(true, {}, _defaultOpts, opts);
 | 
					      this.opts = EXTEND(true, {}, _defaultOpts, opts);
 | 
				
			||||||
      // Call the string-based generation method
 | 
					 | 
				
			||||||
      genInfo = this.invoke(rez, null);
 | 
					      genInfo = this.invoke(rez, null);
 | 
				
			||||||
      outFolder = parsePath(f).dirname;
 | 
					      outFolder = parsePath(f).dirname;
 | 
				
			||||||
      curFmt = opts.themeObj.getFormat(this.format);
 | 
					      curFmt = opts.themeObj.getFormat(this.format);
 | 
				
			||||||
      // Process individual files within this format. For example, the HTML
 | 
					 | 
				
			||||||
      // output format for a theme may have multiple HTML files, CSS files,
 | 
					 | 
				
			||||||
      // etc. Process them here.
 | 
					 | 
				
			||||||
      genInfo.files.forEach(function(file) {
 | 
					      genInfo.files.forEach(function(file) {
 | 
				
			||||||
        var thisFilePath;
 | 
					        var thisFilePath;
 | 
				
			||||||
        // console.dir _.omit(file.info,'cssData','data','css' )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Pre-processing
 | 
					 | 
				
			||||||
        file.info.orgPath = file.info.orgPath || '';
 | 
					        file.info.orgPath = file.info.orgPath || '';
 | 
				
			||||||
        thisFilePath = file.info.primary ? f : PATH.join(outFolder, file.info.orgPath);
 | 
					        thisFilePath = file.info.primary ? f : PATH.join(outFolder, file.info.orgPath);
 | 
				
			||||||
        if (file.info.action !== 'copy' && this.onBeforeSave) {
 | 
					        if (file.info.action !== 'copy' && this.onBeforeSave) {
 | 
				
			||||||
@@ -125,9 +129,7 @@
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (typeof opts.beforeWrite === "function") {
 | 
					        if (typeof opts.beforeWrite === "function") {
 | 
				
			||||||
          opts.beforeWrite({
 | 
					          opts.beforeWrite(thisFilePath);
 | 
				
			||||||
            data: thisFilePath
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        MKDIRP.sync(PATH.dirname(thisFilePath));
 | 
					        MKDIRP.sync(PATH.dirname(thisFilePath));
 | 
				
			||||||
        if (file.info.action !== 'copy') {
 | 
					        if (file.info.action !== 'copy') {
 | 
				
			||||||
@@ -139,11 +141,8 @@
 | 
				
			|||||||
          FS.copySync(file.info.path, thisFilePath);
 | 
					          FS.copySync(file.info.path, thisFilePath);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (typeof opts.afterWrite === "function") {
 | 
					        if (typeof opts.afterWrite === "function") {
 | 
				
			||||||
          opts.afterWrite({
 | 
					          opts.afterWrite(thisFilePath);
 | 
				
			||||||
            data: thisFilePath
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // Post-processing
 | 
					 | 
				
			||||||
        if (this.onAfterSave) {
 | 
					        if (this.onAfterSave) {
 | 
				
			||||||
          return this.onAfterSave({
 | 
					          return this.onAfterSave({
 | 
				
			||||||
            outputFile: fileName,
 | 
					            outputFile: fileName,
 | 
				
			||||||
@@ -152,10 +151,10 @@
 | 
				
			|||||||
          });
 | 
					          });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }, this);
 | 
					      }, this);
 | 
				
			||||||
      // Some themes require a symlink structure. If so, create it.
 | 
					 | 
				
			||||||
      createSymLinks(curFmt, outFolder);
 | 
					      createSymLinks(curFmt, outFolder);
 | 
				
			||||||
      return genInfo;
 | 
					      return genInfo;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Perform a single resume resume transformation using string-based inputs
 | 
					    /** Perform a single resume resume transformation using string-based inputs
 | 
				
			||||||
    and outputs without touching the local file system.
 | 
					    and outputs without touching the local file system.
 | 
				
			||||||
@@ -163,8 +162,10 @@
 | 
				
			|||||||
    @param jst The stringified template data
 | 
					    @param jst The stringified template data
 | 
				
			||||||
    @param format The format name, such as "html" or "latex"
 | 
					    @param format The format name, such as "html" or "latex"
 | 
				
			||||||
    @param cssInfo Needs to be refactored.
 | 
					    @param cssInfo Needs to be refactored.
 | 
				
			||||||
    @param opts Options and passthrough data. */
 | 
					    @param opts Options and passthrough data.
 | 
				
			||||||
    transform(json, jst, format, opts, theme, curFmt) {
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TemplateGenerator.prototype.transform = function(json, jst, format, opts, theme, curFmt) {
 | 
				
			||||||
      var eng, result;
 | 
					      var eng, result;
 | 
				
			||||||
      if (this.opts.freezeBreaks) {
 | 
					      if (this.opts.freezeBreaks) {
 | 
				
			||||||
        jst = freeze(jst);
 | 
					        jst = freeze(jst);
 | 
				
			||||||
@@ -175,30 +176,29 @@
 | 
				
			|||||||
        result = unfreeze(result);
 | 
					        result = unfreeze(result);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return result;
 | 
					      return result;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return TemplateGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(BaseGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  createSymLinks = function(curFmt, outFolder) {
 | 
					  createSymLinks = function(curFmt, outFolder) {
 | 
				
			||||||
    // Some themes require a symlink structure. If so, create it.
 | 
					 | 
				
			||||||
    if (curFmt.symLinks) {
 | 
					    if (curFmt.symLinks) {
 | 
				
			||||||
      Object.keys(curFmt.symLinks).forEach(function(loc) {
 | 
					      Object.keys(curFmt.symLinks).forEach(function(loc) {
 | 
				
			||||||
        var absLoc, absTarg, err, succeeded, type;
 | 
					        var absLoc, absTarg, succeeded, type;
 | 
				
			||||||
        absLoc = PATH.join(outFolder, loc);
 | 
					        absLoc = PATH.join(outFolder, loc);
 | 
				
			||||||
        absTarg = PATH.join(PATH.dirname(absLoc), curFmt.symLinks[loc]);
 | 
					        absTarg = PATH.join(PATH.dirname(absLoc), curFmt.symLinks[loc]);
 | 
				
			||||||
        // Set type to 'file', 'dir', or 'junction' (Windows only)
 | 
					 | 
				
			||||||
        type = parsePath(absLoc).extname ? 'file' : 'junction';
 | 
					        type = parsePath(absLoc).extname ? 'file' : 'junction';
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
          return FS.symlinkSync(absTarg, absLoc, type);
 | 
					          return FS.symlinkSync(absTarg, absLoc, type);
 | 
				
			||||||
        } catch (error) {
 | 
					        } catch (_error) {
 | 
				
			||||||
          err = error;
 | 
					 | 
				
			||||||
          succeeded = false;
 | 
					          succeeded = false;
 | 
				
			||||||
          if (err.code === 'EEXIST') {
 | 
					          if (_error.code === 'EEXIST') {
 | 
				
			||||||
            FS.unlinkSync(absLoc);
 | 
					            FS.unlinkSync(absLoc);
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
              FS.symlinkSync(absTarg, absLoc, type);
 | 
					              FS.symlinkSync(absTarg, absLoc, type);
 | 
				
			||||||
              succeeded = true;
 | 
					              succeeded = true;
 | 
				
			||||||
            } catch (error) {}
 | 
					            } catch (_error) {}
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          if (!succeeded) {
 | 
					          if (!succeeded) {
 | 
				
			||||||
            throw ex;
 | 
					            throw ex;
 | 
				
			||||||
@@ -208,22 +208,31 @@
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Freeze newlines for protection against errant JST parsers. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  freeze = function(markup) {
 | 
					  freeze = function(markup) {
 | 
				
			||||||
    markup.replace(_reg.regN, _defaultOpts.nSym);
 | 
					    markup.replace(_reg.regN, _defaultOpts.nSym);
 | 
				
			||||||
    return markup.replace(_reg.regR, _defaultOpts.rSym);
 | 
					    return markup.replace(_reg.regR, _defaultOpts.rSym);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Unfreeze newlines when the coast is clear. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  unfreeze = function(markup) {
 | 
					  unfreeze = function(markup) {
 | 
				
			||||||
    markup.replace(_reg.regSymR, '\r');
 | 
					    markup.replace(_reg.regSymR, '\r');
 | 
				
			||||||
    return markup.replace(_reg.regSymN, '\n');
 | 
					    return markup.replace(_reg.regSymN, '\n');
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Default template generator options. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _defaultOpts = {
 | 
					  _defaultOpts = {
 | 
				
			||||||
    engine: 'underscore',
 | 
					    engine: 'underscore',
 | 
				
			||||||
    keepBreaks: true,
 | 
					    keepBreaks: true,
 | 
				
			||||||
    freezeBreaks: false,
 | 
					    freezeBreaks: false,
 | 
				
			||||||
    nSym: '&newl;', // newline entity
 | 
					    nSym: '&newl;',
 | 
				
			||||||
    rSym: '&retn;', // return entity
 | 
					    rSym: '&retn;',
 | 
				
			||||||
    template: {
 | 
					    template: {
 | 
				
			||||||
      interpolate: /\{\{(.+?)\}\}/g,
 | 
					      interpolate: /\{\{(.+?)\}\}/g,
 | 
				
			||||||
      escape: /\{\{\=(.+?)\}\}/g,
 | 
					      escape: /\{\{\=(.+?)\}\}/g,
 | 
				
			||||||
@@ -260,12 +269,13 @@
 | 
				
			|||||||
    prettify: {
 | 
					    prettify: {
 | 
				
			||||||
      indent_size: 2,
 | 
					      indent_size: 2,
 | 
				
			||||||
      unformatted: ['em', 'strong', 'a'],
 | 
					      unformatted: ['em', 'strong', 'a'],
 | 
				
			||||||
      max_char: 80 // ← See lib/html.js in above-linked repo
 | 
					      max_char: 80
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //wrap_line_length: 120, <-- Don't use this
 | 
					
 | 
				
			||||||
  /** Regexes for linebreak preservation. */
 | 
					  /** Regexes for linebreak preservation. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _reg = {
 | 
					  _reg = {
 | 
				
			||||||
    regN: new RegExp('\n', 'g'),
 | 
					    regN: new RegExp('\n', 'g'),
 | 
				
			||||||
    regR: new RegExp('\r', 'g'),
 | 
					    regR: new RegExp('\r', 'g'),
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								dist/generators/text-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								dist/generators/text-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,22 +1,32 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the TextGenerator class.
 | 
				
			||||||
 | 
					@module generators/text-generator
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var TemplateGenerator, TextGenerator,
 | 
				
			||||||
  Definition of the TextGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module generators/text-generator
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var TemplateGenerator, TextGenerator;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TemplateGenerator = require('./template-generator');
 | 
					  TemplateGenerator = require('./template-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  The TextGenerator generates a plain-text resume via the TemplateGenerator.
 | 
					  The TextGenerator generates a plain-text resume via the TemplateGenerator.
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = TextGenerator = class TextGenerator extends TemplateGenerator {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = TextGenerator = (function(superClass) {
 | 
				
			||||||
      super('txt');
 | 
					    extend(TextGenerator, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function TextGenerator() {
 | 
				
			||||||
 | 
					      TextGenerator.__super__.constructor.call(this, 'txt');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return TextGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(TemplateGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								dist/generators/word-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								dist/generators/word-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,19 +1,27 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Definition of the WordGenerator class.
 | 
				
			||||||
 | 
					@module generators/word-generator
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /*
 | 
					  var TemplateGenerator, WordGenerator,
 | 
				
			||||||
  Definition of the WordGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module generators/word-generator
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var TemplateGenerator, WordGenerator;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TemplateGenerator = require('./template-generator');
 | 
					  TemplateGenerator = require('./template-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = WordGenerator = class WordGenerator extends TemplateGenerator {
 | 
					  module.exports = WordGenerator = (function(superClass) {
 | 
				
			||||||
    constructor() {
 | 
					    extend(WordGenerator, superClass);
 | 
				
			||||||
      super('doc', 'xml');
 | 
					
 | 
				
			||||||
 | 
					    function WordGenerator() {
 | 
				
			||||||
 | 
					      WordGenerator.__super__.constructor.call(this, 'doc', 'xml');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return WordGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(TemplateGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								dist/generators/xml-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								dist/generators/xml-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,20 +1,30 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the XMLGenerator class.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module generatprs/xml-generator
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var BaseGenerator, XMLGenerator,
 | 
				
			||||||
  Definition of the XMLGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @module generatprs/xml-generator
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var BaseGenerator, XMLGenerator;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  BaseGenerator = require('./base-generator');
 | 
					  BaseGenerator = require('./base-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** The XmlGenerator generates an XML resume via the TemplateGenerator. */
 | 
					  /** The XmlGenerator generates an XML resume via the TemplateGenerator. */
 | 
				
			||||||
  module.exports = XMLGenerator = class XMLGenerator extends BaseGenerator {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = XMLGenerator = (function(superClass) {
 | 
				
			||||||
      super('xml');
 | 
					    extend(XMLGenerator, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function XMLGenerator() {
 | 
				
			||||||
 | 
					      XMLGenerator.__super__.constructor.call(this, 'xml');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return XMLGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(BaseGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								dist/generators/yaml-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								dist/generators/yaml-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,22 +1,32 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the YAMLGenerator class.
 | 
				
			||||||
 | 
					@module yaml-generator.js
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var TemplateGenerator, YAMLGenerator,
 | 
				
			||||||
  Definition of the YAMLGenerator class.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module yaml-generator.js
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var TemplateGenerator, YAMLGenerator;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TemplateGenerator = require('./template-generator');
 | 
					  TemplateGenerator = require('./template-generator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  YamlGenerator generates a YAML-formatted resume via TemplateGenerator.
 | 
					  YamlGenerator generates a YAML-formatted resume via TemplateGenerator.
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = YAMLGenerator = class YAMLGenerator extends TemplateGenerator {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = YAMLGenerator = (function(superClass) {
 | 
				
			||||||
      super('yml', 'yml');
 | 
					    extend(YAMLGenerator, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function YAMLGenerator() {
 | 
				
			||||||
 | 
					      YAMLGenerator.__super__.constructor.call(this, 'yml', 'yml');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return YAMLGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(TemplateGenerator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										35
									
								
								dist/helpers/block-helpers.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								dist/helpers/block-helpers.js
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Block helper definitions for HackMyResume / FluentCV.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module helpers/generic-helpers
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Block helper definitions for HackMyResume / FluentCV.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module helpers/generic-helpers
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** Block helper function definitions. */
 | 
					 | 
				
			||||||
  var BlockHelpers, HMSTATUS, LO, _, unused;
 | 
					  var BlockHelpers, HMSTATUS, LO, _, unused;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HMSTATUS = require('../core/status-codes');
 | 
					  HMSTATUS = require('../core/status-codes');
 | 
				
			||||||
@@ -15,11 +16,15 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  unused = require('../utils/string');
 | 
					  unused = require('../utils/string');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Block helper function definitions. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  BlockHelpers = module.exports = {
 | 
					  BlockHelpers = module.exports = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Emit the enclosed content if the resume has a section with
 | 
					    Emit the enclosed content if the resume has a section with
 | 
				
			||||||
    the specified name. Otherwise, emit an empty string ''.
 | 
					    the specified name. Otherwise, emit an empty string ''.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    section: function(title, options) {
 | 
					    section: function(title, options) {
 | 
				
			||||||
      var obj, ret;
 | 
					      var obj, ret;
 | 
				
			||||||
      title = title.trim().toLowerCase();
 | 
					      title = title.trim().toLowerCase();
 | 
				
			||||||
@@ -38,30 +43,22 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      return ret;
 | 
					      return ret;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    ifHasSkill: function(rez, skill, options) {
 | 
					
 | 
				
			||||||
      var ret, skUp;
 | 
					 | 
				
			||||||
      skUp = skill.toUpperCase();
 | 
					 | 
				
			||||||
      ret = _.some(rez.skills.list, function(sk) {
 | 
					 | 
				
			||||||
        return (skUp.toUpperCase() === sk.name.toUpperCase()) && sk.years;
 | 
					 | 
				
			||||||
      }, this);
 | 
					 | 
				
			||||||
      if (ret) {
 | 
					 | 
				
			||||||
        return options.fn(this);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Emit the enclosed content if the resume has the named
 | 
					    Emit the enclosed content if the resume has the named
 | 
				
			||||||
    property or subproperty.
 | 
					    property or subproperty.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    has: function(title, options) {
 | 
					    has: function(title, options) {
 | 
				
			||||||
      title = title && title.trim().toLowerCase();
 | 
					      title = title && title.trim().toLowerCase();
 | 
				
			||||||
      if (LO.get(this.r, title)) {
 | 
					      if (LO.get(this.r, title)) {
 | 
				
			||||||
        return options.fn(this);
 | 
					        return options.fn(this);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Return true if either value is truthy.
 | 
					    Return true if either value is truthy.
 | 
				
			||||||
    @method either
 | 
					    @method either
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    either: function(lhs, rhs, options) {
 | 
					    either: function(lhs, rhs, options) {
 | 
				
			||||||
      if (lhs || rhs) {
 | 
					      if (lhs || rhs) {
 | 
				
			||||||
        return options.fn(this);
 | 
					        return options.fn(this);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								dist/helpers/console-helpers.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								dist/helpers/console-helpers.js
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Generic template helper definitions for command-line output.
 | 
				
			||||||
 | 
					@module console-helpers.js
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Generic template helper definitions for command-line output.
 | 
					 | 
				
			||||||
  @module console-helpers.js
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var CHALK, LO, PAD, _, consoleFormatHelpers;
 | 
					  var CHALK, LO, PAD, _, consoleFormatHelpers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PAD = require('string-padding');
 | 
					  PAD = require('string-padding');
 | 
				
			||||||
@@ -19,7 +21,7 @@
 | 
				
			|||||||
  consoleFormatHelpers = module.exports = {
 | 
					  consoleFormatHelpers = module.exports = {
 | 
				
			||||||
    v: function(val, defaultVal, padding, style) {
 | 
					    v: function(val, defaultVal, padding, style) {
 | 
				
			||||||
      var retVal, spaces;
 | 
					      var retVal, spaces;
 | 
				
			||||||
      retVal = (val === null || val === void 0) ? defaultVal : val;
 | 
					      retVal = val === null || val === void 0 ? defaultVal : val;
 | 
				
			||||||
      spaces = 0;
 | 
					      spaces = 0;
 | 
				
			||||||
      if (String.is(padding)) {
 | 
					      if (String.is(padding)) {
 | 
				
			||||||
        spaces = parseInt(padding, 10);
 | 
					        spaces = parseInt(padding, 10);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										224
									
								
								dist/helpers/generic-helpers.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										224
									
								
								dist/helpers/generic-helpers.js
									
									
									
									
										vendored
									
									
								
							@@ -1,18 +1,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Generic template helper definitions for HackMyResume / FluentCV.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module helpers/generic-helpers
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var FS, FluentDate, GenericHelpers, H2W, HMSTATUS, LO, MD, PATH, XML, _, _fromTo, _reportError, moment, printf, skillLevelToIndex, unused;
 | 
				
			||||||
  Generic template helper definitions for HackMyResume / FluentCV.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module helpers/generic-helpers
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** Generic template helper function definitions. */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Format a from/to date range for display.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Report an error to the outside world without throwing an exception. Currently
 | 
					 | 
				
			||||||
  relies on kludging the running verb into. opts.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FS, FluentDate, GenericHelpers, H2W, HMSTATUS, LO, MD, PATH, XML, _, _fromTo, _reportError, _skillLevelToIndex, moment, printf, unused;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  MD = require('marked');
 | 
					  MD = require('marked');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -38,7 +32,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  unused = require('../utils/string');
 | 
					  unused = require('../utils/string');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Generic template helper function definitions. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  GenericHelpers = module.exports = {
 | 
					  GenericHelpers = module.exports = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Emit a formatted string representing the specified datetime.
 | 
					    Emit a formatted string representing the specified datetime.
 | 
				
			||||||
    Convert the input date to the specified format through Moment.js. If date is
 | 
					    Convert the input date to the specified format through Moment.js. If date is
 | 
				
			||||||
@@ -51,7 +49,7 @@
 | 
				
			|||||||
    Moment.js-compatible datetime format.
 | 
					    Moment.js-compatible datetime format.
 | 
				
			||||||
    @param {string|Moment} fallback A fallback value to use if the specified date
 | 
					    @param {string|Moment} fallback A fallback value to use if the specified date
 | 
				
			||||||
    is null, undefined, or falsy.
 | 
					    is null, undefined, or falsy.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    formatDate: function(datetime, dtFormat, fallback) {
 | 
					    formatDate: function(datetime, dtFormat, fallback) {
 | 
				
			||||||
      var momentDate;
 | 
					      var momentDate;
 | 
				
			||||||
      if (datetime == null) {
 | 
					      if (datetime == null) {
 | 
				
			||||||
@@ -60,32 +58,22 @@
 | 
				
			|||||||
      if (dtFormat == null) {
 | 
					      if (dtFormat == null) {
 | 
				
			||||||
        dtFormat = 'YYYY-MM';
 | 
					        dtFormat = 'YYYY-MM';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // If a Moment.js object was passed in, just call format on it
 | 
					 | 
				
			||||||
      if (datetime && moment.isMoment(datetime)) {
 | 
					      if (datetime && moment.isMoment(datetime)) {
 | 
				
			||||||
        return datetime.format(dtFormat);
 | 
					        return datetime.format(dtFormat);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (String.is(datetime)) {
 | 
					      if (String.is(datetime)) {
 | 
				
			||||||
        // If a string was passed in, convert to Moment using the 2-paramter
 | 
					 | 
				
			||||||
        // constructor with an explicit format string.
 | 
					 | 
				
			||||||
        momentDate = moment(datetime, dtFormat);
 | 
					        momentDate = moment(datetime, dtFormat);
 | 
				
			||||||
        if (momentDate.isValid()) {
 | 
					        if (momentDate.isValid()) {
 | 
				
			||||||
          return momentDate.format(dtFormat);
 | 
					          return momentDate.format(dtFormat);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // If that didn't work, try again with the single-parameter constructor
 | 
					 | 
				
			||||||
        // but this may throw a deprecation warning
 | 
					 | 
				
			||||||
        momentDate = moment(datetime);
 | 
					        momentDate = moment(datetime);
 | 
				
			||||||
        if (momentDate.isValid()) {
 | 
					        if (momentDate.isValid()) {
 | 
				
			||||||
          return momentDate.format(dtFormat);
 | 
					          return momentDate.format(dtFormat);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // We weren't able to format the provided datetime. Now do one of three
 | 
					 | 
				
			||||||
      // things.
 | 
					 | 
				
			||||||
      //   1. If datetime is non-null/non-falsy, return it. For this helper,
 | 
					 | 
				
			||||||
      // string date values that we can't parse are assumed to be display dates.
 | 
					 | 
				
			||||||
      //   2. If datetime IS null or falsy, use the value from the fallback.
 | 
					 | 
				
			||||||
      //   3. If the fallback value is specifically 'true', emit 'Present'.
 | 
					 | 
				
			||||||
      return datetime || (typeof fallback === 'string' ? fallback : (fallback === true ? 'Present' : ''));
 | 
					      return datetime || (typeof fallback === 'string' ? fallback : (fallback === true ? 'Present' : ''));
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Emit a formatted string representing the specified datetime.
 | 
					    Emit a formatted string representing the specified datetime.
 | 
				
			||||||
    @param {string} dateValue A raw date value from the FRESH or JRS resume.
 | 
					    @param {string} dateValue A raw date value from the FRESH or JRS resume.
 | 
				
			||||||
@@ -93,7 +81,7 @@
 | 
				
			|||||||
    compatible with Moment.js datetime formats.
 | 
					    compatible with Moment.js datetime formats.
 | 
				
			||||||
    @param {string} [dateDefault=null] The default date value to use if the dateValue
 | 
					    @param {string} [dateDefault=null] The default date value to use if the dateValue
 | 
				
			||||||
    parameter is null, undefined, or falsy.
 | 
					    parameter is null, undefined, or falsy.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    date: function(dateValue, dateFormat, dateDefault) {
 | 
					    date: function(dateValue, dateFormat, dateDefault) {
 | 
				
			||||||
      var dateValueMoment, dateValueSafe, reserved;
 | 
					      var dateValueMoment, dateValueSafe, reserved;
 | 
				
			||||||
      if (!dateDefault || !String.is(dateDefault)) {
 | 
					      if (!dateDefault || !String.is(dateDefault)) {
 | 
				
			||||||
@@ -119,27 +107,30 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      return dateValue;
 | 
					      return dateValue;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Given a resume sub-object with a start/end date, format a representation of
 | 
					    Given a resume sub-object with a start/end date, format a representation of
 | 
				
			||||||
    the date range.
 | 
					    the date range.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    dateRange: function(obj, fmt, sep, fallback) {
 | 
					    dateRange: function(obj, fmt, sep, fallback) {
 | 
				
			||||||
      if (!obj) {
 | 
					      if (!obj) {
 | 
				
			||||||
        return '';
 | 
					        return '';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return _fromTo(obj.start, obj.end, fmt, sep, fallback);
 | 
					      return _fromTo(obj.start, obj.end, fmt, sep, fallback);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Format a from/to date range for display.
 | 
					    Format a from/to date range for display.
 | 
				
			||||||
    @method toFrom
 | 
					    @method toFrom
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    fromTo: function() {
 | 
					    fromTo: function() {
 | 
				
			||||||
      return _fromTo.apply(this, arguments);
 | 
					      return _fromTo.apply(this, arguments);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Return a named color value as an RRGGBB string.
 | 
					    Return a named color value as an RRGGBB string.
 | 
				
			||||||
    @method toFrom
 | 
					    @method toFrom
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    color: function(colorName, colorDefault) {
 | 
					    color: function(colorName, colorDefault) {
 | 
				
			||||||
      var ret;
 | 
					      var ret;
 | 
				
			||||||
      if (!(colorName && colorName.trim())) {
 | 
					      if (!(colorName && colorName.trim())) {
 | 
				
			||||||
@@ -159,11 +150,12 @@
 | 
				
			|||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Emit the size of the specified named font.
 | 
					    Emit the size of the specified named font.
 | 
				
			||||||
    @param key {String} A named style from the "fonts" section of the theme's
 | 
					    @param key {String} A named style from the "fonts" section of the theme's
 | 
				
			||||||
    theme.json file. For example: 'default' or 'heading1'.
 | 
					    theme.json file. For example: 'default' or 'heading1'.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    fontSize: function(key, defSize, units) {
 | 
					    fontSize: function(key, defSize, units) {
 | 
				
			||||||
      var fontSpec, hasDef, ret;
 | 
					      var fontSpec, hasDef, ret;
 | 
				
			||||||
      ret = '';
 | 
					      ret = '';
 | 
				
			||||||
@@ -178,22 +170,18 @@
 | 
				
			|||||||
      } else if (GenericHelpers.theme.fonts) {
 | 
					      } else if (GenericHelpers.theme.fonts) {
 | 
				
			||||||
        fontSpec = LO.get(GenericHelpers.theme.fonts, this.format + '.' + key);
 | 
					        fontSpec = LO.get(GenericHelpers.theme.fonts, this.format + '.' + key);
 | 
				
			||||||
        if (!fontSpec) {
 | 
					        if (!fontSpec) {
 | 
				
			||||||
          // Check for an "all" format
 | 
					 | 
				
			||||||
          if (GenericHelpers.theme.fonts.all) {
 | 
					          if (GenericHelpers.theme.fonts.all) {
 | 
				
			||||||
            fontSpec = GenericHelpers.theme.fonts.all[key];
 | 
					            fontSpec = GenericHelpers.theme.fonts.all[key];
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (fontSpec) {
 | 
					        if (fontSpec) {
 | 
				
			||||||
          // fontSpec can be a string, an array, or an object
 | 
					 | 
				
			||||||
          if (String.is(fontSpec)) {
 | 
					          if (String.is(fontSpec)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // No font size was specified, only a font family.
 | 
					 | 
				
			||||||
          } else if (_.isArray(fontSpec)) {
 | 
					          } else if (_.isArray(fontSpec)) {
 | 
				
			||||||
            if (!String.is(fontSpec[0])) {
 | 
					            if (!String.is(fontSpec[0])) {
 | 
				
			||||||
              ret = fontSpec[0].size;
 | 
					              ret = fontSpec[0].size;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            // A font description object.
 | 
					 | 
				
			||||||
            ret = fontSpec.size;
 | 
					            ret = fontSpec.size;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -212,6 +200,7 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      return ret;
 | 
					      return ret;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Emit the font face (such as 'Helvetica' or 'Calibri') associated with the
 | 
					    Emit the font face (such as 'Helvetica' or 'Calibri') associated with the
 | 
				
			||||||
    provided key.
 | 
					    provided key.
 | 
				
			||||||
@@ -219,7 +208,7 @@
 | 
				
			|||||||
    theme.json file. For example: 'default' or 'heading1'.
 | 
					    theme.json file. For example: 'default' or 'heading1'.
 | 
				
			||||||
    @param defFont {String} The font to use if the specified key isn't present.
 | 
					    @param defFont {String} The font to use if the specified key isn't present.
 | 
				
			||||||
    Can be any valid font-face name such as 'Helvetica Neue' or 'Calibri'.
 | 
					    Can be any valid font-face name such as 'Helvetica Neue' or 'Calibri'.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    fontFace: function(key, defFont) {
 | 
					    fontFace: function(key, defFont) {
 | 
				
			||||||
      var fontSpec, hasDef, ret;
 | 
					      var fontSpec, hasDef, ret;
 | 
				
			||||||
      ret = '';
 | 
					      ret = '';
 | 
				
			||||||
@@ -231,25 +220,19 @@
 | 
				
			|||||||
          expected: 'key'
 | 
					          expected: 'key'
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
      // If the theme has a "fonts" section, lookup the font face.
 | 
					 | 
				
			||||||
      } else if (GenericHelpers.theme.fonts) {
 | 
					      } else if (GenericHelpers.theme.fonts) {
 | 
				
			||||||
        fontSpec = LO.get(GenericHelpers.theme.fonts, this.format + '.' + key);
 | 
					        fontSpec = LO.get(GenericHelpers.theme.fonts, this.format + '.' + key);
 | 
				
			||||||
        if (!fontSpec) {
 | 
					        if (!fontSpec) {
 | 
				
			||||||
          // Check for an "all" format
 | 
					 | 
				
			||||||
          if (GenericHelpers.theme.fonts.all) {
 | 
					          if (GenericHelpers.theme.fonts.all) {
 | 
				
			||||||
            fontSpec = GenericHelpers.theme.fonts.all[key];
 | 
					            fontSpec = GenericHelpers.theme.fonts.all[key];
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (fontSpec) {
 | 
					        if (fontSpec) {
 | 
				
			||||||
          // fontSpec can be a string, an array, or an object
 | 
					 | 
				
			||||||
          if (String.is(fontSpec)) {
 | 
					          if (String.is(fontSpec)) {
 | 
				
			||||||
            ret = fontSpec;
 | 
					            ret = fontSpec;
 | 
				
			||||||
          } else if (_.isArray(fontSpec)) {
 | 
					          } else if (_.isArray(fontSpec)) {
 | 
				
			||||||
            // An array of fonts were specified. Each one could be a string
 | 
					 | 
				
			||||||
            // or an object
 | 
					 | 
				
			||||||
            ret = String.is(fontSpec[0]) ? fontSpec[0] : fontSpec[0].name;
 | 
					            ret = String.is(fontSpec[0]) ? fontSpec[0] : fontSpec[0].name;
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            // A font description object.
 | 
					 | 
				
			||||||
            ret = fontSpec.name;
 | 
					            ret = fontSpec.name;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -267,6 +250,18 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      return ret;
 | 
					      return ret;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    Emit a comma-delimited list of font names suitable associated with the
 | 
				
			||||||
 | 
					    provided key.
 | 
				
			||||||
 | 
					    @param key {String} A named style from the "fonts" section of the theme's
 | 
				
			||||||
 | 
					    theme.json file. For example: 'default' or 'heading1'.
 | 
				
			||||||
 | 
					    @param defFontList {Array} The font list to use if the specified key isn't
 | 
				
			||||||
 | 
					    present. Can be an array of valid font-face name such as 'Helvetica Neue'
 | 
				
			||||||
 | 
					    or 'Calibri'.
 | 
				
			||||||
 | 
					    @param sep {String} The default separator to use in the rendered output.
 | 
				
			||||||
 | 
					    Defaults to ", " (comma with a space).
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    fontList: function(key, defFontList, sep) {
 | 
					    fontList: function(key, defFontList, sep) {
 | 
				
			||||||
      var fontSpec, hasDef, ret;
 | 
					      var fontSpec, hasDef, ret;
 | 
				
			||||||
      ret = '';
 | 
					      ret = '';
 | 
				
			||||||
@@ -285,18 +280,14 @@
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (fontSpec) {
 | 
					        if (fontSpec) {
 | 
				
			||||||
          // fontSpec can be a string, an array, or an object
 | 
					 | 
				
			||||||
          if (String.is(fontSpec)) {
 | 
					          if (String.is(fontSpec)) {
 | 
				
			||||||
            ret = fontSpec;
 | 
					            ret = fontSpec;
 | 
				
			||||||
          } else if (_.isArray(fontSpec)) {
 | 
					          } else if (_.isArray(fontSpec)) {
 | 
				
			||||||
            // An array of fonts were specified. Each one could be a string
 | 
					 | 
				
			||||||
            // or an object
 | 
					 | 
				
			||||||
            fontSpec = fontSpec.map(function(ff) {
 | 
					            fontSpec = fontSpec.map(function(ff) {
 | 
				
			||||||
              return "'" + (String.is(ff) ? ff : ff.name) + "'";
 | 
					              return "'" + (String.is(ff) ? ff : ff.name) + "'";
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            ret = fontSpec.join(sep === void 0 ? ', ' : sep || '');
 | 
					            ret = fontSpec.join(sep === void 0 ? ', ' : sep || '');
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            // A font description object.
 | 
					 | 
				
			||||||
            ret = fontSpec.name;
 | 
					            ret = fontSpec.name;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -315,6 +306,11 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      return ret;
 | 
					      return ret;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    Capitalize the first letter of the word. TODO: Rename
 | 
				
			||||||
 | 
					    @method section
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    camelCase: function(val) {
 | 
					    camelCase: function(val) {
 | 
				
			||||||
      val = (val && val.trim()) || '';
 | 
					      val = (val && val.trim()) || '';
 | 
				
			||||||
      if (val) {
 | 
					      if (val) {
 | 
				
			||||||
@@ -323,35 +319,33 @@
 | 
				
			|||||||
        return val;
 | 
					        return val;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Display a user-overridable section title for a FRESH resume theme. Use this in
 | 
					    Display a user-overridable section title for a FRESH resume theme. Use this in
 | 
				
			||||||
    lieue of hard-coding section titles.
 | 
					    lieue of hard-coding section titles.
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Usage:
 | 
					    Usage:
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    {{sectionTitle "sectionName"}}
 | 
					        {{sectionTitle "sectionName"}}
 | 
				
			||||||
    {{sectionTitle "sectionName" "sectionTitle"}}
 | 
					        {{sectionTitle "sectionName" "sectionTitle"}}
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Example:
 | 
					    Example:
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    {{sectionTitle "Education"}}
 | 
					        {{sectionTitle "Education"}}
 | 
				
			||||||
    {{sectionTitle "Employment" "Project History"}}
 | 
					        {{sectionTitle "Employment" "Project History"}}
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @param sect_name The name of the section being title. Must be one of the
 | 
					    @param sect_name The name of the section being title. Must be one of the
 | 
				
			||||||
    top-level FRESH resume sections ("info", "education", "employment", etc.).
 | 
					    top-level FRESH resume sections ("info", "education", "employment", etc.).
 | 
				
			||||||
    @param sect_title The theme-specified section title. May be replaced by the
 | 
					    @param sect_title The theme-specified section title. May be replaced by the
 | 
				
			||||||
    user.
 | 
					    user.
 | 
				
			||||||
    @method sectionTitle
 | 
					    @method sectionTitle
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    sectionTitle: function(sname, stitle) {
 | 
					    sectionTitle: function(sname, stitle) {
 | 
				
			||||||
      // If not provided by the user, stitle should default to sname. ps.
 | 
					 | 
				
			||||||
      // Handlebars silently passes in the options object to the last param,
 | 
					 | 
				
			||||||
      // where in Underscore stitle will be null/undefined, so we check both.
 | 
					 | 
				
			||||||
      // TODO: not actually sure that's true, given that we _.wrap these functions
 | 
					 | 
				
			||||||
      stitle = (stitle && String.is(stitle) && stitle) || sname;
 | 
					      stitle = (stitle && String.is(stitle) && stitle) || sname;
 | 
				
			||||||
      // If there's a section title override, use it.
 | 
					 | 
				
			||||||
      return (this.opts.stitles && this.opts.stitles[sname.toLowerCase().trim()]) || stitle;
 | 
					      return (this.opts.stitles && this.opts.stitles[sname.toLowerCase().trim()]) || stitle;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Convert inline Markdown to inline WordProcessingML. */
 | 
				
			||||||
    wpml: function(txt, inline) {
 | 
					    wpml: function(txt, inline) {
 | 
				
			||||||
      if (!txt) {
 | 
					      if (!txt) {
 | 
				
			||||||
        return '';
 | 
					        return '';
 | 
				
			||||||
@@ -362,10 +356,11 @@
 | 
				
			|||||||
      txt = H2W(txt);
 | 
					      txt = H2W(txt);
 | 
				
			||||||
      return txt;
 | 
					      return txt;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Emit a conditional link.
 | 
					    Emit a conditional link.
 | 
				
			||||||
    @method link
 | 
					    @method link
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    link: function(text, url) {
 | 
					    link: function(text, url) {
 | 
				
			||||||
      if (url && url.trim()) {
 | 
					      if (url && url.trim()) {
 | 
				
			||||||
        return '<a href="' + url + '">' + text + '</a>';
 | 
					        return '<a href="' + url + '">' + text + '</a>';
 | 
				
			||||||
@@ -373,21 +368,11 @@
 | 
				
			|||||||
        return text;
 | 
					        return text;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    /**
 | 
					
 | 
				
			||||||
    Emit a conditional Markdown link.
 | 
					 | 
				
			||||||
    @method link
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    linkMD: function(text, url) {
 | 
					 | 
				
			||||||
      if (url && url.trim()) {
 | 
					 | 
				
			||||||
        return '[' + text + '](' + url + ')';
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        return text;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Return the last word of the specified text.
 | 
					    Return the last word of the specified text.
 | 
				
			||||||
    @method lastWord
 | 
					    @method lastWord
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    lastWord: function(txt) {
 | 
					    lastWord: function(txt) {
 | 
				
			||||||
      if (txt && txt.trim()) {
 | 
					      if (txt && txt.trim()) {
 | 
				
			||||||
        return _.last(txt.split(' '));
 | 
					        return _.last(txt.split(' '));
 | 
				
			||||||
@@ -395,6 +380,7 @@
 | 
				
			|||||||
        return '';
 | 
					        return '';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Convert a skill level to an RGB color triplet. TODO: refactor
 | 
					    Convert a skill level to an RGB color triplet. TODO: refactor
 | 
				
			||||||
    @method skillColor
 | 
					    @method skillColor
 | 
				
			||||||
@@ -402,26 +388,28 @@
 | 
				
			|||||||
    ("beginner", "intermediate", etc.), as an integer (1,5,etc), as a string
 | 
					    ("beginner", "intermediate", etc.), as an integer (1,5,etc), as a string
 | 
				
			||||||
    integer ("1", "5", etc.), or as an RRGGBB color triplet ('#C00000',
 | 
					    integer ("1", "5", etc.), or as an RRGGBB color triplet ('#C00000',
 | 
				
			||||||
    '#FFFFAA').
 | 
					    '#FFFFAA').
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    skillColor: function(lvl) {
 | 
					    skillColor: function(lvl) {
 | 
				
			||||||
      var idx, skillColors;
 | 
					      var idx, skillColors;
 | 
				
			||||||
      idx = _skillLevelToIndex(lvl);
 | 
					      idx = skillLevelToIndex(lvl);
 | 
				
			||||||
      skillColors = (this.theme && this.theme.palette && this.theme.palette.skillLevels) || ['#FFFFFF', '#5CB85C', '#F1C40F', '#428BCA', '#C00000'];
 | 
					      skillColors = (this.theme && this.theme.palette && this.theme.palette.skillLevels) || ['#FFFFFF', '#5CB85C', '#F1C40F', '#428BCA', '#C00000'];
 | 
				
			||||||
      return skillColors[idx];
 | 
					      return skillColors[idx];
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Return an appropriate height. TODO: refactor
 | 
					    Return an appropriate height. TODO: refactor
 | 
				
			||||||
    @method lastWord
 | 
					    @method lastWord
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    skillHeight: function(lvl) {
 | 
					    skillHeight: function(lvl) {
 | 
				
			||||||
      var idx;
 | 
					      var idx;
 | 
				
			||||||
      idx = _skillLevelToIndex(lvl);
 | 
					      idx = skillLevelToIndex(lvl);
 | 
				
			||||||
      return ['38.25', '30', '16', '8', '0'][idx];
 | 
					      return ['38.25', '30', '16', '8', '0'][idx];
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Return all but the last word of the input text.
 | 
					    Return all but the last word of the input text.
 | 
				
			||||||
    @method initialWords
 | 
					    @method initialWords
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    initialWords: function(txt) {
 | 
					    initialWords: function(txt) {
 | 
				
			||||||
      if (txt && txt.trim()) {
 | 
					      if (txt && txt.trim()) {
 | 
				
			||||||
        return _.initial(txt.split(' ')).join(' ');
 | 
					        return _.initial(txt.split(' ')).join(' ');
 | 
				
			||||||
@@ -429,10 +417,11 @@
 | 
				
			|||||||
        return '';
 | 
					        return '';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Trim the protocol (http or https) from a URL/
 | 
					    Trim the protocol (http or https) from a URL/
 | 
				
			||||||
    @method trimURL
 | 
					    @method trimURL
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    trimURL: function(url) {
 | 
					    trimURL: function(url) {
 | 
				
			||||||
      if (url && url.trim()) {
 | 
					      if (url && url.trim()) {
 | 
				
			||||||
        return url.trim().replace(/^https?:\/\//i, '');
 | 
					        return url.trim().replace(/^https?:\/\//i, '');
 | 
				
			||||||
@@ -440,10 +429,11 @@
 | 
				
			|||||||
        return '';
 | 
					        return '';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Convert text to lowercase.
 | 
					    Convert text to lowercase.
 | 
				
			||||||
    @method toLower
 | 
					    @method toLower
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    toLower: function(txt) {
 | 
					    toLower: function(txt) {
 | 
				
			||||||
      if (txt && txt.trim()) {
 | 
					      if (txt && txt.trim()) {
 | 
				
			||||||
        return txt.toLowerCase();
 | 
					        return txt.toLowerCase();
 | 
				
			||||||
@@ -451,10 +441,11 @@
 | 
				
			|||||||
        return '';
 | 
					        return '';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Convert text to lowercase.
 | 
					    Convert text to lowercase.
 | 
				
			||||||
    @method toLower
 | 
					    @method toLower
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    toUpper: function(txt) {
 | 
					    toUpper: function(txt) {
 | 
				
			||||||
      if (txt && txt.trim()) {
 | 
					      if (txt && txt.trim()) {
 | 
				
			||||||
        return txt.toUpperCase();
 | 
					        return txt.toUpperCase();
 | 
				
			||||||
@@ -462,6 +453,7 @@
 | 
				
			|||||||
        return '';
 | 
					        return '';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Conditional stylesheet link. Creates a link to the specified stylesheet with
 | 
					    Conditional stylesheet link. Creates a link to the specified stylesheet with
 | 
				
			||||||
    <link> or embeds the styles inline with <style></style>, depending on the
 | 
					    <link> or embeds the styles inline with <style></style>, depending on the
 | 
				
			||||||
@@ -470,10 +462,9 @@
 | 
				
			|||||||
    @param linkage {String} The default link method. Can be either `embed` or
 | 
					    @param linkage {String} The default link method. Can be either `embed` or
 | 
				
			||||||
    `link`. If omitted, defaults to `embed`. Can be overridden by the `--css`
 | 
					    `link`. If omitted, defaults to `embed`. Can be overridden by the `--css`
 | 
				
			||||||
    command-line switch.
 | 
					    command-line switch.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    styleSheet: function(url, linkage) {
 | 
					    styleSheet: function(url, linkage) {
 | 
				
			||||||
      var rawCss, renderedCss, ret;
 | 
					      var rawCss, renderedCss, ret;
 | 
				
			||||||
      // Establish the linkage style
 | 
					 | 
				
			||||||
      linkage = this.opts.css || linkage || 'embed';
 | 
					      linkage = this.opts.css || linkage || 'embed';
 | 
				
			||||||
      ret = '';
 | 
					      ret = '';
 | 
				
			||||||
      if (linkage === 'link') {
 | 
					      if (linkage === 'link') {
 | 
				
			||||||
@@ -483,20 +474,17 @@
 | 
				
			|||||||
        renderedCss = this.engine.generateSimple(this, rawCss);
 | 
					        renderedCss = this.engine.generateSimple(this, rawCss);
 | 
				
			||||||
        ret = printf('<style>%s</style>', renderedCss);
 | 
					        ret = printf('<style>%s</style>', renderedCss);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // If the currently-executing template is inherited, append styles
 | 
					 | 
				
			||||||
      if (this.opts.themeObj.inherits && this.opts.themeObj.inherits.html && this.format === 'html') {
 | 
					      if (this.opts.themeObj.inherits && this.opts.themeObj.inherits.html && this.format === 'html') {
 | 
				
			||||||
        ret += linkage === 'link' ? '<link href="' + this.opts.themeObj.overrides.path + '" rel="stylesheet" type="text/css">' : '<style>' + this.opts.themeObj.overrides.data + '</style>';
 | 
					        ret += linkage === 'link' ? '<link href="' + this.opts.themeObj.overrides.path + '" rel="stylesheet" type="text/css">' : '<style>' + this.opts.themeObj.overrides.data + '</style>';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // TODO: It would be nice to use Handlebar.SafeString here, but these
 | 
					 | 
				
			||||||
      // are supposed to be generic helpers. Provide an equivalent, or expose
 | 
					 | 
				
			||||||
      // it when Handlebars is the chosen engine, which is most of the time.
 | 
					 | 
				
			||||||
      return ret;
 | 
					      return ret;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Perform a generic comparison.
 | 
					    Perform a generic comparison.
 | 
				
			||||||
    See: http://doginthehat.com.au/2012/02/comparison-block-helper-for-handlebars-templates
 | 
					    See: http://doginthehat.com.au/2012/02/comparison-block-helper-for-handlebars-templates
 | 
				
			||||||
    @method compare
 | 
					    @method compare
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    compare: function(lvalue, rvalue, options) {
 | 
					    compare: function(lvalue, rvalue, options) {
 | 
				
			||||||
      var operator, operators, result;
 | 
					      var operator, operators, result;
 | 
				
			||||||
      if (arguments.length < 3) {
 | 
					      if (arguments.length < 3) {
 | 
				
			||||||
@@ -539,9 +527,6 @@
 | 
				
			|||||||
        return options.inverse(this);
 | 
					        return options.inverse(this);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    Emit padded text.
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    pad: function(stringOrArray, padAmount, unused) {
 | 
					    pad: function(stringOrArray, padAmount, unused) {
 | 
				
			||||||
      var PAD, ret;
 | 
					      var PAD, ret;
 | 
				
			||||||
      stringOrArray = stringOrArray || '';
 | 
					      stringOrArray = stringOrArray || '';
 | 
				
			||||||
@@ -556,43 +541,26 @@
 | 
				
			|||||||
        ret = PAD(stringOrArray, stringOrArray.length + Math.abs(padAmount), null, padAmount < 0 ? PAD.LEFT : PAD.RIGHT);
 | 
					        ret = PAD(stringOrArray, stringOrArray.length + Math.abs(padAmount), null, padAmount < 0 ? PAD.LEFT : PAD.RIGHT);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return ret;
 | 
					      return ret;
 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    Given the name of a skill ("JavaScript" or "HVAC repair"), return the number
 | 
					 | 
				
			||||||
    of years assigned to that skill in the resume.skills.list collection.
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    skillYears: function(skill, rez) {
 | 
					 | 
				
			||||||
      var sk;
 | 
					 | 
				
			||||||
      sk = _.find(rez.skills.list, function(sk) {
 | 
					 | 
				
			||||||
        return sk.name.toUpperCase() === skill.toUpperCase();
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      if (sk) {
 | 
					 | 
				
			||||||
        return sk.years;
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        return '?';
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    Given an object that may be a string or an object, return it as-is if it's a
 | 
					 | 
				
			||||||
    string, otherwise return the value at obj[objPath].
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    stringOrObject: function(obj, objPath, rez) {
 | 
					 | 
				
			||||||
      if (_.isString(obj)) {
 | 
					 | 
				
			||||||
        return obj;
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        return LO.get(obj, objPath);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Report an error to the outside world without throwing an exception. Currently
 | 
				
			||||||
 | 
					  relies on kludging the running verb into. opts.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _reportError = function(code, params) {
 | 
					  _reportError = function(code, params) {
 | 
				
			||||||
    return GenericHelpers.opts.errHandler.err(code, params);
 | 
					    return GenericHelpers.opts.errHandler.err(code, params);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Format a from/to date range for display.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _fromTo = function(dateA, dateB, fmt, sep, fallback) {
 | 
					  _fromTo = function(dateA, dateB, fmt, sep, fallback) {
 | 
				
			||||||
    var dateATrim, dateBTrim, dateFrom, dateTemp, dateTo, reserved;
 | 
					    var dateATrim, dateBTrim, dateFrom, dateTemp, dateTo, reserved;
 | 
				
			||||||
    // Prevent accidental use of safe.start, safe.end, safe.date
 | 
					 | 
				
			||||||
    // The dateRange helper is for raw dates only
 | 
					 | 
				
			||||||
    if (moment.isMoment(dateA) || moment.isMoment(dateB)) {
 | 
					    if (moment.isMoment(dateA) || moment.isMoment(dateB)) {
 | 
				
			||||||
      _reportError(HMSTATUS.invalidHelperUse, {
 | 
					      _reportError(HMSTATUS.invalidHelperUse, {
 | 
				
			||||||
        helper: 'dateRange'
 | 
					        helper: 'dateRange'
 | 
				
			||||||
@@ -602,7 +570,6 @@
 | 
				
			|||||||
    dateFrom = null;
 | 
					    dateFrom = null;
 | 
				
			||||||
    dateTo = null;
 | 
					    dateTo = null;
 | 
				
			||||||
    dateTemp = null;
 | 
					    dateTemp = null;
 | 
				
			||||||
    // Check for 'current', 'present', 'now', '', null, and undefined
 | 
					 | 
				
			||||||
    dateA = dateA || '';
 | 
					    dateA = dateA || '';
 | 
				
			||||||
    dateB = dateB || '';
 | 
					    dateB = dateB || '';
 | 
				
			||||||
    dateATrim = dateA.trim().toLowerCase();
 | 
					    dateATrim = dateA.trim().toLowerCase();
 | 
				
			||||||
@@ -622,9 +589,7 @@
 | 
				
			|||||||
      dateTemp = FluentDate.fmt(dateB);
 | 
					      dateTemp = FluentDate.fmt(dateB);
 | 
				
			||||||
      dateTo = dateTemp.format(fmt);
 | 
					      dateTo = dateTemp.format(fmt);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (dateFrom === dateTo) {
 | 
					    if (dateFrom && dateTo) {
 | 
				
			||||||
      return dateFrom;
 | 
					 | 
				
			||||||
    } else if (dateFrom && dateTo) {
 | 
					 | 
				
			||||||
      return dateFrom + sep + dateTo;
 | 
					      return dateFrom + sep + dateTo;
 | 
				
			||||||
    } else if (dateFrom || dateTo) {
 | 
					    } else if (dateFrom || dateTo) {
 | 
				
			||||||
      return dateFrom || dateTo;
 | 
					      return dateFrom || dateTo;
 | 
				
			||||||
@@ -632,7 +597,7 @@
 | 
				
			|||||||
    return '';
 | 
					    return '';
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _skillLevelToIndex = function(lvl) {
 | 
					  skillLevelToIndex = function(lvl) {
 | 
				
			||||||
    var idx, intVal;
 | 
					    var idx, intVal;
 | 
				
			||||||
    idx = 0;
 | 
					    idx = 0;
 | 
				
			||||||
    if (String.is(lvl)) {
 | 
					    if (String.is(lvl)) {
 | 
				
			||||||
@@ -663,25 +628,6 @@
 | 
				
			|||||||
    return idx;
 | 
					    return idx;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Note [1] --------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Make sure it's precisely a string or array since some template engines jam
 | 
					 | 
				
			||||||
// their options/context object into the last parameter and we are allowing the
 | 
					 | 
				
			||||||
// defFont parameter to be omitted in certain cases. This is a little kludgy,
 | 
					 | 
				
			||||||
// but works fine for this case. If we start doing this regularly, we should
 | 
					 | 
				
			||||||
// rebind these parameters.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Note [2]: -------------------------------------------------------------------
 | 
					 | 
				
			||||||
// If execution reaches here, some sort of cosmic ray or sunspot has landed on
 | 
					 | 
				
			||||||
// HackMyResume, or a theme author is deliberately messing with us by doing
 | 
					 | 
				
			||||||
// something like:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// "fonts": {
 | 
					 | 
				
			||||||
//   "default": "",
 | 
					 | 
				
			||||||
//   "heading1": null
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Rather than sort it out, we'll just fall back to defFont.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//# sourceMappingURL=generic-helpers.js.map
 | 
					//# sourceMappingURL=generic-helpers.js.map
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										81
									
								
								dist/helpers/handlebars-helpers.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										81
									
								
								dist/helpers/handlebars-helpers.js
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Template helper definitions for Handlebars.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module handlebars-helpers.js
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var HANDLEBARS, _, blockHelpers, helpers;
 | 
				
			||||||
  Template helper definitions for Handlebars.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module handlebars-helpers.js
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var HANDLEBARS, HMS, _, blockHelpers, helpers, path;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HANDLEBARS = require('handlebars');
 | 
					  HANDLEBARS = require('handlebars');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,86 +14,35 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  helpers = require('./generic-helpers');
 | 
					  helpers = require('./generic-helpers');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  path = require('path');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  blockHelpers = require('./block-helpers');
 | 
					  blockHelpers = require('./block-helpers');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HMS = require('../core/status-codes');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  Register useful Handlebars helpers.
 | 
					  Register useful Handlebars helpers.
 | 
				
			||||||
  @method registerHelpers
 | 
					  @method registerHelpers
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = function(theme, rez, opts) {
 | 
					
 | 
				
			||||||
    var curGlob, ex, glob, slash, wrappedHelpers;
 | 
					  module.exports = function(theme, opts) {
 | 
				
			||||||
 | 
					    var wrappedHelpers;
 | 
				
			||||||
    helpers.theme = theme;
 | 
					    helpers.theme = theme;
 | 
				
			||||||
    helpers.opts = opts;
 | 
					    helpers.opts = opts;
 | 
				
			||||||
    helpers.type = 'handlebars';
 | 
					    helpers.type = 'handlebars';
 | 
				
			||||||
    // Prepare generic helpers for use with Handlebars. We do this by wrapping them
 | 
					 | 
				
			||||||
    // in a Handlebars-aware wrapper which calls the helper internally.
 | 
					 | 
				
			||||||
    wrappedHelpers = _.mapObject(helpers, function(hVal, hKey) {
 | 
					    wrappedHelpers = _.mapObject(helpers, function(hVal, hKey) {
 | 
				
			||||||
      if (_.isFunction(hVal)) {
 | 
					      if (_.isFunction(hVal)) {
 | 
				
			||||||
        return _.wrap(hVal, function(func) {
 | 
					        _.wrap(hVal, function(func) {
 | 
				
			||||||
          var args;
 | 
					          var args;
 | 
				
			||||||
          args = Array.prototype.slice.call(arguments);
 | 
					          args = Array.prototype.slice.call(arguments);
 | 
				
			||||||
          args.shift(); // lose the 1st element (func) [^1]
 | 
					          args.shift();
 | 
				
			||||||
          //args.pop()                   # lose the last element (HB options hash)
 | 
					          args.pop();
 | 
				
			||||||
          args[args.length - 1] = rez; // replace w/ resume object
 | 
					          return func.apply(this, args);
 | 
				
			||||||
          return func.apply(this, args); // call the generic helper
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return hVal;
 | 
					      return hVal;
 | 
				
			||||||
    }, this);
 | 
					    }, this);
 | 
				
			||||||
    HANDLEBARS.registerHelper(wrappedHelpers);
 | 
					    HANDLEBARS.registerHelper(wrappedHelpers);
 | 
				
			||||||
    // Prepare Handlebars-specific helpers - "blockHelpers" is really a misnomer
 | 
					 | 
				
			||||||
    // since any kind of Handlebars-specific helper can live here
 | 
					 | 
				
			||||||
    HANDLEBARS.registerHelper(blockHelpers);
 | 
					    HANDLEBARS.registerHelper(blockHelpers);
 | 
				
			||||||
    if (_.isString(theme.helpers)) {
 | 
					 | 
				
			||||||
      // Register any theme-provided custom helpers...
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Normalize "theme.helpers" (string or array) to an array
 | 
					 | 
				
			||||||
      theme.helpers = [theme.helpers];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (_.isArray(theme.helpers)) {
 | 
					 | 
				
			||||||
      glob = require('glob');
 | 
					 | 
				
			||||||
      slash = require('slash');
 | 
					 | 
				
			||||||
      curGlob = null;
 | 
					 | 
				
			||||||
      try {
 | 
					 | 
				
			||||||
        _.each(theme.helpers, function(fGlob) { // foreach theme.helpers entry
 | 
					 | 
				
			||||||
          var files;
 | 
					 | 
				
			||||||
          curGlob = fGlob; // ..cache in case of exception
 | 
					 | 
				
			||||||
          fGlob = path.join(theme.folder, fGlob); // ..make relative to theme
 | 
					 | 
				
			||||||
          files = glob.sync(slash(fGlob)); // ..expand the glob
 | 
					 | 
				
			||||||
          if (files.length > 0) { // ..guard against empty glob
 | 
					 | 
				
			||||||
            _.each(files, function(f) { // ..loop over concrete paths
 | 
					 | 
				
			||||||
              HANDLEBARS.registerHelper(require(f)); // ..register the path
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            throw {
 | 
					 | 
				
			||||||
              fluenterror: HMS.themeHelperLoad,
 | 
					 | 
				
			||||||
              inner: er,
 | 
					 | 
				
			||||||
              glob: fGlob
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      } catch (error) {
 | 
					 | 
				
			||||||
        ex = error;
 | 
					 | 
				
			||||||
        throw {
 | 
					 | 
				
			||||||
          fluenterror: HMS.themeHelperLoad,
 | 
					 | 
				
			||||||
          inner: ex,
 | 
					 | 
				
			||||||
          glob: curGlob,
 | 
					 | 
				
			||||||
          exit: true
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // [^1]: This little bit of acrobatics ensures that our generic helpers are
 | 
					 | 
				
			||||||
// called as generic helpers, not as Handlebars-specific helpers. This allows
 | 
					 | 
				
			||||||
// them to be used in other templating engines, like Underscore. If you need a
 | 
					 | 
				
			||||||
// Handlebars-specific helper with normal Handlebars context and options, put it
 | 
					 | 
				
			||||||
// in block-helpers.coffee.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//# sourceMappingURL=handlebars-helpers.js.map
 | 
					//# sourceMappingURL=handlebars-helpers.js.map
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								dist/helpers/underscore-helpers.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								dist/helpers/underscore-helpers.js
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Template helper definitions for Underscore.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module handlebars-helpers.js
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Template helper definitions for Underscore.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module handlebars-helpers.js
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var HANDLEBARS, _, helpers;
 | 
					  var HANDLEBARS, _, helpers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HANDLEBARS = require('handlebars');
 | 
					  HANDLEBARS = require('handlebars');
 | 
				
			||||||
@@ -12,10 +14,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  helpers = require('./generic-helpers');
 | 
					  helpers = require('./generic-helpers');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  Register useful Underscore helpers.
 | 
					  Register useful Underscore helpers.
 | 
				
			||||||
  @method registerHelpers
 | 
					  @method registerHelpers
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = function(theme, opts, cssInfo, ctx, eng) {
 | 
					  module.exports = function(theme, opts, cssInfo, ctx, eng) {
 | 
				
			||||||
    helpers.theme = theme;
 | 
					    helpers.theme = theme;
 | 
				
			||||||
    helpers.opts = opts;
 | 
					    helpers.opts = opts;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							@@ -1,17 +1,21 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					External API surface for HackMyResume.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module hackmycore/index
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** API facade for HackMyResume. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  External API surface for HackMyResume.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module hackmycore/index
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** API facade for HackMyResume. */
 | 
					 | 
				
			||||||
  module.exports = {
 | 
					  module.exports = {
 | 
				
			||||||
    verbs: {
 | 
					    verbs: {
 | 
				
			||||||
      build: require('./verbs/build'),
 | 
					      build: require('./verbs/build'),
 | 
				
			||||||
      analyze: require('./verbs/analyze'),
 | 
					      analyze: require('./verbs/analyze'),
 | 
				
			||||||
      validate: require('./verbs/validate'),
 | 
					      validate: require('./verbs/validate'),
 | 
				
			||||||
      convert: require('./verbs/convert'),
 | 
					      convert: require('./verbs/convert'),
 | 
				
			||||||
      new: require('./verbs/create'),
 | 
					      "new": require('./verbs/create'),
 | 
				
			||||||
      peek: require('./verbs/peek')
 | 
					      peek: require('./verbs/peek')
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    alias: {
 | 
					    alias: {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										42
									
								
								dist/inspectors/gap-inspector.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								dist/inspectors/gap-inspector.js
									
									
									
									
										vendored
									
									
								
							@@ -1,12 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Employment gap analysis for HackMyResume.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module inspectors/gap-inspector
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Employment gap analysis for HackMyResume.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module inspectors/gap-inspector
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Identify gaps in the candidate's employment history.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FluentDate, LO, _, gapInspector, moment;
 | 
					  var FluentDate, LO, _, gapInspector, moment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
@@ -17,8 +16,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  LO = require('lodash');
 | 
					  LO = require('lodash');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Identify gaps in the candidate's employment history.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  gapInspector = module.exports = {
 | 
					  gapInspector = module.exports = {
 | 
				
			||||||
    moniker: 'gap-inspector',
 | 
					    moniker: 'gap-inspector',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Run the Gap Analyzer on a resume.
 | 
					    Run the Gap Analyzer on a resume.
 | 
				
			||||||
    @method run
 | 
					    @method run
 | 
				
			||||||
@@ -30,10 +35,9 @@
 | 
				
			|||||||
          end: // A Moment.js date
 | 
					          end: // A Moment.js date
 | 
				
			||||||
          duration: // Gap length
 | 
					          duration: // Gap length
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    run: function(rez) {
 | 
					    run: function(rez) {
 | 
				
			||||||
      var coverage, dur, g, gap_start, hist, new_e, num_gaps, o, ref_count, tdur, total_gap_days;
 | 
					      var coverage, dur, g, gap_start, hist, new_e, num_gaps, o, ref_count, tdur, total_gap_days;
 | 
				
			||||||
      // This is what we'll return
 | 
					 | 
				
			||||||
      coverage = {
 | 
					      coverage = {
 | 
				
			||||||
        gaps: [],
 | 
					        gaps: [],
 | 
				
			||||||
        overlaps: [],
 | 
					        overlaps: [],
 | 
				
			||||||
@@ -44,14 +48,10 @@
 | 
				
			|||||||
          gaps: 0
 | 
					          gaps: 0
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      // Missing employment section? Bye bye.
 | 
					 | 
				
			||||||
      hist = LO.get(rez, 'employment.history');
 | 
					      hist = LO.get(rez, 'employment.history');
 | 
				
			||||||
      if (!hist || !hist.length) {
 | 
					      if (!hist || !hist.length) {
 | 
				
			||||||
        return coverage;
 | 
					        return coverage;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // Convert the candidate's employment history to an array of dates,
 | 
					 | 
				
			||||||
      // where each element in the array is a start date or an end date of a
 | 
					 | 
				
			||||||
      // job -- it doesn't matter which.
 | 
					 | 
				
			||||||
      new_e = hist.map(function(job) {
 | 
					      new_e = hist.map(function(job) {
 | 
				
			||||||
        var obj;
 | 
					        var obj;
 | 
				
			||||||
        obj = _.pick(job, ['start', 'end']);
 | 
					        obj = _.pick(job, ['start', 'end']);
 | 
				
			||||||
@@ -64,7 +64,6 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return obj;
 | 
					        return obj;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      // Flatten the array, remove empties, and sort
 | 
					 | 
				
			||||||
      new_e = _.filter(_.flatten(new_e, true), function(v) {
 | 
					      new_e = _.filter(_.flatten(new_e, true), function(v) {
 | 
				
			||||||
        return v && v.length && v[0] && v[0].length;
 | 
					        return v && v.length && v[0] && v[0].length;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -74,11 +73,6 @@
 | 
				
			|||||||
      new_e = _.sortBy(new_e, function(elem) {
 | 
					      new_e = _.sortBy(new_e, function(elem) {
 | 
				
			||||||
        return elem[1].unix();
 | 
					        return elem[1].unix();
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      // Iterate over elements in the array. Each time a start date is found,
 | 
					 | 
				
			||||||
      // increment a reference count. Each time an end date is found, decrement
 | 
					 | 
				
			||||||
      // the reference count. When the reference count reaches 0, we have a gap.
 | 
					 | 
				
			||||||
      // When the reference count is > 0, the candidate is employed. When the
 | 
					 | 
				
			||||||
      // reference count reaches 2, the candidate is overlapped.
 | 
					 | 
				
			||||||
      num_gaps = 0;
 | 
					      num_gaps = 0;
 | 
				
			||||||
      ref_count = 0;
 | 
					      ref_count = 0;
 | 
				
			||||||
      total_gap_days = 0;
 | 
					      total_gap_days = 0;
 | 
				
			||||||
@@ -87,13 +81,11 @@
 | 
				
			|||||||
        var inc, lastGap, lastOver;
 | 
					        var inc, lastGap, lastOver;
 | 
				
			||||||
        inc = point[0] === 'start' ? 1 : -1;
 | 
					        inc = point[0] === 'start' ? 1 : -1;
 | 
				
			||||||
        ref_count += inc;
 | 
					        ref_count += inc;
 | 
				
			||||||
        // If the ref count just reached 0, start a new GAP
 | 
					 | 
				
			||||||
        if (ref_count === 0) {
 | 
					        if (ref_count === 0) {
 | 
				
			||||||
          return coverage.gaps.push({
 | 
					          return coverage.gaps.push({
 | 
				
			||||||
            start: point[1],
 | 
					            start: point[1],
 | 
				
			||||||
            end: null
 | 
					            end: null
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        // If the ref count reached 1 by rising, end the last GAP
 | 
					 | 
				
			||||||
        } else if (ref_count === 1 && inc === 1) {
 | 
					        } else if (ref_count === 1 && inc === 1) {
 | 
				
			||||||
          lastGap = _.last(coverage.gaps);
 | 
					          lastGap = _.last(coverage.gaps);
 | 
				
			||||||
          if (lastGap) {
 | 
					          if (lastGap) {
 | 
				
			||||||
@@ -101,13 +93,11 @@
 | 
				
			|||||||
            lastGap.duration = lastGap.end.diff(lastGap.start, 'days');
 | 
					            lastGap.duration = lastGap.end.diff(lastGap.start, 'days');
 | 
				
			||||||
            return total_gap_days += lastGap.duration;
 | 
					            return total_gap_days += lastGap.duration;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        // If the ref count reaches 2 by rising, start a new OVERLAP
 | 
					 | 
				
			||||||
        } else if (ref_count === 2 && inc === 1) {
 | 
					        } else if (ref_count === 2 && inc === 1) {
 | 
				
			||||||
          return coverage.overlaps.push({
 | 
					          return coverage.overlaps.push({
 | 
				
			||||||
            start: point[1],
 | 
					            start: point[1],
 | 
				
			||||||
            end: null
 | 
					            end: null
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        // If the ref count reaches 1 by falling, end the last OVERLAP
 | 
					 | 
				
			||||||
        } else if (ref_count === 1 && inc === -1) {
 | 
					        } else if (ref_count === 1 && inc === -1) {
 | 
				
			||||||
          lastOver = _.last(coverage.overlaps);
 | 
					          lastOver = _.last(coverage.overlaps);
 | 
				
			||||||
          if (lastOver) {
 | 
					          if (lastOver) {
 | 
				
			||||||
@@ -119,9 +109,6 @@
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      // It's possible that the last gap/overlap didn't have an explicit .end
 | 
					 | 
				
			||||||
      // date.If so, set the end date to the present date and compute the
 | 
					 | 
				
			||||||
      // duration normally.
 | 
					 | 
				
			||||||
      if (coverage.overlaps.length) {
 | 
					      if (coverage.overlaps.length) {
 | 
				
			||||||
        o = _.last(coverage.overlaps);
 | 
					        o = _.last(coverage.overlaps);
 | 
				
			||||||
        if (o && !o.end) {
 | 
					        if (o && !o.end) {
 | 
				
			||||||
@@ -136,7 +123,6 @@
 | 
				
			|||||||
          g.duration = g.end.diff(g.start, 'days');
 | 
					          g.duration = g.end.diff(g.start, 'days');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // Package data for return to the client
 | 
					 | 
				
			||||||
      tdur = rez.duration('days');
 | 
					      tdur = rez.duration('days');
 | 
				
			||||||
      dur = {
 | 
					      dur = {
 | 
				
			||||||
        total: tdur,
 | 
					        total: tdur,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										51
									
								
								dist/inspectors/keyword-inspector.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										51
									
								
								dist/inspectors/keyword-inspector.js
									
									
									
									
										vendored
									
									
								
							@@ -1,63 +1,48 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Keyword analysis for HackMyResume.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module inspectors/keyword-inspector
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Keyword analysis for HackMyResume.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module inspectors/keyword-inspector
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Analyze the resume's use of keywords.
 | 
					 | 
				
			||||||
  TODO: BUG: Keyword search regex is inaccurate, especially for one or two
 | 
					 | 
				
			||||||
  letter keywords like "C" or "CLI".
 | 
					 | 
				
			||||||
  @class keywordInspector
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FluentDate, _, keywordInspector;
 | 
					  var FluentDate, _, keywordInspector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FluentDate = require('../core/fluent-date');
 | 
					  FluentDate = require('../core/fluent-date');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Analyze the resume's use of keywords.
 | 
				
			||||||
 | 
					  TODO: BUG: Keyword search regex is inaccurate, especially for one or two
 | 
				
			||||||
 | 
					  letter keywords like "C" or "CLI".
 | 
				
			||||||
 | 
					  @class keywordInspector
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  keywordInspector = module.exports = {
 | 
					  keywordInspector = module.exports = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** A unique name for this inspector. */
 | 
					    /** A unique name for this inspector. */
 | 
				
			||||||
    moniker: 'keyword-inspector',
 | 
					    moniker: 'keyword-inspector',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Run the Keyword Inspector on a resume.
 | 
					    Run the Keyword Inspector on a resume.
 | 
				
			||||||
    @method run
 | 
					    @method run
 | 
				
			||||||
    @return An collection of statistical keyword data.
 | 
					    @return An collection of statistical keyword data.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    run: function(rez) {
 | 
					    run: function(rez) {
 | 
				
			||||||
      var prefix, regex_quote, searchable, suffix;
 | 
					      var prefix, regex_quote, searchable, suffix;
 | 
				
			||||||
      // "Quote" or safely escape a keyword so it can be used as a regex. For
 | 
					 | 
				
			||||||
      // example, if the keyword is "C++", yield "C\+\+".
 | 
					 | 
				
			||||||
      // http://stackoverflow.com/a/2593661/4942583
 | 
					 | 
				
			||||||
      regex_quote = function(str) {
 | 
					      regex_quote = function(str) {
 | 
				
			||||||
        return (str + '').replace(/[.?*+^$[\]\\(){}|-]/ig, "\\$&");
 | 
					        return (str + '').replace(/[.?*+^$[\]\\(){}|-]/ig, "\\$&");
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      // Create a searchable plain-text digest of the resume
 | 
					 | 
				
			||||||
      // TODO: BUG: Don't search within keywords for other keywords. Job A
 | 
					 | 
				
			||||||
      // declares the "foo" keyword. Job B declares the "foo & bar" keyword. Job
 | 
					 | 
				
			||||||
      // B's mention of "foobar" should not count as a mention of "foo".
 | 
					 | 
				
			||||||
      // To achieve this, remove keywords from the search digest and treat them
 | 
					 | 
				
			||||||
      // separately.
 | 
					 | 
				
			||||||
      searchable = '';
 | 
					      searchable = '';
 | 
				
			||||||
      rez.transformStrings(['imp', 'computed', 'safe'], function(key, val) {
 | 
					      rez.transformStrings(['imp', 'computed', 'safe'], function(key, val) {
 | 
				
			||||||
        return searchable += ' ' + val;
 | 
					        return searchable += ' ' + val;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      // Assemble a regex skeleton we can use to test for keywords with a bit
 | 
					 | 
				
			||||||
      // more
 | 
					 | 
				
			||||||
      prefix = '(?:' + ['^', '\\s+', '[\\.,]+'].join('|') + ')';
 | 
					      prefix = '(?:' + ['^', '\\s+', '[\\.,]+'].join('|') + ')';
 | 
				
			||||||
      suffix = '(?:' + ['$', '\\s+', '[\\.,]+'].join('|') + ')';
 | 
					      suffix = '(?:' + ['$', '\\s+', '[\\.,]+'].join('|') + ')';
 | 
				
			||||||
      return rez.keywords().map(function(kw) {
 | 
					      return rez.keywords().map(function(kw) {
 | 
				
			||||||
        var count, myArray, regex, regex_str;
 | 
					        var count, myArray, regex, regex_str;
 | 
				
			||||||
        // 1. Using word boundary or other regex class is inaccurate
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //    var regex = new RegExp( '\\b' + regex_quote( kw )/* + '\\b'*/, 'ig');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // 2. Searching for the raw keyword is inaccurate ("C" will match any
 | 
					 | 
				
			||||||
        // word containing a 'c'!).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //    var regex = new RegExp( regex_quote( kw ), 'ig');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // 3. Instead, use a custom regex with special delimeters.
 | 
					 | 
				
			||||||
        regex_str = prefix + regex_quote(kw) + suffix;
 | 
					        regex_str = prefix + regex_quote(kw) + suffix;
 | 
				
			||||||
        regex = new RegExp(regex_str, 'ig');
 | 
					        regex = new RegExp(regex_str, 'ig');
 | 
				
			||||||
        myArray = null;
 | 
					        myArray = null;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								dist/inspectors/totals-inspector.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								dist/inspectors/totals-inspector.js
									
									
									
									
										vendored
									
									
								
							@@ -1,27 +1,32 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Section analysis for HackMyResume.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module inspectors/totals-inspector
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Section analysis for HackMyResume.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module inspectors/totals-inspector
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Retrieve sectional overview and summary information.
 | 
					 | 
				
			||||||
  @class totalsInspector
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FluentDate, _, totalsInspector;
 | 
					  var FluentDate, _, totalsInspector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FluentDate = require('../core/fluent-date');
 | 
					  FluentDate = require('../core/fluent-date');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Retrieve sectional overview and summary information.
 | 
				
			||||||
 | 
					  @class totalsInspector
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  totalsInspector = module.exports = {
 | 
					  totalsInspector = module.exports = {
 | 
				
			||||||
    moniker: 'totals-inspector',
 | 
					    moniker: 'totals-inspector',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    Run the Totals Inspector on a resume.
 | 
					    Run the Totals Inspector on a resume.
 | 
				
			||||||
    @method run
 | 
					    @method run
 | 
				
			||||||
    @return An object containing summary information for each section on the
 | 
					    @return An object containing summary information for each section on the
 | 
				
			||||||
    resume.
 | 
					    resume.
 | 
				
			||||||
    */
 | 
					     */
 | 
				
			||||||
    run: function(rez) {
 | 
					    run: function(rez) {
 | 
				
			||||||
      var sectionTotals;
 | 
					      var sectionTotals;
 | 
				
			||||||
      sectionTotals = {};
 | 
					      sectionTotals = {};
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										45
									
								
								dist/renderers/handlebars-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								dist/renderers/handlebars-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,13 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the HandlebarsGenerator class.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module renderers/handlebars-generator
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the HandlebarsGenerator class.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module renderers/handlebars-generator
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Perform template-based resume generation using Handlebars.js.
 | 
					 | 
				
			||||||
  @class HandlebarsGenerator
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FS, HANDLEBARS, HMSTATUS, HandlebarsGenerator, PATH, READFILES, SLASH, _, parsePath, registerHelpers, registerPartials;
 | 
					  var FS, HANDLEBARS, HMSTATUS, HandlebarsGenerator, PATH, READFILES, SLASH, _, parsePath, registerHelpers, registerPartials;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
@@ -28,28 +26,32 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  SLASH = require('slash');
 | 
					  SLASH = require('slash');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Perform template-based resume generation using Handlebars.js.
 | 
				
			||||||
 | 
					  @class HandlebarsGenerator
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HandlebarsGenerator = module.exports = {
 | 
					  HandlebarsGenerator = module.exports = {
 | 
				
			||||||
    generateSimple: function(data, tpl) {
 | 
					    generateSimple: function(data, tpl) {
 | 
				
			||||||
      var err, template;
 | 
					      var template;
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        // Compile and run the Handlebars template.
 | 
					 | 
				
			||||||
        template = HANDLEBARS.compile(tpl, {
 | 
					        template = HANDLEBARS.compile(tpl, {
 | 
				
			||||||
          strict: false,
 | 
					          strict: false,
 | 
				
			||||||
          assumeObjects: false,
 | 
					          assumeObjects: false
 | 
				
			||||||
          noEscape: data.opts.noescape
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        return template(data);
 | 
					        return template(data);
 | 
				
			||||||
      } catch (error1) {
 | 
					      } catch (_error) {
 | 
				
			||||||
        err = error1;
 | 
					 | 
				
			||||||
        throw {
 | 
					        throw {
 | 
				
			||||||
          fluenterror: HMSTATUS[template ? 'invokeTemplate' : 'compileTemplate'],
 | 
					          fluenterror: HMSTATUS[template ? 'invokeTemplate' : 'compileTemplate'],
 | 
				
			||||||
          inner: err
 | 
					          inner: _error
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    generate: function(json, jst, format, curFmt, opts, theme) {
 | 
					    generate: function(json, jst, format, curFmt, opts, theme) {
 | 
				
			||||||
      var ctx, encData;
 | 
					      var ctx, encData;
 | 
				
			||||||
      // Preprocess text
 | 
					      registerPartials(format, theme);
 | 
				
			||||||
 | 
					      registerHelpers(theme, opts);
 | 
				
			||||||
      encData = json;
 | 
					      encData = json;
 | 
				
			||||||
      if (format === 'html' || format === 'pdf') {
 | 
					      if (format === 'html' || format === 'pdf') {
 | 
				
			||||||
        encData = json.markdownify();
 | 
					        encData = json.markdownify();
 | 
				
			||||||
@@ -57,10 +59,6 @@
 | 
				
			|||||||
      if (format === 'doc') {
 | 
					      if (format === 'doc') {
 | 
				
			||||||
        encData = json.xmlify();
 | 
					        encData = json.xmlify();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // Set up partials and helpers
 | 
					 | 
				
			||||||
      registerPartials(format, theme);
 | 
					 | 
				
			||||||
      registerHelpers(theme, encData, opts);
 | 
					 | 
				
			||||||
      // Set up the context
 | 
					 | 
				
			||||||
      ctx = {
 | 
					      ctx = {
 | 
				
			||||||
        r: encData,
 | 
					        r: encData,
 | 
				
			||||||
        RAW: json,
 | 
					        RAW: json,
 | 
				
			||||||
@@ -71,7 +69,6 @@
 | 
				
			|||||||
        results: curFmt.files,
 | 
					        results: curFmt.files,
 | 
				
			||||||
        headFragment: opts.headFragment || ''
 | 
					        headFragment: opts.headFragment || ''
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      // Render the template
 | 
					 | 
				
			||||||
      return this.generateSimple(ctx, jst);
 | 
					      return this.generateSimple(ctx, jst);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
@@ -79,10 +76,7 @@
 | 
				
			|||||||
  registerPartials = function(format, theme) {
 | 
					  registerPartials = function(format, theme) {
 | 
				
			||||||
    var partialsFolder;
 | 
					    var partialsFolder;
 | 
				
			||||||
    if (_.contains(['html', 'doc', 'md', 'txt', 'pdf'], format)) {
 | 
					    if (_.contains(['html', 'doc', 'md', 'txt', 'pdf'], format)) {
 | 
				
			||||||
      // Locate the global partials folder
 | 
					 | 
				
			||||||
      partialsFolder = PATH.join(parsePath(require.resolve('fresh-themes')).dirname, '/partials/', format === 'pdf' ? 'html' : format);
 | 
					      partialsFolder = PATH.join(parsePath(require.resolve('fresh-themes')).dirname, '/partials/', format === 'pdf' ? 'html' : format);
 | 
				
			||||||
      // Register global partials in the /partials/[format] folder
 | 
					 | 
				
			||||||
      // TODO: Only do this once per HMR invocation.
 | 
					 | 
				
			||||||
      _.each(READFILES(partialsFolder, function(error) {
 | 
					      _.each(READFILES(partialsFolder, function(error) {
 | 
				
			||||||
        return {};
 | 
					        return {};
 | 
				
			||||||
      }), function(el) {
 | 
					      }), function(el) {
 | 
				
			||||||
@@ -95,7 +89,6 @@
 | 
				
			|||||||
        return theme.partialsInitialized = true;
 | 
					        return theme.partialsInitialized = true;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Register theme-specific partials
 | 
					 | 
				
			||||||
    return _.each(theme.partials, function(el) {
 | 
					    return _.each(theme.partials, function(el) {
 | 
				
			||||||
      var compiledTemplate, tplData;
 | 
					      var compiledTemplate, tplData;
 | 
				
			||||||
      tplData = FS.readFileSync(el.path, 'utf8');
 | 
					      tplData = FS.readFileSync(el.path, 'utf8');
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								dist/renderers/jrs-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								dist/renderers/jrs-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,13 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the JRSGenerator class.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module renderers/jrs-generator
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the JRSGenerator class.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module renderers/jrs-generator
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Perform template-based resume generation for JSON Resume themes.
 | 
					 | 
				
			||||||
  @class JRSGenerator
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FS, HANDLEBARS, JRSGenerator, MD, MDIN, PATH, READFILES, SLASH, _, parsePath, registerHelpers;
 | 
					  var FS, HANDLEBARS, JRSGenerator, MD, MDIN, PATH, READFILES, SLASH, _, parsePath, registerHelpers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
@@ -28,10 +26,15 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  MD = require('marked');
 | 
					  MD = require('marked');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Perform template-based resume generation for JSON Resume themes.
 | 
				
			||||||
 | 
					  @class JRSGenerator
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  JRSGenerator = module.exports = {
 | 
					  JRSGenerator = module.exports = {
 | 
				
			||||||
    generate: function(json, jst, format, cssInfo, opts, theme) {
 | 
					    generate: function(json, jst, format, cssInfo, opts, theme) {
 | 
				
			||||||
      var org, rezHtml, turnoff;
 | 
					      var org, rezHtml, turnoff;
 | 
				
			||||||
      // Disable JRS theme chatter (console.log, console.error, etc.)
 | 
					 | 
				
			||||||
      turnoff = ['log', 'error', 'dir'];
 | 
					      turnoff = ['log', 'error', 'dir'];
 | 
				
			||||||
      org = turnoff.map(function(c) {
 | 
					      org = turnoff.map(function(c) {
 | 
				
			||||||
        var ret;
 | 
					        var ret;
 | 
				
			||||||
@@ -39,20 +42,17 @@
 | 
				
			|||||||
        console[c] = function() {};
 | 
					        console[c] = function() {};
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      // Freeze and render
 | 
					 | 
				
			||||||
      rezHtml = theme.render(json.harden());
 | 
					      rezHtml = theme.render(json.harden());
 | 
				
			||||||
      // Turn logging back on
 | 
					 | 
				
			||||||
      turnoff.forEach(function(c, idx) {
 | 
					      turnoff.forEach(function(c, idx) {
 | 
				
			||||||
        return console[c] = org[idx];
 | 
					        return console[c] = org[idx];
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      // Unfreeze and apply Markdown
 | 
					      return rezHtml = rezHtml.replace(/@@@@~.*?~@@@@/gm, function(val) {
 | 
				
			||||||
      return rezHtml = rezHtml.replace(/@@@@~[\s\S]*?~@@@@/g, function(val) {
 | 
					        return MDIN(val.replace(/~@@@@/gm, '').replace(/@@@@~/gm, ''));
 | 
				
			||||||
        return MDIN(val.replace(/~@@@@/g, '').replace(/@@@@~/g, ''));
 | 
					 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  MDIN = function(txt) { // TODO: Move this
 | 
					  MDIN = function(txt) {
 | 
				
			||||||
    return MD(txt || '').replace(/^\s*<p>|<\/p>\s*$/gi, '');
 | 
					    return MD(txt || '').replace(/^\s*<p>|<\/p>\s*$/gi, '');
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								dist/renderers/underscore-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								dist/renderers/underscore-generator.js
									
									
									
									
										vendored
									
									
								
							@@ -1,13 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the UnderscoreGenerator class.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module underscore-generator.js
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the UnderscoreGenerator class.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module underscore-generator.js
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Perform template-based resume generation using Underscore.js.
 | 
					 | 
				
			||||||
  @class UnderscoreGenerator
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var UnderscoreGenerator, _, escapeLaTeX, registerHelpers;
 | 
					  var UnderscoreGenerator, _, escapeLaTeX, registerHelpers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
@@ -18,26 +16,28 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  escapeLaTeX = require('escape-latex');
 | 
					  escapeLaTeX = require('escape-latex');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Perform template-based resume generation using Underscore.js.
 | 
				
			||||||
 | 
					  @class UnderscoreGenerator
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  UnderscoreGenerator = module.exports = {
 | 
					  UnderscoreGenerator = module.exports = {
 | 
				
			||||||
    generateSimple: function(data, tpl) {
 | 
					    generateSimple: function(data, tpl) {
 | 
				
			||||||
      var HMS, err, t;
 | 
					      var HMS, t;
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        // Compile and run the Handlebars template.
 | 
					 | 
				
			||||||
        t = _.template(tpl);
 | 
					        t = _.template(tpl);
 | 
				
			||||||
        return t(data);
 | 
					        return t(data);
 | 
				
			||||||
      } catch (error) {
 | 
					      } catch (_error) {
 | 
				
			||||||
        err = error;
 | 
					 | 
				
			||||||
        //console.dir _error
 | 
					 | 
				
			||||||
        HMS = require('../core/status-codes');
 | 
					        HMS = require('../core/status-codes');
 | 
				
			||||||
        throw {
 | 
					        throw {
 | 
				
			||||||
          fluenterror: HMS[t ? 'invokeTemplate' : 'compileTemplate'],
 | 
					          fluenterror: HMS[t ? 'invokeTemplate' : 'compileTemplate'],
 | 
				
			||||||
          inner: err
 | 
					          inner: _error
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    generate: function(json, jst, format, cssInfo, opts, theme) {
 | 
					    generate: function(json, jst, format, cssInfo, opts, theme) {
 | 
				
			||||||
      var ctx, delims, r, traverse;
 | 
					      var ctx, delims, r, traverse;
 | 
				
			||||||
      // Tweak underscore's default template delimeters
 | 
					 | 
				
			||||||
      delims = (opts.themeObj && opts.themeObj.delimeters) || opts.template;
 | 
					      delims = (opts.themeObj && opts.themeObj.delimeters) || opts.template;
 | 
				
			||||||
      if (opts.themeObj && opts.themeObj.delimeters) {
 | 
					      if (opts.themeObj && opts.themeObj.delimeters) {
 | 
				
			||||||
        delims = _.mapObject(delims, function(val, key) {
 | 
					        delims = _.mapObject(delims, function(val, key) {
 | 
				
			||||||
@@ -68,20 +68,16 @@
 | 
				
			|||||||
        default:
 | 
					        default:
 | 
				
			||||||
          r = json;
 | 
					          r = json;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // Set up the context
 | 
					 | 
				
			||||||
      ctx = {
 | 
					      ctx = {
 | 
				
			||||||
        r: r,
 | 
					        r: r,
 | 
				
			||||||
        filt: opts.filters,
 | 
					        filt: opts.filters,
 | 
				
			||||||
        XML: require('xml-escape'),
 | 
					        XML: require('xml-escape'),
 | 
				
			||||||
        RAW: json,
 | 
					        RAW: json,
 | 
				
			||||||
        cssInfo: cssInfo,
 | 
					        cssInfo: cssInfo,
 | 
				
			||||||
        //engine: @
 | 
					 | 
				
			||||||
        headFragment: opts.headFragment || '',
 | 
					        headFragment: opts.headFragment || '',
 | 
				
			||||||
        opts: opts
 | 
					        opts: opts
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      // Link to our helpers
 | 
					 | 
				
			||||||
      registerHelpers(theme, opts, cssInfo, ctx, this);
 | 
					      registerHelpers(theme, opts, cssInfo, ctx, this);
 | 
				
			||||||
      // Generate!
 | 
					 | 
				
			||||||
      return this.generateSimple(ctx, jst);
 | 
					      return this.generateSimple(ctx, jst);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								dist/utils/file-contains.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								dist/utils/file-contains.js
									
									
									
									
										vendored
									
									
								
							@@ -1,8 +1,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the SyntaxErrorEx class.
 | 
				
			||||||
 | 
					@module file-contains.js
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the SyntaxErrorEx class.
 | 
					 | 
				
			||||||
  @module file-contains.js
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  module.exports = function(file, needle) {
 | 
					  module.exports = function(file, needle) {
 | 
				
			||||||
    return require('fs').readFileSync(file, 'utf-8').indexOf(needle) > -1;
 | 
					    return require('fs').readFileSync(file, 'utf-8').indexOf(needle) > -1;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								dist/utils/fresh-version-regex.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								dist/utils/fresh-version-regex.js
									
									
									
									
										vendored
									
									
								
							@@ -1,27 +0,0 @@
 | 
				
			|||||||
(function() {
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Defines a regex suitable for matching FRESH versions.
 | 
					 | 
				
			||||||
  @module file-contains.js
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  // Set up a regex that matches all of the following:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  //   - FRESH
 | 
					 | 
				
			||||||
  //   - JRS
 | 
					 | 
				
			||||||
  //   - FRESCA
 | 
					 | 
				
			||||||
  //   - FRESH@1.0.0
 | 
					 | 
				
			||||||
  //   - FRESH@1.0
 | 
					 | 
				
			||||||
  //   - FRESH@1
 | 
					 | 
				
			||||||
  //   - JRS@0.16.0
 | 
					 | 
				
			||||||
  //   - JRS@0.16
 | 
					 | 
				
			||||||
  //   - JRS@0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Don't use a SEMVER regex (eg, NPM's semver-regex) because a) we want to
 | 
					 | 
				
			||||||
  // support partial semvers like "0" or "1.2" and b) we'll expand this later to
 | 
					 | 
				
			||||||
  // support fully scoped FRESH versions.
 | 
					 | 
				
			||||||
  module.exports = function() {
 | 
					 | 
				
			||||||
    return RegExp('^(FRESH|FRESCA|JRS)(?:@(\\d+(?:\\.\\d+)?(?:\\.\\d+)?))?$');
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}).call(this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//# sourceMappingURL=fresh-version-regex.js.map
 | 
					 | 
				
			||||||
							
								
								
									
										22
									
								
								dist/utils/html-to-wpml.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								dist/utils/html-to-wpml.js
									
									
									
									
										vendored
									
									
								
							@@ -1,12 +1,12 @@
 | 
				
			|||||||
(function() {
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the Markdown to WordProcessingML conversion routine.
 | 
					 | 
				
			||||||
  @license MIT. Copyright (c) 2015 James Devlin / FluentDesk.
 | 
					 | 
				
			||||||
  @module utils/html-to-wpml
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var HTML5Tokenizer, XML, _;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  XML = require('xml-escape');
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the Markdown to WordProcessingML conversion routine.
 | 
				
			||||||
 | 
					@license MIT. Copyright (c) 2015 James Devlin / FluentDesk.
 | 
				
			||||||
 | 
					@module utils/html-to-wpml
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(function() {
 | 
				
			||||||
 | 
					  var HTML5Tokenizer, _;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -14,12 +14,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  module.exports = function(html) {
 | 
					  module.exports = function(html) {
 | 
				
			||||||
    var final, is_bold, is_italic, is_link, link_url, tokens;
 | 
					    var final, is_bold, is_italic, is_link, link_url, tokens;
 | 
				
			||||||
    // Tokenize the HTML stream.
 | 
					 | 
				
			||||||
    tokens = HTML5Tokenizer.tokenize(html);
 | 
					    tokens = HTML5Tokenizer.tokenize(html);
 | 
				
			||||||
    final = is_bold = is_italic = is_link = link_url = '';
 | 
					    final = is_bold = is_italic = is_link = link_url = '';
 | 
				
			||||||
    // Process <em>, <strong>, and <a> elements in the HTML stream, producing
 | 
					 | 
				
			||||||
    // equivalent WordProcessingML that can be dumped into a <w:p> or other
 | 
					 | 
				
			||||||
    // text container element.
 | 
					 | 
				
			||||||
    _.each(tokens, function(tok) {
 | 
					    _.each(tokens, function(tok) {
 | 
				
			||||||
      var style;
 | 
					      var style;
 | 
				
			||||||
      switch (tok.type) {
 | 
					      switch (tok.type) {
 | 
				
			||||||
@@ -55,7 +51,7 @@
 | 
				
			|||||||
            style = is_bold ? '<w:b/>' : '';
 | 
					            style = is_bold ? '<w:b/>' : '';
 | 
				
			||||||
            style += is_italic ? '<w:i/>' : '';
 | 
					            style += is_italic ? '<w:i/>' : '';
 | 
				
			||||||
            style += is_link ? '<w:rStyle w:val="Hyperlink"/>' : '';
 | 
					            style += is_link ? '<w:rStyle w:val="Hyperlink"/>' : '';
 | 
				
			||||||
            return final += (is_link ? '<w:hlink w:dest="' + link_url + '">' : '') + '<w:r><w:rPr>' + style + '</w:rPr><w:t>' + XML(tok.chars) + '</w:t></w:r>' + (is_link ? '</w:hlink>' : '');
 | 
					            return final += (is_link ? '<w:hlink w:dest="' + link_url + '">' : '') + '<w:r><w:rPr>' + style + '</w:rPr><w:t>' + tok.chars + '</w:t></w:r>' + (is_link ? '</w:hlink>' : '');
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								dist/utils/md2chalk.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								dist/utils/md2chalk.js
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Inline Markdown-to-Chalk conversion routines.
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					@module utils/md2chalk
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Inline Markdown-to-Chalk conversion routines.
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  @module utils/md2chalk
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var CHALK, LO, MD;
 | 
					  var CHALK, LO, MD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  MD = require('marked');
 | 
					  MD = require('marked');
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								dist/utils/rasterize.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								dist/utils/rasterize.js
									
									
									
									
										vendored
									
									
								
							@@ -1,7 +1,4 @@
 | 
				
			|||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  // Exemplar script for generating documents with Phantom.js.
 | 
					 | 
				
			||||||
  // https://raw.githubusercontent.com/ariya/phantomjs/master/examples/rasterize.js
 | 
					 | 
				
			||||||
  // Converted to CoffeeScript by hacksalot
 | 
					 | 
				
			||||||
  "use strict";
 | 
					  "use strict";
 | 
				
			||||||
  var address, output, page, pageHeight, pageWidth, size, system;
 | 
					  var address, output, page, pageHeight, pageWidth, size, system;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -53,7 +50,7 @@
 | 
				
			|||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        console.log("size:", system.args[3]);
 | 
					        console.log("size:", system.args[3]);
 | 
				
			||||||
        pageWidth = parseInt(system.args[3], 10);
 | 
					        pageWidth = parseInt(system.args[3], 10);
 | 
				
			||||||
        pageHeight = parseInt(pageWidth * 3 / 4, 10); // it's as good an assumption as any
 | 
					        pageHeight = parseInt(pageWidth * 3 / 4, 10);
 | 
				
			||||||
        console.log("pageHeight:", pageHeight);
 | 
					        console.log("pageHeight:", pageHeight);
 | 
				
			||||||
        page.viewportSize = {
 | 
					        page.viewportSize = {
 | 
				
			||||||
          width: pageWidth,
 | 
					          width: pageWidth,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								dist/utils/resume-detector.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								dist/utils/resume-detector.js
									
									
									
									
										vendored
									
									
								
							@@ -1,19 +0,0 @@
 | 
				
			|||||||
(function() {
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the ResumeDetector class.
 | 
					 | 
				
			||||||
  @module utils/resume-detector
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  module.exports = function(rez) {
 | 
					 | 
				
			||||||
    if (rez.meta && rez.meta.format) { //&& rez.meta.format.substr(0, 5).toUpperCase() == 'FRESH'
 | 
					 | 
				
			||||||
      return 'fresh';
 | 
					 | 
				
			||||||
    } else if (rez.basics) {
 | 
					 | 
				
			||||||
      return 'jrs';
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      return 'unk';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}).call(this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//# sourceMappingURL=resume-detector.js.map
 | 
					 | 
				
			||||||
							
								
								
									
										55
									
								
								dist/utils/resume-scrubber.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										55
									
								
								dist/utils/resume-scrubber.js
									
									
									
									
										vendored
									
									
								
							@@ -1,55 +0,0 @@
 | 
				
			|||||||
(function() {
 | 
					 | 
				
			||||||
  module.exports = {
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    Removes ignored or private fields from a resume object
 | 
					 | 
				
			||||||
    @returns an object with the following structure:
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      scrubbed: the processed resume object
 | 
					 | 
				
			||||||
      ignoreList: an array of ignored nodes that were removed
 | 
					 | 
				
			||||||
      privateList: an array of private nodes that were removed
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    scrubResume: function(rep, opts) {
 | 
					 | 
				
			||||||
      var ignoreList, includePrivates, privateList, scrubbed, traverse;
 | 
					 | 
				
			||||||
      traverse = require('traverse');
 | 
					 | 
				
			||||||
      ignoreList = [];
 | 
					 | 
				
			||||||
      privateList = [];
 | 
					 | 
				
			||||||
      includePrivates = opts && opts.private;
 | 
					 | 
				
			||||||
      scrubbed = traverse(rep).map(function() { // [^1]
 | 
					 | 
				
			||||||
        if (!this.isLeaf) {
 | 
					 | 
				
			||||||
          if (this.node.ignore === true || this.node.ignore === 'true') {
 | 
					 | 
				
			||||||
            ignoreList.push(this.node);
 | 
					 | 
				
			||||||
            this.delete();
 | 
					 | 
				
			||||||
          } else if ((this.node.private === true || this.node.private === 'true') && !includePrivates) {
 | 
					 | 
				
			||||||
            privateList.push(this.node);
 | 
					 | 
				
			||||||
            this.delete();
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (_.isArray(this.node)) { // [^2]
 | 
					 | 
				
			||||||
          this.after(function() {
 | 
					 | 
				
			||||||
            this.update(_.compact(this.node));
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      return {
 | 
					 | 
				
			||||||
        scrubbed: scrubbed,
 | 
					 | 
				
			||||||
        ingoreList: ignoreList,
 | 
					 | 
				
			||||||
        privateList: privateList
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // [^1]: As of v0.6.6, the NPM traverse library has a quirk when attempting
 | 
					 | 
				
			||||||
// to remove array elements directly using traverse's `this.remove`. See:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// https://github.com/substack/js-traverse/issues/48
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// [^2]: The workaround is to use traverse's 'this.delete' to nullify the value
 | 
					 | 
				
			||||||
// first, followed by removal with something like _.compact.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// https://github.com/substack/js-traverse/issues/48#issuecomment-142607200
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}).call(this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//# sourceMappingURL=resume-scrubber.js.map
 | 
					 | 
				
			||||||
							
								
								
									
										23
									
								
								dist/utils/safe-json-loader.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								dist/utils/safe-json-loader.js
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the SafeJsonLoader class.
 | 
				
			||||||
 | 
					@module utils/safe-json-loader
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the SafeJsonLoader class.
 | 
					 | 
				
			||||||
  @module utils/safe-json-loader
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FS, SyntaxErrorEx;
 | 
					  var FS, SyntaxErrorEx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FS = require('fs');
 | 
					  FS = require('fs');
 | 
				
			||||||
@@ -11,19 +13,16 @@
 | 
				
			|||||||
  SyntaxErrorEx = require('./syntax-error-ex');
 | 
					  SyntaxErrorEx = require('./syntax-error-ex');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = function(file) {
 | 
					  module.exports = function(file) {
 | 
				
			||||||
    var err, ret, retRaw;
 | 
					    var ret, retRaw;
 | 
				
			||||||
    ret = {};
 | 
					    ret = {};
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      ret.raw = FS.readFileSync(file, 'utf8');
 | 
					      ret.raw = FS.readFileSync(file, 'utf8');
 | 
				
			||||||
      ret.json = JSON.parse(ret.raw);
 | 
					      ret.json = JSON.parse(ret.raw);
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (_error) {
 | 
				
			||||||
      err = error;
 | 
					 | 
				
			||||||
      // If we get here, either FS.readFileSync or JSON.parse failed.
 | 
					 | 
				
			||||||
      // We'll return HMSTATUS.readError or HMSTATUS.parseError.
 | 
					 | 
				
			||||||
      retRaw = ret.raw && ret.raw.trim();
 | 
					      retRaw = ret.raw && ret.raw.trim();
 | 
				
			||||||
      ret.ex = {
 | 
					      ret.ex = {
 | 
				
			||||||
        op: retRaw ? 'parse' : 'read',
 | 
					        operation: retRaw ? 'parse' : 'read',
 | 
				
			||||||
        inner: SyntaxErrorEx.is(err) ? new SyntaxErrorEx(err, retRaw) : err,
 | 
					        inner: SyntaxErrorEx.is(_error) ? new SyntaxErrorEx(_error, retRaw) : _error,
 | 
				
			||||||
        file: file
 | 
					        file: file
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								dist/utils/safe-spawn.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								dist/utils/safe-spawn.js
									
									
									
									
										vendored
									
									
								
							@@ -1,15 +1,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Safe spawn utility for HackMyResume / FluentCV.
 | 
				
			||||||
 | 
					@module utils/safe-spawn
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Safely spawn a process synchronously or asynchronously without throwing an
 | 
				
			||||||
 | 
					exception
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Safe spawn utility for HackMyResume / FluentCV.
 | 
					 | 
				
			||||||
  @module utils/safe-spawn
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** Safely spawn a process synchronously or asynchronously without throwing an
 | 
					 | 
				
			||||||
  exception */
 | 
					 | 
				
			||||||
  module.exports = function(cmd, args, isSync, callback, param) {
 | 
					  module.exports = function(cmd, args, isSync, callback, param) {
 | 
				
			||||||
    var ex, info, spawn;
 | 
					    var info, spawn;
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      // .spawnSync not available on earlier Node.js, so default to .spawn
 | 
					 | 
				
			||||||
      spawn = require('child_process')[isSync ? 'spawnSync' : 'spawn'];
 | 
					      spawn = require('child_process')[isSync ? 'spawnSync' : 'spawn'];
 | 
				
			||||||
      info = spawn(cmd, args);
 | 
					      info = spawn(cmd, args);
 | 
				
			||||||
      if (!isSync) {
 | 
					      if (!isSync) {
 | 
				
			||||||
@@ -29,12 +33,11 @@
 | 
				
			|||||||
          };
 | 
					          };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (_error) {
 | 
				
			||||||
      ex = error;
 | 
					 | 
				
			||||||
      if (typeof callback === "function") {
 | 
					      if (typeof callback === "function") {
 | 
				
			||||||
        callback(ex, param);
 | 
					        callback(_error, param);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return ex;
 | 
					      return _error;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								dist/utils/string-transformer.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								dist/utils/string-transformer.js
									
									
									
									
										vendored
									
									
								
							@@ -1,23 +1,26 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Object string transformation.
 | 
				
			||||||
 | 
					@module utils/string-transformer
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Object string transformation.
 | 
					 | 
				
			||||||
  @module utils/string-transformer
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var _, moment;
 | 
					  var _, moment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  moment = require('moment');
 | 
					  moment = require('moment');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  Create a copy of this object in which all string fields have been run through
 | 
					  Create a copy of this object in which all string fields have been run through
 | 
				
			||||||
  a transformation function (such as a Markdown filter or XML encoder).
 | 
					  a transformation function (such as a Markdown filter or XML encoder).
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = function(ret, filt, transformer) {
 | 
					  module.exports = function(ret, filt, transformer) {
 | 
				
			||||||
    var that, transformStringsInObject;
 | 
					    var that, transformStringsInObject;
 | 
				
			||||||
    that = this;
 | 
					    that = this;
 | 
				
			||||||
    // TODO: refactor recursion
 | 
					 | 
				
			||||||
    transformStringsInObject = function(obj, filters) {
 | 
					    transformStringsInObject = function(obj, filters) {
 | 
				
			||||||
      if (!obj) {
 | 
					      if (!obj) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										22
									
								
								dist/utils/string.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								dist/utils/string.js
									
									
									
									
										vendored
									
									
								
							@@ -1,13 +1,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definitions of string utility functions.
 | 
				
			||||||
 | 
					@module utils/string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Determine if the string is null, empty, or whitespace.
 | 
				
			||||||
 | 
					See: http://stackoverflow.com/a/32800728/4942583
 | 
				
			||||||
 | 
					@method isNullOrWhitespace
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definitions of string utility functions.
 | 
					 | 
				
			||||||
  @module utils/string
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Determine if the string is null, empty, or whitespace.
 | 
					 | 
				
			||||||
  See: http://stackoverflow.com/a/32800728/4942583
 | 
					 | 
				
			||||||
  @method isNullOrWhitespace
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  String.isNullOrWhitespace = function(input) {
 | 
					  String.isNullOrWhitespace = function(input) {
 | 
				
			||||||
    return !input || !input.trim();
 | 
					    return !input || !input.trim();
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										48
									
								
								dist/utils/syntax-error-ex.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								dist/utils/syntax-error-ex.js
									
									
									
									
										vendored
									
									
								
							@@ -1,22 +1,26 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the SyntaxErrorEx class.
 | 
				
			||||||
 | 
					@module utils/syntax-error-ex
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Represents a SyntaxError exception with line and column info.
 | 
				
			||||||
 | 
					Collect syntax error information from the provided exception object. The
 | 
				
			||||||
 | 
					JavaScript `SyntaxError` exception isn't interpreted uniformly across environ-
 | 
				
			||||||
 | 
					ments, so we reparse on error to grab the line and column.
 | 
				
			||||||
 | 
					See: http://stackoverflow.com/q/13323356
 | 
				
			||||||
 | 
					@class SyntaxErrorEx
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the SyntaxErrorEx class.
 | 
					 | 
				
			||||||
  @module utils/syntax-error-ex
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var SyntaxErrorEx;
 | 
					  var SyntaxErrorEx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  SyntaxErrorEx = (function() {
 | 
				
			||||||
  Represents a SyntaxError exception with line and column info.
 | 
					    function SyntaxErrorEx(ex, rawData) {
 | 
				
			||||||
  Collect syntax error information from the provided exception object. The
 | 
					      var JSONLint, colNum, lineNum, lint, ref;
 | 
				
			||||||
  JavaScript `SyntaxError` exception isn't interpreted uniformly across environ-
 | 
					 | 
				
			||||||
  ments, so we reparse on error to grab the line and column.
 | 
					 | 
				
			||||||
  See: http://stackoverflow.com/q/13323356
 | 
					 | 
				
			||||||
  @class SyntaxErrorEx
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  SyntaxErrorEx = class SyntaxErrorEx {
 | 
					 | 
				
			||||||
    constructor(ex, rawData) {
 | 
					 | 
				
			||||||
      var JSONLint, colNum, err, lineNum, lint;
 | 
					 | 
				
			||||||
      lineNum = null;
 | 
					      lineNum = null;
 | 
				
			||||||
      colNum = null;
 | 
					      colNum = null;
 | 
				
			||||||
      JSONLint = require('json-lint');
 | 
					      JSONLint = require('json-lint');
 | 
				
			||||||
@@ -24,22 +28,22 @@
 | 
				
			|||||||
        comments: false
 | 
					        comments: false
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      if (lint.error) {
 | 
					      if (lint.error) {
 | 
				
			||||||
        [this.line, this.col] = [lint.line, lint.character];
 | 
					        ref = [lint.line, lint.character], this.line = ref[0], this.col = ref[1];
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (!lint.error) {
 | 
					      if (!lint.error) {
 | 
				
			||||||
        JSONLint = require('jsonlint');
 | 
					        JSONLint = require('jsonlint');
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
          JSONLint.parse(rawData);
 | 
					          JSONLint.parse(rawData);
 | 
				
			||||||
        } catch (error) {
 | 
					        } catch (_error) {
 | 
				
			||||||
          err = error;
 | 
					          this.line = (/on line (\d+)/.exec(_error))[1];
 | 
				
			||||||
          this.line = (/on line (\d+)/.exec(err))[1];
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return SyntaxErrorEx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Return true if the supplied parameter is a JavaScript SyntaxError
 | 
					 | 
				
			||||||
  SyntaxErrorEx.is = function(ex) {
 | 
					  SyntaxErrorEx.is = function(ex) {
 | 
				
			||||||
    return ex instanceof SyntaxError;
 | 
					    return ex instanceof SyntaxError;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										43
									
								
								dist/verbs/analyze.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								dist/verbs/analyze.js
									
									
									
									
										vendored
									
									
								
							@@ -1,12 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Implementation of the 'analyze' verb for HackMyResume.
 | 
				
			||||||
 | 
					@module verbs/analyze
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var AnalyzeVerb, HMEVENT, HMSTATUS, MKDIRP, PATH, ResumeFactory, Verb, _, _analyze, _analyzeOne, _loadInspectors, chalk,
 | 
				
			||||||
  Implementation of the 'analyze' verb for HackMyResume.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module verbs/analyze
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** Private workhorse for the 'analyze' command. */
 | 
					 | 
				
			||||||
  /** Analyze a single resume. */
 | 
					 | 
				
			||||||
  var AnalyzeVerb, HMEVENT, HMSTATUS, MKDIRP, PATH, ResumeFactory, Verb, _, _analyze, _analyzeOne, _loadInspectors, chalk;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  MKDIRP = require('mkdirp');
 | 
					  MKDIRP = require('mkdirp');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -24,13 +26,22 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  chalk = require('chalk');
 | 
					  chalk = require('chalk');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** An invokable resume analysis command. */
 | 
					  /** An invokable resume analysis command. */
 | 
				
			||||||
  module.exports = AnalyzeVerb = class AnalyzeVerb extends Verb {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = AnalyzeVerb = (function(superClass) {
 | 
				
			||||||
      super('analyze', _analyze);
 | 
					    extend(AnalyzeVerb, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function AnalyzeVerb() {
 | 
				
			||||||
 | 
					      AnalyzeVerb.__super__.constructor.call(this, 'analyze', _analyze);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return AnalyzeVerb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(Verb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Private workhorse for the 'analyze' command. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _analyze = function(sources, dst, opts) {
 | 
					  _analyze = function(sources, dst, opts) {
 | 
				
			||||||
    var nlzrs, results;
 | 
					    var nlzrs, results;
 | 
				
			||||||
@@ -45,10 +56,7 @@
 | 
				
			|||||||
      var r;
 | 
					      var r;
 | 
				
			||||||
      r = ResumeFactory.loadOne(src, {
 | 
					      r = ResumeFactory.loadOne(src, {
 | 
				
			||||||
        format: 'FRESH',
 | 
					        format: 'FRESH',
 | 
				
			||||||
        objectify: true,
 | 
					        objectify: true
 | 
				
			||||||
        inner: {
 | 
					 | 
				
			||||||
          private: opts.private === true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }, this);
 | 
					      }, this);
 | 
				
			||||||
      if (opts.assert && this.hasError()) {
 | 
					      if (opts.assert && this.hasError()) {
 | 
				
			||||||
        return {};
 | 
					        return {};
 | 
				
			||||||
@@ -69,6 +77,9 @@
 | 
				
			|||||||
    return results;
 | 
					    return results;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Analyze a single resume. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _analyzeOne = function(resumeObject, nlzrs, opts) {
 | 
					  _analyzeOne = function(resumeObject, nlzrs, opts) {
 | 
				
			||||||
    var info, rez, safeFormat;
 | 
					    var info, rez, safeFormat;
 | 
				
			||||||
    rez = resumeObject.rez;
 | 
					    rez = resumeObject.rez;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										232
									
								
								dist/verbs/build.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										232
									
								
								dist/verbs/build.js
									
									
									
									
										vendored
									
									
								
							@@ -1,49 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Implementation of the 'build' verb for HackMyResume.
 | 
				
			||||||
 | 
					@module verbs/build
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var BuildVerb, FRESHTheme, FS, HMEVENT, HMSTATUS, JRSTheme, MD, MKDIRP, PATH, RConverter, RTYPES, ResumeFactory, Verb, _, _addFreebieFormats, _build, _err, _expand, _fmts, _loadTheme, _log, _opts, _prep, _rezObj, _single, _verifyOutputs, _verifyTheme, addFreebieFormats, build, expand, extend, loadTheme, parsePath, prep, single, verifyOutputs, verifyTheme,
 | 
				
			||||||
  Implementation of the 'build' verb for HackMyResume.
 | 
					    extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module verbs/build
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Reinforce the chosen theme with "freebie" formats provided by HackMyResume.
 | 
					 | 
				
			||||||
  A "freebie" format is an output format such as JSON, YML, or PNG that can be
 | 
					 | 
				
			||||||
  generated directly from the resume model or from one of the theme's declared
 | 
					 | 
				
			||||||
  output formats. For example, the PNG format can be generated for any theme
 | 
					 | 
				
			||||||
  that declares an HTML format; the theme doesn't have to provide an explicit
 | 
					 | 
				
			||||||
  PNG template.
 | 
					 | 
				
			||||||
  @param theTheme A FRESHTheme or JRSTheme object.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Given a source resume in FRESH or JRS format, a destination resume path, and a
 | 
					 | 
				
			||||||
  theme file, generate 0..N resumes in the desired formats.
 | 
					 | 
				
			||||||
  @param src Path to the source JSON resume file: "rez/resume.json".
 | 
					 | 
				
			||||||
  @param dst An array of paths to the target resume file(s).
 | 
					 | 
				
			||||||
  @param opts Generation options.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Expand output files. For example, "foo.all" should be expanded to
 | 
					 | 
				
			||||||
  ["foo.html", "foo.doc", "foo.pdf", "etc"].
 | 
					 | 
				
			||||||
  @param dst An array of output files as specified by the user.
 | 
					 | 
				
			||||||
  @param theTheme A FRESHTheme or JRSTheme object.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Load the specified theme, which could be either a FRESH theme or a JSON Resume
 | 
					 | 
				
			||||||
  theme (or both).
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Prepare for a BUILD run.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Generate a single target resume such as "out/rez.html" or "out/rez.doc".
 | 
					 | 
				
			||||||
  TODO: Refactor.
 | 
					 | 
				
			||||||
  @param targInfo Information for the target resume.
 | 
					 | 
				
			||||||
  @param theme A FRESHTheme or JRSTheme object.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** Ensure that user-specified outputs/targets are valid. */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Verify the specified theme name/path.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var BuildVerb, FRESHTheme, FS, HMEVENT, HMSTATUS, JRSTheme, MD, MKDIRP, PATH, RConverter, RTYPES, ResumeFactory, Verb, _, _addFreebieFormats, _build, _err, _expand, _fmts, _loadTheme, _log, _opts, _prep, _rezObj, _single, _verifyOutputs, _verifyTheme, addFreebieFormats, build, expand, extend, loadTheme, parsePath, prep, single, verifyOutputs, verifyTheme;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _ = require('underscore');
 | 
					  _ = require('underscore');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -104,17 +69,34 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  loadTheme = null;
 | 
					  loadTheme = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** An invokable resume generation command. */
 | 
					  /** An invokable resume generation command. */
 | 
				
			||||||
  module.exports = BuildVerb = class BuildVerb extends Verb {
 | 
					
 | 
				
			||||||
 | 
					  module.exports = BuildVerb = (function(superClass) {
 | 
				
			||||||
 | 
					    extend1(BuildVerb, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Create a new build verb. */
 | 
					    /** Create a new build verb. */
 | 
				
			||||||
    constructor() {
 | 
					
 | 
				
			||||||
      super('build', _build);
 | 
					    function BuildVerb() {
 | 
				
			||||||
 | 
					      BuildVerb.__super__.constructor.call(this, 'build', _build);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return BuildVerb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(Verb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Given a source resume in FRESH or JRS format, a destination resume path, and a
 | 
				
			||||||
 | 
					  theme file, generate 0..N resumes in the desired formats.
 | 
				
			||||||
 | 
					  @param src Path to the source JSON resume file: "rez/resume.json".
 | 
				
			||||||
 | 
					  @param dst An array of paths to the target resume file(s).
 | 
				
			||||||
 | 
					  @param opts Generation options.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _build = function(src, dst, opts) {
 | 
					  _build = function(src, dst, opts) {
 | 
				
			||||||
    var err, inv, isFRESH, mixed, newEx, orgFormat, problemSheets, results, rez, sheetObjects, sheets, tFolder, targets, theme, toFormat;
 | 
					    var inv, isFRESH, mixed, newEx, orgFormat, problemSheets, results, rez, sheetObjects, sheets, tFolder, targets, theme, toFormat;
 | 
				
			||||||
    if (!src || !src.length) {
 | 
					    if (!src || !src.length) {
 | 
				
			||||||
      this.err(HMSTATUS.resumeNotFound, {
 | 
					      this.err(HMSTATUS.resumeNotFound, {
 | 
				
			||||||
        quit: true
 | 
					        quit: true
 | 
				
			||||||
@@ -122,30 +104,25 @@
 | 
				
			|||||||
      return null;
 | 
					      return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    _prep.call(this, src, dst, opts);
 | 
					    _prep.call(this, src, dst, opts);
 | 
				
			||||||
    // Load input resumes as JSON...
 | 
					 | 
				
			||||||
    sheetObjects = ResumeFactory.load(src, {
 | 
					    sheetObjects = ResumeFactory.load(src, {
 | 
				
			||||||
      format: null,
 | 
					      format: null,
 | 
				
			||||||
      objectify: false,
 | 
					      objectify: false,
 | 
				
			||||||
      quit: true,
 | 
					      quit: true,
 | 
				
			||||||
      inner: {
 | 
					      inner: {
 | 
				
			||||||
        sort: _opts.sort,
 | 
					        sort: _opts.sort
 | 
				
			||||||
        private: _opts.private
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }, this);
 | 
					    }, this);
 | 
				
			||||||
    // Explicit check for any resume loading errors...
 | 
					 | 
				
			||||||
    problemSheets = _.filter(sheetObjects, function(so) {
 | 
					    problemSheets = _.filter(sheetObjects, function(so) {
 | 
				
			||||||
      return so.fluenterror;
 | 
					      return so.fluenterror;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    if (problemSheets && problemSheets.length) {
 | 
					    if (problemSheets && problemSheets.length) {
 | 
				
			||||||
      problemSheets[0].quit = true; // can't go on
 | 
					      problemSheets[0].quit = true;
 | 
				
			||||||
      this.err(problemSheets[0].fluenterror, problemSheets[0]);
 | 
					      this.err(problemSheets[0].fluenterror, problemSheets[0]);
 | 
				
			||||||
      return null;
 | 
					      return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Get the collection of raw JSON sheets
 | 
					 | 
				
			||||||
    sheets = sheetObjects.map(function(r) {
 | 
					    sheets = sheetObjects.map(function(r) {
 | 
				
			||||||
      return r.json;
 | 
					      return r.json;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // Load the theme...
 | 
					 | 
				
			||||||
    theme = null;
 | 
					    theme = null;
 | 
				
			||||||
    this.stat(HMEVENT.beforeTheme, {
 | 
					    this.stat(HMEVENT.beforeTheme, {
 | 
				
			||||||
      theme: _opts.theme
 | 
					      theme: _opts.theme
 | 
				
			||||||
@@ -159,11 +136,10 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      theme = _opts.themeObj = _loadTheme(tFolder);
 | 
					      theme = _opts.themeObj = _loadTheme(tFolder);
 | 
				
			||||||
      _addFreebieFormats(theme);
 | 
					      _addFreebieFormats(theme);
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (_error) {
 | 
				
			||||||
      err = error;
 | 
					 | 
				
			||||||
      newEx = {
 | 
					      newEx = {
 | 
				
			||||||
        fluenterror: HMSTATUS.themeLoad,
 | 
					        fluenterror: HMSTATUS.themeLoad,
 | 
				
			||||||
        inner: err,
 | 
					        inner: _error,
 | 
				
			||||||
        attempted: _opts.theme,
 | 
					        attempted: _opts.theme,
 | 
				
			||||||
        quit: true
 | 
					        quit: true
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
@@ -173,7 +149,6 @@
 | 
				
			|||||||
    this.stat(HMEVENT.afterTheme, {
 | 
					    this.stat(HMEVENT.afterTheme, {
 | 
				
			||||||
      theme: theme
 | 
					      theme: theme
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // Check for invalid outputs...
 | 
					 | 
				
			||||||
    inv = _verifyOutputs.call(this, dst, theme);
 | 
					    inv = _verifyOutputs.call(this, dst, theme);
 | 
				
			||||||
    if (inv && inv.length) {
 | 
					    if (inv && inv.length) {
 | 
				
			||||||
      this.err(HMSTATUS.invalidFormat, {
 | 
					      this.err(HMSTATUS.invalidFormat, {
 | 
				
			||||||
@@ -183,7 +158,6 @@
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
      return null;
 | 
					      return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    //# Merge input resumes, yielding a single source resume...
 | 
					 | 
				
			||||||
    rez = null;
 | 
					    rez = null;
 | 
				
			||||||
    if (sheets.length > 1) {
 | 
					    if (sheets.length > 1) {
 | 
				
			||||||
      isFRESH = !sheets[0].basics;
 | 
					      isFRESH = !sheets[0].basics;
 | 
				
			||||||
@@ -220,17 +194,12 @@
 | 
				
			|||||||
        fmt: toFormat
 | 
					        fmt: toFormat
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Announce the theme
 | 
					 | 
				
			||||||
    this.stat(HMEVENT.applyTheme, {
 | 
					    this.stat(HMEVENT.applyTheme, {
 | 
				
			||||||
      r: rez,
 | 
					      r: rez,
 | 
				
			||||||
      theme: theme
 | 
					      theme: theme
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // Load the resume into a FRESHResume or JRSResume object
 | 
					    _rezObj = new RTYPES[toFormat]().parseJSON(rez);
 | 
				
			||||||
    _rezObj = new RTYPES[toFormat]().parseJSON(rez, {
 | 
					 | 
				
			||||||
      private: _opts.private
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    targets = _expand(dst, theme);
 | 
					    targets = _expand(dst, theme);
 | 
				
			||||||
    // Run the transformation!
 | 
					 | 
				
			||||||
    _.each(targets, function(t) {
 | 
					    _.each(targets, function(t) {
 | 
				
			||||||
      var ref;
 | 
					      var ref;
 | 
				
			||||||
      if (this.hasError() && opts.assert) {
 | 
					      if (this.hasError() && opts.assert) {
 | 
				
			||||||
@@ -255,13 +224,15 @@
 | 
				
			|||||||
    return results;
 | 
					    return results;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Prepare for a BUILD run.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _prep = function(src, dst, opts) {
 | 
					  _prep = function(src, dst, opts) {
 | 
				
			||||||
    var that;
 | 
					    var that;
 | 
				
			||||||
    // Cherry-pick options //_opts = extend( true, _opts, opts );
 | 
					 | 
				
			||||||
    _opts.theme = (opts.theme && opts.theme.toLowerCase().trim()) || 'modern';
 | 
					    _opts.theme = (opts.theme && opts.theme.toLowerCase().trim()) || 'modern';
 | 
				
			||||||
    _opts.prettify = opts.prettify === true;
 | 
					    _opts.prettify = opts.prettify === true;
 | 
				
			||||||
    _opts.private = opts.private === true;
 | 
					 | 
				
			||||||
    _opts.noescape = opts.noescape === true;
 | 
					 | 
				
			||||||
    _opts.css = opts.css;
 | 
					    _opts.css = opts.css;
 | 
				
			||||||
    _opts.pdf = opts.pdf;
 | 
					    _opts.pdf = opts.pdf;
 | 
				
			||||||
    _opts.wrap = opts.wrap || 60;
 | 
					    _opts.wrap = opts.wrap || 60;
 | 
				
			||||||
@@ -271,9 +242,7 @@
 | 
				
			|||||||
    _opts.noTips = opts.noTips;
 | 
					    _opts.noTips = opts.noTips;
 | 
				
			||||||
    _opts.debug = opts.debug;
 | 
					    _opts.debug = opts.debug;
 | 
				
			||||||
    _opts.sort = opts.sort;
 | 
					    _opts.sort = opts.sort;
 | 
				
			||||||
    _opts.wkhtmltopdf = opts.wkhtmltopdf;
 | 
					 | 
				
			||||||
    that = this;
 | 
					    that = this;
 | 
				
			||||||
    // Set up callbacks for internal generators
 | 
					 | 
				
			||||||
    _opts.onTransform = function(info) {
 | 
					    _opts.onTransform = function(info) {
 | 
				
			||||||
      that.stat(HMEVENT.afterTransform, info);
 | 
					      that.stat(HMEVENT.afterTransform, info);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -283,11 +252,17 @@
 | 
				
			|||||||
    _opts.afterWrite = function(info) {
 | 
					    _opts.afterWrite = function(info) {
 | 
				
			||||||
      that.stat(HMEVENT.afterWrite, info);
 | 
					      that.stat(HMEVENT.afterWrite, info);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    // If two or more files are passed to the GENERATE command and the TO
 | 
					 | 
				
			||||||
    // keyword is omitted, the last file specifies the output file.
 | 
					 | 
				
			||||||
    (src.length > 1 && (!dst || !dst.length)) && dst.push(src.pop());
 | 
					    (src.length > 1 && (!dst || !dst.length)) && dst.push(src.pop());
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Generate a single target resume such as "out/rez.html" or "out/rez.doc".
 | 
				
			||||||
 | 
					  TODO: Refactor.
 | 
				
			||||||
 | 
					  @param targInfo Information for the target resume.
 | 
				
			||||||
 | 
					  @param theme A FRESHTheme or JRSTheme object.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _single = function(targInfo, theme, finished) {
 | 
					  _single = function(targInfo, theme, finished) {
 | 
				
			||||||
    var e, ex, f, fName, fType, outFolder, ret, theFormat;
 | 
					    var e, ex, f, fName, fType, outFolder, ret, theFormat;
 | 
				
			||||||
    ret = null;
 | 
					    ret = null;
 | 
				
			||||||
@@ -305,8 +280,6 @@
 | 
				
			|||||||
        file: PATH.relative(process.cwd(), f)
 | 
					        file: PATH.relative(process.cwd(), f)
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      _opts.targets = finished;
 | 
					      _opts.targets = finished;
 | 
				
			||||||
      // If targInfo.fmt.files exists, this format is backed by a document.
 | 
					 | 
				
			||||||
      // Fluent/FRESH themes are handled here.
 | 
					 | 
				
			||||||
      if (targInfo.fmt.files && targInfo.fmt.files.length) {
 | 
					      if (targInfo.fmt.files && targInfo.fmt.files.length) {
 | 
				
			||||||
        theFormat = _fmts.filter(function(fmt) {
 | 
					        theFormat = _fmts.filter(function(fmt) {
 | 
				
			||||||
          return fmt.name === targInfo.fmt.outFormat;
 | 
					          return fmt.name === targInfo.fmt.outFormat;
 | 
				
			||||||
@@ -314,17 +287,15 @@
 | 
				
			|||||||
        MKDIRP.sync(PATH.dirname(f));
 | 
					        MKDIRP.sync(PATH.dirname(f));
 | 
				
			||||||
        ret = theFormat.gen.generate(_rezObj, f, _opts);
 | 
					        ret = theFormat.gen.generate(_rezObj, f, _opts);
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        // Otherwise this is an ad-hoc format (JSON, YML, or PNG) that every theme
 | 
					 | 
				
			||||||
        // gets "for free".
 | 
					 | 
				
			||||||
        theFormat = _fmts.filter(function(fmt) {
 | 
					        theFormat = _fmts.filter(function(fmt) {
 | 
				
			||||||
          return fmt.name === targInfo.fmt.outFormat;
 | 
					          return fmt.name === targInfo.fmt.outFormat;
 | 
				
			||||||
        })[0];
 | 
					        })[0];
 | 
				
			||||||
        outFolder = PATH.dirname(f);
 | 
					        outFolder = PATH.dirname(f);
 | 
				
			||||||
        MKDIRP.sync(outFolder); // Ensure dest folder exists;
 | 
					        MKDIRP.sync(outFolder);
 | 
				
			||||||
        ret = theFormat.gen.generate(_rezObj, f, _opts);
 | 
					        ret = theFormat.gen.generate(_rezObj, f, _opts);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (_error) {
 | 
				
			||||||
      e = error;
 | 
					      e = _error;
 | 
				
			||||||
      ex = e;
 | 
					      ex = e;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.stat(HMEVENT.afterGenerate, {
 | 
					    this.stat(HMEVENT.afterGenerate, {
 | 
				
			||||||
@@ -345,6 +316,9 @@
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Ensure that user-specified outputs/targets are valid. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _verifyOutputs = function(targets, theme) {
 | 
					  _verifyOutputs = function(targets, theme) {
 | 
				
			||||||
    this.stat(HMEVENT.verifyOutputs, {
 | 
					    this.stat(HMEVENT.verifyOutputs, {
 | 
				
			||||||
      targets: targets,
 | 
					      targets: targets,
 | 
				
			||||||
@@ -361,9 +335,18 @@
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Reinforce the chosen theme with "freebie" formats provided by HackMyResume.
 | 
				
			||||||
 | 
					  A "freebie" format is an output format such as JSON, YML, or PNG that can be
 | 
				
			||||||
 | 
					  generated directly from the resume model or from one of the theme's declared
 | 
				
			||||||
 | 
					  output formats. For example, the PNG format can be generated for any theme
 | 
				
			||||||
 | 
					  that declares an HTML format; the theme doesn't have to provide an explicit
 | 
				
			||||||
 | 
					  PNG template.
 | 
				
			||||||
 | 
					  @param theTheme A FRESHTheme or JRSTheme object.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _addFreebieFormats = function(theTheme) {
 | 
					  _addFreebieFormats = function(theTheme) {
 | 
				
			||||||
    // Add freebie formats (JSON, YAML, PNG) every theme gets...
 | 
					 | 
				
			||||||
    // Add HTML-driven PNG only if the theme has an HTML format.
 | 
					 | 
				
			||||||
    theTheme.formats.json = theTheme.formats.json || {
 | 
					    theTheme.formats.json = theTheme.formats.json || {
 | 
				
			||||||
      freebie: true,
 | 
					      freebie: true,
 | 
				
			||||||
      title: 'json',
 | 
					      title: 'json',
 | 
				
			||||||
@@ -394,10 +377,16 @@
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Expand output files. For example, "foo.all" should be expanded to
 | 
				
			||||||
 | 
					  ["foo.html", "foo.doc", "foo.pdf", "etc"].
 | 
				
			||||||
 | 
					  @param dst An array of output files as specified by the user.
 | 
				
			||||||
 | 
					  @param theTheme A FRESHTheme or JRSTheme object.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _expand = function(dst, theTheme) {
 | 
					  _expand = function(dst, theTheme) {
 | 
				
			||||||
    var destColl, targets;
 | 
					    var destColl, targets;
 | 
				
			||||||
    // Set up the destination collection. It's either the array of files passed
 | 
					 | 
				
			||||||
    // by the user or 'out/resume.all' if no targets were specified.
 | 
					 | 
				
			||||||
    destColl = (dst && dst.length && dst) || [PATH.normalize('out/resume.all')];
 | 
					    destColl = (dst && dst.length && dst) || [PATH.normalize('out/resume.all')];
 | 
				
			||||||
    targets = [];
 | 
					    targets = [];
 | 
				
			||||||
    destColl.forEach(function(t) {
 | 
					    destColl.forEach(function(t) {
 | 
				
			||||||
@@ -422,63 +411,40 @@
 | 
				
			|||||||
    return targets;
 | 
					    return targets;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Verify the specified theme name/path.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _verifyTheme = function(themeNameOrPath) {
 | 
					  _verifyTheme = function(themeNameOrPath) {
 | 
				
			||||||
    var exists, tFolder, themesObj;
 | 
					    var exists, tFolder;
 | 
				
			||||||
    // First, see if this is one of the predefined FRESH themes. There are only a
 | 
					    tFolder = PATH.join(parsePath(require.resolve('fresh-themes')).dirname, '/themes/', themeNameOrPath);
 | 
				
			||||||
    // handful of these, but they may change over time, so we need to query
 | 
					 | 
				
			||||||
    // the official source of truth: the fresh-themes repository, which mounts the
 | 
					 | 
				
			||||||
    // themes conveniently by name to the module object, and which is embedded
 | 
					 | 
				
			||||||
    // locally inside the HackMyResume installation.
 | 
					 | 
				
			||||||
    themesObj = require('fresh-themes');
 | 
					 | 
				
			||||||
    if (_.has(themesObj.themes, themeNameOrPath)) {
 | 
					 | 
				
			||||||
      tFolder = PATH.join(parsePath(require.resolve('fresh-themes')).dirname, '/themes/', themeNameOrPath);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      // Otherwsie it's a path to an arbitrary FRESH or JRS theme sitting somewhere
 | 
					 | 
				
			||||||
      // on the user's system (or, in the future, at a URI).
 | 
					 | 
				
			||||||
      tFolder = PATH.resolve(themeNameOrPath);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    // In either case, make sure the theme folder exists
 | 
					 | 
				
			||||||
    exists = require('path-exists').sync;
 | 
					    exists = require('path-exists').sync;
 | 
				
			||||||
    if (exists(tFolder)) {
 | 
					    if (!exists(tFolder)) {
 | 
				
			||||||
      return tFolder;
 | 
					      tFolder = PATH.resolve(themeNameOrPath);
 | 
				
			||||||
    } else {
 | 
					      if (!exists(tFolder)) {
 | 
				
			||||||
      return {
 | 
					        return {
 | 
				
			||||||
        fluenterror: HMSTATUS.themeNotFound,
 | 
					          fluenterror: HMSTATUS.themeNotFound,
 | 
				
			||||||
        data: _opts.theme
 | 
					          data: _opts.theme
 | 
				
			||||||
      };
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    return tFolder;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Load the specified theme, which could be either a FRESH theme or a JSON Resume
 | 
				
			||||||
 | 
					  theme.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _loadTheme = function(tFolder) {
 | 
					  _loadTheme = function(tFolder) {
 | 
				
			||||||
    var exists, theTheme, themeJsonPath;
 | 
					    var theTheme;
 | 
				
			||||||
    themeJsonPath = PATH.join(tFolder, 'theme.json'); // [^1]
 | 
					    theTheme = _opts.theme.indexOf('jsonresume-theme-') > -1 ? new JRSTheme().open(tFolder) : new FRESHTheme().open(tFolder);
 | 
				
			||||||
    exists = require('path-exists').sync;
 | 
					 | 
				
			||||||
    // Create a FRESH or JRS theme object
 | 
					 | 
				
			||||||
    theTheme = exists(themeJsonPath) ? new FRESHTheme().open(tFolder) : new JRSTheme().open(tFolder);
 | 
					 | 
				
			||||||
    // Cache the theme object
 | 
					 | 
				
			||||||
    _opts.themeObj = theTheme;
 | 
					    _opts.themeObj = theTheme;
 | 
				
			||||||
    return theTheme;
 | 
					    return theTheme;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // FOOTNOTES
 | 
					 | 
				
			||||||
// ------------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// [^1] We don't know ahead of time whether this is a FRESH or JRS theme.
 | 
					 | 
				
			||||||
//      However, all FRESH themes have a theme.json file, so we'll use that as a
 | 
					 | 
				
			||||||
//      canary for now, as an interim solution.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//      Unfortunately, with the exception of FRESH's theme.json, both FRESH and
 | 
					 | 
				
			||||||
//      JRS themes are free-form and don't have a ton of reliable distinguishing
 | 
					 | 
				
			||||||
//      marks, which makes a simple task like ad hoc theme detection harder than
 | 
					 | 
				
			||||||
//      it should be to do cleanly.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//      Another complicating factor is that it's possible for a theme to be BOTH.
 | 
					 | 
				
			||||||
//      That is, a single set of theme files can serve as a FRESH theme -and- a
 | 
					 | 
				
			||||||
//      JRS theme.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//      TODO: The most robust way to deal with all these issues is with a strong
 | 
					 | 
				
			||||||
//      theme validator. If a theme structure validates as a particular theme
 | 
					 | 
				
			||||||
//      type, then for all intents and purposes, it IS a theme of that type.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//# sourceMappingURL=build.js.map
 | 
					//# sourceMappingURL=build.js.map
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										129
									
								
								dist/verbs/convert.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										129
									
								
								dist/verbs/convert.js
									
									
									
									
										vendored
									
									
								
							@@ -1,13 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Implementation of the 'convert' verb for HackMyResume.
 | 
				
			||||||
 | 
					@module verbs/convert
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var ConvertVerb, HMEVENT, HMSTATUS, ResumeFactory, Verb, _, _convert, _convertOne, chalk,
 | 
				
			||||||
  Implementation of the 'convert' verb for HackMyResume.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module verbs/convert
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** Private workhorse method. Convert 0..N resumes between FRESH and JRS
 | 
					 | 
				
			||||||
  formats. */
 | 
					 | 
				
			||||||
  /** Private workhorse method. Convert a single resume. */
 | 
					 | 
				
			||||||
  var ConvertVerb, HMEVENT, HMSTATUS, ResumeFactory, Verb, _, _convert, _convertOne, chalk;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ResumeFactory = require('../core/resume-factory');
 | 
					  ResumeFactory = require('../core/resume-factory');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -21,15 +22,24 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  HMEVENT = require('../core/event-codes');
 | 
					  HMEVENT = require('../core/event-codes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = ConvertVerb = class ConvertVerb extends Verb {
 | 
					  module.exports = ConvertVerb = (function(superClass) {
 | 
				
			||||||
    constructor() {
 | 
					    extend(ConvertVerb, superClass);
 | 
				
			||||||
      super('convert', _convert);
 | 
					
 | 
				
			||||||
 | 
					    function ConvertVerb() {
 | 
				
			||||||
 | 
					      ConvertVerb.__super__.constructor.call(this, 'convert', _convert);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return ConvertVerb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(Verb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Private workhorse method. Convert 0..N resumes between FRESH and JRS
 | 
				
			||||||
 | 
					  formats.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _convert = function(srcs, dst, opts) {
 | 
					  _convert = function(srcs, dst, opts) {
 | 
				
			||||||
    var fmtUp, results, targetVer;
 | 
					    var results;
 | 
				
			||||||
    if (!srcs || !srcs.length) {
 | 
					    if (!srcs || !srcs.length) {
 | 
				
			||||||
      this.err(HMSTATUS.resumeNotFound, {
 | 
					      this.err(HMSTATUS.resumeNotFound, {
 | 
				
			||||||
        quit: true
 | 
					        quit: true
 | 
				
			||||||
@@ -50,44 +60,17 @@
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Different number of source and dest resumes? Error out.
 | 
					 | 
				
			||||||
    if (srcs && dst && srcs.length && dst.length && srcs.length !== dst.length) {
 | 
					    if (srcs && dst && srcs.length && dst.length && srcs.length !== dst.length) {
 | 
				
			||||||
      this.err(HMSTATUS.inputOutputParity, {
 | 
					      this.err(HMSTATUS.inputOutputParity, {
 | 
				
			||||||
        quit: true
 | 
					        quit: true
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Validate the destination format (if specified)
 | 
					 | 
				
			||||||
    targetVer = null;
 | 
					 | 
				
			||||||
    if (opts.format) {
 | 
					 | 
				
			||||||
      fmtUp = opts.format.trim().toUpperCase();
 | 
					 | 
				
			||||||
      if (!_.contains(['FRESH', 'FRESCA', 'JRS', 'JRS@1', 'JRS@edge'], fmtUp)) {
 | 
					 | 
				
			||||||
        this.err(HMSTATUS.invalidSchemaVersion, {
 | 
					 | 
				
			||||||
          data: opts.format.trim(),
 | 
					 | 
				
			||||||
          quit: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    // freshVerRegex = require '../utils/fresh-version-regex'
 | 
					 | 
				
			||||||
    // matches = fmtUp.match freshVerRegex()
 | 
					 | 
				
			||||||
    // # null
 | 
					 | 
				
			||||||
    // # [ 'JRS@1.0', 'JRS', '1.0', index: 0, input: 'FRESH' ]
 | 
					 | 
				
			||||||
    // # [ 'FRESH', 'FRESH', undefined, index: 0, input: 'FRESH' ]
 | 
					 | 
				
			||||||
    // if not matches
 | 
					 | 
				
			||||||
    //   @err HMSTATUS.invalidSchemaVersion, data: opts.format.trim(), quit: true
 | 
					 | 
				
			||||||
    // targetSchema = matches[1]
 | 
					 | 
				
			||||||
    // targetVer = matches[2] || '1'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // If any errors have occurred this early, we're done.
 | 
					 | 
				
			||||||
    if (this.hasError()) {
 | 
					 | 
				
			||||||
      this.reject(this.errorCode);
 | 
					 | 
				
			||||||
      return null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    // Map each source resume to the converted destination resume
 | 
					 | 
				
			||||||
    results = _.map(srcs, function(src, idx) {
 | 
					    results = _.map(srcs, function(src, idx) {
 | 
				
			||||||
      var r;
 | 
					      var r;
 | 
				
			||||||
      // Convert each resume in turn
 | 
					      if (opts.assert && this.hasError()) {
 | 
				
			||||||
      r = _convertOne.call(this, src, dst, idx, fmtUp);
 | 
					        return {};
 | 
				
			||||||
      // Handle conversion errors
 | 
					      }
 | 
				
			||||||
 | 
					      r = _convertOne.call(this, src, dst, idx);
 | 
				
			||||||
      if (r.fluenterror) {
 | 
					      if (r.fluenterror) {
 | 
				
			||||||
        r.quit = opts.assert;
 | 
					        r.quit = opts.assert;
 | 
				
			||||||
        this.err(r.fluenterror, r);
 | 
					        this.err(r.fluenterror, r);
 | 
				
			||||||
@@ -102,63 +85,29 @@
 | 
				
			|||||||
    return results;
 | 
					    return results;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _convertOne = function(src, dst, idx, targetSchema) {
 | 
					
 | 
				
			||||||
    var err, rez, rinfo, srcFmt, targetFormat;
 | 
					  /** Private workhorse method. Convert a single resume. */
 | 
				
			||||||
    // Load the resume
 | 
					
 | 
				
			||||||
 | 
					  _convertOne = function(src, dst, idx) {
 | 
				
			||||||
 | 
					    var rinfo, s, srcFmt, targetFormat;
 | 
				
			||||||
    rinfo = ResumeFactory.loadOne(src, {
 | 
					    rinfo = ResumeFactory.loadOne(src, {
 | 
				
			||||||
      format: null,
 | 
					      format: null,
 | 
				
			||||||
      objectify: true,
 | 
					      objectify: true
 | 
				
			||||||
      inner: {
 | 
					 | 
				
			||||||
        privatize: false
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // If a load error occurs, report it and move on to the next file (if any)
 | 
					 | 
				
			||||||
    if (rinfo.fluenterror) {
 | 
					    if (rinfo.fluenterror) {
 | 
				
			||||||
      this.stat(HMEVENT.beforeConvert, {
 | 
					 | 
				
			||||||
        srcFile: src, //rinfo.file
 | 
					 | 
				
			||||||
        srcFmt: '???',
 | 
					 | 
				
			||||||
        dstFile: dst[idx],
 | 
					 | 
				
			||||||
        dstFmt: '???',
 | 
					 | 
				
			||||||
        error: true
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      //@err rinfo.fluenterror, rinfo
 | 
					 | 
				
			||||||
      return rinfo;
 | 
					      return rinfo;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Determine the resume's SOURCE format
 | 
					    s = rinfo.rez;
 | 
				
			||||||
    // TODO: replace with detector component
 | 
					    srcFmt = ((s.basics && s.basics.imp) || s.imp).orgFormat === 'JRS' ? 'JRS' : 'FRESH';
 | 
				
			||||||
    rez = rinfo.rez;
 | 
					    targetFormat = srcFmt === 'JRS' ? 'FRESH' : 'JRS';
 | 
				
			||||||
    srcFmt = '';
 | 
					 | 
				
			||||||
    if (rez.meta && rez.meta.format) { //&& rez.meta.format.substr(0, 5).toUpperCase() == 'FRESH'
 | 
					 | 
				
			||||||
      srcFmt = 'FRESH';
 | 
					 | 
				
			||||||
    } else if (rez.basics) {
 | 
					 | 
				
			||||||
      srcFmt = 'JRS';
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      rinfo.fluenterror = HMSTATUS.unknownSchema;
 | 
					 | 
				
			||||||
      return rinfo;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    // Determine the TARGET format for the conversion
 | 
					 | 
				
			||||||
    targetFormat = targetSchema || (srcFmt === 'JRS' ? 'FRESH' : 'JRS');
 | 
					 | 
				
			||||||
    // Fire the beforeConvert event
 | 
					 | 
				
			||||||
    this.stat(HMEVENT.beforeConvert, {
 | 
					    this.stat(HMEVENT.beforeConvert, {
 | 
				
			||||||
      srcFile: rinfo.file,
 | 
					      srcFile: rinfo.file,
 | 
				
			||||||
      srcFmt: srcFmt,
 | 
					      srcFmt: srcFmt,
 | 
				
			||||||
      dstFile: dst[idx],
 | 
					      dstFile: dst[idx],
 | 
				
			||||||
      dstFmt: targetFormat
 | 
					      dstFmt: targetFormat
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    try {
 | 
					    s.saveAs(dst[idx], targetFormat);
 | 
				
			||||||
      // Save it to the destination format
 | 
					    return s;
 | 
				
			||||||
      rez.saveAs(dst[idx], targetFormat);
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
      err = error;
 | 
					 | 
				
			||||||
      if (err.badVer) {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
          fluenterror: HMSTATUS.invalidSchemaVersion,
 | 
					 | 
				
			||||||
          quit: true,
 | 
					 | 
				
			||||||
          data: err.badVer
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return rez;
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										47
									
								
								dist/verbs/create.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								dist/verbs/create.js
									
									
									
									
										vendored
									
									
								
							@@ -1,12 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Implementation of the 'create' verb for HackMyResume.
 | 
				
			||||||
 | 
					@module verbs/create
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var CreateVerb, HMEVENT, HMSTATUS, MKDIRP, PATH, Verb, _, _create, _createOne, chalk,
 | 
				
			||||||
  Implementation of the 'create' verb for HackMyResume.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module verbs/create
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** Create a new empty resume in either FRESH or JRS format. */
 | 
					 | 
				
			||||||
  /** Create a single new resume */
 | 
					 | 
				
			||||||
  var CreateVerb, HMEVENT, HMSTATUS, MKDIRP, PATH, Verb, _, _create, _createOne, chalk;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  MKDIRP = require('mkdirp');
 | 
					  MKDIRP = require('mkdirp');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -22,12 +24,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  HMEVENT = require('../core/event-codes');
 | 
					  HMEVENT = require('../core/event-codes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = CreateVerb = class CreateVerb extends Verb {
 | 
					  module.exports = CreateVerb = (function(superClass) {
 | 
				
			||||||
    constructor() {
 | 
					    extend(CreateVerb, superClass);
 | 
				
			||||||
      super('new', _create);
 | 
					
 | 
				
			||||||
 | 
					    function CreateVerb() {
 | 
				
			||||||
 | 
					      CreateVerb.__super__.constructor.call(this, 'new', _create);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return CreateVerb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(Verb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Create a new empty resume in either FRESH or JRS format. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _create = function(src, dst, opts) {
 | 
					  _create = function(src, dst, opts) {
 | 
				
			||||||
    var results;
 | 
					    var results;
 | 
				
			||||||
@@ -57,8 +66,11 @@
 | 
				
			|||||||
    return results;
 | 
					    return results;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Create a single new resume */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _createOne = function(t, opts) {
 | 
					  _createOne = function(t, opts) {
 | 
				
			||||||
    var RezClass, err, newRez, ret, safeFmt;
 | 
					    var RezClass, newRez, ret, safeFmt;
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      ret = null;
 | 
					      ret = null;
 | 
				
			||||||
      safeFmt = opts.format.toUpperCase();
 | 
					      safeFmt = opts.format.toUpperCase();
 | 
				
			||||||
@@ -66,16 +78,15 @@
 | 
				
			|||||||
        fmt: safeFmt,
 | 
					        fmt: safeFmt,
 | 
				
			||||||
        file: t
 | 
					        file: t
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      MKDIRP.sync(PATH.dirname(t)); // Ensure dest folder exists;
 | 
					      MKDIRP.sync(PATH.dirname(t));
 | 
				
			||||||
      RezClass = require('../core/' + safeFmt.toLowerCase() + '-resume');
 | 
					      RezClass = require('../core/' + safeFmt.toLowerCase() + '-resume');
 | 
				
			||||||
      newRez = RezClass.default();
 | 
					      newRez = RezClass["default"]();
 | 
				
			||||||
      newRez.save(t);
 | 
					      newRez.save(t);
 | 
				
			||||||
      ret = newRez;
 | 
					      ret = newRez;
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (_error) {
 | 
				
			||||||
      err = error;
 | 
					 | 
				
			||||||
      ret = {
 | 
					      ret = {
 | 
				
			||||||
        fluenterror: HMSTATUS.createError,
 | 
					        fluenterror: HMSTATUS.createError,
 | 
				
			||||||
        inner: err
 | 
					        inner: _error
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    } finally {
 | 
					    } finally {
 | 
				
			||||||
      this.stat(HMEVENT.afterCreate, {
 | 
					      this.stat(HMEVENT.afterCreate, {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										44
									
								
								dist/verbs/peek.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								dist/verbs/peek.js
									
									
									
									
										vendored
									
									
								
							@@ -1,12 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Implementation of the 'peek' verb for HackMyResume.
 | 
				
			||||||
 | 
					@module verbs/peek
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var HMEVENT, HMSTATUS, PeekVerb, Verb, _, __, _peek, _peekOne, safeLoadJSON,
 | 
				
			||||||
  Implementation of the 'peek' verb for HackMyResume.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module verbs/peek
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /** Peek at a resume, resume section, or resume field. */
 | 
					 | 
				
			||||||
  /** Peek at a single resume, resume section, or resume field. */
 | 
					 | 
				
			||||||
  var HMEVENT, HMSTATUS, PeekVerb, Verb, _, __, _peek, _peekOne, safeLoadJSON;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Verb = require('../verbs/verb');
 | 
					  Verb = require('../verbs/verb');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -20,12 +22,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  HMEVENT = require('../core/event-codes');
 | 
					  HMEVENT = require('../core/event-codes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module.exports = PeekVerb = class PeekVerb extends Verb {
 | 
					  module.exports = PeekVerb = (function(superClass) {
 | 
				
			||||||
    constructor() {
 | 
					    extend(PeekVerb, superClass);
 | 
				
			||||||
      super('peek', _peek);
 | 
					
 | 
				
			||||||
 | 
					    function PeekVerb() {
 | 
				
			||||||
 | 
					      PeekVerb.__super__.constructor.call(this, 'peek', _peek);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return PeekVerb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(Verb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Peek at a resume, resume section, or resume field. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _peek = function(src, dst, opts) {
 | 
					  _peek = function(src, dst, opts) {
 | 
				
			||||||
    var objPath, results;
 | 
					    var objPath, results;
 | 
				
			||||||
@@ -45,8 +54,6 @@
 | 
				
			|||||||
      if (tgt.error) {
 | 
					      if (tgt.error) {
 | 
				
			||||||
        this.setError(tgt.error.fluenterror, tgt.error);
 | 
					        this.setError(tgt.error.fluenterror, tgt.error);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      //tgt.error.quit = opts.assert
 | 
					 | 
				
			||||||
      //@err tgt.error.fluenterror, tgt.error
 | 
					 | 
				
			||||||
      return tgt;
 | 
					      return tgt;
 | 
				
			||||||
    }, this);
 | 
					    }, this);
 | 
				
			||||||
    if (this.hasError() && !opts.assert) {
 | 
					    if (this.hasError() && !opts.assert) {
 | 
				
			||||||
@@ -57,23 +64,23 @@
 | 
				
			|||||||
    return results;
 | 
					    return results;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Peek at a single resume, resume section, or resume field. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _peekOne = function(t, objPath) {
 | 
					  _peekOne = function(t, objPath) {
 | 
				
			||||||
    var errCode, obj, pkgError, tgt;
 | 
					    var errCode, obj, pkgError, tgt;
 | 
				
			||||||
    this.stat(HMEVENT.beforePeek, {
 | 
					    this.stat(HMEVENT.beforePeek, {
 | 
				
			||||||
      file: t,
 | 
					      file: t,
 | 
				
			||||||
      target: objPath
 | 
					      target: objPath
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // Load the input file JSON 1st
 | 
					 | 
				
			||||||
    obj = safeLoadJSON(t);
 | 
					    obj = safeLoadJSON(t);
 | 
				
			||||||
    // Fetch the requested object path (or the entire file)
 | 
					 | 
				
			||||||
    tgt = null;
 | 
					    tgt = null;
 | 
				
			||||||
    if (!obj.ex) {
 | 
					    if (!obj.ex) {
 | 
				
			||||||
      tgt = objPath ? __.get(obj.json, objPath) : obj.json;
 | 
					      tgt = objPath ? __.get(obj.json, objPath) : obj.json;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    //# safeLoadJSON can only return a READ error or a PARSE error
 | 
					 | 
				
			||||||
    pkgError = null;
 | 
					    pkgError = null;
 | 
				
			||||||
    if (obj.ex) {
 | 
					    if (obj.ex) {
 | 
				
			||||||
      errCode = obj.ex.op === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError;
 | 
					      errCode = obj.ex.operation === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError;
 | 
				
			||||||
      if (errCode === HMSTATUS.readError) {
 | 
					      if (errCode === HMSTATUS.readError) {
 | 
				
			||||||
        obj.ex.quiet = true;
 | 
					        obj.ex.quiet = true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -82,7 +89,6 @@
 | 
				
			|||||||
        inner: obj.ex
 | 
					        inner: obj.ex
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Fire the 'afterPeek' event with collected info
 | 
					 | 
				
			||||||
    this.stat(HMEVENT.afterPeek, {
 | 
					    this.stat(HMEVENT.afterPeek, {
 | 
				
			||||||
      file: t,
 | 
					      file: t,
 | 
				
			||||||
      requested: objPath,
 | 
					      requested: objPath,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										69
									
								
								dist/verbs/validate.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										69
									
								
								dist/verbs/validate.js
									
									
									
									
										vendored
									
									
								
							@@ -1,21 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Implementation of the 'validate' verb for HackMyResume.
 | 
				
			||||||
 | 
					@module verbs/validate
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					  var FS, HMEVENT, HMSTATUS, ResumeFactory, SyntaxErrorEx, ValidateVerb, Verb, _, _validate, _validateOne, chalk, safeLoadJSON,
 | 
				
			||||||
  Implementation of the 'validate' verb for HackMyResume.
 | 
					    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
 | 
				
			||||||
  @module verbs/validate
 | 
					    hasProp = {}.hasOwnProperty;
 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Validate a single resume.
 | 
					 | 
				
			||||||
  @returns {
 | 
					 | 
				
			||||||
  file: <fileName>,
 | 
					 | 
				
			||||||
  isValid: <validFlag>,
 | 
					 | 
				
			||||||
  status: <validationStatus>,
 | 
					 | 
				
			||||||
  violations: <validationErrors>,
 | 
					 | 
				
			||||||
  schema: <schemaType>,
 | 
					 | 
				
			||||||
  error: <errorObject>
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var FS, HMEVENT, HMSTATUS, ResumeFactory, SyntaxErrorEx, ValidateVerb, Verb, _, _validate, _validateOne, chalk, safeLoadJSON;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FS = require('fs');
 | 
					  FS = require('fs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -35,15 +28,20 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  safeLoadJSON = require('../utils/safe-json-loader');
 | 
					  safeLoadJSON = require('../utils/safe-json-loader');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** An invokable resume validation command. */
 | 
					  /** An invokable resume validation command. */
 | 
				
			||||||
  module.exports = ValidateVerb = class ValidateVerb extends Verb {
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					  module.exports = ValidateVerb = (function(superClass) {
 | 
				
			||||||
      super('validate', _validate);
 | 
					    extend(ValidateVerb, superClass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function ValidateVerb() {
 | 
				
			||||||
 | 
					      ValidateVerb.__super__.constructor.call(this, 'validate', _validate);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return ValidateVerb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })(Verb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Validate 1 to N resumes in FRESH or JSON Resume format.
 | 
					 | 
				
			||||||
  _validate = function(sources, unused, opts) {
 | 
					  _validate = function(sources, unused, opts) {
 | 
				
			||||||
    var results, schemas, validator;
 | 
					    var results, schemas, validator;
 | 
				
			||||||
    if (!sources || !sources.length) {
 | 
					    if (!sources || !sources.length) {
 | 
				
			||||||
@@ -54,7 +52,7 @@
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    validator = require('is-my-json-valid');
 | 
					    validator = require('is-my-json-valid');
 | 
				
			||||||
    schemas = {
 | 
					    schemas = {
 | 
				
			||||||
      fresh: require('fresh-resume-schema'),
 | 
					      fresh: require('fresca'),
 | 
				
			||||||
      jars: require('../core/resume.json')
 | 
					      jars: require('../core/resume.json')
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    results = _.map(sources, function(t) {
 | 
					    results = _.map(sources, function(t) {
 | 
				
			||||||
@@ -73,8 +71,21 @@
 | 
				
			|||||||
    return results;
 | 
					    return results;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					  Validate a single resume.
 | 
				
			||||||
 | 
					  @returns {
 | 
				
			||||||
 | 
					    file: <fileName>,
 | 
				
			||||||
 | 
					    isValid: <validFlag>,
 | 
				
			||||||
 | 
					    status: <validationStatus>,
 | 
				
			||||||
 | 
					    violations: <validationErrors>,
 | 
				
			||||||
 | 
					    schema: <schemaType>,
 | 
				
			||||||
 | 
					    error: <errorObject>
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _validateOne = function(t, validator, schemas, opts) {
 | 
					  _validateOne = function(t, validator, schemas, opts) {
 | 
				
			||||||
    var err, errCode, obj, ret, validate;
 | 
					    var errCode, obj, ret, validate;
 | 
				
			||||||
    ret = {
 | 
					    ret = {
 | 
				
			||||||
      file: t,
 | 
					      file: t,
 | 
				
			||||||
      isValid: false,
 | 
					      isValid: false,
 | 
				
			||||||
@@ -82,7 +93,6 @@
 | 
				
			|||||||
      schema: '-----'
 | 
					      schema: '-----'
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      // Read and parse the resume JSON. Won't throw.
 | 
					 | 
				
			||||||
      obj = safeLoadJSON(t);
 | 
					      obj = safeLoadJSON(t);
 | 
				
			||||||
      if (!obj.ex) {
 | 
					      if (!obj.ex) {
 | 
				
			||||||
        if (obj.json.basics) {
 | 
					        if (obj.json.basics) {
 | 
				
			||||||
@@ -101,8 +111,7 @@
 | 
				
			|||||||
          ret.violations = validate.errors;
 | 
					          ret.violations = validate.errors;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        // If failure, package JSON read/parse errors
 | 
					        if (obj.ex.operation === 'parse') {
 | 
				
			||||||
        if (obj.ex.op === 'parse') {
 | 
					 | 
				
			||||||
          errCode = HMSTATUS.parseError;
 | 
					          errCode = HMSTATUS.parseError;
 | 
				
			||||||
          ret.status = 'broken';
 | 
					          ret.status = 'broken';
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@@ -115,12 +124,10 @@
 | 
				
			|||||||
          quiet: errCode === HMSTATUS.readError
 | 
					          quiet: errCode === HMSTATUS.readError
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (_error) {
 | 
				
			||||||
      err = error;
 | 
					 | 
				
			||||||
      // Package any unexpected exceptions
 | 
					 | 
				
			||||||
      ret.error = {
 | 
					      ret.error = {
 | 
				
			||||||
        fluenterror: HMSTATUS.validateError,
 | 
					        fluenterror: HMSTATUS.validateError,
 | 
				
			||||||
        inner: err
 | 
					        inner: _error
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.stat(HMEVENT.afterValidate, ret);
 | 
					    this.stat(HMEVENT.afterValidate, ret);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										72
									
								
								dist/verbs/verb.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										72
									
								
								dist/verbs/verb.js
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					Definition of the Verb class.
 | 
				
			||||||
 | 
					@module verbs/verb
 | 
				
			||||||
 | 
					@license MIT. See LICENSE.md for details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
  Definition of the Verb class.
 | 
					 | 
				
			||||||
  @module verbs/verb
 | 
					 | 
				
			||||||
  @license MIT. See LICENSE.md for details.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  var EVENTS, HMEVENT, Promise, Verb;
 | 
					  var EVENTS, HMEVENT, Promise, Verb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  EVENTS = require('events');
 | 
					  EVENTS = require('events');
 | 
				
			||||||
@@ -12,57 +14,65 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  Promise = require('pinkie-promise');
 | 
					  Promise = require('pinkie-promise');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
  An abstract invokable verb.
 | 
					  An abstract invokable verb.
 | 
				
			||||||
  Provides base class functionality for verbs. Provide common services such as
 | 
					  Provides base class functionality for verbs. Provide common services such as
 | 
				
			||||||
  error handling, event management, and promise support.
 | 
					  error handling, event management, and promise support.
 | 
				
			||||||
  @class Verb
 | 
					  @class Verb
 | 
				
			||||||
  */
 | 
					   */
 | 
				
			||||||
  module.exports = Verb = class Verb {
 | 
					
 | 
				
			||||||
 | 
					  module.exports = Verb = (function() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Constructor. Automatically called at creation. */
 | 
					    /** Constructor. Automatically called at creation. */
 | 
				
			||||||
    constructor(moniker, workhorse) {
 | 
					    function Verb(moniker, workhorse) {
 | 
				
			||||||
      this.moniker = moniker;
 | 
					      this.moniker = moniker;
 | 
				
			||||||
      this.workhorse = workhorse;
 | 
					      this.workhorse = workhorse;
 | 
				
			||||||
      this.emitter = new EVENTS.EventEmitter();
 | 
					      this.emitter = new EVENTS.EventEmitter();
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Invoke the command. */
 | 
					    /** Invoke the command. */
 | 
				
			||||||
    invoke() {
 | 
					
 | 
				
			||||||
 | 
					    Verb.prototype.invoke = function() {
 | 
				
			||||||
      var argsArray, that;
 | 
					      var argsArray, that;
 | 
				
			||||||
      // Sent the 'begin' notification for this verb
 | 
					 | 
				
			||||||
      this.stat(HMEVENT.begin, {
 | 
					      this.stat(HMEVENT.begin, {
 | 
				
			||||||
        cmd: this.moniker
 | 
					        cmd: this.moniker
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      // Prepare command arguments
 | 
					 | 
				
			||||||
      argsArray = Array.prototype.slice.call(arguments);
 | 
					      argsArray = Array.prototype.slice.call(arguments);
 | 
				
			||||||
      // Create a promise for this verb instance
 | 
					 | 
				
			||||||
      that = this;
 | 
					      that = this;
 | 
				
			||||||
      return this.promise = new Promise(function(res, rej) {
 | 
					      return this.promise = new Promise(function(res, rej) {
 | 
				
			||||||
        that.resolve = res;
 | 
					        that.resolve = res;
 | 
				
			||||||
        that.reject = rej;
 | 
					        that.reject = rej;
 | 
				
			||||||
        that.workhorse.apply(that, argsArray);
 | 
					        that.workhorse.apply(that, argsArray);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Forward subscriptions to the event emitter. */
 | 
					    /** Forward subscriptions to the event emitter. */
 | 
				
			||||||
    on() {
 | 
					
 | 
				
			||||||
 | 
					    Verb.prototype.on = function() {
 | 
				
			||||||
      return this.emitter.on.apply(this.emitter, arguments);
 | 
					      return this.emitter.on.apply(this.emitter, arguments);
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Fire an arbitrary event, scoped to "hmr:". */
 | 
					    /** Fire an arbitrary event, scoped to "hmr:". */
 | 
				
			||||||
    fire(evtName, payload) {
 | 
					
 | 
				
			||||||
 | 
					    Verb.prototype.fire = function(evtName, payload) {
 | 
				
			||||||
      payload = payload || {};
 | 
					      payload = payload || {};
 | 
				
			||||||
      payload.cmd = this.moniker;
 | 
					      payload.cmd = this.moniker;
 | 
				
			||||||
      this.emitter.emit('hmr:' + evtName, payload);
 | 
					      this.emitter.emit('hmr:' + evtName, payload);
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Handle an error condition. */
 | 
					    /** Handle an error condition. */
 | 
				
			||||||
    err(errorCode, payload, hot) {
 | 
					
 | 
				
			||||||
 | 
					    Verb.prototype.err = function(errorCode, payload, hot) {
 | 
				
			||||||
      payload = payload || {};
 | 
					      payload = payload || {};
 | 
				
			||||||
      payload.sub = payload.fluenterror = errorCode;
 | 
					      payload.sub = payload.fluenterror = errorCode;
 | 
				
			||||||
      payload.throw = hot;
 | 
					      payload["throw"] = hot;
 | 
				
			||||||
      this.setError(errorCode, payload);
 | 
					      this.setError(errorCode, payload);
 | 
				
			||||||
      if (payload.quit) {
 | 
					      if (payload.quit) {
 | 
				
			||||||
        this.reject(errorCode);
 | 
					        this.reject(errorCode);
 | 
				
			||||||
@@ -72,28 +82,36 @@
 | 
				
			|||||||
        throw payload;
 | 
					        throw payload;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Fire the 'hmr:status' error event. */
 | 
					    /** Fire the 'hmr:status' error event. */
 | 
				
			||||||
    stat(subEvent, payload) {
 | 
					
 | 
				
			||||||
 | 
					    Verb.prototype.stat = function(subEvent, payload) {
 | 
				
			||||||
      payload = payload || {};
 | 
					      payload = payload || {};
 | 
				
			||||||
      payload.sub = subEvent;
 | 
					      payload.sub = subEvent;
 | 
				
			||||||
      this.fire('status', payload);
 | 
					      this.fire('status', payload);
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Has an error occurred during this verb invocation? */
 | 
					    /** Has an error occurred during this verb invocation? */
 | 
				
			||||||
    hasError() {
 | 
					
 | 
				
			||||||
 | 
					    Verb.prototype.hasError = function() {
 | 
				
			||||||
      return this.errorCode || this.errorObj;
 | 
					      return this.errorCode || this.errorObj;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Associate error info with the invocation. */
 | 
					    /** Associate error info with the invocation. */
 | 
				
			||||||
    setError(code, obj) {
 | 
					
 | 
				
			||||||
 | 
					    Verb.prototype.setError = function(code, obj) {
 | 
				
			||||||
      this.errorCode = code;
 | 
					      this.errorCode = code;
 | 
				
			||||||
      this.errorObj = obj;
 | 
					      this.errorObj = obj;
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					    return Verb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}).call(this);
 | 
					}).call(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2800
									
								
								npm-shrinkwrap.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2800
									
								
								npm-shrinkwrap.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										58
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								package.json
									
									
									
									
									
								
							@@ -1,13 +1,13 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "hackmyresume",
 | 
					  "name": "hackmyresume",
 | 
				
			||||||
  "version": "1.9.0-beta",
 | 
					  "version": "1.8.0",
 | 
				
			||||||
  "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.",
 | 
					  "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": {
 | 
					  "repository": {
 | 
				
			||||||
    "type": "git",
 | 
					    "type": "git",
 | 
				
			||||||
    "url": "https://github.com/hacksalot/HackMyResume.git"
 | 
					    "url": "https://github.com/hacksalot/HackMyResume.git"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "test": "grunt clean:test && mocha --exit",
 | 
					    "test": "grunt clean:test && mocha",
 | 
				
			||||||
    "grunt": "grunt"
 | 
					    "grunt": "grunt"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "keywords": [
 | 
					  "keywords": [
 | 
				
			||||||
@@ -31,7 +31,6 @@
 | 
				
			|||||||
  "author": "hacksalot <hacksalot@indevious.com> (https://github.com/hacksalot)",
 | 
					  "author": "hacksalot <hacksalot@indevious.com> (https://github.com/hacksalot)",
 | 
				
			||||||
  "contributors": [
 | 
					  "contributors": [
 | 
				
			||||||
    "aruberto (https://github.com/aruberto)",
 | 
					    "aruberto (https://github.com/aruberto)",
 | 
				
			||||||
    "daniele-rapagnani (https://github.com/daniele-rapagnani)",
 | 
					 | 
				
			||||||
    "jjanusch (https://github.com/driftdev)",
 | 
					    "jjanusch (https://github.com/driftdev)",
 | 
				
			||||||
    "robertmain (https://github.com/robertmain)",
 | 
					    "robertmain (https://github.com/robertmain)",
 | 
				
			||||||
    "tomheon (https://github.com/tomheon)",
 | 
					    "tomheon (https://github.com/tomheon)",
 | 
				
			||||||
@@ -41,41 +40,39 @@
 | 
				
			|||||||
  "license": "MIT",
 | 
					  "license": "MIT",
 | 
				
			||||||
  "preferGlobal": "true",
 | 
					  "preferGlobal": "true",
 | 
				
			||||||
  "bugs": {
 | 
					  "bugs": {
 | 
				
			||||||
    "url": "https://github.com/hacksalot/HackMyResume/issues"
 | 
					    "url": "https://github.com/JuanCanham/HackMyResume/issues"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "bin": {
 | 
					  "bin": {
 | 
				
			||||||
    "hackmyresume": "dist/cli/index.js"
 | 
					    "hackmyresume": "dist/cli/index.js"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "main": "dist/index.js",
 | 
					  "main": "dist/index.js",
 | 
				
			||||||
  "homepage": "https://github.com/hacksalot/HackMyResume",
 | 
					  "homepage": "https://github.com/JuanCanham/HackMyResume",
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "chalk": "^2.3.1",
 | 
					    "chalk": "^1.1.1",
 | 
				
			||||||
    "commander": "^2.9.0",
 | 
					    "commander": "^2.9.0",
 | 
				
			||||||
    "copy": "^0.3.1",
 | 
					    "copy": "^0.1.3",
 | 
				
			||||||
    "escape-latex": "^1.0.0",
 | 
					    "escape-latex": "^0.1.2",
 | 
				
			||||||
    "extend": "^3.0.0",
 | 
					    "extend": "^3.0.0",
 | 
				
			||||||
    "fresh-jrs-converter": "^1.0.0",
 | 
					    "fresca": "~0.6.0",
 | 
				
			||||||
    "fresh-resume-schema": "^1.0.0-beta",
 | 
					    "fresh-jrs-converter": "^0.2.2",
 | 
				
			||||||
    "fresh-resume-starter": "^0.3.1",
 | 
					    "fresh-resume-starter": "^0.2.2",
 | 
				
			||||||
    "fresh-resume-validator": "^0.2.0",
 | 
					    "fresh-themes": "git+https://git.juancanham.com/JuanCanham/fresh-themes.git#feature/certifications",
 | 
				
			||||||
    "fresh-themes": "^0.17.0-beta",
 | 
					    "fs-extra": "^0.26.4",
 | 
				
			||||||
    "fs-extra": "^5.0.0",
 | 
					 | 
				
			||||||
    "glob": "^7.1.2",
 | 
					 | 
				
			||||||
    "handlebars": "^4.0.5",
 | 
					    "handlebars": "^4.0.5",
 | 
				
			||||||
    "html": "^1.0.0",
 | 
					    "html": "0.0.10",
 | 
				
			||||||
    "is-my-json-valid": "^2.12.4",
 | 
					    "is-my-json-valid": "^2.12.4",
 | 
				
			||||||
    "json-lint": "^0.1.0",
 | 
					    "json-lint": "^0.1.0",
 | 
				
			||||||
    "jsonlint": "^1.6.2",
 | 
					    "jsonlint": "^1.6.2",
 | 
				
			||||||
    "lodash": "^4.17.5",
 | 
					    "lodash": "^3.10.1",
 | 
				
			||||||
    "marked": "^0.3.5",
 | 
					    "marked": "^0.3.5",
 | 
				
			||||||
    "mkdirp": "^0.5.1",
 | 
					    "mkdirp": "^0.5.1",
 | 
				
			||||||
    "moment": "^2.11.1",
 | 
					    "moment": "^2.11.1",
 | 
				
			||||||
    "parse-filepath": "^1.0.2",
 | 
					    "parse-filepath": "^0.6.3",
 | 
				
			||||||
    "path-exists": "^3.0.0",
 | 
					    "path-exists": "^2.1.0",
 | 
				
			||||||
    "pinkie-promise": "^2.0.0",
 | 
					    "pinkie-promise": "^2.0.0",
 | 
				
			||||||
    "printf": "^0.2.3",
 | 
					    "printf": "^0.2.3",
 | 
				
			||||||
    "recursive-readdir-sync": "^1.0.6",
 | 
					    "recursive-readdir-sync": "^1.0.6",
 | 
				
			||||||
    "simple-html-tokenizer": "^0.4.3",
 | 
					    "simple-html-tokenizer": "^0.2.1",
 | 
				
			||||||
    "slash": "^1.0.0",
 | 
					    "slash": "^1.0.0",
 | 
				
			||||||
    "string-padding": "^1.0.2",
 | 
					    "string-padding": "^1.0.2",
 | 
				
			||||||
    "string.prototype.endswith": "^0.2.0",
 | 
					    "string.prototype.endswith": "^0.2.0",
 | 
				
			||||||
@@ -84,26 +81,27 @@
 | 
				
			|||||||
    "underscore": "^1.8.3",
 | 
					    "underscore": "^1.8.3",
 | 
				
			||||||
    "word-wrap": "^1.1.0",
 | 
					    "word-wrap": "^1.1.0",
 | 
				
			||||||
    "xml-escape": "^1.0.0",
 | 
					    "xml-escape": "^1.0.0",
 | 
				
			||||||
    "yamljs": "^0.3.0"
 | 
					    "yamljs": "^0.2.4"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "chai": "*",
 | 
					    "chai": "*",
 | 
				
			||||||
    "chai-as-promised": "^7.1.1",
 | 
					    "dir-compare": "0.0.2",
 | 
				
			||||||
    "dir-compare": "^1.4.0",
 | 
					    "fresh-test-resumes": "^0.7.0",
 | 
				
			||||||
    "fresh-test-resumes": "^0.9.2",
 | 
					 | 
				
			||||||
    "fresh-test-themes": "^0.2.0",
 | 
					 | 
				
			||||||
    "fresh-theme-underscore": "^0.1.1",
 | 
					 | 
				
			||||||
    "grunt": "*",
 | 
					    "grunt": "*",
 | 
				
			||||||
    "grunt-contrib-clean": "^1.1.0",
 | 
					    "grunt-cli": "^0.1.13",
 | 
				
			||||||
    "grunt-contrib-coffee": "^2.0.0",
 | 
					    "grunt-contrib-clean": "^0.7.0",
 | 
				
			||||||
    "grunt-contrib-copy": "^1.0.0",
 | 
					    "grunt-contrib-coffee": "^0.13.0",
 | 
				
			||||||
    "grunt-eslint": "^20.1.0",
 | 
					    "grunt-contrib-copy": "^0.8.2",
 | 
				
			||||||
 | 
					    "grunt-contrib-jshint": "^0.11.3",
 | 
				
			||||||
 | 
					    "grunt-contrib-yuidoc": "^0.10.0",
 | 
				
			||||||
 | 
					    "grunt-jsdoc": "^1.1.0",
 | 
				
			||||||
    "grunt-simple-mocha": "*",
 | 
					    "grunt-simple-mocha": "*",
 | 
				
			||||||
    "jsonresume-theme-boilerplate": "^0.1.2",
 | 
					    "jsonresume-theme-boilerplate": "^0.1.2",
 | 
				
			||||||
    "jsonresume-theme-classy": "^1.0.9",
 | 
					    "jsonresume-theme-classy": "^1.0.9",
 | 
				
			||||||
    "jsonresume-theme-modern": "0.0.18",
 | 
					    "jsonresume-theme-modern": "0.0.18",
 | 
				
			||||||
    "jsonresume-theme-sceptile": "^1.0.5",
 | 
					    "jsonresume-theme-sceptile": "^1.0.5",
 | 
				
			||||||
    "mocha": "*",
 | 
					    "mocha": "*",
 | 
				
			||||||
 | 
					    "resample": "fluentdesk/resample",
 | 
				
			||||||
    "stripcolorcodes": "^0.1.0"
 | 
					    "stripcolorcodes": "^0.1.0"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,12 +7,15 @@ Error-handling routines for HackMyResume.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HMSTATUS = require '../core/status-codes'
 | 
					HMSTATUS = require '../core/status-codes'
 | 
				
			||||||
 | 
					PKG = require '../../package.json'
 | 
				
			||||||
FS = require 'fs'
 | 
					FS = require 'fs'
 | 
				
			||||||
 | 
					FCMD = require '../index'
 | 
				
			||||||
PATH = require 'path'
 | 
					PATH = require 'path'
 | 
				
			||||||
WRAP = require 'word-wrap'
 | 
					WRAP = require 'word-wrap'
 | 
				
			||||||
M2C = require '../utils/md2chalk'
 | 
					M2C = require '../utils/md2chalk'
 | 
				
			||||||
chalk = require 'chalk'
 | 
					chalk = require 'chalk'
 | 
				
			||||||
extend = require 'extend'
 | 
					extend = require 'extend'
 | 
				
			||||||
 | 
					YAML = require 'yamljs'
 | 
				
			||||||
printf = require 'printf'
 | 
					printf = require 'printf'
 | 
				
			||||||
SyntaxErrorEx = require '../utils/syntax-error-ex'
 | 
					SyntaxErrorEx = require '../utils/syntax-error-ex'
 | 
				
			||||||
require 'string.prototype.startswith'
 | 
					require 'string.prototype.startswith'
 | 
				
			||||||
@@ -21,7 +24,7 @@ require 'string.prototype.startswith'
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
###* Error handler for HackMyResume. All errors are handled here.
 | 
					###* Error handler for HackMyResume. All errors are handled here.
 | 
				
			||||||
@class ErrorHandler ###
 | 
					@class ErrorHandler ###
 | 
				
			||||||
module.exports =
 | 
					ErrorHandler = module.exports =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  init: ( debug, assert, silent ) ->
 | 
					  init: ( debug, assert, silent ) ->
 | 
				
			||||||
    @debug = debug
 | 
					    @debug = debug
 | 
				
			||||||
@@ -54,7 +57,7 @@ module.exports =
 | 
				
			|||||||
        stack && o( chalk.gray( stack ) );
 | 
					        stack && o( chalk.gray( stack ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      # Quit if necessary
 | 
					      # Quit if necessary
 | 
				
			||||||
      if shouldExit or ex.exit
 | 
					      if shouldExit
 | 
				
			||||||
        if @debug
 | 
					        if @debug
 | 
				
			||||||
          o chalk.cyan('Exiting with error code ' + ex.fluenterror.toString())
 | 
					          o chalk.cyan('Exiting with error code ' + ex.fluenterror.toString())
 | 
				
			||||||
        if @assert
 | 
					        if @assert
 | 
				
			||||||
@@ -83,7 +86,8 @@ module.exports =
 | 
				
			|||||||
  format_custom: ( msg ) -> msg
 | 
					  format_custom: ( msg ) -> msg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_defaultLog = () -> console.log.apply console.log, arguments # eslint-disable-line no-console
 | 
					
 | 
				
			||||||
 | 
					_defaultLog = () -> console.log.apply console.log, arguments
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -106,19 +110,17 @@ assembleError = ( ex ) ->
 | 
				
			|||||||
      quit = false
 | 
					      quit = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    when HMSTATUS.resumeNotFound
 | 
					    when HMSTATUS.resumeNotFound
 | 
				
			||||||
      #msg = M2C( this.msgs.resumeNotFound.msg, 'yellow' );
 | 
					      msg = M2C( this.msgs.resumeNotFound.msg, 'yellow' );
 | 
				
			||||||
      msg += M2C(FS.readFileSync(
 | 
					 | 
				
			||||||
        PATH.resolve(__dirname, 'help/' + ex.verb + '.txt'), 'utf8' ), 'white', 'yellow')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    when HMSTATUS.missingCommand
 | 
					    when HMSTATUS.missingCommand
 | 
				
			||||||
      # msg = M2C( this.msgs.missingCommand.msg + " (", 'yellow');
 | 
					      msg = M2C( this.msgs.missingCommand.msg + " (", 'yellow');
 | 
				
			||||||
      # msg += Object.keys( FCMD.verbs ).map( (v, idx, ar) ->
 | 
					      msg += Object.keys( FCMD.verbs ).map( (v, idx, ar) ->
 | 
				
			||||||
      #   return ( if idx == ar.length - 1 then chalk.yellow('or ') else '') +
 | 
					        return ( if idx == ar.length - 1 then chalk.yellow('or ') else '') +
 | 
				
			||||||
      #     chalk.yellow.bold(v.toUpperCase());
 | 
					          chalk.yellow.bold(v.toUpperCase());
 | 
				
			||||||
      # ).join( chalk.yellow(', ')) + chalk.yellow(").\n\n");
 | 
					      ).join( chalk.yellow(', ')) + chalk.yellow(").\n\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      msg += M2C(FS.readFileSync(
 | 
					      msg += chalk.gray(FS.readFileSync(
 | 
				
			||||||
        PATH.resolve(__dirname, 'help/use.txt'), 'utf8' ), 'white', 'yellow')
 | 
					        PATH.resolve(__dirname, '../cli/use.txt'), 'utf8' ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    when HMSTATUS.invalidCommand
 | 
					    when HMSTATUS.invalidCommand
 | 
				
			||||||
      msg = printf( M2C( this.msgs.invalidCommand.msg, 'yellow'), ex.attempted )
 | 
					      msg = printf( M2C( this.msgs.invalidCommand.msg, 'yellow'), ex.attempted )
 | 
				
			||||||
@@ -176,7 +178,6 @@ assembleError = ( ex ) ->
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    when HMSTATUS.readError
 | 
					    when HMSTATUS.readError
 | 
				
			||||||
      if !ex.quiet
 | 
					      if !ex.quiet
 | 
				
			||||||
        # eslint-disable-next-line no-console
 | 
					 | 
				
			||||||
        console.error(printf( M2C(this.msgs.readError.msg, 'red'), ex.file))
 | 
					        console.error(printf( M2C(this.msgs.readError.msg, 'red'), ex.file))
 | 
				
			||||||
      msg = ex.inner.toString()
 | 
					      msg = ex.inner.toString()
 | 
				
			||||||
      etype = 'error'
 | 
					      etype = 'error'
 | 
				
			||||||
@@ -202,7 +203,6 @@ assembleError = ( ex ) ->
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    when HMSTATUS.parseError
 | 
					    when HMSTATUS.parseError
 | 
				
			||||||
      if SyntaxErrorEx.is ex.inner
 | 
					      if SyntaxErrorEx.is ex.inner
 | 
				
			||||||
        # eslint-disable-next-line no-console
 | 
					 | 
				
			||||||
        console.error printf( M2C(this.msgs.readError.msg, 'red'), ex.file )
 | 
					        console.error printf( M2C(this.msgs.readError.msg, 'red'), ex.file )
 | 
				
			||||||
        se = new SyntaxErrorEx ex, ex.raw
 | 
					        se = new SyntaxErrorEx ex, ex.raw
 | 
				
			||||||
        if se.line? and se.col?
 | 
					        if se.line? and se.col?
 | 
				
			||||||
@@ -226,42 +226,6 @@ assembleError = ( ex ) ->
 | 
				
			|||||||
      msg = printf M2C( @msgs.validateError.msg ), ex.inner.toString()
 | 
					      msg = printf M2C( @msgs.validateError.msg ), ex.inner.toString()
 | 
				
			||||||
      etype = 'error'
 | 
					      etype = 'error'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    when HMSTATUS.invalidOptionsFile
 | 
					 | 
				
			||||||
      msg = M2C @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? and se.col?
 | 
					 | 
				
			||||||
          msg += printf M2C( this.msgs.parseError.msg[0], 'red' ), se.line, se.col
 | 
					 | 
				
			||||||
        else if se.line?
 | 
					 | 
				
			||||||
          msg += printf M2C( this.msgs.parseError.msg[1], 'red' ), se.line
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          msg += M2C @msgs.parseError.msg[2], 'red'
 | 
					 | 
				
			||||||
      else if ex.inner && ex.inner.line? && ex.inner.col?
 | 
					 | 
				
			||||||
        msg += printf( M2C( this.msgs.parseError.msg[0], 'red' ), ex.inner.line, ex.inner.col)
 | 
					 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        msg += ex
 | 
					 | 
				
			||||||
      msg += @msgs.invalidOptionsFile.msg[1]
 | 
					 | 
				
			||||||
      etype = 'error'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    when HMSTATUS.optionsFileNotFound
 | 
					 | 
				
			||||||
      msg = M2C( @msgs.optionsFileNotFound.msg )
 | 
					 | 
				
			||||||
      etype = 'error'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    when HMSTATUS.unknownSchema
 | 
					 | 
				
			||||||
      msg = M2C( @msgs.unknownSchema.msg[0] )
 | 
					 | 
				
			||||||
      #msg += "\n" + M2C( @msgs.unknownSchema.msg[1], 'yellow' )
 | 
					 | 
				
			||||||
      etype = 'error'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    when HMSTATUS.themeHelperLoad
 | 
					 | 
				
			||||||
      msg = printf M2C( @msgs.themeHelperLoad.msg ), ex.glob
 | 
					 | 
				
			||||||
      etype = 'error'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    when HMSTATUS.invalidSchemaVersion
 | 
					 | 
				
			||||||
      msg = printf M2C( @msgs.invalidSchemaVersion.msg ), ex.data
 | 
					 | 
				
			||||||
      etype = 'error'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  msg: msg              # The error message to display
 | 
					  msg: msg              # The error message to display
 | 
				
			||||||
  withStack: withStack  # Whether to include the stack
 | 
					  withStack: withStack  # Whether to include the stack
 | 
				
			||||||
  quit: quit
 | 
					  quit: quit
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,25 +0,0 @@
 | 
				
			|||||||
**analyze** | Analyze a resume for statistical insight
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume ANALYZE <resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   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:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.**
 | 
					 | 
				
			||||||
@@ -1,69 +0,0 @@
 | 
				
			|||||||
**build** | Generate themed resumes in multiple formats
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume BUILD <resume> TO <target> [--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:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<target>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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 <theme-name-or-path>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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 <engine>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.
 | 
					 | 
				
			||||||
@@ -1,33 +0,0 @@
 | 
				
			|||||||
**convert** | Convert resumes between FRESH and JRS formats
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume CONVERT <resume> TO <target> [--format]**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   The CONVERT command converts one or more resume documents
 | 
					 | 
				
			||||||
   between the FRESH Resume Schema and JSON Resume formats.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Parameters:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Path to a FRESH or JRS resume. Multiple resumes can be
 | 
					 | 
				
			||||||
      specified.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<targets>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      The path of the converted resume. Multiple resumes can
 | 
					 | 
				
			||||||
      be specified, one per provided input resume.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Options:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **--format -f <fmt>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.
 | 
					 | 
				
			||||||
@@ -1,23 +0,0 @@
 | 
				
			|||||||
**help** | View help on a specific HackMyResume command
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume HELP [<command>]**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   The HELP command displays help information for a specific
 | 
					 | 
				
			||||||
   HackMyResume command, including the HELP command itself.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Parameters:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<command>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.**
 | 
					 | 
				
			||||||
@@ -1,29 +0,0 @@
 | 
				
			|||||||
**new** | Create a new FRESH or JRS resume document
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume NEW <fileName> [--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:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<fileName>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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 <fmt>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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'.
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
**peek** | View portions of a resume from the command line
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume PEEK <resume> <at>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   The PEEK command displays a specific piece or part of the
 | 
					 | 
				
			||||||
   resume without requiring the resume to be opened in an
 | 
					 | 
				
			||||||
   editor.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Parameters:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
     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]"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<at>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.**
 | 
					 | 
				
			||||||
@@ -1,70 +0,0 @@
 | 
				
			|||||||
**HackMyResume** | A Swiss Army knife for resumes and CVs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume [--version] [--help] [--silent] [--debug]**
 | 
					 | 
				
			||||||
      **[--options] [--no-colors] <command> [<args>]**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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.
 | 
					 | 
				
			||||||
@@ -1,26 +0,0 @@
 | 
				
			|||||||
**validate** | Validate a resume for correctness
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **hackmyresume VALIDATE <resume> [--assert]**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   The VALIDATE command validates a FRESH or JRS document
 | 
					 | 
				
			||||||
   against its governing schema, verifying that the resume
 | 
					 | 
				
			||||||
   is correctly structured and formatted.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Parameters:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   **<resume>**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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.
 | 
					 | 
				
			||||||
@@ -13,8 +13,9 @@ EXTEND = require 'extend'
 | 
				
			|||||||
chalk = require 'chalk'
 | 
					chalk = require 'chalk'
 | 
				
			||||||
PATH = require 'path'
 | 
					PATH = require 'path'
 | 
				
			||||||
HMSTATUS = require '../core/status-codes'
 | 
					HMSTATUS = require '../core/status-codes'
 | 
				
			||||||
 | 
					HME = require '../core/event-codes'
 | 
				
			||||||
safeLoadJSON = require '../utils/safe-json-loader'
 | 
					safeLoadJSON = require '../utils/safe-json-loader'
 | 
				
			||||||
#StringUtils = require '../utils/string.js'
 | 
					StringUtils = require '../utils/string.js'
 | 
				
			||||||
_ = require 'underscore'
 | 
					_ = require 'underscore'
 | 
				
			||||||
OUTPUT = require './out'
 | 
					OUTPUT = require './out'
 | 
				
			||||||
PAD = require 'string-padding'
 | 
					PAD = require 'string-padding'
 | 
				
			||||||
@@ -36,12 +37,9 @@ line interface as a single method accepting a parameter array.
 | 
				
			|||||||
@param rawArgs {Array} An array of command-line parameters. Will either be
 | 
					@param rawArgs {Array} An array of command-line parameters. Will either be
 | 
				
			||||||
process.argv (in production) or custom parameters (in test).
 | 
					process.argv (in production) or custom parameters (in test).
 | 
				
			||||||
###
 | 
					###
 | 
				
			||||||
module.exports = ( rawArgs, exitCallback ) ->
 | 
					main = module.exports = ( rawArgs, exitCallback ) ->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  initInfo = initialize( rawArgs, exitCallback )
 | 
					  initInfo = initialize( rawArgs, exitCallback )
 | 
				
			||||||
  if initInfo is null
 | 
					 | 
				
			||||||
    return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  args = initInfo.args
 | 
					  args = initInfo.args
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Create the top-level (application) command...
 | 
					  # Create the top-level (application) command...
 | 
				
			||||||
@@ -83,7 +81,6 @@ module.exports = ( rawArgs, exitCallback ) ->
 | 
				
			|||||||
  program
 | 
					  program
 | 
				
			||||||
    .command('convert')
 | 
					    .command('convert')
 | 
				
			||||||
    .description('Convert a resume to/from FRESH or JSON RESUME format.')
 | 
					    .description('Convert a resume to/from FRESH or JSON RESUME format.')
 | 
				
			||||||
    .option('-f --format <fmt>', 'FRESH or JRS format and optional version', undefined)
 | 
					 | 
				
			||||||
    .action(->
 | 
					    .action(->
 | 
				
			||||||
      x = splitSrcDest.call( this );
 | 
					      x = splitSrcDest.call( this );
 | 
				
			||||||
      execute.call( this, x.src, x.dst, this.opts(), logMsg)
 | 
					      execute.call( this, x.src, x.dst, this.opts(), logMsg)
 | 
				
			||||||
@@ -94,7 +91,6 @@ module.exports = ( rawArgs, exitCallback ) ->
 | 
				
			|||||||
  program
 | 
					  program
 | 
				
			||||||
    .command('analyze')
 | 
					    .command('analyze')
 | 
				
			||||||
    .arguments('<sources...>')
 | 
					    .arguments('<sources...>')
 | 
				
			||||||
    .option('--private', 'Include resume fields marked as private', false)
 | 
					 | 
				
			||||||
    .description('Analyze one or more resumes.')
 | 
					    .description('Analyze one or more resumes.')
 | 
				
			||||||
    .action(( sources ) ->
 | 
					    .action(( sources ) ->
 | 
				
			||||||
      execute.call( this, sources, [], this.opts(), logMsg)
 | 
					      execute.call( this, sources, [], this.opts(), logMsg)
 | 
				
			||||||
@@ -106,8 +102,7 @@ module.exports = ( rawArgs, exitCallback ) ->
 | 
				
			|||||||
    .command('peek')
 | 
					    .command('peek')
 | 
				
			||||||
    .arguments('<sources...>')
 | 
					    .arguments('<sources...>')
 | 
				
			||||||
    .description('Peek at a resume field or section')
 | 
					    .description('Peek at a resume field or section')
 | 
				
			||||||
    #.action(( sources, sectionOrField ) ->
 | 
					    .action(( sources, sectionOrField ) ->
 | 
				
			||||||
    .action(( sources ) ->
 | 
					 | 
				
			||||||
      dst = if (sources && sources.length > 1) then [sources.pop()] else []
 | 
					      dst = if (sources && sources.length > 1) then [sources.pop()] else []
 | 
				
			||||||
      execute.call( this, sources, dst, this.opts(), logMsg)
 | 
					      execute.call( this, sources, dst, this.opts(), logMsg)
 | 
				
			||||||
      return
 | 
					      return
 | 
				
			||||||
@@ -123,29 +118,13 @@ module.exports = ( rawArgs, exitCallback ) ->
 | 
				
			|||||||
    .option('-p --pdf <engine>', 'PDF generation engine')
 | 
					    .option('-p --pdf <engine>', 'PDF generation engine')
 | 
				
			||||||
    .option('--no-sort', 'Sort resume sections by date', false)
 | 
					    .option('--no-sort', 'Sort resume sections by date', false)
 | 
				
			||||||
    .option('--tips', 'Display theme tips and warnings.', false)
 | 
					    .option('--tips', 'Display theme tips and warnings.', false)
 | 
				
			||||||
    .option('--private', 'Include resume fields marked as private', false)
 | 
					 | 
				
			||||||
    .option('--no-escape', 'Turn off encoding in Handlebars themes.', false)
 | 
					 | 
				
			||||||
    .description('Generate resume to multiple formats')
 | 
					    .description('Generate resume to multiple formats')
 | 
				
			||||||
    #.action(( sources, targets, options ) ->
 | 
					    .action(( sources, targets, options ) ->
 | 
				
			||||||
    .action(->
 | 
					 | 
				
			||||||
      x = splitSrcDest.call( this );
 | 
					      x = splitSrcDest.call( this );
 | 
				
			||||||
      execute.call( this, x.src, x.dst, this.opts(), logMsg)
 | 
					      execute.call( this, x.src, x.dst, this.opts(), logMsg)
 | 
				
			||||||
      return
 | 
					      return
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Create the HELP command
 | 
					 | 
				
			||||||
  program
 | 
					 | 
				
			||||||
    .command('help')
 | 
					 | 
				
			||||||
    .arguments('[command]')
 | 
					 | 
				
			||||||
    .description('Get help on a HackMyResume command')
 | 
					 | 
				
			||||||
    .action ( cmd ) ->
 | 
					 | 
				
			||||||
      cmd = cmd || 'use'
 | 
					 | 
				
			||||||
      manPage = FS.readFileSync(
 | 
					 | 
				
			||||||
        PATH.join(__dirname, 'help/' + cmd + '.txt'),
 | 
					 | 
				
			||||||
        'utf8')
 | 
					 | 
				
			||||||
      _out.log M2C(manPage, 'white', 'yellow.bold')
 | 
					 | 
				
			||||||
      return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  program.parse( args )
 | 
					  program.parse( args )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if !program.args.length
 | 
					  if !program.args.length
 | 
				
			||||||
@@ -158,16 +137,6 @@ initialize = ( ar, exitCallback ) ->
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  _exitCallback = exitCallback || process.exit
 | 
					  _exitCallback = exitCallback || process.exit
 | 
				
			||||||
  o = initOptions ar
 | 
					  o = initOptions ar
 | 
				
			||||||
  if o.ex
 | 
					 | 
				
			||||||
    _err.init false, true, false
 | 
					 | 
				
			||||||
    if( o.ex.op == 'parse' )
 | 
					 | 
				
			||||||
      _err.err
 | 
					 | 
				
			||||||
        fluenterror: if o.ex.op == 'parse' then HMSTATUS.invalidOptionsFile else HMSTATUS.optionsFileNotFound,
 | 
					 | 
				
			||||||
        inner: o.ex.inner,
 | 
					 | 
				
			||||||
        quit: true
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      _err.err fluenterror: HMSTATUS.optionsFileNotFound, inner: o.ex.inner, quit: true
 | 
					 | 
				
			||||||
    return null
 | 
					 | 
				
			||||||
  o.silent || logMsg( _title )
 | 
					  o.silent || logMsg( _title )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Emit debug prelude if --debug was specified
 | 
					  # Emit debug prelude if --debug was specified
 | 
				
			||||||
@@ -185,23 +154,25 @@ initialize = ( ar, exitCallback ) ->
 | 
				
			|||||||
  _err.init o.debug, o.assert, o.silent
 | 
					  _err.init o.debug, o.assert, o.silent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Handle invalid verbs here (a bit easier here than in commander.js)...
 | 
					  # Handle invalid verbs here (a bit easier here than in commander.js)...
 | 
				
			||||||
  if o.verb && !HMR.verbs[ o.verb ] && !HMR.alias[ o.verb ] && o.verb != 'help'
 | 
					  if o.verb && !HMR.verbs[ o.verb ] && !HMR.alias[ o.verb ]
 | 
				
			||||||
    _err.err fluenterror: HMSTATUS.invalidCommand, quit: true, attempted: o.orgVerb, true
 | 
					    _err.err fluenterror: HMSTATUS.invalidCommand, quit: true, attempted: o.orgVerb, true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Override the .missingArgument behavior
 | 
					  # Override the .missingArgument behavior
 | 
				
			||||||
  Command.prototype.missingArgument = (### unused ###) ->
 | 
					  Command.prototype.missingArgument = (name) ->
 | 
				
			||||||
    if this.name() != 'help'
 | 
					    _err.err
 | 
				
			||||||
      _err.err
 | 
					      fluenterror:
 | 
				
			||||||
        verb: @name()
 | 
					        if this.name() != 'new'
 | 
				
			||||||
        fluenterror: HMSTATUS.resumeNotFound
 | 
					        then HMSTATUS.resumeNotFound
 | 
				
			||||||
        , true
 | 
					        else HMSTATUS.createNameMissing
 | 
				
			||||||
 | 
					      , true
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Override the .helpInformation behavior
 | 
					  # Override the .helpInformation behavior
 | 
				
			||||||
  Command.prototype.helpInformation = ->
 | 
					  Command.prototype.helpInformation = ->
 | 
				
			||||||
    manPage = FS.readFileSync(
 | 
					    manPage = FS.readFileSync(
 | 
				
			||||||
      PATH.join(__dirname, 'help/use.txt'), 'utf8' )
 | 
					      PATH.join(__dirname, 'use.txt'), 'utf8' )
 | 
				
			||||||
    return M2C(manPage, 'white', 'yellow')
 | 
					    return chalk.green.bold(manPage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    args: o.args,
 | 
					    args: o.args,
 | 
				
			||||||
@@ -237,7 +208,6 @@ initOptions = ( ar ) ->
 | 
				
			|||||||
      if optStr && (optStr = optStr.trim())
 | 
					      if optStr && (optStr = optStr.trim())
 | 
				
			||||||
        #var myJSON = JSON.parse(optStr);
 | 
					        #var myJSON = JSON.parse(optStr);
 | 
				
			||||||
        if( optStr[0] == '{')
 | 
					        if( optStr[0] == '{')
 | 
				
			||||||
          # TODO: remove use of evil(). - hacksalot
 | 
					 | 
				
			||||||
          ### jshint ignore:start ###
 | 
					          ### jshint ignore:start ###
 | 
				
			||||||
          oJSON = eval('(' + optStr + ')') # jshint ignore:line <-- no worky
 | 
					          oJSON = eval('(' + optStr + ')') # jshint ignore:line <-- no worky
 | 
				
			||||||
          ### jshint ignore:end ###
 | 
					          ### jshint ignore:end ###
 | 
				
			||||||
@@ -245,22 +215,19 @@ initOptions = ( ar ) ->
 | 
				
			|||||||
          inf = safeLoadJSON( optStr )
 | 
					          inf = safeLoadJSON( optStr )
 | 
				
			||||||
          if( !inf.ex )
 | 
					          if( !inf.ex )
 | 
				
			||||||
            oJSON = inf.json
 | 
					            oJSON = inf.json
 | 
				
			||||||
          else
 | 
					          # TODO: Error handling
 | 
				
			||||||
            return inf
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Grab the --debug flag, --silent, --assert and --no-color flags
 | 
					  # Grab the --debug flag, --silent, --assert and --no-color flags
 | 
				
			||||||
  isDebug = _.some args, (v) -> v == '-d' || v == '--debug'
 | 
					  isDebug = _.some args, (v) -> v == '-d' || v == '--debug'
 | 
				
			||||||
  isSilent = _.some args, (v) -> v == '-s' || v == '--silent'
 | 
					  isSilent = _.some args, (v) -> v == '-s' || v == '--silent'
 | 
				
			||||||
  isAssert = _.some args, (v) -> v == '-a' || v == '--assert'
 | 
					  isAssert = _.some args, (v) -> v == '-a' || v == '--assert'
 | 
				
			||||||
  isMono = _.some args, (v) -> v == '--no-color'
 | 
					  isMono = _.some args, (v) -> v == '--no-color'
 | 
				
			||||||
  isNoEscape = _.some args, (v) -> v == '--no-escape'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    color: !isMono,
 | 
					    color: !isMono,
 | 
				
			||||||
    debug: isDebug,
 | 
					    debug: isDebug,
 | 
				
			||||||
    silent: isSilent,
 | 
					    silent: isSilent,
 | 
				
			||||||
    assert: isAssert,
 | 
					    assert: isAssert,
 | 
				
			||||||
    noescape: isNoEscape,
 | 
					 | 
				
			||||||
    orgVerb: oVerb,
 | 
					    orgVerb: oVerb,
 | 
				
			||||||
    verb: verb,
 | 
					    verb: verb,
 | 
				
			||||||
    json: oJSON,
 | 
					    json: oJSON,
 | 
				
			||||||
@@ -276,7 +243,7 @@ execute = ( src, dst, opts, log ) ->
 | 
				
			|||||||
  v = new HMR.verbs[ @name() ]()
 | 
					  v = new HMR.verbs[ @name() ]()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Initialize command-specific options
 | 
					  # Initialize command-specific options
 | 
				
			||||||
  loadOptions.call this, opts, this.parent.jsonArgs
 | 
					  loadOptions.call( this, opts, this.parent.jsonArgs )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Set up error/output handling
 | 
					  # Set up error/output handling
 | 
				
			||||||
  _opts.errHandler = v
 | 
					  _opts.errHandler = v
 | 
				
			||||||
@@ -294,7 +261,7 @@ execute = ( src, dst, opts, log ) ->
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Success handler for verb invocations. Calls process.exit by default ###
 | 
					### Success handler for verb invocations. Calls process.exit by default ###
 | 
				
			||||||
executeSuccess = (###obj###) ->
 | 
					executeSuccess = (obj) ->
 | 
				
			||||||
  # Can't call _exitCallback here (process.exit) when PDF is running in BK
 | 
					  # Can't call _exitCallback here (process.exit) when PDF is running in BK
 | 
				
			||||||
  #_exitCallback 0; return
 | 
					  #_exitCallback 0; return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -302,15 +269,9 @@ executeSuccess = (###obj###) ->
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Failure handler for verb invocations. Calls process.exit by default ###
 | 
					### Failure handler for verb invocations. Calls process.exit by default ###
 | 
				
			||||||
executeFail = (err) ->
 | 
					executeFail = (err) ->
 | 
				
			||||||
  #console.dir err
 | 
					 | 
				
			||||||
  finalErrorCode = -1
 | 
					  finalErrorCode = -1
 | 
				
			||||||
  if err
 | 
					  if err
 | 
				
			||||||
    if err.fluenterror
 | 
					    finalErrorCode = if err.fluenterror then err.fluenterror else err
 | 
				
			||||||
      finalErrorCode = err.fluenterror
 | 
					 | 
				
			||||||
    else if err.length
 | 
					 | 
				
			||||||
      finalErrorCode = err[0].fluenterror
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      finalErrorCode = err
 | 
					 | 
				
			||||||
  if _opts.debug
 | 
					  if _opts.debug
 | 
				
			||||||
    msgs = require('./msg').errors;
 | 
					    msgs = require('./msg').errors;
 | 
				
			||||||
    logMsg printf M2C( msgs.exiting.msg, 'cyan' ), finalErrorCode
 | 
					    logMsg printf M2C( msgs.exiting.msg, 'cyan' ), finalErrorCode
 | 
				
			||||||
@@ -362,8 +323,7 @@ splitSrcDest = () ->
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  params = this.parent.args.filter((j) -> return String.is(j) )
 | 
					  params = this.parent.args.filter((j) -> return String.is(j) )
 | 
				
			||||||
  if params.length == 0
 | 
					  if params.length == 0
 | 
				
			||||||
    #tmpName = @name()
 | 
					    throw { fluenterror: HMSTATUS.resumeNotFound, quit: true }
 | 
				
			||||||
    throw { fluenterror: HMSTATUS.resumeNotFound, verb: @name(), quit: true }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Find the TO keyword, if any
 | 
					  # Find the TO keyword, if any
 | 
				
			||||||
  splitAt = _.findIndex( params, (p) -> return p.toLowerCase() == 'to'; )
 | 
					  splitAt = _.findIndex( params, (p) -> return p.toLowerCase() == 'to'; )
 | 
				
			||||||
@@ -386,5 +346,4 @@ splitSrcDest = () ->
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Simple logging placeholder. ###
 | 
					### Simple logging placeholder. ###
 | 
				
			||||||
logMsg = () ->
 | 
					logMsg = () ->
 | 
				
			||||||
  # eslint-disable-next-line no-console
 | 
					 | 
				
			||||||
  _opts.silent || console.log.apply( console.log, arguments )
 | 
					  _opts.silent || console.log.apply( console.log, arguments )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,33 +109,3 @@ errors:
 | 
				
			|||||||
    msg: Exiting with status code **%s**.
 | 
					    msg: Exiting with status code **%s**.
 | 
				
			||||||
  validateError:
 | 
					  validateError:
 | 
				
			||||||
    msg: "An error occurred during validation:\n%s"
 | 
					    msg: "An error occurred during validation:\n%s"
 | 
				
			||||||
  invalidOptionsFile:
 | 
					 | 
				
			||||||
    msg:
 | 
					 | 
				
			||||||
      - "The specified options file is invalid:\n"
 | 
					 | 
				
			||||||
      - "\nMake sure the options file contains valid JSON."
 | 
					 | 
				
			||||||
  optionsFileNotFound:
 | 
					 | 
				
			||||||
    msg: "The specified options file is missing or inaccessible."
 | 
					 | 
				
			||||||
  unknownSchema:
 | 
					 | 
				
			||||||
    msg:
 | 
					 | 
				
			||||||
      - "Unknown resume schema. Did you specify a valid FRESH or JRS resume?"
 | 
					 | 
				
			||||||
      - |
 | 
					 | 
				
			||||||
          At a minimum, a FRESH resume must include a "name" field and a "meta"
 | 
					 | 
				
			||||||
          property.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          "name": "John Doe",
 | 
					 | 
				
			||||||
          "meta": {
 | 
					 | 
				
			||||||
            "format": "FRESH@0.1.0"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          JRS-format resumes must include a "basics" section with a "name":
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          "basics": {
 | 
					 | 
				
			||||||
            "name": "John Doe"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
  themeHelperLoad:
 | 
					 | 
				
			||||||
    msg: >-
 | 
					 | 
				
			||||||
      An error occurred while attempting to load the '%s' theme helper. Is the
 | 
					 | 
				
			||||||
      theme correctly installed?
 | 
					 | 
				
			||||||
    dummy: dontcare
 | 
					 | 
				
			||||||
  invalidSchemaVersion:
 | 
					 | 
				
			||||||
    msg: "'%s' is not recognized as a valid schema version."
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,7 @@ HME = require('../core/event-codes')
 | 
				
			|||||||
_ = require('underscore')
 | 
					_ = require('underscore')
 | 
				
			||||||
M2C = require('../utils/md2chalk.js')
 | 
					M2C = require('../utils/md2chalk.js')
 | 
				
			||||||
PATH = require('path')
 | 
					PATH = require('path')
 | 
				
			||||||
 | 
					LO = require('lodash')
 | 
				
			||||||
FS = require('fs')
 | 
					FS = require('fs')
 | 
				
			||||||
EXTEND = require('extend')
 | 
					EXTEND = require('extend')
 | 
				
			||||||
HANDLEBARS = require('handlebars')
 | 
					HANDLEBARS = require('handlebars')
 | 
				
			||||||
@@ -22,7 +23,7 @@ dbgStyle = 'cyan';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###* A stateful output module. All HMR console output handled here. ###
 | 
					###* A stateful output module. All HMR console output handled here. ###
 | 
				
			||||||
class OutputHandler
 | 
					module.exports = class OutputHandler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,10 +40,11 @@ class OutputHandler
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  log: ->
 | 
					  log: ( msg ) ->
 | 
				
			||||||
 | 
					    msg = msg || ''
 | 
				
			||||||
    printf = require('printf')
 | 
					    printf = require('printf')
 | 
				
			||||||
    finished = printf.apply( printf, arguments )
 | 
					    finished = printf.apply( printf, arguments )
 | 
				
			||||||
    @opts.silent || console.log( finished ) # eslint-disable-line no-console
 | 
					    @opts.silent || console.log( finished )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -92,6 +94,7 @@ class OutputHandler
 | 
				
			|||||||
        if evt.cmd == 'build'
 | 
					        if evt.cmd == 'build'
 | 
				
			||||||
          themeName = this.theme.name.toUpperCase()
 | 
					          themeName = this.theme.name.toUpperCase()
 | 
				
			||||||
          if this.opts.tips && (this.theme.message || this.theme.render)
 | 
					          if this.opts.tips && (this.theme.message || this.theme.render)
 | 
				
			||||||
 | 
					            WRAP = require('word-wrap')
 | 
				
			||||||
            if this.theme.message
 | 
					            if this.theme.message
 | 
				
			||||||
              L( M2C( this.msgs.afterBuild.msg[0], 'cyan' ), themeName )
 | 
					              L( M2C( this.msgs.afterBuild.msg[0], 'cyan' ), themeName )
 | 
				
			||||||
              L( M2C( this.theme.message, 'white' ))
 | 
					              L( M2C( this.theme.message, 'white' ))
 | 
				
			||||||
@@ -128,7 +131,7 @@ class OutputHandler
 | 
				
			|||||||
        @log( chalk.cyan(output) )
 | 
					        @log( chalk.cyan(output) )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      when HME.beforeConvert
 | 
					      when HME.beforeConvert
 | 
				
			||||||
        L( M2C( this.msgs.beforeConvert.msg, if evt.error then 'red' else 'green' ),
 | 
					        L( M2C( this.msgs.beforeConvert.msg, 'green' ),
 | 
				
			||||||
          evt.srcFile, evt.srcFmt, evt.dstFile, evt.dstFmt
 | 
					          evt.srcFile, evt.srcFmt, evt.dstFile, evt.dstFmt
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -150,7 +153,7 @@ class OutputHandler
 | 
				
			|||||||
        L(M2C( msgs[0], 'white' ) + chalk[style].bold(adj), evt.file, evt.schema)
 | 
					        L(M2C( msgs[0], 'white' ) + chalk[style].bold(adj), evt.file, evt.schema)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if evt.violations
 | 
					        if evt.violations
 | 
				
			||||||
          _.each evt.violations, (err) ->
 | 
					          _.each evt.violations, (err,idx) ->
 | 
				
			||||||
            L( chalk.yellow.bold('--> ') +
 | 
					            L( chalk.yellow.bold('--> ') +
 | 
				
			||||||
               chalk.yellow(err.field.replace('data.','resume.').toUpperCase() +
 | 
					               chalk.yellow(err.field.replace('data.','resume.').toUpperCase() +
 | 
				
			||||||
               ' ' + err.message))
 | 
					               ' ' + err.message))
 | 
				
			||||||
@@ -169,7 +172,6 @@ class OutputHandler
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        # If the key was present, print it
 | 
					        # If the key was present, print it
 | 
				
			||||||
        if evt.target != undefined and !evt.error
 | 
					        if evt.target != undefined and !evt.error
 | 
				
			||||||
          # eslint-disable-next-line no-console
 | 
					 | 
				
			||||||
          console.dir( evt.target, { depth: null, colors: true } )
 | 
					          console.dir( evt.target, { depth: null, colors: true } )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # If the key was not present, but no error occurred, print it
 | 
					        # If the key was not present, but no error occurred, print it
 | 
				
			||||||
@@ -178,5 +180,3 @@ class OutputHandler
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        else if evt.error
 | 
					        else if evt.error
 | 
				
			||||||
          L chalk.red( evt.error.inner.inner )
 | 
					          L chalk.red( evt.error.inner.inner )
 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = OutputHandler
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										51
									
								
								src/cli/use.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/cli/use.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					Usage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  hackmyresume <command> <sources> [TO <targets>] [<options>]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Available commands:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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.
 | 
				
			||||||
 | 
					  CONVERT       Convert your resume between FRESH and JSON Resume.
 | 
				
			||||||
 | 
					  NEW           Create a new resume in FRESH or JSON Resume format.
 | 
				
			||||||
 | 
					  PEEK          View a specific field or element on your resume.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Available options:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  --theme -t    Path to a FRESH or JSON Resume theme.
 | 
				
			||||||
 | 
					  --pdf -p      Specify the PDF engine to use (wkhtmltopdf or phantom).
 | 
				
			||||||
 | 
					  --options -o  Load options from an external JSON file.
 | 
				
			||||||
 | 
					  --format -f   The format (FRESH or JSON Resume) to use.
 | 
				
			||||||
 | 
					  --debug -d    Emit extended debugging info.
 | 
				
			||||||
 | 
					  --assert -a   Treat resume validation warnings as errors.
 | 
				
			||||||
 | 
					  --no-colors   Disable terminal colors.
 | 
				
			||||||
 | 
					  --tips        Display theme messages and tips.
 | 
				
			||||||
 | 
					  --help -h     Display help documentation.
 | 
				
			||||||
 | 
					  --version -v  Display the current version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Not all options are supported for all commands. For example, the
 | 
				
			||||||
 | 
					--theme option is only supported for the BUILD command.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Examples:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  hackmyresume  BUILD resume.json TO out/resume.all --theme modern
 | 
				
			||||||
 | 
					  hackmyresume  ANALYZE resume.json
 | 
				
			||||||
 | 
					  hackmyresume  NEW my-new-resume.json --format JRS
 | 
				
			||||||
 | 
					  hackmyresume  CONVERT resume-fresh.json TO resume-jrs.json
 | 
				
			||||||
 | 
					  hackmyresume  VALIDATE resume.json
 | 
				
			||||||
 | 
					  hackmyresume  PEEK resume.json employment[2].summary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tips:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - You can specify multiple sources and/or targets for all commands.
 | 
				
			||||||
 | 
					  - You can use any FRESH or JSON Resume theme with HackMyResume.
 | 
				
			||||||
 | 
					  - Specify a file extension of .all to generate your resume to all
 | 
				
			||||||
 | 
					    available formats supported by the theme. (BUILD command.)
 | 
				
			||||||
 | 
					  - The --theme parameter can specify either the name of a preinstalled
 | 
				
			||||||
 | 
					    theme, or the path to a local FRESH or JSON Resume theme.
 | 
				
			||||||
 | 
					  - Visit https://www.npmjs.com/search?q=jsonresume-theme for a full
 | 
				
			||||||
 | 
					    listing of all available JSON Resume themes.
 | 
				
			||||||
 | 
					  - Visit https://github.com/fluentdesk/fresh-themes for a complete
 | 
				
			||||||
 | 
					    listing of all available FRESH themes.
 | 
				
			||||||
 | 
					  - Report bugs to https://githut.com/hacksalot/HackMyResume/issues.
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user