Permalink
Browse files

Split up markdown-js into multiple files, uses Grunt to produce brows…

…er distribution.
  • Loading branch information...
1 parent 95f7b8e commit 2b947247ff7ee2c39a99a2e2b07fcfd285c6722f @eviltrout eviltrout committed with ashb Sep 3, 2013
View
@@ -2,3 +2,5 @@
.DS_Store
/node_modules/
/npm-debug.log
+dist
+lib/markdown.js
View
@@ -0,0 +1,2 @@
+test
+src
View
@@ -19,7 +19,7 @@ module.exports = function(grunt) {
},
jshint: {
- files: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js'],
+ files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
options: {
"browser": false,
"maxerr": 100,
@@ -30,6 +30,7 @@ module.exports = function(grunt) {
"eqnull": true,
"forin": false,
"globals": {
+ "define": true,
"print": true,
"uneval": true,
"window": true
@@ -53,11 +54,40 @@ module.exports = function(grunt) {
"unused": false,
ignores: ['.git', 'node_modules']
}
+ },
+
+ build: {
+ web: {
+ dest: "dist/markdown.js",
+ minimum: ["parser"],
+ removeWith: ['dialects/gruber'],
+ startFile: "inc/header.js",
+ endFile: "inc/footer-web.js"
+ },
+ node: {
+ dest: "lib/markdown.js",
+ minimum: ["parser"],
+ removeWith: ['dialects/gruber'],
+ startFile: "inc/header.js",
+ endFile: "inc/footer-node.js"
+ }
+ },
+
+ uglify: {
+ my_target: {
+ files: {
+ 'dist/markdown.min.js': ['dist/markdown.js']
+ }
+ }
}
+
});
- grunt.registerTask('default', ['test']);
+ grunt.registerTask('all', ['test', 'build', 'uglify']);
+ grunt.registerTask('default', ['all']);
grunt.registerTask('test', 'Runs all tests and linting', ['node_tap', 'jshint']);
grunt.loadNpmTasks('grunt-node-tap');
+ grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.loadTasks("inc/tasks");
};
View
@@ -155,6 +155,29 @@ For example, you may want to grab a list of all URLs linked to in the
document before rendering it to HTML which you could do by recursing
through the HTML tree looking for `a` nodes.
+## Building and Testing markdown-js
+
+We use [Grunt](http://gruntjs.com/) to build and run markdown-js's tests.
+Make sure you run `npm install` to install the developer dependencies for
+the project, then you can:
+
+ $ grunt test
+
+To run our test suite. If you'd like to build markdown-js, you can run:
+
+ $ grunt all
+
+This command will run all the tests, then output a concatenated markdown.js
+and markdown.min.js in the `dist/` directory for use in a browser application.
+
+## Building a custom markdown-js
+
+By default, you will get the Gruber and Maruku dialects included when you run
+`grunt all`. However, you can create a custom build using the following syntax
+if you don't want to include Maruku support.
+
+ $ grunt "custom:-dialects/maruku"
+
## Running tests
To run the tests under node you will need tap installed (it's listed as a
View
@@ -0,0 +1,8 @@
+
+ expose.Markdown = Markdown;
+ expose.parse = Markdown.parse;
+ expose.toHTML = Markdown.toHTML;
+ expose.toHTMLTree = Markdown.toHTMLTree;
+ expose.renderJsonML = Markdown.renderJsonML;
+
+})(exports);
View
@@ -0,0 +1,11 @@
+
+ expose.Markdown = Markdown;
+ expose.parse = Markdown.parse;
+ expose.toHTML = Markdown.toHTML;
+ expose.toHTMLTree = Markdown.toHTMLTree;
+ expose.renderJsonML = Markdown.renderJsonML;
+
+})(function() {
+ window.markdown = {};
+ return window.markdown;
+}());
View
@@ -0,0 +1,7 @@
+// Released under MIT license
+// Copyright (c) 2009-2010 Dominic Baggott
+// Copyright (c) 2009-2010 Ash Berlin
+// Copyright (c) 2011 Christoph Dorn <christoph@christophdorn.com> (http://www.christophdorn.com)
+// Date: @DATE
+
+(function(expose) {
View
@@ -0,0 +1,224 @@
+/**
+ Tasks cribbed from jQuery to handle building custom markdown parsers.
+
+*/
+
+module.exports = function( grunt ) {
+
+ "use strict";
+
+ var fs = require( "fs" ),
+ srcFolder = __dirname + "/../../src/",
+ rdefineEnd = /\}\);[^}\w]*$/,
+ // This is temporary until the skipSemiColonInsertion option makes it to NPM
+ requirejs = require( "requirejs" ),
+ config = {
+ baseUrl: "src",
+ name: "markdown",
+ // We have multiple minify steps
+ optimize: "none",
+ skipSemiColonInsertion: true,
+ onBuildWrite: convert
+ };
+
+ /**
+ * Strip all definitions generated by requirejs
+ * Convert "var" modules to var declarations
+ * "var module" means the module only contains a return statement that should be converted to a var declaration
+ * This is indicated by including the file in any "var" folder
+ * @param {String} name
+ * @param {String} path
+ * @param {String} contents The contents to be written (including their AMD wrappers)
+ */
+ function convert( name, path, contents ) {
+ // Convert var modules
+ if ( /.\/var\//.test( path ) ) {
+ contents = contents
+ .replace( /define\([\w\W]*?return/, "var " + (/var\/([\w-]+)/.exec(name)[1]) + " =" )
+ .replace( rdefineEnd, "" );
+
+ } else {
+
+ contents = contents
+ .replace( /\s*return\s+[^\}]+(\}\);[^\w\}]*)$/, "$1" );
+
+ // Remove define wrappers, closure ends, and empty declarations
+ contents = contents
+ .replace( /define\([^{]*?{/, "" )
+ .replace( rdefineEnd, "" );
+
+ // Remove empty definitions
+ contents = contents
+ .replace( /define\(\[[^\]]+\]\)[\W\n]+$/, "" );
+ }
+ return contents;
+ }
+
+ grunt.registerMultiTask(
+ "build",
+ "Concatenate source, remove sub AMD definitions, (include/exclude modules with +/- flags), embed date/version",
+ function() {
+ var flag, index,
+ done = this.async(),
+ flags = this.flags,
+ name = this.data.dest,
+ minimum = this.data.minimum,
+ removeWith = this.data.removeWith,
+ excluded = [],
+ included = [],
+ version = grunt.config( "pkg.version" ),
+ /**
+ * Recursively calls the excluder to remove on all modules in the list
+ * @param {Array} list
+ * @param {String} [prepend] Prepend this to the module name. Indicates we're walking a directory
+ */
+ excludeList = function( list, prepend ) {
+ if ( list ) {
+ prepend = prepend ? prepend + "/" : "";
+ list.forEach(function( module ) {
+ // Exclude var modules as well
+ if ( module === "var" ) {
+ excludeList( fs.readdirSync( srcFolder + prepend + module ), prepend + module );
+ return;
+ }
+ if ( prepend ) {
+ // Skip if this is not a js file and we're walking files in a dir
+ if ( !(module = /([\w-\/]+)\.js$/.exec( module )) ) {
+ return;
+ }
+ // Prepend folder name if passed
+ // Remove .js extension
+ module = prepend + module[1];
+ }
+
+ // Avoid infinite recursion
+ if ( excluded.indexOf( module ) === -1 ) {
+ excluder( "-" + module );
+ }
+ });
+ }
+ },
+ /**
+ * Adds the specified module to the excluded or included list, depending on the flag
+ * @param {String} flag A module path relative to the src directory starting with + or - to indicate whether it should included or excluded
+ */
+ excluder = function( flag ) {
+ var m = /^(\+|\-|)([\w\/-]+)$/.exec( flag ),
+ exclude = m[ 1 ] === "-",
+ module = m[ 2 ];
+
+ if ( exclude ) {
+ // Can't exclude certain modules
+ if ( minimum.indexOf( module ) === -1 ) {
+ // Add to excluded
+ if ( excluded.indexOf( module ) === -1 ) {
+ grunt.log.writeln( flag );
+ excluded.push( module );
+ // Exclude all files in the folder of the same name
+ // These are the removable dependencies
+ // It's fine if the directory is not there
+ try {
+ excludeList( fs.readdirSync( srcFolder + module ), module );
+ } catch( e ) {
+ grunt.verbose.writeln( e );
+ }
+ }
+ // Check removeWith list
+ excludeList( removeWith[ module ] );
+ } else {
+ grunt.log.error( "Module \"" + module + "\" is a mimimum requirement.");
+ if ( module === "selector" ) {
+ grunt.log.error( "If you meant to replace Sizzle, use -sizzle instead." );
+ }
+ }
+ } else {
+ grunt.log.writeln( flag );
+ included.push( module );
+ }
+ };
+
+ // append commit id to version
+ if ( process.env.COMMIT ) {
+ version += " " + process.env.COMMIT;
+ }
+
+ // figure out which files to exclude based on these rules in this order:
+ // dependency explicit exclude
+ // > explicit exclude
+ // > explicit include
+ // > dependency implicit exclude
+ // > implicit exclude
+ // examples:
+ // * none (implicit exclude)
+ // *:* all (implicit include)
+ // *:*:-css all except css and dependents (explicit > implicit)
+ // *:*:-css:+effects same (excludes effects because explicit include is trumped by explicit exclude of dependency)
+ // *:+effects none except effects and its dependencies (explicit include trumps implicit exclude of dependency)
+ for ( flag in flags ) {
+ if ( flag !== "*" ) {
+ excluder( flag );
+ }
+ }
+ grunt.verbose.writeflags( excluded, "Excluded" );
+ grunt.verbose.writeflags( included, "Included" );
+
+ // append excluded modules to version
+ if ( excluded.length ) {
+ version += " -" + excluded.join( ",-" );
+ // set pkg.version to version with excludes, so minified file picks it up
+ grunt.config.set( "pkg.version", version );
+ grunt.verbose.writeln( "Version changed to " + version );
+ // Have to use shallow or core will get excluded since it is a dependency
+ config.excludeShallow = excluded;
+ }
+ config.include = included;
+
+ config.wrap = {
+ startFile: this.data.startFile,
+ endFile: this.data.endFile
+ };
+
+
+ /**
+ * Handle Final output from the optimizer
+ * @param {String} compiled
+ */
+ config.out = function( compiled ) {
+ compiled = compiled
+ // Embed Version
+ .replace( /@VERSION/g, version )
+ // Embed Date
+ // yyyy-mm-ddThh:mmZ
+ .replace( /@DATE/g, ( new Date() ).toISOString().replace( /:\d+\.\d+Z$/, "Z" ) );
+
+ // Write concatenated source to file
+ grunt.file.write( name, compiled );
+ };
+
+ // Trace dependencies and concatenate files
+ requirejs.optimize( config, function( response ) {
+ grunt.verbose.writeln( response );
+ grunt.log.ok( "File '" + name + "' created." );
+ done();
+ }, function( err ) {
+ done( err );
+ });
+ });
+
+ // Special "alias" task to make custom build creation less grawlix-y
+ // Translation example
+ //
+ // grunt custom:+ajax,-dimensions,-effects,-offset
+ //
+ // Becomes:
+ //
+ // grunt build:*:*:+ajax:-dimensions:-effects:-offset
+ grunt.registerTask( "custom", function() {
+ var args = [].slice.call( arguments ),
+ modules = args.length ? args[ 0 ].replace( /,/g, ":" ) : "";
+
+ grunt.log.writeln( "Creating custom build...\n" );
+
+ grunt.task.run([ "build:*:*:" + modules, 'uglify']);
+ });
+};
Oops, something went wrong.

0 comments on commit 2b94724

Please sign in to comment.