diff --git a/Jakefile.js b/Jakefile.js index db873d44f..4af806db4 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -1,67 +1,26 @@ -var build = require('./build/build.js'), - lint = require('./build/hint.js'); +/* +Leaflet.markercluster building, testing and linting scripts. -var COPYRIGHT = '/*\n Copyright (c) 2012, Smartrak, David Leaver\n' + - ' Leaflet.markercluster is an open-source JavaScript library for Marker Clustering on leaflet powered maps.\n' + - ' https://github.com/danzel/Leaflet.markercluster\n*/\n'; +To use, install Node, then run the following commands in the project root: + + npm install -g jake + npm install + +To check the code for errors and build Leaflet from source, run "jake". +To run the tests, run "jake test". + +For a custom build, open build/build.html in the browser and follow the instructions. +*/ + +var build = require('./build/build.js'); desc('Check Leaflet.markercluster source for errors with JSHint'); -task('lint', function () { - - var files = build.getFiles(); - - console.log('Checking for JS errors...'); - - var errorsFound = lint.jshint(files); - - if (errorsFound > 0) { - console.log(errorsFound + ' error(s) found.\n'); - fail(); - } else { - console.log('\tCheck passed'); - } -}); +task('lint', build.lint); desc('Combine and compress Leaflet.markercluster source files'); -task('build', ['lint'], function (compsBase32, buildName) { +task('build', ['lint'], build.build); - var files = build.getFiles(compsBase32); +desc('Run PhantomJS tests'); +task('test', ['lint'], build.test); - console.log('Concatenating ' + files.length + ' files...'); - - var content = build.combineFiles(files), - newSrc = COPYRIGHT + content, - - pathPart = 'dist/leaflet.markercluster' + (buildName ? '-' + buildName : ''), - srcPath = pathPart + '-src.js', - - oldSrc = build.load(srcPath), - srcDelta = build.getSizeDelta(newSrc, oldSrc); - - console.log('\tUncompressed size: ' + newSrc.length + ' bytes (' + srcDelta + ')'); - - if (newSrc === oldSrc) { - console.log('\tNo changes'); - } else { - build.save(srcPath, newSrc); - console.log('\tSaved to ' + srcPath); - } - - console.log('Compressing...'); - - var path = pathPart + '.js', - oldCompressed = build.load(path), - newCompressed = COPYRIGHT + build.uglify(content), - delta = build.getSizeDelta(newCompressed, oldCompressed); - - console.log('\tCompressed size: ' + newCompressed.length + ' bytes (' + delta + ')'); - - if (newCompressed === oldCompressed) { - console.log('\tNo changes'); - } else { - build.save(path, newCompressed); - console.log('\tSaved to ' + path); - } -}); - -task('default', ['build']); +task('default', ['build']); \ No newline at end of file diff --git a/build/build.html b/build/build.html deleted file mode 100644 index bf94db3fd..000000000 --- a/build/build.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - Leaflet.markercluster Build Helper - - - - - - -
-

Leaflet.markercluster Build Helper

- -

- Select All | - Deselect All -

- - - -

Building using Node and UglifyJS

-
    -
  1. Download and install Node
  2. -
  3. Run this in the command line:
    -
    npm install -g jake
    -npm install jshint
    -npm install uglify-js
  4. -
  5. Run this command inside the Leaflet.markercluster directory:
    -
-

Building using Closure Compiler

-
    -
  1. Download Closure Compiler, extract it into closure-compiler directory
  2. -
  3. Run this command in the root Leaflet directory:
  4. -
-
- - - - diff --git a/build/build.js b/build/build.js index b41c7e114..5fd41a751 100644 --- a/build/build.js +++ b/build/build.js @@ -1,13 +1,34 @@ var fs = require('fs'), - uglifyjs = require('uglify-js'), - deps = require('./deps.js').deps; + jshint = require('jshint'), + UglifyJS = require('uglify-js'), -exports.getFiles = function (compsBase32) { + deps = require('./deps.js').deps, + hintrc = require('./hintrc.js').config; + +function lintFiles(files) { + + var errorsFound = 0, + i, j, len, len2, src, errors, e; + + for (i = 0, len = files.length; i < len; i++) { + + jshint.JSHINT(fs.readFileSync(files[i], 'utf8'), hintrc, i ? {L: true} : null); + errors = jshint.JSHINT.errors; + + for (j = 0, len2 = errors.length; j < len2; j++) { + e = errors[j]; + console.log(files[i] + '\tline ' + e.line + '\tcol ' + e.character + '\t ' + e.reason); + } + + errorsFound += len2; + } + + return errorsFound; +} + +function getFiles(compsBase32) { var memo = {}, - comps, - i, - files = [], - src; + comps; if (compsBase32) { comps = parseInt(compsBase32, 32).toString(2).split(''); @@ -15,82 +36,158 @@ exports.getFiles = function (compsBase32) { } function addFiles(srcs) { - var j, - len; - for (j = 0, len = srcs.length; j < len; j += 1) { + for (var j = 0, len = srcs.length; j < len; j++) { memo[srcs[j]] = true; } } - for (i in deps) { - if (deps.hasOwnProperty(i)) { - if (comps) { - if (parseInt(comps.pop(), 2) === 1) { - console.log('\t* ' + i); - addFiles(deps[i].src); - } else { - console.log('\t ' + i); - } - } else { + for (var i in deps) { + if (comps) { + if (parseInt(comps.pop(), 2) === 1) { + console.log('\t* ' + i); addFiles(deps[i].src); + } else { + console.log('\t ' + i); } + } else { + addFiles(deps[i].src); } } - for (src in memo) { - if (memo.hasOwnProperty(src)) { - files.push('src/' + src); - } + var files = []; + + for (var src in memo) { + files.push('src/' + src); } return files; -}; +} -exports.uglify = function (code) { - var ast, - compressor; - ast = uglifyjs.parse(code); +exports.getFiles = getFiles; - // compressor needs figure_out_scope too - ast.figure_out_scope(); - compressor = uglifyjs.Compressor(); - ast = ast.transform(compressor); +exports.lint = function () { - // need to figure out scope again so mangler works optimally - ast.figure_out_scope(); - ast.compute_char_frequency(); - ast.mangle_names(); + var files = getFiles(); - // get Ugly code back :) - return ast.print_to_string(); -}; + console.log('Checking for JS errors...'); -exports.combineFiles = function (files) { - var content = '(function () {\n\n', - i, - len; - for (i = 0, len = files.length; i < len; i += 1) { - content += fs.readFileSync(files[i], 'utf8') + '\n\n'; - } - return content + '\n\n}(this));'; -}; + var errorsFound = lintFiles(files); -exports.save = function (savePath, compressed) { - return fs.writeFileSync(savePath, compressed, 'utf8'); -}; - -exports.load = function (loadPath) { - try { - return fs.readFileSync(loadPath, 'utf8'); - } catch (e) { - return null; + if (errorsFound > 0) { + console.log(errorsFound + ' error(s) found.\n'); + fail(); + } else { + console.log('\tCheck passed'); } }; -exports.getSizeDelta = function (newContent, oldContent) { + +function getSizeDelta(newContent, oldContent) { if (!oldContent) { return 'new'; } - var delta = newContent.length - oldContent.length; + var newLen = newContent.replace(/\r\n?/g, '\n').length, + oldLen = oldContent.replace(/\r\n?/g, '\n').length, + delta = newLen - oldLen; + return (delta >= 0 ? '+' : '') + delta; +} + +function loadSilently(path) { + try { + return fs.readFileSync(path, 'utf8'); + } catch (e) { + return null; + } +} + +function combineFiles(files) { + var content = ''; + for (var i = 0, len = files.length; i < len; i++) { + content += fs.readFileSync(files[i], 'utf8') + '\n\n'; + } + return content; +} + +exports.build = function (compsBase32, buildName) { + + var files = getFiles(compsBase32); + + console.log('Concatenating ' + files.length + ' files...'); + + var copy = fs.readFileSync('src/copyright.js', 'utf8'), + intro = '(function (window, document, undefined) {', + outro = '}(window, document));', + newSrc = copy + intro + combineFiles(files) + outro, + + pathPart = 'dist/leaflet.markercluster' + (buildName ? '-' + buildName : ''), + srcPath = pathPart + '-src.js', + + oldSrc = loadSilently(srcPath), + srcDelta = getSizeDelta(newSrc, oldSrc); + + console.log('\tUncompressed size: ' + newSrc.length + ' bytes (' + srcDelta + ')'); + + if (newSrc === oldSrc) { + console.log('\tNo changes'); + } else { + fs.writeFileSync(srcPath, newSrc); + console.log('\tSaved to ' + srcPath); + } + + console.log('Compressing...'); + + var path = pathPart + '.js', + oldCompressed = loadSilently(path), + newCompressed = copy + UglifyJS.minify(newSrc, { + warnings: true, + fromString: true + }).code, + delta = getSizeDelta(newCompressed, oldCompressed); + + console.log('\tCompressed size: ' + newCompressed.length + ' bytes (' + delta + ')'); + + if (newCompressed === oldCompressed) { + console.log('\tNo changes'); + } else { + fs.writeFileSync(path, newCompressed); + console.log('\tSaved to ' + path); + } +}; + +exports.test = function() { + var karma = require('karma'), + testConfig = {configFile : __dirname + '/../spec/karma.conf.js'}; + + testConfig.browsers = ['PhantomJS']; + + if (isArgv('--chrome')) { + testConfig.browsers.push('Chrome'); + } + if (isArgv('--safari')) { + testConfig.browsers.push('Safari'); + } + if (isArgv('--ff')) { + testConfig.browsers.push('Firefox'); + } + if (isArgv('--ie')) { + testConfig.browsers.push('IE'); + } + + if (isArgv('--cov')) { + testConfig.preprocessors = { + '../src/**/*.js': 'coverage' + }; + testConfig.coverageReporter = { + type : 'html', + dir : 'coverage/' + }; + testConfig.reporters = ['coverage']; + } + + karma.server.start(testConfig); + + function isArgv(optName) { + return process.argv.indexOf(optName) !== -1; + } }; diff --git a/build/hint.js b/build/hint.js deleted file mode 100644 index 464bbe115..000000000 --- a/build/hint.js +++ /dev/null @@ -1,30 +0,0 @@ -var jshint = require('jshint').JSHINT, - fs = require('fs'), - config = require('./hintrc.js').config; - -function jshintSrc(path, src) { - jshint(src, config); - - var errors = jshint.errors, - i, len, e, line; - - for (i = 0, len = errors.length; i < len; i++) { - e = errors[i]; - //console.log(e.evidence); - console.log(path + '\tline ' + e.line + '\tcol ' + e.character + '\t ' + e.reason); - } - - return len; -} - -exports.jshint = function (files) { - var errorsFound = 0; - - for (var i = 0, len = files.length; i < len; i++) { - var src = fs.readFileSync(files[i], 'utf8'); - - errorsFound += jshintSrc(files[i], src); - } - - return errorsFound; -}; \ No newline at end of file diff --git a/build/hintrc.js b/build/hintrc.js index ce23a0b85..55bfb3695 100644 --- a/build/hintrc.js +++ b/build/hintrc.js @@ -1,47 +1,37 @@ exports.config = { + + // environment "browser": true, "node": true, - "predef": ["L"], - - "debug": false, - "devel": false, - - "es5": false, + "predef": ['L', 'define'], "strict": false, - "globalstrict": false, - "asi": false, - "laxbreak": false, + // code style "bitwise": true, - "boss": false, + "camelcase": true, "curly": true, - "eqnull": false, - "evil": false, - "expr": false, + "eqeqeq": true, "forin": false, "immed": true, "latedef": true, - "loopfunc": false, - "noarg": true, - "regexp": true, - "regexdash": false, - "scripturl": false, - "shadow": false, - "supernew": false, - "undef": true, - "funcscope": false, - "newcap": true, + "noarg": true, "noempty": true, "nonew": true, - "nomen": false, - "onevar": false, - "plusplus": false, - "sub": false, - "indent": 4, + "undef": true, + "unused": true, + //"quotmark": "single", - "eqeqeq": true, + // whitespace + "indent": 4, "trailing": true, "white": true, - "smarttabs": true + "smarttabs": true, + //"maxlen": 120 + + // code simplicity - not enforced but nice to check from time to time + // "maxstatements": 20, + // "maxcomplexity": 5 + // "maxparams": 4, + // "maxdepth": 4 }; diff --git a/package.json b/package.json new file mode 100644 index 000000000..3b9684126 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "Leaflet.markercluster", + "version": "0.3.0", + "description": "Provides Beautiful Animated Marker Clustering functionality for Leaflet", + "dependencies": { + "leaflet": "git://github.com/Leaflet/Leaflet.git#016f635616fa1df18744baa036cc0e67f94f6248" + }, + "devDependencies": { + "jshint": "~2.1.3", + "mocha": "~1.10.0", + "karma": "~0.8.5", + "uglify-js": "~2.3.6", + "jake": "~0.5.16" + }, + "main": "dist/leaflet.markercluster.js", + "scripts": { + "test": "jake test", + "prepublish": "jake" + }, + "repository": { + "type": "git", + "url": "git://github.com/Leaflet/Leaflet.markercluster.git" + }, + "keywords": ["gis", "map"] +} \ No newline at end of file diff --git a/src/copyright.js b/src/copyright.js new file mode 100644 index 000000000..2fdcec950 --- /dev/null +++ b/src/copyright.js @@ -0,0 +1,5 @@ +/* + Leaflet.markercluster, Provides Beautiful Animated Marker Clustering functionality for Leaflet, a JS library for interactive maps. + https://github.com/Leaflet/Leaflet.markercluster + (c) 2012-2013, Dave Leaver, smartrak +*/