Commit ff9670cd authored by Philipp Nowinski's avatar Philipp Nowinski
Browse files

Merge branch 'v300' into 'master'

V300

See merge request !1
parents e695589d 5146b97a
......@@ -4,27 +4,22 @@
> [Yeoman](http://yeoman.io) generator
> **Note: major changes with version 3.0.0**
> If you have used previous versions of this generator, there are some things to notice:
> The asset-paths.json files are no longer needed. The generator now follows a convention over configuration approach
> and assumes, that your extensions follow the same directory structure. Also, the standalone mode has been removed.
> The whole purpose of this generator is now to scaffold a frontend build process for TYPO3 projects with Extbase Extensions.
## Installation
* [Install Node](docs/INSTALL-NODE.md)
> **Note:**
> The sprite engine that is used in this generator does currently not support node v0.12
> To install the latest v0.10 release of node with nvm, run:
> ```bash
> nvm install 0.10
> ```
> You can make this selection permanent by running
> ```bash
> nvm alias default 0.10
> ```
To use the sgalinski-generator you need to have node and npm installed. Furthermore, you should have
yeoman, gulp and bower installed globally. To do so, simply run
```bash
npm install -g yo
npm install -g bower
npm install -g gulp
```
......@@ -42,27 +37,10 @@ To run the generator, navigate to the directory you want to create your project
yo gulp-sgalinski
```
### Standalone vs. TYPO3 project
The first question the generator will ask you, is what kind of a project you want to build. Basically, there are two
different kinds of projects: Standalone and TYPO3 projects.
#### Standalone
The standalone option is meant for scaffolding projects that do not require a backend. At [sgalinski Internet Services](http://www.sgalinski.de/),
we mainly use this for building prototypes.
#### TYPO3 projects
The main function of this generator is to scaffold a frontend setup for TYPO3 projects with Extbase Extensions. This
setup is separated into two components. In your project root (next to the typo3conf directory), you need to generate
the 'TYPO3 Frontend Setup'. This will install the gulp tasks to your project root. You'll then need to generate the
'TYPO3 Extbase Extension' setup inside every extensions folder you want to use the gulp setup on. This will generate
some config files inside the extensions folder, so that gulp knows where to put things when you run tasks.
### Firing up gulp
To invoke a gulp task, you simply run 'gulp', followed by the name of the task you want to run. E.g. if you want to run
the CSS task, you'd run 'gulp css'. Below, you'll find a list of commands that come bundled with this generator.
#### Work with extensions
If you are working on a TYPO3 project, there are two different ways of running tasks. You can either run a specific task for a specific extension, or you can run the default task, which will start a dev environment with BrowserSync and a couple of watchers.
The purpose of this generator is to scaffold a frontend build process for TYPO3 projects with Extbase Extensions. This
assumes, that your code is organized in extension folders under typo3conf/ext and that all extensions follow the same
directory structure. The generator will ask you for the paths to the asset files relative to the extensions folder.
##### Running a specific task
If you just want to run a specific task for a specific extension, run
......@@ -85,7 +63,7 @@ gulp
```
you will get a development environment with BrowserSync and some watchers that will automatically trigger tasks when you change sourcefiles. If you are not familliar with [BrowserSync](http://www.browsersync.io/), you should definitely check it out.
BrowserSync will basically start up a server and provide you with a URL which points to your project. If you are running a standalone project, BrowserSync will simply serve files from your project root. If you are running a TYPO3 project, BrowserSync will be set up with a proxy that tunnels request to your development URL. You can change this URL inside gulp/browser-sync.js. BrowserSync will also disable the TYPO3 cache and the ([scriptmerger extension](http://typo3.org/extensions/repository/view/scriptmerger)) for every request, by setting query string parameters. Apart from the livereload functionallity, BrowserSync offers some other cool features like syncing Mouse- and Keyboardevents. Since version 2.0.0, there is also a UI with a lot more to discover. You should read about this on the BrowserSync website.
BrowserSync will basically start up a server and provide you with a URL which points to your project. BrowserSync will be set up with a proxy that tunnels request to your development URL. You can change this URL inside gulp/browser-sync.js. BrowserSync will also disable the TYPO3 cache and the ([scriptmerger extension](http://typo3.org/extensions/repository/view/scriptmerger)) for every request, by setting query string parameters. Apart from the livereload functionallity, BrowserSync offers some other cool features like syncing Mouse- and Keyboardevents. Since version 2.0.0, there is also a UI with a lot more to discover. You should read about this on the BrowserSync website.
Once the default tasks started and BrowserSync is ready to serve your files, all changes you make to you CSS and JavaScript files will automatically injected into the browser, without reloading the site. Gulp will automatically figure out the extension you made changes to and pass the information to the corresponding task.
......@@ -101,11 +79,12 @@ Once the default tasks started and BrowserSync is ready to serve your files, all
* It will autoprefix your css.
* It will resolve css @import-statements to avoid additional requests.
* It will generate sourcempas for your css files.
* It will log the filesize of the generated css to the console. You can specify a limit to get warnings if this limit is exceeded.
* It will minify your css if you enabled this option during project generation.
* javascript
*[command: 'gulp javascript']
* The javascript task runs jshint on your JS files. Depending on your configuration, it also runs
[browserify](http://browserify.org/) on them, or concatenates them into one file. If you chose this option when
* The javascript task runs jshint on your JS files. It also runs
[browserify](http://browserify.org/) on them. If you chose this option when
generating the setup, it will also minify them.
* images
* [command: 'gulp images']
......@@ -126,17 +105,9 @@ The gulp-sgalinski generator will generate the following config files:
* .jshintrc
* This is where you can define all rules JsHint will apply to your code. If you delete this file, JsHint will use
the standard settings. This file should also work for instances of JsHint that are built into your Editor.
* gulp/settings.js
* This is where all gulp tasks read the paths to you assets from. It will be configured according to your answers
to the generators questions.
* asset-paths.json [only for Extbase Extensions]
* If you're working on a TYPO3 project, your gulp tasks (including settings.js) will live in your project root.
Since different extensions can store their assets to different paths, gulp needs to be aware of the paths for the
extension you want to work on. This is a simple JSON file, that lives inside every extensions folder and defines
the paths for its assets.
* bower.json [optional]
* This file is where all clientside dependencies can be defined if you want to use Bower. See
[http://bower.io](http://bower.io) for more information on what Bower can do for you.
* gulp/config.json
* This is where the paths to your asset files, relative to the extension folder are defined, as well as the list
of extension names you want gulp to watch for changes.
* package.json [mandatory]
* The package.json file is the manifest for every node.js module. Since gulp is written in node, you will need this
file. This is where all used node modules (e.g. every gulp task is a node module) are defined as dependencies. They
......@@ -150,14 +121,11 @@ on your ignorelist (.gitignore, .svnignore, etc.):
* node_modules
* This folder can be quite heavy and its contents can differ depending on you Operating System. The recommended way
is to check in the package.json and run 'npm install' on every new checkout.
* bower_components
* If you decide to use Bower, this is where all clientside dependencies will be stored
((http://bower.io/docs/config/)[you can change the name if you want to]). You might consider to handle them the
same way as node dependencies and just check in the bower.json file.
## Changelog
* 2015-05-21   v3.0.0   Remove standalone mode; get rid of asset-path.json; add check-filesize-plugin
* 2015-02-22   v2.1.0   add cache and scriptmerger deactivation via query string params
* 2015-02-15   v2.0.0   get rid of compass + update browsersync + add global watcher
* 2015-01-19   v1.1.0   major changes to the scaffolded gulp tasks + massive README
......
......@@ -3,36 +3,17 @@ var yeoman = require('yeoman-generator'),
chalk = require('chalk'),
yosay = require('yosay'),
path = require('path'),
_ = require('underscore');
_ = require('underscore'),
_s = require('underscore.string');
module.exports = yeoman.generators.Base.extend((function() {
var Generator = {},
answers = {},
resourcePathsSuggestions = {
extbaseExtension: {
cssPath: path.join('Resources', 'Public', 'StyleSheets'),
sassPath: path.join('Resources', 'Public', 'Sass'),
imagesPath: path.join('Resources', 'Public', 'Images'),
javascriptPath: path.join('Resources', 'Public', 'Scripts')
},
standalone: {
cssPath: 'css',
sassPath: 'sass',
imagesPath: 'images',
javascriptPath: 'javascript'
}
},
jsUglifySuggestions = {
standalone: true,
typo3Frontend: false
},
jsConcatSuggestions = {
standalone: true,
typo3Frontend: false
},
cssMinifySuggestions = {
standalone: true,
typo3Frontend: false
cssPath: path.join('Resources', 'Public', 'StyleSheets'),
sassPath: path.join('Resources', 'Public', 'Sass'),
imagesPath: path.join('Resources', 'Public', 'Images'),
javascriptPath: path.join('Resources', 'Public', 'Scripts')
};
Generator.initializing = function() {
......@@ -48,30 +29,14 @@ module.exports = yeoman.generators.Base.extend((function() {
'Welcome to the dandy ' + chalk.red('Sgalinski') + ' generator!'
));
this.log(chalk.bold.yellow('I will help you to setup a frontend build process for ' +
'your TYPO3 project with Extbase Extensions.\n\n'));
this.prompt([
{
type: 'list',
name: 'projectType',
message: 'What do you want me to build a frontend setup for?',
choices: [
{
value: 'extbaseExtension',
name: 'TYPO3 Extbase Extension'
},
{
value: 'typo3Frontend',
name: 'TYPO3 Frontend Setup'
},
{
value: 'standalone',
name: 'Standalone Frontend Project'
}
]
},
{
type: 'input',
name: 'projectName',
message: 'Please enter the name of your project/extension',
message: 'Please enter the name of your project',
default: process.cwd().split(path.sep).pop()
}
], function(_answers) {
......@@ -80,240 +45,196 @@ module.exports = yeoman.generators.Base.extend((function() {
});
},
pathPrompts: function() {
if (answers.projectType !== 'typo3Frontend') {
var done = this.async(),
questions;
var done = this.async(),
questions;
// define questions
questions = [
{
type: 'input',
name: 'cssPath',
message: 'Please specify the path to the compiled css files',
default: resourcePathsSuggestions[answers.projectType].cssPath
},
{
type: 'input',
name: 'sassPath',
message: 'Please specify the path to the sass source files',
default: resourcePathsSuggestions[answers.projectType].sassPath
},
{
type: 'input',
name: 'javascriptPath',
message: 'Please specify the path to the javascript files',
default: resourcePathsSuggestions[answers.projectType].javascriptPath
},
{
type: 'input',
name: 'imagesPath',
message: 'Please specify the path to the images',
default: resourcePathsSuggestions[answers.projectType].imagesPath
// define questions
questions = [
{
type: 'input',
name: 'cssPath',
message: 'Please specify the path to the compiled css files',
default: resourcePathsSuggestions.cssPath
},
{
type: 'input',
name: 'sassPath',
message: 'Please specify the path to the sass source files',
default: resourcePathsSuggestions.sassPath
},
{
type: 'input',
name: 'javascriptPath',
message: 'Please specify the path to the javascript files',
default: resourcePathsSuggestions.javascriptPath
},
{
type: 'input',
name: 'imagesPath',
message: 'Please specify the path to the images',
default: resourcePathsSuggestions.imagesPath
},
{
type: 'input',
name: 'extensions',
message: 'Please enter the names of the extensions you want gulp to watch for changes, ' +
'separated by commas (project_base, ext_one, ext_two).',
default: ''
}
];
// ask questions
this.prompt(questions, function(_answers) {
var extensionArray = _answers.extensions.split(',');
_answers.extensions = '';
for (var ext in extensionArray) {
if (_answers.extensions !== '') {
_answers.extensions += ',\n\t\t';
}
];
// ask questions
this.prompt(questions, function(_answers) {
answers = _.extend(answers, _answers);
done();
});
}
_answers.extensions += '"' + _s.trim(extensionArray[ext]) + '"';
}
answers = _.extend(answers, _answers);
done();
});
},
cssPrompts: function() {
var done = this.async();
this.prompt([
{
when: function() { return answers.projectType !== 'extbaseExtension'; },
type: 'confirm',
name: 'minifyCss',
message: 'Do you want to include minification for CSS files?',
default: cssMinifySuggestions[answers.projectType]
message: 'Do you want to include minification for CSS files?\nYou won\'t need this if you have the' +
'Scriptmerger Extension installed (http://typo3.org/extensions/repository/view/scriptmerger)',
default: false
},
{
type: 'input',
name: 'maxCssFileSize',
message: 'Specify a maximum size (in Bytes) for CSS files. Leave blank if you don\'t want to ' +
'specify a limit',
default: ''
}
], function(_answers) {
answers = _.extend(answers, _answers);
done();
});
},
javascriptPrompts: function() {
if (answers.projectType !== 'extbaseExtension') {
var done = this.async();
this.prompt([
{
type: 'confirm',
name: 'browserify',
message: 'Do you want to use Browserify for organizing you JS modules?',
default: true
},
{
when: function(answers) { return !answers.browserify; },
type: 'confirm',
name: 'jsconcat',
message: 'Do you want to include a concat task for JavaScript?',
default: jsConcatSuggestions[answers.projectType]
},
{
type: 'confirm',
name: 'jsuglify',
message: 'Do you want to include uglify for JavaScript?',
default: jsUglifySuggestions[answers.projectType]
}
], function(_answers) {
answers = _.extend(answers, _answers);
done();
});
}
var done = this.async();
this.prompt([
{
type: 'confirm',
name: 'browserify',
message: 'Do you want to use Browserify for organizing you JS modules?',
default: true
},
{
type: 'confirm',
name: 'jsuglify',
message: 'Do you want to include uglify for JavaScript?\nYou won\'t need this if you have the' +
'Scriptmerger Extension installed (http://typo3.org/extensions/repository/view/scriptmerger)',
default: false
},
{
type: 'input',
name: 'maxJsFileSize',
message: 'Specify a maximum size (in Bytes) for JavaScript files. Leave blank if you don\'t want to ' +
'specify a limit',
default: ''
}
], function(_answers) {
answers = _.extend(answers, _answers);
done();
});
},
configPrompts: function() {
if (answers.projectType !== 'extbaseExtension') {
var done = this.async();
this.prompt([
{
type: 'input',
name: 'autoprefixerBrowserSelection',
message: 'Please provide the configuration strings for autoprefixer',
default: '\'last 1 version\', \'> 1%\', \'ie 8\''
},
{
type: 'confirm',
name: 'bower',
message: 'Do you want to include bower for handling client-side dependencies?',
default: true
}
], function(_answers) {
answers = _.extend(answers, _answers);
done();
});
}
var done = this.async();
this.prompt([
{
type: 'input',
name: 'autoprefixerBrowserSelection',
message: 'Please provide the configuration strings for autoprefixer',
default: '\'last 1 version\', \'> 1%\', \'ie 8\''
}
], function(_answers) {
answers = _.extend(answers, _answers);
done();
});
},
browserSyncPrompts: function() {
if (answers.projectType === 'typo3Frontend') {
var done = this.async();
this.prompt({
type: 'input',
name: 'devUrl',
message: 'Please specify the URL where your TYPO3 site will be reachable during development',
default: answers.projectName + '.dev'
}, function(_answers) {
answers = _.extend(answers, _answers);
done();
});
}
var done = this.async();
this.prompt({
type: 'input',
name: 'devUrl',
message: 'Please specify the URL where your TYPO3 site will be reachable during development',
default: answers.projectName + '.dev'
}, function(_answers) {
answers = _.extend(answers, _answers);
done();
});
}
};
Generator.writeGeneralConfigs = function() {
if (answers.projectType !== 'extbaseExtension') {
this.fs.copy(
this.templatePath('_editorconfig'),
this.destinationPath('.editorconfig')
);
this.fs.copy(
this.templatePath('_jshintrc'),
this.destinationPath('.jshintrc')
);
}
this.fs.copy(
this.templatePath('_editorconfig'),
this.destinationPath('.editorconfig')
);
this.fs.copy(
this.templatePath('_jshintrc'),
this.destinationPath('.jshintrc')
);
};
Generator.writeGulp = function() {
if (answers.projectType !== 'extbaseExtension') {
this.fs.copyTpl(
this.templatePath('_gulpfile.js'),
this.destinationPath('gulpfile.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/settings.js'),
this.destinationPath('gulp/settings.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/css.js'),
this.destinationPath('gulp/css.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/browser-sync.js'),
this.destinationPath('gulp/browser-sync.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/images.js'),
this.destinationPath('gulp/images.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/javascript.js'),
this.destinationPath('gulp/javascript.js'),
answers
);
this.fs.copy(
this.templatePath('gulp/sprite-scss-template.mustache'),
this.destinationPath('gulp/sprite-scss-template.mustache'),
answers
);
}
};
Generator.writeHtml = function() {
if (answers.projectType === 'standalone') {
this.fs.copyTpl(
this.templatePath('_index.html'),
this.destinationPath('index.html'),
answers
);
}
};
Generator.writeSass = function() {
if (answers.projectType !== 'typo3Frontend') {
this.fs.copy(
this.templatePath('_main.scss'),
this.destinationPath(answers.sassPath + '/main.scss')
);
}
};
Generator.writeJavascript = function() {
if (answers.projectType !== 'typo3Frontend') {
this.fs.copy(
this.templatePath('_main.js'),
this.destinationPath(answers.javascriptPath + '/main.js')
);
}
};
Generator.writeDirectories = function() {
if (answers.projectType !== 'typo3Frontend') {
this.mkdir(this.destinationPath(answers.imagesPath));
}
};
Generator.writePathConfig = function() {
if (answers.projectType === 'extbaseExtension') {
this.fs.copyTpl(
this.templatePath('_asset-paths.json'),
this.destinationPath('asset-paths.json'),
answers
);
}
this.fs.copyTpl(
this.templatePath('_gulpfile.js'),
this.destinationPath('gulpfile.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/settings.js'),
this.destinationPath('gulp/settings.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/css.js'),
this.destinationPath('gulp/css.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/browser-sync.js'),
this.destinationPath('gulp/browser-sync.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/images.js'),
this.destinationPath('gulp/images.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/javascript.js'),
this.destinationPath('gulp/javascript.js'),
answers
);
this.fs.copyTpl(
this.templatePath('gulp/config.json'),
this.destinationPath('gulp/config.json'),
answers
);
this.fs.copy(
this.templatePath('gulp/sprite-scss-template.mustache'),
this.destinationPath('gulp/sprite-scss-template.mustache'),
answers
);
};
Generator.writeDependencyManagement = function() {
if (answers.projectType !== 'extbaseExtension') {
this.fs.copyTpl(
this.templatePath('_package.json'),
this.destinationPath('package.json'),
answers
);
}
if (answers.bower && answers.projectType !== 'extbaseExtension') {
this.fs.copyTpl(
this.templatePath('_bower.json'),
this.destinationPath('bower.json'),
answers
);
}
this.fs.copyTpl(
this.templatePath('_package.json'),
this.destinationPath('package.json'),
answers
);
};
Generator.install = function() {
......
{
"css": "<%= cssPath %>",
"sass": "<%= sassPath %>",
"javascript": "<%= javascriptPath %>",
"images": "<%= imagesPath %>"
}
{
"name": "package",
"version": "0.0.0",
"dependencies": {}
}
......@@ -2,30 +2,45 @@
var gulp = require('gulp'),