├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .travis.yml ├── README.md ├── app ├── index.js └── templates │ └── gitignore ├── package.json ├── test ├── test-creation.js └── test-load.js └── util └── art.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = tab 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.diff 3 | *.err 4 | *.orig 5 | *.log 6 | *.rej 7 | *.swo 8 | *.swp 9 | *.zip 10 | *.vi 11 | *~ 12 | 13 | #OS folders 14 | .DS_Store 15 | ._* 16 | Thumbs.db 17 | .cache 18 | .project 19 | .settings 20 | .tmproj 21 | *.esproj 22 | *.sass-cache 23 | *.ruby-version 24 | node_modules/ 25 | temp/ -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | before_install: 5 | - currentfolder=${PWD##*/} 6 | - if [ "$currentfolder" != 'generator-emi' ]; then cd .. && eval "mv $currentfolder generator-emi" && cd generator-emi; fi 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Generate Emi, an automated WordPress Starter Theme 2 | 3 | This is a Yeoman generator that lets you quickly and easily create a new WordPress theme based on Emi, a starter theme. The generated starter theme is ready to roll with naming conventions based on your generator input, and with Sass and [Gulp.js](gulpjs.com) for further automation as you work on your customizations. 4 | 5 | ## Getting Started 6 | 7 | ### Install Yeoman 8 | 9 | If you don't already have Yeoman installed, you'll need to take care of that: 10 | 11 | ``` 12 | $ npm install -g yo 13 | ``` 14 | 15 | Or, if you get errors related to permissions, try: 16 | 17 | ``` 18 | $ sudo npm install -g yo 19 | ``` 20 | 21 | ### Install Emi 22 | 23 | 24 | You can install the Emi generator using the command: 25 | 26 | ``` 27 | $ npm install -g generator-emi 28 | ``` 29 | 30 | Then, you should be able to initiate the generator. 31 | 32 | ``` 33 | $ yo emi 34 | ``` 35 | 36 | You'll want to do this from your `/wp-content/themes/` directory or wherever you want your new theme folder to live. Your theme files will be created in their own directory, named based on your input. 37 | 38 | That's all there is to it! 39 | 40 | ## Changelog 41 | 2.1.2 Fixed directory path for renaming file variables 42 | 2.1.0 Updated ReadMe, version bump for refactor 43 | 2.0.6 Updated to create the theme directory, fixed a few bugs 44 | 2.0.3 Fix package.json so other subdirectories are downloaded 45 | 2.0.2 Update installation directions 46 | 2.0.1 Improve description 47 | 2.0.0 Pulls Emi from the theme's repo 48 | 1.0.0 Initial release 49 | 50 | 51 | ## License 52 | 53 | MIT -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'), 3 | path = require('path'), 4 | fs = require('fs'), 5 | yeoman = require('yeoman-generator'), 6 | chalk = require('chalk'), 7 | art = require('../util/art'); 8 | 9 | var EmiGenerator = yeoman.generators.Base.extend({ 10 | initializing: function () { 11 | this.pkg = require('../package.json'); 12 | 13 | // Welcome art & description 14 | this.log.writeln(chalk.yellow(art.emi)); 15 | console.log(chalk.yellow('You\'re about to generate a new starter theme based on Emi. Just a few questions to get started...')); 16 | }, 17 | prompting: function () { 18 | 19 | var done = this.async(); 20 | 21 | var prompts = [{ 22 | name: 'themeName', 23 | message: 'What do you want to name your theme?', 24 | },{ 25 | name: 'themeAuthor', 26 | message: 'Who is the theme author?', 27 | default: function( answers ) { 28 | return 'Zoe Rooney Web Development'; 29 | } 30 | },{ 31 | name: 'authorURI', 32 | message: 'What\'s their website URL (the author)?', 33 | default: function( answers ) { 34 | return 'http://www.zoerooney.com'; 35 | } 36 | },{ 37 | name: 'themeURI', 38 | message: 'What is the final website URL?' 39 | },{ 40 | name: 'themeDescription', 41 | message: 'Please briefly describe this theme.', 42 | default: function( answers ) { 43 | return answers.themeName+' custom theme'; 44 | } 45 | }, { 46 | name: 'themeDesigner', 47 | message: 'Who designed the theme?' 48 | }, { 49 | name: 'designerURI', 50 | message: 'Designer\'s website URL?' 51 | } 52 | ]; 53 | 54 | this.prompt(prompts, function (props) { 55 | 56 | //All the names 57 | this.themeName = props.themeName; 58 | this.themeHandle = props.themeName.trim().replace(/ /g,'_'); 59 | this.themeFunction = props.themeName.toLowerCase().trim().replace(/ /g,'_'); 60 | this.themeTextDomain = props.themeName.toLowerCase().trim().replace(/ /g,'-'); 61 | this.themeAuthor = props.themeAuthor; 62 | this.authorURI = props.authorURI; 63 | this.themeURI = props.themeURI; 64 | this.themeDescription = props.themeDescription; 65 | this.themeDesigner = props.themeDesigner; 66 | this.designerURI = props.designerURI; 67 | 68 | done(); 69 | }.bind(this)); 70 | }, 71 | configuring: function() { 72 | var cb = this.async(), 73 | self = this 74 | 75 | this.log.writeln(chalk.yellow('\n\nLet\'s grab the latest version of Emi...\n\n')); 76 | this.extract('https://github.com/zoerooney/Emi/archive/master.tar.gz', '.', cb); 77 | this.log.writeln(chalk.yellow(art.checkmark)); 78 | this.log.writeln(chalk.yellow('\n\nGot it (that was quick)!\n\n')); 79 | }, 80 | writing: function () { 81 | var complete = this.async(), 82 | self = this 83 | 84 | fs.rename('Emi-master', self.themeTextDomain); 85 | 86 | // parse recursively a directory 87 | function parseDirectory( path ) { 88 | 89 | fs.readdir( path , function(err, files) { 90 | files.forEach( function(file) { 91 | var filePath = fs.realpathSync( path + '/' + file), 92 | isDirectory = fs.statSync( filePath ).isDirectory() 93 | 94 | if (isDirectory) { 95 | parseDirectory( filePath ) 96 | } else { 97 | fs.readFile( filePath, 'utf8', function (err,data) { 98 | data = data.replace(/themeName/g, self.themeName) 99 | data = data.replace(/themeHandle/g, self.themeHandle) 100 | data = data.replace(/themeFunction/g, self.themeFunction) 101 | data = data.replace(/themeTextDomain/g, self.themeTextDomain) 102 | data = data.replace(/themeAuthor/g, self.themeAuthor) 103 | data = data.replace(/authorURI/g, self.authorURI) 104 | data = data.replace(/themeURI/g, self.themeURI) 105 | data = data.replace(/themeDescription/g, self.themeDescription) 106 | data = data.replace(/themeDesigner/g, self.themeDesigner) 107 | data = data.replace(/designerURI/g, self.designerURI) 108 | 109 | fs.writeFile(filePath, data, 'utf8', function (err) { 110 | if (err) return console.log(err); 111 | }); 112 | }); 113 | } //endif 114 | }) 115 | }) 116 | } 117 | parseDirectory(self.themeTextDomain) 118 | complete() 119 | }, 120 | install: function(){ 121 | console.log(chalk.yellow('\n\nNext I\'ll install all the dependencies, so sit tight!\n\n')); 122 | 123 | process.chdir(this.themeTextDomain); 124 | this.npmInstall('',function(){ 125 | console.log(chalk.yellow(art.checkmark + '\nWhew, all installed! Last but not least, we\'ll set up style.css.\n\nOnce this last bit runs we\'re all done here!\n\n')); 126 | }); 127 | }, 128 | end: function(){ 129 | this.spawnCommand('gulp', ['styles']); 130 | } 131 | 132 | }); 133 | module.exports = EmiGenerator; -------------------------------------------------------------------------------- /app/templates/gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.diff 3 | *.err 4 | *.orig 5 | *.log 6 | *.rej 7 | *.swo 8 | *.swp 9 | *.zip 10 | *.vi 11 | *~ 12 | 13 | #OS folders 14 | .DS_Store 15 | ._* 16 | Thumbs.db 17 | .cache 18 | .project 19 | .settings 20 | .tmproj 21 | *.esproj 22 | *.sass-cache 23 | *.ruby-version 24 | node_modules -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-emi", 3 | "version": "2.1.2", 4 | "description": "Use Yeoman to generate a clean, Sass and Gulp-ready WordPress starter theme", 5 | "license": "MIT", 6 | "homepage": "https://github.com/zoerooney/yo-emi", 7 | "bugs": "https://github.com/zoerooney/yo-emi/issues", 8 | "main": "app/index.js", 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/zoerooney/yo-emi.git" 12 | }, 13 | "author": { 14 | "name": "Zoe Rooney", 15 | "email": "hello@zoerooney.com", 16 | "url": "http://github.com/zoerooney" 17 | }, 18 | "engines": { 19 | "node": ">=0.10.0", 20 | "npm": ">=1.2.10" 21 | }, 22 | "scripts": { 23 | "test": "mocha" 24 | }, 25 | "files": [ 26 | "app", 27 | "test", 28 | "util" 29 | ], 30 | "keywords": [ 31 | "yeoman-generator", 32 | "wordpress", 33 | "theme", 34 | "front-end", 35 | "gulp", 36 | "starter theme", 37 | "emi" 38 | ], 39 | "dependencies": { 40 | "yeoman-generator": ">=0.16.0", 41 | "chalk": ">=0.4.0" 42 | }, 43 | "devDependencies": { 44 | "mocha": "*" 45 | }, 46 | "peerDependencies": { 47 | "yo": ">=1.0.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/test-creation.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it */ 2 | 'use strict'; 3 | var path = require('path'); 4 | var helpers = require('yeoman-generator').test; 5 | 6 | describe('emi generator', function () { 7 | beforeEach(function (done) { 8 | helpers.testDirectory(path.join(__dirname, 'temp'), function (err) { 9 | if (err) { 10 | return done(err); 11 | } 12 | 13 | this.app = helpers.createGenerator('emi:app', [ 14 | '../../app' 15 | ]); 16 | done(); 17 | }.bind(this)); 18 | }); 19 | 20 | it('creates expected files', function (done) { 21 | var expected = [ 22 | // add files you expect to exist here. 23 | '.gitignore', 24 | '404.php', 25 | '503.php', 26 | 'assets/theme.js', 27 | 'assets/vendor/html5.js', 28 | 'comments.php', 29 | 'content-page.php', 30 | 'content.php', 31 | 'footer.php', 32 | 'front-page.php', 33 | 'functions.php', 34 | 'header.php', 35 | 'inc/aq_resizer.php', 36 | 'index.php', 37 | 'page-full-width.php', 38 | 'page-redirect-url.php', 39 | 'page-redirect.php', 40 | 'page.php', 41 | 'scss/style.max.scss', 42 | 'search.php', 43 | 'searchform.php', 44 | 'sidebar.php', 45 | 'single.php', 46 | 'style.css' 47 | ]; 48 | 49 | helpers.mockPrompt(this.app, { 50 | 'themeName': true, 51 | 'themeAuthor': true, 52 | 'themeAuthorURI': true, 53 | 'themeURI': true, 54 | 'themeDescription': true, 55 | 'themeDesigner': true, 56 | 'themeDesignerURI': true, 57 | 'taskRunner': true 58 | }); 59 | this.app.options['skip-install'] = true; 60 | this.app.run({}, function () { 61 | helpers.assertFile(expected); 62 | done(); 63 | }); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /test/test-load.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it*/ 2 | 'use strict'; 3 | var assert = require('assert'); 4 | 5 | describe('emi generator', function () { 6 | it('can be imported without blowing up', function () { 7 | var app = require('../app'); 8 | assert(app !== undefined); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /util/art.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk'); 2 | 3 | module.exports = { 4 | emi : [ 5 | '', 6 | '███████╗ ███╗ ███╗ ██╗', 7 | '██╔════╝ ████╗ ████║ ██║', 8 | '█████╗ ██╔████╔██║ ██║', 9 | '██╔══╝ ██║╚██╔╝██║ ██║', 10 | '███████╗ ██║ ╚═╝ ██║ ██║', 11 | '╚══════╝ ╚═╝ ╚═╝ ╚═╝', 12 | '' 13 | ].join('\n'), 14 | checkmark : [ 15 | '', 16 | ' ██', 17 | ' ██ ', 18 | '██ ██ ', 19 | ' ██ ██ ', 20 | ' ██ ', 21 | '' 22 | ].join('\n') 23 | }; --------------------------------------------------------------------------------