mirror of
				https://github.com/JuanCanham/HackMyResume.git
				synced 2025-10-31 13:17:26 +00:00 
			
		
		
		
	Merge branch 'dev' into docs-2.0
This commit is contained in:
		| @@ -16,9 +16,6 @@ install: | |||||||
|   - wkhtmltoimage -V |   - wkhtmltoimage -V | ||||||
| language: node_js | language: node_js | ||||||
| node_js: | node_js: | ||||||
|   - "4.0" |  | ||||||
|   - "4" |  | ||||||
|   - "5" |  | ||||||
|   - "6" |   - "6" | ||||||
|   - "7" |   - "7" | ||||||
|   - "8" |   - "8" | ||||||
|   | |||||||
							
								
								
									
										59
									
								
								Gruntfile.js
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								Gruntfile.js
									
									
									
									
									
								
							| @@ -39,39 +39,40 @@ module.exports = function (grunt) { | |||||||
|       all: { src: ['test/*.js'] } |       all: { src: ['test/*.js'] } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     jsdoc : { |     // jsdoc : { | ||||||
|       dist : { |     //   dist : { | ||||||
|         src: ['src/**/*.js'], |     //     src: ['src/**/*.js'], | ||||||
|         options: { |     //     options: { | ||||||
|           private: true, |     //       private: true, | ||||||
|           destination: 'doc' |     //       destination: 'doc' | ||||||
|         } |     //     } | ||||||
|       } |     //   } | ||||||
|     }, |     // }, | ||||||
|  |  | ||||||
|     clean: { |     clean: { | ||||||
|       test: ['test/sandbox'], |       test: ['test/sandbox'], | ||||||
|       dist: ['dist'] |       dist: ['dist'] | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     yuidoc: { |     // yuidoc: { | ||||||
|       compile: { |     //   compile: { | ||||||
|         name: '<%= pkg.name %>', |     //     name: '<%= pkg.name %>', | ||||||
|         description: '<%= pkg.description %>', |     //     description: '<%= pkg.description %>', | ||||||
|         version: '<%= pkg.version %>', |     //     version: '<%= pkg.version %>', | ||||||
|         url: '<%= pkg.homepage %>', |     //     url: '<%= pkg.homepage %>', | ||||||
|         options: { |     //     options: { | ||||||
|           paths: 'src/', |     //       paths: 'src/', | ||||||
|           outdir: 'docs/' |     //       outdir: 'docs/' | ||||||
|         } |     //     } | ||||||
|       } |     //   } | ||||||
|     }, |     // }, | ||||||
|  |  | ||||||
|     jshint: { |     jshint: { | ||||||
|       options: { |       options: { | ||||||
|         laxcomma: true, |         laxcomma: true, | ||||||
|         expr: true, |         expr: true, | ||||||
|         eqnull: true |         eqnull: true, | ||||||
|  |         esversion: 6 | ||||||
|       }, |       }, | ||||||
|       all: ['Gruntfile.js', 'dist/cli/**/*.js', 'test/*.js'] |       all: ['Gruntfile.js', 'dist/cli/**/*.js', 'test/*.js'] | ||||||
|     } |     } | ||||||
| @@ -82,22 +83,22 @@ 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-contrib-yuidoc'); |   //grunt.loadNpmTasks('grunt-contrib-yuidoc'); | ||||||
|   grunt.loadNpmTasks('grunt-jsdoc'); |   //grunt.loadNpmTasks('grunt-jsdoc'); | ||||||
|   grunt.loadNpmTasks('grunt-contrib-jshint'); |   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( config ) { |     function( config ) { | ||||||
|       grunt.task.run(['clean:test','build','jshint','simplemocha:all']); |       grunt.task.run(['clean:test','build',/*'jshint',*/'simplemocha:all']); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|   // Use 'grunt document' to build docs |   // Use 'grunt document' to build docs | ||||||
|   grunt.registerTask('document', 'Generate HackMyResume documentation.', |   // grunt.registerTask('document', 'Generate HackMyResume documentation.', | ||||||
|     function( config ) { |   //   function( config ) { | ||||||
|       grunt.task.run( ['jsdoc'] ); |   //     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.', | ||||||
|   | |||||||
							
								
								
									
										42
									
								
								dist/cli/error.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								dist/cli/error.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,11 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Error-handling routines for HackMyResume. |   Error-handling routines for HackMyResume. | ||||||
|   @module cli/error |   @module cli/error | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   /** Error handler for HackMyResume. All errors are handled here. | ||||||
| (function() { |   @class ErrorHandler */ | ||||||
|   var ErrorHandler, FCMD, FS, HMSTATUS, M2C, PATH, PKG, SyntaxErrorEx, WRAP, YAML, _defaultLog, assembleError, chalk, extend, printf; |   var ErrorHandler, FCMD, FS, HMSTATUS, M2C, PATH, PKG, SyntaxErrorEx, WRAP, YAML, _defaultLog, assembleError, chalk, extend, printf; | ||||||
|  |  | ||||||
|   HMSTATUS = require('../core/status-codes'); |   HMSTATUS = require('../core/status-codes'); | ||||||
| @@ -34,11 +34,6 @@ Error-handling routines for HackMyResume. | |||||||
|  |  | ||||||
|   require('string.prototype.startswith'); |   require('string.prototype.startswith'); | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** Error handler for HackMyResume. All errors are handled here. |  | ||||||
|   @class ErrorHandler |  | ||||||
|    */ |  | ||||||
|  |  | ||||||
|   ErrorHandler = module.exports = { |   ErrorHandler = module.exports = { | ||||||
|     init: function(debug, assert, silent) { |     init: function(debug, assert, silent) { | ||||||
|       this.debug = debug; |       this.debug = debug; | ||||||
| @@ -49,14 +44,20 @@ Error-handling routines for HackMyResume. | |||||||
|     }, |     }, | ||||||
|     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)); | ||||||
| @@ -72,6 +73,7 @@ Error-handling routines for HackMyResume. | |||||||
|           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) { | ||||||
| @@ -113,14 +115,16 @@ Error-handling routines for HackMyResume. | |||||||
|         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(function(v, idx, ar) { |         // msg += Object.keys( FCMD.verbs ).map( (v, idx, ar) -> | ||||||
|           return (idx === ar.length - 1 ? chalk.yellow('or ') : '') + chalk.yellow.bold(v.toUpperCase()); |         //   return ( if idx == ar.length - 1 then chalk.yellow('or ') else '') + | ||||||
|         }).join(chalk.yellow(', ')) + chalk.yellow(").\n\n"); |         //     chalk.yellow.bold(v.toUpperCase()); | ||||||
|         msg += chalk.gray(FS.readFileSync(PATH.resolve(__dirname, '../cli/use.txt'), 'utf8')); |         // ).join( chalk.yellow(', ')) + chalk.yellow(").\n\n"); | ||||||
|  |         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); | ||||||
| @@ -228,6 +232,7 @@ Error-handling routines for HackMyResume. | |||||||
|         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; | ||||||
| @@ -261,15 +266,20 @@ Error-handling routines for HackMyResume. | |||||||
|         break; |         break; | ||||||
|       case HMSTATUS.unknownSchema: |       case HMSTATUS.unknownSchema: | ||||||
|         msg = M2C(this.msgs.unknownSchema.msg[0]); |         msg = M2C(this.msgs.unknownSchema.msg[0]); | ||||||
|  |         //msg += "\n" + M2C( @msgs.unknownSchema.msg[1], 'yellow' ) | ||||||
|         etype = 'error'; |         etype = 'error'; | ||||||
|         break; |         break; | ||||||
|       case HMSTATUS.themeHelperLoad: |       case HMSTATUS.themeHelperLoad: | ||||||
|         msg = printf(M2C(this.msgs.themeHelperLoad.msg), ex.glob); |         msg = printf(M2C(this.msgs.themeHelperLoad.msg), ex.glob); | ||||||
|         etype = 'error'; |         etype = 'error'; | ||||||
|  |         break; | ||||||
|  |       case HMSTATUS.invalidSchemaVersion: | ||||||
|  |         msg = printf(M2C(this.msgs.invalidSchemaVersion.msg), ex.data); | ||||||
|  |         etype = 'error'; | ||||||
|     } |     } | ||||||
|     return { |     return { | ||||||
|       msg: msg, |       msg: msg, // The error message to display | ||||||
|       withStack: withStack, |       withStack: withStack, // Whether to include the stack | ||||||
|       quit: quit, |       quit: quit, | ||||||
|       etype: etype |       etype: etype | ||||||
|     }; |     }; | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								dist/cli/help/analyze.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								dist/cli/help/analyze.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | **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
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								dist/cli/help/build.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | **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
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								dist/cli/help/convert.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | **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
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								dist/cli/help/help.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | **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
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								dist/cli/help/new.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | **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
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								dist/cli/help/peek.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | **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
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								dist/cli/help/use.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | **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
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								dist/cli/help/validate.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | **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. | ||||||
							
								
								
									
										134
									
								
								dist/cli/main.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										134
									
								
								dist/cli/main.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,28 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the `main` function. |   Definition of the `main` function. | ||||||
|   @module cli/main |   @module cli/main | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   /* Invoke a HackMyResume verb. */ | ||||||
| (function() { |   /* 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. */ | ||||||
|  |   /* | ||||||
|  |   A callable implementation of the HackMyResume CLI. Encapsulates the command | ||||||
|  |   line interface as a single method accepting a parameter array. | ||||||
|  |   @alias module:cli/main.main | ||||||
|  |   @param rawArgs {Array} An array of command-line parameters. Will either be | ||||||
|  |   process.argv (in production) or custom parameters (in test). | ||||||
|  |   */ | ||||||
|  |   /* Split multiple command-line filenames by the 'TO' keyword */ | ||||||
|   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; |   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; | ||||||
|  |  | ||||||
|   HMR = require('../index'); |   HMR = require('../index'); | ||||||
| @@ -50,15 +67,6 @@ Definition of the `main` function. | |||||||
|  |  | ||||||
|   _exitCallback = null; |   _exitCallback = null; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /* |  | ||||||
|   A callable implementation of the HackMyResume CLI. Encapsulates the command |  | ||||||
|   line interface as a single method accepting a parameter array. |  | ||||||
|   @alias module:cli/main.main |  | ||||||
|   @param rawArgs {Array} An array of command-line parameters. Will either be |  | ||||||
|   process.argv (in production) or custom parameters (in test). |  | ||||||
|    */ |  | ||||||
|  |  | ||||||
|   main = 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); | ||||||
| @@ -66,32 +74,46 @@ Definition of the `main` function. | |||||||
|       return; |       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; | ||||||
|     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) { |     // 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) { | ||||||
|       execute.call(this, sources, [], this.opts(), logMsg); |       execute.call(this, sources, [], this.opts(), logMsg); | ||||||
|     })); |     })); | ||||||
|     program.command('validate')["arguments"]('<sources...>').description('Validate a resume in FRESH or JSON RESUME format.').action(function(sources) { |     // Create the VALIDATE command | ||||||
|  |     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); | ||||||
|     }); |     }); | ||||||
|     program.command('convert').description('Convert a resume to/from FRESH or JSON RESUME format.').action(function() { |     // Create the CONVERT command | ||||||
|  |     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); | ||||||
|     }); |     }); | ||||||
|     program.command('analyze')["arguments"]('<sources...>').option('--private', 'Include resume fields marked as private', false).description('Analyze one or more resumes.').action(function(sources) { |     // Create the ANALYZE command | ||||||
|  |     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); | ||||||
|     }); |     }); | ||||||
|     program.command('peek')["arguments"]('<sources...>').description('Peek at a resume field or section').action(function(sources, sectionOrField) { |     // Create the PEEK command | ||||||
|  |     program.command('peek').arguments('<sources...>').description('Peek at a resume field or section').action(function(sources, sectionOrField) { | ||||||
|       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).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(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(sources, targets, options) { | ||||||
|       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 { | ||||||
| @@ -100,9 +122,6 @@ Definition of the `main` function. | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /* 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; | ||||||
| @@ -125,6 +144,7 @@ Definition of the `main` function. | |||||||
|       return null; |       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(''); | ||||||
| @@ -132,25 +152,33 @@ Definition of the `main` function. | |||||||
|       _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); | ||||||
|     if (o.verb && !HMR.verbs[o.verb] && !HMR.alias[o.verb]) { |     // 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') { | ||||||
|       _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(name) { | ||||||
|  |       if (this.name() !== 'help') { | ||||||
|         _err.err({ |         _err.err({ | ||||||
|         fluenterror: this.name() !== 'new' ? HMSTATUS.resumeNotFound : HMSTATUS.createNameMissing |           verb: this.name(), | ||||||
|  |           fluenterror: HMSTATUS.resumeNotFound | ||||||
|         }, true); |         }, true); | ||||||
|  |       } | ||||||
|     }; |     }; | ||||||
|  |     // Override the .helpInformation behavior | ||||||
|     Command.prototype.helpInformation = function() { |     Command.prototype.helpInformation = function() { | ||||||
|       var manPage; |       var manPage; | ||||||
|       manPage = FS.readFileSync(PATH.join(__dirname, 'use.txt'), 'utf8'); |       manPage = FS.readFileSync(PATH.join(__dirname, 'help/use.txt'), 'utf8'); | ||||||
|       return chalk.green.bold(manPage); |       return M2C(manPage, 'white', 'yellow'); | ||||||
|     }; |     }; | ||||||
|     return { |     return { | ||||||
|       args: o.args, |       args: o.args, | ||||||
| @@ -158,17 +186,16 @@ Definition of the `main` function. | |||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /* 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, isNoEscape, 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] !== '-'; | ||||||
|       }); |       }); | ||||||
| @@ -176,6 +203,7 @@ Definition of the `main` function. | |||||||
|         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'; | ||||||
|       }); |       }); | ||||||
| @@ -183,12 +211,11 @@ Definition of the `main` function. | |||||||
|         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 + ')'); |             oJSON = eval('(' + optStr + ')'); // jshint ignore:line <-- no worky | ||||||
|  |  | ||||||
|             /* jshint ignore:end */ |  | ||||||
|           } else { |           } else { | ||||||
|             inf = safeLoadJSON(optStr); |             inf = safeLoadJSON(optStr); | ||||||
|             if (!inf.ex) { |             if (!inf.ex) { | ||||||
| @@ -200,6 +227,7 @@ Definition of the `main` function. | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |     // 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'; | ||||||
|     }); |     }); | ||||||
| @@ -228,36 +256,35 @@ Definition of the `main` function. | |||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /* 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); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /* Success handler for verb invocations. Calls process.exit by default */ |  | ||||||
|  |  | ||||||
|   executeSuccess = function(obj) {}; |   executeSuccess = function(obj) {}; | ||||||
|  |  | ||||||
|  |   // Can't call _exitCallback here (process.exit) when PDF is running in BK | ||||||
|  |   //_exitCallback 0; return | ||||||
|   /* 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); |     //console.dir err | ||||||
|     finalErrorCode = -1; |     finalErrorCode = -1; | ||||||
|     if (err) { |     if (err) { | ||||||
|       if (err.fluenterror) { |       if (err.fluenterror) { | ||||||
| @@ -278,19 +305,16 @@ Definition of the `main` function. | |||||||
|     _exitCallback(finalErrorCode); |     _exitCallback(finalErrorCode); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /* |  | ||||||
|   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) { |   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 | ||||||
|     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; | ||||||
|     } |     } | ||||||
| @@ -310,9 +334,6 @@ Definition of the `main` function. | |||||||
|     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) { | ||||||
| @@ -320,13 +341,17 @@ Definition of the `main` function. | |||||||
|     }); |     }); | ||||||
|     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; | ||||||
| @@ -337,9 +362,6 @@ Definition of the `main` function. | |||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /* Simple logging placeholder. */ |  | ||||||
|  |  | ||||||
|   logMsg = function() { |   logMsg = function() { | ||||||
|     return _opts.silent || console.log.apply(console.log, arguments); |     return _opts.silent || console.log.apply(console.log, arguments); | ||||||
|   }; |   }; | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								dist/cli/msg.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								dist/cli/msg.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Message-handling routines for HackMyResume. |   Message-handling routines for HackMyResume. | ||||||
|   @module cli/msg |   @module cli/msg | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var PATH, YAML; |   var PATH, YAML; | ||||||
|  |  | ||||||
|   PATH = require('path'); |   PATH = require('path'); | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								dist/cli/msg.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/cli/msg.yml
									
									
									
									
										vendored
									
									
								
							| @@ -137,3 +137,5 @@ errors: | |||||||
|       An error occurred while attempting to load the '%s' theme helper. Is the |       An error occurred while attempting to load the '%s' theme helper. Is the | ||||||
|       theme correctly installed? |       theme correctly installed? | ||||||
|     dummy: dontcare |     dummy: dontcare | ||||||
|  |   invalidSchemaVersion: | ||||||
|  |     msg: "'%s' is not recognized as a valid schema version." | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								dist/cli/out.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								dist/cli/out.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Output routines for HackMyResume. |   Output routines for HackMyResume. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module cli/out |   @module cli/out | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var EXTEND, FS, HANDLEBARS, HME, LO, M2C, OutputHandler, PATH, YAML, _, chalk, dbgStyle, pad, printf; |   var EXTEND, FS, HANDLEBARS, HME, LO, M2C, OutputHandler, PATH, YAML, _, chalk, dbgStyle, pad, printf; | ||||||
|  |  | ||||||
|   chalk = require('chalk'); |   chalk = require('chalk'); | ||||||
| @@ -34,29 +32,26 @@ Output routines for HackMyResume. | |||||||
|  |  | ||||||
|   dbgStyle = 'cyan'; |   dbgStyle = 'cyan'; | ||||||
|  |  | ||||||
|  |   module.exports = OutputHandler = class OutputHandler { | ||||||
|   /** A stateful output module. All HMR console output handled here. */ |     constructor(opts) { | ||||||
|  |  | ||||||
|   module.exports = OutputHandler = (function() { |  | ||||||
|     function OutputHandler(opts) { |  | ||||||
|       this.init(opts); |       this.init(opts); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     OutputHandler.prototype.init = function(opts) { |     init(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; | ||||||
|     }; |     } | ||||||
|  |  | ||||||
|     OutputHandler.prototype.log = function(msg) { |     log(msg) { | ||||||
|       var finished; |       var finished; | ||||||
|       msg = msg || ''; |       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); |       return this.opts.silent || console.log(finished); | ||||||
|     }; |     } | ||||||
|  |  | ||||||
|     OutputHandler.prototype["do"] = function(evt) { |     do(evt) { | ||||||
|       var L, WRAP, 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() { | ||||||
| @@ -65,6 +60,9 @@ Output routines for HackMyResume. | |||||||
|       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; | ||||||
| @@ -166,11 +164,13 @@ Output routines for HackMyResume. | |||||||
|           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) { | ||||||
|             return console.dir(evt.target, { |             return console.dir(evt.target, { | ||||||
|               depth: null, |               depth: null, | ||||||
| @@ -182,12 +182,10 @@ Output routines for HackMyResume. | |||||||
|             return L(chalk.red(evt.error.inner.inner)); |             return L(chalk.red(evt.error.inner.inner)); | ||||||
|           } |           } | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|     return OutputHandler; |  | ||||||
|  |  | ||||||
|   })(); |  | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
| //# sourceMappingURL=out.js.map | //# sourceMappingURL=out.js.map | ||||||
|   | |||||||
							
								
								
									
										52
									
								
								dist/cli/use.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								dist/cli/use.txt
									
									
									
									
										vendored
									
									
								
							| @@ -1,52 +0,0 @@ | |||||||
| 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. |  | ||||||
|   --private     Include resume fields marked as private |  | ||||||
|   --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. |  | ||||||
							
								
								
									
										113
									
								
								dist/core/abstract-resume.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										113
									
								
								dist/core/abstract-resume.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,113 +0,0 @@ | |||||||
|  |  | ||||||
| /** |  | ||||||
| Definition of the AbstractResume class. |  | ||||||
| @license MIT. See LICENSE.md for details. |  | ||||||
| @module core/abstract-resume |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var AbstractResume, FluentDate, _, __; |  | ||||||
|  |  | ||||||
|   _ = require('underscore'); |  | ||||||
|  |  | ||||||
|   __ = require('lodash'); |  | ||||||
|  |  | ||||||
|   FluentDate = require('./fluent-date'); |  | ||||||
|  |  | ||||||
|   AbstractResume = (function() { |  | ||||||
|     function AbstractResume() {} |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|     Compute the total duration of the work history. |  | ||||||
|     @returns The total duration of the sheet's work history, that is, the number |  | ||||||
|     of years between the start date of the earliest job on the resume and the |  | ||||||
|     *latest end date of all jobs in the work history*. This last condition is for |  | ||||||
|     sheets that have overlapping jobs. |  | ||||||
|      */ |  | ||||||
|  |  | ||||||
|     AbstractResume.prototype.duration = function(collKey, startKey, endKey, unit) { |  | ||||||
|       var firstDate, hist, lastDate, new_e; |  | ||||||
|       unit = unit || 'years'; |  | ||||||
|       hist = __.get(this, collKey); |  | ||||||
|       if (!hist || !hist.length) { |  | ||||||
|         return 0; |  | ||||||
|       } |  | ||||||
|       new_e = hist.map(function(job) { |  | ||||||
|         var obj; |  | ||||||
|         obj = _.pick(job, [startKey, endKey]); |  | ||||||
|         if (!_.has(obj, endKey)) { |  | ||||||
|           obj[endKey] = 'current'; |  | ||||||
|         } |  | ||||||
|         if (obj && (obj[startKey] || obj[endKey])) { |  | ||||||
|           obj = _.pairs(obj); |  | ||||||
|           obj[0][1] = FluentDate.fmt(obj[0][1]); |  | ||||||
|           if (obj.length > 1) { |  | ||||||
|             obj[1][1] = FluentDate.fmt(obj[1][1]); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|         return obj; |  | ||||||
|       }); |  | ||||||
|       new_e = _.filter(_.flatten(new_e, true), function(v) { |  | ||||||
|         return v && v.length && v[0] && v[0].length; |  | ||||||
|       }); |  | ||||||
|       if (!new_e || !new_e.length) { |  | ||||||
|         return 0; |  | ||||||
|       } |  | ||||||
|       new_e = _.sortBy(new_e, function(elem) { |  | ||||||
|         return elem[1].unix(); |  | ||||||
|       }); |  | ||||||
|       firstDate = _.first(new_e)[1]; |  | ||||||
|       lastDate = _.last(new_e)[1]; |  | ||||||
|       return lastDate.diff(firstDate, unit); |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|     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 |  | ||||||
|     } |  | ||||||
|      */ |  | ||||||
|  |  | ||||||
|     AbstractResume.prototype.scrubResume = function(rep, opts) { |  | ||||||
|       var ignoreList, includePrivates, privateList, scrubbed, traverse; |  | ||||||
|       traverse = require('traverse'); |  | ||||||
|       ignoreList = []; |  | ||||||
|       privateList = []; |  | ||||||
|       includePrivates = opts && opts["private"]; |  | ||||||
|       scrubbed = traverse(rep).map(function() { |  | ||||||
|         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)) { |  | ||||||
|           this.after(function() { |  | ||||||
|             this.update(_.compact(this.node)); |  | ||||||
|           }); |  | ||||||
|         } |  | ||||||
|       }); |  | ||||||
|       return { |  | ||||||
|         scrubbed: scrubbed, |  | ||||||
|         ingoreList: ignoreList, |  | ||||||
|         privateList: privateList |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     return AbstractResume; |  | ||||||
|  |  | ||||||
|   })(); |  | ||||||
|  |  | ||||||
|   module.exports = AbstractResume; |  | ||||||
|  |  | ||||||
| }).call(this); |  | ||||||
|  |  | ||||||
| //# sourceMappingURL=abstract-resume.js.map |  | ||||||
							
								
								
									
										30
									
								
								dist/core/default-formats.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								dist/core/default-formats.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,55 +1,59 @@ | |||||||
|  | (function() { | ||||||
|   /* |   /* | ||||||
|   Event code definitions. |   Event code definitions. | ||||||
|   @module core/default-formats |   @module core/default-formats | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** Supported resume formats. */ |   /** Supported resume formats. */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   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', | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								dist/core/default-options.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								dist/core/default-options.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,20 +1,20 @@ | |||||||
|  | (function() { | ||||||
|   /* |   /* | ||||||
|   Event code definitions. |   Event code definitions. | ||||||
|   @module core/default-options |   @module core/default-options | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   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 |       max_char: 80 // ← See lib/html.js in above-linked repo | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   // wrap_line_length: 120, ← Don't use this | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
| //# sourceMappingURL=default-options.js.map | //# sourceMappingURL=default-options.js.map | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								dist/core/event-codes.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								dist/core/event-codes.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /* |   /* | ||||||
|   Event code definitions. |   Event code definitions. | ||||||
|   @module core/event-codes |   @module core/event-codes | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   module.exports = { |   module.exports = { | ||||||
|     error: -1, |     error: -1, | ||||||
|     success: 0, |     success: 0, | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								dist/core/fluent-date.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								dist/core/fluent-date.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,18 +1,15 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   The HackMyResume date representation. |   The HackMyResume date representation. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module core/fluent-date |   @module core/fluent-date | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   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. | ||||||
| @@ -29,20 +26,17 @@ The HackMyResume date representation. | |||||||
|   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 { | ||||||
|   FluentDate = (function() { |     constructor(dt) { | ||||||
|     function FluentDate(dt) { |  | ||||||
|       this.rep = this.fmt(dt); |       this.rep = this.fmt(dt); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     FluentDate.isCurrent = function(dt) { |     static isCurrent(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 = {}; | ||||||
|  |  | ||||||
|   abbr = {}; |   abbr = {}; | ||||||
| @@ -64,20 +58,20 @@ The HackMyResume date representation. | |||||||
|     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)) { |       if (/^(present|now|current)$/.test(dt)) { // "Present", "Now" | ||||||
|         return moment(); |         return moment(); | ||||||
|       } else if (/^\D+\s+\d{4}$/.test(dt)) { |       } else if (/^\D+\s+\d{4}$/.test(dt)) { // "Mar 2015" | ||||||
|         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)) { |       } else if (/^\d{4}-\d{1,2}$/.test(dt)) { // "2015-03", "1998-4" | ||||||
|         return moment(dt, 'YYYY-MM'); |         return moment(dt, 'YYYY-MM'); | ||||||
|       } else if (/^\s*\d{4}\s*$/.test(dt)) { |       } else if (/^\s*\d{4}\s*$/.test(dt)) { // "2015" | ||||||
|         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); | ||||||
|   | |||||||
							
								
								
									
										244
									
								
								dist/core/fresh-resume.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										244
									
								
								dist/core/fresh-resume.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,17 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the FRESHResume class. |   Definition of the FRESHResume class. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module core/fresh-resume |   @module core/fresh-resume | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   Convert human-friendly dates into formal Moment.js dates for all collections. | ||||||
|   var AbstractResume, CONVERTER, FS, FluentDate, FreshResume, JRSResume, MD, PATH, XML, _, __, _parseDates, extend, moment, validator, |   We don't want to lose the raw textual date as entered by the user, so we store | ||||||
|     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; }, |   the Moment-ified date as a separate property with a prefix of .safe. For ex: | ||||||
|     hasProp = {}.hasOwnProperty; |   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'); | ||||||
|  |  | ||||||
| @@ -34,33 +37,20 @@ Definition of the FRESHResume class. | |||||||
|  |  | ||||||
|   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. | ||||||
| @@ -75,14 +65,17 @@ Definition of the FRESHResume class. | |||||||
|     compute: Prepare computed resume totals. |     compute: Prepare computed resume totals. | ||||||
|     } |     } | ||||||
|     */ |     */ | ||||||
|  |     parseJSON(rep, opts) { | ||||||
|     FreshResume.prototype.parseJSON = function(rep, opts) { |       var ignoreList, privateList, ref, scrubbed, scrubber; | ||||||
|       var ignoreList, privateList, ref, ref1, scrubbed; |  | ||||||
|       if (opts && opts.privatize) { |       if (opts && opts.privatize) { | ||||||
|         ref = this.scrubResume(rep, opts), scrubbed = ref.scrubbed, ignoreList = ref.ignoreList, privateList = ref.privateList; |         // Ignore any element with the 'ignore: true' or 'private: true' designator. | ||||||
|  |         scrubber = require('../utils/resume-scrubber'); | ||||||
|  |         ({scrubbed, ignoreList, privateList} = scrubber.scrubResume(rep, opts)); | ||||||
|       } |       } | ||||||
|  |       // Now apply the resume representation onto this object | ||||||
|       extend(true, this, opts && opts.privatize ? scrubbed : rep); |       extend(true, this, opts && opts.privatize ? scrubbed : rep); | ||||||
|       if (!((ref1 = this.imp) != null ? ref1.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 || {}; | ||||||
| @@ -92,6 +85,7 @@ Definition of the FRESHResume class. | |||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         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 = { | ||||||
| @@ -100,34 +94,43 @@ Definition of the FRESHResume class. | |||||||
|         }); |         }); | ||||||
|       } |       } | ||||||
|       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) { | ||||||
|     FreshResume.prototype.saveAs = function(filename, format) { |       var newRep, parts, safeFormat, useEdgeSchema; | ||||||
|       var newRep; |       // If format isn't specified, default to FRESH | ||||||
|       if (format !== 'JRS') { |       safeFormat = (format && format.trim()) || 'FRESH'; | ||||||
|  |       // 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 { |       } else if (parts[0] === 'JRS') { | ||||||
|         newRep = CONVERTER.toJRS(this); |         useEdgeSchema = parts.length > 1 ? parts[1] === '1' : false; | ||||||
|  |         newRep = CONVERTER.toJRS(this, { | ||||||
|  |           edge: useEdgeSchema | ||||||
|  |         }); | ||||||
|         FS.writeFileSync(filename, JRSResume.stringify(newRep), 'utf8'); |         FS.writeFileSync(filename, JRSResume.stringify(newRep), 'utf8'); | ||||||
|  |       } else { | ||||||
|  |         throw { | ||||||
|  |           badVer: safeFormat | ||||||
|  |         }; | ||||||
|       } |       } | ||||||
|       return this; |       return this; | ||||||
|     }; |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|     Duplicate this FreshResume instance. |     Duplicate this FreshResume instance. | ||||||
| @@ -136,46 +139,39 @@ Definition of the FRESHResume class. | |||||||
|     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, ''); | ||||||
| @@ -187,42 +183,49 @@ Definition of the FRESHResume class. | |||||||
|         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. | ||||||
|  |  | ||||||
|     /** Return a unique list of all keywords across all skills. */ |     // 2) Doesn't bother trying to integrate skills.list with skills.sets if they | ||||||
|  |     // happen to declare different skills, and if skills.sets declares ONE skill and | ||||||
|  |     // skills.list declared 50, only 1 skill will be registered. | ||||||
|  |  | ||||||
|     FreshResume.prototype.keywords = function() { |     // 3) In the future, skill.sets should only be able to use skills declared in | ||||||
|  |     // 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) { | ||||||
| @@ -240,19 +243,17 @@ Definition of the FRESHResume class. | |||||||
|         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; |       delete this.computed; // Don't use Object.keys() here | ||||||
|       delete this.employment; |       delete this.employment; | ||||||
|       delete this.service; |       delete this.service; | ||||||
|       delete this.education; |       delete this.education; | ||||||
| @@ -262,14 +263,12 @@ Definition of the FRESHResume class. | |||||||
|       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; | ||||||
|       } |       } | ||||||
| @@ -280,14 +279,11 @@ Definition of the FRESHResume class. | |||||||
|         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) { | ||||||
| @@ -298,63 +294,53 @@ Definition of the FRESHResume class. | |||||||
|         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('fresh-resume-schema'); | ||||||
|       validator = require('is-my-json-valid'); |       validator = require('is-my-json-valid'); | ||||||
|       validate = validator(schemaObj, { |       validate = validator(schemaObj, { // See Note [1]. | ||||||
|         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})?)?$/ | ||||||
|         } |         } | ||||||
| @@ -365,19 +351,19 @@ Definition of the FRESHResume class. | |||||||
|         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)) { | ||||||
| @@ -411,30 +397,24 @@ Definition of the FRESHResume class. | |||||||
|           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) { |     replacer = function(key, value) { // Exclude these keys from stringification | ||||||
|       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) { | ||||||
| @@ -448,19 +428,11 @@ Definition of the FRESHResume class. | |||||||
|     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; | ||||||
| @@ -492,11 +464,15 @@ Definition of the FRESHResume class. | |||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** 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 | ||||||
|   | |||||||
							
								
								
									
										97
									
								
								dist/core/fresh-theme.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										97
									
								
								dist/core/fresh-theme.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,12 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the FRESHTheme class. |   Definition of the FRESHTheme class. | ||||||
|   @module core/fresh-theme |   @module core/fresh-theme | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   /* Load and parse theme source files. */ | ||||||
| (function() { |   /* 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'); | ||||||
| @@ -30,85 +31,98 @@ Definition of the FRESHTheme class. | |||||||
|  |  | ||||||
|   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() { | ||||||
|   FRESHTheme = (function() { |  | ||||||
|     function FRESHTheme() { |  | ||||||
|       this.baseFolder = 'src'; |       this.baseFolder = 'src'; | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     /* 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.op === '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, themesFolder; |           var d, themePath, themesObj; | ||||||
|           themesFolder = require.resolve('fresh-themes'); |           // First, see if this is one of the predefined FRESH themes. There are | ||||||
|           d = parsePath(themeFolder).dirname; |           // only a 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. | ||||||
|  |           // 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); |             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) { | ||||||
|     FRESHTheme.prototype.getFormat = function(fmt) { |  | ||||||
|       return this.formats[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, jsFiles, major, that, tplFolder; | ||||||
|     that = this; |     that = this; | ||||||
|     major = false; |     major = false; | ||||||
|     tplFolder = PATH.join(this.folder, this.baseFolder); |     tplFolder = PATH.join(this.folder, this.baseFolder); | ||||||
|     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) { | ||||||
| @@ -120,6 +134,8 @@ Definition of the FRESHTheme class. | |||||||
|         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 | ||||||
| @@ -127,6 +143,7 @@ Definition of the FRESHTheme class. | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|  |     // Now, save all the javascript file paths to a theme property. | ||||||
|     jsFiles = fmts.filter(function(fmt) { |     jsFiles = fmts.filter(function(fmt) { | ||||||
|       return fmt && (fmt.ext === 'js'); |       return fmt && (fmt.ext === 'js'); | ||||||
|     }); |     }); | ||||||
| @@ -136,9 +153,6 @@ Definition of the FRESHTheme class. | |||||||
|     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); | ||||||
| @@ -149,6 +163,8 @@ Definition of the FRESHTheme class. | |||||||
|     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; | ||||||
| @@ -164,6 +180,9 @@ Definition of the FRESHTheme class. | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     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] === '_') { | ||||||
| @@ -199,13 +218,16 @@ Definition of the FRESHTheme class. | |||||||
|         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, | ||||||
| @@ -214,16 +236,15 @@ Definition of the FRESHTheme class. | |||||||
|       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()) || ''; | ||||||
|   | |||||||
							
								
								
									
										232
									
								
								dist/core/jrs-resume.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										232
									
								
								dist/core/jrs-resume.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,17 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the JRSResume class. |   Definition of the JRSResume class. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module core/jrs-resume |   @module core/jrs-resume | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   Convert human-friendly dates into formal Moment.js dates for all collections. | ||||||
|   var AbstractResume, CONVERTER, FS, JRSResume, MD, PATH, _, _parseDates, extend, moment, validator, |   We don't want to lose the raw textual date as entered by the user, so we store | ||||||
|     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; }, |   the Moment-ified date as a separate property with a prefix of .safe. For ex: | ||||||
|     hasProp = {}.hasOwnProperty; |   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'); | ||||||
|  |  | ||||||
| @@ -26,35 +29,24 @@ Definition of the JRSResume class. | |||||||
|  |  | ||||||
|   moment = require('moment'); |   moment = require('moment'); | ||||||
|  |  | ||||||
|   AbstractResume = require('./abstract-resume'); |   JRSResume = (function() { | ||||||
|  |     /** Reset the sheet to an empty state. */ | ||||||
|  |     var clear; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|     A JRS resume or CV. JRS resumes are backed by JSON, and each JRSResume object |     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. |     is an instantiation of that JSON decorated with utility methods. | ||||||
|     @class JRSResume |     @class JRSResume | ||||||
|     */ |     */ | ||||||
|  |     class JRSResume { // extends AbstractResume | ||||||
|   JRSResume = (function(superClass) { |  | ||||||
|     var clear; |  | ||||||
|  |  | ||||||
|     extend1(JRSResume, superClass); |  | ||||||
|  |  | ||||||
|     function JRSResume() { |  | ||||||
|       return JRSResume.__super__.constructor.apply(this, arguments); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|       /** Initialize the the JSResume from string. */ |       /** Initialize the the JSResume from string. */ | ||||||
|  |       parse(stringData, opts) { | ||||||
|     JRSResume.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 JRSResume object from JSON. |       Initialize the JRSResume object from JSON. | ||||||
| @@ -69,15 +61,18 @@ Definition of the JRSResume class. | |||||||
|       compute: Prepare computed resume totals. |       compute: Prepare computed resume totals. | ||||||
|       } |       } | ||||||
|       */ |       */ | ||||||
|  |       parseJSON(rep, opts) { | ||||||
|     JRSResume.prototype.parseJSON = function(rep, opts) { |         var ignoreList, privateList, ref, scrubbed, scrubber; | ||||||
|       var ignoreList, privateList, ref, ref1, scrubbed; |  | ||||||
|         opts = opts || {}; |         opts = opts || {}; | ||||||
|         if (opts.privatize) { |         if (opts.privatize) { | ||||||
|         ref = this.scrubResume(rep, opts), scrubbed = ref.scrubbed, ignoreList = ref.ignoreList, privateList = ref.privateList; |           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); |         extend(true, this, opts.privatize ? scrubbed : rep); | ||||||
|       if (!((ref1 = this.imp) != null ? ref1.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 || {}; | ||||||
| @@ -88,6 +83,7 @@ Definition of the JRSResume class. | |||||||
|           } |           } | ||||||
|           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(); | ||||||
|         if (opts.compute === void 0 || opts.compute) { |         if (opts.compute === void 0 || opts.compute) { | ||||||
| @@ -97,21 +93,17 @@ Definition of the JRSResume class. | |||||||
|           }; |           }; | ||||||
|         } |         } | ||||||
|         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) { | ||||||
|     JRSResume.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(this), 'utf8'); |         FS.writeFileSync(this.imp.file, this.stringify(this), 'utf8'); | ||||||
|         return this; |         return this; | ||||||
|     }; |       } | ||||||
|  |  | ||||||
|  |  | ||||||
|       /** Save the sheet to disk in a specific format, either FRESH or JRS. */ |       /** Save the sheet to disk in a specific format, either FRESH or JRS. */ | ||||||
|  |       saveAs(filename, format) { | ||||||
|     JRSResume.prototype.saveAs = function(filename, format) { |  | ||||||
|         var newRep, stringRep; |         var newRep, stringRep; | ||||||
|         if (format === 'JRS') { |         if (format === 'JRS') { | ||||||
|           this.imp.file = filename || this.imp.file; |           this.imp.file = filename || this.imp.file; | ||||||
| @@ -122,23 +114,19 @@ Definition of the JRSResume class. | |||||||
|           FS.writeFileSync(filename, stringRep, 'utf8'); |           FS.writeFileSync(filename, stringRep, 'utf8'); | ||||||
|         } |         } | ||||||
|         return this; |         return this; | ||||||
|     }; |       } | ||||||
|  |  | ||||||
|  |  | ||||||
|       /** Return the resume format. */ |       /** Return the resume format. */ | ||||||
|  |       format() { | ||||||
|     JRSResume.prototype.format = function() { |  | ||||||
|         return 'JRS'; |         return 'JRS'; | ||||||
|     }; |       } | ||||||
|  |  | ||||||
|     JRSResume.prototype.stringify = function() { |       stringify() { | ||||||
|         return JRSResume.stringify(this); |         return JRSResume.stringify(this); | ||||||
|     }; |       } | ||||||
|  |  | ||||||
|  |  | ||||||
|       /** Return a unique list of all keywords across all skills. */ |       /** Return a unique list of all keywords across all skills. */ | ||||||
|  |       keywords() { | ||||||
|     JRSResume.prototype.keywords = function() { |  | ||||||
|         var flatSkills; |         var flatSkills; | ||||||
|         flatSkills = []; |         flatSkills = []; | ||||||
|         if (this.skills && this.skills.length) { |         if (this.skills && this.skills.length) { | ||||||
| @@ -147,82 +135,53 @@ Definition of the JRSResume class. | |||||||
|           }); |           }); | ||||||
|         } |         } | ||||||
|         return flatSkills; |         return flatSkills; | ||||||
|     }; |       } | ||||||
|  |  | ||||||
|  |  | ||||||
|       /** |       /** | ||||||
|       Return internal metadata. Create if it doesn't exist. |       Return internal metadata. Create if it doesn't exist. | ||||||
|       JSON Resume v0.0.0 doesn't allow additional properties at the root level, |       JSON Resume v0.0.0 doesn't allow additional properties at the root level, | ||||||
|       so tuck this into the .basic sub-object. |       so tuck this into the .basic sub-object. | ||||||
|       */ |       */ | ||||||
|  |       i() { | ||||||
|     JRSResume.prototype.i = function() { |  | ||||||
|         var ref; |         var ref; | ||||||
|         return this.imp = (ref = this.imp) != null ? ref : {}; |         return this.imp = (ref = this.imp) != null ? ref : {}; | ||||||
|     }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** Reset the sheet to an empty state. */ |  | ||||||
|  |  | ||||||
|     clear = function(clearMeta) { |  | ||||||
|       clearMeta = ((clearMeta === void 0) && true) || clearMeta; |  | ||||||
|       if (clearMeta) { |  | ||||||
|         delete this.imp; |  | ||||||
|       } |       } | ||||||
|       delete this.basics.computed; |  | ||||||
|       delete this.work; |  | ||||||
|       delete this.volunteer; |  | ||||||
|       delete this.education; |  | ||||||
|       delete this.awards; |  | ||||||
|       delete this.publications; |  | ||||||
|       delete this.interests; |  | ||||||
|       delete this.skills; |  | ||||||
|       return delete this.basics.profiles; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|       /** Add work experience to the sheet. */ |       /** Add work experience to the sheet. */ | ||||||
|  |       add(moniker) { | ||||||
|     JRSResume.prototype.add = function(moniker) { |  | ||||||
|         var defSheet, newObject; |         var defSheet, newObject; | ||||||
|       defSheet = JRSResume["default"](); |         defSheet = JRSResume.default(); | ||||||
|         newObject = $.extend(true, {}, defSheet[moniker][0]); |         newObject = $.extend(true, {}, defSheet[moniker][0]); | ||||||
|         this[moniker] = this[moniker] || []; |         this[moniker] = this[moniker] || []; | ||||||
|         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) { | ||||||
|     JRSResume.prototype.hasProfile = function(socialNetwork) { |  | ||||||
|         socialNetwork = socialNetwork.trim().toLowerCase(); |         socialNetwork = socialNetwork.trim().toLowerCase(); | ||||||
|         return this.basics.profiles && _.some(this.basics.profiles, function(p) { |         return this.basics.profiles && _.some(this.basics.profiles, function(p) { | ||||||
|           return p.network.trim().toLowerCase() === socialNetwork; |           return p.network.trim().toLowerCase() === socialNetwork; | ||||||
|         }); |         }); | ||||||
|     }; |       } | ||||||
|  |  | ||||||
|  |  | ||||||
|       /** Determine if the sheet includes a specific skill. */ |       /** Determine if the sheet includes a specific skill. */ | ||||||
|  |       hasSkill(skill) { | ||||||
|     JRSResume.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 JSON Resume schema. */ |       /** Validate the sheet against the JSON Resume schema. */ | ||||||
|  |       isValid() { // TODO: ↓ fix this path ↓ | ||||||
|     JRSResume.prototype.isValid = function() { |  | ||||||
|         var ret, schema, schemaObj, temp, validate; |         var ret, schema, schemaObj, temp, validate; | ||||||
|         schema = FS.readFileSync(PATH.join(__dirname, 'resume.json'), 'utf8'); |         schema = FS.readFileSync(PATH.join(__dirname, 'resume.json'), 'utf8'); | ||||||
|         schemaObj = JSON.parse(schema); |         schemaObj = JSON.parse(schema); | ||||||
|         validator = require('is-my-json-valid'); |         validator = require('is-my-json-valid'); | ||||||
|       validate = validator(schemaObj, { |         validate = validator(schemaObj, { // Note [1] | ||||||
|           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})?)?$/ | ||||||
|           } |           } | ||||||
| @@ -236,19 +195,19 @@ Definition of the JRSResume class. | |||||||
|           this.imp.validationErrors = validate.errors; |           this.imp.validationErrors = validate.errors; | ||||||
|         } |         } | ||||||
|         return ret; |         return ret; | ||||||
|     }; |       } | ||||||
|  |  | ||||||
|     JRSResume.prototype.duration = function(unit) { |  | ||||||
|       return JRSResume.__super__.duration.call(this, 'work', 'startDate', 'endDate', unit); |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|  |       duration(unit) { | ||||||
|  |         var inspector; | ||||||
|  |         inspector = require('../inspectors/duration-inspector'); | ||||||
|  |         return inspector.run(this, 'work', 'startDate', 'endDate', 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() { | ||||||
|     JRSResume.prototype.sort = function() { |  | ||||||
|         var byDateDesc; |         var byDateDesc; | ||||||
|         byDateDesc = function(a, b) { |         byDateDesc = function(a, b) { | ||||||
|           if (a.safeStartDate.isBefore(b.safeStartDate)) { |           if (a.safeStartDate.isBefore(b.safeStartDate)) { | ||||||
| @@ -274,89 +233,69 @@ Definition of the JRSResume class. | |||||||
|             return (a.safeReleaseDate.isAfter(b.safeReleaseDate) && -1) || 0; |             return (a.safeReleaseDate.isAfter(b.safeReleaseDate) && -1) || 0; | ||||||
|           } |           } | ||||||
|         }); |         }); | ||||||
|     }; |       } | ||||||
|  |  | ||||||
|     JRSResume.prototype.dupe = function() { |       dupe() { | ||||||
|         var rnew; |         var rnew; | ||||||
|         rnew = new JRSResume(); |         rnew = new JRSResume(); | ||||||
|         rnew.parse(this.stringify(), {}); |         rnew.parse(this.stringify(), {}); | ||||||
|         return rnew; |         return rnew; | ||||||
|     }; |       } | ||||||
|  |  | ||||||
|  |  | ||||||
|       /** |       /** | ||||||
|       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. | ||||||
|       */ |       */ | ||||||
|  |       harden() { | ||||||
|     JRSResume.prototype.harden = function() { |         var HD, HDIN, ret, transformer; | ||||||
|       var HD, HDIN, hardenStringsInObject, ret, that; |  | ||||||
|       that = this; |  | ||||||
|         ret = this.dupe(); |         ret = this.dupe(); | ||||||
|         HD = function(txt) { |         HD = function(txt) { | ||||||
|           return '@@@@~' + txt + '~@@@@'; |           return '@@@@~' + txt + '~@@@@'; | ||||||
|         }; |         }; | ||||||
|         HDIN = function(txt) { |         HDIN = function(txt) { | ||||||
|  |           //return MD(txt || '' ).replace(/^\s*<p>|<\/p>\s*$/gi, ''); | ||||||
|           return HD(txt); |           return HD(txt); | ||||||
|         }; |         }; | ||||||
|       hardenStringsInObject = function(obj, inline) { |         transformer = require('../utils/string-transformer'); | ||||||
|         if (!obj) { |         return transformer(ret, ['skills', 'url', 'website', 'startDate', 'endDate', 'releaseDate', 'date', 'phone', 'email', 'address', 'postalCode', 'city', 'country', 'region', 'safeStartDate', 'safeEndDate'], function(key, val) { | ||||||
|           return; |           return HD(val); | ||||||
|         } |  | ||||||
|         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]); |     clear = function(clearMeta) { | ||||||
|       }); |       clearMeta = ((clearMeta === void 0) && true) || clearMeta; | ||||||
|       return ret; |       if (clearMeta) { | ||||||
|  |         delete this.imp; | ||||||
|  |       } | ||||||
|  |       delete this.basics.computed; // Don't use Object.keys() here | ||||||
|  |       delete this.work; | ||||||
|  |       delete this.volunteer; | ||||||
|  |       delete this.education; | ||||||
|  |       delete this.awards; | ||||||
|  |       delete this.publications; | ||||||
|  |       delete this.interests; | ||||||
|  |       delete this.skills; | ||||||
|  |       return delete this.basics.profiles; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     return JRSResume; |     return JRSResume; | ||||||
|  |  | ||||||
|   })(AbstractResume); |   }).call(this); | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** 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) { |     replacer = function(key, value) { // Exclude these keys from stringification | ||||||
|       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; | ||||||
| @@ -370,15 +309,6 @@ Definition of the JRSResume class. | |||||||
|     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; | ||||||
| @@ -402,11 +332,9 @@ Definition of the JRSResume class. | |||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|   Export the JRSResume function/ctor. |   Export the JRSResume function/ctor. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
|   module.exports = JRSResume; |   module.exports = JRSResume; | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								dist/core/jrs-theme.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								dist/core/jrs-theme.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the JRSTheme class. |   Definition of the JRSTheme class. | ||||||
|   @module core/jrs-theme |   @module core/jrs-theme | ||||||
|   @license MIT. See LICENSE.MD for details. |   @license MIT. See LICENSE.MD for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var JRSTheme, PATH, _, errors, parsePath, pathExists; |   var JRSTheme, PATH, _, errors, parsePath, pathExists; | ||||||
|  |  | ||||||
|   _ = require('underscore'); |   _ = require('underscore'); | ||||||
| @@ -18,32 +16,30 @@ Definition of the JRSTheme class. | |||||||
|  |  | ||||||
|   errors = require('./status-codes'); |   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 JRS 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); |         thApi = require(thFolder); // Requiring the folder yields whatever the package.json's "main" is set to | ||||||
|         thPkg = require(pkgJsonPath); |         thPkg = require(pkgJsonPath); // Get the package.json as JSON | ||||||
|         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', | ||||||
| @@ -76,32 +72,26 @@ Definition of the JRSTheme class. | |||||||
|         }; |         }; | ||||||
|       } |       } | ||||||
|       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) { | ||||||
|     JRSTheme.prototype.getFormat = function(fmt) { |  | ||||||
|       return this.formats[fmt]; |       return this.formats[fmt]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|     return JRSTheme; |  | ||||||
|  |  | ||||||
|   })(); |  | ||||||
|  |  | ||||||
|   module.exports = JRSTheme; |   module.exports = JRSTheme; | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|   | |||||||
							
								
								
									
										35
									
								
								dist/core/resume-factory.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								dist/core/resume-factory.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,13 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the ResumeFactory class. |   Definition of the ResumeFactory class. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module core/resume-factory |   @module core/resume-factory | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   A simple factory class for FRESH and JSON Resumes. | ||||||
|  |   @class ResumeFactory | ||||||
|  |   */ | ||||||
|   var FS, HME, HMS, ResumeConverter, ResumeFactory, SyntaxErrorEx, _, _parse, chalk, resumeDetect; |   var FS, HME, HMS, ResumeConverter, ResumeFactory, SyntaxErrorEx, _, _parse, chalk, resumeDetect; | ||||||
|  |  | ||||||
|   FS = require('fs'); |   FS = require('fs'); | ||||||
| @@ -26,14 +28,7 @@ Definition of the ResumeFactory class. | |||||||
|  |  | ||||||
|   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. | ||||||
|  |  | ||||||
| @@ -47,31 +42,38 @@ Definition of the ResumeFactory class. | |||||||
|             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.  */ |     /** Load a single resume from disk.  */ | ||||||
|     loadOne: function(src, opts, emitter) { |     loadOne: function(src, opts, emitter) { | ||||||
|       var ResumeClass, info, json, orgFormat, reqLib, rez, toFormat; |       var ResumeClass, info, json, orgFormat, reqLib, rez, toFormat; | ||||||
|       toFormat = opts.format; |       toFormat = opts.format; // Can be null | ||||||
|  |        | ||||||
|  |       // Get the destination format. Can be 'fresh', 'jrs', or null/undefined. | ||||||
|       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); |       orgFormat = resumeDetect(json); | ||||||
|       if (orgFormat === 'unk') { |       if (orgFormat === 'unk') { | ||||||
|         info.fluenterror = HMS.unknownSchema; |         info.fluenterror = HMS.unknownSchema; | ||||||
|         return info; |         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 (opts.objectify) { | ||||||
|         reqLib = '../core/' + (toFormat || orgFormat) + '-resume'; |         reqLib = '../core/' + (toFormat || orgFormat) + '-resume'; | ||||||
| @@ -88,9 +90,10 @@ Definition of the ResumeFactory class. | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   _parse = function(fileName, opts, eve) { |   _parse = function(fileName, opts, eve) { | ||||||
|     var orgFormat, rawData, ret; |     var err, 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 | ||||||
|       }); |       }); | ||||||
| @@ -112,10 +115,12 @@ Definition of the ResumeFactory class. | |||||||
|         fmt: orgFormat |         fmt: orgFormat | ||||||
|       }); |       }); | ||||||
|       return ret; |       return ret; | ||||||
|     } catch (_error) { |     } catch (error) { | ||||||
|  |       err = error; | ||||||
|       return { |       return { | ||||||
|  |         // Can be ENOENT, EACCES, SyntaxError, etc. | ||||||
|         fluenterror: rawData ? HMS.parseError : HMS.readError, |         fluenterror: rawData ? HMS.parseError : HMS.readError, | ||||||
|         inner: _error, |         inner: err, | ||||||
|         raw: rawData, |         raw: rawData, | ||||||
|         file: fileName |         file: fileName | ||||||
|       }; |       }; | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								dist/core/status-codes.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								dist/core/status-codes.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Status codes for HackMyResume. |   Status codes for HackMyResume. | ||||||
|   @module core/status-codes |   @module core/status-codes | ||||||
|   @license MIT. See LICENSE.MD for details. |   @license MIT. See LICENSE.MD for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   module.exports = { |   module.exports = { | ||||||
|     success: 0, |     success: 0, | ||||||
|     themeNotFound: 1, |     themeNotFound: 1, | ||||||
| @@ -37,7 +35,8 @@ Status codes for HackMyResume. | |||||||
|     invalidOptionsFile: 27, |     invalidOptionsFile: 27, | ||||||
|     optionsFileNotFound: 28, |     optionsFileNotFound: 28, | ||||||
|     unknownSchema: 29, |     unknownSchema: 29, | ||||||
|     themeHelperLoad: 30 |     themeHelperLoad: 30, | ||||||
|  |     invalidSchemaVersion: 31 | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								dist/generators/base-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								dist/generators/base-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,39 +1,33 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the BaseGenerator class. |   Definition of the BaseGenerator class. | ||||||
|   @module generators/base-generator |   @module generators/base-generator | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var BaseGenerator; | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|   The BaseGenerator class is the root of the generator hierarchy. Functionality |   The BaseGenerator class is the root of the generator hierarchy. Functionality | ||||||
|   common to ALL generators lives here. |   common to ALL generators lives here. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var BaseGenerator; |  | ||||||
|  |  | ||||||
|   module.exports = BaseGenerator = (function() { |   module.exports = BaseGenerator = (function() { | ||||||
|  |     class BaseGenerator { | ||||||
|       /** Base-class initialize. */ |       /** Base-class initialize. */ | ||||||
|     function BaseGenerator(format) { |       constructor(format) { | ||||||
|         this.format = 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); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								dist/generators/html-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								dist/generators/html-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,10 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the HTMLGenerator class. |   Definition of the HTMLGenerator class. | ||||||
|   @module generators/html-generator |   @module generators/html-generator | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var FS, HTML, HtmlGenerator, PATH, TemplateGenerator; | ||||||
| (function() { |  | ||||||
|   var FS, HTML, HtmlGenerator, PATH, TemplateGenerator, |  | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   TemplateGenerator = require('./template-generator'); |   TemplateGenerator = require('./template-generator'); | ||||||
|  |  | ||||||
| @@ -20,20 +16,16 @@ Definition of the HTMLGenerator class. | |||||||
|  |  | ||||||
|   require('string.prototype.endswith'); |   require('string.prototype.endswith'); | ||||||
|  |  | ||||||
|   module.exports = HtmlGenerator = (function(superClass) { |   module.exports = HtmlGenerator = class HtmlGenerator extends TemplateGenerator { | ||||||
|     extend(HtmlGenerator, superClass); |     constructor() { | ||||||
|  |       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; | ||||||
|       } |       } | ||||||
| @@ -42,12 +34,10 @@ Definition of the HTMLGenerator class. | |||||||
|       } else { |       } else { | ||||||
|         return info.mk; |         return info.mk; | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|     return HtmlGenerator; |  | ||||||
|  |  | ||||||
|   })(TemplateGenerator); |  | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
| //# sourceMappingURL=html-generator.js.map | //# sourceMappingURL=html-generator.js.map | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								dist/generators/html-pdf-cli-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								dist/generators/html-pdf-cli-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,10 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the HtmlPdfCLIGenerator class. |   Definition of the HtmlPdfCLIGenerator class. | ||||||
|   @module generators/html-pdf-generator.js |   @module generators/html-pdf-generator.js | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var FS, HMSTATUS, HtmlPdfCLIGenerator, PATH, SLASH, SPAWN, TemplateGenerator, _, engines; | ||||||
| (function() { |  | ||||||
|   var FS, HMSTATUS, HtmlPdfCLIGenerator, PATH, SLASH, SPAWN, TemplateGenerator, _, engines, |  | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   TemplateGenerator = require('./template-generator'); |   TemplateGenerator = require('./template-generator'); | ||||||
|  |  | ||||||
| @@ -24,26 +20,21 @@ Definition of the HtmlPdfCLIGenerator class. | |||||||
|  |  | ||||||
|   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 { | ||||||
|   module.exports = HtmlPdfCLIGenerator = (function(superClass) { |     constructor() { | ||||||
|     extend(HtmlPdfCLIGenerator, superClass); |       super('pdf', 'html'); | ||||||
|  |  | ||||||
|     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'; | ||||||
| @@ -53,32 +44,27 @@ Definition of the HtmlPdfCLIGenerator class. | |||||||
|       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, info.opts, this.onError); | ||||||
|         return null; |         return null; // halt further processing | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|     }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     /* 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; |   // TODO: Move each engine to a separate module | ||||||
|  |  | ||||||
|   })(TemplateGenerator); |  | ||||||
|  |  | ||||||
|   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 | ||||||
| @@ -88,8 +74,10 @@ Definition of the HtmlPdfCLIGenerator class. | |||||||
|     */ |     */ | ||||||
|     wkhtmltopdf: function(markup, fOut, opts, on_error) { |     wkhtmltopdf: function(markup, fOut, opts, on_error) { | ||||||
|       var tempFile, wkargs, wkopts; |       var tempFile, wkargs, wkopts; | ||||||
|  |       // 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. | ||||||
|       wkopts = _.extend({ |       wkopts = _.extend({ | ||||||
|         'margin-top': '10mm', |         'margin-top': '10mm', | ||||||
|         'margin-bottom': '10mm' |         'margin-bottom': '10mm' | ||||||
| @@ -100,7 +88,6 @@ Definition of the HtmlPdfCLIGenerator class. | |||||||
|       wkargs = wkopts.concat([tempFile, fOut]); |       wkargs = wkopts.concat([tempFile, fOut]); | ||||||
|       SPAWN('wkhtmltopdf', wkargs, false, on_error, this); |       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 | ||||||
| @@ -110,6 +97,7 @@ Definition of the HtmlPdfCLIGenerator class. | |||||||
|     */ |     */ | ||||||
|     phantomjs: function(markup, fOut, opts, on_error) { |     phantomjs: function(markup, fOut, opts, 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')); | ||||||
| @@ -118,7 +106,6 @@ Definition of the HtmlPdfCLIGenerator class. | |||||||
|       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. |     Generate a PDF from HTML using WeasyPrint's CLI interface. | ||||||
|     Spawns a child process with `weasyprint <source> <target>`. Weasy Print |     Spawns a child process with `weasyprint <source> <target>`. Weasy Print | ||||||
| @@ -127,6 +114,7 @@ Definition of the HtmlPdfCLIGenerator class. | |||||||
|     */ |     */ | ||||||
|     weasyprint: function(markup, fOut, opts, on_error) { |     weasyprint: function(markup, fOut, opts, on_error) { | ||||||
|       var tempFile; |       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'); | ||||||
|       SPAWN('weasyprint', [tempFile, fOut], false, on_error, this); |       SPAWN('weasyprint', [tempFile, fOut], false, on_error, this); | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								dist/generators/html-png-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								dist/generators/html-png-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,17 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the HtmlPngGenerator class. |   Definition of the HtmlPngGenerator class. | ||||||
|   @module generators/html-png-generator |   @module generators/html-png-generator | ||||||
|   @license MIT. See LICENSE.MD for details. |   @license MIT. See LICENSE.MD for details. | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   Generate a PDF from HTML using Phantom's CLI interface. | ||||||
|   var FS, HTML, HtmlPngGenerator, PATH, SLASH, SPAWN, TemplateGenerator, phantom, |   Spawns a child process with `phantomjs <script> <source> <target>`. Phantom | ||||||
|     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; }, |   must be installed and path-accessible. | ||||||
|     hasProp = {}.hasOwnProperty; |   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'); | ||||||
|  |  | ||||||
| @@ -22,21 +25,18 @@ Definition of the HtmlPngGenerator class. | |||||||
|  |  | ||||||
|   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 { | ||||||
|   module.exports = HtmlPngGenerator = (function(superClass) { |     constructor() { | ||||||
|     extend(HtmlPngGenerator, superClass); |       super('png', 'html'); | ||||||
|  |  | ||||||
|     function HtmlPngGenerator() { |  | ||||||
|       HtmlPngGenerator.__super__.constructor.call(this, 'png', 'html'); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     HtmlPngGenerator.prototype.invoke = function(rez, themeMarkup, cssInfo, opts) {}; |     invoke(rez, themeMarkup, cssInfo, opts) {} | ||||||
|  |  | ||||||
|     HtmlPngGenerator.prototype.generate = function(rez, f, opts) { |     // TODO: Not currently called or callable. | ||||||
|  |     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,23 +45,13 @@ Definition of the HtmlPngGenerator class. | |||||||
|         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'))); | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								dist/generators/json-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								dist/generators/json-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,10 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the JsonGenerator class. |   Definition of the JsonGenerator class. | ||||||
|   @module generators/json-generator |   @module generators/json-generator | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var BaseGenerator, FJCV, FS, JsonGenerator, _; | ||||||
| (function() { |  | ||||||
|   var BaseGenerator, FJCV, FS, JsonGenerator, _, |  | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   BaseGenerator = require('./base-generator'); |   BaseGenerator = require('./base-generator'); | ||||||
|  |  | ||||||
| @@ -18,30 +14,25 @@ Definition of the JsonGenerator class. | |||||||
|  |  | ||||||
|   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 { | ||||||
|   module.exports = JsonGenerator = (function(superClass) { |     constructor() { | ||||||
|     extend(JsonGenerator, superClass); |       super('json'); | ||||||
|  |  | ||||||
|     function JsonGenerator() { |  | ||||||
|       JsonGenerator.__super__.constructor.call(this, 'json'); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     JsonGenerator.prototype.invoke = function(rez) { |     invoke(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); | ||||||
|     }; |     } | ||||||
|  |  | ||||||
|     JsonGenerator.prototype.generate = function(rez, f) { |     //altRez.stringify() | ||||||
|  |     generate(rez, f) { | ||||||
|       FS.writeFileSync(f, this.invoke(rez), 'utf8'); |       FS.writeFileSync(f, this.invoke(rez), 'utf8'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|     return JsonGenerator; |  | ||||||
|  |  | ||||||
|   })(BaseGenerator); |  | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
| //# sourceMappingURL=json-generator.js.map | //# sourceMappingURL=json-generator.js.map | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								dist/generators/json-yaml-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								dist/generators/json-yaml-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,10 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the JsonYamlGenerator class. |   Definition of the JsonYamlGenerator class. | ||||||
|   @module generators/json-yaml-generator |   @module generators/json-yaml-generator | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var BaseGenerator, FS, JsonYamlGenerator, YAML; | ||||||
| (function() { |  | ||||||
|   var BaseGenerator, FS, JsonYamlGenerator, YAML, |  | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   BaseGenerator = require('./base-generator'); |   BaseGenerator = require('./base-generator'); | ||||||
|  |  | ||||||
| @@ -16,35 +12,29 @@ Definition of the JsonYamlGenerator class. | |||||||
|  |  | ||||||
|   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 { | ||||||
|   module.exports = JsonYamlGenerator = (function(superClass) { |     constructor() { | ||||||
|     extend(JsonYamlGenerator, superClass); |       super('yml'); | ||||||
|  |  | ||||||
|     function JsonYamlGenerator() { |  | ||||||
|       JsonYamlGenerator.__super__.constructor.call(this, 'yml'); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     JsonYamlGenerator.prototype.invoke = function(rez, themeMarkup, cssInfo, opts) { |     invoke(rez, themeMarkup, cssInfo, opts) { | ||||||
|       return YAML.stringify(JSON.parse(rez.stringify()), Infinity, 2); |       return YAML.stringify(JSON.parse(rez.stringify()), 2e308, 2); | ||||||
|     }; |     } | ||||||
|  |  | ||||||
|     JsonYamlGenerator.prototype.generate = function(rez, f, opts) { |     generate(rez, f, opts) { | ||||||
|       var data; |       var data; | ||||||
|       data = YAML.stringify(JSON.parse(rez.stringify()), Infinity, 2); |       data = YAML.stringify(JSON.parse(rez.stringify()), 2e308, 2); | ||||||
|       FS.writeFileSync(f, data, 'utf8'); |       FS.writeFileSync(f, data, 'utf8'); | ||||||
|       return data; |       return data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|     return JsonYamlGenerator; |  | ||||||
|  |  | ||||||
|   })(BaseGenerator); |  | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
| //# sourceMappingURL=json-yaml-generator.js.map | //# sourceMappingURL=json-yaml-generator.js.map | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								dist/generators/latex-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								dist/generators/latex-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,32 +1,22 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the LaTeXGenerator class. |   Definition of the LaTeXGenerator class. | ||||||
|   @module generators/latex-generator |   @module generators/latex-generator | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var LaTeXGenerator, TemplateGenerator; | ||||||
| (function() { |  | ||||||
|   var LaTeXGenerator, TemplateGenerator, |  | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   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 { | ||||||
|   module.exports = LaTeXGenerator = (function(superClass) { |     constructor() { | ||||||
|     extend(LaTeXGenerator, superClass); |       super('latex', 'tex'); | ||||||
|  |  | ||||||
|     function LaTeXGenerator() { |  | ||||||
|       LaTeXGenerator.__super__.constructor.call(this, 'latex', 'tex'); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return LaTeXGenerator; |   }; | ||||||
|  |  | ||||||
|   })(TemplateGenerator); |  | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								dist/generators/markdown-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								dist/generators/markdown-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,32 +1,22 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the MarkdownGenerator class. |   Definition of the MarkdownGenerator class. | ||||||
|   @module generators/markdown-generator |   @module generators/markdown-generator | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var MarkdownGenerator, TemplateGenerator; | ||||||
| (function() { |  | ||||||
|   var MarkdownGenerator, TemplateGenerator, |  | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   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 { | ||||||
|   module.exports = MarkdownGenerator = (function(superClass) { |     constructor() { | ||||||
|     extend(MarkdownGenerator, superClass); |       super('md', 'txt'); | ||||||
|  |  | ||||||
|     function MarkdownGenerator() { |  | ||||||
|       MarkdownGenerator.__super__.constructor.call(this, 'md', 'txt'); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return MarkdownGenerator; |   }; | ||||||
|  |  | ||||||
|   })(TemplateGenerator); |  | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										106
									
								
								dist/generators/template-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										106
									
								
								dist/generators/template-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,13 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the TemplateGenerator class. TODO: Refactor |   Definition of the TemplateGenerator class. TODO: Refactor | ||||||
|   @module generators/template-generator |   @module generators/template-generator | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   /** Default template generator options. */ | ||||||
| (function() { |   /** Freeze newlines for protection against errant JST parsers. */ | ||||||
|   var BaseGenerator, EXTEND, FRESHTheme, FS, JRSTheme, MD, MKDIRP, PATH, TemplateGenerator, XML, _, _defaultOpts, _reg, createSymLinks, freeze, parsePath, unfreeze, |   /** Unfreeze newlines when the coast is clear. */ | ||||||
|     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; }, |   var BaseGenerator, EXTEND, FRESHTheme, FS, JRSTheme, MD, MKDIRP, PATH, TemplateGenerator, XML, _, _defaultOpts, _reg, createSymLinks, freeze, parsePath, unfreeze; | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   FS = require('fs-extra'); |   FS = require('fs-extra'); | ||||||
|  |  | ||||||
| @@ -32,46 +31,38 @@ Definition of the TemplateGenerator class. TODO: Refactor | |||||||
|  |  | ||||||
|   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') { | ||||||
| @@ -95,25 +86,30 @@ Definition of the TemplateGenerator class. TODO: Refactor | |||||||
|       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) { | ||||||
| @@ -129,7 +125,9 @@ Definition of the TemplateGenerator class. TODO: Refactor | |||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         if (typeof opts.beforeWrite === "function") { |         if (typeof opts.beforeWrite === "function") { | ||||||
|           opts.beforeWrite(thisFilePath); |           opts.beforeWrite({ | ||||||
|  |             data: thisFilePath | ||||||
|  |           }); | ||||||
|         } |         } | ||||||
|         MKDIRP.sync(PATH.dirname(thisFilePath)); |         MKDIRP.sync(PATH.dirname(thisFilePath)); | ||||||
|         if (file.info.action !== 'copy') { |         if (file.info.action !== 'copy') { | ||||||
| @@ -141,8 +139,11 @@ Definition of the TemplateGenerator class. TODO: Refactor | |||||||
|           FS.copySync(file.info.path, thisFilePath); |           FS.copySync(file.info.path, thisFilePath); | ||||||
|         } |         } | ||||||
|         if (typeof opts.afterWrite === "function") { |         if (typeof opts.afterWrite === "function") { | ||||||
|           opts.afterWrite(thisFilePath); |           opts.afterWrite({ | ||||||
|  |             data: thisFilePath | ||||||
|  |           }); | ||||||
|         } |         } | ||||||
|  |         // Post-processing | ||||||
|         if (this.onAfterSave) { |         if (this.onAfterSave) { | ||||||
|           return this.onAfterSave({ |           return this.onAfterSave({ | ||||||
|             outputFile: fileName, |             outputFile: fileName, | ||||||
| @@ -151,10 +152,10 @@ Definition of the TemplateGenerator class. TODO: Refactor | |||||||
|           }); |           }); | ||||||
|         } |         } | ||||||
|       }, 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. | ||||||
| @@ -162,10 +163,8 @@ Definition of the TemplateGenerator class. TODO: Refactor | |||||||
|     @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); | ||||||
| @@ -176,29 +175,30 @@ Definition of the TemplateGenerator class. TODO: Refactor | |||||||
|         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, succeeded, type; |         var absLoc, absTarg, err, 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 (_error.code === 'EEXIST') { |           if (err.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,31 +208,22 @@ Definition of the TemplateGenerator class. TODO: Refactor | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** 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;', |     nSym: '&newl;', // newline entity | ||||||
|     rSym: '&retn;', |     rSym: '&retn;', // return entity | ||||||
|     template: { |     template: { | ||||||
|       interpolate: /\{\{(.+?)\}\}/g, |       interpolate: /\{\{(.+?)\}\}/g, | ||||||
|       escape: /\{\{\=(.+?)\}\}/g, |       escape: /\{\{\=(.+?)\}\}/g, | ||||||
| @@ -269,13 +260,12 @@ Definition of the TemplateGenerator class. TODO: Refactor | |||||||
|     prettify: { |     prettify: { | ||||||
|       indent_size: 2, |       indent_size: 2, | ||||||
|       unformatted: ['em', 'strong', 'a'], |       unformatted: ['em', 'strong', 'a'], | ||||||
|       max_char: 80 |       max_char: 80 // ← See lib/html.js in above-linked repo | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   //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'), | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								dist/generators/text-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								dist/generators/text-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,32 +1,22 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the TextGenerator class. |   Definition of the TextGenerator class. | ||||||
|   @module generators/text-generator |   @module generators/text-generator | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var TemplateGenerator, TextGenerator; | ||||||
| (function() { |  | ||||||
|   var TemplateGenerator, TextGenerator, |  | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   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 { | ||||||
|   module.exports = TextGenerator = (function(superClass) { |     constructor() { | ||||||
|     extend(TextGenerator, superClass); |       super('txt'); | ||||||
|  |  | ||||||
|     function TextGenerator() { |  | ||||||
|       TextGenerator.__super__.constructor.call(this, 'txt'); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return TextGenerator; |   }; | ||||||
|  |  | ||||||
|   })(TemplateGenerator); |  | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								dist/generators/word-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								dist/generators/word-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,27 +1,19 @@ | |||||||
|  | (function() { | ||||||
|   /* |   /* | ||||||
|   Definition of the WordGenerator class. |   Definition of the WordGenerator class. | ||||||
|   @module generators/word-generator |   @module generators/word-generator | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var TemplateGenerator, WordGenerator; | ||||||
| (function() { |  | ||||||
|   var TemplateGenerator, WordGenerator, |  | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   TemplateGenerator = require('./template-generator'); |   TemplateGenerator = require('./template-generator'); | ||||||
|  |  | ||||||
|   module.exports = WordGenerator = (function(superClass) { |   module.exports = WordGenerator = class WordGenerator extends TemplateGenerator { | ||||||
|     extend(WordGenerator, superClass); |     constructor() { | ||||||
|  |       super('doc', 'xml'); | ||||||
|     function WordGenerator() { |  | ||||||
|       WordGenerator.__super__.constructor.call(this, 'doc', 'xml'); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return WordGenerator; |   }; | ||||||
|  |  | ||||||
|   })(TemplateGenerator); |  | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								dist/generators/xml-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								dist/generators/xml-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,30 +1,20 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the XMLGenerator class. |   Definition of the XMLGenerator class. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module generatprs/xml-generator |   @module generatprs/xml-generator | ||||||
|   */ |   */ | ||||||
|  |   var BaseGenerator, XMLGenerator; | ||||||
| (function() { |  | ||||||
|   var BaseGenerator, XMLGenerator, |  | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   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 { | ||||||
|   module.exports = XMLGenerator = (function(superClass) { |     constructor() { | ||||||
|     extend(XMLGenerator, superClass); |       super('xml'); | ||||||
|  |  | ||||||
|     function XMLGenerator() { |  | ||||||
|       XMLGenerator.__super__.constructor.call(this, 'xml'); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return XMLGenerator; |   }; | ||||||
|  |  | ||||||
|   })(BaseGenerator); |  | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								dist/generators/yaml-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								dist/generators/yaml-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,32 +1,22 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the YAMLGenerator class. |   Definition of the YAMLGenerator class. | ||||||
|   @module yaml-generator.js |   @module yaml-generator.js | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var TemplateGenerator, YAMLGenerator; | ||||||
| (function() { |  | ||||||
|   var TemplateGenerator, YAMLGenerator, |  | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   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 { | ||||||
|   module.exports = YAMLGenerator = (function(superClass) { |     constructor() { | ||||||
|     extend(YAMLGenerator, superClass); |       super('yml', 'yml'); | ||||||
|  |  | ||||||
|     function YAMLGenerator() { |  | ||||||
|       YAMLGenerator.__super__.constructor.call(this, 'yml', 'yml'); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return YAMLGenerator; |   }; | ||||||
|  |  | ||||||
|   })(TemplateGenerator); |  | ||||||
|  |  | ||||||
| }).call(this); | }).call(this); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								dist/helpers/block-helpers.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								dist/helpers/block-helpers.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,10 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Block helper definitions for HackMyResume / FluentCV. |   Block helper definitions for HackMyResume / FluentCV. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module helpers/generic-helpers |   @module helpers/generic-helpers | ||||||
|   */ |   */ | ||||||
|  |   /** Block helper function definitions. */ | ||||||
| (function() { |  | ||||||
|   var BlockHelpers, HMSTATUS, LO, _, unused; |   var BlockHelpers, HMSTATUS, LO, _, unused; | ||||||
|  |  | ||||||
|   HMSTATUS = require('../core/status-codes'); |   HMSTATUS = require('../core/status-codes'); | ||||||
| @@ -16,11 +15,7 @@ Block helper definitions for HackMyResume / FluentCV. | |||||||
|  |  | ||||||
|   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 ''. | ||||||
| @@ -43,7 +38,16 @@ Block helper definitions for HackMyResume / FluentCV. | |||||||
|       } |       } | ||||||
|       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. | ||||||
| @@ -54,7 +58,6 @@ Block helper definitions for HackMyResume / FluentCV. | |||||||
|         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 | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								dist/helpers/console-helpers.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								dist/helpers/console-helpers.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Generic template helper definitions for command-line output. |   Generic template helper definitions for command-line output. | ||||||
|   @module console-helpers.js |   @module console-helpers.js | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var CHALK, LO, PAD, _, consoleFormatHelpers; |   var CHALK, LO, PAD, _, consoleFormatHelpers; | ||||||
|  |  | ||||||
|   PAD = require('string-padding'); |   PAD = require('string-padding'); | ||||||
| @@ -21,7 +19,7 @@ Generic template helper definitions for command-line output. | |||||||
|   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); | ||||||
|   | |||||||
							
								
								
									
										168
									
								
								dist/helpers/generic-helpers.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										168
									
								
								dist/helpers/generic-helpers.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,12 +1,18 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Generic template helper definitions for HackMyResume / FluentCV. |   Generic template helper definitions for HackMyResume / FluentCV. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module helpers/generic-helpers |   @module helpers/generic-helpers | ||||||
|   */ |   */ | ||||||
|  |   /** Generic template helper function definitions. */ | ||||||
| (function() { |   /** | ||||||
|   var FS, FluentDate, GenericHelpers, H2W, HMSTATUS, LO, MD, PATH, XML, _, _fromTo, _reportError, moment, printf, skillLevelToIndex, unused; |   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'); | ||||||
|  |  | ||||||
| @@ -32,11 +38,7 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|  |  | ||||||
|   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 | ||||||
| @@ -58,22 +60,32 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|       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. | ||||||
| @@ -107,7 +119,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|       } |       } | ||||||
|       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. | ||||||
| @@ -118,7 +129,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|       } |       } | ||||||
|       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 | ||||||
| @@ -126,7 +136,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|     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 | ||||||
| @@ -150,7 +159,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         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 | ||||||
| @@ -170,18 +178,22 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|       } 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; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| @@ -200,7 +212,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|       } |       } | ||||||
|       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. | ||||||
| @@ -220,19 +231,25 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|           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; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| @@ -250,18 +267,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|       } |       } | ||||||
|       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 = ''; | ||||||
| @@ -280,14 +285,18 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         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; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| @@ -306,11 +315,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|       } |       } | ||||||
|       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) { | ||||||
| @@ -319,7 +323,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         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. | ||||||
| @@ -341,11 +344,14 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|     @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 ''; | ||||||
| @@ -356,7 +362,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|       txt = H2W(txt); |       txt = H2W(txt); | ||||||
|       return txt; |       return txt; | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|     Emit a conditional link. |     Emit a conditional link. | ||||||
|     @method link |     @method link | ||||||
| @@ -368,7 +373,17 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         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 | ||||||
| @@ -380,7 +395,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         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 | ||||||
| @@ -391,21 +405,19 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|     */ |     */ | ||||||
|     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 | ||||||
| @@ -417,7 +429,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         return ''; |         return ''; | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|     Trim the protocol (http or https) from a URL/ |     Trim the protocol (http or https) from a URL/ | ||||||
|     @method trimURL |     @method trimURL | ||||||
| @@ -429,7 +440,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         return ''; |         return ''; | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|     Convert text to lowercase. |     Convert text to lowercase. | ||||||
|     @method toLower |     @method toLower | ||||||
| @@ -441,7 +451,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         return ''; |         return ''; | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|     Convert text to lowercase. |     Convert text to lowercase. | ||||||
|     @method toLower |     @method toLower | ||||||
| @@ -453,7 +462,6 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         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 | ||||||
| @@ -465,6 +473,7 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|     */ |     */ | ||||||
|     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') { | ||||||
| @@ -474,12 +483,15 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         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 | ||||||
| @@ -527,6 +539,9 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         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 || ''; | ||||||
| @@ -541,26 +556,43 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|         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' | ||||||
| @@ -570,6 +602,7 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|     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(); | ||||||
| @@ -599,7 +632,7 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|     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)) { | ||||||
| @@ -630,6 +663,25 @@ Generic template helper definitions for HackMyResume / FluentCV. | |||||||
|     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 | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								dist/helpers/handlebars-helpers.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								dist/helpers/handlebars-helpers.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Template helper definitions for Handlebars. |   Template helper definitions for Handlebars. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module handlebars-helpers.js |   @module handlebars-helpers.js | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var HANDLEBARS, HMS, _, blockHelpers, helpers, path; |   var HANDLEBARS, HMS, _, blockHelpers, helpers, path; | ||||||
|  |  | ||||||
|   HANDLEBARS = require('handlebars'); |   HANDLEBARS = require('handlebars'); | ||||||
| @@ -20,32 +18,38 @@ Template helper definitions for Handlebars. | |||||||
|  |  | ||||||
|   HMS = require('../core/status-codes'); |   HMS = require('../core/status-codes'); | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|   Register useful Handlebars helpers. |   Register useful Handlebars helpers. | ||||||
|   @method registerHelpers |   @method registerHelpers | ||||||
|   */ |   */ | ||||||
|  |   module.exports = function(theme, rez, opts) { | ||||||
|   module.exports = function(theme, opts) { |  | ||||||
|     var curGlob, ex, glob, slash, wrappedHelpers; |     var curGlob, ex, glob, slash, 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)) { | ||||||
|         _.wrap(hVal, function(func) { |         return _.wrap(hVal, function(func) { | ||||||
|           var args; |           var args; | ||||||
|           args = Array.prototype.slice.call(arguments); |           args = Array.prototype.slice.call(arguments); | ||||||
|           args.shift(); |           args.shift(); // lose the 1st element (func) [^1] | ||||||
|           args.pop(); |           //args.pop()                   # lose the last element (HB options hash) | ||||||
|           return func.apply(this, args); |           args[args.length - 1] = rez; // replace w/ resume object | ||||||
|  |           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)) { |     if (_.isString(theme.helpers)) { | ||||||
|  |       // Register any theme-provided custom helpers... | ||||||
|  |  | ||||||
|  |       // Normalize "theme.helpers" (string or array) to an array | ||||||
|       theme.helpers = [theme.helpers]; |       theme.helpers = [theme.helpers]; | ||||||
|     } |     } | ||||||
|     if (_.isArray(theme.helpers)) { |     if (_.isArray(theme.helpers)) { | ||||||
| @@ -53,14 +57,14 @@ Template helper definitions for Handlebars. | |||||||
|       slash = require('slash'); |       slash = require('slash'); | ||||||
|       curGlob = null; |       curGlob = null; | ||||||
|       try { |       try { | ||||||
|         _.each(theme.helpers, function(fGlob) { |         _.each(theme.helpers, function(fGlob) { // foreach theme.helpers entry | ||||||
|           var files; |           var files; | ||||||
|           curGlob = fGlob; |           curGlob = fGlob; // ..cache in case of exception | ||||||
|           fGlob = path.join(theme.folder, fGlob); |           fGlob = path.join(theme.folder, fGlob); // ..make relative to theme | ||||||
|           files = glob.sync(slash(fGlob)); |           files = glob.sync(slash(fGlob)); // ..expand the glob | ||||||
|           if (files.length > 0) { |           if (files.length > 0) { // ..guard against empty glob | ||||||
|             _.each(files, function(f) { |             _.each(files, function(f) { // ..loop over concrete paths | ||||||
|               HANDLEBARS.registerHelper(require(f)); |               HANDLEBARS.registerHelper(require(f)); // ..register the path | ||||||
|             }); |             }); | ||||||
|           } else { |           } else { | ||||||
|             throw { |             throw { | ||||||
| @@ -70,8 +74,8 @@ Template helper definitions for Handlebars. | |||||||
|             }; |             }; | ||||||
|           } |           } | ||||||
|         }); |         }); | ||||||
|       } catch (_error) { |       } catch (error) { | ||||||
|         ex = _error; |         ex = error; | ||||||
|         throw { |         throw { | ||||||
|           fluenterror: HMS.themeHelperLoad, |           fluenterror: HMS.themeHelperLoad, | ||||||
|           inner: ex, |           inner: ex, | ||||||
| @@ -82,6 +86,12 @@ Template helper definitions for Handlebars. | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   // [^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 | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								dist/helpers/underscore-helpers.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								dist/helpers/underscore-helpers.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Template helper definitions for Underscore. |   Template helper definitions for Underscore. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module handlebars-helpers.js |   @module handlebars-helpers.js | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var HANDLEBARS, _, helpers; |   var HANDLEBARS, _, helpers; | ||||||
|  |  | ||||||
|   HANDLEBARS = require('handlebars'); |   HANDLEBARS = require('handlebars'); | ||||||
| @@ -14,12 +12,10 @@ Template helper definitions for Underscore. | |||||||
|  |  | ||||||
|   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; | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,21 +1,17 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   External API surface for HackMyResume. |   External API surface for HackMyResume. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module hackmycore/index |   @module hackmycore/index | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** API facade for HackMyResume. */ |   /** API facade for HackMyResume. */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   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: { | ||||||
|   | |||||||
							
								
								
									
										65
									
								
								dist/inspectors/duration-inspector.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								dist/inspectors/duration-inspector.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | |||||||
|  | (function() { | ||||||
|  |   var FluentDate, _, lo; | ||||||
|  |  | ||||||
|  |   FluentDate = require('../core/fluent-date'); | ||||||
|  |  | ||||||
|  |   _ = require('underscore'); | ||||||
|  |  | ||||||
|  |   lo = require('lodash'); | ||||||
|  |  | ||||||
|  |   module.exports = { | ||||||
|  |     /** | ||||||
|  |     Compute the total duration of the work history. | ||||||
|  |     @returns The total duration of the sheet's work history, that is, the number | ||||||
|  |     of years between the start date of the earliest job on the resume and the | ||||||
|  |     *latest end date of all jobs in the work history*. This last condition is for | ||||||
|  |     sheets that have overlapping jobs. | ||||||
|  |      */ | ||||||
|  |     run: function(rez, collKey, startKey, endKey, unit) { | ||||||
|  |       var firstDate, hist, lastDate, new_e; | ||||||
|  |       unit = unit || 'years'; | ||||||
|  |       hist = lo.get(rez, collKey); | ||||||
|  |       if (!hist || !hist.length) { | ||||||
|  |         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) { | ||||||
|  |         var obj; | ||||||
|  |         obj = _.pick(job, [startKey, endKey]); | ||||||
|  |         if (!_.has(obj, endKey)) { | ||||||
|  |           // Synthesize an end date if this is a "current" gig | ||||||
|  |           obj[endKey] = 'current'; | ||||||
|  |         } | ||||||
|  |         if (obj && (obj[startKey] || obj[endKey])) { | ||||||
|  |           obj = _.pairs(obj); | ||||||
|  |           obj[0][1] = FluentDate.fmt(obj[0][1]); | ||||||
|  |           if (obj.length > 1) { | ||||||
|  |             obj[1][1] = FluentDate.fmt(obj[1][1]); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         return obj; | ||||||
|  |       }); | ||||||
|  |       // Flatten the array, remove empties, and sort | ||||||
|  |       new_e = _.filter(_.flatten(new_e, true), function(v) { | ||||||
|  |         return v && v.length && v[0] && v[0].length; | ||||||
|  |       }); | ||||||
|  |       if (!new_e || !new_e.length) { | ||||||
|  |         return 0; | ||||||
|  |       } | ||||||
|  |       new_e = _.sortBy(new_e, function(elem) { | ||||||
|  |         return elem[1].unix(); | ||||||
|  |       }); | ||||||
|  |       // END CODE DUPLICATION | ||||||
|  |       firstDate = _.first(new_e)[1]; | ||||||
|  |       lastDate = _.last(new_e)[1]; | ||||||
|  |       return lastDate.diff(firstDate, unit); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  | }).call(this); | ||||||
|  |  | ||||||
|  | //# sourceMappingURL=duration-inspector.js.map | ||||||
							
								
								
									
										32
									
								
								dist/inspectors/gap-inspector.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								dist/inspectors/gap-inspector.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,12 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Employment gap analysis for HackMyResume. |   Employment gap analysis for HackMyResume. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module inspectors/gap-inspector |   @module inspectors/gap-inspector | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   Identify gaps in the candidate's employment history. | ||||||
|  |   */ | ||||||
|   var FluentDate, LO, _, gapInspector, moment; |   var FluentDate, LO, _, gapInspector, moment; | ||||||
|  |  | ||||||
|   _ = require('underscore'); |   _ = require('underscore'); | ||||||
| @@ -16,14 +17,8 @@ Employment gap analysis for HackMyResume. | |||||||
|  |  | ||||||
|   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 | ||||||
| @@ -38,6 +33,7 @@ Employment gap analysis for HackMyResume. | |||||||
|     */ |     */ | ||||||
|     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: [], | ||||||
| @@ -48,10 +44,14 @@ Employment gap analysis for HackMyResume. | |||||||
|           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,6 +64,7 @@ Employment gap analysis for HackMyResume. | |||||||
|         } |         } | ||||||
|         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; | ||||||
|       }); |       }); | ||||||
| @@ -73,6 +74,11 @@ Employment gap analysis for HackMyResume. | |||||||
|       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; | ||||||
| @@ -81,11 +87,13 @@ Employment gap analysis for HackMyResume. | |||||||
|         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) { | ||||||
| @@ -93,11 +101,13 @@ Employment gap analysis for HackMyResume. | |||||||
|             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) { | ||||||
| @@ -109,6 +119,9 @@ Employment gap analysis for HackMyResume. | |||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|  |       // 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) { | ||||||
| @@ -123,6 +136,7 @@ Employment gap analysis for HackMyResume. | |||||||
|           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, | ||||||
|   | |||||||
							
								
								
									
										39
									
								
								dist/inspectors/keyword-inspector.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								dist/inspectors/keyword-inspector.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,30 +1,24 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Keyword analysis for HackMyResume. |   Keyword analysis for HackMyResume. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module inspectors/keyword-inspector |   @module inspectors/keyword-inspector | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var FluentDate, _, keywordInspector; |  | ||||||
|  |  | ||||||
|   _ = require('underscore'); |  | ||||||
|  |  | ||||||
|   FluentDate = require('../core/fluent-date'); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|   Analyze the resume's use of keywords. |   Analyze the resume's use of keywords. | ||||||
|   TODO: BUG: Keyword search regex is inaccurate, especially for one or two |   TODO: BUG: Keyword search regex is inaccurate, especially for one or two | ||||||
|   letter keywords like "C" or "CLI". |   letter keywords like "C" or "CLI". | ||||||
|   @class keywordInspector |   @class keywordInspector | ||||||
|   */ |   */ | ||||||
|  |   var FluentDate, _, keywordInspector; | ||||||
|  |  | ||||||
|  |   _ = require('underscore'); | ||||||
|  |  | ||||||
|  |   FluentDate = require('../core/fluent-date'); | ||||||
|  |  | ||||||
|   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 | ||||||
| @@ -32,17 +26,38 @@ Keyword analysis for HackMyResume. | |||||||
|     */ |     */ | ||||||
|     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; | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								dist/inspectors/totals-inspector.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								dist/inspectors/totals-inspector.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,26 +1,21 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Section analysis for HackMyResume. |   Section analysis for HackMyResume. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module inspectors/totals-inspector |   @module inspectors/totals-inspector | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   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 | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								dist/renderers/handlebars-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								dist/renderers/handlebars-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,13 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the HandlebarsGenerator class. |   Definition of the HandlebarsGenerator class. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module renderers/handlebars-generator |   @module renderers/handlebars-generator | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   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'); | ||||||
| @@ -26,33 +28,28 @@ Definition of the HandlebarsGenerator class. | |||||||
|  |  | ||||||
|   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 template; |       var err, 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 || false |           noEscape: data.opts.noescape | ||||||
|         }); |         }); | ||||||
|         return template(data); |         return template(data); | ||||||
|       } catch (_error) { |       } catch (error1) { | ||||||
|  |         err = error1; | ||||||
|         throw { |         throw { | ||||||
|           fluenterror: HMSTATUS[template ? 'invokeTemplate' : 'compileTemplate'], |           fluenterror: HMSTATUS[template ? 'invokeTemplate' : 'compileTemplate'], | ||||||
|           inner: _error |           inner: err | ||||||
|         }; |         }; | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     generate: function(json, jst, format, curFmt, opts, theme) { |     generate: function(json, jst, format, curFmt, opts, theme) { | ||||||
|       var ctx, encData; |       var ctx, encData; | ||||||
|       registerPartials(format, theme); |       // Preprocess text | ||||||
|       registerHelpers(theme, opts); |  | ||||||
|       encData = json; |       encData = json; | ||||||
|       if (format === 'html' || format === 'pdf') { |       if (format === 'html' || format === 'pdf') { | ||||||
|         encData = json.markdownify(); |         encData = json.markdownify(); | ||||||
| @@ -60,6 +57,10 @@ Definition of the HandlebarsGenerator class. | |||||||
|       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, | ||||||
| @@ -70,6 +71,7 @@ Definition of the HandlebarsGenerator class. | |||||||
|         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); | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
| @@ -77,7 +79,10 @@ Definition of the HandlebarsGenerator class. | |||||||
|   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) { | ||||||
| @@ -90,6 +95,7 @@ Definition of the HandlebarsGenerator class. | |||||||
|         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'); | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								dist/renderers/jrs-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								dist/renderers/jrs-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,13 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the JRSGenerator class. |   Definition of the JRSGenerator class. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module renderers/jrs-generator |   @module renderers/jrs-generator | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   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'); | ||||||
| @@ -26,15 +28,10 @@ Definition of the JRSGenerator class. | |||||||
|  |  | ||||||
|   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; | ||||||
| @@ -42,17 +39,20 @@ Definition of the JRSGenerator class. | |||||||
|         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]; | ||||||
|       }); |       }); | ||||||
|       return rezHtml = rezHtml.replace(/@@@@~.*?~@@@@/gm, function(val) { |       // Unfreeze and apply Markdown | ||||||
|         return MDIN(val.replace(/~@@@@/gm, '').replace(/@@@@~/gm, '')); |       return rezHtml = rezHtml.replace(/@@@@~[\s\S]*?~@@@@/g, function(val) { | ||||||
|  |         return MDIN(val.replace(/~@@@@/g, '').replace(/@@@@~/g, '')); | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   MDIN = function(txt) { |   MDIN = function(txt) { // TODO: Move this | ||||||
|     return MD(txt || '').replace(/^\s*<p>|<\/p>\s*$/gi, ''); |     return MD(txt || '').replace(/^\s*<p>|<\/p>\s*$/gi, ''); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								dist/renderers/underscore-generator.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								dist/renderers/underscore-generator.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,13 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the UnderscoreGenerator class. |   Definition of the UnderscoreGenerator class. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module underscore-generator.js |   @module underscore-generator.js | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   Perform template-based resume generation using Underscore.js. | ||||||
|  |   @class UnderscoreGenerator | ||||||
|  |   */ | ||||||
|   var UnderscoreGenerator, _, escapeLaTeX, registerHelpers; |   var UnderscoreGenerator, _, escapeLaTeX, registerHelpers; | ||||||
|  |  | ||||||
|   _ = require('underscore'); |   _ = require('underscore'); | ||||||
| @@ -16,28 +18,26 @@ Definition of the UnderscoreGenerator class. | |||||||
|  |  | ||||||
|   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, t; |       var HMS, err, 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: _error |           inner: err | ||||||
|         }; |         }; | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     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,16 +68,20 @@ Definition of the UnderscoreGenerator class. | |||||||
|         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); | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								dist/utils/file-contains.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								dist/utils/file-contains.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,10 +1,8 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the SyntaxErrorEx class. |   Definition of the SyntaxErrorEx class. | ||||||
|   @module file-contains.js |   @module file-contains.js | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   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
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								dist/utils/fresh-version-regex.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | (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 | ||||||
							
								
								
									
										12
									
								
								dist/utils/html-to-wpml.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								dist/utils/html-to-wpml.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,12 +1,12 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the Markdown to WordProcessingML conversion routine. |   Definition of the Markdown to WordProcessingML conversion routine. | ||||||
|   @license MIT. Copyright (c) 2015 James Devlin / FluentDesk. |   @license MIT. Copyright (c) 2015 James Devlin / FluentDesk. | ||||||
|   @module utils/html-to-wpml |   @module utils/html-to-wpml | ||||||
|   */ |   */ | ||||||
|  |   var HTML5Tokenizer, XML, _; | ||||||
|  |  | ||||||
| (function() { |   XML = require('xml-escape'); | ||||||
|   var HTML5Tokenizer, _; |  | ||||||
|  |  | ||||||
|   _ = require('underscore'); |   _ = require('underscore'); | ||||||
|  |  | ||||||
| @@ -14,8 +14,12 @@ Definition of the Markdown to WordProcessingML conversion routine. | |||||||
|  |  | ||||||
|   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) { | ||||||
| @@ -51,7 +55,7 @@ Definition of the Markdown to WordProcessingML conversion routine. | |||||||
|             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>' + 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>' + XML(tok.chars) + '</w:t></w:r>' + (is_link ? '</w:hlink>' : ''); | ||||||
|           } |           } | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								dist/utils/md2chalk.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								dist/utils/md2chalk.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Inline Markdown-to-Chalk conversion routines. |   Inline Markdown-to-Chalk conversion routines. | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   @module utils/md2chalk |   @module utils/md2chalk | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   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,4 +1,7 @@ | |||||||
| (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; | ||||||
|  |  | ||||||
| @@ -50,7 +53,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); |         pageHeight = parseInt(pageWidth * 3 / 4, 10); // it's as good an assumption as any | ||||||
|         console.log("pageHeight:", pageHeight); |         console.log("pageHeight:", pageHeight); | ||||||
|         page.viewportSize = { |         page.viewportSize = { | ||||||
|           width: pageWidth, |           width: pageWidth, | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								dist/utils/resume-detector.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								dist/utils/resume-detector.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,13 +1,11 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the ResumeDetector class. |   Definition of the ResumeDetector class. | ||||||
|   @module utils/resume-detector |   @module utils/resume-detector | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   module.exports = function(rez) { |   module.exports = function(rez) { | ||||||
|     if (rez.meta && rez.meta.format) { |     if (rez.meta && rez.meta.format) { //&& rez.meta.format.substr(0, 5).toUpperCase() == 'FRESH' | ||||||
|       return 'fresh'; |       return 'fresh'; | ||||||
|     } else if (rez.basics) { |     } else if (rez.basics) { | ||||||
|       return 'jrs'; |       return 'jrs'; | ||||||
|   | |||||||
							
								
								
									
										55
									
								
								dist/utils/resume-scrubber.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								dist/utils/resume-scrubber.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | (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 | ||||||
							
								
								
									
										13
									
								
								dist/utils/safe-json-loader.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								dist/utils/safe-json-loader.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the SafeJsonLoader class. |   Definition of the SafeJsonLoader class. | ||||||
|   @module utils/safe-json-loader |   @module utils/safe-json-loader | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var FS, SyntaxErrorEx; |   var FS, SyntaxErrorEx; | ||||||
|  |  | ||||||
|   FS = require('fs'); |   FS = require('fs'); | ||||||
| @@ -13,16 +11,19 @@ Definition of the SafeJsonLoader class. | |||||||
|   SyntaxErrorEx = require('./syntax-error-ex'); |   SyntaxErrorEx = require('./syntax-error-ex'); | ||||||
|  |  | ||||||
|   module.exports = function(file) { |   module.exports = function(file) { | ||||||
|     var ret, retRaw; |     var err, 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', |         op: retRaw ? 'parse' : 'read', | ||||||
|         inner: SyntaxErrorEx.is(_error) ? new SyntaxErrorEx(_error, retRaw) : _error, |         inner: SyntaxErrorEx.is(err) ? new SyntaxErrorEx(err, retRaw) : err, | ||||||
|         file: file |         file: file | ||||||
|       }; |       }; | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								dist/utils/safe-spawn.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								dist/utils/safe-spawn.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,19 +1,15 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Safe spawn utility for HackMyResume / FluentCV. |   Safe spawn utility for HackMyResume / FluentCV. | ||||||
|   @module utils/safe-spawn |   @module utils/safe-spawn | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** Safely spawn a process synchronously or asynchronously without throwing an |   /** Safely spawn a process synchronously or asynchronously without throwing an | ||||||
| exception |   exception */ | ||||||
|  */ |  | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   module.exports = function(cmd, args, isSync, callback, param) { |   module.exports = function(cmd, args, isSync, callback, param) { | ||||||
|     var info, spawn; |     var ex, 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) { | ||||||
| @@ -33,11 +29,12 @@ exception | |||||||
|           }; |           }; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } catch (_error) { |     } catch (error) { | ||||||
|  |       ex = error; | ||||||
|       if (typeof callback === "function") { |       if (typeof callback === "function") { | ||||||
|         callback(_error, param); |         callback(ex, param); | ||||||
|       } |       } | ||||||
|       return _error; |       return ex; | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								dist/utils/string-transformer.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								dist/utils/string-transformer.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,26 +1,23 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Object string transformation. |   Object string transformation. | ||||||
|   @module utils/string-transformer |   @module utils/string-transformer | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   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; | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								dist/utils/string.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								dist/utils/string.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,17 +1,13 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definitions of string utility functions. |   Definitions of string utility functions. | ||||||
|   @module utils/string |   @module utils/string | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|   Determine if the string is null, empty, or whitespace. |   Determine if the string is null, empty, or whitespace. | ||||||
|   See: http://stackoverflow.com/a/32800728/4942583 |   See: http://stackoverflow.com/a/32800728/4942583 | ||||||
|   @method isNullOrWhitespace |   @method isNullOrWhitespace | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   String.isNullOrWhitespace = function(input) { |   String.isNullOrWhitespace = function(input) { | ||||||
|     return !input || !input.trim(); |     return !input || !input.trim(); | ||||||
|   }; |   }; | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								dist/utils/syntax-error-ex.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								dist/utils/syntax-error-ex.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,10 +1,10 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the SyntaxErrorEx class. |   Definition of the SyntaxErrorEx class. | ||||||
|   @module utils/syntax-error-ex |   @module utils/syntax-error-ex | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   var SyntaxErrorEx; | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|   Represents a SyntaxError exception with line and column info. |   Represents a SyntaxError exception with line and column info. | ||||||
| @@ -14,13 +14,9 @@ ments, so we reparse on error to grab the line and column. | |||||||
|   See: http://stackoverflow.com/q/13323356 |   See: http://stackoverflow.com/q/13323356 | ||||||
|   @class SyntaxErrorEx |   @class SyntaxErrorEx | ||||||
|   */ |   */ | ||||||
|  |   SyntaxErrorEx = class SyntaxErrorEx { | ||||||
| (function() { |     constructor(ex, rawData) { | ||||||
|   var SyntaxErrorEx; |       var JSONLint, colNum, err, lineNum, lint; | ||||||
|  |  | ||||||
|   SyntaxErrorEx = (function() { |  | ||||||
|     function SyntaxErrorEx(ex, rawData) { |  | ||||||
|       var JSONLint, colNum, lineNum, lint, ref; |  | ||||||
|       lineNum = null; |       lineNum = null; | ||||||
|       colNum = null; |       colNum = null; | ||||||
|       JSONLint = require('json-lint'); |       JSONLint = require('json-lint'); | ||||||
| @@ -28,22 +24,22 @@ See: http://stackoverflow.com/q/13323356 | |||||||
|         comments: false |         comments: false | ||||||
|       }); |       }); | ||||||
|       if (lint.error) { |       if (lint.error) { | ||||||
|         ref = [lint.line, lint.character], this.line = ref[0], this.col = ref[1]; |         [this.line, this.col] = [lint.line, lint.character]; | ||||||
|       } |       } | ||||||
|       if (!lint.error) { |       if (!lint.error) { | ||||||
|         JSONLint = require('jsonlint'); |         JSONLint = require('jsonlint'); | ||||||
|         try { |         try { | ||||||
|           JSONLint.parse(rawData); |           JSONLint.parse(rawData); | ||||||
|         } catch (_error) { |         } catch (error) { | ||||||
|           this.line = (/on line (\d+)/.exec(_error))[1]; |           err = error; | ||||||
|  |           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; | ||||||
|   }; |   }; | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								dist/verbs/analyze.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								dist/verbs/analyze.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,12 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Implementation of the 'analyze' verb for HackMyResume. |   Implementation of the 'analyze' verb for HackMyResume. | ||||||
|   @module verbs/analyze |   @module verbs/analyze | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   /** Private workhorse for the 'analyze' command. */ | ||||||
| (function() { |   /** Analyze a single resume. */ | ||||||
|   var AnalyzeVerb, HMEVENT, HMSTATUS, MKDIRP, PATH, ResumeFactory, Verb, _, _analyze, _analyzeOne, _loadInspectors, chalk, |   var AnalyzeVerb, HMEVENT, HMSTATUS, MKDIRP, PATH, ResumeFactory, Verb, _, _analyze, _analyzeOne, _loadInspectors, chalk; | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   MKDIRP = require('mkdirp'); |   MKDIRP = require('mkdirp'); | ||||||
|  |  | ||||||
| @@ -26,22 +24,13 @@ Implementation of the 'analyze' verb for HackMyResume. | |||||||
|  |  | ||||||
|   chalk = require('chalk'); |   chalk = require('chalk'); | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** An invokable resume analysis command. */ |   /** An invokable resume analysis command. */ | ||||||
|  |   module.exports = AnalyzeVerb = class AnalyzeVerb extends Verb { | ||||||
|   module.exports = AnalyzeVerb = (function(superClass) { |     constructor() { | ||||||
|     extend(AnalyzeVerb, superClass); |       super('analyze', _analyze); | ||||||
|  |  | ||||||
|     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; | ||||||
| @@ -58,7 +47,7 @@ Implementation of the 'analyze' verb for HackMyResume. | |||||||
|         format: 'FRESH', |         format: 'FRESH', | ||||||
|         objectify: true, |         objectify: true, | ||||||
|         inner: { |         inner: { | ||||||
|           "private": opts["private"] === true |           private: opts.private === true | ||||||
|         } |         } | ||||||
|       }, this); |       }, this); | ||||||
|       if (opts.assert && this.hasError()) { |       if (opts.assert && this.hasError()) { | ||||||
| @@ -80,9 +69,6 @@ Implementation of the 'analyze' verb for HackMyResume. | |||||||
|     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; | ||||||
|   | |||||||
							
								
								
									
										191
									
								
								dist/verbs/build.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										191
									
								
								dist/verbs/build.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,49 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Implementation of the 'build' verb for HackMyResume. |   Implementation of the 'build' verb for HackMyResume. | ||||||
|   @module verbs/build |   @module verbs/build | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   Reinforce the chosen theme with "freebie" formats provided by HackMyResume. | ||||||
|   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, |   A "freebie" format is an output format such as JSON, YML, or PNG that can be | ||||||
|     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; }, |   generated directly from the resume model or from one of the theme's declared | ||||||
|     hasProp = {}.hasOwnProperty; |   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'); | ||||||
|  |  | ||||||
| @@ -69,34 +104,17 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|  |  | ||||||
|   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() { | ||||||
|     function BuildVerb() { |       super('build', _build); | ||||||
|       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 inv, isFRESH, mixed, newEx, orgFormat, problemSheets, results, rez, sheetObjects, sheets, tFolder, targets, theme, toFormat; |     var err, 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 | ||||||
| @@ -104,26 +122,30 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|       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"] |         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; |       problemSheets[0].quit = true; // can't go on | ||||||
|       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 | ||||||
| @@ -137,10 +159,11 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|       } |       } | ||||||
|       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: _error, |         inner: err, | ||||||
|         attempted: _opts.theme, |         attempted: _opts.theme, | ||||||
|         quit: true |         quit: true | ||||||
|       }; |       }; | ||||||
| @@ -150,6 +173,7 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|     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, { | ||||||
| @@ -159,6 +183,7 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|       }); |       }); | ||||||
|       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; | ||||||
| @@ -195,14 +220,17 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|         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"] |       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) { | ||||||
| @@ -227,16 +255,12 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|     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.private = opts.private === true; | ||||||
|     _opts.noescape = opts.noescape === true; |     _opts.noescape = opts.noescape === true; | ||||||
|     _opts.css = opts.css; |     _opts.css = opts.css; | ||||||
|     _opts.pdf = opts.pdf; |     _opts.pdf = opts.pdf; | ||||||
| @@ -249,6 +273,7 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|     _opts.sort = opts.sort; |     _opts.sort = opts.sort; | ||||||
|     _opts.wkhtmltopdf = opts.wkhtmltopdf; |     _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); | ||||||
|     }; |     }; | ||||||
| @@ -258,17 +283,11 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|     _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; | ||||||
| @@ -286,6 +305,8 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|         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; | ||||||
| @@ -293,15 +314,17 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|         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); |         MKDIRP.sync(outFolder); // Ensure dest folder exists; | ||||||
|         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, { | ||||||
| @@ -322,9 +345,6 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|     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, | ||||||
| @@ -341,18 +361,9 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|   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', | ||||||
| @@ -383,16 +394,10 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|   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) { | ||||||
| @@ -417,19 +422,22 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|     return targets; |     return targets; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|   Verify the specified theme name/path. |  | ||||||
|    */ |  | ||||||
|  |  | ||||||
|   _verifyTheme = function(themeNameOrPath) { |   _verifyTheme = function(themeNameOrPath) { | ||||||
|     var exists, tFolder, themesObj; |     var exists, tFolder, themesObj; | ||||||
|  |     // First, see if this is one of the predefined FRESH themes. There are only a | ||||||
|  |     // 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'); |     themesObj = require('fresh-themes'); | ||||||
|     if (_.has(themesObj.themes, themeNameOrPath)) { |     if (_.has(themesObj.themes, themeNameOrPath)) { | ||||||
|       tFolder = PATH.join(parsePath(require.resolve('fresh-themes')).dirname, '/themes/', themeNameOrPath); |       tFolder = PATH.join(parsePath(require.resolve('fresh-themes')).dirname, '/themes/', themeNameOrPath); | ||||||
|     } else { |     } 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); |       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; |       return tFolder; | ||||||
| @@ -441,21 +449,36 @@ Implementation of the 'build' verb for HackMyResume. | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|   Load the specified theme, which could be either a FRESH theme or a JSON Resume |  | ||||||
|   theme (or both). |  | ||||||
|    */ |  | ||||||
|  |  | ||||||
|   _loadTheme = function(tFolder) { |   _loadTheme = function(tFolder) { | ||||||
|     var exists, theTheme, themeJsonPath; |     var exists, theTheme, themeJsonPath; | ||||||
|     themeJsonPath = PATH.join(tFolder, 'theme.json'); |     themeJsonPath = PATH.join(tFolder, 'theme.json'); // [^1] | ||||||
|     exists = require('path-exists').sync; |     exists = require('path-exists').sync; | ||||||
|  |     // Create a FRESH or JRS theme object | ||||||
|     theTheme = exists(themeJsonPath) ? new FRESHTheme().open(tFolder) : new JRSTheme().open(tFolder); |     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 | ||||||
|   | |||||||
							
								
								
									
										90
									
								
								dist/verbs/convert.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										90
									
								
								dist/verbs/convert.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,13 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Implementation of the 'convert' verb for HackMyResume. |   Implementation of the 'convert' verb for HackMyResume. | ||||||
|   @module verbs/convert |   @module verbs/convert | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   /** Private workhorse method. Convert 0..N resumes between FRESH and JRS | ||||||
| (function() { |   formats. */ | ||||||
|   var ConvertVerb, HMEVENT, HMSTATUS, ResumeFactory, Verb, _, _convert, _convertOne, chalk, |   /** Private workhorse method. Convert a single resume. */ | ||||||
|     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; }, |   var ConvertVerb, HMEVENT, HMSTATUS, ResumeFactory, Verb, _, _convert, _convertOne, chalk; | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   ResumeFactory = require('../core/resume-factory'); |   ResumeFactory = require('../core/resume-factory'); | ||||||
|  |  | ||||||
| @@ -22,24 +21,15 @@ Implementation of the 'convert' verb for HackMyResume. | |||||||
|  |  | ||||||
|   HMEVENT = require('../core/event-codes'); |   HMEVENT = require('../core/event-codes'); | ||||||
|  |  | ||||||
|   module.exports = ConvertVerb = (function(superClass) { |   module.exports = ConvertVerb = class ConvertVerb extends Verb { | ||||||
|     extend(ConvertVerb, superClass); |     constructor() { | ||||||
|  |       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 results; |     var fmtUp, results, targetVer; | ||||||
|     if (!srcs || !srcs.length) { |     if (!srcs || !srcs.length) { | ||||||
|       this.err(HMSTATUS.resumeNotFound, { |       this.err(HMSTATUS.resumeNotFound, { | ||||||
|         quit: true |         quit: true | ||||||
| @@ -60,18 +50,44 @@ Implementation of the 'convert' verb for HackMyResume. | |||||||
|         }); |         }); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |     // 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()) { |     if (this.hasError()) { | ||||||
|       this.reject(this.errorCode); |       this.reject(this.errorCode); | ||||||
|       return null; |       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; | ||||||
|       r = _convertOne.call(this, src, dst, idx); |       // Convert each resume in turn | ||||||
|  |       r = _convertOne.call(this, src, dst, idx, fmtUp); | ||||||
|  |       // Handle conversion errors | ||||||
|       if (r.fluenterror) { |       if (r.fluenterror) { | ||||||
|         r.quit = opts.assert; |         r.quit = opts.assert; | ||||||
|         this.err(r.fluenterror, r); |         this.err(r.fluenterror, r); | ||||||
| @@ -86,11 +102,9 @@ Implementation of the 'convert' verb for HackMyResume. | |||||||
|     return results; |     return results; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   _convertOne = function(src, dst, idx, targetSchema) { | ||||||
|   /** Private workhorse method. Convert a single resume. */ |     var err, rez, rinfo, srcFmt, targetFormat; | ||||||
|  |     // Load the resume | ||||||
|   _convertOne = function(src, dst, idx) { |  | ||||||
|     var rez, rinfo, srcFmt, targetFormat; |  | ||||||
|     rinfo = ResumeFactory.loadOne(src, { |     rinfo = ResumeFactory.loadOne(src, { | ||||||
|       format: null, |       format: null, | ||||||
|       objectify: true, |       objectify: true, | ||||||
| @@ -98,19 +112,23 @@ Implementation of the 'convert' verb for HackMyResume. | |||||||
|         privatize: false |         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, { |       this.stat(HMEVENT.beforeConvert, { | ||||||
|         srcFile: src, |         srcFile: src, //rinfo.file | ||||||
|         srcFmt: '???', |         srcFmt: '???', | ||||||
|         dstFile: dst[idx], |         dstFile: dst[idx], | ||||||
|         dstFmt: '???', |         dstFmt: '???', | ||||||
|         error: true |         error: true | ||||||
|       }); |       }); | ||||||
|  |       //@err rinfo.fluenterror, rinfo | ||||||
|       return rinfo; |       return rinfo; | ||||||
|     } |     } | ||||||
|  |     // Determine the resume's SOURCE format | ||||||
|  |     // TODO: replace with detector component | ||||||
|     rez = rinfo.rez; |     rez = rinfo.rez; | ||||||
|     srcFmt = ''; |     srcFmt = ''; | ||||||
|     if (rez.meta && rez.meta.format) { |     if (rez.meta && rez.meta.format) { //&& rez.meta.format.substr(0, 5).toUpperCase() == 'FRESH' | ||||||
|       srcFmt = 'FRESH'; |       srcFmt = 'FRESH'; | ||||||
|     } else if (rez.basics) { |     } else if (rez.basics) { | ||||||
|       srcFmt = 'JRS'; |       srcFmt = 'JRS'; | ||||||
| @@ -118,14 +136,28 @@ Implementation of the 'convert' verb for HackMyResume. | |||||||
|       rinfo.fluenterror = HMSTATUS.unknownSchema; |       rinfo.fluenterror = HMSTATUS.unknownSchema; | ||||||
|       return rinfo; |       return rinfo; | ||||||
|     } |     } | ||||||
|     targetFormat = srcFmt === 'JRS' ? 'FRESH' : 'JRS'; |     // 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 { | ||||||
|  |       // Save it to the destination format | ||||||
|       rez.saveAs(dst[idx], targetFormat); |       rez.saveAs(dst[idx], targetFormat); | ||||||
|  |     } catch (error) { | ||||||
|  |       err = error; | ||||||
|  |       if (err.badVer) { | ||||||
|  |         return { | ||||||
|  |           fluenterror: HMSTATUS.invalidSchemaVersion, | ||||||
|  |           quit: true, | ||||||
|  |           data: err.badVer | ||||||
|  |         }; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|     return rez; |     return rez; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										39
									
								
								dist/verbs/create.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								dist/verbs/create.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,12 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Implementation of the 'create' verb for HackMyResume. |   Implementation of the 'create' verb for HackMyResume. | ||||||
|   @module verbs/create |   @module verbs/create | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   /** Create a new empty resume in either FRESH or JRS format. */ | ||||||
| (function() { |   /** Create a single new resume */ | ||||||
|   var CreateVerb, HMEVENT, HMSTATUS, MKDIRP, PATH, Verb, _, _create, _createOne, chalk, |   var CreateVerb, HMEVENT, HMSTATUS, MKDIRP, PATH, Verb, _, _create, _createOne, chalk; | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   MKDIRP = require('mkdirp'); |   MKDIRP = require('mkdirp'); | ||||||
|  |  | ||||||
| @@ -24,19 +22,12 @@ Implementation of the 'create' verb for HackMyResume. | |||||||
|  |  | ||||||
|   HMEVENT = require('../core/event-codes'); |   HMEVENT = require('../core/event-codes'); | ||||||
|  |  | ||||||
|   module.exports = CreateVerb = (function(superClass) { |   module.exports = CreateVerb = class CreateVerb extends Verb { | ||||||
|     extend(CreateVerb, superClass); |     constructor() { | ||||||
|  |       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; | ||||||
| @@ -66,11 +57,8 @@ Implementation of the 'create' verb for HackMyResume. | |||||||
|     return results; |     return results; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** Create a single new resume */ |  | ||||||
|  |  | ||||||
|   _createOne = function(t, opts) { |   _createOne = function(t, opts) { | ||||||
|     var RezClass, newRez, ret, safeFmt; |     var RezClass, err, newRez, ret, safeFmt; | ||||||
|     try { |     try { | ||||||
|       ret = null; |       ret = null; | ||||||
|       safeFmt = opts.format.toUpperCase(); |       safeFmt = opts.format.toUpperCase(); | ||||||
| @@ -78,15 +66,16 @@ Implementation of the 'create' verb for HackMyResume. | |||||||
|         fmt: safeFmt, |         fmt: safeFmt, | ||||||
|         file: t |         file: t | ||||||
|       }); |       }); | ||||||
|       MKDIRP.sync(PATH.dirname(t)); |       MKDIRP.sync(PATH.dirname(t)); // Ensure dest folder exists; | ||||||
|       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: _error |         inner: err | ||||||
|       }; |       }; | ||||||
|     } finally { |     } finally { | ||||||
|       this.stat(HMEVENT.afterCreate, { |       this.stat(HMEVENT.afterCreate, { | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								dist/verbs/peek.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								dist/verbs/peek.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,12 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Implementation of the 'peek' verb for HackMyResume. |   Implementation of the 'peek' verb for HackMyResume. | ||||||
|   @module verbs/peek |   @module verbs/peek | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   /** Peek at a resume, resume section, or resume field. */ | ||||||
| (function() { |   /** Peek at a single resume, resume section, or resume field. */ | ||||||
|   var HMEVENT, HMSTATUS, PeekVerb, Verb, _, __, _peek, _peekOne, safeLoadJSON, |   var HMEVENT, HMSTATUS, PeekVerb, Verb, _, __, _peek, _peekOne, safeLoadJSON; | ||||||
|     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; }, |  | ||||||
|     hasProp = {}.hasOwnProperty; |  | ||||||
|  |  | ||||||
|   Verb = require('../verbs/verb'); |   Verb = require('../verbs/verb'); | ||||||
|  |  | ||||||
| @@ -22,19 +20,12 @@ Implementation of the 'peek' verb for HackMyResume. | |||||||
|  |  | ||||||
|   HMEVENT = require('../core/event-codes'); |   HMEVENT = require('../core/event-codes'); | ||||||
|  |  | ||||||
|   module.exports = PeekVerb = (function(superClass) { |   module.exports = PeekVerb = class PeekVerb extends Verb { | ||||||
|     extend(PeekVerb, superClass); |     constructor() { | ||||||
|  |       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; | ||||||
| @@ -54,6 +45,8 @@ Implementation of the 'peek' verb for HackMyResume. | |||||||
|       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) { | ||||||
| @@ -64,20 +57,20 @@ Implementation of the 'peek' verb for HackMyResume. | |||||||
|     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.op === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError; | ||||||
| @@ -89,6 +82,7 @@ Implementation of the 'peek' verb for HackMyResume. | |||||||
|         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, | ||||||
|   | |||||||
							
								
								
									
										57
									
								
								dist/verbs/validate.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								dist/verbs/validate.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +1,21 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Implementation of the 'validate' verb for HackMyResume. |   Implementation of the 'validate' verb for HackMyResume. | ||||||
|   @module verbs/validate |   @module verbs/validate | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |   /** | ||||||
| (function() { |   Validate a single resume. | ||||||
|   var FS, HMEVENT, HMSTATUS, ResumeFactory, SyntaxErrorEx, ValidateVerb, Verb, _, _validate, _validateOne, chalk, safeLoadJSON, |   @returns { | ||||||
|     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; }, |   file: <fileName>, | ||||||
|     hasProp = {}.hasOwnProperty; |   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'); | ||||||
|  |  | ||||||
| @@ -28,20 +35,15 @@ Implementation of the 'validate' verb for HackMyResume. | |||||||
|  |  | ||||||
|   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 { | ||||||
|   module.exports = ValidateVerb = (function(superClass) { |     constructor() { | ||||||
|     extend(ValidateVerb, superClass); |       super('validate', _validate); | ||||||
|  |  | ||||||
|     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) { | ||||||
| @@ -71,21 +73,8 @@ Implementation of the 'validate' verb for HackMyResume. | |||||||
|     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 errCode, obj, ret, validate; |     var err, errCode, obj, ret, validate; | ||||||
|     ret = { |     ret = { | ||||||
|       file: t, |       file: t, | ||||||
|       isValid: false, |       isValid: false, | ||||||
| @@ -93,6 +82,7 @@ Implementation of the 'validate' verb for HackMyResume. | |||||||
|       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) { | ||||||
| @@ -111,6 +101,7 @@ Implementation of the 'validate' verb for HackMyResume. | |||||||
|           ret.violations = validate.errors; |           ret.violations = validate.errors; | ||||||
|         } |         } | ||||||
|       } else { |       } else { | ||||||
|  |         // If failure, package JSON read/parse errors | ||||||
|         if (obj.ex.op === 'parse') { |         if (obj.ex.op === 'parse') { | ||||||
|           errCode = HMSTATUS.parseError; |           errCode = HMSTATUS.parseError; | ||||||
|           ret.status = 'broken'; |           ret.status = 'broken'; | ||||||
| @@ -124,10 +115,12 @@ Implementation of the 'validate' verb for HackMyResume. | |||||||
|           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: _error |         inner: err | ||||||
|       }; |       }; | ||||||
|     } |     } | ||||||
|     this.stat(HMEVENT.afterValidate, ret); |     this.stat(HMEVENT.afterValidate, ret); | ||||||
|   | |||||||
							
								
								
									
										62
									
								
								dist/verbs/verb.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								dist/verbs/verb.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,9 @@ | |||||||
|  | (function() { | ||||||
|   /** |   /** | ||||||
|   Definition of the Verb class. |   Definition of the Verb class. | ||||||
|   @module verbs/verb |   @module verbs/verb | ||||||
|   @license MIT. See LICENSE.md for details. |   @license MIT. See LICENSE.md for details. | ||||||
|   */ |   */ | ||||||
|  |  | ||||||
| (function() { |  | ||||||
|   var EVENTS, HMEVENT, Promise, Verb; |   var EVENTS, HMEVENT, Promise, Verb; | ||||||
|  |  | ||||||
|   EVENTS = require('events'); |   EVENTS = require('events'); | ||||||
| @@ -14,65 +12,57 @@ Definition of the Verb class. | |||||||
|  |  | ||||||
|   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. */ | ||||||
|     function Verb(moniker, workhorse) { |     constructor(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); | ||||||
| @@ -82,37 +72,29 @@ Definition of the Verb class. | |||||||
|         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); | ||||||
|  |  | ||||||
| //# sourceMappingURL=verb.js.map | //# sourceMappingURL=verb.js.map | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								package.json
									
									
									
									
									
								
							| @@ -49,32 +49,33 @@ | |||||||
|   "main": "dist/index.js", |   "main": "dist/index.js", | ||||||
|   "homepage": "https://github.com/hacksalot/HackMyResume", |   "homepage": "https://github.com/hacksalot/HackMyResume", | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "chalk": "^1.1.1", |     "chalk": "^2.3.1", | ||||||
|     "commander": "^2.9.0", |     "commander": "^2.9.0", | ||||||
|     "copy": "^0.1.3", |     "copy": "^0.3.1", | ||||||
|     "escape-latex": "^0.1.2", |     "escape-latex": "^1.0.0", | ||||||
|     "extend": "^3.0.0", |     "extend": "^3.0.0", | ||||||
|     "fresh-jrs-converter": "^0.2.3", |     "fresh-jrs-converter": "^1.0.0", | ||||||
|     "fresh-resume-schema": "^1.0.0-beta", |     "fresh-resume-schema": "^1.0.0-beta", | ||||||
|     "fresh-resume-starter": "^0.3.1", |     "fresh-resume-starter": "^0.3.1", | ||||||
|     "fresh-themes": "^0.16.0-beta", |     "fresh-resume-validator": "^0.2.0", | ||||||
|     "fs-extra": "^0.26.4", |     "fresh-themes": "^0.17.0-beta", | ||||||
|  |     "fs-extra": "^5.0.0", | ||||||
|     "glob": "^7.1.2", |     "glob": "^7.1.2", | ||||||
|     "handlebars": "^4.0.5", |     "handlebars": "^4.0.5", | ||||||
|     "html": "0.0.10", |     "html": "^1.0.0", | ||||||
|     "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": "^3.10.1", |     "lodash": "^4.17.5", | ||||||
|     "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": "^0.6.3", |     "parse-filepath": "^1.0.2", | ||||||
|     "path-exists": "^2.1.0", |     "path-exists": "^3.0.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.2.1", |     "simple-html-tokenizer": "^0.4.3", | ||||||
|     "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", | ||||||
| @@ -83,22 +84,20 @@ | |||||||
|     "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.2.4" |     "yamljs": "^0.3.0" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "chai": "*", |     "chai": "*", | ||||||
|     "chai-as-promised": "^7.1.1", |     "chai-as-promised": "^7.1.1", | ||||||
|     "dir-compare": "0.0.2", |     "dir-compare": "^1.4.0", | ||||||
|     "fresh-test-resumes": "^0.9.1", |     "fresh-test-resumes": "^0.9.2", | ||||||
|     "fresh-test-themes": "^0.1.0", |     "fresh-test-themes": "^0.2.0", | ||||||
|  |     "fresh-theme-underscore": "^0.1.1", | ||||||
|     "grunt": "*", |     "grunt": "*", | ||||||
|     "grunt-cli": "^0.1.13", |     "grunt-contrib-clean": "^1.1.0", | ||||||
|     "grunt-contrib-clean": "^0.7.0", |     "grunt-contrib-coffee": "^2.0.0", | ||||||
|     "grunt-contrib-coffee": "^0.13.0", |     "grunt-contrib-copy": "^1.0.0", | ||||||
|     "grunt-contrib-copy": "^0.8.2", |     "grunt-contrib-jshint": "^1.1.0", | ||||||
|     "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", | ||||||
|   | |||||||
| @@ -110,17 +110,19 @@ 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 += chalk.gray(FS.readFileSync( |       msg += M2C(FS.readFileSync( | ||||||
|         PATH.resolve(__dirname, '../cli/use.txt'), 'utf8' )) |         PATH.resolve(__dirname, 'help/use.txt'), 'utf8' ), 'white', 'yellow') | ||||||
|  |  | ||||||
|     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 ) | ||||||
| @@ -257,6 +259,9 @@ assembleError = ( ex ) -> | |||||||
|       msg = printf M2C( @msgs.themeHelperLoad.msg ), ex.glob |       msg = printf M2C( @msgs.themeHelperLoad.msg ), ex.glob | ||||||
|       etype = 'error' |       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 | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								src/cli/help/analyze.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/cli/help/analyze.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | **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
									
								
								src/cli/help/build.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/cli/help/build.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | **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
									
								
								src/cli/help/convert.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/cli/help/convert.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | **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
									
								
								src/cli/help/help.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/cli/help/help.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | **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
									
								
								src/cli/help/new.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/cli/help/new.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | **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
									
								
								src/cli/help/peek.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/cli/help/peek.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | **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
									
								
								src/cli/help/use.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/cli/help/use.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | **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
									
								
								src/cli/help/validate.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/cli/help/validate.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | **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. | ||||||
| @@ -84,6 +84,7 @@ main = 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) | ||||||
| @@ -131,6 +132,19 @@ main = module.exports = ( rawArgs, exitCallback ) -> | |||||||
|       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 | ||||||
| @@ -170,24 +184,23 @@ 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 ] |   if o.verb && !HMR.verbs[ o.verb ] && !HMR.alias[ o.verb ] && o.verb != 'help' | ||||||
|     _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 = (name) -> |   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 |  | ||||||
|         else HMSTATUS.createNameMissing |  | ||||||
|         , true |         , 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, 'use.txt'), 'utf8' ) |       PATH.join(__dirname, 'help/use.txt'), 'utf8' ) | ||||||
|     return chalk.green.bold(manPage) |     return M2C(manPage, 'white', 'yellow') | ||||||
|  |  | ||||||
|   return { |   return { | ||||||
|     args: o.args, |     args: o.args, | ||||||
| @@ -288,7 +301,7 @@ 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 |   #console.dir err | ||||||
|   finalErrorCode = -1 |   finalErrorCode = -1 | ||||||
|   if err |   if err | ||||||
|     if err.fluenterror |     if err.fluenterror | ||||||
| @@ -348,7 +361,8 @@ 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 | ||||||
|     throw { fluenterror: HMSTATUS.resumeNotFound, quit: true } |     #tmpName = @name() | ||||||
|  |     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'; ) | ||||||
|   | |||||||
| @@ -137,3 +137,5 @@ errors: | |||||||
|       An error occurred while attempting to load the '%s' theme helper. Is the |       An error occurred while attempting to load the '%s' theme helper. Is the | ||||||
|       theme correctly installed? |       theme correctly installed? | ||||||
|     dummy: dontcare |     dummy: dontcare | ||||||
|  |   invalidSchemaVersion: | ||||||
|  |     msg: "'%s' is not recognized as a valid schema version." | ||||||
|   | |||||||
| @@ -1,52 +0,0 @@ | |||||||
| 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. |  | ||||||
|   --private     Include resume fields marked as private |  | ||||||
|   --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,98 +0,0 @@ | |||||||
| ###* |  | ||||||
| Definition of the AbstractResume class. |  | ||||||
| @license MIT. See LICENSE.md for details. |  | ||||||
| @module core/abstract-resume |  | ||||||
| ### |  | ||||||
|  |  | ||||||
| _ = require 'underscore' |  | ||||||
| __ = require 'lodash' |  | ||||||
| FluentDate = require('./fluent-date') |  | ||||||
|  |  | ||||||
| class AbstractResume |  | ||||||
|  |  | ||||||
|   ###* |  | ||||||
|   Compute the total duration of the work history. |  | ||||||
|   @returns The total duration of the sheet's work history, that is, the number |  | ||||||
|   of years between the start date of the earliest job on the resume and the |  | ||||||
|   *latest end date of all jobs in the work history*. This last condition is for |  | ||||||
|   sheets that have overlapping jobs. |  | ||||||
|   ### |  | ||||||
|   duration: (collKey, startKey, endKey, unit) -> |  | ||||||
|     unit = unit || 'years' |  | ||||||
|     hist = __.get @, collKey |  | ||||||
|     return 0 if !hist or !hist.length |  | ||||||
|  |  | ||||||
|     # 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 ( job ) -> |  | ||||||
|       obj = _.pick( job, [startKey, endKey] ) |  | ||||||
|       # Synthesize an end date if this is a "current" gig |  | ||||||
|       obj[endKey] = 'current' if !_.has obj, endKey |  | ||||||
|       if obj && (obj[startKey] || obj[endKey]) |  | ||||||
|         obj = _.pairs obj |  | ||||||
|         obj[0][1] = FluentDate.fmt( obj[0][1] ) |  | ||||||
|         if obj.length > 1 |  | ||||||
|           obj[1][1] = FluentDate.fmt( obj[1][1] ) |  | ||||||
|       obj |  | ||||||
|  |  | ||||||
|     # Flatten the array, remove empties, and sort |  | ||||||
|     new_e = _.filter _.flatten( new_e, true ), (v) -> |  | ||||||
|       return v && v.length && v[0] && v[0].length |  | ||||||
|     return 0 if !new_e or !new_e.length |  | ||||||
|     new_e = _.sortBy new_e, ( elem ) -> return elem[1].unix() |  | ||||||
|  |  | ||||||
|     # END CODE DUPLICATION |  | ||||||
|  |  | ||||||
|     firstDate = _.first( new_e )[1]; |  | ||||||
|     lastDate = _.last( new_e )[1]; |  | ||||||
|     lastDate.diff firstDate, unit |  | ||||||
|  |  | ||||||
|   ###* |  | ||||||
|   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: (rep, opts) -> |  | ||||||
|     traverse = require 'traverse' |  | ||||||
|     ignoreList = [] |  | ||||||
|     privateList = [] |  | ||||||
|     includePrivates = opts && opts.private |  | ||||||
|  |  | ||||||
|     scrubbed = traverse( rep ).map () -> # [^1] |  | ||||||
|       if !@isLeaf |  | ||||||
|         if @node.ignore == true || @node.ignore == 'true' |  | ||||||
|           ignoreList.push @node |  | ||||||
|           @delete() |  | ||||||
|         else if (@node.private == true || @node.private == 'true') && !includePrivates |  | ||||||
|           privateList.push @node |  | ||||||
|           @delete() |  | ||||||
|       if _.isArray(@node) # [^2] |  | ||||||
|         @after () -> |  | ||||||
|           @update _.compact this.node |  | ||||||
|           return |  | ||||||
|       return |  | ||||||
|  |  | ||||||
|     scrubbed: scrubbed |  | ||||||
|     ingoreList: ignoreList |  | ||||||
|     privateList: privateList |  | ||||||
|  |  | ||||||
| module.exports = AbstractResume |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # [^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 |  | ||||||
| # |  | ||||||
| @@ -18,7 +18,6 @@ MD = require 'marked' | |||||||
| CONVERTER = require 'fresh-jrs-converter' | CONVERTER = require 'fresh-jrs-converter' | ||||||
| JRSResume = require './jrs-resume' | JRSResume = require './jrs-resume' | ||||||
| FluentDate = require './fluent-date' | FluentDate = require './fluent-date' | ||||||
| AbstractResume = require './abstract-resume' |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -27,7 +26,7 @@ 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 | ||||||
| ### | ### | ||||||
| class FreshResume extends AbstractResume | class FreshResume# extends AbstractResume | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -55,7 +54,8 @@ class FreshResume extends AbstractResume | |||||||
|  |  | ||||||
|     if opts and opts.privatize |     if opts and opts.privatize | ||||||
|       # Ignore any element with the 'ignore: true' or 'private: true' designator. |       # Ignore any element with the 'ignore: true' or 'private: true' designator. | ||||||
|       { scrubbed, ignoreList, privateList } = @scrubResume rep, opts |       scrubber = require '../utils/resume-scrubber' | ||||||
|  |       { scrubbed, ignoreList, privateList } = scrubber.scrubResume rep, opts | ||||||
|  |  | ||||||
|     # Now apply the resume representation onto this object |     # Now apply the resume representation onto this object | ||||||
|     extend true, @, if opts and opts.privatize then scrubbed else rep |     extend true, @, if opts and opts.privatize then scrubbed else rep | ||||||
| @@ -95,12 +95,27 @@ class FreshResume extends AbstractResume | |||||||
|   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 ) -> |   saveAs: ( filename, format ) -> | ||||||
|     if format != 'JRS' |  | ||||||
|  |     # If format isn't specified, default to FRESH | ||||||
|  |     safeFormat = (format && format.trim()) || 'FRESH' | ||||||
|  |  | ||||||
|  |     # 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' | ||||||
|       @imp.file = filename || @imp.file |       @imp.file = filename || @imp.file | ||||||
|       FS.writeFileSync @imp.file, @stringify(), 'utf8' |       FS.writeFileSync @imp.file, @stringify(), 'utf8' | ||||||
|     else |  | ||||||
|       newRep = CONVERTER.toJRS this |     else if parts[0] == 'JRS' | ||||||
|  |       useEdgeSchema = if parts.length > 1 then parts[1] == '1' else false | ||||||
|  |       newRep = CONVERTER.toJRS @, edge: useEdgeSchema | ||||||
|       FS.writeFileSync filename, JRSResume.stringify( newRep ), 'utf8' |       FS.writeFileSync filename, JRSResume.stringify( newRep ), 'utf8' | ||||||
|  |     else | ||||||
|  |       throw badVer: safeFormat | ||||||
|     @ |     @ | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -180,7 +195,24 @@ class FreshResume extends AbstractResume | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   ###* Return a unique list of all keywords across all skills. ### |   ###* | ||||||
|  |   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 | ||||||
|  |   # 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 | ||||||
|  |   # 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: () -> |   keywords: () -> | ||||||
|     flatSkills = [] |     flatSkills = [] | ||||||
|     if @skills |     if @skills | ||||||
| @@ -299,7 +331,9 @@ class FreshResume extends AbstractResume | |||||||
|  |  | ||||||
|  |  | ||||||
|   duration: (unit) -> |   duration: (unit) -> | ||||||
|     super('employment.history', 'start', 'end', unit) |     inspector = require '../inspectors/duration-inspector' | ||||||
|  |     inspector.run @, 'employment.history', 'start', 'end', unit | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -59,9 +59,23 @@ class FRESHTheme | |||||||
|     if @inherits |     if @inherits | ||||||
|       cached = { } |       cached = { } | ||||||
|       _.each @inherits, (th, key) -> |       _.each @inherits, (th, key) -> | ||||||
|         themesFolder = require.resolve 'fresh-themes' |         # First, see if this is one of the predefined FRESH themes. There are | ||||||
|         d = parsePath( themeFolder ).dirname |         # only a 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. | ||||||
|  |         # 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 |           themePath = PATH.join d, th | ||||||
|  |  | ||||||
|         cached[ th ] = cached[th] || new FRESHTheme().open( themePath ) |         cached[ th ] = cached[th] || new FRESHTheme().open( themePath ) | ||||||
|         formatsHash[ key ] = cached[ th ].getFormat( key ) |         formatsHash[ key ] = cached[ th ].getFormat( key ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,7 +14,6 @@ PATH = require('path') | |||||||
| MD = require('marked') | MD = require('marked') | ||||||
| CONVERTER = require('fresh-jrs-converter') | CONVERTER = require('fresh-jrs-converter') | ||||||
| moment = require('moment') | moment = require('moment') | ||||||
| AbstractResume = require('./abstract-resume') |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ###* | ###* | ||||||
| @@ -22,7 +21,7 @@ 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. | is an instantiation of that JSON decorated with utility methods. | ||||||
| @class JRSResume | @class JRSResume | ||||||
| ### | ### | ||||||
| class JRSResume extends AbstractResume | class JRSResume# extends AbstractResume | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -49,8 +48,9 @@ class JRSResume extends AbstractResume | |||||||
|   parseJSON: ( rep, opts ) -> |   parseJSON: ( rep, opts ) -> | ||||||
|     opts = opts || { }; |     opts = opts || { }; | ||||||
|     if opts.privatize |     if opts.privatize | ||||||
|  |       scrubber = require '../utils/resume-scrubber' | ||||||
|       # Ignore any element with the 'ignore: true' or 'private: true' designator. |       # Ignore any element with the 'ignore: true' or 'private: true' designator. | ||||||
|       { scrubbed, ignoreList, privateList } = @scrubResume rep, opts |       { scrubbed, ignoreList, privateList } = scrubber.scrubResume rep, opts | ||||||
|  |  | ||||||
|     # Extend resume properties onto ourself. |     # Extend resume properties onto ourself. | ||||||
|     extend true, this, if opts.privatize then scrubbed else rep |     extend true, this, if opts.privatize then scrubbed else rep | ||||||
| @@ -188,7 +188,8 @@ class JRSResume extends AbstractResume | |||||||
|  |  | ||||||
|  |  | ||||||
|   duration: (unit) -> |   duration: (unit) -> | ||||||
|     super('work', 'startDate', 'endDate', unit) |     inspector = require '../inspectors/duration-inspector'; | ||||||
|  |     inspector.run @, 'work', 'startDate', 'endDate', unit | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -232,7 +233,6 @@ class JRSResume extends AbstractResume | |||||||
|   ### |   ### | ||||||
|   harden: () -> |   harden: () -> | ||||||
|  |  | ||||||
|     that = @ |  | ||||||
|     ret = @dupe() |     ret = @dupe() | ||||||
|  |  | ||||||
|     HD = (txt) -> '@@@@~' + txt + '~@@@@' |     HD = (txt) -> '@@@@~' + txt + '~@@@@' | ||||||
| @@ -241,38 +241,12 @@ class JRSResume extends AbstractResume | |||||||
|       #return MD(txt || '' ).replace(/^\s*<p>|<\/p>\s*$/gi, ''); |       #return MD(txt || '' ).replace(/^\s*<p>|<\/p>\s*$/gi, ''); | ||||||
|       return HD txt |       return HD txt | ||||||
|  |  | ||||||
|     # TODO: refactor recursion |     transformer = require '../utils/string-transformer' | ||||||
|     hardenStringsInObject = ( obj, inline ) -> |     transformer ret, | ||||||
|  |       [ 'skills','url','website','startDate','endDate', 'releaseDate', 'date', | ||||||
|       return if !obj |       'phone','email','address','postalCode','city','country','region', | ||||||
|       inline = inline == undefined || inline |       'safeStartDate','safeEndDate' ], | ||||||
|  |       (key, val) -> HD val | ||||||
|       if Object.prototype.toString.call( obj ) == '[object Array]' |  | ||||||
|         obj.forEach (elem, idx, ar) -> |  | ||||||
|           if typeof elem == 'string' || elem instanceof String |  | ||||||
|             ar[idx] = if inline then HDIN(elem) else HD( elem ) |  | ||||||
|           else |  | ||||||
|             hardenStringsInObject elem |  | ||||||
|       else if typeof obj == 'object' |  | ||||||
|         Object.keys( obj ).forEach (key) -> |  | ||||||
|           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' |  | ||||||
|               obj[key] = HD( obj[key] ) |  | ||||||
|             else |  | ||||||
|               obj[key] = if inline then HDIN( obj[key] ) else HD( obj[key] ) |  | ||||||
|           else |  | ||||||
|             hardenStringsInObject sub |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     Object.keys( ret ).forEach (member) -> |  | ||||||
|       hardenStringsInObject ret[ member ] |  | ||||||
|  |  | ||||||
|     ret |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -104,9 +104,9 @@ _parse = ( fileName, opts, eve ) -> | |||||||
|  |  | ||||||
|     eve && eve.stat HME.afterParse, { file: fileName, data: ret.json, fmt: orgFormat } |     eve && eve.stat HME.afterParse, { file: fileName, data: ret.json, fmt: orgFormat } | ||||||
|     return ret |     return ret | ||||||
|   catch |   catch err | ||||||
|     # Can be ENOENT, EACCES, SyntaxError, etc. |     # Can be ENOENT, EACCES, SyntaxError, etc. | ||||||
|     fluenterror: if rawData then HMS.parseError else HMS.readError |     fluenterror: if rawData then HMS.parseError else HMS.readError | ||||||
|     inner: _error |     inner: err | ||||||
|     raw: rawData |     raw: rawData | ||||||
|     file: fileName |     file: fileName | ||||||
|   | |||||||
| @@ -37,3 +37,4 @@ module.exports = | |||||||
|   optionsFileNotFound: 28 |   optionsFileNotFound: 28 | ||||||
|   unknownSchema: 29 |   unknownSchema: 29 | ||||||
|   themeHelperLoad: 30 |   themeHelperLoad: 30 | ||||||
|  |   invalidSchemaVersion: 31 | ||||||
|   | |||||||
| @@ -122,14 +122,14 @@ module.exports = class TemplateGenerator extends BaseGenerator | |||||||
|           return |           return | ||||||
|  |  | ||||||
|       # Write the file |       # Write the file | ||||||
|       opts.beforeWrite? thisFilePath |       opts.beforeWrite? data: thisFilePath | ||||||
|       MKDIRP.sync PATH.dirname( thisFilePath ) |       MKDIRP.sync PATH.dirname( thisFilePath ) | ||||||
|  |  | ||||||
|       if file.info.action != 'copy' |       if file.info.action != 'copy' | ||||||
|         FS.writeFileSync thisFilePath, file.data, encoding: 'utf8', flags: 'w' |         FS.writeFileSync thisFilePath, file.data, encoding: 'utf8', flags: 'w' | ||||||
|       else |       else | ||||||
|         FS.copySync file.info.path, thisFilePath |         FS.copySync file.info.path, thisFilePath | ||||||
|       opts.afterWrite? thisFilePath |       opts.afterWrite? data: thisFilePath | ||||||
|  |  | ||||||
|       # Post-processing |       # Post-processing | ||||||
|       if @onAfterSave |       if @onAfterSave | ||||||
| @@ -174,9 +174,9 @@ createSymLinks = ( curFmt, outFolder ) -> | |||||||
|  |  | ||||||
|       try |       try | ||||||
|         FS.symlinkSync absTarg, absLoc, type |         FS.symlinkSync absTarg, absLoc, type | ||||||
|       catch |       catch err | ||||||
|         succeeded = false |         succeeded = false | ||||||
|         if _error.code == 'EEXIST' |         if err.code == 'EEXIST' | ||||||
|           FS.unlinkSync absLoc |           FS.unlinkSync absLoc | ||||||
|           try |           try | ||||||
|             FS.symlinkSync absTarg, absLoc, type |             FS.symlinkSync absTarg, absLoc, type | ||||||
|   | |||||||
| @@ -38,6 +38,14 @@ BlockHelpers = module.exports = | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   ifHasSkill: ( rez, skill, options ) -> | ||||||
|  |     skUp = skill.toUpperCase() | ||||||
|  |     ret = _.some rez.skills.list, (sk) -> | ||||||
|  |       (skUp.toUpperCase() == sk.name.toUpperCase()) and sk.years | ||||||
|  |     , @ | ||||||
|  |     options.fn @ if ret | ||||||
|  |  | ||||||
|  |  | ||||||
|   ###* |   ###* | ||||||
|   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. | ||||||
|   | |||||||
| @@ -329,6 +329,7 @@ GenericHelpers = module.exports = | |||||||
|     # If not provided by the user, stitle should default to sname. ps. |     # If not provided by the user, stitle should default to sname. ps. | ||||||
|     # Handlebars silently passes in the options object to the last param, |     # Handlebars silently passes in the options object to the last param, | ||||||
|     # where in Underscore stitle will be null/undefined, so we check both. |     # 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. |     # If there's a section title override, use it. | ||||||
| @@ -342,7 +343,7 @@ GenericHelpers = module.exports = | |||||||
|   wpml: ( txt, inline ) -> |   wpml: ( txt, inline ) -> | ||||||
|     return '' if !txt |     return '' if !txt | ||||||
|     inline = (inline && !inline.hash) || false |     inline = (inline && !inline.hash) || false | ||||||
|     txt = XML(txt.trim()) |     txt = XML txt.trim() | ||||||
|     txt = if inline then MD(txt).replace(/^\s*<p>|<\/p>\s*$/gi, '') else MD(txt) |     txt = if inline then MD(txt).replace(/^\s*<p>|<\/p>\s*$/gi, '') else MD(txt) | ||||||
|     txt = H2W( txt ) |     txt = H2W( txt ) | ||||||
|     return txt |     return txt | ||||||
| @@ -358,6 +359,15 @@ GenericHelpers = module.exports = | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   ###* | ||||||
|  |   Emit a conditional Markdown link. | ||||||
|  |   @method link | ||||||
|  |   ### | ||||||
|  |   linkMD: ( text, url ) -> | ||||||
|  |     return if url && url.trim() then ('[' + text + '](' + url + ')') else text | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   ###* |   ###* | ||||||
|   Return the last word of the specified text. |   Return the last word of the specified text. | ||||||
|   @method lastWord |   @method lastWord | ||||||
| @@ -376,7 +386,7 @@ GenericHelpers = module.exports = | |||||||
|   '#FFFFAA'). |   '#FFFFAA'). | ||||||
|   ### |   ### | ||||||
|   skillColor: ( lvl ) -> |   skillColor: ( lvl ) -> | ||||||
|     idx = skillLevelToIndex lvl |     idx = _skillLevelToIndex lvl | ||||||
|     skillColors = (this.theme && this.theme.palette && |     skillColors = (this.theme && this.theme.palette && | ||||||
|       this.theme.palette.skillLevels) || |       this.theme.palette.skillLevels) || | ||||||
|       [ '#FFFFFF', '#5CB85C', '#F1C40F', '#428BCA', '#C00000' ] |       [ '#FFFFFF', '#5CB85C', '#F1C40F', '#428BCA', '#C00000' ] | ||||||
| @@ -389,7 +399,7 @@ GenericHelpers = module.exports = | |||||||
|   @method lastWord |   @method lastWord | ||||||
|   ### |   ### | ||||||
|   skillHeight: ( lvl ) -> |   skillHeight: ( lvl ) -> | ||||||
|     idx = skillLevelToIndex lvl |     idx = _skillLevelToIndex lvl | ||||||
|     ['38.25', '30', '16', '8', '0'][idx] |     ['38.25', '30', '16', '8', '0'][idx] | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -491,6 +501,9 @@ GenericHelpers = module.exports = | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   ###* | ||||||
|  |   Emit padded text. | ||||||
|  |   ### | ||||||
|   pad: (stringOrArray, padAmount, unused ) -> |   pad: (stringOrArray, padAmount, unused ) -> | ||||||
|     stringOrArray = stringOrArray || '' |     stringOrArray = stringOrArray || '' | ||||||
|     padAmount = padAmount || 0 |     padAmount = padAmount || 0 | ||||||
| @@ -506,6 +519,25 @@ GenericHelpers = module.exports = | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   ###* | ||||||
|  |   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: ( skill, rez ) -> | ||||||
|  |     sk = _.find rez.skills.list, (sk) -> sk.name.toUpperCase() == skill.toUpperCase() | ||||||
|  |     if sk then sk.years else '?' | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   ###* | ||||||
|  |   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: ( obj, objPath, rez ) -> | ||||||
|  |     if _.isString obj then obj else LO.get obj, objPath | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ###* | ###* | ||||||
| Report an error to the outside world without throwing an exception. Currently | Report an error to the outside world without throwing an exception. Currently | ||||||
| relies on kludging the running verb into. opts. | relies on kludging the running verb into. opts. | ||||||
| @@ -562,7 +594,7 @@ _fromTo = ( dateA, dateB, fmt, sep, fallback ) -> | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| skillLevelToIndex = ( lvl ) -> | _skillLevelToIndex = ( lvl ) -> | ||||||
|   idx = 0 |   idx = 0 | ||||||
|   if String.is( lvl ) |   if String.is( lvl ) | ||||||
|     lvl = lvl.trim().toLowerCase() |     lvl = lvl.trim().toLowerCase() | ||||||
|   | |||||||
| @@ -17,23 +17,28 @@ Register useful Handlebars helpers. | |||||||
| @method registerHelpers | @method registerHelpers | ||||||
| ### | ### | ||||||
|  |  | ||||||
| module.exports = ( theme, opts ) -> | module.exports = ( theme, rez, opts ) -> | ||||||
|  |  | ||||||
|   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, ( hVal, hKey ) -> |   wrappedHelpers = _.mapObject helpers, ( hVal, hKey ) -> | ||||||
|     if _.isFunction hVal |     if _.isFunction hVal | ||||||
|       _.wrap hVal, (func) -> |       return _.wrap hVal, (func) -> | ||||||
|         args = Array.prototype.slice.call arguments |         args = Array.prototype.slice.call arguments | ||||||
|         args.shift() # lose the 1st element (func) |         args.shift()                  # lose the 1st element (func) [^1] | ||||||
|         args.pop() # lose the last element (the Handlebars options hash) |         #args.pop()                   # lose the last element (HB options hash) | ||||||
|         func.apply @, args |         args[ args.length - 1 ] = rez # replace w/ resume object | ||||||
|  |         func.apply @, args            # call the generic helper | ||||||
|     hVal |     hVal | ||||||
|   , @ |   , @ | ||||||
|  |  | ||||||
|   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 | ||||||
|  |  | ||||||
|   # Register any theme-provided custom helpers... |   # Register any theme-provided custom helpers... | ||||||
| @@ -64,3 +69,9 @@ module.exports = ( theme, opts ) -> | |||||||
|         inner: ex |         inner: ex | ||||||
|         glob: curGlob, exit: true |         glob: curGlob, exit: true | ||||||
|       return |       return | ||||||
|  |  | ||||||
|  | # [^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. | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								src/inspectors/duration-inspector.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/inspectors/duration-inspector.coffee
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | FluentDate = require '../core/fluent-date' | ||||||
|  | _ = require 'underscore' | ||||||
|  | lo = require 'lodash' | ||||||
|  |  | ||||||
|  | module.exports = | ||||||
|  |  | ||||||
|  |   ###* | ||||||
|  |   Compute the total duration of the work history. | ||||||
|  |   @returns The total duration of the sheet's work history, that is, the number | ||||||
|  |   of years between the start date of the earliest job on the resume and the | ||||||
|  |   *latest end date of all jobs in the work history*. This last condition is for | ||||||
|  |   sheets that have overlapping jobs. | ||||||
|  |   ### | ||||||
|  |   run: (rez, collKey, startKey, endKey, unit) -> | ||||||
|  |     unit = unit || 'years' | ||||||
|  |     hist = lo.get rez, collKey | ||||||
|  |     return 0 if !hist or !hist.length | ||||||
|  |  | ||||||
|  |     # 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 ( job ) -> | ||||||
|  |       obj = _.pick( job, [startKey, endKey] ) | ||||||
|  |       # Synthesize an end date if this is a "current" gig | ||||||
|  |       obj[endKey] = 'current' if !_.has obj, endKey | ||||||
|  |       if obj && (obj[startKey] || obj[endKey]) | ||||||
|  |         obj = _.pairs obj | ||||||
|  |         obj[0][1] = FluentDate.fmt( obj[0][1] ) | ||||||
|  |         if obj.length > 1 | ||||||
|  |           obj[1][1] = FluentDate.fmt( obj[1][1] ) | ||||||
|  |       obj | ||||||
|  |  | ||||||
|  |     # Flatten the array, remove empties, and sort | ||||||
|  |     new_e = _.filter _.flatten( new_e, true ), (v) -> | ||||||
|  |       return v && v.length && v[0] && v[0].length | ||||||
|  |     return 0 if !new_e or !new_e.length | ||||||
|  |     new_e = _.sortBy new_e, ( elem ) -> return elem[1].unix() | ||||||
|  |  | ||||||
|  |     # END CODE DUPLICATION | ||||||
|  |  | ||||||
|  |     firstDate = _.first( new_e )[1]; | ||||||
|  |     lastDate = _.last( new_e )[1]; | ||||||
|  |     lastDate.diff firstDate, unit | ||||||
| @@ -30,22 +30,20 @@ HandlebarsGenerator = module.exports = | |||||||
|     try |     try | ||||||
|       # Compile and run the Handlebars template. |       # Compile and run the Handlebars template. | ||||||
|       template = HANDLEBARS.compile tpl, |       template = HANDLEBARS.compile tpl, | ||||||
|         strict: false, assumeObjects: false, noEscape: data.opts.noescape || false |         strict: false | ||||||
|  |         assumeObjects: false | ||||||
|  |         noEscape: data.opts.noescape | ||||||
|       return template data |       return template data | ||||||
|     catch |     catch err | ||||||
|       throw |       throw | ||||||
|         fluenterror: |         fluenterror: | ||||||
|           HMSTATUS[ if template then 'invokeTemplate' else 'compileTemplate' ] |           HMSTATUS[ if template then 'invokeTemplate' else 'compileTemplate' ] | ||||||
|         inner: _error |         inner: err | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   generate: ( json, jst, format, curFmt, opts, theme ) -> |   generate: ( json, jst, format, curFmt, opts, theme ) -> | ||||||
|  |  | ||||||
|     # Set up partials and helpers |  | ||||||
|     registerPartials format, theme |  | ||||||
|     registerHelpers theme, opts |  | ||||||
|  |  | ||||||
|     # Preprocess text |     # Preprocess text | ||||||
|     encData = json |     encData = json | ||||||
|     if format == 'html' || format == 'pdf' |     if format == 'html' || format == 'pdf' | ||||||
| @@ -53,6 +51,10 @@ HandlebarsGenerator = module.exports = | |||||||
|     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 |     # Set up the context | ||||||
|     ctx = |     ctx = | ||||||
|       r: encData |       r: encData | ||||||
|   | |||||||
| @@ -37,8 +37,8 @@ JRSGenerator = module.exports = | |||||||
|     turnoff.forEach (c, idx) -> console[c] = org[idx] |     turnoff.forEach (c, idx) -> console[c] = org[idx] | ||||||
|  |  | ||||||
|     # Unfreeze and apply Markdown |     # Unfreeze and apply Markdown | ||||||
|     rezHtml = rezHtml.replace /@@@@~.*?~@@@@/gm, (val) -> |     rezHtml = rezHtml.replace /@@@@~[\s\S]*?~@@@@/g, (val) -> | ||||||
|       MDIN( val.replace( /~@@@@/gm,'' ).replace( /@@@@~/gm,'' ) ) |       MDIN( val.replace( /~@@@@/g,'' ).replace( /@@@@~/g,'' ) ) | ||||||
|  |  | ||||||
|  |  | ||||||
| MDIN = (txt) -> # TODO: Move this | MDIN = (txt) -> # TODO: Move this | ||||||
|   | |||||||
| @@ -24,12 +24,12 @@ UnderscoreGenerator = module.exports = | |||||||
|       # Compile and run the Handlebars template. |       # Compile and run the Handlebars template. | ||||||
|       t = _.template tpl |       t = _.template tpl | ||||||
|       t data |       t data | ||||||
|     catch |     catch err | ||||||
|       #console.dir _error |       #console.dir _error | ||||||
|       HMS = require '../core/status-codes' |       HMS = require '../core/status-codes' | ||||||
|       throw |       throw | ||||||
|         fluenterror: HMS[if t then 'invokeTemplate' else 'compileTemplate'] |         fluenterror: HMS[if t then 'invokeTemplate' else 'compileTemplate'] | ||||||
|         inner: _error |         inner: err | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								src/utils/fresh-version-regex.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/utils/fresh-version-regex.coffee
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | ###* | ||||||
|  | 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 = () -> | ||||||
|  |   RegExp '^(FRESH|FRESCA|JRS)(?:@(\\d+(?:\\.\\d+)?(?:\\.\\d+)?))?$' | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user