├── .editorconfig
├── .eslintrc
├── .gitignore
├── .travis.yml
├── .verb.md
├── README.md
├── appveyor.yml
├── docs
└── author.md
├── package.json
└── recipes
├── browser-sync
├── README.md
├── content
│ └── page-1.md
├── index.js
├── less
│ ├── default.less
│ ├── typography.less
│ └── variables.less
├── run.js
└── templates
│ └── layouts
│ └── default.hbs
├── collection-basic
├── README.md
├── content
│ ├── articles
│ │ ├── article-1.md
│ │ └── article-2.md
│ └── pages
│ │ ├── page-1.md
│ │ └── page-2.md
├── helpers
│ └── ctx.js
├── index.js
├── index.spec.js
└── templates
│ └── layouts
│ └── default.hbs
├── default-layout
├── README.md
├── content
│ ├── explicit.md
│ └── implicit.md
├── index.js
├── index.spec.js
└── templates
│ └── layouts
│ ├── default.hbs
│ └── the-special-one.hbs
├── drafts
├── README.md
├── content
│ ├── default.md
│ ├── draft-false.md
│ └── draft-true.md
├── index.js
├── index.spec.js
└── plugins
│ └── drafts.js
├── gulp-sitemap
├── README.md
├── assemblefile.js
├── assemblefile.spec.js
├── package.json
└── src
│ ├── layouts
│ └── default.hbs
│ └── pages
│ ├── about.hbs
│ ├── contact.hbs
│ └── index.hbs
├── less
├── README.md
├── index.js
├── index.spec.js
└── less
│ ├── default.less
│ ├── typography.less
│ └── variables.less
├── lib
├── test-utils.js
└── utils.js
├── loading-handlebar-helpers
├── README.md
├── content
│ ├── if_eq.md
│ ├── if_eq_false.md
│ └── test.md
├── helpers
│ ├── if_q.js
│ └── test.js
├── index.js
├── index.spec.js
└── run.js
├── middleware-page-toc
├── README.md
├── content
│ └── article-1.md
├── index.js
├── index.spec.js
├── run.js
└── templates
│ └── layouts
│ └── default.hbs
├── middleware
├── README.md
├── content
│ └── page-1.md
├── index.js
├── index.spec.js
└── run.js
├── permalinks-copy-images
├── README.md
├── content
│ ├── articles
│ │ ├── article-1
│ │ │ ├── README.md
│ │ │ └── images
│ │ │ │ ├── article-1.png
│ │ │ │ └── dot.png
│ │ └── article-2
│ │ │ ├── README.md
│ │ │ └── images
│ │ │ ├── article-2.png
│ │ │ └── dot.png
│ └── posts
│ │ ├── 2016-01-01-post-1
│ │ ├── README.md
│ │ └── images
│ │ │ ├── dot.png
│ │ │ └── post-1.png
│ │ └── 2016-01-02-post-2
│ │ ├── README.md
│ │ └── images
│ │ ├── dot.png
│ │ └── post-2.png
├── index.js
├── index.spec.js
├── run.js
└── templates
│ └── layouts
│ └── index.hbs
├── permalinks-folder-per-file-filebase
├── README.md
├── assemblefile.js
├── content
│ └── articles
│ │ ├── bar.md
│ │ ├── baz.md
│ │ └── foo.md
├── index.spec.js
├── run.js
└── src
│ └── plugins
│ └── index.js
├── permalinks-folder-per-file
├── README.md
├── content
│ ├── folder-1
│ │ ├── a.md
│ │ └── folder-1-1
│ │ │ ├── c.md
│ │ │ └── d.md
│ ├── folder-2
│ │ └── b.md
│ ├── y.md
│ └── z.md
├── index.js
├── index.spec.js
└── run.js
├── permalinks
├── README.md
├── content
│ ├── articles
│ │ ├── article-1
│ │ │ └── README.md
│ │ └── article-2
│ │ │ └── README.md
│ └── posts
│ │ └── post-1
│ │ └── README.md
├── index.js
├── index.spec.js
├── run.js
└── templates
│ └── layouts
│ └── body.hbs
├── visual-studio-integration
├── assemblefile.js
├── bower.json
├── package.json
├── readme.md
└── src
│ ├── assets
│ ├── css
│ │ ├── carousel.css
│ │ ├── ie10-viewport-bug-workaround.css
│ │ └── styles.less
│ ├── images
│ │ └── icon.png
│ └── js
│ │ └── ie10-viewport-bug-workaround.js
│ ├── data
│ └── site.json
│ ├── layouts
│ └── default.hbs
│ └── pages
│ ├── about.hbs
│ ├── contact.hbs
│ └── index.hbs
└── vscode-integration
├── .vscode
└── tasks.json
├── README.md
├── assemblefile.js
└── package.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | end_of_line = lf
9 | insert_final_newline = true
10 |
11 | # 4 tab indentation
12 | [*.*]
13 | indent_style = tab
14 | indent_size = 4
15 |
16 | # 2 space indentation for package.json since this is npm default
17 | [package.json]
18 | indent_style = space
19 | indent_size = 2
20 |
21 | # 2 space indentation for all .yml files
22 | [*.yml]
23 | indent_style = space
24 | indent_size = 2
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "env": {
4 | "es6": false,
5 | "node": true,
6 | "mocha": true
7 | },
8 | "ecmaFeatures": {
9 | "modules": true
10 | },
11 | "globals": {
12 | "chai": false,
13 | "sinon": false,
14 | "expect": false
15 | },
16 | "extends": "eslint:recommended",
17 | "rules": {
18 | "no-console": 0,
19 | "no-alert": 2,
20 | "no-array-constructor": 2,
21 | "no-caller": 2,
22 | "no-catch-shadow": 2,
23 | "no-eval": 2,
24 | "no-extend-native": 2,
25 | "no-extra-bind": 2,
26 | "no-implied-eval": 2,
27 | "no-iterator": 2,
28 | "no-label-var": 2,
29 | "no-labels": 2,
30 | "no-lone-blocks": 2,
31 | "no-loop-func": 2,
32 | "no-multi-spaces": 2,
33 | "no-multi-str": 2,
34 | "no-native-reassign": 2,
35 | "no-new": 2,
36 | "no-new-func": 2,
37 | "no-new-object": 2,
38 | "no-new-wrappers": 2,
39 | "no-octal-escape": 2,
40 | "no-process-exit": 2,
41 | "no-proto": 2,
42 | "no-return-assign": 2,
43 | "no-script-url": 2,
44 | "no-sequences": 2,
45 | "no-shadow": 2,
46 | "no-shadow-restricted-names": 2,
47 | "no-spaced-func": 2,
48 | "no-trailing-spaces": 2,
49 | "no-undef": 2,
50 | "no-undef-init": 2,
51 | "no-underscore-dangle": 2,
52 | "no-unused-expressions": 2,
53 | "no-use-before-define": 2,
54 | "no-with": 2,
55 | "camelcase": 2,
56 | "comma-spacing": 2,
57 | "consistent-return": 2,
58 | "curly": [2, "all"],
59 | "dot-notation": [2, { "allowKeywords": true }],
60 | "eol-last": 2,
61 | "no-extra-parens": [2, "functions"],
62 | "eqeqeq": 2,
63 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }],
64 | "new-cap": [2, {
65 | "capIsNewExceptions": ["Router", "Promise"]
66 | }],
67 | "new-parens": 2,
68 | "quotes": [2, "single"],
69 | "semi": 2,
70 | "semi-spacing": [2, {"before": false, "after": true}],
71 | "space-infix-ops": 2,
72 | "space-in-parens": [2, "always"],
73 | "keyword-spacing": 2,
74 | "space-unary-ops": [2, { "words": true, "nonwords": false }],
75 | "strict": [2, "global"],
76 | "yoda": [2, "never"],
77 | "mocha/no-exclusive-tests": 2
78 | },
79 | "plugins": [
80 | "mocha"
81 | ]
82 | }
83 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vscode/
3 | .DS_Store
4 | node_modules/
5 | npm-debug.log
6 | todo.md
7 | /**/.build
8 | /recipes/**/wwwroot
9 | /recipes/**/bower_components
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - "stable"
5 | - "6"
6 | - "5"
7 | - "4"
8 | - "0.12"
9 | - "0.10"
10 | before_install:
11 | - npm install -g npm@next
12 | matrix:
13 | fast_finish: true
14 | allow_failures:
15 | - node_js: "0.10"
16 | - node_js: "0.12"
17 |
--------------------------------------------------------------------------------
/.verb.md:
--------------------------------------------------------------------------------
1 | # Assemble recipes {%= badge("fury") %} {%= badge("travis") %}
2 |
3 | > {%= description %}
4 |
5 | ## Recipes
6 |
7 | All recipes contain some explanation but also a fully working version of the recipe in the according folder.
8 |
9 | - [Assemble & BrowserSync](recipes/browser-sync)
10 | - [Working with collections](recipes/collection-basic)
11 | - [Default layout](recipes/default-layout)
12 | - [Drafts](recipes/drafts)
13 | - [Gulp sitemap](recipes/gulp-sitemap)
14 | - [Less to CSS](recipes/less)
15 | - [Loading handlebar helpers](recipes/loading-handlebar-helpers)
16 | - [Permalinks](recipes/permalinks)
17 | - [Permalinks - Folder per file](recipes/permalinks-folder-per-file)
18 | - [Permalinks with subfolders/images](recipes/permalinks-copy-images)
19 | - [Events to hook into with middleware](recipes/middleware)
20 | - [Middleware example: Bind TOC to view](recipes/middleware-page-toc)
21 | - [Visual Studio Integration: Basic Bootstrap Site](recipes/visual-studio-integration)
22 | - [VS Code](recipes/vscode-integration)
23 |
24 | ## Running tests
25 | {%= include("tests") %}
26 |
27 | ## Contributing
28 | {%= include("contributing") %}
29 |
30 | ## Author
31 | {%= docs("author") %}
32 |
33 | ## License
34 | {%= copyright() %}
35 | {%= license %}
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Assemble recipes [](https://www.npmjs.com/package/assemble-workshop) [](https://travis-ci.org/Stefan%20Walther/assemble-workshop)
2 |
3 | > Some recipes using assemble v0.16.0.
4 |
5 | ## Recipes
6 |
7 | All recipes contain some explanation but also a fully working version of the recipe in the according folder.
8 |
9 | - [Assemble & BrowserSync](recipes/browser-sync)
10 | - [Working with collections](recipes/collection-basic)
11 | - [Default layout](recipes/default-layout)
12 | - [Drafts](recipes/drafts)
13 | - [Gulp sitemap](recipes/gulp-sitemap)
14 | - [Less to CSS](recipes/less)
15 | - [Loading handlebar helpers](recipes/loading-handlebar-helpers)
16 | - [Permalinks](recipes/permalinks)
17 | - [Permalinks - Folder per file](recipes/permalinks-folder-per-file)
18 | - [Permalinks with subfolders/images](recipes/permalinks-copy-images)
19 | - [Events to hook into with middleware](recipes/middleware)
20 | - [Middleware example: Bind TOC to view](recipes/middleware-page-toc)
21 | - [Visual Studio Integration: Basic Bootstrap Site](recipes/visual-studio-integration)
22 | - [VS Code](recipes/vscode-integration)
23 |
24 | ## Running tests
25 | Install dev dependencies:
26 |
27 | ```sh
28 | $ npm install -d && npm test
29 | ```
30 |
31 | ## Contributing
32 | Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
33 |
34 | ## Author
35 | **Stefan Walther**
36 |
37 | * [qliksite.io](http://qliksite.io)
38 | * [twitter/waltherstefan](http://twitter.com/waltherstefan)
39 | * [github.com/stefanwalther](http://github.com/stefanwalther)
40 |
41 | ## License
42 | Copyright © 2016, Stefan Walther.
43 | Released under the MIT license.
44 |
45 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | # Test against this version of Node.js
2 | environment:
3 | matrix:
4 | # node.js
5 | - nodejs_version: "6.0"
6 | - nodejs_version: "5.0"
7 | - nodejs_version: "4.0"
8 | - nodejs_version: "0.12"
9 | - nodejs_version: "0.10"
10 |
11 | # Configure matrix failures
12 | matrix:
13 | fast_finish: true
14 | allow_failures:
15 | - nodejs_version: "0.12"
16 | - nodejs_version: "0.10"
17 |
18 | # Install scripts. (runs after repo cloning)
19 | install:
20 | # Get the latest stable version of Node.js or io.js
21 | - ps: Install-Product node $env:nodejs_version
22 | # install modules
23 | - npm install
24 |
25 | # Post-install test scripts.
26 | test_script:
27 | # Output useful info for debugging.
28 | - node --version
29 | - npm --version
30 | # run tests
31 | - npm test
32 |
33 | # Don't actually build.
34 | build: off
35 |
--------------------------------------------------------------------------------
/docs/author.md:
--------------------------------------------------------------------------------
1 | **Stefan Walther**
2 |
3 | * [qliksite.io](http://qliksite.io)
4 | * [twitter/waltherstefan](http://twitter.com/waltherstefan)
5 | * [github.com/stefanwalther](http://github.com/stefanwalther)
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "assemble-workshop",
3 | "version": "0.7.3",
4 | "description": "Some recipes using assemble v0.16.0.",
5 | "keywords": [
6 | "assemble",
7 | "demos",
8 | "recipes",
9 | "samples",
10 | "workshop"
11 | ],
12 | "homepage": "https://github.com/assemble/assemble-workshop#readme",
13 | "bugs": {
14 | "url": "https://github.com/assemble/assemble-workshop/issues"
15 | },
16 | "license": "MIT",
17 | "author": {
18 | "name": "Stefan Walther",
19 | "url": "https://github.com/stefanwalther"
20 | },
21 | "main": "",
22 | "repository": {
23 | "type": "git",
24 | "url": "git+https://github.com/assemble/assemble-workshop.git"
25 | },
26 | "scripts": {
27 | "eslint": "node node_modules/eslint/bin/eslint recipes",
28 | "test": "mocha ./recipes/**/*.spec.js"
29 | },
30 | "dependencies": {
31 | "assemble": "github:assemble/assemble",
32 | "assemble-permalinks": "^0.5.0",
33 | "base-watch": "^0.1.3",
34 | "browser-sync": "^2.13.0",
35 | "debug": "^2.2.0",
36 | "del": "^2.2.1",
37 | "export-files": "^2.1.1",
38 | "fs-extra": "^0.30.0",
39 | "glob": "^7.0.5",
40 | "gulp": "^3.9.1",
41 | "gulp-cssnano": "^2.1.2",
42 | "gulp-drafts": "^0.2.0",
43 | "gulp-extname": "^0.2.2",
44 | "gulp-less": "^3.1.0",
45 | "gulp-sitemap": "^4.1.1",
46 | "gulp-sourcemaps": "^1.6.0",
47 | "helper-markdown": "^0.2.1",
48 | "markdown-toc": "^0.12.15",
49 | "slug": "^0.9.1"
50 | },
51 | "devDependencies": {
52 | "chai": "^3.5.0",
53 | "chai-files": "^1.4.0",
54 | "eslint": "^3.1.1",
55 | "eslint-plugin-mocha": "^4.2.0",
56 | "mocha": "^2.5.3",
57 | "sinon": "^1.17.5",
58 | "sinon-chai": "^2.8.0"
59 | },
60 | "engines": {
61 | "node": ">=0.10.0"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/recipes/browser-sync/README.md:
--------------------------------------------------------------------------------
1 | # Assemble and Browser-Sync
2 |
3 | > This recipe uses assemble and [browser-sync](https://www.browsersync.io/) to both serve the files but also update the served files if needed.
4 |
5 | ## Purpose of this recipe
6 | - Convert some .less files to a single style sheet (.css file).
7 | - Convert some markdown files to html output, containing also a link to the generated CSS file.
8 | - Serve the files in the local browser automatically
9 | - Create some watchers on
10 | - all .less files (`./less` folder)
11 | - all content files (`./content` folder
12 | - In case any watcher is triggered, update either the stylesheets or the generated html files.
13 |
14 | **Main file:**
15 | ```js
16 | 'use strict';
17 | var assemble = require( 'assemble' );
18 | var extname = require( 'gulp-extname' );
19 | var less = require( 'gulp-less' );
20 | var browserSync = require( 'browser-sync' ).create();
21 | var path = require( 'path' );
22 |
23 | var app = assemble();
24 |
25 | app.task( 'init', function ( cb ) {
26 | app.helper('markdown', require('helper-markdown'));
27 | app.layouts( './templates/layouts/**/*.hbs' );
28 | cb();
29 | } );
30 |
31 | app.task( 'css', function () {
32 | return app.src( './less/default.less' )
33 | .pipe( less() )
34 | .pipe( app.dest( './.build/css' ) )
35 | .pipe( browserSync.stream() )
36 | } );
37 |
38 | app.task( 'serve', function () {
39 | browserSync.init( {
40 | port: 8080,
41 | startPath: 'page-1.html',
42 | server: {
43 | baseDir: './.build'
44 | }
45 | } )
46 | } );
47 |
48 | app.task( 'content', ['init'], function () {
49 | return app.pages.src( './content/**/*.{md,hbs}' )
50 | .pipe( app.renderFile() )
51 | .on( 'err', console.error )
52 | .pipe( extname() )
53 | .pipe( app.dest( './.build' ) )
54 | .pipe(browserSync.stream());
55 | } );
56 |
57 | app.task( 'default', ['css', 'content', 'serve'], function () {
58 | } );
59 |
60 | app.watch( './content/**/*.md', ['content']);
61 | app.watch( './less/**/*.less', ['css']);
62 |
63 | module.exports = app;
64 | ```
65 |
66 | **less/default.less**
67 | ```css
68 | @import "typography.less";
69 | @import "variables.less";
70 | ```
71 |
72 | **less/typography.less**
73 | ```css
74 | html, body {
75 | font-family: @defaultFont;
76 | color: @mainColor;
77 | }
78 |
79 | h1 {
80 | color: @secondColor;
81 | }
82 | ```
83 |
84 | **less/variables.less**
85 | ```css
86 | @mainColor: #666;
87 | @defaultFont: Arial, "Helvetica Neue", Helvetica, sans-serif;
88 | ```
89 |
90 | **templates/layouts/default.hbs**
91 | ```html
92 |
93 |
94 |
95 |
96 | {{title}}
97 |
98 |
99 |
100 | {{title}}
101 | {{#markdown}}
102 | {% body %}
103 | {{/markdown}}
104 |
105 |
106 | ```
107 |
108 | **content/page-1.md**
109 | ```
110 | ---
111 | title: Page 1
112 | layout: default
113 | ---
114 | This is the content of page 1
115 | ```
116 |
--------------------------------------------------------------------------------
/recipes/browser-sync/content/page-1.md:
--------------------------------------------------------------------------------
1 | title: Page 1
2 | ---
3 | This is the content of page 1
--------------------------------------------------------------------------------
/recipes/browser-sync/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var extname = require( 'gulp-extname' );
4 | var less = require( 'gulp-less' );
5 | var browserSync = require( 'browser-sync' ).create();
6 | var path = require( 'path' );
7 | var watch = require( 'base-watch' );
8 |
9 | var app = assemble();
10 | app.use( watch() );
11 | app.option( 'layout', 'default' );
12 |
13 | app.task( 'init', function ( cb ) {
14 | app.helper( 'markdown', require( 'helper-markdown' ) );
15 | app.layouts( path.join( __dirname, './templates/layouts/**/*.hbs' ) );
16 | cb();
17 | } );
18 |
19 | app.task( 'css', function () {
20 | return app.src( path.join( __dirname, './less/default.less' ) )
21 | .pipe( less() )
22 | .pipe( app.dest( path.join( __dirname, './.build/css' ) ) )
23 | .pipe( browserSync.stream() );
24 | } );
25 |
26 | app.task( 'serve', function () {
27 | browserSync.init( {
28 | port: 8080,
29 | startPath: 'page-1.html',
30 | server: {
31 | baseDir: path.join( __dirname, './.build' )
32 | }
33 | } );
34 | } );
35 |
36 | app.task( 'content', ['init'], function () {
37 | return app.pages.src( path.join( __dirname, './content/**/*.{md,hbs}' ) )
38 | .pipe( app.renderFile() )
39 | .on( 'err', console.error )
40 | .pipe( extname() )
41 | .pipe( app.dest( path.join( __dirname, './.build' ) ) )
42 | .pipe( browserSync.stream() );
43 | } );
44 |
45 | app.task( 'default',
46 | [
47 | 'css',
48 | 'content',
49 | 'serve'
50 | ], function () {
51 | } );
52 |
53 | app.watch( path.join( __dirname, './content/**/*.md' ), ['content'] );
54 | app.watch( path.join( __dirname, './less/**/*.less' ), ['css'] );
55 |
56 | module.exports = app;
57 |
--------------------------------------------------------------------------------
/recipes/browser-sync/less/default.less:
--------------------------------------------------------------------------------
1 | @import "typography.less";
2 | @import "variables.less";
--------------------------------------------------------------------------------
/recipes/browser-sync/less/typography.less:
--------------------------------------------------------------------------------
1 | html, body {
2 | font-family: @defaultFont;
3 | color: @mainColor;
4 | }
5 |
6 | h1 {
7 | color: @secondColor;
8 | }
--------------------------------------------------------------------------------
/recipes/browser-sync/less/variables.less:
--------------------------------------------------------------------------------
1 | @mainColor: #666;
2 | @defaultFont: Arial, "Helvetica Neue", Helvetica, sans-serif;
3 | @secondColor: #333;
--------------------------------------------------------------------------------
/recipes/browser-sync/run.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var app = require( './index' );
3 |
4 | app.build( 'default', function ( err ) {
5 | if ( err ) {
6 | console.error( 'ERROR', err );
7 | }
8 | } );
9 |
--------------------------------------------------------------------------------
/recipes/browser-sync/templates/layouts/default.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{title}}
6 |
7 |
8 |
9 | {{title}}
10 | {{#markdown}}
11 | {% body %}
12 | {{/markdown}}
13 |
14 |
--------------------------------------------------------------------------------
/recipes/collection-basic/README.md:
--------------------------------------------------------------------------------
1 | ## Working with collections
2 |
3 | **Purpose of this recipe**
4 |
5 | - Create a two collections, `articles` and `pages`
6 | - Render each file in the collections
7 | - Make the collections available for all files
8 | - Create a list in each file, containing a list using the own and the other collection ("List of all pages", "List of all articles")
--------------------------------------------------------------------------------
/recipes/collection-basic/content/articles/article-1.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Article 1
3 | abstract: "This is the abstract of article 1"
4 | layout: default
5 | ---
6 | This is {{title}}
--------------------------------------------------------------------------------
/recipes/collection-basic/content/articles/article-2.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Article 2
3 | abstract: "This is the abstract of article 2"
4 | layout: default
5 | ---
6 | This is {{title}}
--------------------------------------------------------------------------------
/recipes/collection-basic/content/pages/page-1.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Page 1
3 | abstract: "This is the abstract of page 1"
4 | layout: default
5 | ---
6 | This is {{title}}
--------------------------------------------------------------------------------
/recipes/collection-basic/content/pages/page-2.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Page 2
3 | abstract: "This is the abstract of page 2"
4 | layout: default
5 | ---
6 | This is {{title}}
--------------------------------------------------------------------------------
/recipes/collection-basic/helpers/ctx.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function ( context ) {
4 | console.log( '------------------------------------------------------' );
5 | console.info( 'ARGUMENTS:' );
6 | console.log( arguments );
7 | console.log( '------------------------------------------------------' );
8 | console.info( 'CONTEXT:' );
9 | console.log( context ); // the object passed to the helper
10 | console.log( '------------------------------------------------------' );
11 | console.info( 'CONTEXT.HASH:' );
12 | console.log( context.hash ); // hash arguments, like `foo='bar'`
13 | console.log( '------------------------------------------------------' );
14 | console.info( 'THIS:' );
15 | console.log( this ); // handlebars context
16 | console.log( '------------------------------------------------------' );
17 | console.info( 'THIS.OPTIONS:' );
18 | console.log( this.options ); // assemble `options`
19 | console.log( '------------------------------------------------------' );
20 | console.info( 'THIS.CONTEXT:' );
21 | console.log( this.context ); // context of the current 'view'
22 | console.log( '------------------------------------------------------' );
23 | console.info( 'THIS.APP:' );
24 | console.log( this.app ); // assemble instance
25 | };
26 |
--------------------------------------------------------------------------------
/recipes/collection-basic/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var extname = require( 'gulp-extname' );
4 | var path = require( 'path' );
5 |
6 | var app = assemble();
7 |
8 | app.create( 'articles' );
9 | // No need to create the collection pages; `pages` is a default collection in assemble
10 |
11 | app.task( 'init', function ( cb ) {
12 | app.helper( 'ctx', path.join( __dirname, './helpers/ctx.js' ) );
13 | app.layouts( path.join( __dirname, './templates/layouts/*.hbs' ) );
14 | app.articles( path.join( __dirname, './content/articles/**/*.{md,hbs}' ) );
15 | app.pages( path.join( __dirname, './content/pages/**/*.{md,hbs}' ) );
16 | cb();
17 | } );
18 |
19 | app.preRender( /./, function ( view, next ) {
20 | view.data.articles = app.views.articles;
21 | view.data.pages = app.views.pages;
22 | next();
23 | } );
24 |
25 | app.task( 'content:articles', ['init'], function () {
26 | return app.toStream( 'articles' )
27 | .on( 'err', console.error )
28 | .pipe( app.renderFile() )
29 | .on( 'err', console.error )
30 | .pipe( extname() )
31 | .pipe( app.dest( path.join( __dirname, './.build' ) ) );
32 | } );
33 |
34 | app.task( 'content:pages', ['init'], function () {
35 | return app.toStream( 'pages' )
36 | .on( 'err', console.error )
37 | .pipe( app.renderFile() )
38 | .on( 'err', console.error )
39 | .pipe( extname() )
40 | .pipe( app.dest( path.join( __dirname, './.build' ) ) );
41 | } );
42 |
43 | app.task( 'default', ['content:articles', 'content:pages'] );
44 |
45 | module.exports = app;
46 |
--------------------------------------------------------------------------------
/recipes/collection-basic/index.spec.js:
--------------------------------------------------------------------------------
1 | /*global require*/
2 | /*eslint no-unused-expressions:0*/
3 | 'use strict';
4 | var chai = require( 'chai' );
5 | var expect = chai.expect;
6 | var path = require( 'path' );
7 | var chaiFiles = require( 'chai-files' );
8 | var utils = require( './../lib/test-utils' );
9 |
10 | chai.use( chaiFiles );
11 |
12 | var file = chaiFiles.file;
13 | var app = require( './index' );
14 |
15 | describe( 'Collection Basic', function () {
16 |
17 | var delPath = path.join( __dirname, './.build' );
18 |
19 | beforeEach( function ( cb ) {
20 | utils.clean( delPath, cb );
21 | } );
22 |
23 | afterEach( function ( cb ) {
24 | utils.clean( delPath, cb );
25 | } );
26 |
27 | // Skipping test for now, getting the following error: "Uncaught Error: no writecb in Transform class"
28 | xit( 'should succeed', function ( done ) {
29 | app.build( ['default'], function ( err ) {
30 |
31 | expect( err ).to.not.exist;
32 |
33 | var filePath = path.join( __dirname, './.build/article-1.html' );
34 | expect( file( filePath ) ).to.exist;
35 | expect( file( filePath ) ).to.contain( 'This is the abstract of article 1' );
36 |
37 | filePath = path.join( __dirname, './.build/article-2.html' );
38 | expect( file( filePath ) ).to.exist;
39 |
40 | filePath = path.join( __dirname, './.build/page-1.html' );
41 | expect( file( filePath ) ).to.exist;
42 |
43 | filePath = path.join( __dirname, './.build/page-2.html' );
44 | expect( file( filePath ) ).to.exist;
45 |
46 | // Just a negative test to ensure that assertion works correctly.
47 | expect( file( path.join( __dirname, './.build/page-3.html' ) ) ).to.not.exist;
48 | done();
49 | } );
50 | } );
51 | } );
52 |
--------------------------------------------------------------------------------
/recipes/collection-basic/templates/layouts/default.hbs:
--------------------------------------------------------------------------------
1 | # {{title}}
2 |
3 | {% body %}
4 |
5 | ---
6 |
7 | {{abstract}}
8 |
9 | ---
10 | All articles:
11 |
12 | {{#each articles}}
13 | {{data.title}} - {{data.abstract}}
14 | {{/each}}
15 |
16 |
17 | All pages:
18 |
19 | {{#each pages}}
20 | {{data.title}} - {{data.abstract}}
21 | {{/each}}
22 |
23 |
--------------------------------------------------------------------------------
/recipes/default-layout/README.md:
--------------------------------------------------------------------------------
1 | ## Default layout
2 |
3 | > This recipe demonstrates how to define or force a default layout.
4 |
5 | **Setting the layout manually:**
6 |
7 | The layout for each document can be set in the front matter yml:
8 |
9 | ```
10 | ---
11 | title: Some amazing title
12 | layout: whatever-layout
13 | ---
14 | ```
15 |
16 | **Defining a default layout:**
17 |
18 | If you want to define a default layout for the entire app, first set the global option `layout`:
19 |
20 | ```
21 | app.option('layout', 'whatever-layout');
22 | ```
23 |
24 | Then use some middleware to set the default layout if not explicitly defined in the current document:
25 |
26 | ```js
27 | app.preLayout( /./, function ( view, next ) {
28 | // if the layout is not defined, use the default one ...
29 | if (!view.layout && app.options.layout) {
30 | view.layout = app.options.layout;
31 | }
32 | next();
33 | } );
34 | ```
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/recipes/default-layout/content/explicit.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Explicit
3 | layout: the-special-one
4 | ---
5 | {{title}}
--------------------------------------------------------------------------------
/recipes/default-layout/content/implicit.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Implicit
3 | ---
4 | {{title}}
--------------------------------------------------------------------------------
/recipes/default-layout/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var path = require( 'path' );
4 |
5 | var app = assemble();
6 |
7 | app.option( 'layout', 'the-special-one' );
8 | app.preLayout( /./, function ( view, next ) {
9 | // if the layout is not defined, use the default one ...
10 | if ( !view.layout && app.options.layout ) {
11 | view.layout = app.options.layout;
12 | }
13 | next();
14 | } );
15 |
16 | app.task( 'init', function ( cb ) {
17 | app.helper( 'markdown', require( 'helper-markdown' ) );
18 | app.layouts( path.join( __dirname, './templates/layouts/**/*.hbs' ) );
19 | cb();
20 | } );
21 |
22 | app.task( 'default', ['init'], function () {
23 | return app.pages.src( path.join( __dirname, './content/**/*.{md,hbs}' ) )
24 | .pipe( app.renderFile() )
25 | .pipe( app.dest( path.join( __dirname, './.build' ) ) );
26 | } );
27 |
28 | module.exports = app;
29 |
30 |
31 |
--------------------------------------------------------------------------------
/recipes/default-layout/index.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var path = require( 'path' );
6 | var chaiFiles = require( 'chai-files' );
7 | var utils = require( './../lib/test-utils' );
8 |
9 | chai.use( chaiFiles );
10 | var file = chaiFiles.file;
11 | var app = require( './index' );
12 |
13 | describe( 'default-layout', function () {
14 |
15 | var delPath = path.join( __dirname, './.build' );
16 | beforeEach( function ( cb ) {
17 | utils.clean( delPath, cb );
18 | } );
19 | afterEach( function ( cb ) {
20 | utils.clean( delPath, cb );
21 | } );
22 |
23 | it( 'should be effective', function ( done ) {
24 | app.build( 'default', function ( err ) {
25 | expect( err ).to.not.exist;
26 | expect( file( path.join( __dirname, './.build/explicit.md' ) ) ).to.match( /This is the special layout/ );
27 | expect( file( path.join( __dirname, './.build/implicit.md' ) ) ).to.match( /This is the special layout/ );
28 | done();
29 | } );
30 | } );
31 | } );
32 |
--------------------------------------------------------------------------------
/recipes/default-layout/templates/layouts/default.hbs:
--------------------------------------------------------------------------------
1 | The default layout.
2 |
3 | {% body %}
--------------------------------------------------------------------------------
/recipes/default-layout/templates/layouts/the-special-one.hbs:
--------------------------------------------------------------------------------
1 | This is the special layout.
2 |
3 | {% body %}
--------------------------------------------------------------------------------
/recipes/drafts/README.md:
--------------------------------------------------------------------------------
1 | ## Working with drafts
2 |
3 | Two different approaches are used in this recipe:
4 |
5 | - Using the plugin `gulp-drafts`
6 | - Using a custom plugin (`./templates/plugins/drafts.js`
7 |
8 | ### Usage
9 |
10 | - Mark documents in the front matter as draft to prevent them from being rendered.
11 |
--------------------------------------------------------------------------------
/recipes/drafts/content/default.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Default
3 | ---
4 | {{title}}
--------------------------------------------------------------------------------
/recipes/drafts/content/draft-false.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Draft false
3 | draft: false
4 | ---
5 | {{title}}
--------------------------------------------------------------------------------
/recipes/drafts/content/draft-true.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Draft true
3 | draft: true
4 | ---
5 | {{title}}
--------------------------------------------------------------------------------
/recipes/drafts/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var path = require( 'path' );
4 | var gulpDrafts = require( 'gulp-drafts' );
5 | var pluginDrafts = require( './plugins/drafts' );
6 | var app = assemble();
7 |
8 | var paths = {
9 | srcDir: path.join( __dirname, './content/**/*.{md,hbs}' ),
10 | buildDir: path.join( __dirname, './.build' )
11 | };
12 |
13 | app.pages( paths.srcDir );
14 |
15 | app.task( 'gulp-draft', function () {
16 | return app.pages.toStream()
17 | .on( 'err', console.error )
18 | .pipe( gulpDrafts() )
19 | .pipe( app.renderFile() )
20 | .on( 'err', console.error )
21 | .pipe( app.dest( paths.buildDir ) );
22 | } );
23 |
24 | app.task( 'draft-plugin', function () {
25 |
26 | app.use( pluginDrafts( 'pages' ) );
27 |
28 | return app.pages.toStream()
29 | .on( 'error', console.error )
30 | .pipe( app.renderFile() )
31 | .on( 'error', console.error )
32 | .pipe( app.dest( paths.buildDir ) );
33 |
34 | } );
35 |
36 | module.exports = app;
37 |
--------------------------------------------------------------------------------
/recipes/drafts/index.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var path = require( 'path' );
6 | var chaiFiles = require( 'chai-files' );
7 | var utils = require( './../lib/test-utils' );
8 |
9 | chai.use( chaiFiles );
10 | var file = chaiFiles.file;
11 | var app = require( './index' );
12 |
13 | describe( 'drafts', function () {
14 |
15 | var delPath = path.join( __dirname, './.build' );
16 | beforeEach( function ( cb ) {
17 | utils.clean( delPath, cb );
18 | } );
19 | afterEach( function ( cb ) {
20 | utils.clean( delPath, cb );
21 | } );
22 |
23 | it( 'using gulp-drafts: renders only non-draft files.', function ( done ) {
24 | app.build( 'gulp-draft', function ( err ) {
25 | expect( err ).to.not.exist;
26 | expect( file( path.join( __dirname, './.build/default.md' ) ) ).to.contain( 'Default' );
27 | expect( file( path.join( __dirname, './.build/draft-false.md' ) ) ).to.contain( 'Draft false' );
28 | done();
29 | } );
30 | } );
31 |
32 | it( 'using custom draft-plugin: renders only non-draft files.', function ( done ) {
33 | app.build( 'draft-plugin', function ( err ) {
34 | expect( err ).to.not.exist;
35 | expect( file( path.join( __dirname, './.build/default.md' ) ) ).to.contain( 'Default' );
36 | expect( file( path.join( __dirname, './.build/draft-false.md' ) ) ).to.contain( 'Draft false' );
37 | done();
38 | } );
39 | } );
40 | } );
41 |
--------------------------------------------------------------------------------
/recipes/drafts/plugins/drafts.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * Expose `plugin`.
4 | */
5 |
6 | /**
7 | * Assemble plugin to remove files marked as `draft` from a collection.
8 | *
9 | * @return {Function}
10 | */
11 | module.exports = function plugin ( name ) {
12 | return function ( app ) {
13 | var files = app.getViews( name );
14 | for ( var file in files ) {
15 | if ( files[file].data.draft ) {
16 | delete files[file];
17 | }
18 | }
19 | };
20 | };
21 |
--------------------------------------------------------------------------------
/recipes/gulp-sitemap/README.md:
--------------------------------------------------------------------------------
1 | # Gulp Sitemap
2 |
3 | > Generate a sitemap for your assemble generated site.
4 |
5 | ## Generate some pages
6 |
7 | Here is a simple example of generating some html files from handle bars (.hbs) files.
8 |
9 | ```js
10 |
11 | 'use strict';
12 |
13 | var app = require('assemble')();
14 | var path = require('path');
15 | var ext = require('gulp-extname');
16 |
17 | app.option('layout', 'default');
18 | app.layouts(path.join(__dirname, 'src/layouts/**/*.hbs'));
19 |
20 | app.task('default', function () {
21 |
22 | //Here we are using a gulp plugin to replace the .hbs ext with .html for all the pages.
23 | return app.src('src/pages/**/*.hbs', { layout: 'default' })
24 | .pipe(app.renderFile())
25 | .pipe(ext()))
26 | .pipe(app.dest('wwwroot'));
27 | });
28 |
29 | module.exports = app;
30 |
31 | ```
32 |
33 | ## Generate a sitemap files
34 |
35 | Now that we have some html files generated, we need to include a sitemap for the bots.
36 | This can be done easily using a gulp plugin. This is possible beacause assemble supports
37 | can use any gulp plugin. So, we simply add the
38 | [gulp-sitemap](https://www.npmjs.com/package/gulp-sitemap) plugin,
39 | configure it will the sites base url and configure the tasks so that
40 | the sitemap is created after the pages generated.
41 |
42 | ```js
43 |
44 | 'use strict';
45 |
46 | var app = require('assemble')();
47 | var path = require('path');
48 | var ext = require('gulp-extname');
49 | var sitemap = require('gulp-sitemap');
50 |
51 | app.option('layout', 'default');
52 | app.layouts(path.join(__dirname, 'src/layouts/**/*.hbs'));
53 |
54 | app.task('pages', function () {
55 |
56 | //Here we are using a gulp plugin to replace the .hbs ext with .html for all the pages.
57 | return app.src('src/pages/**/*.hbs', { layout: 'default' })
58 | .pipe(app.renderFile())
59 | .pipe(ext())
60 | .pipe(app.dest('wwwroot'));
61 | });
62 |
63 |
64 | app.task('default', ['pages'], function () {
65 |
66 | //Here we are using a gulp plugin to generate a sitemap for the files generated by the pages task.
67 | return app.src('wwwroot/**/*.html')
68 | .pipe(sitemap({
69 | siteUrl: 'http://whatever.site'
70 | }))
71 | .pipe(app.dest('wwwroot'));
72 | });
73 |
74 |
75 | module.exports = app;
76 |
77 | ```
--------------------------------------------------------------------------------
/recipes/gulp-sitemap/assemblefile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var app = require('assemble')();
4 | var path = require('path');
5 | var ext = require('gulp-extname');
6 | var sitemap = require('gulp-sitemap');
7 |
8 | app.option('layout', 'default');
9 | app.layouts(path.join(__dirname, 'src/layouts/**/*.hbs'));
10 |
11 | app.task('pages', function () {
12 |
13 | //Here we are using a gulp plugin to replace the .hbs ext with .html for all the pages.
14 | return app.src(path.join(__dirname, 'src/pages/**/*.hbs'), { layout: 'default' })
15 | .pipe(app.renderFile())
16 | .pipe(ext())
17 | .pipe(app.dest(path.join(__dirname, 'wwwroot')));
18 | });
19 |
20 |
21 | app.task('default', ['pages'], function () {
22 |
23 | //Here we are using a gulp plugin to generate a sitemap for the files generated by the pages task.
24 | return app.src(path.join(__dirname, 'wwwroot/**/*.html'))
25 | .pipe(sitemap({
26 | siteUrl: 'http://whatever.site'
27 | }))
28 | .pipe(app.dest(path.join(__dirname, 'wwwroot')));
29 | });
30 |
31 |
32 | module.exports = app;
--------------------------------------------------------------------------------
/recipes/gulp-sitemap/assemblefile.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var path = require( 'path' );
6 | var chaiFiles = require( 'chai-files' );
7 | var utils = require( './../lib/test-utils' );
8 |
9 | chai.use( chaiFiles );
10 | var file = chaiFiles.file;
11 | var app = require( './assemblefile' );
12 |
13 | describe( 'Gulp-sitemap using Assemble', function () {
14 |
15 | var delPath = path.join( __dirname, './wwwroot' );
16 | beforeEach( function ( cb ) {
17 | utils.clean( delPath, cb );
18 | } );
19 | afterEach( function ( cb ) {
20 | utils.clean( delPath, cb );
21 | } );
22 |
23 | it( 'creates a three html files from hbs files in src/pages', function ( done ) {
24 | app.build( 'pages', function ( err ) {
25 | expect( err ).to.not.exist;
26 | expect( file ( path.join( __dirname, './wwwroot/index.html' ) ) ).to.exist;
27 | expect( file ( path.join( __dirname, './wwwroot/about.html' ) ) ).to.exist;
28 | expect( file ( path.join( __dirname, './wwwroot/contact.html' ) ) ).to.exist
29 | done();
30 | } );
31 | } );
32 |
33 | it( 'creates a stemap.xml file', function ( done ) {
34 | app.build( 'default', function ( err ) {
35 | expect( err ).to.not.exist;
36 |
37 | var p = path.join( __dirname, './wwwroot/sitemap.xml' );
38 | expect( file ( p ) ).to.exist;
39 | expect( file ( p ) ).to.match( /urlset/ );
40 | done();
41 | } );
42 | } );
43 | } );
44 |
--------------------------------------------------------------------------------
/recipes/gulp-sitemap/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "assemble-site-template",
3 | "version": "1.0.0",
4 | "description": "",
5 | "devDependencies": {
6 | "assemble": "^0.12.0",
7 | "gulp": "^3.9.1",
8 | "gulp-extname" : "^0.2.2",
9 | "gulp-sitemap": "^4.1.1"
10 | },
11 | "author": "ITLackey",
12 | "license": "ISC"
13 | }
14 |
--------------------------------------------------------------------------------
/recipes/gulp-sitemap/src/layouts/default.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 | {% body %}
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/recipes/gulp-sitemap/src/pages/about.hbs:
--------------------------------------------------------------------------------
1 | ---
2 | title: About
3 | layout: default
4 | ---
5 | About page
--------------------------------------------------------------------------------
/recipes/gulp-sitemap/src/pages/contact.hbs:
--------------------------------------------------------------------------------
1 | ---
2 | title: Contact Us
3 | layout: default
4 | ---
5 | Contact page
--------------------------------------------------------------------------------
/recipes/gulp-sitemap/src/pages/index.hbs:
--------------------------------------------------------------------------------
1 | ---
2 | title: Home
3 | layout: default
4 | ---
5 | Home page
--------------------------------------------------------------------------------
/recipes/less/README.md:
--------------------------------------------------------------------------------
1 | # Less to CSS
2 |
3 | > Convert your .less files to .css files using assemble and several Gulp plugins.
4 |
5 | ## Convert from .less to .css
6 |
7 | The beauty of assemble is that you can use any Gulp plugin. So converting .less files to .css files is pretty easy using [gulp-less](https://www.npmjs.com/package/gulp-less):
8 |
9 | ```js
10 | var assemble = require( 'assemble' );
11 | var less = require( 'gulp-less' );
12 | var path = require( 'path' );
13 |
14 | var app = assemble();
15 |
16 | app.task( 'css', function () {
17 | return app.src( './less/default.less' )
18 | .pipe( less() )
19 | .pipe( app.dest( './.build/css' ) );
20 | } );
21 |
22 | module.exports = app;
23 | ```
24 |
25 | ## Minification & Source Maps
26 |
27 | Based on the logic from above, let's use another two Gulp plugins to minify the css ([gulp-cssnano](https://www.npmjs.com/package/gulp-cssnano)) and to add source map support ([gulp-sourcemaps](https://www.npmjs.com/package/gulp-sourcemaps)):
28 |
29 | ```js
30 | var assemble = require( 'assemble' );
31 | var less = require( 'gulp-less' );
32 | var path = require( 'path' );
33 | var nano = require( 'gulp-cssnano' );
34 | var sourceMaps = require( 'gulp-sourcemaps' );
35 |
36 | var app = assemble();
37 |
38 | app.task( 'css:optimized', function () {
39 |
40 | var lessOptions = {};
41 | var nanoOptions = {};
42 |
43 | return app.src( './less/default.less' )
44 | .pipe( sourceMaps.init() )
45 | .pipe( less( lessOptions ) )
46 | .pipe( nano( nanoOptions ) )
47 | .pipe( sourceMaps.write() )
48 | .pipe( app.dest( './.build/css' ) );
49 | } );
50 |
51 | module.exports = app;
52 |
53 | ```
54 |
--------------------------------------------------------------------------------
/recipes/less/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var less = require( 'gulp-less' );
4 | var path = require( 'path' );
5 | var nano = require( 'gulp-cssnano' );
6 | var sourceMaps = require( 'gulp-sourcemaps' );
7 |
8 | var app = assemble();
9 |
10 | app.task( 'css', function () {
11 | return app.src( path.join( __dirname, './less/default.less' ) )
12 | .pipe( less() )
13 | .pipe( app.dest( path.join( __dirname, './.build/css' ) ) );
14 | } );
15 |
16 | app.task( 'css:optimized', function () {
17 |
18 | // http://lesscss.org/#using-less-configuration
19 | var lessOptions = {
20 | compress: false // Let's cssnano do the job.
21 | };
22 |
23 | // http://cssnano.co/optimisations/
24 | var nanoOptions = {
25 | autoprefixer: false
26 | };
27 |
28 | return app.src( path.join( __dirname, './less/default.less' ) )
29 | .pipe( sourceMaps.init() )
30 | .pipe( less( lessOptions ) )
31 | .pipe( nano( nanoOptions ) )
32 | .pipe( sourceMaps.write() )
33 | .pipe( app.dest( path.join( __dirname, './.build/css' ) ) );
34 | } );
35 |
36 | module.exports = app;
37 |
--------------------------------------------------------------------------------
/recipes/less/index.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var path = require( 'path' );
6 | var chaiFiles = require( 'chai-files' );
7 | var utils = require( './../lib/test-utils' );
8 |
9 | chai.use( chaiFiles );
10 | var file = chaiFiles.file;
11 | var app = require( './index' );
12 |
13 | describe( 'Less to css', function () {
14 |
15 | var delPath = path.join( __dirname, './.build' );
16 | beforeEach( function ( cb ) {
17 | utils.clean( delPath, cb );
18 | } );
19 | afterEach( function ( cb ) {
20 | utils.clean( delPath, cb );
21 | } );
22 |
23 | it( 'creates a single file, merged from multiple less files', function ( done ) {
24 | app.build( 'css', function ( err ) {
25 | expect( err ).to.not.exist;
26 | expect( file( path.join( __dirname, './.build/css/default.css' ) ) ).to.exist;
27 | expect( file( path.join( __dirname, './.build/css/typography.css' ) ) ).to.not.exist;
28 | expect( file( path.join( __dirname, './.build/variables.css' ) ) ).to.not.exist;
29 | done();
30 | } );
31 | } );
32 |
33 | it( 'creates a single file, minifies and includes sourcemap', function ( done ) {
34 | app.build( 'css:optimized', function ( err ) {
35 | expect( err ).to.not.exist;
36 | var p = path.join( __dirname, './.build/css/default.css' );
37 | expect( file( p ) ).to.exist;
38 | expect( file( p ) ).to.match( /sourceMappingURL/ );
39 | expect( file( p ) ).to.match( /body,html\{font-family:Arial,Helvetica Neue,Helvetica,sans-serif;color:#666}h1\{color:#333}/ );
40 |
41 | expect( file( path.join( __dirname, './.build/css/typography.css' ) ) ).to.not.exist;
42 | expect( file( path.join( __dirname, './.build/variables.css' ) ) ).to.not.exist;
43 | done();
44 | } );
45 | } );
46 | } );
47 |
--------------------------------------------------------------------------------
/recipes/less/less/default.less:
--------------------------------------------------------------------------------
1 | @import "typography.less";
2 | @import "variables.less";
--------------------------------------------------------------------------------
/recipes/less/less/typography.less:
--------------------------------------------------------------------------------
1 | html, body {
2 | font-family: @defaultFont;
3 | color: @mainColor;
4 | }
5 |
6 | h1 {
7 | color: @secondColor;
8 | }
--------------------------------------------------------------------------------
/recipes/less/less/variables.less:
--------------------------------------------------------------------------------
1 | @mainColor: #666;
2 | @defaultFont: Arial, "Helvetica Neue", Helvetica, sans-serif;
3 | @secondColor: #333;
--------------------------------------------------------------------------------
/recipes/lib/test-utils.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var del = require( 'del' );
3 |
4 | function clean ( delPath, cb ) {
5 | del( delPath )
6 | .then( function () {
7 | cb();
8 | } );
9 | }
10 |
11 | module.exports.clean = clean;
12 |
--------------------------------------------------------------------------------
/recipes/lib/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var path = require( 'path' );
3 |
4 | module.exports = {
5 | stripExtension: function ( filepath, ext ) {
6 | ext = ext || path.extname( filepath );
7 | var r = filepath.slice( 0, filepath.length - ext.length );
8 | console.log( r );
9 | return r;
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/recipes/loading-handlebar-helpers/README.md:
--------------------------------------------------------------------------------
1 | ## Loading handlebar helpers
2 |
3 | Example how to define and load handlebar helpers:
4 |
5 | ```js
6 | app.helpers( './helpers/*.js' );
7 | ```
8 |
--------------------------------------------------------------------------------
/recipes/loading-handlebar-helpers/content/if_eq.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: if_q
3 | ---
4 | {{#if_q "a" "a"}}
5 | a==a
6 | {{/if_q}}
7 |
--------------------------------------------------------------------------------
/recipes/loading-handlebar-helpers/content/if_eq_false.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: if_q
3 | ---
4 | {{#if_q "a" "b"}}
5 | a==a
6 | {{else}}
7 | a!=b
8 | {{/if_q}}
9 |
--------------------------------------------------------------------------------
/recipes/loading-handlebar-helpers/content/test.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Content 1
3 | ---
4 | {{test}}
5 |
--------------------------------------------------------------------------------
/recipes/loading-handlebar-helpers/helpers/if_q.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /*eslint camelcase: 0*/
4 | module.exports = function if_q ( a, b, opts ) {
5 |
6 | if ( a === b ) {
7 | return opts.fn( this );
8 | } else {
9 | return opts.inverse( this );
10 | }
11 |
12 | };
13 |
--------------------------------------------------------------------------------
/recipes/loading-handlebar-helpers/helpers/test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function test( /*opts*/ ) {
4 |
5 | return 'This is a test';
6 |
7 | };
8 |
9 |
--------------------------------------------------------------------------------
/recipes/loading-handlebar-helpers/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var path = require( 'path' );
4 |
5 | var app = assemble();
6 |
7 | app.helpers( path.join( __dirname, './helpers/*.js' ) );
8 |
9 | app.task( 'default', function () {
10 | return app.pages.src( path.join( __dirname, './content/**/*.{md,hbs}' ) )
11 | .pipe( app.renderFile() )
12 | .pipe( app.dest( path.join( __dirname, './.build' ) ) );
13 | } );
14 |
15 | module.exports = app;
16 |
17 |
--------------------------------------------------------------------------------
/recipes/loading-handlebar-helpers/index.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var chaiFiles = require( 'chai-files' );
6 | var path = require( 'path' );
7 | var del = require( 'del' );
8 |
9 | chai.use( chaiFiles );
10 | var file = chaiFiles.file;
11 | var app = require( './index' );
12 |
13 | describe( 'Helper', function () {
14 |
15 | after( function ( done ) {
16 | del( path.join( __dirname, './.build' ) )
17 | .then( function () {
18 | done();
19 | } );
20 | //done();
21 | } );
22 |
23 | it( ' should resolve properly', function ( done ) {
24 | app.build( 'default', function ( err ) {
25 | expect( err ).to.not.exist;
26 | expect( file( path.join( __dirname, './.build/test.md' ) ) ).to.match( /This is a test/ );
27 | done();
28 | } );
29 | } );
30 |
31 | it( ' should resolve properly if condition is true', function ( done ) {
32 | app.build( 'default', function ( err ) {
33 | expect( err ).to.not.exist;
34 | expect( file( path.join( __dirname, './.build/if_eq.md' ) ) ).to.match( /a==a/ );
35 | done();
36 | } );
37 | } );
38 |
39 | it( ' should resolve properly if condition is false', function ( done ) {
40 | app.build( 'default', function ( err ) {
41 | expect( err ).to.not.exist;
42 | expect( file( path.join( __dirname, './.build/if_eq_false.md' ) ) ).to.match( /a!=b/ );
43 | done();
44 | } );
45 | } );
46 |
47 | } );
48 |
--------------------------------------------------------------------------------
/recipes/loading-handlebar-helpers/run.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var app = require( './index' );
3 |
4 | app.build( ['default'], function ( err ) {
5 | if ( err ) {
6 | console.error( 'ERROR: ', err );
7 | }
8 | } );
9 |
--------------------------------------------------------------------------------
/recipes/middleware-page-toc/README.md:
--------------------------------------------------------------------------------
1 | # Middleware to bind toc to view
2 |
3 | This recipe uses a middleware and markdown-toc to bind a table of contents to the view and then uses this data in the layout to render a specific table of contents.
--------------------------------------------------------------------------------
/recipes/middleware-page-toc/content/article-1.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Article 1
3 | layout: default
4 | ---
5 |
6 | # Heading 1
7 |
8 | ## Heading 1.1
9 |
10 | # Heading 2
11 |
12 | ## Heading 2.1
13 |
14 | ## Heading 2.2
15 |
16 | ### Heading 2.2.1
17 |
18 | ### Heading 2.2.2
19 |
20 | ## Heading 2.3
21 |
--------------------------------------------------------------------------------
/recipes/middleware-page-toc/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var extname = require( 'gulp-extname' );
4 | var toc = require( 'markdown-toc' );
5 | var path = require( 'path' );
6 |
7 | var app = assemble();
8 |
9 | app.pages( path.join( __dirname, './content/**/*.{md,hbs}' ) );
10 | app.layouts( path.join( __dirname, './templates/layouts/**/*.hbs' ) );
11 | /**
12 | * Bind an object called `toc` to each view containing the table of contents using markdown-toc.
13 | */
14 | app.preRender( /\.md/, function ( view, next ) {
15 | view.data.toc = toc( view._content ).json; //eslint-disable-line
16 | next();
17 | } );
18 |
19 | app.helper( 'markdown', require( 'helper-markdown' ) );
20 |
21 | /**
22 | * Set the default layout for files with the extension .md or .hbs.
23 | */
24 | app.preLayout( /\/content\/.*\.(md|hbs)/, function ( view, next ) {
25 | if ( !view.layout ) {
26 | view.layout = 'default';
27 | }
28 | next();
29 | } );
30 |
31 | app.task( 'default', function () {
32 | return app.toStream( 'pages' )
33 | .pipe( app.renderFile() )
34 | .on( 'error', console.error )
35 | .pipe( extname() )
36 | .pipe( app.dest( path.join( __dirname, './.build' ) ) );
37 | } );
38 |
39 | module.exports = app;
40 |
--------------------------------------------------------------------------------
/recipes/middleware-page-toc/index.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var path = require( 'path' );
6 | var utils = require( './../lib/test-utils' );
7 |
8 | var app = require( './index' );
9 |
10 | describe( 'Plugin Page-TOC', function () {
11 |
12 | var delPath = path.join( __dirname, './.build' );
13 | beforeEach( function ( cb ) {
14 | utils.clean( delPath, cb );
15 | } );
16 | afterEach( function ( cb ) {
17 | utils.clean( delPath, cb );
18 | } );
19 |
20 | it( 'should succeed', function ( done ) {
21 | app.build( 'default', function ( err ) {
22 | expect( err ).to.not.exist;
23 | expect( app.pages.getView( path.join( __dirname, './content/article-1.md' ) ) ).to.exist;
24 | expect( app.pages.getView( path.join( __dirname, './content/article-1.md' ) ).data ).to.have.property( 'toc' );
25 | expect( app.pages.getView( path.join( __dirname, './content/article-1.md' ) ).data.toc[0] ).to.have.property( 'slug' );
26 | done();
27 | } );
28 | } );
29 | } );
30 |
--------------------------------------------------------------------------------
/recipes/middleware-page-toc/run.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var app = require( './index' );
3 |
4 | app.build( ['default'], function ( err ) {
5 | if ( err ) {
6 | console.error( 'ERROR: ', err );
7 | }
8 | } );
9 |
--------------------------------------------------------------------------------
/recipes/middleware-page-toc/templates/layouts/default.hbs:
--------------------------------------------------------------------------------
1 | {{#markdown}}
2 | {% body %}
3 | {{/markdown}}
4 | ---
5 | Table of Contents:
6 |
7 | {{#each toc}}
8 | {{./content}}
9 | {{/each}}
10 |
--------------------------------------------------------------------------------
/recipes/middleware/README.md:
--------------------------------------------------------------------------------
1 | ## Middleware events
2 |
3 | Events where you can hook into to create middleware logic.
4 |
5 | - preLayout
6 | - onLoad
7 | - preCompile
8 | - postCompile
9 | - preRender
10 | - postRender
11 |
12 | Example for a middleware to set the layout (if not already defined in the front matter):
13 |
14 | ```js
15 | app.preLayout( /./, function ( view, next ) {
16 | // if the layout is not defined, set it to a specific one ...
17 | if ( !view.layout ) {
18 | view.layout = 'whatever-layout';
19 | }
20 | next();
21 | } );
22 | ```
--------------------------------------------------------------------------------
/recipes/middleware/content/page-1.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Page 1
3 | ---
4 | {{title}}
--------------------------------------------------------------------------------
/recipes/middleware/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var path = require( 'path' );
4 |
5 | var app = assemble();
6 |
7 | app.preLayout( /\.md/, function ( view, next ) {
8 | // console.log( view.data.title + ': preLayout', view );
9 | next();
10 | } );
11 |
12 | app.onLoad( /\.md/, function ( view, next ) {
13 | // console.log( view.data.title + ': onLoad', view );
14 | next();
15 | } );
16 |
17 | app.preCompile( /\.md/, function ( view, next ) {
18 | // console.log( view.data.title + ': preCompile', view );
19 | next();
20 | } );
21 |
22 | app.postCompile( /\.md/, function ( view, next ) {
23 | // console.log( view.data.title + ': postCompile', view );
24 | next();
25 | } );
26 |
27 | app.preRender( /\.md/, function ( view, next ) {
28 | // console.log( view.data.title + ': preRender', view );
29 | next();
30 | } );
31 |
32 | app.postRender( /\.md/, function ( view, next ) {
33 | // console.log( view.data.title + ': postRender', view );
34 | next();
35 | } );
36 |
37 | app.postWrite( /\.md/, function ( view, next ) {
38 | next();
39 | } );
40 |
41 | app.task( 'default', function () {
42 | return app.pages.src( path.join( __dirname, './content/**/*.{md,hbs}' ) )
43 | .pipe( app.renderFile() )
44 | .pipe( app.dest( path.join( __dirname, './.build' ) ) );
45 | } );
46 |
47 | module.exports = app;
48 |
--------------------------------------------------------------------------------
/recipes/middleware/index.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var sinonChai = require( 'sinon-chai' );
6 | var sinon = require( 'sinon' );
7 | var utils = require( './../lib/test-utils' );
8 | var path = require( 'path' );
9 |
10 | chai.use( sinonChai );
11 |
12 | var app = require( './index' );
13 |
14 | describe( 'middleware', function () {
15 |
16 | var delPath = path.join( __dirname, './.build' );
17 | beforeEach( function ( cb ) {
18 | utils.clean( delPath, cb );
19 | } );
20 | afterEach( function ( cb ) {
21 | utils.clean( delPath, cb );
22 | } );
23 |
24 | it( 'events are emitted', function ( done ) {
25 |
26 | var spyOnLoad = sinon.spy();
27 | app.on( 'onLoad', spyOnLoad );
28 |
29 | var spyOnStream = sinon.spy();
30 | app.on( 'onStream', spyOnStream );
31 |
32 | var spyPreRender = sinon.spy();
33 | app.on( 'preRender', spyPreRender );
34 |
35 | var spyPreCompile = sinon.spy();
36 | app.on( 'preCompile', spyPreCompile );
37 |
38 | var spyPreLayout = sinon.spy();
39 | app.on( 'preLayout', spyPreLayout );
40 |
41 | var spyOnLayout = sinon.spy();
42 | app.on( 'onLayout', spyOnLayout );
43 |
44 | var spyPostLayout = sinon.spy();
45 | app.on( 'postLayout', spyPostLayout );
46 |
47 | var spyPostCompile = sinon.spy();
48 | app.on( 'postCompile', spyPostCompile );
49 |
50 | var spyPostRender = sinon.spy();
51 | app.on( 'postRender', spyPostRender );
52 |
53 | var spyOnMerge = sinon.spy();
54 | app.on( 'onMerge', spyOnMerge );
55 |
56 | app.build( 'default', function ( err ) {
57 | expect( err ).to.not.exist;
58 |
59 | //expect( spyOnLoad ).to.have.been.calledOnce;
60 | //expect( spyOnStream ).to.have.been.calledOnce
61 | //expect( spyOnLayout).to.have.been.calledOnce;
62 | //expect( spyPostLayout).to.have.been.calledOnce;
63 | //expect( spyOnMerge).to.have.been.calledOnce;
64 |
65 | expect( spyPreRender ).to.have.been.calledOnce;
66 | //expect( spyPreRender).to.have.been.calledAfter(spyOnStream);
67 |
68 | expect( spyPreCompile ).to.have.been.calledOnce;
69 | expect( spyPreCompile ).to.have.been.calledAfter( spyPreRender );
70 |
71 | expect( spyPreLayout ).to.have.been.calledOnce;
72 | expect( spyPreLayout ).to.have.been.calledAfter( spyPreCompile );
73 |
74 | expect( spyPostCompile ).to.have.been.calledOnce;
75 | expect( spyPostCompile ).to.have.been.calledAfter( spyPreLayout );
76 |
77 | expect( spyPostRender ).to.have.been.calledOnce;
78 | expect( spyPostRender ).to.have.been.calledAfter( spyPostCompile );
79 |
80 | done();
81 | } );
82 | } );
83 | } );
84 |
--------------------------------------------------------------------------------
/recipes/middleware/run.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var app = require( './index' );
3 |
4 | app.build( ['default'], function ( err ) {
5 | if ( err ) {
6 | console.error( 'ERROR: ', err );
7 | }
8 | } );
9 |
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/README.md:
--------------------------------------------------------------------------------
1 | ## permalinks-copy-images
2 |
3 | This recipe follows a quite useful - though uncommon - pattern how to store content on GitHub and then use it to create static pages:
4 |
5 | Let's assume you have the following structure on GitHub:
6 |
7 | ```bash
8 | |── content
9 | |── article-1
10 | |── images
11 | | screenshot.png
12 | | another-image.png
13 | | README.md
14 | |── article-2
15 | |── images
16 | | screenshot.png
17 | | another-image.png
18 | | README.md
19 | ```
20 |
21 | This pattern has some benefits:
22 | - You can send out a link to just the folder and the README.md will always be shown as the default content
23 | - You can reference the images relatively and they will be shown always be shown correctly
24 | - When using hundreds of articles using assembly, you do not run into the risk that you mix-up image names
25 | - The images are always related to its articles, therefore it's easy to move around content
26 |
27 |
28 | Using now `assemble-permalinks` in combination with a `postWrite` middleware copies all files to the generated permalink-folder:
29 |
30 | ```bash
31 | |── articles
32 | |── article-1-permalink
33 | |── images
34 | | screenshot.png
35 | | another-image.png
36 | | index.html
37 | |── article-2-permalink
38 | |── images
39 | | screenshot.png
40 | | another-image.png
41 | | index.html
42 | ```
43 |
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/articles/article-1/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Article 1
3 | category: articles
4 | ---
5 | {{title}}
6 |
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/articles/article-1/images/article-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/assemble/assemble-workshop/36d1a041915c773d87c9a412af2b5ed94f1d3aa6/recipes/permalinks-copy-images/content/articles/article-1/images/article-1.png
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/articles/article-1/images/dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/assemble/assemble-workshop/36d1a041915c773d87c9a412af2b5ed94f1d3aa6/recipes/permalinks-copy-images/content/articles/article-1/images/dot.png
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/articles/article-2/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Article 2
3 | category: articles
4 | ---
5 | {{title}}
6 |
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/articles/article-2/images/article-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/assemble/assemble-workshop/36d1a041915c773d87c9a412af2b5ed94f1d3aa6/recipes/permalinks-copy-images/content/articles/article-2/images/article-2.png
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/articles/article-2/images/dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/assemble/assemble-workshop/36d1a041915c773d87c9a412af2b5ed94f1d3aa6/recipes/permalinks-copy-images/content/articles/article-2/images/dot.png
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/posts/2016-01-01-post-1/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Post 1
3 | postData: 2016-01-01
4 | category: posts
5 | ---
6 | {{title}}
7 |
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/posts/2016-01-01-post-1/images/dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/assemble/assemble-workshop/36d1a041915c773d87c9a412af2b5ed94f1d3aa6/recipes/permalinks-copy-images/content/posts/2016-01-01-post-1/images/dot.png
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/posts/2016-01-01-post-1/images/post-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/assemble/assemble-workshop/36d1a041915c773d87c9a412af2b5ed94f1d3aa6/recipes/permalinks-copy-images/content/posts/2016-01-01-post-1/images/post-1.png
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/posts/2016-01-02-post-2/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Post 2
3 | postData: 2016-01-02
4 | category: posts
5 | ---
6 | {{title}}
7 |
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/posts/2016-01-02-post-2/images/dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/assemble/assemble-workshop/36d1a041915c773d87c9a412af2b5ed94f1d3aa6/recipes/permalinks-copy-images/content/posts/2016-01-02-post-2/images/dot.png
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/content/posts/2016-01-02-post-2/images/post-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/assemble/assemble-workshop/36d1a041915c773d87c9a412af2b5ed94f1d3aa6/recipes/permalinks-copy-images/content/posts/2016-01-02-post-2/images/post-2.png
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var path = require( 'path' );
4 | var fs = require( 'fs-extra' );
5 | var permalinks = require( 'assemble-permalinks' );
6 | var slugify = require( 'slug' );
7 |
8 | var paths = {
9 | templates: path.join( __dirname, './templates/layouts/**/*.hbs' ),
10 | articleDir: path.join( __dirname, './content/**/*.{md,hbs}' ),
11 | buildDir: path.join( __dirname, './.build' )
12 | };
13 |
14 | var app = assemble();
15 |
16 | app.task( 'init', function ( cb ) {
17 | app.layouts( path.templates );
18 | cb();
19 | } );
20 |
21 | app.create( 'articles' )
22 | .use( permalinks( path.join( paths.buildDir, 'whatever/:category/:getSlug()/index.html' ), {
23 | getSlug: function () {
24 | if ( this.slug ) {
25 | return slugify( this.slug, {lower: true} );
26 | } else {
27 | return slugify( this.title, {lower: true} );
28 | }
29 | }
30 | } ) );
31 |
32 | app.articles( paths.articleDir );
33 |
34 | app.postWrite( /\.html/, function ( view, next ) {
35 | var sourcePath = path.dirname( view.key );
36 | var imagesExist = fs.existsSync( path.join( sourcePath, 'images' ) );
37 |
38 | if ( imagesExist ) {
39 | var destPath = path.dirname( view.data.permalink );
40 | return fs.copy( path.join( sourcePath, 'images' ), path.join( destPath, 'images' ), function ( err ) {
41 | if ( err ) {
42 | console.error( err );
43 | return next( err );
44 | }
45 | return next();
46 | } );
47 | } else {
48 | return next();
49 | }
50 | } );
51 |
52 | app.task( 'articles', function () {
53 | return app.toStream( 'articles' )
54 | .pipe( app.renderFile() )
55 | .on( 'error', console.error )
56 | .pipe( app.articles.permalink() )
57 | .pipe( app.dest( paths.buildDir ) );
58 | } );
59 |
60 | app.task( 'default', ['init', 'articles'] );
61 |
62 | module.exports = app;
63 |
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/index.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var path = require( 'path' );
6 | var chaiFiles = require( 'chai-files' );
7 | var utils = require( './../lib/test-utils' );
8 |
9 | chai.use( chaiFiles );
10 | var file = chaiFiles.file;
11 | var app = require( './index' );
12 |
13 | describe( 'permalinks-folder-structure', function () {
14 |
15 | var delPath = path.join( __dirname, './.build' );
16 | beforeEach( function ( cb ) {
17 | utils.clean( delPath, cb );
18 | } );
19 | afterEach( function ( cb ) {
20 | utils.clean( delPath, cb );
21 | } );
22 |
23 | it( 'should create the appropriate output', function ( done ) {
24 | app.build( 'default', function ( err ) {
25 |
26 | if ( err ) { console.error( err );}
27 |
28 | expect( file( path.join( __dirname, './.build/whatever/articles/article-1/index.html' ) ) ).to.exist;
29 | expect( file( path.join( __dirname, './.build/whatever/articles/article-1/images/article-1.png' ) ) ).to.exist;
30 | expect( file( path.join( __dirname, './.build/whatever/articles/article-1/images/dot.png' ) ) ).to.exist;
31 |
32 | expect( file( path.join( __dirname, './.build/whatever/articles/article-2/index.html' ) ) ).to.exist;
33 | expect( file( path.join( __dirname, './.build/whatever/articles/article-2/images/article-2.png' ) ) ).to.exist;
34 | expect( file( path.join( __dirname, './.build/whatever/articles/article-2/images/dot.png' ) ) ).to.exist;
35 |
36 | expect( file( path.join( __dirname, './.build/whatever/posts/post-1/index.html' ) ) ).to.exist;
37 | expect( file( path.join( __dirname, './.build/whatever/posts/post-1/images/post-1.png' ) ) ).to.exist;
38 | expect( file( path.join( __dirname, './.build/whatever/posts/post-1/images/dot.png' ) ) ).to.exist;
39 |
40 | expect( file( path.join( __dirname, './.build/whatever/posts/post-2/index.html' ) ) ).to.exist;
41 | expect( file( path.join( __dirname, './.build/whatever/posts/post-2/images/post-2.png' ) ) ).to.exist;
42 | expect( file( path.join( __dirname, './.build/whatever/posts/post-2/images/dot.png' ) ) ).to.exist;
43 |
44 | done();
45 | } );
46 | } );
47 |
48 | } );
49 |
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/run.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var app = require( './index' );
3 |
4 | app.build( ['default'], function ( err ) {
5 | if ( err ) { console.error( 'ERROR: ', err ); }
6 | } );
7 |
--------------------------------------------------------------------------------
/recipes/permalinks-copy-images/templates/layouts/index.hbs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/assemble/assemble-workshop/36d1a041915c773d87c9a412af2b5ed94f1d3aa6/recipes/permalinks-copy-images/templates/layouts/index.hbs
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file-filebase/README.md:
--------------------------------------------------------------------------------
1 | ## Permalinks: folder per file 2
2 |
3 | This recipe solves an issue described here: https://github.com/assemble/assemble-permalinks/issues/7
4 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file-filebase/assemblefile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var path = require( 'path' );
4 | var plugin = require( './src/plugins' );
5 |
6 | var paths = {
7 | buildDir: path.join( __dirname, './.build/articles' ),
8 | srcDir: path.join( __dirname, './content/articles/**/*.{md,hbs}' )
9 | };
10 |
11 | var app = assemble();
12 |
13 | app.create( 'articles' )
14 | .use( plugin.permalinks( path.join( paths.buildDir, ':name/index.html' ) ) );
15 |
16 | app.articles( paths.srcDir );
17 |
18 | app.task( 'articles', function () {
19 | return app.toStream( 'articles' )
20 | .pipe( app.renderFile() )
21 | .on( 'error', console.error )
22 | .pipe( app.articles.permalink() )
23 | .on( 'error', console.error )
24 | .pipe( app.dest( function ( file ) {
25 | file.base = paths.buildDir;
26 | return paths.buildDir;
27 | } ) )
28 | .on( 'error', console.error );
29 | } );
30 |
31 | app.task( 'default', [
32 | 'articles'
33 | ] );
34 |
35 | module.exports = app;
36 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file-filebase/content/articles/bar.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: bar
3 | ---
4 | {{title}}
5 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file-filebase/content/articles/baz.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: baz
3 | ---
4 | {{title}}
5 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file-filebase/content/articles/foo.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: foo
3 | ---
4 | {{title}}
5 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file-filebase/index.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var path = require( 'path' );
6 | var chaiFiles = require( 'chai-files' );
7 | var utils = require( './../lib/test-utils' );
8 |
9 | chai.use( chaiFiles );
10 | var file = chaiFiles.file;
11 | var app = require( './assemblefile' );
12 |
13 | describe( 'permalinks-folder-per-file-filebase', function () {
14 |
15 | var delPath = path.join( __dirname, './.build' );
16 | beforeEach( function ( cb ) {
17 | utils.clean( delPath, cb );
18 | } );
19 | afterEach( function ( cb ) {
20 | utils.clean( delPath, cb );
21 | } );
22 |
23 | it( 'should create a folder (+ index.html) per file', function ( done ) {
24 | app.build( ['default'], function ( err ) {
25 |
26 | if ( err ) { console.error( err );}
27 |
28 | expect( file( path.join( __dirname, './.build/articles/foo/index.html' ) ) ).to.exist;
29 | expect( file( path.join( __dirname, './.build/articles/bar/index.html' ) ) ).to.exist;
30 | expect( file( path.join( __dirname, './.build/articles/baz/index.html' ) ) ).to.exist;
31 |
32 | done();
33 | } );
34 | } );
35 |
36 | } );
37 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file-filebase/run.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var app = require( './assemblefile' );
3 |
4 | app.build( ['default'], function ( err ) {
5 | if ( err ) {
6 | console.error( 'ERROR: ', err );
7 | }
8 | } );
9 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file-filebase/src/plugins/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var plugins = module.exports = require( 'export-files' )( __dirname );
4 | plugins.permalinks = require( 'assemble-permalinks' );
5 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file/README.md:
--------------------------------------------------------------------------------
1 | ## Permalinks - Folder per file
2 |
3 | Recipe to showcase how to use `assemble-permalinks` to create a folder per file (based on the underlying folder-structure):
4 |
5 | ### Source
6 |
7 | ```
8 | |── content
9 | |── folder-1
10 | |── folder-1-1
11 | | c.md
12 | | d.md
13 | | a.md
14 | |── folder-2
15 | | b.md
16 | | y.md
17 | | z.md
18 | ```
19 |
20 | ### Result
21 |
22 | ```js
23 | |── content
24 | |── folder-1
25 | |── a
26 | | index.html
27 | |── folder-1-1
28 | |── c
29 | | index.html
30 | |── d
31 | | index.html
32 | |── folder-2
33 | |── b
34 | | index.html
35 | |── y
36 | | index.html
37 | |── z
38 | | index.html
39 |
40 | ```
41 |
42 | ### Code
43 |
44 | ```js
45 |
46 | 'use strict';
47 | var assemble = require( 'assemble' );
48 | var path = require( 'path' );
49 | var permalinks = require( 'assemble-permalinks' );
50 |
51 | var paths = {
52 | buildDir: path.join( __dirname, './.build' ),
53 | srcDir: path.join( __dirname, './content/**/*.{md,hbs}' )
54 | };
55 |
56 | var app = assemble();
57 |
58 | app.create( 'articles' )
59 | .use( permalinks( path.join( paths.buildDir, ':getQualifiedName()/index.html' ), {
60 | getQualifiedName: function () {
61 | var relPath = path.relative( this.base, this.dirname );
62 | return path.join( relPath, this.name );
63 | }
64 | } ) );
65 |
66 | app.articles( paths.srcDir );
67 |
68 | app.task( 'articles', function () {
69 | return app.toStream( 'articles' )
70 | .pipe( app.renderFile() )
71 | .on( 'error', console.error )
72 | .pipe( app.articles.permalink() )
73 | .on( 'error', console.error )
74 | .pipe( app.dest( paths.buildDir ) )
75 | .on( 'error', console.error );
76 | } );
77 |
78 | app.task( 'default', [
79 | 'articles'
80 | ] );
81 |
82 | module.exports = app;
83 |
84 | ```
85 |
86 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file/content/folder-1/a.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: a (folder-1)
3 | ---
4 | {{title}}
5 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file/content/folder-1/folder-1-1/c.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: c (folder-1-1)
3 | ---
4 | {{title}}
5 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file/content/folder-1/folder-1-1/d.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: d (folder-1-1)
3 | ---
4 | {{title}}
5 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file/content/folder-2/b.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: b (folder-2)
3 | ---
4 | {{title}}
5 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file/content/y.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: y
3 | ---
4 | {{title}}
5 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file/content/z.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: z
3 | ---
4 | {{title}}
5 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var path = require( 'path' );
4 | var permalinks = require( 'assemble-permalinks' );
5 |
6 | var paths = {
7 | buildDir: path.join( __dirname, './.build' ),
8 | srcDir: path.join( __dirname, './content/**/*.{md,hbs}' )
9 | };
10 |
11 | var app = assemble();
12 |
13 | app.create( 'articles' )
14 | .use( permalinks( path.join( paths.buildDir, ':getQualifiedName()/index.html' ), {
15 | getQualifiedName: function () {
16 | var relPath = path.relative( this.base, this.dirname );
17 | return path.join( relPath, this.name );
18 | }
19 | } ) );
20 |
21 | app.articles( paths.srcDir );
22 |
23 | app.task( 'articles', function () {
24 | return app.toStream( 'articles' )
25 | .pipe( app.renderFile() )
26 | .on( 'error', console.error )
27 | .pipe( app.articles.permalink() )
28 | .on( 'error', console.error )
29 | .pipe( app.dest( paths.buildDir ) )
30 | .on( 'error', console.error );
31 | } );
32 |
33 | app.task( 'default', [
34 | 'articles'
35 | ] );
36 |
37 | module.exports = app;
38 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file/index.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var path = require( 'path' );
6 | var chaiFiles = require( 'chai-files' );
7 | var utils = require( './../lib/test-utils' );
8 |
9 | chai.use( chaiFiles );
10 | var file = chaiFiles.file;
11 | var app = require( './index' );
12 |
13 | describe( 'permalinks-folder-per-file', function () {
14 |
15 | var delPath = path.join( __dirname, './.build' );
16 | beforeEach( function ( cb ) {
17 | utils.clean( delPath, cb );
18 | } );
19 | afterEach( function ( cb ) {
20 | utils.clean( delPath, cb );
21 | } );
22 |
23 | it( 'should create a folder per file', function ( done ) {
24 | app.build( ['default'], function ( err ) {
25 |
26 | if ( err ) { console.error( err );}
27 |
28 | expect( file( path.join( __dirname, './.build/y/index.html' ) ) ).to.exist;
29 | expect( file( path.join( __dirname, './.build/z/index.html' ) ) ).to.exist;
30 |
31 | expect( file( path.join( __dirname, './.build/folder-1/a/index.html' ) ) ).to.exist;
32 | expect( file( path.join( __dirname, './.build/folder-1/folder-1-1/c/index.html' ) ) ).to.exist;
33 | expect( file( path.join( __dirname, './.build/folder-1/folder-1-1/d/index.html' ) ) ).to.exist;
34 |
35 | expect( file( path.join( __dirname, './.build/folder-2/b/index.html' ) ) ).to.exist;
36 |
37 | done();
38 | } );
39 | } );
40 |
41 | } );
42 |
--------------------------------------------------------------------------------
/recipes/permalinks-folder-per-file/run.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var app = require( './index' );
3 |
4 | app.build( ['default'], function ( err ) {
5 | if ( err ) {
6 | console.error( 'ERROR: ', err );
7 | }
8 | } );
9 |
--------------------------------------------------------------------------------
/recipes/permalinks/README.md:
--------------------------------------------------------------------------------
1 | ## Working with permalinks
2 |
3 |
--------------------------------------------------------------------------------
/recipes/permalinks/content/articles/article-1/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Article 1
3 | category: articles
4 | slug: article-1-updated-slug
5 | ---
6 | {{title}}
7 |
--------------------------------------------------------------------------------
/recipes/permalinks/content/articles/article-2/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Article 2
3 | category: articles
4 | ---
5 | {{title}}
6 |
--------------------------------------------------------------------------------
/recipes/permalinks/content/posts/post-1/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Post 1
3 | category: posts
4 | slug: post-1
5 | ---
6 | Post 1
7 |
--------------------------------------------------------------------------------
/recipes/permalinks/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 | var path = require( 'path' );
4 | var utils = require( './../lib/utils' );
5 | var permalinks = require( 'assemble-permalinks' );
6 | var del = require( 'del' );
7 | var slugify = require( 'slug' );
8 |
9 | var paths = {
10 | buildDir: path.join( __dirname, './.build' ),
11 | srcDir: path.join( __dirname, './content/**/*.{md,hbs}' ),
12 | templates: path.join( __dirname, './templates/layouts/**/*.hbs' )
13 | };
14 |
15 | var app = assemble();
16 |
17 | app.create( 'articles' /*, {layout: 'body'}*/ )
18 | .use( permalinks( path.join( paths.buildDir, 'whatever/:category/:getSlug()/index.html' ), {
19 | getSlug: function () {
20 | if ( this.slug ) {
21 | return slugify( this.slug, {lower: true} );
22 | } else {
23 | return slugify( this.title, {lower: true} );
24 | }
25 | }
26 | } ) );
27 |
28 | app.articles( paths.srcDir );
29 |
30 | app.option( 'renameKey', function ( key /*, view */ ) {
31 | key = path.relative( path.join( __dirname, './content/' ), key );
32 | return utils.stripExtension( key, path.extname( key ) );
33 | } );
34 |
35 | app.task( 'load-templates', function ( cb ) {
36 | app.layouts( paths.templates );
37 | cb();
38 | } );
39 |
40 | app.task( 'articles', function () {
41 | return app.toStream( 'articles' )
42 | .pipe( app.renderFile() )
43 | .on( 'error', console.error )
44 | .pipe( app.articles.permalink() )
45 | .pipe( app.dest( paths.buildDir ) );
46 | } );
47 |
48 | /**
49 | * Clean the output director.
50 | */
51 | app.task( 'clean', function ( cb ) {
52 | del( paths.buildDir ).then( function () {
53 | cb();
54 | } );
55 | } );
56 |
57 | /**
58 | * Main task
59 | */
60 | app.task( 'default', [
61 | 'clean',
62 | 'load-templates',
63 | 'articles'
64 | ] );
65 |
66 | module.exports = app;
67 |
--------------------------------------------------------------------------------
/recipes/permalinks/index.spec.js:
--------------------------------------------------------------------------------
1 | /*eslint no-unused-expressions:0*/
2 | 'use strict';
3 | var chai = require( 'chai' );
4 | var expect = chai.expect;
5 | var path = require( 'path' );
6 | var chaiFiles = require( 'chai-files' );
7 | var utils = require( './../lib/test-utils' );
8 |
9 | chai.use( chaiFiles );
10 | var file = chaiFiles.file;
11 | var app = require( './index' );
12 |
13 | describe( 'permalinks', function () {
14 |
15 | var delPath = path.join( __dirname, './.build' );
16 | beforeEach( function ( cb ) {
17 | utils.clean( delPath, cb );
18 | } );
19 | afterEach( function ( cb ) {
20 | utils.clean( delPath, cb );
21 | } );
22 |
23 | it( 'should create the appropriate output', function ( done ) {
24 | app.build( 'default', function ( err ) {
25 | if ( err ) { console.error( err ); }
26 | expect( file( path.join( __dirname, './.build/whatever/articles/article-1-updated-slug/index.html' ) ) ).to.exist;
27 | expect( file( path.join( __dirname, './.build/whatever/articles/article-2/index.html' ) ) ).to.exist;
28 | expect( file( path.join( __dirname, './.build/whatever/posts/post-1/index.html' ) ) ).to.exist;
29 | return done();
30 | } );
31 | } );
32 |
33 | } );
34 |
--------------------------------------------------------------------------------
/recipes/permalinks/run.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var app = require( './index' );
3 |
4 | app.build( ['default'], function ( err ) {
5 | if ( err ) {
6 | console.error( 'ERROR: ', err );
7 | }
8 | } );
9 |
--------------------------------------------------------------------------------
/recipes/permalinks/templates/layouts/body.hbs:
--------------------------------------------------------------------------------
1 | {% body %}
2 |
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/assemblefile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var assemble = require( 'assemble' );
4 | var path = require( 'path' );
5 | var less = require( 'gulp-less' );
6 | var ext = require( 'gulp-extname' );
7 | var watch = require( 'base-watch' );
8 | var browserSync = require( 'browser-sync' ).create();
9 | var app = assemble();
10 |
11 | app.use( watch() );
12 | app.option( 'layout', 'default' );
13 | app.data( 'src/data/**/*.json' );
14 |
15 | //use some middleware to set the default layout if not explicitly defined in the current document:
16 | app.preLayout( /./, function ( view, next ) {
17 | // if the layout is not defined, use the default one ...
18 | if ( !view.layout && app.options.layout ) {
19 | view.layout = app.options.layout;
20 | }
21 | next();
22 | } );
23 |
24 | app.task( 'init', function ( cb ) {
25 | //setup assemble
26 |
27 | app.helpers( 'node_modules/handlebars-helpers/lib' );
28 |
29 | app.helper( 'isActive', function ( title ) {
30 | //custom helper to mark 'current page' as active in bootstrap menu
31 | if ( this.context.title === title ) {
32 | return 'class="active"';
33 | } else {
34 | return '';
35 | }
36 | } );
37 |
38 | app.layouts( path.join( __dirname, 'src/layouts/**/*.hbs' ) );
39 | cb();
40 | } );
41 |
42 | app.task( 'default', ['pages', 'assets', 'serve'], function () {
43 | // placeholder to recompile entire site, start watching and spin up browsersync...
44 | } );
45 |
46 | app.task( 'rebuild', ['pages', 'assets'], function () {
47 | //placeholder to rebuild entire site
48 | } );
49 |
50 | app.task( 'pages', ['init'], function () {
51 | return app.src( 'src/pages/**/*.hbs', {layout: 'default'} )
52 | .pipe( app.renderFile() )
53 | .pipe( ext())
54 | .pipe( app.dest( 'wwwroot' ) )
55 | .pipe( browserSync.stream() );
56 | } );
57 |
58 | app.task( 'assets', ['js', 'css', 'bower'], function () {
59 | return app.src( 'src/assets/**/*.{css, png, jpg, js}' )
60 | .pipe( app.dest( 'wwwroot/assets/' ) );
61 | } );
62 |
63 | app.task( 'css', function () {
64 | return app.src( 'src/assets/**/*.less' )
65 | .pipe( less() )
66 | .pipe( ext())
67 | .pipe( app.dest( 'wwwroot/assets/' ) )
68 | .pipe( browserSync.stream() );
69 | } );
70 |
71 | app.task( 'js', function () {
72 | return app.src( 'src/assets/**/*.js' )
73 | .pipe( app.dest( 'wwwroot/assets/' ) );
74 | } );
75 |
76 | app.task( 'bower', function () {
77 | //copy the files we need from their bower packages
78 | app.src( ['bower_components/jquery/dist/jquery.min.js'] )
79 | .pipe( app.dest( 'wwwroot/assets/js' ) );
80 |
81 | return app.src( ['bower_components/bootstrap/dist/**/*.{min.js,min.css,ttf,svg,woff,eot,woff2}'] )
82 | .pipe( app.dest( 'wwwroot/assets/' ) );
83 | } );
84 |
85 | app.task( 'serve', ['watch'], function () {
86 | browserSync.init( {
87 | port: 8080,
88 | startPath: 'index.html',
89 | server: {
90 | baseDir: './wwwroot'
91 | }
92 | } );
93 | } );
94 |
95 | app.task( 'watch', function ( cb ) {
96 | //watch for changes and run tasks for those file types.
97 | app.watch( 'src/**/*.hbs', ['pages'] );
98 | app.watch( 'src/data/**/*.json', ['pages'] );
99 | app.watch( 'src/assets/**/*.less', ['css'] );
100 | app.watch( 'src/assets/**/*.js', ['js'] );
101 | cb();
102 | } );
103 |
104 | app.task( 'publish', function ( cb ) {
105 | //here is where you could place code to publish the site
106 | console.log( 'deploying..' );
107 | cb();
108 | } );
109 |
110 | module.exports = app;
111 |
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vs-integration-recipes",
3 | "description": "",
4 | "main": "index.js",
5 | "authors": [
6 | "ITLackey"
7 | ],
8 | "license": "ISC",
9 | "homepage": "",
10 | "private": true,
11 | "ignore": [
12 | "**/.*",
13 | "node_modules",
14 | "bower_components",
15 | "test",
16 | "tests"
17 | ],
18 | "dependencies": {
19 | "bootstrap": "^3.3.6"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vs-integration-recipe",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "dependencies": { },
7 | "devDependencies": {
8 | "assemble": "^0.12.0",
9 | "assemble-handlebars": "^0.3.0",
10 | "handlebars-helpers": "^0.6.1",
11 | "base-watch": "^0.1.3",
12 | "browser-sync": "^2.13.0",
13 | "gulp": "^3.9.1",
14 | "gulp-extname": "^0.2.2",
15 | "gulp-less": "^3.1.0"
16 | },
17 | "author": "ITLackey",
18 | "license": "ISC",
19 | "scripts": {
20 | "build": "assemble pages",
21 | "rebuild": "assemble rebuild",
22 | "start": "assemble",
23 | "deploy": "assemble publish"
24 | },
25 | "-vs-binding":{"BeforeBuild":["build"],"Clean":["rebuild","build"]}
26 | }
27 |
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/readme.md:
--------------------------------------------------------------------------------
1 | # Visual Studio Integration
2 |
3 | > This recipe describes how to use assemble within Visual Studio and builds upon the [browser-sync recipe](https://github.com/assemble/assemble-recipes/tree/master/recipes/browser-sync).
4 |
5 | ## Purpose of this recipe
6 | - The primary purpose is to demonstrate using assemble with the Visual Studio IDE
7 |
8 | ### Additional examples
9 | Additionally these topics are also demonstrated in this recipe
10 |
11 | - Convert some .less files to a single style sheet (.css file).
12 | - Convert some .hbs files to HTML output, using styles in the generated CSS file.
13 | - Serve the files in the local browser automatically
14 | - Using site metadata
15 | - Using a default layout file
16 | - Load handlebars-helpers
17 | - Using bower packages
18 | - Using a Bootstrap theme in the layout
19 | - Defining a custom helper
20 | - Create some watchers on
21 | - all .less files (`./src/assets/css` folder)
22 | - all .js files (`./src/assets/js` folder)
23 | - all content files (`./src/pages` and `./src/layouts` folders)
24 | - all data files (`./src/data` folder)
25 | - In case any watcher is triggered, update the corresponding files.
26 |
27 | ## Overview
28 |
29 | This recipe describes how you can leverage assemble within Visual Studio. Included
30 | in this template is an example of a simple site that is using some bower packages,
31 | a bootstrap example theme and some gulp plug-ins within assemble.
32 |
33 | This recipe is not meant to be an example of best practices and it should be
34 | used only as reference when starting an assemble project.
35 |
36 | ## Visual Studio Extensions
37 |
38 | To begin the following visual studio extensions must be installed.
39 |
40 | - [Task Runner Explorer](https://visualstudiogallery.msdn.microsoft.com/8e1b4368-4afb-467a-bc13-9650572db708)
41 | - [NPM Task Runner](https://visualstudiogallery.msdn.microsoft.com/8f2f2cbc-4da5-43ba-9de2-c9d08ade4941)
42 |
43 |
44 | ## Visual Studio Fix
45 |
46 | By default Visual Studio uses node 0.10.x for its Task Runner Explorer.
47 | In order to have the task runner use a newer version of node the options
48 | for the External Web Tools must be changed. Specifically the order of the
49 | paths in which visual studio looks for web tools must be modified. This
50 | article describes the issue and explains the solution in detail.
51 |
52 | [Customize external web tools in visual studio 2015](https://blogs.msdn.microsoft.com/webdev/2015/03/19/customize-external-web-tools-in-visual-studio-2015/)
53 |
54 |
55 | ## NPM Tasks Configuration
56 |
57 | By configuring the scripts section the of the package.json in the project
58 | the Task Runner Explorer will display these tasks and allow the to be
59 | run manually using the context menu. These script definitions are simply
60 | examples and the scripts can be defined differently to meet projects
61 | requirements.
62 |
63 | ``` json
64 | "scripts": {
65 | "build": "assemble pages",
66 | "rebuild": "assemble rebuild",
67 | "start": "assemble",
68 | "deploy": "assemble publish"
69 | }
70 | ```
71 |
72 | ## Visual Studio Event Bindings
73 |
74 | Using the context menu in the Task Runner Explorer for the
75 | scripts defined in your package.json file
76 | you can bind assemble commands to Visual Studio events such as
77 | Project Open, Before Build, After Build and Clean. Doing so
78 | adds an additional section to the package.json file to hold
79 | the event bindings. It looks similar to the following snippet.
80 |
81 | ``` json
82 | "-vs-binding":{"BeforeBuild":["build"]}
83 | ```
84 |
85 |
86 |
87 | ## References
88 |
89 | Information was used from the following resources in this recipe
90 |
91 | * [Task Runner Explorer](https://visualstudiogallery.msdn.microsoft.com/8e1b4368-4afb-467a-bc13-9650572db708)
92 | * [NPM Task Runner](https://visualstudiogallery.msdn.microsoft.com/8f2f2cbc-4da5-43ba-9de2-c9d08ade4941)
93 | * [Fix Web Tools Path](https://blogs.msdn.microsoft.com/webdev/2015/03/19/customize-external-web-tools-in-visual-studio-2015/)
94 | * [Theme](http://getbootstrap.com/examples/carousel/)
95 | * [About Page](http://bootsnipp.com/snippets/6n1ym)
96 | * [Contact Us](http://bootsnipp.com/snippets/featured/contact-us-page)
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/src/assets/css/carousel.css:
--------------------------------------------------------------------------------
1 | /* GLOBAL STYLES
2 | -------------------------------------------------- */
3 | /* Padding below the footer and lighter body text */
4 |
5 | body {
6 | padding-bottom: 40px;
7 | color: #5a5a5a;
8 | }
9 |
10 |
11 | /* CUSTOMIZE THE NAVBAR
12 | -------------------------------------------------- */
13 |
14 | /* Special class on .container surrounding .navbar, used for positioning it into place. */
15 | .navbar-wrapper {
16 | position: absolute;
17 | top: 0;
18 | right: 0;
19 | left: 0;
20 | z-index: 20;
21 | }
22 |
23 | /* Flip around the padding for proper display in narrow viewports */
24 | .navbar-wrapper > .container {
25 | padding-right: 0;
26 | padding-left: 0;
27 | }
28 | .navbar-wrapper .navbar {
29 | padding-right: 15px;
30 | padding-left: 15px;
31 | }
32 | .navbar-wrapper .navbar .container {
33 | width: auto;
34 | }
35 |
36 |
37 | /* CUSTOMIZE THE CAROUSEL
38 | -------------------------------------------------- */
39 |
40 | /* Carousel base class */
41 | .carousel {
42 | height: 500px;
43 | margin-bottom: 60px;
44 | }
45 | /* Since positioning the image, we need to help out the caption */
46 | .carousel-caption {
47 | z-index: 10;
48 | }
49 |
50 | /* Declare heights because of positioning of img element */
51 | .carousel .item {
52 | height: 500px;
53 | background-color: #777;
54 | }
55 | .carousel-inner > .item > img {
56 | position: absolute;
57 | top: 0;
58 | left: 0;
59 | min-width: 100%;
60 | height: 500px;
61 | }
62 |
63 |
64 | /* MARKETING CONTENT
65 | -------------------------------------------------- */
66 |
67 | /* Center align the text within the three columns below the carousel */
68 | .marketing .col-lg-4 {
69 | margin-bottom: 20px;
70 | text-align: center;
71 | }
72 | .marketing h2 {
73 | font-weight: normal;
74 | }
75 | .marketing .col-lg-4 p {
76 | margin-right: 10px;
77 | margin-left: 10px;
78 | }
79 |
80 |
81 | /* Featurettes
82 | ------------------------- */
83 |
84 | .featurette-divider {
85 | margin: 80px 0; /* Space out the Bootstrap more */
86 | }
87 |
88 | /* Thin out the marketing headings */
89 | .featurette-heading {
90 | font-weight: 300;
91 | line-height: 1;
92 | letter-spacing: -1px;
93 | }
94 |
95 |
96 | /* RESPONSIVE CSS
97 | -------------------------------------------------- */
98 |
99 | @media (min-width: 768px) {
100 | /* Navbar positioning foo */
101 | .navbar-wrapper {
102 | margin-top: 0;
103 | }
104 | .navbar-wrapper .container {
105 | padding-right: 15px;
106 | padding-left: 15px;
107 | }
108 | .navbar-wrapper .navbar {
109 | padding-right: 0;
110 | padding-left: 0;
111 | }
112 |
113 | /* The navbar becomes detached from the top, so we round the corners */
114 | .navbar-wrapper .navbar {
115 | border-radius: 4px;
116 | }
117 |
118 | /* Bump up size of carousel content */
119 | .carousel-caption p {
120 | margin-bottom: 20px;
121 | font-size: 21px;
122 | line-height: 1.4;
123 | }
124 |
125 | .featurette-heading {
126 | font-size: 50px;
127 | }
128 | }
129 |
130 | @media (min-width: 992px) {
131 | .featurette-heading {
132 | margin-top: 120px;
133 | }
134 | }
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/src/assets/css/ie10-viewport-bug-workaround.css:
--------------------------------------------------------------------------------
1 |
2 | /*!
3 | * IE10 viewport hack for Surface/desktop Windows 8 bug
4 | * Copyright 2014-2015 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | */
7 |
8 | /*
9 | * See the Getting Started docs for more information:
10 | * http://getbootstrap.com/getting-started/#support-ie10-width
11 | */
12 | @-webkit-viewport { width: device-width; }
13 | @-moz-viewport { width: device-width; }
14 | @-ms-viewport { width: device-width; }
15 | @-o-viewport { width: device-width; }
16 | @viewport { width: device-width; }
17 |
18 |
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/src/assets/css/styles.less:
--------------------------------------------------------------------------------
1 | @import url("http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css");
2 |
3 | .marketing{
4 | margin-top: 80px;
5 | }
6 |
7 | /*contact*/
8 | .jumbotron {
9 | background: #358CCE;
10 | color: #FFF;
11 | border-radius: 0px;
12 | }
13 |
14 | .jumbotron-sm {
15 | padding-top: 24px;
16 | padding-bottom: 24px;
17 | }
18 |
19 | .jumbotron small {
20 | color: #FFF;
21 | }
22 |
23 | .h1 small {
24 | font-size: 24px;
25 | }
26 |
27 |
28 | /*About */
29 | .panel-pricing {
30 | -moz-transition: all .3s ease;
31 | -o-transition: all .3s ease;
32 | -webkit-transition: all .3s ease;
33 | }
34 | .panel-pricing:hover {
35 | box-shadow: 0px 0px 30px rgba(0, 0, 0, 0.2);
36 | }
37 | .panel-pricing .panel-heading {
38 | padding: 20px 10px;
39 | }
40 | .panel-pricing .panel-heading .fa {
41 | margin-top: 10px;
42 | font-size: 58px;
43 | }
44 | .panel-pricing .list-group-item {
45 | color: #777777;
46 | border-bottom: 1px solid rgba(250, 250, 250, 0.5);
47 | }
48 | .panel-pricing .list-group-item:last-child {
49 | border-bottom-right-radius: 0px;
50 | border-bottom-left-radius: 0px;
51 | }
52 | .panel-pricing .list-group-item:first-child {
53 | border-top-right-radius: 0px;
54 | border-top-left-radius: 0px;
55 | }
56 | .panel-pricing .panel-body {
57 | background-color: #f0f0f0;
58 | font-size: 40px;
59 | color: #777777;
60 | padding: 20px;
61 | margin: 0px;
62 | }
63 |
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/src/assets/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/assemble/assemble-workshop/36d1a041915c773d87c9a412af2b5ed94f1d3aa6/recipes/visual-studio-integration/src/assets/images/icon.png
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/src/assets/js/ie10-viewport-bug-workaround.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | /*!
3 | * IE10 viewport hack for Surface/desktop Windows 8 bug
4 | * Copyright 2014-2015 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | */
7 |
8 | // See the Getting Started docs for more information:
9 | // http://getbootstrap.com/getting-started/#support-ie10-width
10 |
11 | (function () {
12 | 'use strict';
13 |
14 | if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
15 | var msViewportStyle = document.createElement('style');
16 | msViewportStyle.appendChild(
17 | document.createTextNode(
18 | '@-ms-viewport{width:auto!important}'
19 | )
20 | );
21 | document.querySelector('head').appendChild(msViewportStyle)
22 | }
23 |
24 | })();
25 | /* eslint-enable */
26 |
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/src/data/site.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Example Site Template",
3 | "author": "ITLackey",
4 | "keywords": "example metadata, assemble",
5 | "description": "This is an example site template",
6 | "email": "example@email.com",
7 | "ga_code": "XXX",
8 | "gse_code": "XXX",
9 | "facebook": "",
10 | "twitter": "",
11 | "googleplus": ""
12 | }
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/src/layouts/default.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{title}} - {{site.title}}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
27 |
28 |
29 |
30 |
31 |
32 |
68 |
69 |
70 | {% body %}
71 |
72 |
73 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/src/pages/about.hbs:
--------------------------------------------------------------------------------
1 | ---
2 | title: About
3 | ---
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Requirements
16 |
17 |
18 |
19 | Network
20 | Speed
21 | SIM
22 | Modem
23 | Connection
24 | Sender ID (Branded SMS)
25 | Interaction
26 | Personalize SMS
27 | Scheduler
28 | Fee
29 | Application
30 | Cost of SMS
31 | Load Expiry
32 | UNLITXT Promos
33 | International SMS
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
Busybee PowerBlast
45 |
46 |
47 | GSM
48 | 15 – 20 SMS per minute
49 | SIM needed
50 | Modem needed
51 | Offline
52 | No
53 | Two-way
54 | Yes
55 | Yes
56 | You pay for the software
57 | With fee
58 | Normal cellphone charges apply (SIM)
59 | Not applicable
60 | Yes (will depend on the SIM)
61 | Yes (will depend on the SIM)
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
Busybee BrandTxT
73 |
74 |
75 |
76 | SMS Gateway
77 | 1 SMS per second
78 | No need for SIM
79 | No need for Modem
80 | Online
81 | Yes
82 | One-way
83 | Yes
84 | Yes
85 | You pay for the SMS
86 | Free
87 | PHP 1.00 per SMS ($0.025)
88 | Without Expiry
89 | No
90 | Yes
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/src/pages/contact.hbs:
--------------------------------------------------------------------------------
1 | ---
2 | title: Contact Us
3 | ---
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Contact us Feel free to contact us
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
71 |
72 |
73 | Our office
74 |
75 | Twitter, Inc.
76 | 795 Folsom Ave, Suite 600
77 | San Francisco, CA 94107
78 |
79 | P:
80 |
81 | (123) 456-7890
82 |
83 |
84 | Full Name
85 | first.last@example.com
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/recipes/visual-studio-integration/src/pages/index.hbs:
--------------------------------------------------------------------------------
1 | ---
2 | title: Home
3 | ---
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
Example headline.
19 |
Note: If you're viewing this page via a file://
URL, the "next" and "previous" Glyphicon buttons on the left and right might not load/display properly due to web browser security rules.
20 |
Sign up today
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
Another example headline.
29 |
Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.
30 |
Learn more
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
One more for good measure.
39 |
Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.
40 |
Browse gallery
41 |
42 |
43 |
44 |
45 |
46 |
47 | Previous
48 |
49 |
50 |
51 | Next
52 |
53 |
54 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
Heading
65 |
Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus magna.
66 |
View details »
67 |
68 |
69 |
70 |
Heading
71 |
Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.
72 |
View details »
73 |
74 |
75 |
76 |
Heading
77 |
Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.
78 |
View details »
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
First featurette heading. It'll blow your mind.
88 |
Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
Oh yeah, it's that good. See for yourself.
100 |
Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
And lastly, this one. Checkmate.
112 |
Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/recipes/vscode-integration/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.1.0",
3 | "command": "assemble",
4 | "isShellCommand": true,
5 | "args": [],
6 | "showOutput": "always",
7 | "tasks": [
8 | {
9 | "taskName": "build",
10 | "args": [],
11 | "isBuildCommand": true,
12 | "isWatching": false
13 | },
14 | {
15 | "taskName": "start",
16 | "args": [],
17 | "isBuildCommand": false,
18 | "isWatching": true
19 | },
20 | {
21 | "taskName": "publish",
22 | "args": [],
23 | "isBuildCommand": false,
24 | "isWatching": false
25 | }
26 | ]
27 | }
--------------------------------------------------------------------------------
/recipes/vscode-integration/README.md:
--------------------------------------------------------------------------------
1 | ## VS Code Integration
2 |
3 | > This recipe demonstrates how to wire assemble to VS Code.
4 |
5 | **Set up some tasks in your `assemblefile.js`**
6 |
7 | These are just placeholder tasks for demonstration purposes.
8 |
9 | ```js
10 |
11 | 'use strict';
12 | var assemble = require( 'assemble' );
13 |
14 | var app = assemble();
15 |
16 | app.task('default', ['build'], function (cb) {
17 | console.log('default task...');
18 | cb();
19 | });
20 |
21 | app.task( 'start', function () {
22 | console.log("Here is where you could do some browsersync stuff...");
23 | });
24 |
25 | app.task('build', function (cb) {
26 | console.log('building...');
27 | cb();
28 | });
29 |
30 | app.task('publish', function (cb) {
31 | console.log('publishing...');
32 | cb();
33 | });
34 |
35 | module.exports = app;
36 |
37 | ```
38 |
39 | **Defining the VS Code Commands:**
40 |
41 | To enable the ability to launch these tasks from the VS Code command palette
42 | you will need to configure the task runner. The easiest way to do this is to
43 | select `Configure Task Runner` from the command palette.
44 |
45 | ```json
46 | {
47 | "version": "0.1.0",
48 | "command": "assemble",
49 | "isShellCommand": true,
50 | "args": [],
51 | "showOutput": "always",
52 | "tasks": [
53 | {
54 | "taskName": "build",
55 | "args": [],
56 | "isBuildCommand": true,
57 | "isWatching": false
58 | },
59 | {
60 | "taskName": "start",
61 | "args": [],
62 | "isBuildCommand": false,
63 | "isWatching": true
64 | },
65 | {
66 | "taskName": "publish",
67 | "args": [],
68 | "isBuildCommand": false,
69 | "isWatching": false
70 | }
71 | ]
72 | }
73 | ```
74 |
75 | With this `tasks.json` added to the .vscode folder, the `build`, `start` and `publish` will be available from the command palette.
76 |
77 | More detailed information on VS Code tasks can be found in this article: [Integrate with External Tools via Tasks](http://code.visualstudio.com/docs/editor/tasks)
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/recipes/vscode-integration/assemblefile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assemble = require( 'assemble' );
3 |
4 | var app = assemble();
5 |
6 | app.task( 'default', ['build'], function ( cb ) {
7 | console.log( 'default task...' );
8 | cb();
9 | } );
10 |
11 | app.task( 'start', function () {
12 | console.log( 'Here is where you could do some browsersync stuff...' );
13 | } );
14 |
15 | app.task( 'build', function ( cb ) {
16 | console.log( 'building...' );
17 | cb();
18 | } );
19 |
20 | app.task( 'publish', function ( cb ) {
21 | console.log( 'publishing...' );
22 | cb();
23 | } );
24 |
25 | module.exports = app;
26 |
--------------------------------------------------------------------------------
/recipes/vscode-integration/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vscode-integration",
3 | "version": "1.0.0",
4 | "description": "example of how to use assemble with VSCode",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 0",
8 | "build": "assemble build",
9 | "start": "assemble",
10 | "deploy": "assemble publish"
11 | },
12 | "author": "ITLackey",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "assemble": "^0.14.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------