Gulp plugin for all in one static site building.
Main features:
- generate pages from sitemap
- compile pages with Handlebars using layouts, partials and external data
- compile and minify styles with SASS
- compile and minify scripts with Webpack
- generate favicon and minify images
- generate sitemap.xml and robots.txt
We recommend using yarn insted of npm.
yarn add gulp-site
First time site generation:
mkdir my-new-site && cd my-new-site
yarn init
yarn add gulp-site
Add to package.json scripts section:
"scripts": {
"setup": "site init && site generate",
"custom": "site create",
"start": "site default",
"build": "site build --production",
"generate": "site generate",
"favicon": "site favicon",
"catalog": "site catalog"
},
And generate site base files and directories:
yarn setup
yarn start
Enjoy.
You can configure gulp-site builder with config.yml
# Your project's server will run on localhost:xxxx at this port
PORT: 8000
# Your site production web-root, available in templates, but for dev will be replaced with http://localhost:<port>
ORIGIN: https://test.test
INDEX:
# Additional disallow paths for generating robots.txt
disallow:
- /assets/
# Autoprefixer will make sure your CSS works with these browsers
COMPATIBILITY:
- "last 2 versions"
- "ie >= 9"
- "ios >= 7"
- "android >= 4.4"
# Settings for UnCSS
UNCSS:
enabled: true # false by default, has known UNCSS bug with js execution
ignore:
- !!js/regexp ^\.is-.*
# Include this styles and scripts in all pages
CDN:
root: https://cdn.mysite.com/ # will set this to {{cdn}} variable with production build
js:
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/core.js" integrity="sha256-36hEPcG8mKookfvUVvEqRkpdYV1unP6wvxIqbgdeVhk=" crossorigin="anonymous"></script>
css:
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css" integrity="sha256-vK3UTo/8wHbaUn+dTQD0X6dzidqc5l7gczvH+Bnowwk=" crossorigin="anonymous" />
# All path must be relative to your working dir
PATHS:
dist: dist # destination path
logo: src/assets/img/logo.png # at least 260x260px image or svg for favicon generation
sitemap: src/sitemap.yml # source file for generating site pages
pages: src/pages # site pages in .html, .json or .yaml files
layouts: src/layouts # .html, .hbs or .handlebars layouts
partials: src/partials # .html, .hbs or .handlebars partials
public: src/public # this files will be copied to the root of destination
assets: src/assets # images, styles, scripts and other required files
data: src/data # .json, .yaml files containing data for templates
helpers: src/helpers # .js files with helpers
sass: [] # this paths will be available for import in your scss files
entries: ['/js/app.js'] # scripts entry files
styles: ['/scss/app.scss'] # styles entry files
All configuration options you can see in settings.js file in module folder.
Page can be defined with .html, .yml or .json file. HTML files can contain YAML Front Matter:
---
layout: default
url: /contact
title: Contact page
index: true
---
<h1>Contact page</h1>
In YAML format this will look as:
layout: default
url: /contact
title: Contact page
index: true
body: <h1>Contact page</h1>
In .yml and .json files you can define body as map of partials, where key is partial name and value data passed to partial exclusively:
{
"layout": "default",
"url": "/contact",
"title": "Contact page",
"index": true,
"body": {
"widget_map": {
"link": "<link to my map>"
},
"feedback_form": {
"title": "Contact us!"
}
}
}
This body will be generated in template like this:
{{#with body.widget_map}}
{{> widget_map}}
{{/with}}
{{#with body.feedback_form}}
{{> feedback_form}}
{{/with}}
layout: — name of the layout file used for this page
url: — page will be available by this url, for example /contact will create file at contact/index.html
title: — page head title, in the default layout placed in <title>{{title}}</title>
description: — page head description tag
keywords: — page head keywords tag
index: — boolean type, declare page indexation, indexed page (index: true) will be available in sitemap.xml
with date of last file changing. Not indexed page (index: false) will de dissallowed in robots.txt
og: — open graph data, used in meta.html
partial provided by gulp-site. Read about it in partials.
cdn: — contain js and css array properties with scripts and styles available only on this page
Layout files can have the extension .html
, .hbs
, or .handlebars
. Default layout provided:
{{#wrap 'html5' this}}
{{> body}}
{{/wrap}}
You can customise layout by calling next command:
yarn custom layout:default
And default layout will be copied to the src/layouts/default.html
All layouts have a special Handlebars partial called body
which contains the contents of the page.
<!-- Header up here -->
{{> body}}
<!-- Footer down here -->
Partial files can have the extension .html
, .hbs
, or .handlebars
. Each will be registered as a Handlebars partial which can be accessed using the name of the file. (The path to the file doesn't matter—only the name of the file itself is used.)
<!-- Renders partials/header.html -->
{{> header}}
Gulp-site provide partial {{> meta}} for meta tags generation:
<meta name="description" content="{{description}}" />
<meta name="keywords" content="{{keywords}}" />
<link rel="canonical" href="{{site.domain}}{{url}}"/>
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico'>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
{{#if theme}}
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="{{theme.safari_tab_color}}">
<meta name="msapplication-TileColor" content="{{theme.msapp_color}}">
<meta name="theme-color" content="{{theme.color}}">
{{/if}}
{{#if og}}
<meta property="og:type" content="{{#if og.type}}{{og.type}}{{else}}website{{/if}}" />
<meta property="og:site_name" content="{{og.site_name}}" />
<meta property="og:image:width" content="{{#if og.image_width}}{{og.image_width}}{{else}}795{{/if}}">
<meta property="og:image:height" content="{{#if og.image_wheight}}{{og.image_height}}{{else}}200{{/if}}">
<meta property="og:url" content="{{settings.origin}}">
<meta property="og:image" content="{{settings.origin}}/{{og.image}}">
<meta property="og:title" content="{{#if og.image_width}}{{og.title}}{{else}}{{title}}{{/if}}">
<meta property="og:description" content="{{#if og.image_width}}{{og.description}}{{else}}{{description}}{{/if}}">
{{/if}}
{{#unless index}}
<meta name="robots" content="noindex, nofollow"/>
{{/unless}}
Is a special type of partials for wrapping around your code.
For example html5
wrapper is contain next code:
<!doctype html>
<html class="no-js" lang="{{site.language}}">
<head>
{{#if site.tagID}}
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','{{site.tagID}}');</script> <!-- End Google Tag Manager -->
{{/if}}
{{> meta}}
{{#if css}}
{{#each css}}
{{{this}}}
{{/each}}
{{/if}}
<link rel="stylesheet" href="{{cdn}}css/app.css?{{timestamp}}">
</head>
<body>
{{#if site.tagID}}
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id={{site.tagID}}"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
{{/if}}
{{{child}}}
{{#if js}}
{{#each js}}
{{{this}}}
{{/each}}
{{/if}}
<script src="{{cdn}}js/app.js?{{timestamp}}"></script>
</body>
</html>
Is is like a layout, but replace {{> body}}
with {{{child}}}
tag.
<!-- Wrapper start up here -->
{{{child}}}
<!-- Wrapper end down here -->
Handlebars helpers are .js
files which export a function via module.exports
. The name used to register the helper is the same as the name of the file.
For example, a file named content.js
that exports this function would add a Handlebars helper called {{content}}
.
module.exports = function(text, options) {
return `<p>${text}</p>`
}
Argument options contain all data, or fn function with child elements with helper block call:
{{#content}}
<b>Hello</b>
{{/content}}
And content.js will be:
module.exports = function(text, options) {
return '<p>' + options.fn(options.data.root) + '</p>';
}
In this context available Handlebars property if you need listing of partials or call .compile function.
Provided default next helpers:
{{#code 'html'}} ... {{/code}} — highlight code examples with selected language using highlight.js
{{getData 'site.tagID'}} — get data by path from the root
{{getPage 'contact'}} — return page object with all data
{{getPage 'contact' 'body.feedback_form'}} — return data from selected page by path
{{ifEqual 'a' 'b'}} ... {{else}} ... {{/ifEqual}} — if the values are equal, content inside of the helper. If not, the content inside the {{else}}
block
{{#markdown}} ... {{/markdown}} — render markdown formated text to html
{{repeat 3}} ... {{/repeat}} — repeate n times content inside of the helper
{{#wrap 'partial_name'}} ... {{/wrap}} — use selected partial for wraping content inside tags. Partial used in wrap must contain {{{child}}}
tag, rendered in root context.
{{#wrap 'partial_name' withData}} ... {{/wrap}} — Partial used in wrap rendered in withData
context., if withData not set used global context. For current context set this
.
Data can be formatted as JSON (.json
) or YAML (.yml
). Within a template, the data is stored within a variable with the same name as the file it came from.
For example, a file named contact.json
with key/value pairs such as the following:
{
"name": "John Doe",
"email": "john.doe@gmail.com",
"phone": "555-1212"
}
Could be used to output the value of John Doe within a template using the Handlebars syntax of {{contact.name}}
.
Data can also be inserted into the page itself with a Front Matter template at the top of the .html file or defined in .yml or .json fields of page file.
Lastly, the reserved page
variable is added to every page template as it renders. It contains the name of the page being rendered, without the extension.
When generating initial setup will be provided site.yml
file:
name: new site
tagID:
about: short description
description: full description
contact:
phone:
email:
time:
Property tagID
used for Google Tag Manager code placement in the default layout provided by gulp-site.
Site data can be readed from /data//index.{yml,json,js} files. This files can be filled manual or generated by command yarn catalog --name <catalog-name>
. This command output catalog data file with directory tree of this catalog.
By default output will be looked like this:
items:
folder1:
images:
- url: /folder1/1.jpg
preview: /folder1/1@s.jpg
videos: []
folder2:
items:
subfolder1:
images:
- url: /folder2/subfolder1/1.jpg
preview: /folder2/subfolder1/1@s.jpg
By default catalog generator copy media files to /src/public/content/<catalog-name>
folder, for images also make a preview with size 120x120px.
You can configure output by add settings.yml file on any level of catalog and this options will be applied to this folder.
Available options:
prefix
- string prepended the folder name in result index.yml file.
flatItems
- do not place child items in items
key, each of child will be placed on the folder root level.
dataTemplate
- object fields appended to result folder object. Work as template with ${keyname} style (warning: filled one by one by declaration order). Available two default variable: ${itemDirName}
, ${parentDirName}
.
subSettings
- settings applied to the each subfolders. If subfolder has own settings file this one merged with this options, but own subdolder settings has priority.