diff --git a/CHANGELOG b/CHANGELOG index b17d38d63..9d61789b3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,12 @@ THIS CHANGELOG IS AN ATTEMPT TO DOCUMENT CHANGES TO THIS PROJECT. +PL-node-v0.1.3 + - ADD: Pattern states + - ADD: Ships with grunt connect if you are into that kinda thing + - FIX: Removed all grunt dependencies from patternlab.js + - FIX: Ignore dotfiles + - THX: thanks @bramsmulders for suggestion and help with mac + PL-node-v0.1.2 - ADD: Abstracted template rendering into a function for easier swapping of rendering engine - ADD: Smarter filtering of files to support other templates Thanks diff --git a/Gruntfile.js b/Gruntfile.js index 4b1bfbce5..0a9791dd4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -24,12 +24,12 @@ module.exports = function(grunt) { copy: { main: { files: [ - { expand: true, cwd: './source/js/', src: '*', dest: './public/js/'}, - { expand: true, cwd: './source/css/', src: 'style.css', dest: './public/css/' }, - { expand: true, cwd: './source/images/', src: ['*.png', '*.jpg', '*.gif', '*.jpeg'], dest: './public/images/' }, - { expand: true, cwd: './source/images/sample/', src: ['*.png', '*.jpg', '*.gif', '*.jpeg'], dest: './public/images/sample/'}, - { expand: true, cwd: './source/fonts/', src: '*', dest: './public/fonts/'}, - { expand: true, cwd: './source/_data/', src: 'annotations.js', dest: './public/data/' } + { expand: true, cwd: './source/js/', src: '*', dest: './public/js/'}, + { expand: true, cwd: './source/css/', src: 'style.css', dest: './public/css/' }, + { expand: true, cwd: './source/images/', src: ['*.png', '*.jpg', '*.gif', '*.jpeg'], dest: './public/images/' }, + { expand: true, cwd: './source/images/sample/', src: ['*.png', '*.jpg', '*.gif', '*.jpeg'], dest: './public/images/sample/'}, + { expand: true, cwd: './source/fonts/', src: '*', dest: './public/fonts/'}, + { expand: true, cwd: './source/_data/', src: 'annotations.js', dest: './public/data/' } ] } }, @@ -50,12 +50,12 @@ module.exports = function(grunt) { // files: ['source/css/**/*.scss', 'public/styleguide/css/*.scss'], // tasks: ['default'] // }, - mustache: { - files: ['source/_patterns/**/*.mustache'], - tasks: ['default'] - }, - data: { - files: ['source/_patterns/**/*.json', 'source/_data/*.json'], + all: { + files: [ + 'source/_patterns/**/*.mustache', + 'source/_patterns/**/*.json', + 'source/_data/*.json' + ], tasks: ['default'] } }, @@ -74,6 +74,16 @@ module.exports = function(grunt) { }, nodeunit: { all: ['test/*_tests.js'] + }, + connect: { + app:{ + options: { + port: 9001, + base: './public', + hostname: 'localhost', + keepalive: true + } + } } }); @@ -88,4 +98,10 @@ module.exports = function(grunt) { //travis CI task grunt.registerTask('travis', ['clean', 'concat', 'patternlab', /*'sass',*/ 'copy', 'nodeunit']); + + grunt.registerTask('serve', ['clean', 'concat', 'patternlab', /*'sass',*/ 'copy', 'connect:app']); + //need to get livereload working + //http://www.thecrumb.com/2014/03/16/using-grunt-for-live-reload-revisited/ + //http://rhumaric.com/2013/07/renewing-the-grunt-livereload-magic/ + }; \ No newline at end of file diff --git a/README.md b/README.md index 06df49d26..a738715e7 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,22 @@ The current selection is as follows. It reflects support versus patternlab-php. ##### Verbose Mode `patternlab.json` is a file created for debugging purposes. Set `debug` to true in `.config.json` to see all the secrets. +##### Pattern States +You can set the state of a pattern by including it in `config.json` too. The out of the box styles are in progress (orange), in review (yellow), and complete (green). +Pattern states should be lowercase and use hyphens where spaces are present. +``` +"patternStates": { + "colors" : "inprogress", + "fonts" : "inreview", + "three-up" : "complete" +} +``` + +##### Server +Running `grunt serve` will compile the patternlab front end and host it on http://localhost:9001 by default. This can be changed in the `Gruntfile.js` + +**Next steps: Livereload and watches** + ### Under Active Development [![Build Status](https://travis-ci.org/pattern-lab/patternlab-node.png?branch=master)](https://travis-ci.org/pattern-lab/patternlab-node) The Node version of Pattern Lab is under active development by [@bmuenzenmeyer](https://twitter.com/bmuenzenmeyer) and contributors. Pull requests welcome, but please take a moment to read the [guidelines](https://github.com/pattern-lab/patternlab-node/blob/master/CONTRIBUTING.md). diff --git a/builder/object_factory.js b/builder/object_factory.js index 1f90367e1..8788e73ba 100644 --- a/builder/object_factory.js +++ b/builder/object_factory.js @@ -1,5 +1,5 @@ /* - * patternlab-node - v0.1.2 - 2014 + * patternlab-node - v0.1.3 - 2014 * * Brian Muenzenmeyer, and the web community. * Licensed under the MIT license. diff --git a/builder/patternlab-grunt.js b/builder/patternlab-grunt.js new file mode 100644 index 000000000..bd014dd03 --- /dev/null +++ b/builder/patternlab-grunt.js @@ -0,0 +1,30 @@ +var patternlab_engine = require('./patternlab.js'); + +module.exports = function(grunt) { + grunt.registerTask('patternlab', 'create design systems with atomic design', function(arg) { + + var patternlab = patternlab_engine(); + + if(arguments.length === 0){ + patternlab.build(); + } + + if(arg && arg === 'v'){ + patternlab.version(); + } + + if(arg && arg === "only_patterns"){ + patternlab.build_patterns_only(); + } + + if(arg && arg === "help"){ + patternlab.help(); + } + + if(arg && (arg !== "v" && arg !=="only_patterns" && arg !=="help")){ + patternlab.help(); + } + + }); + +}; \ No newline at end of file diff --git a/builder/patternlab.js b/builder/patternlab.js index 7c90afbd2..37d75805b 100644 --- a/builder/patternlab.js +++ b/builder/patternlab.js @@ -1,5 +1,5 @@ /* - * patternlab-node - v0.1.2 - 2014 + * patternlab-node - v0.1.3 - 2014 * * Brian Muenzenmeyer, and the web community. * Licensed under the MIT license. @@ -8,82 +8,101 @@ * */ -var patternlab_engine = function(grunt){ +var patternlab_engine = function(){ var path = require('path'), + fs = require('fs-extra'), + diveSync = require('diveSync'), mustache = require('mustache'), of = require('./object_factory'), pa = require('./pattern_assembler'), patternlab = {}; - patternlab.package = grunt.file.readJSON('package.json'); - patternlab.config = grunt.file.readJSON('config.json'); + patternlab.package =fs.readJSONSync('./package.json'); + patternlab.config = fs.readJSONSync('./config.json'); function getVersion() { - grunt.log.ok(patternlab.package.version); + console.log(patternlab.package.version); } function help(){ - grunt.log.subhead('Patternlab Node Help'); - grunt.log.writeln('==============================='); - grunt.log.writeln('Command Line Arguments'); - grunt.log.writeln('patternlab:only_patterns'); - grunt.log.writeln(' > Compiles the patterns only, outputting to ./public/patterns'); - grunt.log.writeln('patternlab:v'); - grunt.log.writeln(' > Retrieve the version of patternlab-node you have installed'); - grunt.log.writeln('patternlab:help'); - grunt.log.writeln(' > Get more information about patternlab-node, pattern lab in general, and where to report issues.'); - grunt.log.writeln('==============================='); - grunt.log.writeln('Visit http://patternlab.io/docs/index.html for general help on pattern-lab'); - grunt.log.writeln('Visit https://github.com/pattern-lab/patternlab-node/issues to open a bug.'); + console.log('Patternlab Node Help'); + console.log('==============================='); + console.log('Command Line Arguments'); + console.log('patternlab:only_patterns'); + console.log(' > Compiles the patterns only, outputting to ./public/patterns'); + console.log('patternlab:v'); + console.log(' > Retrieve the version of patternlab-node you have installed'); + console.log('patternlab:help'); + console.log(' > Get more information about patternlab-node, pattern lab in general, and where to report issues.'); + console.log('==============================='); + console.log('Visit http://patternlab.io/docs/index.html for general help on pattern-lab'); + console.log('Visit https://github.com/pattern-lab/patternlab-node/issues to open a bug.'); } function printDebug() { //debug file can be written by setting flag on config.json if(patternlab.config.debug){ - var outputFilename = './patternlab.json'; - grunt.file.write(outputFilename, JSON.stringify(patternlab, null, 3)); + console.log('writing patternlab debug file to ./patternlab.json'); + fs.outputFileSync('./patternlab.json', JSON.stringify(patternlab, null, 3)); } } - function buildPatterns(){ - patternlab.data = grunt.file.readJSON('./source/_data/data.json'); - patternlab.listitems = grunt.file.readJSON('./source/_data/listitems.json'); - patternlab.header = grunt.file.read('./source/_patternlab-files/pattern-header-footer/header.html'); - patternlab.footer = grunt.file.read('./source/_patternlab-files/pattern-header-footer/footer.html'); + function buildPatterns(callback){ + patternlab.data = fs.readJSONSync('./source/_data/data.json'); + patternlab.listitems = fs.readJSONSync('./source/_data/listitems.json'); + patternlab.header = fs.readFileSync('./source/_patternlab-files/pattern-header-footer/header.html', 'utf8'); + patternlab.footer = fs.readFileSync('./source/_patternlab-files/pattern-header-footer/footer.html', 'utf8'); patternlab.patterns = []; patternlab.patternIndex = []; patternlab.partials = {}; - grunt.file.recurse('./source/_patterns', function(abspath, rootdir, subdir, filename){ + diveSync('./source/_patterns', function(err, file){ + + //log any errors + if(err){ + console.log(err); + return; + } + + //extract some information + var abspath = file.substring(2); + var subdir = path.dirname(path.relative('./source/_patterns', file)); + var filename = path.basename(file); + //check if the pattern already exists. - var patternName = filename.substring(0, filename.indexOf('.')); - var patternIndex = patternlab.patternIndex.indexOf(subdir + '-' + patternName); - var currentPattern; - var flatPatternPath; + var patternName = filename.substring(0, filename.indexOf('.')), + patternIndex = patternlab.patternIndex.indexOf(subdir + '-' + patternName), + currentPattern, + flatPatternPath; - //ignore _underscored patterns and json - if(filename.charAt(0) === '_' || grunt.util._.str.include(filename, 'json')){ + //ignore _underscored patterns, json, and dotfiles + if(filename.charAt(0) === '_' || path.extname(filename) === '.json' || filename.charAt(0) === '.'){ return; } - //make a new Pattern Object - var flatPatternName = subdir.replace(/\//g, '-') + '-' + patternName; - flatPatternName = flatPatternName.replace(/\//g, '-'); + var flatPatternName = subdir.replace(/\\/g, '-') + '-' + patternName; + + flatPatternName = flatPatternName.replace(/\\/g, '-'); currentPattern = new of.oPattern(flatPatternName, subdir, filename, {}); currentPattern.patternName = patternName.substring(patternName.indexOf('-') + 1); currentPattern.data = null; + //see if this file has a state + if(patternlab.config.patternStates[currentPattern.patternName]){ + currentPattern.patternState = patternlab.config.patternStates[currentPattern.patternName]; + } + //look for a json file for this template try { var jsonFilename = abspath.substr(0, abspath.lastIndexOf(".")) + ".json"; - currentPattern.data = grunt.file.readJSON(jsonFilename); + currentPattern.data = fs.readJSONSync(jsonFilename); } catch(e) { } - currentPattern.template = grunt.file.read(abspath); + currentPattern.template = fs.readFileSync(abspath, 'utf8'); //render the pattern. pass partials object just in case. if(currentPattern.data) { // Pass JSON as data @@ -98,7 +117,7 @@ var patternlab_engine = function(grunt){ //add footer info before writing var currentPatternFooter = renderPattern(patternlab.footer, currentPattern); - grunt.file.write('./public/patterns/' + flatPatternPath, patternlab.header + currentPattern.patternPartial + currentPatternFooter); + fs.outputFileSync('./public/patterns/' + flatPatternPath, patternlab.header + currentPattern.patternPartial + currentPatternFooter); currentPattern.patternLink = flatPatternPath; //add as a partial in case this is referenced later. convert to syntax needed by existing patterns @@ -119,7 +138,6 @@ var patternlab_engine = function(grunt){ //add to patternlab arrays so we can look these up later. this could probably just be an object. patternlab.patternIndex.push(currentPattern.name); patternlab.patterns.push(currentPattern); - }); } @@ -131,17 +149,17 @@ var patternlab_engine = function(grunt){ patternlab.viewAllPaths = {}; //build the styleguide - var styleguideTemplate = grunt.file.read('./source/_patternlab-files/styleguide.mustache'); + var styleguideTemplate = fs.readFileSync('./source/_patternlab-files/styleguide.mustache', 'utf8'); var styleguideHtml = renderPattern(styleguideTemplate, {partials: patternlab.patterns}); - grunt.file.write('./public/styleguide/html/styleguide.html', styleguideHtml); + fs.outputFileSync('./public/styleguide/html/styleguide.html', styleguideHtml); //build the patternlab website - var patternlabSiteTemplate = grunt.file.read('./source/_patternlab-files/index.mustache'); + var patternlabSiteTemplate = fs.readFileSync('./source/_patternlab-files/index.mustache', 'utf8'); //loop through all patterns. deciding to do this separate from the recursion, even at a performance hit, to attempt to separate the tasks of styleguide creation versus site menu creation for(var i = 0; i < patternlab.patterns.length; i++){ var pattern = patternlab.patterns[i]; - var bucketName = pattern.name.replace(/\//g, '-').split('-')[1]; + var bucketName = pattern.name.replace(/\\/g, '-').split('-')[1]; //check if the bucket already exists var bucketIndex = patternlab.bucketIndex.indexOf(bucketName); @@ -158,8 +176,6 @@ var patternlab_engine = function(grunt){ //get the navSubItem var navSubItemName = pattern.patternName.replace(/-/g, ' '); - //grunt.log.writeln('new bucket found: ' + bucketName + " " + navItemName + " " + navSubItemName); - //test whether the pattern struture is flat or not - usually due to a template or page var flatPatternItem = false; if(navItemName === bucketName){ @@ -174,13 +190,18 @@ var patternlab_engine = function(grunt){ navSubItem.patternPath = pattern.patternLink; navSubItem.patternPartial = bucketName + "-" + pattern.patternName; //add the hyphenated name + //add the patternState if it exists + if(pattern.patternState){ + navSubItem.patternState = pattern.patternState; + } + //if it is flat - we should not add the pattern to patternPaths if(flatPatternItem){ bucket.patternItems.push(navSubItem); //add to patternPaths - patternlab.patternPaths[bucketName][pattern.patternName] = pattern.subdir + "/" + pattern.filename.substring(0, pattern.filename.indexOf('.')); + addToPatternPaths(bucketName, pattern); } else{ @@ -190,7 +211,7 @@ var patternlab_engine = function(grunt){ navItem.navSubItemsIndex.push(navSubItemName); //add to patternPaths - patternlab.patternPaths[bucketName][pattern.patternName] = pattern.subdir + "/" + pattern.filename.substring(0, pattern.filename.indexOf('.')); + addToPatternPaths(bucketName, pattern); } @@ -215,6 +236,11 @@ var patternlab_engine = function(grunt){ navSubItem.patternPath = pattern.patternLink; navSubItem.patternPartial = bucketName + "-" + pattern.patternName; //add the hyphenated name + //add the patternState if it exists + if(pattern.patternState){ + navSubItem.patternState = pattern.patternState; + } + //test whether the pattern struture is flat or not - usually due to a template or page var flatPatternItem = false; if(navItemName === bucketName){ @@ -228,7 +254,7 @@ var patternlab_engine = function(grunt){ bucket.patternItems.push(navSubItem); //add to patternPaths - patternlab.patternPaths[bucketName][pattern.patternName] = pattern.subdir + "/" + pattern.filename.substring(0, pattern.filename.indexOf('.')); + addToPatternPaths(bucketName, pattern); } else{ //check to see if navItem exists @@ -251,33 +277,32 @@ var patternlab_engine = function(grunt){ } // just add to patternPaths - patternlab.patternPaths[bucketName][pattern.patternName] = pattern.subdir + "/" + pattern.filename.substring(0, pattern.filename.indexOf('.')); - + addToPatternPaths(bucketName, pattern); } } - }; + } //the patternlab site requires a lot of partials to be rendered. //patternNav - var patternNavTemplate = grunt.file.read('./source/_patternlab-files/partials/patternNav.mustache'); + var patternNavTemplate = fs.readFileSync('./source/_patternlab-files/partials/patternNav.mustache', 'utf8'); var patternNavPartialHtml = renderPattern(patternNavTemplate, patternlab); //ishControls - var ishControlsTemplate = grunt.file.read('./source/_patternlab-files/partials/ishControls.mustache'); + var ishControlsTemplate = fs.readFileSync('./source/_patternlab-files/partials/ishControls.mustache', 'utf8'); var ishControlsPartialHtml = renderPattern(ishControlsTemplate, patternlab.config); //patternPaths - var patternPathsTemplate = grunt.file.read('./source/_patternlab-files/partials/patternPaths.mustache'); + var patternPathsTemplate = fs.readFileSync('./source/_patternlab-files/partials/patternPaths.mustache', 'utf8'); var patternPathsPartialHtml = renderPattern(patternPathsTemplate, {'patternPaths': JSON.stringify(patternlab.patternPaths)}); //viewAllPaths - var viewAllPathsTemplate = grunt.file.read('./source/_patternlab-files/partials/viewAllPaths.mustache'); + var viewAllPathsTemplate = fs.readFileSync('./source/_patternlab-files/partials/viewAllPaths.mustache', 'utf8'); var viewAllPathersPartialHtml = renderPattern(viewAllPathsTemplate, {'viewallpaths': JSON.stringify(patternlab.viewAllPaths)}); //websockets - var websocketsTemplate = grunt.file.read('./source/_patternlab-files/partials/websockets.mustache'); + var websocketsTemplate = fs.readFileSync('./source/_patternlab-files/partials/websockets.mustache', 'utf8'); patternlab.contentsyncport = patternlab.config.contentSyncPort; patternlab.navsyncport = patternlab.config.navSyncPort; @@ -291,8 +316,7 @@ var patternlab_engine = function(grunt){ 'websockets': websocketsPartialHtml, 'viewAllPaths': viewAllPathersPartialHtml }); - grunt.file.write('./public/index.html', patternlabSiteHtml); - + fs.outputFileSync('./public/index.html', patternlabSiteHtml); } function renderPattern(name, data, partials) { @@ -303,6 +327,11 @@ var patternlab_engine = function(grunt){ } } + function addToPatternPaths(bucketName, pattern){ + //this is messy, could use a refactor. + patternlab.patternPaths[bucketName][pattern.patternName] = pattern.subdir.replace(/\\/g, '/') + "/" + pattern.filename.substring(0, pattern.filename.indexOf('.')); + } + return { version: function(){ return getVersion(); @@ -311,13 +340,11 @@ var patternlab_engine = function(grunt){ buildPatterns(); buildFrontEnd(); printDebug(); - }, help: function(){ help(); }, build_patterns_only: function(){ - grunt.log.ok('only_patterns argument not yet implemented'); buildPatterns(); printDebug(); } @@ -327,31 +354,3 @@ var patternlab_engine = function(grunt){ module.exports = patternlab_engine; -module.exports = function(grunt) { - grunt.registerTask('patternlab', 'create design systems with atomic design', function(arg) { - - var patternlab = patternlab_engine(grunt); - - if(arguments.length === 0){ - patternlab.build(); - } - - if(arg && arg === 'v'){ - patternlab.version(); - } - - if(arg && arg === "only_patterns"){ - patternlab.build_patterns_only(); - } - - if(arg && arg === "help"){ - patternlab.help(); - } - - if(arg && (arg !== "v" && arg !=="only_patterns" && arg !=="help")){ - patternlab.help(); - } - - }); - -}; \ No newline at end of file diff --git a/config.json b/config.json index 84e5356e9..65a6e56fa 100644 --- a/config.json +++ b/config.json @@ -27,5 +27,7 @@ "tools-reload": false, "tools-shortcuts": false, "tools-docs": true + }, + "patternStates": { } } \ No newline at end of file diff --git a/package.json b/package.json index 30b052578..6d8487426 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "patternlab-node", "description": "Pattern Lab is a collection of tools to help you create atomic design systems. This is the node command line interface (CLI).", - "version": "0.1.2", + "version": "0.1.3", "devDependencies": { "grunt": "~0.4.0", "grunt-contrib-watch": "~0.2.0", @@ -11,8 +11,11 @@ "grunt-contrib-clean": "~0.5.0", "grunt-contrib-concat": "~0.3.0", "grunt-contrib-nodeunit": "~0.3.0", + "grunt-contrib-connect": "^0.8.0", "mustache": "~0.8.1", - "matchdep": "~0.3.0" + "matchdep": "~0.3.0", + "fs-extra": "^0.10.0", + "diveSync": "^0.2.1" }, "keywords": [ "Pattern Lab", @@ -28,7 +31,7 @@ "author": "Brian Muenzenmeyer", "license": "MIT", "scripts": { - "test" : "grunt travis --verbose" + "test": "grunt travis --verbose" }, "engines": { "node": ">=0.1" diff --git a/source/_patternlab-files/partials/patternNav.mustache b/source/_patternlab-files/partials/patternNav.mustache index 3a60f2ab9..7664a1f94 100644 --- a/source/_patternlab-files/partials/patternNav.mustache +++ b/source/_patternlab-files/partials/patternNav.mustache @@ -4,7 +4,7 @@ {{# navItems }}
  • {{ sectionNameUC }}
      {{# navSubItems }} -
    1. {{ patternName }}
    2. +
    3. {{ patternName }}
    4. {{/ navSubItems }}
  • {{/ navItems }} diff --git a/source/_patternlab-files/styleguide.mustache b/source/_patternlab-files/styleguide.mustache index e6088e871..e2c66202a 100644 --- a/source/_patternlab-files/styleguide.mustache +++ b/source/_patternlab-files/styleguide.mustache @@ -17,7 +17,7 @@
    {{# partials }}
    -

    {{ patternName }}

    +

    {{ patternName }}

    {{{ patternPartial }}}