Following a few queries, I wrote this gist who quickly explain how we use GruntJS to build Patternlab and generate HTML for TYPO3 TemplaVoilà templates.
We use
- TYPO3 CMS 4.7.17
- TemplaVoilà! 1.7.0
If you have any question, leave a comment.
The entire Gruntfile.js
.
@alienlebarge Care to throw up a gist real quick?
— Brad Frost (@brad_frost) 4 Mars 2014
@alienlebarge i would love to know more about the conversion to TYPO3 +@brad_frost
— Dave Olsen (@dmolsen) 5 Mars 2014
Basically, we have two folder:
intranet13-src
which contain all the source files.intranet13
is the<%= dest %>
. It contain all the build files use in production.
├── intranet13
│ └── …
├── intranet13-src
│ ├── Configuration
│ │ ├── TsConfig
│ │ ├── TypoScript
│ │ └── templavoila
│ ├── Gruntfile.js
│ ├── README.md
│ ├── build.bat
│ ├── node_modules
│ │ └── …
│ ├── package.json
│ └── patternlab-php
│ ├── CHANGELOG
│ ├── LICENSE
│ ├── README.md
│ ├── config
│ ├── core
│ ├── extras
│ ├── public
│ └── source
First of all, let’s clean all the generated files.
// Clean folder
clean: {
minifed_js: [
'patternlab-php/source/js/**/*.min.js'
],
css: [
'patternlab-php/source/css'
],
// Clean main build
dist: {
options: {
force: true
},
src:['<%= dest %>/**/*']
}
},
We use bootstrap front-end framework. Bootstrap is located in intranet13-src/patternlab-php/source/assets/bootstrap/
.
less: {
compileCore: {
options: {
strictMath: true
},
files: {
'patternlab-php/source/css/style.css': 'patternlab-php/source/less/style.less'
}
},
compileRTE: {
options: {
strictMath: true
},
files: {
'patternlab-php/source/css/rte.css': 'patternlab-php/source/less/rte.less'
}
},
minify: {
options: {
cleancss: true,
report: 'min'
},
files: {
'patternlab-php/source/css/style.min.css': 'patternlab-php/source/css/style.css',
'patternlab-php/source/css/rte.min.css': 'patternlab-php/source/css/rte.css'
}
}
},
less
si for the main stylesheet.- A specific CSS for the TYPO3 RTE is generated with
compileRTE
. minify
build a minified version of the main stylesheet.
patternlab-php/source/less/style.less
is our main LESS file. This is were all the bootstrap files are included.
// The following import method allow to not edit the default Bootstrap files.
// You can overwrite the complete `../assets/bootstrap/` folder without any problem.
// BOOTSTRAP
// ------------------------------------
// The following `@import` are the same as in `../assets/bootstrap/less/bootstrap.less`
// excpeted a `custom-variables.less` is added to override the default variables
// Core variables and mixins
@import "../assets/bootstrap/less/variables.less";
@import "01_settings/variables.less"; // Custom & Override variables
@import "../assets/bootstrap/less/mixins.less";
// Reset
@import "../assets/bootstrap/less/normalize.less";
@import "../assets/bootstrap/less/print.less";
// Core CSS
@import "../assets/bootstrap/less/scaffolding.less";
@import "../assets/bootstrap/less/type.less";
@import "../assets/bootstrap/less/code.less";
@import "../assets/bootstrap/less/grid.less";
@import "../assets/bootstrap/less/tables.less";
@import "../assets/bootstrap/less/forms.less";
@import "../assets/bootstrap/less/buttons.less";
// Components
@import "../assets/bootstrap/less/component-animations.less";
@import "../assets/bootstrap/less/glyphicons.less";
@import "../assets/bootstrap/less/dropdowns.less";
//@import "../assets/bootstrap/less/button-groups.less";
//@import "../assets/bootstrap/less/input-groups.less";
@import "../assets/bootstrap/less/navs.less";
@import "../assets/bootstrap/less/navbar.less";
@import "../assets/bootstrap/less/breadcrumbs.less";
@import "../assets/bootstrap/less/pagination.less";
//@import "../assets/bootstrap/less/pager.less";
//@import "../assets/bootstrap/less/labels.less";
//@import "../assets/bootstrap/less/badges.less";
//@import "../assets/bootstrap/less/jumbotron.less";
@import "../assets/bootstrap/less/thumbnails.less";
@import "../assets/bootstrap/less/alerts.less";
//@import "../assets/bootstrap/less/progress-bars.less";
@import "../assets/bootstrap/less/media.less";
@import "../assets/bootstrap/less/list-group.less";
@import "../assets/bootstrap/less/panels.less";
@import "../assets/bootstrap/less/wells.less";
//@import "../assets/bootstrap/less/close.less";
// Components w/ JavaScript
//@import "../assets/bootstrap/less/modals.less";
//@import "../assets/bootstrap/less/tooltip.less";
//@import "../assets/bootstrap/less/popovers.less";
//@import "../assets/bootstrap/less/carousel.less";
// Utility classes
@import "../assets/bootstrap/less/utilities.less";
@import "../assets/bootstrap/less/responsive-utilities.less";
// CUSTOM STYLE
// ------------------------------------
@import ‘custom.less';
The following part concat all the bootstrap js files.
concat: {
bootstrap: {
src: [
//'patternlab-php/source/assets/bootstrap/js/transition.js',
//'patternlab-php/source/assets/bootstrap/js/alert.js',
//'patternlab-php/source/assets/bootstrap/js/button.js',
//'patternlab-php/source/assets/bootstrap/js/carousel.js',
'patternlab-php/source/assets/bootstrap/js/collapse.js',
'patternlab-php/source/assets/bootstrap/js/dropdown.js'
//'patternlab-php/source/assets/bootstrap/js/modal.js',
//'patternlab-php/source/assets/bootstrap/js/tooltip.js',
//'patternlab-php/source/assets/bootstrap/js/popover.js',
//'patternlab-php/source/assets/bootstrap/js/scrollspy.js',
//'patternlab-php/source/assets/bootstrap/js/tab.js',
//'patternlab-php/source/assets/bootstrap/js/affix.js'
],
dest: 'patternlab-php/source/js/bootstrap.js'
}
},
And here, we uglify all the JS assets
uglify: {
options: {
report: 'min'
},
bootstrap: {
src: ['<%= concat.bootstrap.dest %>'],
dest: 'patternlab-php/source/js/bootstrap.min.js'
},
fitvids: {
src: ['patternlab-php/source/assets/fitvids/*.js'],
dest: 'patternlab-php/source/js/jquery.fitvids.min.js'
},
html5shiv: {
src: ['patternlab-php/source/assets/html5shiv/dist/html5shiv.js'],
dest: 'patternlab-php/source/js/html5shiv.min.js'
},
jquery: {
src: ['patternlab-php/source/assets/jquery/*.js'],
dest: 'patternlab-php/source/js/jquery.min.js'
},
respond: {
src: ['patternlab-php/source/assets/respond/dest/respond.src.js'],
dest: 'patternlab-php/source/js/respond.min.js'
},
script: {
src: ['patternlab-php/source/js/script.js'],
dest: 'patternlab-php/source/js/script.min.js'
}
},
All our files are ready for patternlab. So we can build it.
// Compile pattern-lab files
shell: {
// Run patternlab build
pl: {
options: {
stdout: true
},
command: 'php patternlab-php/core/builder.php -g'
}
},
The TYPO3 specifics files are in intranet13-src/Configuration
. It means, the TsConfig, Typoscript and TemplaVoilà DataStructures & HTML Back-End Layout.
├── intranet13-src
│ ├── Configuration
│ │ ├── TsConfig
│ │ │ ├── Page
│ │ │ └── User
│ │ ├── TypoScript
│ │ │ ├── Config
│ │ │ ├── Content
│ │ │ ├── Lib
│ │ │ ├── Page
│ │ │ ├── Plugin
│ │ │ └── RTE
│ │ └── templavoila
│ │ ├── fce
│ │ └── page
We use patternlab to generate the HTML files for the TemplaVoilà mapping. A new pattern section as been created for this purpose.
├── 00-atoms
│ ├── 00-meta
│ ├── 01-global
│ ├── 02-text
│ ├── 03-lists
│ ├── 04-images
│ ├── 05-forms
│ ├── 06-buttons
│ ├── 07-tables
│ └── 08-media
├── 01-molecules
│ ├── 00-text
│ ├── 01-layout
│ ├── 02-blocks
│ ├── 03-media
│ ├── 04-forms
│ ├── 05-navigation
│ └── 06-components
├── 02-organisms
│ ├── 00-global
│ ├── 01-article
│ ├── 02-comments
│ ├── 03-components
│ ├── 04-sections
│ └── 05-widget
├── 03-templates
├── 04-pages
└── 05-templavoila
├── 00-page-templates
└── 01-flexible-ce
All our files are ready to use in intranet13-src
. So let’s copy what we need to intranet13
.
pl
copy the content of patternlabpublic
folder except patternlab specifics files and patterns.config
copy all the TYPO3 specifics files.tvhtml
copy the HTML patterns for TemplaVoilà mapping.
// Copy files
copy: {
pl: {
expand: true,
cwd: 'patternlab-php/public/',
src: ['**','!**listeners/**','!**patterns/**','!**styleguide/**','!**data/**'],
dest: '<%= dest %>'
},
config: {
expand: true,
cwd: 'Configuration',
src: '**',
dest: '<%= dest %>config'
},
tvhtml: {
expand: true,
flatten: true,
src: [
'patternlab-php/public/patterns/05-templavoila-00-page-templates-00-1col/*',
'patternlab-php/public/patterns/05-templavoila-00-page-templates-01-2col/*',
'patternlab-php/public/patterns/05-templavoila-00-page-templates-02-3col/*'
],
dest: '<%= dest %>config/templavoila/page/',
filter: 'isFile'
}
},
We rename the HTML file for TemplaVoilà.
// rename TemplaVoilà HTML files
rename: {
tvhtml: {
files: [
{src: '<%= copy.tvhtml.dest %>05-templavoila-00-page-templates-00-1col.html', dest: '<%= copy.tvhtml.dest %>1col.html'},
{src: '<%= copy.tvhtml.dest %>05-templavoila-00-page-templates-01-2col.html', dest: '<%= copy.tvhtml.dest %>2col.html'},
{src: '<%= copy.tvhtml.dest %>05-templavoila-00-page-templates-02-3col.html', dest: '<%= copy.tvhtml.dest %>3col.html'}
]
}
},
The we need to clean those files. There is a lot of patternlab specific code that we don’t need (and don’t want).
// Process HTML
processhtml: {
// remove patternlab comments in html and fix links with dist folder structure
tvhtml: {
files: {
'<%= copy.tvhtml.dest %>1col.html': ['<%= copy.tvhtml.dest %>1col.html'],
'<%= copy.tvhtml.dest %>2col.html': ['<%= copy.tvhtml.dest %>2col.html'],
'<%= copy.tvhtml.dest %>3col.html': ['<%= copy.tvhtml.dest %>3col.html']
}
}
},
For that, we use grunt-processhtml
to clean the HTML depending on the tags we placed in /00-atoms/00-meta/_00-head.mustache
<!DOCTYPE html>
<html class="{{ htmlClass }}">
<head>
<title>{{ title }}</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../../css/style.css?{{ cacheBuster }}" media="all">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="../../js/html5shiv.min.js?{{ cacheBuster }}"></script>
<script src="../../js/respond.min.js?{{ cacheBuster }}"></script>
<![endif]-->
<!-- build:remove --><!-- The following code is removed by Grunt for TemplaVoilà mapping. Otherwize, it will be on the production site-->
<!-- Begin Pattern Lab (Required for Pattern Lab to run properly) -->
{% pattern-lab-head %}
<!-- End Pattern Lab -->
<!-- /build -->
</head>
<body class="{{ bodyClass }}">
and /00-atoms/00-meta/_01-foot.mustache
<!-- build:remove --><!-- The following code is removed by Grunt for TemplaVoilà mapping. Otherwize, it will be on the production site-->
<!-- jQuery -->
<script src="../../js/jquery.min.js?{{ cacheBuster }}"></script>
<!-- Bootstrap -->
<script src="../../js/bootstrap.min.js?{{ cacheBuster }}"></script>
<!-- Fitvids -->
<script src="../../js/jquery.fitvids.min.js?{{ cacheBuster }}"></script>
<!-- Custom scripts -->
<script src="../../js/script.min.js.min.js?{{ cacheBuster }}"></script>
<!-- /build -->
<!-- build:remove --><!-- The following code is removed by Grunt for TemplaVoilà mapping. Otherwize, it will be on the production site-->
<!-- LiveReload only fo patternlab dev -->
<script src="//localhost:35729/livereload.js"></script>
<!-- /build -->
<!-- build:remove --><!-- The following code is removed by Grunt for TemplaVoilà mapping. Otherwize, it will be on the production site-->
<!--DO NOT REMOVE-->
{% pattern-lab-foot %}
<!-- /build -->
</body>
</html>
Then a simple task to validate the HTML files:
validation: {
pl: {
options: {
reset: true
},
files: {
src: ['patternlab-php/public/patterns/**/*.html']
}
},
tvhtml: {
options: {
reset: true
},
files: {
src: ['<%= copy.tvhtml.dest %>/*.html']
}
}
},
Then we set the config to deploy on our different environments.
'ftp-deploy': {
// push patternlab in integration
integ_pl: {
auth: {
host: 'integ.server.ch',
port: 21,
authKey: 'key'
},
src: 'patternlab-php/public',
dest: 'path/intranet13-src/patternlab-php/public',
exclusions: ['**/.DS_Store', '**/Thumbs.db'],
simple: true
},
// push distribution files in integration
integ_dist: {
auth: {
host: 'integ.server.ch',
port: 21,
authKey: 'key'
},
src: '<%= dest %>',
dest: 'path/intranet13-src/<%= dest %>',
exclusions: ['**/.DS_Store', '**/Thumbs.db'],
simple: true
},
// push patternlab in valid
valid_pl: {
auth: {
host: 'valid.server.ch',
port: 21,
authKey: 'key'
},
src: 'patternlab-php/public',
dest: 'path/intranet13-src/patternlab-php/public',
exclusions: ['**/.DS_Store', '**/Thumbs.db'],
simple: true
},
// push distribution files in valid
valid_dist: {
auth: {
host: 'valid.server.ch',
port: 21,
authKey: 'key'
},
src: '<%= dest %>',
dest: 'path/intranet13-src/<%= dest %>',
exclusions: ['**/.DS_Store', '**/Thumbs.db'],
simple: true
},
// push distribution files in valid
valid_dist_config: {
auth: {
host: 'valid.server.ch',
port: 21,
authKey: 'key'
},
src: '<%= copy.config.dest %>',
dest: 'path/intranet13-src/<%= copy.config.dest %>',
exclusions: ['**/.DS_Store', '**/Thumbs.db'],
simple: true
}
},
We set a little watch
to automatically rebuild patternlab when working on it. It execute when a less or pattern file change.
watch: {
less: {
files: ['patternlab-php/source/less/**/*.less'],
tasks: ['clean:css', 'less','shell'],
options: {
livereload: true
},
},
patterns: {
files: ['patternlab-php/source/_patterns/**/*.mustache'],
tasks: ['shell'],
options: {
livereload: true
},
}
}
I'm curently testing to deploy patternlab public
folder in github gh-page
branche with Grunt.