mirror of
https://github.com/kogakure/website-11ty-hamburg.stefanimhoff.de.git
synced 2026-02-03 12:15:28 +00:00
Basic setup
This commit is contained in:
11
.editorconfig
Normal file
11
.editorconfig
Normal file
@@ -0,0 +1,11 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
90
.eleventy.js
Normal file
90
.eleventy.js
Normal file
@@ -0,0 +1,90 @@
|
||||
const pluginLazyImages = require('eleventy-plugin-lazyimages');
|
||||
const pluginRssFeed = require('@11ty/eleventy-plugin-rss');
|
||||
|
||||
const filterNbsp = require('eleventy-nbsp-filter');
|
||||
|
||||
const filters = require('./src/utils/filters.js');
|
||||
const shortcodes = require('./src/utils/shortcodes.js');
|
||||
const collections = require('./src/utils/collections.js');
|
||||
|
||||
module.exports = function (config) {
|
||||
// Plugins
|
||||
config.addPlugin(pluginRssFeed);
|
||||
|
||||
if (process.env.ELEVENTY_ENV == 'production') {
|
||||
config.addPlugin(pluginLazyImages);
|
||||
}
|
||||
|
||||
// Markdown It
|
||||
let markdownIt = require('markdown-it');
|
||||
let markdownItFootnotes = require('markdown-it-footnote');
|
||||
let markdownItGitHubHeadings = require('markdown-it-github-headings');
|
||||
let markdownItSub = require('markdown-it-sub');
|
||||
let markdownItSup = require('markdown-it-sup');
|
||||
let markdownItExternalAnchor = require('markdown-it-external-anchor');
|
||||
let options = {
|
||||
html: true,
|
||||
};
|
||||
|
||||
let markdownLib = markdownIt(options)
|
||||
.use(markdownItFootnotes)
|
||||
.use(markdownItGitHubHeadings)
|
||||
.use(markdownItExternalAnchor, {
|
||||
domain: 'hamburg.stefanimhoff.de',
|
||||
class: 'external',
|
||||
})
|
||||
.use(markdownItSub)
|
||||
.use(markdownItSup);
|
||||
|
||||
config.setLibrary('md', markdownLib);
|
||||
|
||||
// Compress and combine JS files
|
||||
config.addFilter('jsmin', require('./src/utils/minify-js.js'));
|
||||
|
||||
// Minify the HTML in production
|
||||
if (process.env.ELEVENTY_ENV == 'production') {
|
||||
config.addTransform('htmlmin', require('./src/utils/minify-html.js'));
|
||||
}
|
||||
|
||||
// Shortcodes
|
||||
|
||||
// Filters
|
||||
Object.keys(filters).forEach((filterName) => {
|
||||
config.addFilter(filterName, filters[filterName]);
|
||||
});
|
||||
config.addFilter('nbsp', filterNbsp(2, 15));
|
||||
|
||||
// Watch for changes and reload
|
||||
config.addWatchTarget('src/assets');
|
||||
|
||||
// Copy static files to dist
|
||||
config.addPassthroughCopy({ 'src/static/**/*.{xml,html,ico}': '.' });
|
||||
config.addPassthroughCopy({ 'src/static/.well-known/*': '.well-known' });
|
||||
config.addPassthroughCopy({ 'src/downloads': 'downloads' });
|
||||
config.addPassthroughCopy({ 'src/assets/fonts': 'assets/fonts' });
|
||||
config.addPassthroughCopy({ 'src/assets/images': 'assets/images' });
|
||||
|
||||
// Deep-Merge
|
||||
config.setDataDeepMerge(true);
|
||||
|
||||
// Custom Collections
|
||||
Object.keys(collections).forEach((collectionName) => {
|
||||
config.addCollection(collectionName, collections[collectionName]);
|
||||
});
|
||||
|
||||
// Set input and output folders
|
||||
return {
|
||||
dir: {
|
||||
input: 'src',
|
||||
data: 'data',
|
||||
includes: 'includes',
|
||||
layouts: 'layouts',
|
||||
output: 'dist',
|
||||
},
|
||||
templateFormats: ['njk', 'md', '11ty.js', 'jpg', 'png', 'svg'],
|
||||
htmlTemplateEngine: 'njk',
|
||||
dataTemplateEngine: 'njk',
|
||||
markdownTemplateEngine: 'njk',
|
||||
passthroughFileCopy: true,
|
||||
};
|
||||
};
|
||||
15
.eslintrc.json
Normal file
15
.eslintrc.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"browser": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "plugin:prettier/recommended"],
|
||||
"plugins": ["prettier"],
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"prettier/prettier": "error"
|
||||
}
|
||||
}
|
||||
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# npm
|
||||
node_modules
|
||||
|
||||
# 11ty
|
||||
dist
|
||||
src/includes/critical
|
||||
.lazyimages.json
|
||||
|
||||
# Local Netlify folder
|
||||
.netlify
|
||||
15
.prettierrc.json
Normal file
15
.prettierrc.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5",
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.md",
|
||||
"options": {
|
||||
"singleQuote": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
1
.stylelintignore
Normal file
1
.stylelintignore
Normal file
@@ -0,0 +1 @@
|
||||
src/assets/styles/base/_normalize.css
|
||||
35
.stylelintrc.json
Normal file
35
.stylelintrc.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"plugins": [
|
||||
"stylelint-order",
|
||||
"stylelint-config-rational-order/plugin",
|
||||
"stylelint-a11y",
|
||||
"stylelint-high-performance-animation",
|
||||
"stylelint-prettier"
|
||||
],
|
||||
"extends": [
|
||||
"stylelint-config-recommended",
|
||||
"stylelint-a11y/recommended",
|
||||
"stylelint-prettier/recommended"
|
||||
],
|
||||
"syntax": "scss",
|
||||
"rules": {
|
||||
"property-no-unknown": [
|
||||
true,
|
||||
{
|
||||
"ignoreProperties": ["suffix", "symbols", "system"]
|
||||
}
|
||||
],
|
||||
"no-descending-specificity": null,
|
||||
"order/order": ["custom-properties", "declarations"],
|
||||
"order/properties-alphabetical-order": true,
|
||||
"plugin/no-low-performance-animation-properties": true,
|
||||
"at-rule-no-unknown": [
|
||||
true,
|
||||
{
|
||||
"ignoreAtRules": ["define-placeholder", "extend"]
|
||||
}
|
||||
],
|
||||
"string-quotes": "single",
|
||||
"prettier/prettier": true
|
||||
}
|
||||
}
|
||||
33
README.md
Normal file
33
README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
[](https://app.netlify.com/sites/hamburg-stefanimhoff-de/deploys)
|
||||
[](https://hamburg.stefanimhoff.de/)
|
||||

|
||||
|
||||
# hamburg.stefanimhoff.de
|
||||
|
||||
This the source of my [travel blog] build with [Eleventy], [PostCSS], and [Gulp].
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
## Running the Website
|
||||
|
||||
```sh
|
||||
npm start
|
||||
```
|
||||
|
||||
For more tasks have a look into the `package.json`.
|
||||
|
||||
## Licence
|
||||
|
||||
All content is copyrighted by [Stefan Imhoff] unless otherwise stated. Feel free to learn from the source code and reuse code for your projects. The only thing which is not allowed is the usage of my design (the unique combination of layout, fonts, images).
|
||||
|
||||
In easier words: **This is not a free theme**. Learn from it. Remix. Reuse. Build your own stuff. 🤘
|
||||
|
||||
[eleventy]: https://www.11ty.dev/
|
||||
[gulp]: https://gulpjs.com/
|
||||
[postcss]: https://postcss.org/
|
||||
[si]: https://www.stefanimhoff.de/
|
||||
[travel blog]: https://hamburg.stefanimhoff.de/
|
||||
3
babel.config.json
Normal file
3
babel.config.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env"]
|
||||
}
|
||||
125
gulpfile.js
Normal file
125
gulpfile.js
Normal file
@@ -0,0 +1,125 @@
|
||||
const { task, src, dest, watch, series, parallel } = require('gulp');
|
||||
|
||||
const babel = require('babelify');
|
||||
const browserify = require('browserify');
|
||||
const buffer = require('vinyl-buffer');
|
||||
const source = require('vinyl-source-stream');
|
||||
|
||||
const imagemin = require('gulp-imagemin');
|
||||
const plumber = require('gulp-plumber');
|
||||
const postcss = require('gulp-postcss');
|
||||
const size = require('gulp-size');
|
||||
const sourcemaps = require('gulp-sourcemaps');
|
||||
const svgSprite = require('gulp-svg-sprite');
|
||||
|
||||
/**
|
||||
* Package JavaScript with Babel and Browserify
|
||||
*/
|
||||
task('js', () => {
|
||||
return browserify(['./src/assets/scripts/main.js'], {
|
||||
debug: true,
|
||||
})
|
||||
.transform(babel)
|
||||
.bundle()
|
||||
.on('error', function (err) {
|
||||
console.error(err);
|
||||
this.emit('end');
|
||||
})
|
||||
.pipe(source('main.js'))
|
||||
.pipe(buffer())
|
||||
.pipe(sourcemaps.init({ loadMaps: true }))
|
||||
.pipe(sourcemaps.write('.'))
|
||||
.pipe(dest('./dist/assets/scripts'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Create CSS and Sourcemaps with PostCSS
|
||||
*/
|
||||
task('css', function () {
|
||||
return src([
|
||||
'./src/assets/styles/*.css',
|
||||
'./src/assets/styles/critical/*.css',
|
||||
])
|
||||
.pipe(plumber())
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(postcss())
|
||||
.pipe(sourcemaps.write('.'))
|
||||
.pipe(dest('./dist/assets/styles'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Create CSS with PostCSS for production
|
||||
*/
|
||||
task('css:production', function () {
|
||||
return src(['./src/assets/styles/*.css'])
|
||||
.pipe(plumber())
|
||||
.pipe(postcss())
|
||||
.pipe(dest('./dist/assets/styles'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Copy critical CSS files to project folder
|
||||
*/
|
||||
task('css:critical', function () {
|
||||
return src(['./src/assets/styles/critical/*.css'])
|
||||
.pipe(plumber())
|
||||
.pipe(postcss())
|
||||
.pipe(dest('./src/includes/critical'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Create SVG sprite map from SVG files
|
||||
*/
|
||||
task('svg', () => {
|
||||
return src('./src/icons/*.svg')
|
||||
.pipe(plumber())
|
||||
.pipe(
|
||||
svgSprite({
|
||||
mode: {
|
||||
symbol: {
|
||||
dest: '.',
|
||||
sprite: 'icons.svg',
|
||||
},
|
||||
svg: {
|
||||
xmlDeclaration: false,
|
||||
doctypeDeclaration: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.pipe(dest('src/includes'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Optimize and minimize images
|
||||
*/
|
||||
task('optimize:images', () => {
|
||||
return src('src/assets/images/**/*.{jpg,jpeg,png,gif,svg}')
|
||||
.pipe(
|
||||
imagemin({
|
||||
optimizationLevel: 3,
|
||||
progressive: true,
|
||||
interlaced: true,
|
||||
})
|
||||
)
|
||||
.pipe(dest('src/assets/images/'))
|
||||
.pipe(size());
|
||||
});
|
||||
|
||||
/**
|
||||
* Run build for production
|
||||
*/
|
||||
task('build', parallel('js', 'css:production', 'css:critical'));
|
||||
|
||||
/**
|
||||
* Watch for changes in files
|
||||
*/
|
||||
task('watch', () => {
|
||||
watch('./src/assets/scripts/**/*.js', series('js'));
|
||||
watch('./src/assets/styles/**/*.css', series('css'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Compile assets and start watching for changes
|
||||
*/
|
||||
task('default', parallel('js', 'css', 'watch'));
|
||||
21
netlify.toml
Normal file
21
netlify.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
[build]
|
||||
command = "npm run build"
|
||||
publish = "dist"
|
||||
|
||||
[build.environment]
|
||||
NODE_VERSION = "12.16"
|
||||
|
||||
[[headers]]
|
||||
for = "/*"
|
||||
[headers.values]
|
||||
X-Frame-Options = "DENY"
|
||||
X-XSS-Protection = "1; mode=block"
|
||||
X-Content-Type-Options = "nosniff"
|
||||
Referrer-Policy= "no-referrer-when-downgrade"
|
||||
Permissions-Policy = "interest-cohort=()"
|
||||
|
||||
[[headers]]
|
||||
for = "/sw.js"
|
||||
|
||||
[headers.values]
|
||||
cache-control = "max-age=0,no-cache,no-store,must-revalidate"
|
||||
21517
package-lock.json
generated
Normal file
21517
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
87
package.json
Normal file
87
package.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"name": "website-11ty-hamburg.stefanimhoff.de",
|
||||
"version": "1.0.0",
|
||||
"description": "Source code of my travel blog",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "ELEVENTY_ENV=production npm-run-all build:assets build:html build:sw",
|
||||
"build:assets": "gulp build",
|
||||
"build:html": "eleventy",
|
||||
"build:sw": "workbox generateSW workbox.config.js",
|
||||
"clean": "npx del dist",
|
||||
"debug": "DEBUG=* npx eleventy",
|
||||
"plop": "plop",
|
||||
"prebuild": "npm run clean",
|
||||
"prestart": "npm run clean",
|
||||
"start": "npm run watch",
|
||||
"svg": "gulp svg",
|
||||
"watch": "npm-run-all --parallel watch:*",
|
||||
"watch:assets": "gulp",
|
||||
"watch:html": "eleventy --serve"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/kogakure/website-11ty-hamburg.stefanimhoff.de.git"
|
||||
},
|
||||
"keywords": [
|
||||
"11ty"
|
||||
],
|
||||
"author": "Stefan Imhoff",
|
||||
"license": "ISC",
|
||||
"homepage": "https://hamburg.stefanimhoff.de",
|
||||
"devDependencies": {
|
||||
"@11ty/eleventy": "^0.12.1",
|
||||
"@11ty/eleventy-plugin-rss": "^1.1.1",
|
||||
"autoprefixer": "^10.2.5",
|
||||
"babelify": "^10.0.0",
|
||||
"browserify": "^17.0.0",
|
||||
"cssnano": "^5.0.2",
|
||||
"del-cli": "^3.0.1",
|
||||
"eleventy-nbsp-filter": "^0.1.0",
|
||||
"eleventy-plugin-lazyimages": "^2.1.0",
|
||||
"eslint": "^7.25.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^3.4.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-imagemin": "^7.1.0",
|
||||
"gulp-plumber": "^1.2.1",
|
||||
"gulp-postcss": "^9.0.0",
|
||||
"gulp-size": "^3.0.0",
|
||||
"gulp-sourcemaps": "^3.0.0",
|
||||
"gulp-svg-sprite": "^1.5.0",
|
||||
"html-minifier": "^4.0.0",
|
||||
"markdown-it-external-anchor": "^1.0.0",
|
||||
"markdown-it-footnote": "^3.0.2",
|
||||
"markdown-it-github-headings": "^2.0.0",
|
||||
"markdown-it-sub": "^1.0.0",
|
||||
"markdown-it-sup": "^1.0.0",
|
||||
"moment": "^2.29.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"outdent": "^0.8.0",
|
||||
"plop": "^2.7.4",
|
||||
"postcss": "^8.2.13",
|
||||
"postcss-100vh-fix": "^1.0.2",
|
||||
"postcss-advanced-variables": "^3.0.1",
|
||||
"postcss-cli": "^8.3.1",
|
||||
"postcss-custom-media": "^8.0.0",
|
||||
"postcss-custom-properties": "^11.0.0",
|
||||
"postcss-extend": "^1.0.5",
|
||||
"postcss-import": "^14.0.1",
|
||||
"postcss-media-minmax": "^5.0.0",
|
||||
"postcss-nested": "^5.0.5",
|
||||
"postcss-sort-media-queries": "^3.8.9",
|
||||
"prettier": "^2.2.1",
|
||||
"stylelint": "^13.13.0",
|
||||
"stylelint-a11y": "^1.2.3",
|
||||
"stylelint-config-prettier": "^8.0.2",
|
||||
"stylelint-config-rational-order": "^0.1.2",
|
||||
"stylelint-config-recommended": "^5.0.0",
|
||||
"stylelint-high-performance-animation": "^1.5.2",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"stylelint-prettier": "^1.2.0",
|
||||
"uglify-js": "^3.13.4",
|
||||
"vinyl-buffer": "^1.0.1",
|
||||
"vinyl-source-stream": "^2.0.0",
|
||||
"workbox-cli": "^6.1.5"
|
||||
}
|
||||
}
|
||||
15
postcss.config.js
Normal file
15
postcss.config.js
Normal file
@@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('postcss-advanced-variables'),
|
||||
require('postcss-import'),
|
||||
require('postcss-custom-properties'),
|
||||
require('postcss-nested'),
|
||||
require('postcss-extend'),
|
||||
require('postcss-media-minmax'),
|
||||
require('postcss-custom-media'),
|
||||
require('postcss-100vh-fix'),
|
||||
require('postcss-sort-media-queries')(),
|
||||
require('autoprefixer'),
|
||||
...(process.env.ELEVENTY_ENV === 'production' ? [require('cssnano')] : []),
|
||||
],
|
||||
};
|
||||
5
src/assets/scripts/embedded/register-serviceworker.js
Normal file
5
src/assets/scripts/embedded/register-serviceworker.js
Normal file
@@ -0,0 +1,5 @@
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('/sw.js').catch((registrationError) => {
|
||||
console.error('SW registration failed: ', registrationError);
|
||||
});
|
||||
});
|
||||
42
src/assets/scripts/embedded/theme-switcher.js
Normal file
42
src/assets/scripts/embedded/theme-switcher.js
Normal file
@@ -0,0 +1,42 @@
|
||||
(function () {
|
||||
const root = document.getElementsByTagName('html')[0];
|
||||
|
||||
function setTheme(newTheme) {
|
||||
window.__theme = newTheme;
|
||||
preferredTheme = newTheme;
|
||||
const currentTheme = newTheme === 'light' ? 'dark' : 'light';
|
||||
root.classList.add(newTheme);
|
||||
root.classList.remove(currentTheme);
|
||||
}
|
||||
|
||||
let preferredTheme;
|
||||
|
||||
try {
|
||||
preferredTheme = localStorage.getItem('theme');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
window.__setPreferredTheme = function (newTheme) {
|
||||
setTheme(newTheme);
|
||||
try {
|
||||
localStorage.setItem('theme', newTheme);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
window.__toggleTheme = function () {
|
||||
const currentTheme = window.__theme;
|
||||
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
|
||||
window.__setPreferredTheme(newTheme);
|
||||
};
|
||||
|
||||
const darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
|
||||
darkQuery.addEventListener('change', function (e) {
|
||||
window.__setPreferredTheme(e.matches ? 'dark' : 'light');
|
||||
});
|
||||
|
||||
setTheme(preferredTheme || (darkQuery.matches ? 'dark' : 'light'));
|
||||
})();
|
||||
1
src/assets/scripts/main.js
Normal file
1
src/assets/scripts/main.js
Normal file
@@ -0,0 +1 @@
|
||||
console.log('Hello, world');
|
||||
0
src/assets/styles/main.css
Normal file
0
src/assets/styles/main.css
Normal file
0
src/assets/styles/print.css
Normal file
0
src/assets/styles/print.css
Normal file
9
src/data/site.js
Normal file
9
src/data/site.js
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
isProduction: process.env.ELEVENTY_ENV === 'production',
|
||||
buildTime: new Date(),
|
||||
title: '',
|
||||
description: '',
|
||||
url: 'https://www.kogakure.de',
|
||||
author: 'Stefan Imhoff',
|
||||
twitter: '@kogakure',
|
||||
};
|
||||
4
src/includes/favicons.njk
Normal file
4
src/includes/favicons.njk
Normal file
@@ -0,0 +1,4 @@
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="icon" href="{{ site.faviconPath }}favicon.svg" type="image/svg+xml" />
|
||||
<link rel="apple-touch-icon" href="{{ site.faviconPath }}apple-touch-icon.png" />
|
||||
<link rel="manifest" href="/manifest.webmanifest" />
|
||||
1
src/includes/feeds.njk
Normal file
1
src/includes/feeds.njk
Normal file
@@ -0,0 +1 @@
|
||||
<link rel="alternate" type="application/rss+xml" title="" href="{{ site.url }}/index.xml" />
|
||||
3
src/includes/icon-sprites.njk
Normal file
3
src/includes/icon-sprites.njk
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="0" height="0">
|
||||
{# {% include "icons.svg" %} #}
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 123 B |
45
src/includes/meta-tags.njk
Normal file
45
src/includes/meta-tags.njk
Normal file
@@ -0,0 +1,45 @@
|
||||
{%- set ogTitle -%}
|
||||
{%- if page.url === "/" -%}
|
||||
{{ site.author }} · {{ site.description }}
|
||||
{%- else -%}
|
||||
{{ title }} · {{ site.author }}
|
||||
{%- endif -%}
|
||||
{%- endset -%}
|
||||
|
||||
{%- set ogDescription -%}
|
||||
{%- if page.url === "/" -%}
|
||||
{{ site.tagline }}
|
||||
{%- else -%}
|
||||
{{ description or title }}
|
||||
{%- endif -%}
|
||||
{%- endset -%}
|
||||
|
||||
{%- set ogImage -%}
|
||||
{%- if og -%}
|
||||
{{ site.url }}/assets/images/branding/og/{{ og }}
|
||||
{%- else -%}
|
||||
{{ site.url }}/assets/images/branding/og/banner.png
|
||||
{%- endif -%}
|
||||
{%- endset -%}
|
||||
|
||||
<!-- Meta -->
|
||||
<meta name="author" content="{{ site.author }}" />
|
||||
<meta name="description" content="{{ ogDescription }}" />
|
||||
<meta name="theme-color" content="#e7e6e4" />
|
||||
|
||||
<!-- Open graph -->
|
||||
<meta property="og:title" content="{{ ogTitle }}" />
|
||||
<meta property="og:url" content="{{ site.url }}{{ page.url }}" />
|
||||
<meta property="og:description" content="{{ ogDescription }}" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:image" content="{{ ogImage }}"/>
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="675" />
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta name="twitter:title" content="{{ ogTitle }}" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="{{ site.twitter }}" />
|
||||
<meta name="twitter:description" content="{{ ogDescription }}" />
|
||||
<meta name="twitter:image" content="{{ ogImage }}" />
|
||||
<meta name="twitter:creator" content="{{ site.twitter }}" />
|
||||
3
src/includes/preload.njk
Normal file
3
src/includes/preload.njk
Normal file
@@ -0,0 +1,3 @@
|
||||
<link rel="preload" href="{{ '/assets/fonts/xyz1.woff2' | url }}" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="{{ '/assets/fonts/xyz2.woff2' | url }}" as="font" type="font/woff2" crossorigin />
|
||||
|
||||
5
src/includes/robots.njk
Normal file
5
src/includes/robots.njk
Normal file
@@ -0,0 +1,5 @@
|
||||
{% if robots %}
|
||||
<meta name="robots" content="{{ robots }}" />
|
||||
{% else %}
|
||||
<meta name="robots" content="all" />
|
||||
{% endif %}
|
||||
7
src/includes/scripts.njk
Normal file
7
src/includes/scripts.njk
Normal file
@@ -0,0 +1,7 @@
|
||||
{% set js %}
|
||||
{% include "../assets/scripts/embedded/theme-switcher.js" %}
|
||||
{% if site.isProduction %}
|
||||
{% include "../assets/scripts/embedded/register-serviceworker.js" %}
|
||||
{% endif %}
|
||||
{% endset %}
|
||||
<script>{{ js | jsmin | safe }}</script>
|
||||
28
src/includes/styles.njk
Normal file
28
src/includes/styles.njk
Normal file
@@ -0,0 +1,28 @@
|
||||
{% if site.isProduction %}
|
||||
{% set criticalCSS %}
|
||||
{% include "critical/base.css" %}
|
||||
{% if css %}
|
||||
{% include "critical/" + css %}
|
||||
{% endif %}
|
||||
{% endset %}
|
||||
|
||||
<style>
|
||||
{{ criticalCSS | safe }}
|
||||
</style>
|
||||
|
||||
{% else %}
|
||||
|
||||
<link rel="stylesheet" href="{{ '/assets/styles/base.css' | url }}" />
|
||||
{% if css %}
|
||||
<link rel="stylesheet" href="{{ '/assets/styles/' + css | url }}" />
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
<link rel="stylesheet" href="{{ '/assets/styles/main.css' | url }}" media="print" onload="this.media='all'" />
|
||||
<link rel="stylesheet" href="{{ '/assets/styles/print.css' | url }}" media="print" />
|
||||
|
||||
|
||||
<noscript>
|
||||
<link rel="stylesheet" href="{{ '/assets/styles/main.css' | url }}" />
|
||||
</noscript>
|
||||
35
src/layouts/base.njk
Normal file
35
src/layouts/base.njk
Normal file
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<title>
|
||||
{%- if page.url === "/" -%}
|
||||
{{ site.author }} · {{ site.description }}
|
||||
{%- else -%}
|
||||
{{ title }} · {{ site.author }}
|
||||
{%- endif -%}
|
||||
</title>
|
||||
|
||||
<link rel="canonical" href="{{ site.url }}{{ page.url }}" />
|
||||
|
||||
<script type="module">
|
||||
document.documentElement.classList.remove('no-js');
|
||||
document.documentElement.classList.add('js');
|
||||
</script>
|
||||
|
||||
{% include "scripts.njk" %}
|
||||
{% include "styles.njk" %}
|
||||
{% include "favicons.njk" %}
|
||||
{% include "meta-tags.njk" %}
|
||||
{% include "preload.njk" %}
|
||||
{% include "robots.njk" %}
|
||||
{% include "feeds.njk" %}
|
||||
</head>
|
||||
<body {% if bodyClass %}class="{{ bodyClass }}"{% endif %}>
|
||||
{% include "icon-sprites.njk" %}
|
||||
{{ content | safe }}
|
||||
<script src="/assets/scripts/main.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
7
src/pages/homepage.njk
Normal file
7
src/pages/homepage.njk
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
layout: base
|
||||
title: Home
|
||||
permalink: /
|
||||
---
|
||||
|
||||
Hello, world!
|
||||
1
src/utils/collections.js
Normal file
1
src/utils/collections.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = {};
|
||||
10
src/utils/filters.js
Normal file
10
src/utils/filters.js
Normal file
@@ -0,0 +1,10 @@
|
||||
const moment = require('moment');
|
||||
|
||||
module.exports = {
|
||||
dateToFormat: function (date, format = 'MMMM Do, YYYY') {
|
||||
return moment(date).format(format);
|
||||
},
|
||||
dateToISO: function (date) {
|
||||
return moment(date).format();
|
||||
},
|
||||
};
|
||||
15
src/utils/minify-html.js
Normal file
15
src/utils/minify-html.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const htmlmin = require('html-minifier');
|
||||
|
||||
module.exports = function (content, outputPath) {
|
||||
if (outputPath.endsWith('.html')) {
|
||||
let minified = htmlmin.minify(content, {
|
||||
useShortDoctype: true,
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
});
|
||||
|
||||
return minified;
|
||||
}
|
||||
|
||||
return content;
|
||||
};
|
||||
12
src/utils/minify-js.js
Normal file
12
src/utils/minify-js.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const UglifyJS = require('uglify-js');
|
||||
|
||||
module.exports = function (code) {
|
||||
let minified = UglifyJS.minify(code);
|
||||
|
||||
if (minified.error) {
|
||||
console.log('UglifyJS error: ', minified.error);
|
||||
return code;
|
||||
}
|
||||
|
||||
return minified.code;
|
||||
};
|
||||
10
src/utils/shortcodes.js
Normal file
10
src/utils/shortcodes.js
Normal file
@@ -0,0 +1,10 @@
|
||||
const outdent = require('outdent')({ newline: ' ' });
|
||||
|
||||
module.exports = {
|
||||
test: function () {
|
||||
const html = outdent`
|
||||
<div>Hello, World</div>`;
|
||||
|
||||
return html;
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user