Skip to content

Commit 9d34266

Browse files
committed
Merge pull request #69 from rtfpessoa/hogan.js
Use Hogan.js for templating engine
2 parents 3742653 + b1f1ba6 commit 9d34266

22 files changed

+380
-132
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,8 @@ target/
1919
node_modules/
2020
npm-debug.log
2121

22+
# Istanbul
23+
coverage/
24+
2225
# Bower
2326
bower_components/

.jscsrc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@
2121
"disallowTrailingWhitespace": true,
2222
"maximumLineLength": 130,
2323
"requireCamelCaseOrUpperCaseIdentifiers": true,
24-
"requireCapitalizedComments": true,
2524
"requireCapitalizedConstructors": true,
26-
"requireCurlyBraces": true,
2725
"requireSpaceAfterKeywords": [
2826
"if",
2927
"else",

circle.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@ test:
55
- nvm install 5 && npm test
66
post:
77
- npm install
8-
- istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec
8+
- npm test
99
- cat ./coverage/lcov.info | ./node_modules/.bin/codacy-coverage
10-
- rm -rf ./coverage

package.json

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,29 +32,35 @@
3232
"url": "https://www.github.com/rtfpessoa/diff2html/issues"
3333
},
3434
"engines": {
35-
"node": ">=0.10"
35+
"node": ">=0.12"
3636
},
3737
"preferGlobal": true,
3838
"scripts": {
39-
"release": "bash release.sh",
40-
"test": "mocha",
39+
"release": "./scripts/release.sh",
40+
"templates": "./scripts/hulk.js --wrapper node --variable 'browserTemplates' ./src/templates/*.mustache > ./src/templates/diff2html-templates.js",
41+
"test": "istanbul cover _mocha --report lcovonly -- -u exports -R spec ./test/**/*",
4142
"style": "jscs src test",
42-
"codacy": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/.bin/codacy-coverage && rm -rf ./coverage"
43+
"codacy": "istanbul cover _mocha --report lcovonly -- -u exports -R spec ./test/**/* && cat ./coverage/lcov.info | codacy-coverage"
4344
},
4445
"main": "./src/diff2html.js",
46+
"browser": {
47+
"fs": false
48+
},
4549
"dependencies": {
4650
"diff": "^2.2.2",
47-
"nunjucks": "^2.4.1"
51+
"hogan.js": "^3.0.2"
4852
},
4953
"devDependencies": {
54+
"browserify": "^13.0.0",
5055
"clean-css": "^3.4.10",
5156
"codacy-coverage": "^1.1.3",
5257
"fast-html-parser": "^1.0.1",
5358
"istanbul": "^0.4.2",
5459
"jscs": "^2.11.0",
60+
"mkdirp": "^0.5.1",
5561
"mocha": "^2.4.5",
56-
"uglifyjs": "^2.4.10",
57-
"webpack": "^1.12.14"
62+
"nopt": "^3.0.6",
63+
"uglifyjs": "^2.4.10"
5864
},
5965
"license": "MIT",
6066
"files": [

sample/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script>
1717
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script>
1818

19+
<script src="https://cdnjs.cloudflare.com/ajax/libs/hogan.js/3.0.2/hogan.min.js"></script>
20+
1921
<!-- diff2html -->
2022
<link rel="stylesheet" type="text/css" href="../dist/diff2html.css">
2123
<script type="text/javascript" src="../dist/diff2html-templates.js"></script>

scripts/.ignore

Whitespace-only changes.

scripts/hulk.js

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
#!/usr/bin/env node
2+
3+
/*
4+
* Copyright 2011 Twitter, Inc.
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
19+
// dependencies
20+
var hogan = require('hogan.js');
21+
var path = require('path');
22+
var nopt = require('nopt');
23+
var mkderp = require('mkdirp');
24+
var fs = require('fs');
25+
26+
27+
// locals
28+
var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'];
29+
var specialsRegExp = new RegExp('(\\' + specials.join('|\\') + ')', 'g');
30+
var options = {
31+
'namespace': String,
32+
'outputdir': path,
33+
'variable': String,
34+
'wrapper': String,
35+
'version': true,
36+
'help': true
37+
};
38+
var shortHand = {
39+
'n': ['--namespace'],
40+
'o': ['--outputdir'],
41+
'vn': ['--variable'],
42+
'w': ['--wrapper'],
43+
'h': ['--help'],
44+
'v': ['--version']
45+
};
46+
var templates;
47+
48+
49+
// options
50+
options = nopt(options, shortHand);
51+
52+
53+
// escape special regexp characters
54+
function esc(text) {
55+
return text.replace(specialsRegExp, '\\$1');
56+
}
57+
58+
59+
// cyan function for rob
60+
function cyan(text) {
61+
return '\033[36m' + text + '\033[39m';
62+
}
63+
64+
65+
// check for dirs and correct ext (<3 for windows)
66+
function extractFiles(args) {
67+
var usage = '\n' +
68+
cyan('USAGE:') + ' hulk [--wrapper wrapper] [--outputdir outputdir] ' +
69+
'[--namespace namespace] [--variable variable] FILES\n\n' +
70+
cyan('OPTIONS:') + ' [-w, --wrapper] :: wraps the template (i.e. amd)\n' +
71+
' [-o, --outputdir] :: outputs the templates as individual files to a directory\n\n' +
72+
' [-n, --namespace] :: prepend string to template names\n\n' +
73+
' [-vn, --variable] :: variable name for non-amd wrapper\n\n' +
74+
cyan('EXAMPLE:') + ' hulk --wrapper amd ./templates/*.mustache\n\n' +
75+
cyan('NOTE:') + ' hulk supports the "*" wildcard and allows you to target specific extensions too\n';
76+
var files = [];
77+
78+
if (options.version) {
79+
console.log(require('../package.json').version);
80+
process.exit(0);
81+
}
82+
83+
if (!args.length || options.help) {
84+
console.log(usage);
85+
process.exit(0);
86+
}
87+
88+
args.forEach(function(arg) {
89+
90+
if (/\*/.test(arg)) {
91+
arg = arg.split('*');
92+
return files = files.concat(
93+
fs.readdirSync(arg[0] || '.')
94+
.map(function(f) {
95+
var file = path.join(arg[0], f);
96+
return new RegExp(esc(arg[1]) + '$').test(f) && fs.statSync(file).isFile() && file;
97+
})
98+
.filter(function(f) {
99+
return f;
100+
})
101+
);
102+
}
103+
104+
if (fs.statSync(arg).isFile()) files.push(arg);
105+
106+
});
107+
108+
return files;
109+
}
110+
111+
112+
// remove utf-8 byte order mark, http://en.wikipedia.org/wiki/Byte_order_mark
113+
function removeByteOrderMark(text) {
114+
if (text.charCodeAt(0) === 0xfeff) {
115+
return text.substring(1);
116+
}
117+
return text;
118+
}
119+
120+
121+
// wrap templates
122+
function wrap(file, name, openedFile) {
123+
switch (options.wrapper) {
124+
case "amd":
125+
return 'define(' + (!options.outputdir ? '"' + path.join(path.dirname(file), name) + '", ' : '') +
126+
'[ "hogan.js" ], function(Hogan){ return new Hogan.Template(' +
127+
hogan.compile(openedFile, {asString: 1}) +
128+
');});';
129+
case "node":
130+
var globalObj = 'global.' + (options.variable || 'templates') + '["' + name + '"]';
131+
var globalStmt = globalObj + ' = new Hogan.Template(' + hogan.compile(openedFile, {asString: 1}) + ');';
132+
var nodeOutput = globalStmt;
133+
134+
// if we have a template per file the export will expose the template directly
135+
if (options.outputdir) {
136+
nodeOutput = nodeOutput + '\n' + 'module.exports = ' + globalObj + ';';
137+
}
138+
139+
return nodeOutput;
140+
default:
141+
return (options.variable || 'templates') +
142+
'["' + name + '"] = new Hogan.Template(' +
143+
hogan.compile(openedFile, {asString: 1}) +
144+
');';
145+
}
146+
}
147+
148+
149+
function prepareOutput(content) {
150+
var variableName = options.variable || 'templates';
151+
switch (options.wrapper) {
152+
case "amd":
153+
return content;
154+
case "node":
155+
var nodeExport = '';
156+
157+
// if we have aggregated templates the export will expose the template map
158+
if (!options.outputdir) {
159+
nodeExport = 'module.exports = global.' + variableName + ';\n';
160+
}
161+
162+
return '(function() {\n' +
163+
'if (!!!global.' + variableName + ') global.' + variableName + ' = {};\n' +
164+
content + '\n' +
165+
nodeExport +
166+
'})();';
167+
default:
168+
return 'if (!!!' + variableName + ') var ' + variableName + ' = {};\n' + content;
169+
}
170+
}
171+
172+
173+
// write the directory
174+
if (options.outputdir) {
175+
mkderp.sync(options.outputdir);
176+
}
177+
178+
179+
// Prepend namespace to template name
180+
function namespace(name) {
181+
return (options.namespace || '') + name;
182+
}
183+
184+
185+
// write a template foreach file that matches template extension
186+
templates = extractFiles(options.argv.remain)
187+
.map(function(file) {
188+
var openedFile = fs.readFileSync(file, 'utf-8');
189+
var name;
190+
if (!openedFile) return;
191+
name = namespace(path.basename(file).replace(/\..*$/, ''));
192+
openedFile = removeByteOrderMark(openedFile.trim());
193+
openedFile = wrap(file, name, openedFile);
194+
if (!options.outputdir) return openedFile;
195+
fs.writeFileSync(path.join(options.outputdir, name + '.js')
196+
, prepareOutput(openedFile));
197+
})
198+
.filter(function(t) {
199+
return t;
200+
});
201+
202+
203+
// output templates
204+
if (!templates.length || options.outputdir) process.exit(0);
205+
206+
console.log(prepareOutput(templates.join('\n')));

release.sh renamed to scripts/release.sh

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ INPUT_JS_FILE=${INPUT_DIR}/diff2html.js
1414
INPUT_JS_UI_FILE=${INPUT_UI_DIR}/js/diff2html-ui.js
1515
INPUT_CSS_FILE=${INPUT_UI_DIR}/css/diff2html.css
1616

17+
GENERATED_TEMPLATES_FILE=${INTPUT_TEMPLATES_DIR}/diff2html-templates.js
18+
1719
OUTPUT_DIR=dist
1820
OUTPUT_JS_FILE=${OUTPUT_DIR}/diff2html.js
1921
OUTPUT_MIN_JS_FILE=${OUTPUT_DIR}/diff2html.min.js
@@ -30,28 +32,27 @@ echo "Cleaning previous versions ..."
3032
rm -rf ${OUTPUT_DIR}
3133
mkdir -p ${OUTPUT_DIR}
3234

35+
echo "Minifying ${OUTPUT_CSS_FILE} to ${OUTPUT_MIN_CSS_FILE}"
36+
cp -f ${INPUT_CSS_FILE} ${OUTPUT_CSS_FILE}
37+
cleancss --advanced --compatibility=ie8 -o ${OUTPUT_MIN_CSS_FILE} ${OUTPUT_CSS_FILE}
38+
39+
echo "Pre-compile hogan.js templates"
40+
npm run templates
41+
42+
echo "Minifying ${OUTPUT_TEMPLATES_FILE} to ${OUTPUT_MIN_TEMPLATES_FILE}"
43+
browserify -e ${GENERATED_TEMPLATES_FILE} -o ${OUTPUT_TEMPLATES_FILE}
44+
uglifyjs ${OUTPUT_TEMPLATES_FILE} -c -o ${OUTPUT_MIN_TEMPLATES_FILE}
45+
3346
echo "Generating js aggregation file in ${OUTPUT_JS_FILE}"
34-
webpack ${INPUT_JS_FILE} ${OUTPUT_JS_FILE}
47+
browserify -e ${INPUT_JS_FILE} -o ${OUTPUT_JS_FILE}
3548

3649
echo "Minifying ${OUTPUT_JS_FILE} to ${OUTPUT_MIN_JS_FILE}"
3750
uglifyjs ${OUTPUT_JS_FILE} -c -o ${OUTPUT_MIN_JS_FILE}
3851

3952
echo "Generating js ui aggregation file in ${OUTPUT_JS_UI_FILE}"
40-
webpack ${INPUT_JS_UI_FILE} ${OUTPUT_JS_UI_FILE}
53+
browserify -e ${INPUT_JS_UI_FILE} -o ${OUTPUT_JS_UI_FILE}
4154

4255
echo "Minifying ${OUTPUT_JS_UI_FILE} to ${OUTPUT_MIN_JS_UI_FILE}"
4356
uglifyjs ${OUTPUT_JS_UI_FILE} -c -o ${OUTPUT_MIN_JS_UI_FILE}
4457

45-
echo "Pre-compile nunjucks templates in ${INTPUT_TEMPLATES_DIR}"
46-
nunjucks-precompile ${INTPUT_TEMPLATES_DIR} > ${OUTPUT_TEMPLATES_FILE}
47-
48-
echo "Minifying ${OUTPUT_TEMPLATES_FILE} to ${OUTPUT_MIN_TEMPLATES_FILE}"
49-
uglifyjs ${OUTPUT_TEMPLATES_FILE} -c -o ${OUTPUT_MIN_TEMPLATES_FILE}
50-
51-
echo "Copying css file to ${OUTPUT_CSS_FILE}"
52-
cp -f ${INPUT_CSS_FILE} ${OUTPUT_CSS_FILE}
53-
54-
echo "Minifying ${OUTPUT_CSS_FILE} to ${OUTPUT_MIN_CSS_FILE}"
55-
cleancss --advanced --compatibility=ie8 -o ${OUTPUT_MIN_CSS_FILE} ${OUTPUT_CSS_FILE}
56-
5758
echo "diff2html release created successfully!"

0 commit comments

Comments
 (0)