1
0
mirror of https://github.com/locomotivemtl/locomotive-boilerplate.git synced 2026-01-15 00:55:08 +08:00

12 Commits

Author SHA1 Message Date
Deven Caron
6f04e21146 Update README.md 2025-07-24 10:41:30 -04:00
Lucas Vallenet
97b0d57dbd Upgrade packages 2025-07-24 11:37:10 +02:00
Chauncey McAskill
c434d0843f Remove svg4everybody 2025-01-07 13:17:41 -05:00
Chauncey McAskill
5f8767f04d Update NPM dependencies
Updated:
- esbuild v0.24.0 → v0.24.2
- postcss v8.4.47 → v8.4.49
- purgecss v6.0.0 → v7.0.2
2025-01-06 12:11:38 -05:00
Chauncey McAskill
b4ee0955c3 Update NPM dependencies
Updated:
- autoprefixer v10.4.19 → v10.4.20
- esbuild v0.21.5 → v0.21.5
- locomotive-scroll v5.0.0-beta.13 → v5.0.0-beta.21
- micromatch v4.0.4 → v4.0.8
- postcss v8.4.38 → v8.4.47
- svg-mixer v2.4.0 → v2.3.14
2024-10-16 10:54:56 -04:00
Michel Descoteaux
1ec1229fe4 Upgrade sass package to v1.79 (#183)
* Update sass to v1.79

* Fix broken node_modules import

* Fix conflict with new sass color() function

color() -> colorCode()

* build:styles - Remove deprecated sass.render()

* build:styles - remove infile + outfile from sass.compile options
2024-10-16 10:07:10 -04:00
Chauncey McAskill
d593fe5409 Update to NPM v10 + Update dependencies (#179)
* Update NPM constraint and dependencies

Requied:
- NPM v8 → v10

Changed:
- Fixed Node/NPM requirements in README.
- Fixed dependency vulenerabilities.
- Updated dependencies.
- Removed obsolete Node flag `--experimental-json-modules`.
- Replaced obsolete import `assert` keyword with `with`.

* Update gitignore of assets to use wildcards

---------

Co-authored-by: Deven Caron <devencaron@gmail.com>
2024-07-04 13:12:54 -04:00
Chauncey McAskill
f8a46043a6 Remove babel-polyfill (#178)
All features are suported by modern browsers.

Can be restored if ever needed to support older browsers.
2024-07-04 13:12:18 -04:00
Chauncey McAskill
25823286d5 Remove polyfill.io
See: https://sansec.io/research/polyfill-supply-chain-attack
2024-06-25 18:19:00 -04:00
Chauncey McAskill
605f30c948 Fix svg-mixer support for sub-directories
By default, svg-mixer only uses the SVG's file name as its ID. If any SVG files are stored in sub-directories, that information is ignored in the assembled spritesheet. This is problematic since context is lost (the sub-directory's name) and risks duplicate symbol IDs.

This commit introduces a new NPM dependency, `common-path` to resolve the longest common base path, and uses a dependency of `svg-mixer` named `url-slug` in order to prefix the directory name.
2024-04-03 09:29:52 -04:00
Lucas Bigot
27a41aba66 Add default text dedicated file (#173) 2024-04-03 08:29:24 -04:00
Lucas Bigot
353a38915d Update default headings (#172)
* Move font-size css var into dedicated heading file + Add default mixins

* Rename responsive-type for a more generic name
2024-04-03 08:28:57 -04:00
42 changed files with 2691 additions and 5274 deletions

13
.gitignore vendored
View File

@@ -4,15 +4,10 @@ Thumbs.db
loconfig.*.json
!loconfig.example.json
.prettierrc
www/**/*.html
www/assets/scripts/app.js
www/assets/scripts/app.js.map
www/assets/scripts/vendors.js
www/assets/styles/main.css
www/assets/styles/main.css.map
www/assets/styles/critical.css
www/assets/styles/critical.css.map
www/assets/scripts/*
!www/assets/scripts/.gitkeep
www/assets/styles/*
!www/assets/styles/.gitkeep
assets.json

2
.nvmrc
View File

@@ -1 +1 @@
v20.10
v20

View File

@@ -1,3 +1,6 @@
> [!WARNING]
> This repository is no longer maintained. We recommend checking out our [Astro](https://github.com/locomotivemtl/astro-boilerplate) or [Craft](https://github.com/locomotivemtl/craft-boilerplate) boilerplates instead.
<p align="center">
<a href="https://github.com/locomotivemtl/locomotive-boilerplate">
<img src="https://user-images.githubusercontent.com/4596862/54868065-c2aea200-4d5e-11e9-9ce3-e0013c15f48c.png" height="140">
@@ -23,8 +26,8 @@ Learn more about [languages and technologies](docs/technologies.md).
Make sure you have the following installed:
* [Node] — at least 17.9, the latest LTS is recommended.
* [NPM] — at least 8.0, the latest LTS is recommended.
* [Node] — at least 20, the latest LTS is recommended.
* [NPM] — at least 10, the latest LTS is recommended.
> 💡 You can use [NVM] to install and use different versions of Node via the command-line.

View File

@@ -1,4 +1,3 @@
import svg4everybody from 'svg4everybody';
import { ENV } from './config';
// Dynamic imports for development mode only
@@ -11,11 +10,6 @@ let gridHelper;
})();
export default function () {
/**
* Use external SVG spritemaps
*/
svg4everybody();
/**
* Add grid helper
*/

View File

@@ -27,7 +27,7 @@ $input-icon-color: 424242; // No #
.c-form_input {
padding: rem(10px);
border: 1px solid lightgray;
background-color: color(lightest);
background-color: colorCode(lightest);
&:hover {
border-color: darkgray;
@@ -71,7 +71,7 @@ $checkbox-icon-color: $input-icon-color;
}
&::before {
background-color: color(lightest);
background-color: colorCode(lightest);
border: 1px solid lightgray;
}

View File

@@ -2,30 +2,78 @@
// Components / Headings
// ==========================================================================
// Font sizes
// ==========================================================================
:root {
// Default
--font-size-h1: #{responsive-value(38px, 90px, $from-xl)};
--font-size-h2: #{responsive-value(34px, 72px, $from-xl)};
--font-size-h3: #{responsive-value(28px, 54px, $from-xl)};
--font-size-h4: #{responsive-value(24px, 40px, $from-xl)};
--font-size-h5: #{responsive-value(20px, 30px, $from-xl)};
--font-size-h6: #{responsive-value(18px, 23px, $from-xl)};
}
// Mixins
// ==========================================================================
@mixin heading {
font-family: ff('sans');
font-weight: $font-weight-medium;
}
@mixin heading-h1 {
font-size: var(--font-size-h1);
line-height: 1.1;
}
@mixin heading-h2 {
font-size: var(--font-size-h2);
line-height: 1.1;
}
@mixin heading-h3 {
font-size: var(--font-size-h3);
line-height: 1.1;
}
@mixin heading-h4 {
font-size: var(--font-size-h4);
line-height: 1.2;
}
@mixin heading-h5 {
font-size: var(--font-size-h5);
line-height: 1.2;
}
@mixin heading-h6 {
font-size: var(--font-size-h6);
line-height: 1.4;
}
// Styles
// ==========================================================================
.c-heading {
margin-bottom: rem(30px);
@include heading;
&.-h1 {
font-size: var(--font-size-h1);
@include heading-h1;
}
&.-h2 {
font-size: var(--font-size-h2);
@include heading-h2;
}
&.-h3 {
font-size: var(--font-size-h3);
@include heading-h3;
}
&.-h4 {
font-size: var(--font-size-h4);
@include heading-h4;
}
&.-h5 {
font-size: var(--font-size-h5);
@include heading-h5;
}
&.-h6 {
font-size: var(--font-size-h6);
@include heading-h6;
}
}

View File

@@ -25,7 +25,7 @@
position: absolute;
top: 0;
right: 0;
background-color: color(darkest);
background-color: colorCode(darkest);
opacity: 0.5;
width: 7px;
border-radius: 10px;

View File

@@ -0,0 +1,53 @@
// ==========================================================================
// Components / Texts
// ==========================================================================
// Font sizes
// ==========================================================================
:root {
--font-size-body-regular: #{responsive-value(15px, 17px, $from-lg)};
--font-size-body-medium: #{responsive-value(18px, 23px, $from-lg)};
--font-size-body-small: #{responsive-value(13px, 16px, $from-lg)};
}
// Mixins
// ==========================================================================
@mixin text {
font-family: ff('sans');
}
@mixin body-regular {
font-size: var(--font-size-body-regular);
font-weight: $font-weight-normal;
line-height: 1.2;
}
@mixin body-medium {
font-size: var(--font-size-body-medium);
font-weight: $font-weight-normal;
line-height: 1.2;
}
@mixin body-small {
font-size: var(--font-size-body-small);
font-weight: $font-weight-normal;
line-height: 1.2;
}
// Styles
// ==========================================================================
.c-text {
@include text;
&.-body-regular {
@include body-regular;
}
&.-body-medium {
@include body-medium;
}
&.-body-small {
@include body-small;
}
}

View File

@@ -32,7 +32,7 @@
// Vendors
// ==========================================================================
@import "node_modules/locomotive-scroll/dist/locomotive-scroll";
@import "../../node_modules/locomotive-scroll/dist/locomotive-scroll";
// Elements
// ==========================================================================
@@ -54,6 +54,7 @@
// ==========================================================================
@import "components/heading";
@import "components/text";
@import "components/button";
@import "components/form";

View File

@@ -1,3 +1,5 @@
@use 'sass:color';
// ==========================================================================
// Settings / Config / Colors
// ==========================================================================
@@ -18,7 +20,7 @@ $colors: (
//
// ```scss
// .c-box {
// color: color(primary);
// color: colorCode(primary);
// }
// ```
//
@@ -26,7 +28,7 @@ $colors: (
// @param {number} $alpha - The alpha for the color value.
// @return {color}
@function color($key, $alpha: 1) {
@function colorCode($key, $alpha: 1) {
@if not map-has-key($colors, $key) {
@error "Unknown '#{$key}' in $colors.";
}
@@ -44,13 +46,13 @@ $colors: (
// ==========================================================================
// Link
$color-link: color(primary);
$color-link-focus: color(primary);
$color-link-hover: darken(color(primary), 10%);
$color-link: colorCode(primary);
$color-link-focus: colorCode(primary);
$color-link-hover: color.adjust(colorCode(primary), $lightness: -10%);
// Selection
$color-selection-text: color(darkest);
$color-selection-background: color(lightest);
$color-selection-text: colorCode(darkest);
$color-selection-background: colorCode(lightest);
// Socials
$color-facebook: #3B5998;

View File

@@ -17,7 +17,7 @@ $assets-path: "../" !default;
// Base
$font-size: 16px;
$line-height: math.div(24px, $font-size);
$font-color: color(darkest);
$font-color: colorCode(darkest);
// Weights
$font-weight-light: 300;

View File

@@ -12,19 +12,6 @@
// Container
--container-width: calc(100% - 2 * var(--grid-margin));
// Font sizes
--font-size-h1: #{responsive-type(36px, 72px, 1400px)};
--font-size-h2: #{rem(28px)};
--font-size-h3: #{rem(24px)};
--font-size-h4: #{rem(20px)};
--font-size-h5: #{rem(18px)};
--font-size-h6: #{rem(16px)};
// // Colors
// @each $color, $value in $colors {
// --color-#{"" + $color}: #{$value};
// }
@media (min-width: $from-sm) {
--grid-columns: #{$base-column-nb};
--grid-gutter: #{rem(16px)};

View File

@@ -196,11 +196,11 @@ $context: 'frontend' !default;
//
// ```scss
// .c-heading.-h1 {
// font-size: responsive-type(30px, 60px, 1800);
// font-size: responsive-value(30px, 60px, 1800);
// }
//
// .c-heading.-h2 {
// font-size: responsive-type(20px, 40px, $from-xl);
// font-size: responsive-value(20px, 40px, $from-xl);
// }
// ```
//
@@ -208,7 +208,7 @@ $context: 'frontend' !default;
// @param {number} $max-size - Maximum font size in pixels.
// @param {number} $breakpoint - Maximum breakpoint.
// @return {function<number, function<number>, number>}
@function responsive-type($min-size, $max-size, $breakpoint) {
@function responsive-value($min-size, $max-size, $breakpoint) {
$delta: math.div($max-size, $breakpoint);
@return clamp($min-size, calc(#{strip-unit($delta)} * #{vw(100)}), $max-size);
}

View File

@@ -1,11 +1,9 @@
import buildEleventy from './tasks/eleventy.js';
import concatFiles from './tasks/concats.js';
import compileScripts from './tasks/scripts.js';
import compileStyles from './tasks/styles.js';
import compileSVGs from './tasks/svgs.js';
import bumpVersions from './tasks/versions.js';
buildEleventy();
concatFiles();
compileScripts();
compileStyles();

View File

@@ -2,14 +2,14 @@
* @file Provides simple user configuration options.
*/
import loconfig from '../../loconfig.json' assert { type: 'json' };
import loconfig from '../../loconfig.json' with { type: 'json' };
import { merge } from '../utils/index.js';
let usrconfig;
try {
usrconfig = await import('../../loconfig.local.json', {
assert: { type: 'json' },
with: { type: 'json' },
});
usrconfig = usrconfig.default;

View File

@@ -1,50 +0,0 @@
import message from '../helpers/message.js';
import { merge } from '../utils/index.js';
import Eleventy from "@11ty/eleventy";
export const defaultEleventyOptions = {
production: true
}
export const developmentEleventyOptions = {
production: false
}
export const productionEleventyOptions = {
production: true
}
let elev;
export default async function buildEleventy(eleventyOptions = null) {
if (eleventyOptions == null) {
eleventyOptions = productionEleventyOptions;
} else if (
eleventyOptions !== developmentEleventyOptions &&
eleventyOptions !== productionEleventyOptions
) {
eleventyOptions = merge({}, defaultEleventyOptions, eleventyOptions);
}
const { production } = eleventyOptions;
const timeLabel = `11ty compiled in`;
console.time(timeLabel);
try {
if(!elev) {
elev = new Eleventy();
if(!production) {
await elev.watch();
}
}
// Disable caching to ensure a fresh build each time
await elev.write();
message(`11ty compiled`, 'success', timeLabel);
} catch(err) {
console.error(err)
message(err, 'error', timeLabel);
}
}

View File

@@ -10,12 +10,9 @@ import resolve from '../helpers/template.js';
import { merge } from '../utils/index.js';
import { writeFile } from 'node:fs/promises';
import { basename } from 'node:path';
import { promisify } from 'node:util';
import * as sass from 'sass';
import { PurgeCSS } from 'purgecss';
const sassRender = promisify(sass.render);
let postcssProcessor;
/**
@@ -24,16 +21,15 @@ let postcssProcessor;
* @const {object} productionSassOptions - The predefined Sass options for production.
*/
export const defaultSassOptions = {
omitSourceMapUrl: true,
sourceMapIncludeSources: true,
sourceMap: true,
sourceMapContents: true,
};
export const developmentSassOptions = Object.assign({}, defaultSassOptions, {
outputStyle: 'expanded',
style: 'expanded',
});
export const productionSassOptions = Object.assign({}, defaultSassOptions, {
outputStyle: 'compressed',
style: 'compressed',
});
/**
@@ -127,10 +123,7 @@ export default async function compileStyles(sassOptions = null, postcssOptions =
infile = resolve(infile);
outfile = resolve(outfile);
let result = await sassRender(Object.assign({}, sassOptions, {
file: infile,
outFile: outfile,
}));
let result = sass.compile(infile, sassOptions);
if (supportsPostCSS && postcssOptions) {
if (typeof postcssProcessor === 'undefined') {

View File

@@ -1,21 +1,36 @@
import loconfig from '../helpers/config.js';
import glob, { supportsGlob } from '../helpers/glob.js';
import message from '../helpers/message.js';
import notification from '../helpers/notification.js';
import resolve from '../helpers/template.js';
import { resolve as resolveTemplate } from '../helpers/template.js';
import { merge } from '../utils/index.js';
import { basename } from 'node:path';
import {
basename,
dirname,
extname,
resolve,
} from 'node:path';
import commonPath from 'common-path';
import mixer from 'svg-mixer';
import slugify from 'url-slug';
const basePath = loconfig?.paths?.svgs?.src
? resolve(loconfig.paths.svgs.src)
: null;
/**
* @const {object} defaultMixerOptions - The default shared Mixer options.
* @const {object} developmentMixerOptions - The predefined Mixer options for development.
* @const {object} productionMixerOptions - The predefined Mixer options for production.
* @const {object} defaultMixerOptions - The default shared Mixer options.
*/
export const defaultMixerOptions = {
spriteConfig: {
usages: false,
},
};
/**
* @const {object} developmentMixerOptions - The predefined Mixer options for development.
* @const {object} productionMixerOptions - The predefined Mixer options for production.
*/
export const developmentMixerOptions = Object.assign({}, defaultMixerOptions);
export const productionMixerOptions = Object.assign({}, defaultMixerOptions);
@@ -74,10 +89,52 @@ export default async function compileSVGs(mixerOptions = null) {
includes = [ includes ];
}
includes = resolve(includes);
outfile = resolve(outfile);
includes = resolveTemplate(includes);
outfile = resolveTemplate(outfile);
const result = await mixer(includes, mixerOptions);
if (supportsGlob && basePath) {
includes = await glob(includes);
includes = [ ...new Set(includes) ];
const common = commonPath(includes);
if (common.commonDir) {
common.commonDir = resolve(common.commonDir);
}
/**
* Generates the `<symbol id>` attribute and prefix any
* SVG files in subdirectories according to the paths
* common base path.
*
* Example for SVG source path `./assets/images/sprite`:
*
* | Path | ID |
* | ------------------------------------ | --------- |
* | `./assets/images/sprite/foo.svg` | `foo` |
* | `./assets/images/sprite/baz/qux.svg` | `baz-qux` |
*
* @param {string} path - The absolute path to the file.
* @param {string} [query=''] - A query string.
* @return {string} The symbol ID.
*/
mixerOptions.generateSymbolId = (path, query = '') => {
let dirName = dirname(path)
.replace(common.commonDir ?? basePath, '')
.replace(/^\/|\/$/, '')
.replace('/', '-');
if (dirName) {
dirName += '-';
}
const fileName = basename(path, extname(path));
const decodedQuery = decodeURIComponent(decodeURIComponent(query));
return `${dirName}${fileName}${slugify(decodedQuery)}`;
};
}
const result = await mixer(includes, {
...mixerOptions,
});
await result.write(outfile);

View File

@@ -2,7 +2,6 @@ import concatFiles, { developmentConcatFilesArgs } from './tasks/concats.js';
import compileScripts, { developmentScriptsArgs } from './tasks/scripts.js';
import compileStyles, { developmentStylesArgs } from './tasks/styles.js' ;
import compileSVGs, { developmentSVGsArgs } from './tasks/svgs.js';
import buildEleventy, { developmentEleventyOptions } from './tasks/eleventy.js';
import loconfig from './helpers/config.js';
import message from './helpers/message.js';
import notification from './helpers/notification.js';
@@ -20,7 +19,6 @@ concatFiles(...developmentConcatFilesArgs);
compileScripts(...developmentScriptsArgs);
compileStyles(...developmentStylesArgs);
compileSVGs(...developmentSVGsArgs);
await buildEleventy(developmentEleventyOptions);
// Create a new BrowserSync instance
const server = browserSync.create();
@@ -55,7 +53,10 @@ function configureServer(server, { paths, tasks }) {
// Reload on any changes to views or processed files
server.watch(
[
join(paths.dest, '**/*')
...views,
join(paths.scripts.dest, '*.js'),
join(paths.styles.dest, '*.css'),
join(paths.svgs.dest, '*.svg'),
]
).on('change', server.reload);

View File

@@ -1,4 +0,0 @@
{
"title": "Locomotive Boilerplate",
"description": "Front-end boilerplate for projects by Locomotive."
}

View File

@@ -1,34 +0,0 @@
[
{
"title": "Lusail Stadium",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Scelerisque viverra mauris in aliquam sem fringilla ut morbi tincidunt. In dictum non consectetur a erat nam at lectus urna. Ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue."
},
{
"title": "Tottenham Hotspur Stadium",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing. Eget mi proin sed libero enim sed. Tincidunt id aliquet risus feugiat in ante metus."
},
{
"title": "Narendra Modi Stadium",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae tempus quam pellentesque nec nam aliquam. Velit laoreet id donec ultrices tincidunt. Tincidunt lobortis feugiat vivamus at augue eget arcu."
},
{
"title": "Texas A&M Kyle Field",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Adipiscing diam donec adipiscing tristique risus nec feugiat in fermentum. Integer malesuada nunc vel risus commodo viverra maecenas accumsan. Dui faucibus in ornare quam viverra orci sagittis."
},
{
"title": "The Cathedral — A New Icon for Milan",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Scelerisque viverra mauris in aliquam sem fringilla ut morbi tincidunt. In dictum non consectetur a erat nam at lectus urna. Ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue."
},
{
"title": "Allianz Field",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing. Eget mi proin sed libero enim sed. Tincidunt id aliquet risus feugiat in ante metus."
},
{
"title": "TQL Stadium",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae tempus quam pellentesque nec nam aliquam. Velit laoreet id donec ultrices tincidunt. Tincidunt lobortis feugiat vivamus at augue eget arcu."
},
{
"title": "Groupama Stadium and Training Centre",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Adipiscing diam donec adipiscing tristique risus nec feugiat in fermentum. Integer malesuada nunc vel risus commodo viverra maecenas accumsan. Dui faucibus in ornare quam viverra orci sagittis."
}
]

View File

@@ -1,71 +0,0 @@
// Import required modules
const twig = require("twig");
const fs = require('fs')
const eleventyPluginTwig = require("@factorial/eleventy-plugin-twig");
// Export Eleventy configuration
module.exports = function(eleventyConfig) {
// Function to generate a version identifier
function generateVersion() {
// You can use a timestamp, a hash of asset files, or any other method you prefer
return Date.now();
}
eleventyConfig.setServerOptions({
enabled: false,
});
eleventyConfig.addWatchTarget("views/**/*");
// Use twig
eleventyConfig.addPlugin(eleventyPluginTwig, {
twig: {
namespaces: {
layouts: "views/layouts",
partials: "views/partials",
snippets: "views/snippets"
}
},
dir: {
input: 'views/templates',
output: 'www'
}
});
twig.extendFilter("log", function(value) {
return '<pre>'+JSON.stringify(value)+'</pre>';
});
twig.extendFilter("slug", function(str) {
return str
.toLowerCase() // Convert the string to lowercase
.replace(/\s+/g, '-') // Replace spaces with dashes
.replace(/[^\w-]/g, '') // Remove non-word characters
.replace(/--+/g, '-') // Replace consecutive dashes with a single dash
.trim(); // Trim any leading or trailing dashes
})
// // Add a filter to append the version to asset URLs
twig.extendFilter('version', function(url) {
const version = generateVersion();
return `${url}?v=${version}`;
});
twig.extendFunction("critical_css", function() {
try {
return fs.readFileSync('./www/assets/styles/critical.css', 'utf-8')
} catch(error) {
return '';
}
});
// Configure and return Eleventy settings
return {
templateFormats: ['twig'],
dir: {
input: 'views/templates',
output: 'www',
data: '../../data'
}
};
};

View File

@@ -19,10 +19,7 @@
"dest": "./www/assets/images"
},
"views": {
"src": "./views/"
},
"data": {
"src": "./data/"
"src": "./www/"
}
},
"tasks": {

6481
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,42 +6,42 @@
"author": "Locomotive <info@locomotive.ca>",
"type": "module",
"engines": {
"node": "20.x",
"npm": ">=8.0"
"node": ">=20",
"npm": ">=10"
},
"scripts": {
"start": "node --experimental-json-modules --no-warnings build/watch.js",
"build": "node --experimental-json-modules --no-warnings build/build.js"
"start": "node --no-warnings build/watch.js",
"build": "node --no-warnings build/build.js"
},
"dependencies": {
"locomotive-scroll": "^5.0.0-beta.11",
"locomotive-scroll": "^5.0.0-beta.21",
"modujs": "^1.4.2",
"modularload": "^1.2.6",
"svg4everybody": "^2.1.9"
"modularload": "^1.2.6"
},
"devDependencies": {
"@11ty/eleventy": "^2.0.1",
"@11ty/eleventy-img": "^3.1.8",
"@factorial/eleventy-plugin-twig": "^0.1.2",
"autoprefixer": "^10.4.17",
"browser-sync": "^3.0.2",
"autoprefixer": "^10.4.21",
"browser-sync": "^3.0.4",
"common-path": "^1.0.1",
"concat": "^1.0.3",
"esbuild": "^0.20.0",
"esbuild": "^0.25.8",
"kleur": "^4.1.5",
"node-notifier": "^10.0.1",
"postcss": "^8.4.21",
"purgecss": "^5.0.0",
"sass": "^1.70.0",
"svg-mixer": "~2.3.14",
"tiny-glob": "^0.2.9",
"twig": "^1.17.1"
"postcss": "^8.5.6",
"purgecss": "^7.0.2",
"sass": "^1.89.2",
"svg-mixer": "^2.3.14",
"tiny-glob": "^0.2.9"
},
"overrides": {
"browser-sync": {
"ua-parser-js": "~1.0.33"
"ua-parser-js": "^1.0.33"
},
"svg-mixer": {
"postcss": "^8.4.20"
"micromatch": "^4.0.8",
"postcss": "^8.4.49"
},
"svg-mixer-utils": {
"anymatch": "^3.1.3"
}
}
}

View File

@@ -1,48 +0,0 @@
<!doctype html>
<html class="is-loading" lang="en" data-page="images">
<head>
<meta charset="utf-8">
<base href="/">
<title>{% if title %}{{ title }} | {% endif %}{{ metadata.title }}</title>
<meta name="description" content="{% if description %}{{description}}{% else %}{{ metadata.description }}{% endif %}">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print" onload="this.media='all'; this.onload=null; this.isLoaded=true">
</head>
<body data-module-load>
<div data-load-container>
{% block beforeMain %}
<div data-module-scroll="main">
{% include "@partials/header.twig" %}
{% endblock %}
<main>
{% block content %}{% endblock %}
{% block afterContent %}
{% include "@partials/footer.twig" %}
{% endblock %}
</main>
{% block afterMain %}
</div>
{% endblock %}
</div>
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js" crossorigin="anonymous"></script>
<script nomodule src="https://polyfill.io/v3/polyfill.min.js?features=Element.prototype.remove%2CElement.prototype.append%2Cfetch%2CCustomEvent%2CElement.prototype.matches%2CNodeList.prototype.forEach%2CAbortController" crossorigin="anonymous"></script>
<script src="assets/scripts/vendors.js" defer></script>
<script src="assets/scripts/app.js" defer></script>
</body>
</html>

View File

@@ -1,5 +0,0 @@
<footer class="o-container">
<p>Made by Locomotive<br>
<a href="https://github.com/locomotivemtl/locomotive-boilerplate" title="Locomotive Boilerplate" target="_blank" rel="noopener">Github</a>
</p>
</footer>

View File

@@ -1,11 +0,0 @@
<header class="o-container">
<h1><a href="/">Locomotive Boilerplate</a></h1>
<nav>
<ul>
<li><a href="/grid">Grid</a></li>
<li><a href="/form" data-load="customTransition">Form</a></li>
<li><a href="/wysiwyg">Wysiwyg</a></li>
<li><a href="/projects">Projects</a></li>
</ul>
</nav>
</header>

View File

@@ -1,51 +0,0 @@
{# --- Parameters ------------------------- #}
{% set _tag = tag | default('button') %}
{% set _href = href | default(null) %}
{% set _external = external ?? false %}
{% set _classes = classes | default(null) %}
{% set _modifiers = modifiers | default(null) %}
{% set _label = label | default(null) %}
{% set _icon = icon | default(null) %}
{% set _attr = attr | default(null) %}
{# --- Computed --------------------------- #}
{% if _href != null %}
{% set _tag = 'a' %}
{% elseif _tag == 'a' %}
{% set _tag = 'span' %}
{% endif %}
{% if _classes != null %}
{% set _classes = ' ' ~ _classes %}
{% endif %}
{% if _modifiers != null %}
{% set _classes = ' ' ~ _modifiers ~ ' ' ~ _classes %}
{% endif %}
{# ---------------------------------------- #}
<{{ _tag }}
class="c-button{{ _classes }}"
{% if _href %}href="{{ _href }}"{% endif %}
{% if _external %}target="_blank" rel="noopener noreferrer" data-load="false"{% endif %}
{% if _attr %}{{ _attr | raw }}{% endif %}
>
{% block inner %}
<span class="c-button_inner">
{% if _label %}
<span class="c-button_label">
{{ _label }}
</span>
{% endif %}
{% if _icon %}
{% include "@snippets/icon.twig" with {
icon: _icon,
classes: 'c-button_icon',
} only %}
{% endif %}
</span>
{% endblock %}
</{{ _tag }}>

View File

@@ -1,15 +0,0 @@
{# --- Parameters ------------------------- #}
{% set _icon = icon %}
{% set _classes = classes | default(null) %}
{% set _modifiers = modifiers | default(null) %}
{# ---------------------------------------- #}
{% if _icon %}
<span class="o-icon {{ _classes }} {{ _modifiers }}">
<svg class="svg-{{ _icon }}" focusable="false" aria-hidden="true">
<use xlink:href="#{{ _icon }}"></use>
</svg>
</span>
{% endif %}

View File

@@ -1,95 +0,0 @@
{#
Image snippet
The `img` parameter was made to receive formatted data from a CMS.
The use case would be to output an image without overriding is dimensions or other properties.
It needs to be an object with the following keys :
-src: String,
-width: Int,
-height: Int,
-alt?: String,
-caption?: String
```twig
{% include '@snippets/image.twig' with
img: project.featured_image
%}
```
#}
{# Defaults #}
{% set _width = img.width | default(1) %}
{% set _height = img.height | default(1) %}
{% set _src = img.src | default(null) %}
{% set _alt = img.alt | default(null) %}
{% set _caption = img.caption | default(null) %}
{% set _attr = attr | default(null) %}
{% set _has_parallax = has_parallax | default(null) %}
{% set _parallax_speed = parallax_speed | default('-0.1') %}
{# Override properties #}
{% set _width = width | default(_width) %}
{% set _height = height | default(_height) %}
{% set _src = src | default(_src) %}
{% set _alt = alt | default(_alt) %}
{% set _caption = caption | default(_caption) %}
{# Misc. #}
{% set _is_figure = is_figure | default(false) %}
{% set _is_lazy_load = is_lazy_load | default(true) %}
{% set _tag = _is_figure ? 'figure' : 'div' %}
{# Classes & modifiers #}
{% set _classes = classes | default(null) %}
{% set _modifiers = modifiers | default(null) %}
{% if _has_parallax %}
{% set _modifiers = _modifiers ~ ' -parallax' %}
{% endif %}
{% if _is_lazy_load %}
{% set _modifiers = _modifiers ~ ' -lazy-load' %}
{% set _loading = 'lazy' %}
{% else %}
{% set _loading = 'eager' %}
{% endif %}
{% if _classes != null %}
{% set _classes = ' ' ~ _classes %}
{% endif %}
{% if _modifiers != null %}
{% set _classes = ' ' ~ _modifiers ~ ' ' ~ _classes %}
{% endif %}
{# ---------------------------------------- #}
<{{_tag}} class="c-image{{ _classes }}" {{_attr}}>
<div
class="c-image_inner"
{% if has_parallax %}
data-scroll
data-scroll-speed="{{ _parallax_speed }}"
{% endif %}
>
<img
class="c-image_img"
src="{{ _src }}"
alt="{{ _alt }}"
width="{{ _width }}"
height="{{ _height }}"
loading="{{ _loading }}"
onload="this.closest('.c-image')?.classList?.add('is-loaded');"
>
</div>
{% if _caption %}
{% if _is_figure %}
<figcaption class="c-image_description">{{ _caption }}</figcaption>
{% else %}
<div class="c-image_description"><span>{{ _caption }}</span></div>
{% endif %}
{% endif %}
</{{ _tag }}>

View File

@@ -1,61 +0,0 @@
{% extends "@layouts/base.twig" %}
{% block content %}
<div class="o-container">
<h1 class="c-heading -h1">Page</h1>
<div class="o-layout">
<div class="o-layout_item u-1/2@from-small">
<form class="c-form">
<div class="c-form_item">
<label class="c-form_label" for="input">Input</label>
<input class="c-form_input" type="text" id="input">
</div>
<div class="c-form_item">
<div class="o-layout -gutter">
<div class="o-layout_item u-1/2">
<input class="c-form_checkbox" type="checkbox" id="checkbox">
<label class="c-form_checkboxLabel" for="checkbox">Checkbox</label>
</div>
<div class="o-layout_item u-1/2">
<input class="c-form_checkbox" type="checkbox" id="checkbox2">
<label class="c-form_checkboxLabel" for="checkbox2">Checkbox 2</label>
</div>
</div>
</div>
<div class="c-form_item">
<div class="o-layout -gutter">
<div class="o-layout_item u-1/2">
<input class="c-form_radio" type="radio" name="radio" id="radio">
<label class="c-form_radioLabel" for="radio">Radio</label>
</div>
<div class="o-layout_item u-1/2">
<input class="c-form_radio" type="radio" name="radio" id="radio2">
<label class="c-form_radioLabel" for="radio2">Radio 2</label>
</div>
</div>
</div>
<div class="c-form_item">
<label class="c-form_label" for="select">Select</label>
<div class="c-form_select">
<select class="c-form_select_input" id="select">
<option value="option">Option</option>
<option value="option2">Option 2</option>
<option value="option3">Option 3</option>
</select>
</div>
</div>
<div class="c-form_item">
<label class="c-form_label" for="textarea">Textarea</label>
<textarea class="c-form_textarea" id="textarea"></textarea>
</div>
<button class="c-button" type="submit">
Submit
</button>
</form>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,29 +0,0 @@
{% extends "@layouts/base.twig" %}
{% block content %}
<div class="o-container">
<h1 class="c-heading -h1">Hello</h1>
<div class="o-grid -col-4 -col-12@from-md -gutters">
<div class="o-grid_item u-gc-1/8@from-md" style="background-color: gray;">
<h2 class="c-heading -h2">This grid has 4 columns and 12 columns from `md` MQ</h2>
</div>
<div class="o-grid_item u-gc-1/5@from-md" style="background-color: yellow;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-5/9@from-md" style="background-color: red;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-9/13@from-md" style="background-color: blue;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-1/3 u-gc-5/13@from-md" style="background-color: pink;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,89 +0,0 @@
{% extends "@layouts/base.twig" %}
{% block content %}
<div data-module-scroll="main">
<div class="o-container">
<h1 class="c-heading -h1">Images</h1>
<section>
<h2 class="c-heading -h2">Lazy load demo</h2>
<h3 class="c-heading -h3">Basic</h3>
<div style="width: 640px; max-width: 100%;">
<div class="o-ratio u-4:3"><img data-load-src="http://picsum.photos/800/600?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
<div class="o-ratio u-4:3"><img data-load-src="http://picsum.photos/800/600?v=2" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
</div>
<h4 class="c-heading -h3">Using o-ratio & background-image</h3>
<div style="width: 480px; max-width: 100%;">
<div class="o-ratio u-16:9" data-load-style="background-size: cover; background-position: center; background-image: url(http://picsum.photos/640/480?v=1);"></div>
<div class="o-ratio u-16:9" data-load-style="background-size: cover; background-position: center; background-image: url(http://picsum.photos/640/480?v=2);"></div>
</div>
</section>
<section>
<h3 class="c-heading -h3">Relative to scroll</h3>
<h4 class="c-heading -h3">Using o-ratio & img</h3>
<div style="width: 640px; max-width: 100%;">
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=2" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=3" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=4" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=5" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
</div>
<h4 class="c-heading -h3">Using o-ratio & background-image</h3>
<div style="width: 480px; max-width: 100%;">
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=1"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=2"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=3"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=4"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=5"></div>
</div>
<h4 class="c-heading -h3">Using SVG viewport for ratio</h3>
<div style="width: 480px; max-width: 100%;">
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=6"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=7"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=8"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
</div>
</section>
</div>
</div>
{% endblock %}

View File

@@ -1,54 +0,0 @@
---
title: Home
---
{% extends "@layouts/base.twig" %}
{% block content %}
<div class="o-container">
{# ====================== #}
{# ====== Headings ====== #}
{# ====================== #}
<h1 class="c-heading -h1">Heading 1</h1>
<h1 class="c-heading -h2">Heading 2</h1>
<h1 class="c-heading -h3">Heading 3</h1>
<h1 class="c-heading -h4">Heading 4</h1>
<h1 class="c-heading -h5">Heading 5</h1>
<h1 class="c-heading -h6">Heading 6</h1>
<hr>
{# ======================= #}
{# ======== Texts ======== #}
{# ======================= #}
<p class="c-text -body-regular" style="max-width: 500px">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Totam libero, sit pariatur voluptatum amet magni odio ducimus! Saepe facere iste porro voluptatem. Tenetur perferendis ea a quasi vitae! Ullam, blanditiis.
</p>
<hr>
{# ======================= #}
{# ======= Buttons ======= #}
{# ======================= #}
{% include "@snippets/button.twig" with {
label: 'Button'
} %}
<hr>
{# ====================== #}
{# ======= Images ======= #}
{# ====================== #}
{% include "@snippets/image.twig" with {
src: 'http://picsum.photos/800/600?v=1',
width: 800,
height: 600
} %}
</div>
{% endblock %}

View File

@@ -1,16 +0,0 @@
---
pagination:
data: projects
size: 1
alias: project
permalink: "project/{{ project.title | slug }}/index.html"
---
{% extends "@layouts/base.twig" %}
{% block content %}
<div data-module-scroll="main">
<h1 class="c-heading -h1">{{project.title}}</h1>
<p>{{project.desc}}</p>
</div>
{% endblock %}

View File

@@ -1,30 +0,0 @@
---
pagination:
data: projects
size: 4
---
{% extends "@layouts/base.twig" %}
{% block content %}
<div data-module-scroll="main">
<h1 class="c-heading -h1">Projects</h1>
<ul>
{% for item in pagination.items %}
<li><a href="/project/{{item.title|slug}}">{{ item.title }}</a></li>
{% endfor %}
</ul>
<ol>
{% for pageEntry in pagination.pages %}
{% if page.url == pagination.hrefs[ loop.index0 ] %}
<span aria-current="page">{{ loop.index }}</span>
{% else %}
<a href="{{ pagination.hrefs[ loop.index0 ] }}">{{ loop.index }}</a>
{% endif %}
{% endfor %}
</ol>
</div>
{% endblock %}

View File

@@ -1,78 +0,0 @@
{% extends "@layouts/base.twig" %}
{% block content %}
<div data-module-scroll="main">
<div class="o-container || c-wysiwyg">
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
<h1>Heading 1</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<h2>Heading 2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<h3>Heading 3</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<h4>Heading 4</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<h5>Heading 5</h5>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<h6>Heading 6</h6>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p><p><strong>Lorem ipsum dolor sit amet, consectetur</strong> adipiscing elit, sed do eiusmod tempor incididunt u<strong>t labore et dolore magna aliqua</strong>. Ut enim ad minim <em>veniam, quis nostrud exercitation</em> ullamco laboris <em>nisi ut aliquip ex ea</em> commodo consequat. <span style="text-decoration: underline;">Duis aute irure dolor in reprehenderit in voluptate velit</span> esse cillum dolore eu fugiat nulla pariatur. <span style="text-decoration: underline;">Excepteur sint occaecat cupidatat</span> non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
</blockquote>
<p>Je suis un <a href="https://www.lipsum.com/" target="_blank" title="Un super lien" rel="noopener noreferrer">super lien.</a> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor <a href="https://www.lipsum.com/" title="Lorem Ipsum">incididunt ut labore et dolore magna aliqua</a>. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<p>
<a href="mailto:example@example.com" title="Test mail">Lien mail.</a><br/>
<a href="tel:+0-123-456-7890" title="Test tel">Lien téléphone.</a>
</p>
<ul>
<li>Item 1</li>
<li><strong>Item 2</strong></li>
<li><em><strong>Item 3</strong></em></li>
<li><span style="text-decoration: underline;">Item 4</span></li>
<li><a href="https://www.lipsum.com/" title="Lorem ipsum">Item 5</a></li>
</ul>
<ol>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ol>
<p style="padding-left: 60px;">"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. <br/>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex."</p>
<p style="text-align: left;">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<p style="text-align: center;">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<p style="text-align: right;">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<table width="539" height="90">
<tbody>
<tr>
<td style="width: 126.55px;"><strong>Last name</strong></td>
<td style="width: 261.417px;"><span style="text-decoration: underline;">First name</span></td>
<td style="width: 126.533px;"><em>City</em></td>
</tr>
<tr>
<td style="width: 126.55px;">Lorem</td>
<td style="width: 261.417px;">Ipsum</td>
<td style="width: 126.533px;">Montréal</td>
</tr>
<tr>
<td style="width: 126.55px;">Dolor</td>
<td style="width: 261.417px;">Sit</td>
<td style="width: 126.533px;">Paris</td>
</tr>
</tbody>
</table>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<p><img src="https://www.airinuit.com/uploads/destinations/XGR/Mathias_Laroque_MWL.pilot_website_fall_2021_HD.jpg" alt=""/></p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<p><img src="https://www.airinuit.com/uploads/destinations/XGR/Mathias_Laroque_MWL.pilot_website_fall_2021_HD.jpg" alt=""/></p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<p><iframe width="560" height="315" src="https://www.youtube.com/embed/qt7jSw55N1A" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.</p>
<p><img src="https://www.airinuit.com/uploads/destinations/XGR/Mathias_Laroque_MWL.pilot_website_fall_2021_HD.jpg" alt=""/></p>
</div>
</div>
{% endblock %}

102
www/form.html Normal file
View File

@@ -0,0 +1,102 @@
<!doctype html>
<html class="is-loading" lang="en" data-page="page">
<head>
<meta charset="utf-8">
<title>Form | Locomotive Boilerplate</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print" onload="this.media='all'; this.onload=null; this.isLoaded=true">
</head>
<body data-module-load>
<div data-load-container>
<div data-module-scroll="main">
<header>
<a href="/"><h1>Locomotive Boilerplate</h1></a>
<nav>
<ul>
<li><a href="images.html">Images</a></li>
<li><a href="form.html" data-load="customTransition">Form</a></li>
<li><a href="grid.html">Grid</a></li>
</ul>
</nav>
</header>
<main>
<div class="o-container">
<h1 class="c-heading -h1">Page</h1>
<div class="o-layout">
<div class="o-layout_item u-1/2@from-small">
<form class="c-form">
<div class="c-form_item">
<label class="c-form_label" for="input">Input</label>
<input class="c-form_input" type="text" id="input">
</div>
<div class="c-form_item">
<div class="o-layout -gutter">
<div class="o-layout_item u-1/2">
<input class="c-form_checkbox" type="checkbox" id="checkbox">
<label class="c-form_checkboxLabel" for="checkbox">Checkbox</label>
</div>
<div class="o-layout_item u-1/2">
<input class="c-form_checkbox" type="checkbox" id="checkbox2">
<label class="c-form_checkboxLabel" for="checkbox2">Checkbox 2</label>
</div>
</div>
</div>
<div class="c-form_item">
<div class="o-layout -gutter">
<div class="o-layout_item u-1/2">
<input class="c-form_radio" type="radio" name="radio" id="radio">
<label class="c-form_radioLabel" for="radio">Radio</label>
</div>
<div class="o-layout_item u-1/2">
<input class="c-form_radio" type="radio" name="radio" id="radio2">
<label class="c-form_radioLabel" for="radio2">Radio 2</label>
</div>
</div>
</div>
<div class="c-form_item">
<label class="c-form_label" for="select">Select</label>
<div class="c-form_select">
<select class="c-form_select_input" id="select">
<option value="option">Option</option>
<option value="option2">Option 2</option>
<option value="option3">Option 3</option>
</select>
</div>
</div>
<div class="c-form_item">
<label class="c-form_label" for="textarea">Textarea</label>
<textarea class="c-form_textarea" id="textarea"></textarea>
</div>
<button class="c-button" type="submit">
Submit
</button>
</form>
</div>
</div>
</div>
</main>
<footer>
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate" title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
</footer>
</div>
</div>
<script src="assets/scripts/vendors.js" defer></script>
<script src="assets/scripts/app.js" defer></script>
</body>
</html>

90
www/grid.html Normal file
View File

@@ -0,0 +1,90 @@
<!doctype html>
<html class="is-loading" lang="en" data-page="grid">
<head>
<meta charset="utf-8">
<title>Locomotive Boilerplate</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
<!-- For a dark mode managment and svg favicon add this in your favicon.svg -->
<!--
<style>
path {
fill: #000;
}
@media (prefers-color-scheme: dark) {
path {
fill: #fff;
}
}
</style>
-->
<!-- <link rel="icon" href="assets/images/favicons/favicon.svg"> -->
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print"
onload="this.media='all'; this.onload=null; this.isLoaded=true">
</head>
<body data-module-load>
<div data-load-container>
<div data-module-scroll="main">
<header>
<a href="/">
<h1>Locomotive Boilerplate</h1>
</a>
<nav>
<ul>
<li><a href="images.html">Images</a></li>
<li><a href="form.html" data-load="customTransition">Form</a></li>
<li><a href="grid.html">Grid</a></li>
</ul>
</nav>
</header>
<main>
<div class="o-container">
<h1 class="c-heading -h1">Hello</h1>
<div class="o-grid -col-4 -col-12@from-medium -gutters">
<div class="o-grid_item u-gc-1/8@from-medium" style="background-color: gray;">
<h2 class="c-heading -h2">This grid has 4 columns and 12 columns from `medium` MQ</h2>
</div>
<div class="o-grid_item u-gc-1/5@from-medium" style="background-color: yellow;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-5/9@from-medium" style="background-color: red;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-9/13@from-medium" style="background-color: blue;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-1/3 u-gc-5/13@from-medium" style="background-color: pink;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
</div>
</div>
</main>
<footer>
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate"
title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
</footer>
</div>
</div>
<script src="assets/scripts/vendors.js" defer></script>
<script src="assets/scripts/app.js" defer></script>
</body>
</html>

128
www/images.html Normal file
View File

@@ -0,0 +1,128 @@
<!doctype html>
<html class="is-loading" lang="en" data-page="images">
<head>
<meta charset="utf-8">
<title>Images | Locomotive Boilerplate</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print" onload="this.media='all'; this.onload=null; this.isLoaded=true">
</head>
<body data-module-load>
<div data-load-container>
<div data-module-scroll="main">
<header>
<a href="/"><h1>Locomotive Boilerplate</h1></a>
<nav>
<ul>
<li><a href="images.html">Images</a></li>
<li><a href="form.html" data-load="customTransition">Form</a></li>
<li><a href="grid.html">Grid</a></li>
</ul>
</nav>
</header>
<main>
<div class="o-container">
<h1 class="c-heading -h1">Images</h1>
<section>
<h2 class="c-heading -h2">Lazy load demo</h2>
<h3 class="c-heading -h3">Basic</h3>
<div style="width: 640px; max-width: 100%;">
<div class="o-ratio u-4:3"><img data-load-src="http://picsum.photos/800/600?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
<div class="o-ratio u-4:3"><img data-load-src="http://picsum.photos/800/600?v=2" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
</div>
<h4 class="c-heading -h3">Using o-ratio & background-image</h3>
<div style="width: 480px; max-width: 100%;">
<div class="o-ratio u-16:9" data-load-style="background-size: cover; background-position: center; background-image: url(http://picsum.photos/640/480?v=1);"></div>
<div class="o-ratio u-16:9" data-load-style="background-size: cover; background-position: center; background-image: url(http://picsum.photos/640/480?v=2);"></div>
</div>
</section>
<section>
<h3 class="c-heading -h3">Relative to scroll</h3>
<h4 class="c-heading -h3">Using o-ratio & img</h3>
<div style="width: 640px; max-width: 100%;">
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=2" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=3" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=4" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=5" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
</div>
<h4 class="c-heading -h3">Using o-ratio & background-image</h3>
<div style="width: 480px; max-width: 100%;">
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=1"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=2"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=3"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=4"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=5"></div>
</div>
<h4 class="c-heading -h3">Using SVG viewport for ratio</h3>
<div style="width: 480px; max-width: 100%;">
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=6"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=7"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=8"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
</div>
</section>
</div>
</main>
<footer>
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate" title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
</footer>
</div>
</div>
<script src="assets/scripts/vendors.js" defer></script>
<script src="assets/scripts/app.js" defer></script>
</body>
</html>

76
www/index.html Normal file
View File

@@ -0,0 +1,76 @@
<!doctype html>
<html class="is-loading" lang="en" data-page="home">
<head>
<meta charset="utf-8">
<title>Locomotive Boilerplate</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
<!-- For a dark mode managment and svg favicon add this in your favicon.svg -->
<!--
<style>
path {
fill: #000;
}
@media (prefers-color-scheme: dark) {
path {
fill: #fff;
}
}
</style>
-->
<!-- <link rel="icon" href="assets/images/favicons/favicon.svg"> -->
<!-- Preload Fonts -->
<link rel="preload" href="assets/fonts/SourceSans3-Bold.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="assets/fonts/SourceSans3-BoldIt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="assets/fonts/SourceSans3-Regular.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="assets/fonts/SourceSans3-RegularIt.woff2" as="font" type="font/woff2" crossorigin>
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print"
onload="this.media='all'; this.onload=null; this.isLoaded=true">
</head>
<body data-module-load>
<div data-load-container>
<div data-module-scroll="main">
<header>
<a href="/">
<h1>Locomotive Boilerplate</h1>
</a>
<nav>
<ul>
<li><a href="images.html">Images</a></li>
<li><a href="form.html" data-load="customTransition">Form</a></li>
<li><a href="grid.html">Grid</a></li>
</ul>
</nav>
</header>
<main data-module-example>
<div class="o-container">
<h1 class="c-heading -h1">Hello</h1>
</div>
</main>
<footer>
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate"
title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
</footer>
</div>
</div>
<script src="assets/scripts/vendors.js" defer></script>
<script src="assets/scripts/app.js" defer></script>
</body>
</html>