From 8237c8da28cc52811ce1bbefef97f8d1dd26ba4c Mon Sep 17 00:00:00 2001 From: Rodrigo Fernandes Date: Fri, 15 Apr 2016 23:08:57 +0100 Subject: [PATCH 1/4] Use hogan.js as templating engine --- package.json | 9 ++- release.sh | 36 ++++++------ sample/index.html | 2 + src/hoganjs-utils.js | 58 +++++++++++++++++++ src/line-by-line-printer.js | 32 ++++++---- src/nunjucks-utils.js | 34 ----------- .../line-by-line-column-line-number.mustache | 6 ++ .../line-by-line-empty-diff.mustache | 7 +++ ...f.html => line-by-line-file-diff.mustache} | 10 ++-- src/templates/line-by-line-line.mustache | 16 +++++ ...per.html => line-by-line-wrapper.mustache} | 2 +- .../line-by-line/column-line-number.html | 6 -- src/templates/line-by-line/empty-diff.html | 7 --- src/templates/line-by-line/line.html | 16 ----- webpack.config.js | 25 -------- 15 files changed, 140 insertions(+), 126 deletions(-) create mode 100644 src/hoganjs-utils.js delete mode 100644 src/nunjucks-utils.js create mode 100644 src/templates/line-by-line-column-line-number.mustache create mode 100644 src/templates/line-by-line-empty-diff.mustache rename src/templates/{line-by-line/file-diff.html => line-by-line-file-diff.mustache} (60%) create mode 100644 src/templates/line-by-line-line.mustache rename src/templates/{line-by-line/wrapper.html => line-by-line-wrapper.mustache} (64%) delete mode 100644 src/templates/line-by-line/column-line-number.html delete mode 100644 src/templates/line-by-line/empty-diff.html delete mode 100644 src/templates/line-by-line/line.html delete mode 100644 webpack.config.js diff --git a/package.json b/package.json index f6266ca..c4ca33d 100644 --- a/package.json +++ b/package.json @@ -42,19 +42,22 @@ "codacy": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/.bin/codacy-coverage && rm -rf ./coverage" }, "main": "./src/diff2html.js", + "browser": { + "fs": false + }, "dependencies": { "diff": "^2.2.2", - "nunjucks": "^2.4.1" + "hogan.js": "^3.0.2" }, "devDependencies": { + "browserify": "^13.0.0", "clean-css": "^3.4.10", "codacy-coverage": "^1.1.3", "fast-html-parser": "^1.0.1", "istanbul": "^0.4.2", "jscs": "^2.11.0", "mocha": "^2.4.5", - "uglifyjs": "^2.4.10", - "webpack": "^1.12.14" + "uglifyjs": "^2.4.10" }, "license": "MIT", "files": [ diff --git a/release.sh b/release.sh index 66ccf24..e757f2d 100755 --- a/release.sh +++ b/release.sh @@ -30,28 +30,28 @@ echo "Cleaning previous versions ..." rm -rf ${OUTPUT_DIR} mkdir -p ${OUTPUT_DIR} -echo "Generating js aggregation file in ${OUTPUT_JS_FILE}" -webpack ${INPUT_JS_FILE} ${OUTPUT_JS_FILE} - -echo "Minifying ${OUTPUT_JS_FILE} to ${OUTPUT_MIN_JS_FILE}" -uglifyjs ${OUTPUT_JS_FILE} -c -o ${OUTPUT_MIN_JS_FILE} - -echo "Generating js ui aggregation file in ${OUTPUT_JS_UI_FILE}" -webpack ${INPUT_JS_UI_FILE} ${OUTPUT_JS_UI_FILE} - -echo "Minifying ${OUTPUT_JS_UI_FILE} to ${OUTPUT_MIN_JS_UI_FILE}" -uglifyjs ${OUTPUT_JS_UI_FILE} -c -o ${OUTPUT_MIN_JS_UI_FILE} - -echo "Pre-compile nunjucks templates in ${INTPUT_TEMPLATES_DIR}" -nunjucks-precompile ${INTPUT_TEMPLATES_DIR} > ${OUTPUT_TEMPLATES_FILE} - -echo "Minifying ${OUTPUT_TEMPLATES_FILE} to ${OUTPUT_MIN_TEMPLATES_FILE}" -uglifyjs ${OUTPUT_TEMPLATES_FILE} -c -o ${OUTPUT_MIN_TEMPLATES_FILE} - echo "Copying css file to ${OUTPUT_CSS_FILE}" cp -f ${INPUT_CSS_FILE} ${OUTPUT_CSS_FILE} echo "Minifying ${OUTPUT_CSS_FILE} to ${OUTPUT_MIN_CSS_FILE}" cleancss --advanced --compatibility=ie8 -o ${OUTPUT_MIN_CSS_FILE} ${OUTPUT_CSS_FILE} +echo "Pre-compile hogan.js templates in ${INTPUT_TEMPLATES_DIR}" +hulk --variable "browserTemplates" ${INTPUT_TEMPLATES_DIR}/*.mustache > ${OUTPUT_TEMPLATES_FILE} + +echo "Minifying ${OUTPUT_TEMPLATES_FILE} to ${OUTPUT_MIN_TEMPLATES_FILE}" +uglifyjs ${OUTPUT_TEMPLATES_FILE} -c -o ${OUTPUT_MIN_TEMPLATES_FILE} + +echo "Generating js aggregation file in ${OUTPUT_JS_FILE}" +browserify -e ${INPUT_JS_FILE} -o ${OUTPUT_JS_FILE} + +echo "Minifying ${OUTPUT_JS_FILE} to ${OUTPUT_MIN_JS_FILE}" +uglifyjs ${OUTPUT_JS_FILE} -c -o ${OUTPUT_MIN_JS_FILE} + +echo "Generating js ui aggregation file in ${OUTPUT_JS_UI_FILE}" +browserify -e ${INPUT_JS_UI_FILE} -o ${OUTPUT_JS_UI_FILE} + +echo "Minifying ${OUTPUT_JS_UI_FILE} to ${OUTPUT_MIN_JS_UI_FILE}" +uglifyjs ${OUTPUT_JS_UI_FILE} -c -o ${OUTPUT_MIN_JS_UI_FILE} + echo "diff2html release created successfully!" diff --git a/sample/index.html b/sample/index.html index 693457a..2d658a1 100644 --- a/sample/index.html +++ b/sample/index.html @@ -16,6 +16,8 @@ + + diff --git a/src/hoganjs-utils.js b/src/hoganjs-utils.js new file mode 100644 index 0000000..a2d6aa4 --- /dev/null +++ b/src/hoganjs-utils.js @@ -0,0 +1,58 @@ +/* + * + * Utils (hoganjs-utils.js) + * Author: rtfpessoa + * + */ + +(function() { + + var fs = require('fs'); + var path = require('path'); + + var hogan = require('hogan.js'); + + var templatesPath = path.resolve(__dirname, 'templates'); + var templatesCache = {}; + + function HoganJsUtils() { + } + + HoganJsUtils.prototype.render = function(namespace, view, params) { + var template = this._getTemplate(namespace, view); + if (template) { + return template.render(params); + } + + return null; + }; + + HoganJsUtils.prototype._getTemplate = function(namespace, view) { + var templateKey = this._templateKey(namespace, view); + var template = this._readFromCache(templateKey); + + if (!template && fs) { + var templatePath = path.join(templatesPath, namespace, view); + var templateContent = fs.readFileSync(templatePath + '.mustache', 'utf8'); + template = hogan.compile(templateContent); + this._addToCache(templateKey, template); + } + + return template; + }; + + HoganJsUtils.prototype._addToCache = function(templateKey, template) { + templatesCache[templateKey] = template; + }; + + HoganJsUtils.prototype._readFromCache = function(templateKey) { + return browserTemplates && browserTemplates[templateKey] || templatesCache[templateKey]; + }; + + HoganJsUtils.prototype._templateKey = function(namespace, view) { + return namespace + '-' + view; + }; + + module.exports.HoganJsUtils = new HoganJsUtils(); + +})(); diff --git a/src/line-by-line-printer.js b/src/line-by-line-printer.js index 88130ca..401cb22 100644 --- a/src/line-by-line-printer.js +++ b/src/line-by-line-printer.js @@ -12,7 +12,7 @@ var utils = require('./utils.js').Utils; var Rematch = require('./rematch.js').Rematch; - var nunjucksUtils = require('./nunjucks-utils.js').NunjucksUtils; + var hoganUtils = require('./hoganjs-utils.js').HoganJsUtils; var baseTemplatesPath = 'line-by-line'; function LineByLinePrinter(config) { @@ -20,11 +20,16 @@ } LineByLinePrinter.prototype.makeFileDiffHtml = function(file, diffs) { - return nunjucksUtils.render(baseTemplatesPath, 'file-diff.html', {'file': file, 'diffs': diffs}); + return hoganUtils.render(baseTemplatesPath, 'file-diff', { + file: file, + fileDiffName: printerUtils.getDiffName(file), + fileHtmlId: printerUtils.getHtmlId(file), + diffs: diffs + }); }; LineByLinePrinter.prototype.makeLineByLineHtmlWrapper = function(content) { - return nunjucksUtils.render(baseTemplatesPath, 'wrapper.html', {'content': content}); + return hoganUtils.render(baseTemplatesPath, 'wrapper', {'content': content}); }; LineByLinePrinter.prototype.generateLineByLineJsonHtml = function(diffFiles) { @@ -50,7 +55,10 @@ }); LineByLinePrinter.prototype.makeColumnLineNumberHtml = function(block) { - return nunjucksUtils.render(baseTemplatesPath, 'column-line-number.html', {block: block}); + return hoganUtils.render(baseTemplatesPath, 'column-line-number', { + diffParser: diffParser, + block: utils.escape(block.header) + }); }; LineByLinePrinter.prototype._generateFileHtml = function(file) { @@ -69,7 +77,7 @@ var comparisons = oldLines.length * newLines.length; var maxComparisons = that.config.matchingMaxComparisons || 2500; var doMatching = comparisons < maxComparisons && (that.config.matching === 'lines' || - that.config.matching === 'words'); + that.config.matching === 'words'); if (doMatching) { matches = matcher(oldLines, newLines); @@ -162,18 +170,20 @@ }; LineByLinePrinter.prototype.makeLineHtml = function(type, oldNumber, newNumber, content, prefix) { - return nunjucksUtils.render(baseTemplatesPath, 'line.html', + return hoganUtils.render(baseTemplatesPath, 'line', { type: type, - oldNumber: oldNumber, - newNumber: newNumber, - prefix: prefix, - content: content + oldNumber: utils.valueOrEmpty(oldNumber), + newNumber: utils.valueOrEmpty(newNumber), + prefix: prefix && utils.convertWhiteSpaceToNonBreakingSpace(prefix), + content: content && utils.convertWhiteSpaceToNonBreakingSpace(content) }); }; LineByLinePrinter.prototype._generateEmptyDiff = function() { - return nunjucksUtils.render(baseTemplatesPath, 'empty-diff.html', {}); + return hoganUtils.render(baseTemplatesPath, 'empty-diff', { + diffParser: diffParser + }); }; module.exports.LineByLinePrinter = LineByLinePrinter; diff --git a/src/nunjucks-utils.js b/src/nunjucks-utils.js deleted file mode 100644 index 1fb4bdd..0000000 --- a/src/nunjucks-utils.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * Utils (utils.js) - * Author: rtfpessoa - * - */ - -(function() { - - var path = require('path'); - - var nunjucks = require('nunjucks'); - var templatesPath = path.resolve(__dirname, 'templates'); - - var diffParser = require('./diff-parser.js').DiffParser; - var printerUtils = require('./printer-utils.js').PrinterUtils; - var utils = require('./utils.js').Utils; - - var nunjucksEnv = nunjucks.configure(templatesPath, {"autoescape": false}) - .addGlobal('printerUtils', printerUtils) - .addGlobal('utils', utils) - .addGlobal('diffParser', diffParser); - - function NunjucksUtils() { - } - - NunjucksUtils.prototype.render = function(namespace, view, params) { - var viewPath = path.join(namespace, view); - return nunjucksEnv.render(viewPath, params); - }; - - module.exports.NunjucksUtils = new NunjucksUtils(); - -})(); diff --git a/src/templates/line-by-line-column-line-number.mustache b/src/templates/line-by-line-column-line-number.mustache new file mode 100644 index 0000000..ca6d6cb --- /dev/null +++ b/src/templates/line-by-line-column-line-number.mustache @@ -0,0 +1,6 @@ + + + +
{{{blockHeader}}}
+ + diff --git a/src/templates/line-by-line-empty-diff.mustache b/src/templates/line-by-line-empty-diff.mustache new file mode 100644 index 0000000..c9907a3 --- /dev/null +++ b/src/templates/line-by-line-empty-diff.mustache @@ -0,0 +1,7 @@ + + +
+ File without changes +
+ + diff --git a/src/templates/line-by-line/file-diff.html b/src/templates/line-by-line-file-diff.mustache similarity index 60% rename from src/templates/line-by-line/file-diff.html rename to src/templates/line-by-line-file-diff.mustache index 5629706..7789fda 100644 --- a/src/templates/line-by-line/file-diff.html +++ b/src/templates/line-by-line-file-diff.mustache @@ -1,22 +1,22 @@ -
+
- +{{ file.addedLines }} + +{{file.addedLines}} - -{{ file.deletedLines }} + -{{file.deletedLines}} -  {{ printerUtils.getDiffName(file) }} +  {{fileDiffName}}
- {{ diffs | safe}} + {{{diffs}}}
diff --git a/src/templates/line-by-line-line.mustache b/src/templates/line-by-line-line.mustache new file mode 100644 index 0000000..081c2e2 --- /dev/null +++ b/src/templates/line-by-line-line.mustache @@ -0,0 +1,16 @@ + + +
{{oldNumber}}
+
{{newNumber}}
+ + +
+ {{#prefix}} + {{{prefix}}} + {{/prefix}} + {{#content}} + {{{content}}} + {{/content}} +
+ + diff --git a/src/templates/line-by-line/wrapper.html b/src/templates/line-by-line-wrapper.mustache similarity index 64% rename from src/templates/line-by-line/wrapper.html rename to src/templates/line-by-line-wrapper.mustache index 002e85c..be5096a 100644 --- a/src/templates/line-by-line/wrapper.html +++ b/src/templates/line-by-line-wrapper.mustache @@ -1,3 +1,3 @@
- {{ content }} + {{{content}}}
diff --git a/src/templates/line-by-line/column-line-number.html b/src/templates/line-by-line/column-line-number.html deleted file mode 100644 index 6e1029c..0000000 --- a/src/templates/line-by-line/column-line-number.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -
{{ utils.escape(block.header) }}
- - diff --git a/src/templates/line-by-line/empty-diff.html b/src/templates/line-by-line/empty-diff.html deleted file mode 100644 index 65211b9..0000000 --- a/src/templates/line-by-line/empty-diff.html +++ /dev/null @@ -1,7 +0,0 @@ - - -
- File without changes -
- - diff --git a/src/templates/line-by-line/line.html b/src/templates/line-by-line/line.html deleted file mode 100644 index 698583f..0000000 --- a/src/templates/line-by-line/line.html +++ /dev/null @@ -1,16 +0,0 @@ - - -
{{ utils.valueOrEmpty(oldNumber) | safe }}
-
{{ utils.valueOrEmpty(newNumber) | safe }}
- - -
- {%- if prefix %} - {{ utils.convertWhiteSpaceToNonBreakingSpace(prefix) | safe }} - {% endif -%} - {% if content -%} - {{ utils.convertWhiteSpaceToNonBreakingSpace(content) | safe }} - {%- endif %} -
- - diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index fba230d..0000000 --- a/webpack.config.js +++ /dev/null @@ -1,25 +0,0 @@ -// Webpack config -var webpack = require('webpack'); - -module.exports = { - - plugins: [ - - new webpack.NormalModuleReplacementPlugin( - /(nunjucks)$/, - 'nunjucks/index' - ), - - new webpack.NormalModuleReplacementPlugin( - /(precompile|nodes|lexer|parser|transformer|compiler|loaders)$/, - 'node-libs-browser/mock/empty' - ), - - new webpack.DefinePlugin({ - 'process.env': { - IS_BROWSER: true - } - }) - - ] -}; From 8c45320674d51b65e1ce48a82159750a89e549fd Mon Sep 17 00:00:00 2001 From: Rodrigo Fernandes Date: Sat, 16 Apr 2016 11:10:08 +0100 Subject: [PATCH 2/4] Fix wrong template path --- src/hoganjs-utils.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/hoganjs-utils.js b/src/hoganjs-utils.js index a2d6aa4..a4893bf 100644 --- a/src/hoganjs-utils.js +++ b/src/hoganjs-utils.js @@ -19,7 +19,9 @@ } HoganJsUtils.prototype.render = function(namespace, view, params) { - var template = this._getTemplate(namespace, view); + var templateKey = this._templateKey(namespace, view); + + var template = this._getTemplate(templateKey); if (template) { return template.render(params); } @@ -27,12 +29,11 @@ return null; }; - HoganJsUtils.prototype._getTemplate = function(namespace, view) { - var templateKey = this._templateKey(namespace, view); + HoganJsUtils.prototype._getTemplate = function(templateKey) { var template = this._readFromCache(templateKey); if (!template && fs) { - var templatePath = path.join(templatesPath, namespace, view); + var templatePath = path.join(templatesPath, templateKey); var templateContent = fs.readFileSync(templatePath + '.mustache', 'utf8'); template = hogan.compile(templateContent); this._addToCache(templateKey, template); From 05a09ae2a722ead544e18b4dfd6787f1ad63bd44 Mon Sep 17 00:00:00 2001 From: Rodrigo Fernandes Date: Sat, 16 Apr 2016 11:14:31 +0100 Subject: [PATCH 3/4] Fix browserTemplates global usage in node --- src/hoganjs-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hoganjs-utils.js b/src/hoganjs-utils.js index a4893bf..31cad57 100644 --- a/src/hoganjs-utils.js +++ b/src/hoganjs-utils.js @@ -47,7 +47,7 @@ }; HoganJsUtils.prototype._readFromCache = function(templateKey) { - return browserTemplates && browserTemplates[templateKey] || templatesCache[templateKey]; + return global.browserTemplates && global.browserTemplates[templateKey] || templatesCache[templateKey]; }; HoganJsUtils.prototype._templateKey = function(namespace, view) { From b1f1ba6008aaf9ddd82e1c812426e901443595f3 Mon Sep 17 00:00:00 2001 From: Rodrigo Fernandes Date: Sat, 16 Apr 2016 12:06:03 +0100 Subject: [PATCH 4/4] Use pre-compiled templates in node --- .gitignore | 3 + .jscsrc | 2 - circle.yml | 3 +- package.json | 11 +- scripts/.ignore | 0 scripts/hulk.js | 206 ++++++++++++++++++ release.sh => scripts/release.sh | 11 +- src/hoganjs-utils.js | 30 ++- src/printer-utils.js | 4 +- src/templates/diff2html-templates.js | 9 + .../line-by-line-column-line-number.mustache | 2 +- src/templates/line-by-line-line.mustache | 12 +- 12 files changed, 263 insertions(+), 30 deletions(-) create mode 100644 scripts/.ignore create mode 100755 scripts/hulk.js rename release.sh => scripts/release.sh (89%) create mode 100644 src/templates/diff2html-templates.js diff --git a/.gitignore b/.gitignore index d9ee7ac..6ed8e20 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,8 @@ target/ node_modules/ npm-debug.log +# Istanbul +coverage/ + # Bower bower_components/ diff --git a/.jscsrc b/.jscsrc index 03eb9b2..8d2a6cc 100644 --- a/.jscsrc +++ b/.jscsrc @@ -21,9 +21,7 @@ "disallowTrailingWhitespace": true, "maximumLineLength": 130, "requireCamelCaseOrUpperCaseIdentifiers": true, - "requireCapitalizedComments": true, "requireCapitalizedConstructors": true, - "requireCurlyBraces": true, "requireSpaceAfterKeywords": [ "if", "else", diff --git a/circle.yml b/circle.yml index addc8c7..b239e90 100644 --- a/circle.yml +++ b/circle.yml @@ -5,6 +5,5 @@ test: - nvm install 5 && npm test post: - npm install - - istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec + - npm test - cat ./coverage/lcov.info | ./node_modules/.bin/codacy-coverage - - rm -rf ./coverage diff --git a/package.json b/package.json index c4ca33d..21825d0 100644 --- a/package.json +++ b/package.json @@ -32,14 +32,15 @@ "url": "https://www.github.com/rtfpessoa/diff2html/issues" }, "engines": { - "node": ">=0.10" + "node": ">=0.12" }, "preferGlobal": true, "scripts": { - "release": "bash release.sh", - "test": "mocha", + "release": "./scripts/release.sh", + "templates": "./scripts/hulk.js --wrapper node --variable 'browserTemplates' ./src/templates/*.mustache > ./src/templates/diff2html-templates.js", + "test": "istanbul cover _mocha --report lcovonly -- -u exports -R spec ./test/**/*", "style": "jscs src test", - "codacy": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/.bin/codacy-coverage && rm -rf ./coverage" + "codacy": "istanbul cover _mocha --report lcovonly -- -u exports -R spec ./test/**/* && cat ./coverage/lcov.info | codacy-coverage" }, "main": "./src/diff2html.js", "browser": { @@ -56,7 +57,9 @@ "fast-html-parser": "^1.0.1", "istanbul": "^0.4.2", "jscs": "^2.11.0", + "mkdirp": "^0.5.1", "mocha": "^2.4.5", + "nopt": "^3.0.6", "uglifyjs": "^2.4.10" }, "license": "MIT", diff --git a/scripts/.ignore b/scripts/.ignore new file mode 100644 index 0000000..e69de29 diff --git a/scripts/hulk.js b/scripts/hulk.js new file mode 100755 index 0000000..38e58ad --- /dev/null +++ b/scripts/hulk.js @@ -0,0 +1,206 @@ +#!/usr/bin/env node + +/* + * Copyright 2011 Twitter, Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// dependencies +var hogan = require('hogan.js'); +var path = require('path'); +var nopt = require('nopt'); +var mkderp = require('mkdirp'); +var fs = require('fs'); + + +// locals +var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\']; +var specialsRegExp = new RegExp('(\\' + specials.join('|\\') + ')', 'g'); +var options = { + 'namespace': String, + 'outputdir': path, + 'variable': String, + 'wrapper': String, + 'version': true, + 'help': true +}; +var shortHand = { + 'n': ['--namespace'], + 'o': ['--outputdir'], + 'vn': ['--variable'], + 'w': ['--wrapper'], + 'h': ['--help'], + 'v': ['--version'] +}; +var templates; + + +// options +options = nopt(options, shortHand); + + +// escape special regexp characters +function esc(text) { + return text.replace(specialsRegExp, '\\$1'); +} + + +// cyan function for rob +function cyan(text) { + return '\033[36m' + text + '\033[39m'; +} + + +// check for dirs and correct ext (<3 for windows) +function extractFiles(args) { + var usage = '\n' + + cyan('USAGE:') + ' hulk [--wrapper wrapper] [--outputdir outputdir] ' + + '[--namespace namespace] [--variable variable] FILES\n\n' + + cyan('OPTIONS:') + ' [-w, --wrapper] :: wraps the template (i.e. amd)\n' + + ' [-o, --outputdir] :: outputs the templates as individual files to a directory\n\n' + + ' [-n, --namespace] :: prepend string to template names\n\n' + + ' [-vn, --variable] :: variable name for non-amd wrapper\n\n' + + cyan('EXAMPLE:') + ' hulk --wrapper amd ./templates/*.mustache\n\n' + + cyan('NOTE:') + ' hulk supports the "*" wildcard and allows you to target specific extensions too\n'; + var files = []; + + if (options.version) { + console.log(require('../package.json').version); + process.exit(0); + } + + if (!args.length || options.help) { + console.log(usage); + process.exit(0); + } + + args.forEach(function(arg) { + + if (/\*/.test(arg)) { + arg = arg.split('*'); + return files = files.concat( + fs.readdirSync(arg[0] || '.') + .map(function(f) { + var file = path.join(arg[0], f); + return new RegExp(esc(arg[1]) + '$').test(f) && fs.statSync(file).isFile() && file; + }) + .filter(function(f) { + return f; + }) + ); + } + + if (fs.statSync(arg).isFile()) files.push(arg); + + }); + + return files; +} + + +// remove utf-8 byte order mark, http://en.wikipedia.org/wiki/Byte_order_mark +function removeByteOrderMark(text) { + if (text.charCodeAt(0) === 0xfeff) { + return text.substring(1); + } + return text; +} + + +// wrap templates +function wrap(file, name, openedFile) { + switch (options.wrapper) { + case "amd": + return 'define(' + (!options.outputdir ? '"' + path.join(path.dirname(file), name) + '", ' : '') + + '[ "hogan.js" ], function(Hogan){ return new Hogan.Template(' + + hogan.compile(openedFile, {asString: 1}) + + ');});'; + case "node": + var globalObj = 'global.' + (options.variable || 'templates') + '["' + name + '"]'; + var globalStmt = globalObj + ' = new Hogan.Template(' + hogan.compile(openedFile, {asString: 1}) + ');'; + var nodeOutput = globalStmt; + + // if we have a template per file the export will expose the template directly + if (options.outputdir) { + nodeOutput = nodeOutput + '\n' + 'module.exports = ' + globalObj + ';'; + } + + return nodeOutput; + default: + return (options.variable || 'templates') + + '["' + name + '"] = new Hogan.Template(' + + hogan.compile(openedFile, {asString: 1}) + + ');'; + } +} + + +function prepareOutput(content) { + var variableName = options.variable || 'templates'; + switch (options.wrapper) { + case "amd": + return content; + case "node": + var nodeExport = ''; + + // if we have aggregated templates the export will expose the template map + if (!options.outputdir) { + nodeExport = 'module.exports = global.' + variableName + ';\n'; + } + + return '(function() {\n' + + 'if (!!!global.' + variableName + ') global.' + variableName + ' = {};\n' + + content + '\n' + + nodeExport + + '})();'; + default: + return 'if (!!!' + variableName + ') var ' + variableName + ' = {};\n' + content; + } +} + + +// write the directory +if (options.outputdir) { + mkderp.sync(options.outputdir); +} + + +// Prepend namespace to template name +function namespace(name) { + return (options.namespace || '') + name; +} + + +// write a template foreach file that matches template extension +templates = extractFiles(options.argv.remain) + .map(function(file) { + var openedFile = fs.readFileSync(file, 'utf-8'); + var name; + if (!openedFile) return; + name = namespace(path.basename(file).replace(/\..*$/, '')); + openedFile = removeByteOrderMark(openedFile.trim()); + openedFile = wrap(file, name, openedFile); + if (!options.outputdir) return openedFile; + fs.writeFileSync(path.join(options.outputdir, name + '.js') + , prepareOutput(openedFile)); + }) + .filter(function(t) { + return t; + }); + + +// output templates +if (!templates.length || options.outputdir) process.exit(0); + +console.log(prepareOutput(templates.join('\n'))); diff --git a/release.sh b/scripts/release.sh similarity index 89% rename from release.sh rename to scripts/release.sh index e757f2d..80f0d9c 100755 --- a/release.sh +++ b/scripts/release.sh @@ -14,6 +14,8 @@ INPUT_JS_FILE=${INPUT_DIR}/diff2html.js INPUT_JS_UI_FILE=${INPUT_UI_DIR}/js/diff2html-ui.js INPUT_CSS_FILE=${INPUT_UI_DIR}/css/diff2html.css +GENERATED_TEMPLATES_FILE=${INTPUT_TEMPLATES_DIR}/diff2html-templates.js + OUTPUT_DIR=dist OUTPUT_JS_FILE=${OUTPUT_DIR}/diff2html.js OUTPUT_MIN_JS_FILE=${OUTPUT_DIR}/diff2html.min.js @@ -30,16 +32,15 @@ echo "Cleaning previous versions ..." rm -rf ${OUTPUT_DIR} mkdir -p ${OUTPUT_DIR} -echo "Copying css file to ${OUTPUT_CSS_FILE}" -cp -f ${INPUT_CSS_FILE} ${OUTPUT_CSS_FILE} - echo "Minifying ${OUTPUT_CSS_FILE} to ${OUTPUT_MIN_CSS_FILE}" +cp -f ${INPUT_CSS_FILE} ${OUTPUT_CSS_FILE} cleancss --advanced --compatibility=ie8 -o ${OUTPUT_MIN_CSS_FILE} ${OUTPUT_CSS_FILE} -echo "Pre-compile hogan.js templates in ${INTPUT_TEMPLATES_DIR}" -hulk --variable "browserTemplates" ${INTPUT_TEMPLATES_DIR}/*.mustache > ${OUTPUT_TEMPLATES_FILE} +echo "Pre-compile hogan.js templates" +npm run templates echo "Minifying ${OUTPUT_TEMPLATES_FILE} to ${OUTPUT_MIN_TEMPLATES_FILE}" +browserify -e ${GENERATED_TEMPLATES_FILE} -o ${OUTPUT_TEMPLATES_FILE} uglifyjs ${OUTPUT_TEMPLATES_FILE} -c -o ${OUTPUT_MIN_TEMPLATES_FILE} echo "Generating js aggregation file in ${OUTPUT_JS_FILE}" diff --git a/src/hoganjs-utils.js b/src/hoganjs-utils.js index 31cad57..84b2016 100644 --- a/src/hoganjs-utils.js +++ b/src/hoganjs-utils.js @@ -12,10 +12,17 @@ var hogan = require('hogan.js'); + var hoganTemplates; + var templatesPath = path.resolve(__dirname, 'templates'); var templatesCache = {}; function HoganJsUtils() { + try { + hoganTemplates = require('./templates/diff2html-templates.js'); + } catch (_ignore) { + hoganTemplates = {}; + } } HoganJsUtils.prototype.render = function(namespace, view, params) { @@ -32,22 +39,29 @@ HoganJsUtils.prototype._getTemplate = function(templateKey) { var template = this._readFromCache(templateKey); - if (!template && fs) { - var templatePath = path.join(templatesPath, templateKey); - var templateContent = fs.readFileSync(templatePath + '.mustache', 'utf8'); - template = hogan.compile(templateContent); - this._addToCache(templateKey, template); + if (!template) { + template = this._loadTemplate(templateKey); } return template; }; - HoganJsUtils.prototype._addToCache = function(templateKey, template) { - templatesCache[templateKey] = template; + HoganJsUtils.prototype._loadTemplate = function(templateKey) { + var template; + if (fs.readFileSync) { + var templatePath = path.join(templatesPath, templateKey); + var templateContent = fs.readFileSync(templatePath + '.mustache', 'utf8'); + template = hogan.compile(templateContent); + templatesCache[templateKey] = template; + } + + return template; }; HoganJsUtils.prototype._readFromCache = function(templateKey) { - return global.browserTemplates && global.browserTemplates[templateKey] || templatesCache[templateKey]; + return global.browserTemplates && global.browserTemplates[templateKey] || + hoganTemplates[templateKey] || + templatesCache[templateKey]; }; HoganJsUtils.prototype._templateKey = function(namespace, view) { diff --git a/src/printer-utils.js b/src/printer-utils.js index b405f14..109228c 100644 --- a/src/printer-utils.js +++ b/src/printer-utils.js @@ -39,8 +39,8 @@ var oldFilename = file.oldName; var newFilename = file.newName; - if (oldFilename && newFilename && oldFilename !== newFilename - && !isDevNullName(oldFilename) && !isDevNullName(newFilename)) { + if (oldFilename && newFilename && oldFilename !== newFilename && + !isDevNullName(oldFilename) && !isDevNullName(newFilename)) { return oldFilename + ' -> ' + newFilename; } else if (newFilename && !isDevNullName(newFilename)) { return newFilename; diff --git a/src/templates/diff2html-templates.js b/src/templates/diff2html-templates.js new file mode 100644 index 0000000..1fcb5ec --- /dev/null +++ b/src/templates/diff2html-templates.js @@ -0,0 +1,9 @@ +(function() { +if (!!!global.browserTemplates) global.browserTemplates = {}; +global.browserTemplates["line-by-line-column-line-number"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
");t.b(t.t(t.f("blockHeader",c,p,0)));t.b("
");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +global.browserTemplates["line-by-line-empty-diff"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
");t.b("\n" + i);t.b(" File without changes");t.b("\n" + i);t.b("
");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +global.browserTemplates["line-by-line-file-diff"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("
");t.b("\n" + i);t.b("
");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" +");t.b(t.v(t.d("file.addedLines",c,p,0)));t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" -");t.b(t.v(t.d("file.deletedLines",c,p,0)));t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("  ");t.b(t.v(t.f("fileDiffName",c,p,0)));t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
");t.b("\n" + i);t.b("
");t.b("\n" + i);t.b("
");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b(t.t(t.f("diffs",c,p,0)));t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
");t.b("\n" + i);t.b("
");t.b("\n" + i);t.b("
");t.b("\n" + i);t.b("
");return t.fl(); },partials: {}, subs: { }}); +global.browserTemplates["line-by-line-line"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
");t.b(t.v(t.f("oldNumber",c,p,0)));t.b("
");t.b("\n" + i);t.b("
");t.b(t.v(t.f("newNumber",c,p,0)));t.b("
");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
");t.b("\n" + i);if(t.s(t.f("prefix",c,p,1),c,p,0,253,329,"{{ }}")){t.rs(c,p,function(c,p,t){t.b(" ");t.b(t.t(t.f("prefix",c,p,0)));t.b("");t.b("\n" + i);});c.pop();}if(t.s(t.f("content",c,p,1),c,p,0,361,435,"{{ }}")){t.rs(c,p,function(c,p,t){t.b(" ");t.b(t.t(t.f("content",c,p,0)));t.b("");t.b("\n" + i);});c.pop();}t.b("
");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +global.browserTemplates["line-by-line-wrapper"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("
");t.b("\n" + i);t.b(" ");t.b(t.t(t.f("content",c,p,0)));t.b("\n" + i);t.b("
");return t.fl(); },partials: {}, subs: { }}); +module.exports = global.browserTemplates; +})(); diff --git a/src/templates/line-by-line-column-line-number.mustache b/src/templates/line-by-line-column-line-number.mustache index ca6d6cb..72825ed 100644 --- a/src/templates/line-by-line-column-line-number.mustache +++ b/src/templates/line-by-line-column-line-number.mustache @@ -1,6 +1,6 @@ -
{{{blockHeader}}}
+
{{{blockHeader}}}
diff --git a/src/templates/line-by-line-line.mustache b/src/templates/line-by-line-line.mustache index 081c2e2..1893a24 100644 --- a/src/templates/line-by-line-line.mustache +++ b/src/templates/line-by-line-line.mustache @@ -5,12 +5,12 @@
- {{#prefix}} - {{{prefix}}} - {{/prefix}} - {{#content}} - {{{content}}} - {{/content}} + {{#prefix}} + {{{prefix}}} + {{/prefix}} + {{#content}} + {{{content}}} + {{/content}}