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
22 changed files with 3035 additions and 5931 deletions

12
.gitignore vendored
View File

@@ -5,13 +5,9 @@ loconfig.*.json
!loconfig.example.json
.prettierrc
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

@@ -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

@@ -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);

8622
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,38 +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": {
"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",
"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

@@ -96,9 +96,6 @@
</div>
</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>

View File

@@ -83,12 +83,6 @@
</div>
</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>

View File

@@ -122,9 +122,6 @@
</div>
</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>

View File

@@ -69,12 +69,6 @@
</div>
</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>