first commit

This commit is contained in:
Matthew Gaffen 2019-08-14 19:09:08 +01:00
commit 4b77d0b8ca
46 changed files with 12603 additions and 0 deletions

3
.browserlistrc Normal file
View File

@ -0,0 +1,3 @@
# Browsers that we support
> .05%
not ie <= 9

38
.eleventy.js Normal file
View File

@ -0,0 +1,38 @@
const path = require("path");
const fs = require("fs");
const manifest = require("./data/manifest.json");
const Nunjucks = require("nunjucks");
// Require the Vue component render custom tag
const vueTag = require("./njktags/vue");
module.exports = function(eleventyConfig) {
let nunjucksEnvironment = new Nunjucks.Environment(
new Nunjucks.FileSystemLoader("layouts")
);
eleventyConfig.setLibrary("njk", nunjucksEnvironment);
let options = {
html: true
};
// Install custom tag
eleventyConfig.addNunjucksTag("vue", function(nunjucksEngine) {
return new vueTag(nunjucksEngine);
});
eleventyConfig.addPassthroughCopy("img");
eleventyConfig.addPassthroughCopy("favicon");
return {
dir: {
input: "src/content",
output: "build",
includes: "../../layouts",
data: "../../data"
},
templateFormats: ["md", "njk"]
};
};

12
.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
build/*
!build/.gitkeep
build/posts/*
!build/fonts/*
!build/posts/.gitkeep
!build/favicon/*
src/content/posts/*
!src/content/posts/.gitkeep
node_modules
/assets/*
/src/js/modernizr.js
/layouts/partials/sprite.svg

5
.modernizrrc.json Normal file
View File

@ -0,0 +1,5 @@
{
"minify": true,
"options": ["mq", "setClasses"],
"feature-detects": []
}

30
README.md Normal file
View File

@ -0,0 +1,30 @@
# Kindling: A static site generation starterkit using eleventy.js
## How to use:
`npm install` \
`npm start` to open the site in a browser for local development \
`npm run generate` to compile modernizr and svg sprites (if you need that) \
`npm run build` to export the site for upload to the `/build` directory
If you want to use an SVG spritesheet, the `spritesheet` script will compole all svg's contained in `/src/svg`
[Check the eleventy documentation for information on how to construct the site in detail](https://www.11ty.io/docs/)
[Check the Nunjucks documentation for information on how to use the templating language](https://mozilla.github.io/nunjucks/templating.html)
Pages are created bu placing markdown files (like this one!) in the `/src/content` folder.
Javascript and css are compiled from the `/src/js/` and `/src/scss/` folders, by default `styles.scss` and `main.js` are compiled.
The syles are written in `scss` and organised in an [ITCSS](https://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528) and [BEM](http://getbem.com/) - inspired way by default, including some boilerplate css elements I find useful.
More customisation can be made tp the build process in the `/webpack/` directory.
Modernizr and babel/es6 are configured by default.
Page title and meta description can be set globally within the `/data/meta.json` file, or by overriding those variables in a pages' markdown frontmatter.
Layouts are stored in `/layouts`, the layout can also be set using frontmatter with the `layout` variable. Check out `/src/content/index.md` for an example.
Happy hunting!

11
babel.config.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = function(api) {
api.cache(true);
const presets = [["@babel/preset-env", { useBuiltIns: "usage", corejs: 3 }]];
const plugins = [];
return {
presets,
plugins
};
};

1
data/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
manifest.json

4
data/meta.json Normal file
View File

@ -0,0 +1,4 @@
{
"title": "Kindling",
"desc": "The kindling static site framework"
}

0
favicon/.gitkeep Normal file
View File

0
img/.gitkeep Normal file
View File

20
layouts/base.njk Normal file
View File

@ -0,0 +1,20 @@
{% include "partials/header.njk" %}
</head>
<body>
<div class="hidden">
{% include "partials/sprite.svg" %}
</div>
<header>
<h1>Your brand-spanking new Kindling website!</h1>
</header>
{% block body %}
{{ content | safe }}
{% endblock %}
{% block footer %}
<footer class="sitefooter">
{% include 'partials/footer.njk' %}
</footer>
<script async="true" src="/assets/{{manifest.main.js}}"></script>
{% endblock %}
</body>
</html>

11
layouts/home.njk Normal file
View File

@ -0,0 +1,11 @@
{% extends "./base.njk" %}
{% block body %}
{% vue { component:"HelloWorld" } %}
{% vue { component:"HelloWorld", props: { message: "This is a test" } } %}
{% vue { component:"HelloWorld", props: { message: "Of server rendered Vue components" } } %}
{% vue { component:"ListComp", props: { startlist: [{message:"Render Vue in Nunjucks"}, {message:"???"}, {message:"Profit!"}] } } %}
<section id="content" role="main" class="content-wrapper">
{{content|safe}}
</section>
{% endblock %}

View File

@ -0,0 +1,3 @@
<p>
<a href="https://github.com/Gaffen/Kindling" target="_blank">Kindling</a> by <a href="https://gaffen.co.uk" target="_blank">Gaffen</a>
</p>

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<!--[if lt IE 7]><html class="no-js ie ie6 lt-ie9 lt-ie8 lt-ie7" {{site.language_attributes}}> <![endif]-->
<!--[if IE 7]><html class="no-js ie ie7 lt-ie9 lt-ie8" {{site.language_attributes}}> <![endif]-->
<!--[if IE 8]><html class="no-js ie ie8 lt-ie9" {{site.language_attributes}}> <![endif]-->
<!--[if gt IE 8]><!--><html class="no-js"> <!--<![endif]-->
<head>
<meta charset="UTF-8" />
<title>{{meta.title}}</title>
<link rel="preload" href="https://fonts.googleapis.com/css?family=Roboto+Slab|Roboto:300,400,700&display=swap" as="style" />
<link rel="preload" href="/assets/{{manifest.main.css}}" as="style" />
<link rel="preload" href="/assets/{{manifest.main.js}}" as="script"/>
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
<link rel="manifest" href="/favicon/site.webmanifest">
<link rel="mask-icon" href="/favicon/safari-pinned-tab.svg" color="#00aab7">
<link rel="shortcut icon" href="/favicon/favicon.ico">
<meta name="msapplication-TileColor" content="#00aab7">
<meta name="msapplication-config" content="/favicon/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<meta name="Description" content="{{meta.desc}}">
<link rel="stylesheet" href="/assets/{{manifest.main.css}}">
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab:300|Roboto:300,400,700&display=swap" rel="stylesheet">

86
njktags/vue.js Normal file
View File

@ -0,0 +1,86 @@
const path = require("path");
const fs = require("fs");
const Vue = require("vue");
const TemplateCompiler = require("vue-template-compiler");
const VueServerRenderer = require("vue-server-renderer");
const requireFromString = require("require-from-string");
const babel = require("@babel/core");
const manifest = require("../data/manifest.json");
module.exports = function(nunjucksEngine, settings) {
this.tags = ["vue"];
this.nunjucksEngine = nunjucksEngine;
this.parse = function(parser, nodes, lexer) {
let tok = parser.nextToken();
let args = parser.parseSignature(null, true);
parser.advanceAfterBlockEnd(tok.value);
return new nodes.CallExtensionAsync(this, "run", args);
};
this.run = function(context, args, callback) {
const parsedComponent = TemplateCompiler.parseComponent(
fs.readFileSync(
path.join(
__dirname,
"..",
"src",
"js",
"components",
`${args.component}.vue`
),
"utf8"
)
);
const moduleScript = requireFromString(
babel.transformSync(parsedComponent.script.content, {
presets: [["@babel/env", { modules: false, loose: true }]],
plugins: ["@babel/plugin-transform-modules-commonjs"]
}).code
).default;
const renderer = VueServerRenderer.createRenderer({
template: `<!--vue-ssr-outlet-->`
});
moduleScript.template = parsedComponent.template.content;
if (manifest.vue[args.component]) {
moduleScript._scopeId = `data-v-${manifest.vue[args.component]}`;
}
let component = Vue.component(args.component, moduleScript);
let props = "";
let keys = [];
if (args.props) {
props = " ";
Object.keys(args.props).forEach(e => {
let data = args.props[e];
if (typeof data != "string" && typeof data != "undefined") {
data = JSON.stringify(data);
}
props += `${e}='${data}'`;
keys.push(e);
});
}
renderer.renderToString(
new Vue({
props: keys,
template: `<${args.component}${props}></${args.component}>`
}),
(err, result) => {
if (!err) {
callback(null, new nunjucksEngine.runtime.SafeString(result));
} else {
callback(null, err);
}
}
);
};
};

10951
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

61
package.json Normal file
View File

@ -0,0 +1,61 @@
{
"name": "kindling",
"version": "1.0.0",
"description": "The Kindling static site framework",
"main": ".eleventy.js",
"scripts": {
"build": "webpack --env production && eleventy",
"compile": "npx eleventy",
"start": "npm run devserve",
"devserve": "NODE_ENV=development npx babel-node --presets @babel/preset-env ./serve.js",
"spritesheet": "node ./svgsprite.js",
"modernizr": "npx modernizr -c .modernizrrc.json -d src/js/modernizr.js -u",
"generate": "npm run modernizr && npm run spritesheet && npm run build"
},
"author": "Matthew Gaffen",
"license": "ISC",
"devDependencies": {
"@11ty/eleventy": "^0.8.3",
"@babel/core": "^7.5.5",
"@babel/node": "^7.5.0",
"@babel/plugin-transform-modules-commonjs": "^7.5.0",
"@babel/preset-env": "^7.5.5",
"autoprefixer": "^9.6.1",
"babel-loader": "^8.0.6",
"bluebird": "^3.5.5",
"browser-sync": "^2.26.7",
"bs-fullscreen-message": "^1.1.0",
"clean-webpack-plugin": "^3.0.0",
"co": "^4.6.0",
"compression": "^1.7.4",
"css-loader": "^3.0.0",
"debug": "^4.1.1",
"file-loader": "^4.0.0",
"lodash.debounce": "^4.0.8",
"mini-css-extract-plugin": "^0.7.0",
"node-sass": "^4.12.0",
"optimize-js-plugin": "0.0.4",
"panelsnap": "^1.2.2",
"postcss-loader": "^3.0.0",
"require-from-string": "^2.0.2",
"sass-loader": "^7.1.0",
"strip-ansi": "^5.2.0",
"style-loader": "^0.23.1",
"svg-inline-loader": "^0.8.0",
"svgstore": "^3.0.0-2",
"tree-kill": "^1.2.1",
"url-loader": "^2.0.1",
"vue-loader": "^15.7.1",
"vue-server-renderer": "^2.6.10",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.35.3",
"webpack-assets-manifest": "^3.1.1",
"webpack-cli": "^3.3.6"
},
"dependencies": {
"animejs": "^3.0.1",
"core-js": "^3.1.4",
"vue": "^2.6.10",
"waypoints": "^4.0.1"
}
}

167
serve.js Normal file
View File

@ -0,0 +1,167 @@
import Promise from "bluebird";
import co from "co";
import debounce from "lodash.debounce";
import compress from "compression";
import config from "./webpack.config.js";
import webpack from "webpack";
// Set debug variables
process.env.NODE_ENV = process.env.NODE_ENV || "development";
if (!process.env.DEBUG) {
process.env.DEBUG = "browser-sync-server:*,*:info,*:error";
}
const debug = require("debug")("browser-sync-server");
const error = debug.extend("error");
const info = debug.extend("info");
info("debug", process.env.DEBUG);
// Enable gzip
const gz = true;
const browser_sync = require("browser-sync");
const strip_ansi = require("strip-ansi");
const { spawn } = require("child_process");
const kill = require("tree-kill");
const path = require("path");
// Initialize Browsersync and webpack
const sync = browser_sync.create();
let child;
const run_build_command = command =>
new Promise((resolve, reject) => {
child = spawn(command, { stdio: "inherit", shell: true });
child.on("close", (code, signal) => {
if (code || signal) {
reject(`Stopped - code: ${code}, signal: ${signal}`);
} else {
resolve();
}
});
});
const kill_child = pid =>
new Promise((resolve, reject) => {
kill(pid, "SIGTERM", err => {
if (err) {
return reject(err);
}
return resolve();
});
});
function startServer() {
sync.init(
{
server: path.join(__dirname, "build"),
cors: true,
open: true,
logFileChanges: true,
plugins: ["bs-fullscreen-message"],
watchOptions: {
awaitWriteFinish: {
stabilityThreshold: 500,
pollInterval: 100
}
},
files: [
{
match: [
path.join(__dirname, "layouts", "**", "*"),
path.join(__dirname, "src", "content", "**", "*")
],
fn: (event, file) => {
debug(`File changed: ${file}`);
build_site(false);
}
}
// {
// match: [
// path.join(__dirname, "src", "js", "**", "*"),
// path.join(__dirname, "src", "scss", "**", "*"),
// path.join(__dirname, "src", "svg", "**", "*")
// ],
// fn: () => build_site(true, false)
// }
],
middleware: [
(req, res, next) => {
if (!gz) return;
const gzip = compress();
gzip(req, res, next);
}
]
},
(err, bs) => {
if (err) {
error(err);
}
bs.addMiddleware("*", (req, res) => {
res.write("404 mayne");
res.end();
});
}
);
}
// Run build command
const build_site = debounce(
(build_assets = true, build_site = true, file_filter = "") => {
co(function*() {
if (child && typeof child.pid) {
info(`Killing ${child.pid}`);
yield kill_child(child.pid);
}
info("Building Website");
info(`build_assets: ${build_assets}`);
info(`file: ${file_filter}`);
if (build_assets) {
// console.log("Webpack Started");
// console.log("Execute webpack build here");
// yield run_build_command(
// `webpack --env ${process.env.NODE_ENV} --watch`
// );
// console.log("Webpack Finished");
yield run_build_command(`npm run spritesheet`);
}
if (build_site) {
info("Build Started");
const build_command = ["npm run compile"];
yield run_build_command(build_command.join(" "));
info("Build Finished");
}
if (!sync.active) {
startServer();
}
child = void 0;
sync.reload();
}).catch(err => {
sync.sockets.emit("fullscreen:message", {
title: err.name,
body: strip_ansi(`${err.message}\n\n${err.stack}`),
timeout: 5e3
});
});
},
200
);
build_site();
const compiler = webpack(config(process.env.NODE_ENV));
compiler.watch({}, err => {
sync.reload();
});

9
src/content/index.md Normal file
View File

@ -0,0 +1,9 @@
---
layout: "home.njk"
title: "Home"
hideheader: true
---
## This is your homepage!
This is some _markdown formatted_ **content**.

View File

@ -0,0 +1,20 @@
<template lang="html">
<p class="HelloWorld" v-bind:data-message="message">
{{ message }}
</p>
</template>
<script>
export default {
props: { message: { type: String, default: "Hello World!" } },
mounted: function() {
console.log(this.message);
}
};
</script>
<style lang="scss" scoped>
p {
border: 1px solid grey;
}
</style>

View File

@ -0,0 +1,45 @@
<template lang="html">
<div class="ListComp" v-bind:data-startlist="startlist">
<ol>
<li v-for="item in list">
{{ item.message }}
</li>
</ol>
<input v-model="newitem.message" />
<button v-on:click="addItem"></button>
</div>
</template>
<script>
import Vue from "vue";
export default {
props: {
startlist: {
type: Array,
default: function() {
return [{ message: "Add items to me" }];
}
}
},
data: function() {
return {
newitem: { message: "Enter text here" },
list: [].concat([this.startlist])
};
},
mounted: function() {
console.log(this.startlist);
},
methods: {
addItem: function(e) {
this.list = this.list.concat([Object.assign({}, this.newitem)]);
}
}
};
</script>
<style lang="scss" scoped>
ol {
border: 1px solid grey;
}
</style>

20
src/js/main.js Normal file
View File

@ -0,0 +1,20 @@
import "modernizr";
import Vue from "vue";
import HelloWorld from "./components/HelloWorld.vue";
import ListComp from "./components/ListComp.vue";
Array.prototype.forEach.call(document.querySelectorAll(".HelloWorld"), function(
elem
) {
new Vue({
render: h => h(HelloWorld, { props: { message: elem.dataset.message } })
}).$mount(elem);
});
Array.prototype.forEach.call(document.querySelectorAll(".ListComp"), function(
elem
) {
new Vue({
render: h => h(ListComp, { props: { message: elem.dataset.list } })
}).$mount(elem);
});

22
src/scss/base/_base.scss Normal file
View File

@ -0,0 +1,22 @@
html {
font-size: $bodysize;
font-family: $body;
color: $dark;
}
body {
background: $bg;
font-weight: 300;
line-height: $bodyline;
text-align: center;
}
.site {
display: flex;
min-height: 100vh;
flex-direction: column;
}
.site-content {
flex: 1;
}

5
src/scss/base/_form.scss Normal file
View File

@ -0,0 +1,5 @@
input,
button {
font-family: $body;
font-weight: normal;
}

2
src/scss/base/_main.scss Normal file
View File

@ -0,0 +1,2 @@
@import "base";
@import "form";

View File

@ -0,0 +1,21 @@
.fitimg{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
img{
position: absolute;
top: 0;
}
}
.object-fit{
.fitimg{
img{
width: 100%;
height: 100%;
object-fit: cover;
}
}
}

View File

@ -0,0 +1 @@
@import "fitimg";

View File

@ -0,0 +1 @@
@import "normalize";

View File

@ -0,0 +1,519 @@
/*! normalize.css v1.1.2 | MIT License | git.io/normalize */
/* ==========================================================================
HTML5 display definitions
========================================================================== */
/**
* Correct `block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section,
summary {
display: block;
}
/**
* Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address styling not present in IE 7/8/9, Firefox 3, and Safari 4.
* Known issue: no IE 6 support.
*/
[hidden] {
display: none;
}
/* ==========================================================================
Base
========================================================================== */
/**
* 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using
* `em` units.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-size: 100%; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
* Address `font-family` inconsistency between `textarea` and other form
* elements.
*/
/**
* Address margins handled incorrectly in IE 6/7.
*/
body {
margin: 0;
}
/* ==========================================================================
Links
========================================================================== */
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* ==========================================================================
Typography
========================================================================== */
/**
* Address font sizes and margins set differently in IE 6/7.
* Address font sizes within `section` and `article` in Firefox 4+, Safari 5,
* and Chrome.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
h2 {
font-size: 1.5em;
margin: 0.83em 0;
}
h3 {
font-size: 1.17em;
margin: 1em 0;
}
h4 {
font-size: 1em;
margin: 1.33em 0;
}
h5 {
font-size: 0.83em;
margin: 1.67em 0;
}
h6 {
font-size: 0.67em;
margin: 2.33em 0;
}
/**
* Address styling not present in IE 7/8/9, Safari 5, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/**
* Address style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome.
*/
b,
strong {
font-weight: bold;
}
blockquote {
margin: 1em 40px;
}
/**
* Address styling not present in Safari 5 and Chrome.
*/
dfn {
font-style: italic;
}
/**
* Address differences between Firefox and other browsers.
* Known issue: no IE 6/7 normalization.
*/
hr {
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 0;
}
/**
* Address styling not present in IE 6/7/8/9.
*/
mark {
background: #ff0;
color: #000;
}
/**
* Address margins set differently in IE 6/7.
*/
p,
pre {
margin: 1em 0;
}
/**
* Correct font family set oddly in IE 6, Safari 4/5, and Chrome.
*/
code,
kbd,
pre,
samp {
font-family: monospace, serif;
_font-family: 'courier new', monospace;
font-size: 1em;
}
/**
* Improve readability of pre-formatted text in all browsers.
*/
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
/**
* Address CSS quotes not supported in IE 6/7.
*/
q {
quotes: none;
}
/**
* Address `quotes` property not supported in Safari 4.
*/
q:before,
q:after {
content: '';
content: none;
}
/**
* Address inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* ==========================================================================
Lists
========================================================================== */
/**
* Address margins set differently in IE 6/7.
*/
dl,
menu,
ol,
ul {
margin: 1em 0;
}
dd {
margin: 0 0 0 40px;
}
/**
* Address paddings set differently in IE 6/7.
*/
menu,
ol,
ul {
padding: 0 0 0 40px;
}
/**
* Correct list images handled incorrectly in IE 7.
*/
nav ul,
nav ol {
list-style: none;
list-style-image: none;
}
/* ==========================================================================
Embedded content
========================================================================== */
/**
* 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3.
* 2. Improve image quality when scaled in IE 7.
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/**
* Correct overflow displayed oddly in IE 9.
*/
svg:not(:root) {
overflow: hidden;
}
/* ==========================================================================
Figures
========================================================================== */
/**
* Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
*/
figure {
margin: 0;
}
/* ==========================================================================
Forms
========================================================================== */
/**
* Correct margin displayed oddly in IE 6/7.
*/
form {
margin: 0;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct color not being inherited in IE 6/7/8/9.
* 2. Correct text not wrapping in Firefox 3.
* 3. Correct alignment displayed oddly in IE 6/7.
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
*margin-left: -7px; /* 3 */
}
/**
* 1. Correct font size not being inherited in all browsers.
* 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5,
* and Chrome.
* 3. Improve appearance and consistency in all browsers.
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
*vertical-align: middle; /* 3 */
}
/**
* Address Firefox 3+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+.
* Correct `select` style inheritance in Firefox 4+ and Opera.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
* 4. Remove inner spacing in IE 7 without affecting normal text inputs.
* Known issue: inner spacing remains in IE 6.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
*overflow: visible; /* 4 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* 1. Address box sizing set to content-box in IE 8/9.
* 2. Remove excess padding in IE 8/9.
* 3. Remove excess padding in IE 7.
* Known issue: excess padding remains in IE 6.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
*height: 13px; /* 3 */
*width: 13px; /* 3 */
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Remove inner padding and border in Firefox 3+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* 1. Remove default vertical scrollbar in IE 6/7/8/9.
* 2. Improve readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/* ==========================================================================
Tables
========================================================================== */
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}

View File

@ -0,0 +1,91 @@
.gridwrap {
max-width: 1224px;
margin: auto;
position: relative;
padding: 0 10px;
clear: both;
width: 100%;
@extend .group;
@include breakpoint($mobLand + 1) {
padding: 0 20px;
}
}
.col {
border-top: 0;
border-bottom: 0;
float: left;
background-clip: padding-box;
position: relative;
&--centred {
float: none;
margin: auto;
}
}
.col,
.colwrap {
padding: 0 10px;
@include breakpoint($mobLand + 1) {
padding: 0 20px;
}
}
.col--space {
height: 30px;
}
.col__inner {
padding: 0 20px;
}
.col--nopad {
border: none;
padding-left: 0;
padding-right: 0;
}
.col--1-6,
.col--1-4,
.col--3-4,
.col--1-3,
.col--2-3,
.col--1-2,
.col--1,
.col--5-6 {
width: 100%;
}
@include breakpoint($mobLand + 1) {
.col--1-6 {
width: (100% / 6);
}
.col--5-6 {
width: (100% / 6) * 5;
}
.col--1-4 {
width: (100% / 4);
}
.col--3-4 {
width: (100% / 4) * 3;
}
.col--1-3 {
width: (100% / 3);
}
.col--2-3 {
width: (100% / 3) * 2;
}
.col--1-2 {
width: (100% / 2);
}
.vcol--1-2 {
height: 50%;
}
}

View File

@ -0,0 +1 @@
@import "grid";

View File

@ -0,0 +1 @@
@import "variables";

View File

@ -0,0 +1,41 @@
/* ==========================================================================
Colours
========================================================================== */
$black: #000000;
$white: #ffffff;
$link-active: #7393a7;
$dark: #4b4b4b;
$med-dark-grey: #b3b2b2;
$med-grey: #464646;
$med-grey-1: #d2d2d2;
$light-grey-1: #adadad;
$light-grey: #ebebeb;
$white-grey-1: #f1f1f1;
$white-grey: #f8f8f8;
$pipa-navy: #030f1f;
$pipa-teal: #00aab7;
$bg: $white-grey;
/* ==========================================================================
Typography
========================================================================== */
$small: 12px;
$medium: 18px;
$bodysize: $medium;
$bodyline: 1.222;
$body: "Roboto", sans-serif;
$title: "Roboto Slab", serif;
/* ==========================================================================
Media Queries
========================================================================== */
$mobLand: 720px;
$tablet: 1024px;

7
src/scss/styles.scss Normal file
View File

@ -0,0 +1,7 @@
@import "settings/main";
@import "tools/main";
@import "generic/main";
@import "base/main";
@import "objects/main";
@import "components/main";
@import "trumps/main";

View File

@ -0,0 +1,24 @@
@mixin breakpoint($point) {
@if $point == large {
@media (min-width: 64.375em) { @content; }
}
@else if $point == medium {
@media (min-width: $tablet) { @content; }
}
@else if $point == small {
@media (min-width: $mobLand) { @content; }
}
@else {
@media (min-width: $point) { @content; }
}
}
@mixin retina(){
@media
only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and ( min--moz-device-pixel-ratio: 2),
only screen and ( -o-min-device-pixel-ratio: 2/1),
only screen and ( min-device-pixel-ratio: 2),
only screen and ( min-resolution: 192dpi),
only screen and ( min-resolution: 2dppx){ @content; }
}

View File

@ -0,0 +1 @@
@import "breakpoints"

View File

@ -0,0 +1,21 @@
.hide{
display: none;
}
.fullwidth{
width: 100%;
}
img.fullwidth{
width: 100%;
height: auto;
display: block;
}
.floatleft{
float: left;
}
.floatright{
float: right;
}

View File

@ -0,0 +1,61 @@
/* ==========================================================================
Helper classes
========================================================================== */
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
.ir {
background-color: transparent;
border: 0;
overflow: hidden;
*text-indent: -9999px;
}
.ir:before {
content: "";
display: block;
width: 0;
height: 150%;
}
.hidden {
display: none !important;
visibility: hidden;
}
.visuallyhidden {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.visuallyhidden.focusable:active,
.visuallyhidden.focusable:focus {
clip: auto;
height: auto;
margin: 0;
overflow: visible;
position: static;
width: auto;
}
.invisible {
visibility: hidden;
}
.group:after {
content: "";
display: table;
clear: both;
}

View File

@ -0,0 +1,2 @@
@import "helpers";
@import "display";

0
src/svg/.gitkeep Normal file
View File

33
svgsprite.js Normal file
View File

@ -0,0 +1,33 @@
const svgstore = require("svgstore");
const fs = require("fs");
const path = require("path");
const genSVG = () => {
const sprites = svgstore({
cleanDefs: true,
cleanSymbols: true,
symbolAttrs: { fill: null }
});
const srcDir = path.resolve(__dirname, "src", "svg");
fs.readdir(srcDir, (err, files) => {
if (err) {
return console.error("Unable to read directory");
}
files.forEach(file => {
sprites.add(
file.split(".")[0],
fs.readFileSync(`${srcDir}/${file}`, { encoding: "utf-8" })
);
});
fs.writeFileSync(
path.resolve(__dirname, "layouts", "partials", "sprite.svg"),
sprites
);
});
};
return genSVG();

3
webpack.config.js Normal file
View File

@ -0,0 +1,3 @@
const config = require("./webpack/config.js");
module.exports = config;

32
webpack/config.js Normal file
View File

@ -0,0 +1,32 @@
const path = require("path");
const envSettings = require("./environment.config.js");
const getLoaders = require("./loaders.js");
const webpack = require("webpack");
const assetsPath = path.resolve(__dirname, "..", "build", "assets");
module.exports = env => {
let config = {
context: path.resolve(__dirname, ".."),
entry: {
main: ["./src/js/main.js", "./src/scss/styles.scss"]
},
mode: env,
output: {
path: assetsPath,
filename: env == "development" ? "[name].js" : "[name]-[hash].js",
chunkFilename:
env == "development" ? "[name].js" : "[name]-[chunkhash].js",
publicPath: "/assets/"
},
optimization: {
minimize: env === "production"
},
module: {
rules: getLoaders()
}
};
return envSettings(config, env);
};

View File

@ -0,0 +1,88 @@
const OptimizeJsPlugin = require("optimize-js-plugin");
const resolvers = require("./resolvers.js");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const WebpackAssetsManifest = require("webpack-assets-manifest");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const url = require("url");
// Vue config Stuff
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const path = require("path");
const webpack = require("webpack");
const assetsPath = path.resolve(__dirname, "..", "public", "assets");
function isProduction(env) {
return env === "production";
}
function getPlugins(env) {
let plugins = [new webpack.ProgressPlugin({ profile: false })];
return [
new webpack.IgnorePlugin(/\.\/dev/, /\/config$/),
new CleanWebpackPlugin(),
new OptimizeJsPlugin({
sourceMap: !isProduction(env)
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new MiniCssExtractPlugin({
filename: env == "development" ? "[name].css" : "[name]-[chunkhash].css",
chunkFilename: "[id].css"
}),
// Map output assets to eleventy data
new WebpackAssetsManifest({
output: "../../data/manifest.json",
transform: (assets, manifest) => {
// Object to contain final asset map
let output = {};
// Create dedicated asset map for vue components
let vueComponents = {};
Object.keys(manifest.compiler.records).forEach(e => {
if (e.includes(".vue?")) {
// Add vue component to object with component name as key
const compName = e
.match(/\/(.*)\.vue/)[1]
.split("/")
.pop();
vueComponents[compName] = url.parse(e.split(" ")[1], true).query.id;
}
});
// Add vue components to the 'vue' key of the asset manifest
output.vue = vueComponents;
Object.keys(assets).forEach(assetName => {
const batchName = assetName.replace(/\.[^/.]+$/, ""),
outputName = assets[assetName];
if (typeof output[batchName] == "undefined") {
output[batchName] = {};
}
if (outputName.endsWith(".js")) {
output[batchName].js = outputName;
} else if (outputName.endsWith(".css")) {
output[batchName].css = outputName;
}
});
return output;
}
}),
new VueLoaderPlugin()
];
}
module.exports = (config, env, target) => {
if (!isProduction(env)) {
config.devtool = "cheap-module-eval-source-map";
}
config.resolve = resolvers;
config.plugins = getPlugins(env);
config.externals = {
window: "window"
};
config.optimization = { minimize: isProduction(env) };
return config;
};

90
webpack/loaders.js Normal file
View File

@ -0,0 +1,90 @@
const autoprefixer = require("autoprefixer");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const production = JSON.stringify(process.env) === "production";
module.exports = function() {
let cssLoaders = [
{
loader: MiniCssExtractPlugin.loader,
options: {
importLoaders: 1
}
}
],
sassLoaders = [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
importLoaders: 1,
sourceMap: !production,
url: false
}
},
{
loader: "postcss-loader",
options: {
plugins: function(e) {
return [autoprefixer(["last 2 version", "> 1%", "ie 9", "ie 8"])];
},
sourceMap: !production
}
},
{
loader: "sass-loader", // compiles Sass to CSS
options: {
sourceMap: !production
}
}
];
return [
{
test: /\.woff$|\.woff2?$|\.ttf$|\.eot$|\.otf$|\.svg$/,
loader: "file-loader",
options: {
emitFile: false,
name: "[name].[ext]",
publicPath: "fonts"
},
exclude: /src\/svg/
},
{
test: /\.(png|jpg|gif)$/,
loader: "file-loader",
options: {}
},
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
use: "babel-loader"
},
{
test: /\.css$/,
exclude: /node_modules/,
use: cssLoaders
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: sassLoaders
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: "svg-inline-loader",
options: {
removingTagAttrs: ["fill", "stroke"]
}
},
exclude: /src\/fonts/
},
// Loader for Vue files
{
test: /\.vue?$/,
use: "vue-loader"
}
];
};

13
webpack/resolvers.js Normal file
View File

@ -0,0 +1,13 @@
const path = require("path");
module.exports = {
modules: [
path.join(__dirname, "../node_modules"),
path.join(__dirname, "../src")
],
extensions: [".json", ".js"],
alias: {
modernizr$: path.resolve(__dirname, "..", "src", "js", "modernizr.js"),
styles: path.resolve(__dirname, "..", "src", "scss")
}
};