diff --git a/bundler/lintdocs.js b/bundler/lintdocs.js new file mode 100644 index 00000000..f0e8013a --- /dev/null +++ b/bundler/lintdocs.js @@ -0,0 +1,109 @@ +#!/usr/bin/env node + +var fs = require("fs") +var path = require("path") + +//lint rules +function lint(file, data) { + ensureCodeIsHighlightable(file, data) + ensureCodeIsSyntaticallyValid(file, data) + ensureCodeIsRunnable(file, data) + ensureCommentStyle(file, data) +} + +function ensureCodeIsHighlightable(file, data) { + var codeBlocks = data.match(/```(.|\n|\r)*?```/gim) || [] + codeBlocks.forEach(function(block) { + block = block.slice(3, -3) + if (block.indexOf("javascript") !== 0) { + try {if (new Function(block)) console.log(file + " - javascript block missing language tag after triple backtick\n\n" + block + "\n\n---\n\n")} + catch (e) {} + } + }) +} + +function ensureCodeIsSyntaticallyValid(file, data) { + var codeBlocks = data.match(/```javascript(.|\n|\r)*?```/gim) || [] + codeBlocks.forEach(function(block) { + block = block.slice(13, -3) + try {new Function(block)} + catch (e) {console.log(file + " -: javascript block has wrong syntax\n\n" + e.message + "\n\n" + block + "\n\n---\n\n")} + }) +} + +function ensureCodeIsRunnable(file, data) { + var codeBlocks = data.match(/```javascript(.|\n|\r)*?```/gim) || [] + var code = codeBlocks.map(function(block) {return block.slice(13, -3)}).join(";") + + //stubs + var silentConsole = {log: function() {}} + var fetch = function() { + return Promise.resolve({ + json: function() {} + }) + } + + try { + new Function("console,fetch", code).call(this, silentConsole, fetch) + } + catch (e) {console.log(file + " -: javascript code cannot run\n\n" + e.stack + "\n\n" + code + "\n\n---\n\n")} + +} + +function ensureCommentStyle(file, data) { + var codeBlocks = data.match(/```javascript(.|\n|\r)*?```/gim) || [] + codeBlocks.forEach(function(block) { + block = block.slice(13, -3) + if (block.match(/(^|\s)\/\/[\S]/)) console.log(file + " -: comment missing space\n\n" + block + "\n\n---\n\n") + }) +} + +//runner +function traverseDirectory(pathname, callback) { + pathname = pathname.replace(/\\/g, "/") + return new Promise(function(resolve, reject) { + fs.lstat(pathname, function(err, stat) { + if (err) reject(err) + if (stat.isDirectory()) { + fs.readdir(pathname, function(err, pathnames) { + if (err) reject(err) + var promises = [] + for (var i = 0; i < pathnames.length; i++) { + pathnames[i] = path.join(pathname, pathnames[i]) + promises.push(traverseDirectory(pathnames[i], callback)) + } + callback(pathname, stat, pathnames) + resolve(Promise.all(promises)) + }) + } + else { + callback(pathname, stat) + resolve(pathname) + } + }) + }) +} + +//init mocks +var domMock = require("../../test-utils/domMock")() +var xhrMock = require("../../test-utils/xhrMock")() +var pushStateMock = require("../../test-utils/pushStateMock")() + +global.window = {} +for (var key in domMock) if (!window[key]) window[key] = domMock[key] +for (var key in xhrMock) if (!window[key]) window[key] = xhrMock[key] +for (var key in pushStateMock) if (!window[key]) window[key] = pushStateMock[key] + +global.document = window.document +global.m = require("../../index") + +//run +traverseDirectory("./docs", function(pathname, stat, children) { + if (pathname.indexOf(".md") > -1 && pathname.indexOf("migration") < 0) { + fs.readFile(pathname, "utf8", function(err, data) { + if (err) console.log(err) + else lint(pathname, data) + }) + } +}) + diff --git a/bundler/minify.js b/bundler/minify.js new file mode 100644 index 00000000..fc178ce6 --- /dev/null +++ b/bundler/minify.js @@ -0,0 +1,49 @@ +var http = require("http") +var querystring = require("querystring") +var fs = require("fs") + +var code = fs.readFileSync("./mithril.js", "utf8") + +var data = { + output_format: "json", + output_info: ["compiled_code", "warnings", "errors", "statistics"], + compilation_level: "SIMPLE_OPTIMIZATIONS",//ADVANDED_OPTIMIZATIONS + warning_level: "default", + output_file_name: "default.js", + js_code: code, +} + +var body = querystring.stringify(data) + +var req = http.request({ + method: "POST", + protocol: "http:", + hostname: "closure-compiler.appspot.com", + path: "/compile", + headers: { + "Content-Type": "application/x-www-form-urlencoded;charset=utf-8", + "Content-Length": body.length + } +}, function(res) { + res.on("data", function(chunk) { + response += chunk.toString() + }) + res.on("end", function() { + var results = JSON.parse(response) + var stats = results.statistics + console.log("Original size: " + format(stats.originalGzipSize) + " bytes gzipped (" + format(stats.originalSize) + " bytes uncompressed)") + console.log("Compiled size: " + format(stats.compressedGzipSize) + " bytes gzipped (" + format(stats.compressedSize) + " bytes uncompressed)") + + fs.writeFileSync("mithril.min.js", results.compiledCode, "utf8") + }) +}) + +var response = "" + +req.write(body) +req.end() +console.log("compiling...") + +function format(n) { + return n.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,") +} \ No newline at end of file diff --git a/package.json b/package.json index 33fae8a4..8ee589d1 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "main": "index.js", "scripts": { "build": "node bundler/bundler", - "minify": "uglifyjs mithril.js -m -c -o mithril.min.js", - "size": "uglifyjs mithril.js -m -c | gzipped", + "minify": "node bundler/minify", + "lintdocs": "node bundler/lintdocs", "lint": "eslint .", "test": "node ospec/bin/ospec", "cover": "istanbul cover --print both ospec/bin/ospec" @@ -19,5 +19,8 @@ }, "publishConfig": { "tag": "beta" + }, + "bin": { + "ospec": "./ospec/bin/ospec" } }