project first commit
90
.eleventy.js
Normal file
@ -0,0 +1,90 @@
|
||||
const rssPlugin = require('@11ty/eleventy-plugin-rss');
|
||||
const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight');
|
||||
const fs = require('fs');
|
||||
|
||||
// Import filters
|
||||
const dateFilter = require('./src/filters/date-filter.js');
|
||||
const markdownFilter = require('./src/filters/markdown-filter.js');
|
||||
const w3DateFilter = require('./src/filters/w3-date-filter.js');
|
||||
|
||||
// Import transforms
|
||||
const htmlMinTransform = require('./src/transforms/html-min-transform.js');
|
||||
const parseTransform = require('./src/transforms/parse-transform.js');
|
||||
|
||||
// Import data files
|
||||
const site = require('./src/_data/site.json');
|
||||
|
||||
module.exports = function(config) {
|
||||
// Filters
|
||||
config.addFilter('dateFilter', dateFilter);
|
||||
config.addFilter('markdownFilter', markdownFilter);
|
||||
config.addFilter('w3DateFilter', w3DateFilter);
|
||||
|
||||
// Layout aliases
|
||||
config.addLayoutAlias('home', 'layouts/home.njk');
|
||||
|
||||
// Transforms
|
||||
config.addTransform('htmlmin', htmlMinTransform);
|
||||
config.addTransform('parse', parseTransform);
|
||||
|
||||
// Passthrough copy
|
||||
config.addPassthroughCopy('src/fonts');
|
||||
config.addPassthroughCopy('src/images');
|
||||
config.addPassthroughCopy('src/js');
|
||||
config.addPassthroughCopy('src/admin/config.yml');
|
||||
config.addPassthroughCopy('src/admin/previews.js');
|
||||
config.addPassthroughCopy('node_modules/nunjucks/browser/nunjucks-slim.js');
|
||||
config.addPassthroughCopy('src/robots.txt');
|
||||
|
||||
const now = new Date();
|
||||
|
||||
// Custom collections
|
||||
const livePosts = post => post.date <= now && !post.data.draft;
|
||||
config.addCollection('posts', collection => {
|
||||
return [
|
||||
...collection.getFilteredByGlob('./src/posts/*.md').filter(livePosts)
|
||||
].reverse();
|
||||
});
|
||||
|
||||
config.addCollection('postFeed', collection => {
|
||||
return [...collection.getFilteredByGlob('./src/posts/*.md').filter(livePosts)]
|
||||
.reverse()
|
||||
.slice(0, site.maxPostsPerPage);
|
||||
});
|
||||
config.addCollection('newsFeed', collection => {
|
||||
return [...collection.getFilteredByGlob('./src/posts/*.md').filter(livePosts)]
|
||||
.reverse()
|
||||
.slice(0, site.maxNewsPerPage);
|
||||
});
|
||||
|
||||
// Plugins
|
||||
config.addPlugin(rssPlugin);
|
||||
config.addPlugin(syntaxHighlight);
|
||||
|
||||
// 404
|
||||
config.setBrowserSyncConfig({
|
||||
callbacks: {
|
||||
ready: function(err, browserSync) {
|
||||
const content_404 = fs.readFileSync('dist/404.html');
|
||||
|
||||
browserSync.addMiddleware('*', (req, res) => {
|
||||
// Provides the 404 content without redirect.
|
||||
res.write(content_404);
|
||||
res.end();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Watch sass
|
||||
// config.addWatchTarget("./src/scss/");
|
||||
|
||||
return {
|
||||
dir: {
|
||||
input: 'src',
|
||||
output: 'dist'
|
||||
},
|
||||
passthroughFileCopy: true,
|
||||
pathPrefix: '/preprod' //TODO remove when prod
|
||||
};
|
||||
};
|
19
.gitignore
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
*.log
|
||||
npm-debug.*
|
||||
*.scssc
|
||||
*.log
|
||||
*.swp
|
||||
.DS_Store
|
||||
.sass-cache
|
||||
node_modules
|
||||
dist/*
|
||||
deploy-prod.js
|
||||
deploy-preprod.js
|
||||
|
||||
# Specifics
|
||||
|
||||
# Hide design tokens
|
||||
src/scss/_tokens.scss
|
||||
|
||||
# Hide compiled CSS
|
||||
src/_includes/assets/*
|
6
.prettierrc
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"printWidth": 90,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"bracketSpacing": false
|
||||
}
|
18
.stylelintrc.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "stylelint-config-sass-guidelines",
|
||||
"rules": {
|
||||
"order/properties-alphabetical-order": null,
|
||||
"property-no-vendor-prefix": null,
|
||||
"selector-class-pattern": [
|
||||
"^[a-z0-9\\-_]+$",
|
||||
{
|
||||
"message":
|
||||
"Selector should be written in lowercase (selector-class-pattern)"
|
||||
}
|
||||
],
|
||||
"max-nesting-depth": 4,
|
||||
"number-leading-zero": "never",
|
||||
"selector-no-qualifying-type": null,
|
||||
"selector-max-compound-selectors": 4
|
||||
}
|
||||
}
|
21
LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 andy-bell.design and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
30
deploy.js
Normal file
@ -0,0 +1,30 @@
|
||||
var FtpDeploy = require("ftp-deploy");
|
||||
var ftpDeploy = new FtpDeploy();
|
||||
|
||||
var config = {
|
||||
user: "user",
|
||||
// Password optional, prompted if none given
|
||||
password: "password",
|
||||
host: "ftp.someserver.com",
|
||||
port: 21,
|
||||
localRoot: __dirname + "/local-folder",
|
||||
remoteRoot: "/public_html/remote-folder/",
|
||||
// include: ["*", "**/*"], // this would upload everything except dot files
|
||||
include: ["*.php", "dist/*", ".*"],
|
||||
// e.g. exclude sourcemaps, and ALL files in node_modules (including dot files)
|
||||
exclude: ["dist/**/*.map", "node_modules/**", "node_modules/**/.*", ".git/**"],
|
||||
// delete ALL existing files at destination before uploading, if true
|
||||
deleteRemote: false,
|
||||
// Passive mode is forced (EPSV command is not sent)
|
||||
forcePasv: true
|
||||
};
|
||||
|
||||
// use with promises
|
||||
ftpDeploy
|
||||
.deploy(config)
|
||||
.then(res => console.log("finished:", res))
|
||||
.catch(err => console.log(err));
|
||||
|
||||
ftpDeploy.on("uploading", function(data) {
|
||||
console.log(data.filename); // partial path with filename being uploaded
|
||||
});
|
9665
package-lock.json
generated
Normal file
56
package.json
Executable file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "astrolabe-website",
|
||||
"version": "0.1.0",
|
||||
"description": "Site web de la coopérative Astrolabe CAE",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@11ty/eleventy": "^0.10.0",
|
||||
"@11ty/eleventy-plugin-rss": "^1.0.7",
|
||||
"@11ty/eleventy-plugin-syntaxhighlight": "^2.0.3",
|
||||
"@tbranyen/jsdom": "^13.0.0",
|
||||
"concurrently": "^4.1.2",
|
||||
"html-minifier": "^4.0.0",
|
||||
"image-size": "^0.8.3",
|
||||
"json-to-scss": "^1.5.0",
|
||||
"sass": "^1.26.3",
|
||||
"semver": "^6.3.0",
|
||||
"slugify": "^1.4.0",
|
||||
"stalfos": "github:hankchizljaw/stalfos#c8971d22726326cfc04089b2da4d51eeb1ebb0eb"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@erquhart/rollup-plugin-node-builtins": "^2.1.5",
|
||||
"bl": "^3.0.0",
|
||||
"chokidar-cli": "^2.1.0",
|
||||
"cross-env": "^5.2.1",
|
||||
"ftp-deploy": "^2.3.7",
|
||||
"make-dir-cli": "^2.0.0",
|
||||
"prettier": "^1.19.1",
|
||||
"rollup": "^1.32.1",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-json": "^4.0.0",
|
||||
"rollup-plugin-node-resolve": "^5.2.0",
|
||||
"stylelint": "^13.6.1",
|
||||
"stylelint-config-sass-guidelines": "^7.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"sass:tokens": "npx json-to-scss src/_data/tokens.json src/scss/_tokens.scss",
|
||||
"sass:lint": "npx stylelint src/scss/**/*.scss",
|
||||
"sass:process": "npm run sass:tokens && npm run sass:lint && sass src/scss/global.scss src/_includes/assets/css/global.css --style=compressed",
|
||||
"start": "concurrently \"npm run sass:process -- --watch\" \"npm run serve\"",
|
||||
"serve": "cross-env ELEVENTY_ENV=development npx eleventy --serve",
|
||||
"preprod": "cross-env ELEVENTY_ENV=preprod npm run sass:process && npx eleventy",
|
||||
"deploy-preprod": "npm run preprod && node deploy-preprod",
|
||||
"prod": "cross-env ELEVENTY_ENV=prod npm run sass:process && npx eleventy"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://git.ouvaton.coop/astrolabe/SiteWebAstrolabe.git"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://git.ouvaton.coop/astrolabe/SiteWebAstrolabe/issues"
|
||||
},
|
||||
"homepage": "https://git.ouvaton.coop/astrolabe/SiteWebAstrolabe"
|
||||
}
|
17
src/404.md
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
title: '404 - not found'
|
||||
layout: layouts/page.njk
|
||||
permalink: 404.html
|
||||
eleventyExcludeFromCollections: true
|
||||
---
|
||||
|
||||
We’re sorry, but that content can’t be found. Please go [back to home](/).
|
||||
|
||||
{% comment %}
|
||||
Read more: https://www.11ty.io/docs/quicktips/not-found/
|
||||
|
||||
This will work for both GitHub pages and Netlify:
|
||||
|
||||
- https://help.github.com/articles/creating-a-custom-404-page-for-your-github-pages-site/
|
||||
- https://www.netlify.com/docs/redirects/#custom-404
|
||||
{% endcomment %}
|
9
src/_data/global.js
Normal file
@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
random() {
|
||||
const segment = () => {
|
||||
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
||||
};
|
||||
return `${segment()}-${segment()}-${segment()}`;
|
||||
},
|
||||
now: Date.now()
|
||||
};
|
10
src/_data/helpers.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
getNextHeadingLevel(currentLevel) {
|
||||
return parseInt(currentLevel, 10) + 1;
|
||||
},
|
||||
getReadingTime(text) {
|
||||
const wordsPerMinute = 200;
|
||||
const numberOfWords = text.split(/\s/g).length;
|
||||
return Math.ceil(numberOfWords / wordsPerMinute);
|
||||
}
|
||||
};
|
29
src/_data/navigation.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"text": "Comprendre la CAE",
|
||||
"url": "/comprendre",
|
||||
"external": false
|
||||
},
|
||||
{
|
||||
"text": "Nous rejoindre",
|
||||
"url": "/rejoindre",
|
||||
"external": false
|
||||
},
|
||||
{
|
||||
"text": "L'équipe",
|
||||
"url": "/equipe",
|
||||
"external": false
|
||||
},
|
||||
{
|
||||
"text": "Actualité",
|
||||
"url": "/actualite",
|
||||
"external": false
|
||||
},
|
||||
{
|
||||
"text": "Nous contacter",
|
||||
"url": "/contact",
|
||||
"external": false
|
||||
}
|
||||
]
|
||||
}
|
23
src/_data/site.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"showThemeCredit": true,
|
||||
"name": "Astrolabe CAE",
|
||||
"shortDesc": "Site web de la coopérative Astrolabe CAE",
|
||||
"url": "https://astrolabe.coop/preprod",
|
||||
"authorEmail": "contacte@astrolabe.coop",
|
||||
"authorHandle": "@AstrolabeCae",
|
||||
"authorName": "Astrolabe CAE",
|
||||
"authorAddress": "34 La Ville Allée",
|
||||
"authorCity": "35630 HEDE BAZOUGES",
|
||||
"authorSocial": {
|
||||
"mastodon": "https://framapiaf.org/@AstrolabeCAE",
|
||||
"twitter": "https://twitter.com/AstrolabeCae",
|
||||
"linkedin": "https://www.linkedin.com/company/astrolabe-cae/"
|
||||
},
|
||||
"designerName": "Yves Gatesoupe",
|
||||
"designerHandle": "https://twitter.com/YGdsgn",
|
||||
"illustrators": "Igé Maulana, Leopold Merleau",
|
||||
"enableThirdPartyComments": false,
|
||||
"maxPostsPerPage": 5,
|
||||
"maxNewsPerPage": 4,
|
||||
"faviconPath": "/images/favicon.png"
|
||||
}
|
28
src/_data/styleguide.js
Normal file
@ -0,0 +1,28 @@
|
||||
const tokens = require('./tokens.json');
|
||||
|
||||
module.exports = {
|
||||
colors() {
|
||||
let response = [];
|
||||
|
||||
Object.keys(tokens.colors).forEach(key => {
|
||||
response.push({
|
||||
value: tokens.colors[key],
|
||||
key
|
||||
});
|
||||
});
|
||||
|
||||
return response;
|
||||
},
|
||||
sizes() {
|
||||
let response = [];
|
||||
|
||||
Object.keys(tokens['size-scale']).forEach(key => {
|
||||
response.push({
|
||||
value: tokens['size-scale'][key],
|
||||
key
|
||||
});
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
};
|
28
src/_data/tokens.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"size-scale": {
|
||||
"base": "1rem",
|
||||
"300": "0.8rem",
|
||||
"500": "1.25rem",
|
||||
"600": "1.56rem",
|
||||
"700": "1.95rem",
|
||||
"800": "2.44rem",
|
||||
"900": "3.05rem",
|
||||
"max": "4rem"
|
||||
},
|
||||
"colors": {
|
||||
"primary": "#d6f253",
|
||||
"primary-shade": "#102538",
|
||||
"primary-glare": "#22547c",
|
||||
"secondary": "#282156",
|
||||
"highlight": "#d6f253",
|
||||
"light-gray": "#f1f0f7",
|
||||
"light": "#fff",
|
||||
"mid": "#ccc",
|
||||
"dark": "#111",
|
||||
"slate": "#404040"
|
||||
},
|
||||
"fonts": {
|
||||
"base": "\"'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'\"",
|
||||
"brand": "\"'Varela', sans-serif\""
|
||||
}
|
||||
}
|
13
src/_includes/icons/arrow.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
focusable="false"
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
d="M9.707 18.707l6-6a.999.999 0 0 0 0-1.414l-6-6a.999.999 0 1 0-1.414 1.414L13.586 12l-5.293 5.293a.999.999 0 1 0 1.414 1.414z"
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 310 B |
3
src/_includes/icons/astrolabe_logo.svg
Normal file
After Width: | Height: | Size: 7.4 KiB |
16
src/_includes/layouts/archive.njk
Normal file
@ -0,0 +1,16 @@
|
||||
{% extends 'layouts/base.njk' %}
|
||||
|
||||
{# Intro content #}
|
||||
{% set introHeading = title %}
|
||||
{% set introSummary %}{{ content | safe }}{% endset %}
|
||||
|
||||
{# Post list content #}
|
||||
{% set postListHeading = 'All posts' %}
|
||||
{% set postListItems = collections.posts %}
|
||||
|
||||
{% block content %}
|
||||
<main id="main-content" tabindex="-1">
|
||||
{% include "partials/components/intro.njk" %}
|
||||
{% include "partials/components/post-list.njk" %}
|
||||
</main>
|
||||
{% endblock %}
|
32
src/_includes/layouts/base.njk
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ site.url }}/feed.xml" />
|
||||
<link rel="icon" href="{{ site.faviconPath }}" type="image/png" />
|
||||
{% include "partials/global/meta-info.njk" %}
|
||||
<script>document.documentElement.classList.remove('no-js');</script>
|
||||
<style>{% include "assets/css/global.css" %}</style>
|
||||
{% block head %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{% include "partials/global/site-head.njk" %}
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
{% include "partials/global/site-foot.njk" %}
|
||||
{% block foot %}
|
||||
{% endblock %}
|
||||
{# <script type="module" src="/js/components/theme-toggle.js" async defer></script> #}
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('/service-worker.js');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js" defer></script>
|
||||
</body>
|
||||
</html>
|
18
src/_includes/layouts/contact.njk
Normal file
@ -0,0 +1,18 @@
|
||||
{% extends 'layouts/base.njk' %}
|
||||
|
||||
{# Intro content #}
|
||||
{% set introHeading = title %}
|
||||
|
||||
{% block content %}
|
||||
<main id="main-content" tabindex="-1">
|
||||
<article class="[ post ] [ h-entry ]">
|
||||
{% include "partials/components/intro.njk" %}
|
||||
<div class="[ post__body ] [ inner-wrapper ] [ leading-loose pad-top-900 pad-bottom-900 text-500 ] [ sf-flow ] [ e-content ]">
|
||||
{{ content | safe }}
|
||||
{% include "partials/components/contact-form.njk" %}
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
||||
{{ content | safe }}
|
19
src/_includes/layouts/home.njk
Normal file
@ -0,0 +1,19 @@
|
||||
{% extends 'layouts/base.njk' %}
|
||||
|
||||
{# Post list content #}
|
||||
{% set newsListHeading = newsHeading %}
|
||||
{% set newsListItems = collections.newsFeed %}
|
||||
|
||||
{# Presentation content #}
|
||||
{% set presentation %}
|
||||
{{ content | safe }}
|
||||
{% endset %}
|
||||
|
||||
{% block content %}
|
||||
<main id="main-content" tabindex="-1">
|
||||
{% include "partials/components/intro.njk" %}
|
||||
{% include "partials/components/news-list.njk" %}
|
||||
{% include "partials/components/post-list.njk" %}
|
||||
{% include "partials/components/presentation.njk" %}
|
||||
</main>
|
||||
{% endblock %}
|
17
src/_includes/layouts/page.njk
Normal file
@ -0,0 +1,17 @@
|
||||
{% extends 'layouts/base.njk' %}
|
||||
|
||||
{# Intro content #}
|
||||
{% set introHeading = title %}
|
||||
|
||||
{% block content %}
|
||||
<main id="main-content" tabindex="-1">
|
||||
<article class="[ post ] [ h-entry ]">
|
||||
{% include "partials/components/intro.njk" %}
|
||||
<div class="[ post__body ] [ inner-wrapper ] [ leading-loose pad-top-900 pad-bottom-900 text-500 ] [ sf-flow ] [ e-content ]">
|
||||
{{ content | safe }}
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
||||
{{ content | safe }}
|
47
src/_includes/layouts/post.njk
Normal file
@ -0,0 +1,47 @@
|
||||
{% extends 'layouts/base.njk' %}
|
||||
|
||||
{# Intro content #}
|
||||
{% set introHeading = title %}
|
||||
{% set introSummary %}
|
||||
<p class="[ intro__meta ] [ text-500 leading-tight ]">
|
||||
{% if date %}
|
||||
<time datetime="{{ date | w3DateFilter }}" class="dt-published">{{ date | dateFilter }}</time>
|
||||
{% endif %}
|
||||
<span>— {{ helpers.getReadingTime(content) }} minute read</span>
|
||||
</p>
|
||||
{% endset %}
|
||||
|
||||
{% block content %}
|
||||
<main id="main-content" tabindex="-1">
|
||||
<article class="[ post ] [ h-entry ]">
|
||||
{% include "partials/components/intro.njk" %}
|
||||
<div class="[ post__body ] [ inner-wrapper ] [ leading-loose pad-top-900 {{ 'pad-bottom-900' if not site.enableThirdPartyComments }} text-500 ] [ sf-flow ] [ e-content ]">
|
||||
{{ content | safe }}
|
||||
</div>
|
||||
{% if site.enableThirdPartyComments %}
|
||||
<hr />
|
||||
<aside class="[ post__body ] [ inner-wrapper ] [ pad-bottom-900 text-500 ]">
|
||||
{% include "partials/global/third-party-comments.njk" %}
|
||||
</aside>
|
||||
{% endif %}
|
||||
{% if tags %}
|
||||
<footer class="[ post__footer ] [ pad-top-500 pad-bottom-500 ]">
|
||||
<div class="inner-wrapper">
|
||||
<div class="[ nav ] [ box-flex align-center ]">
|
||||
<h2 class="font-base text-600 weight-mid">Filed under</h2>
|
||||
<ul class="[ nav__list ] [ box-flex align-center pad-left-400 ] [ p-category ]">
|
||||
{% for item in tags %}
|
||||
<li class="nav__item">
|
||||
<a href="/tags/{{ item }}">{{ item }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
{% endif %}
|
||||
</article>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
||||
{{ content | safe }}
|
181
src/_includes/macros/form.njk
Normal file
@ -0,0 +1,181 @@
|
||||
{# ===================
|
||||
Forms
|
||||
=================== #}
|
||||
|
||||
{% macro label( text, name ) %}
|
||||
<label class="question__label" for="field-{{ name }}">{{ text }}</label>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro field( type, name, data ) %}
|
||||
<br>
|
||||
<input class="question__field"
|
||||
type="{{ type }}"
|
||||
name="{{ name }}"
|
||||
id="field-{{ name }}"
|
||||
{% if data.required %}required aria-required="true"{% endif %}
|
||||
{% if data.placeholder %}placeholder="{{ data.placeholder }}"{% endif %}
|
||||
{% if data.pattern %}pattern="{{ data.pattern }}"{% endif %}
|
||||
{% if data.description %}aria-describedby="description-{{ name }}"{% endif %}
|
||||
{% if data.autocomplete %}autocomplete="{{ data.autocomplete }}"{% endif %}
|
||||
{% if data.autocorrect %}autocorrect="{{ data.autocorrect }}"{% endif %}
|
||||
{% if data.spellcheck %}spellcheck="{{ data.spellcheck }}"{% endif %}
|
||||
{% if data.autocapitalize %}autocapitalize="{{ data.autocapitalize }}"{% endif %}
|
||||
>
|
||||
{% if data.description %}
|
||||
<br>
|
||||
{{ description( name, data.description ) }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro confirm( text, name, data ) %}
|
||||
<label for="field-{{ name }}" class="question--confirm">
|
||||
<input class="question__field question__field--confirm"
|
||||
type="checkbox"
|
||||
name="{{ name }}"
|
||||
id="field-{{ name }}"
|
||||
value="1"
|
||||
{% if data.required %}required aria-required="true"{% endif %}
|
||||
{% if data.description %}aria-describedby="description-{{ name }}"{% endif %}
|
||||
>
|
||||
{{ text }}
|
||||
</label>
|
||||
{% if data.description %}
|
||||
<br>
|
||||
{{ description( name, data.description ) }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro select( name, options, data ) %}
|
||||
<br>
|
||||
<select id="field-{{ name }}"
|
||||
name="{{ name }}"
|
||||
{% if data.required %}required aria-required="true"{% endif %}
|
||||
{% if data.multiple %}multiple{% endif %}
|
||||
{% if data.description %}aria-describedby="description-{{ name }}"{% endif %}
|
||||
>
|
||||
{% for opt in data.options_before %}
|
||||
{{ option( opt ) }}
|
||||
{% endfor %}
|
||||
{% for opt in options %}
|
||||
{{ option( opt ) }}
|
||||
{% endfor %}
|
||||
{% for opt in data.options_after %}
|
||||
{{ option( opt ) }}
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% if data.description %}
|
||||
<br>
|
||||
{{ description( name, data.description ) }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro option( data ) %}
|
||||
{% if data.value %}
|
||||
<option value="{{ data.value }}">{{ data.label }}</option>
|
||||
{% else %}
|
||||
<option>{{ data }}</option>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro textarea( name, data ) %}
|
||||
<br>
|
||||
<textarea id="field-{{ name }}"
|
||||
name="{{ name }}"
|
||||
{% if data.rows %}rows="{{ data.rows }}"{% else %}rows="5"{% endif %}
|
||||
cols="100"
|
||||
{% if data.required %}required aria-required="true"{% endif %}
|
||||
{% if data.autocorrect %}autocorrect="{{ data.autocorrect }}"{% endif %}
|
||||
{% if data.spellcheck %}spellcheck="{{ data.spellcheck }}"{% endif %}
|
||||
{% if data.autocapitalize %}autocapitalize="{{ data.autocapitalize }}"{% endif %}
|
||||
{% if data.description %}aria-describedby="description-{{ name }}"{% endif %}
|
||||
></textarea>
|
||||
{% if data.description %}
|
||||
{{ description( name, data.description ) }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro radios( label, name, options, data ) %}
|
||||
<fieldset>
|
||||
<legend
|
||||
{% if data.description %}aria-describedby="description-{{ name }}"{% endif %}
|
||||
>{{ label }}</legend>
|
||||
<ul class="field-list__field-group__list">
|
||||
{% for option in options %}
|
||||
<li>
|
||||
{% if option.value %}
|
||||
<label for="field-{{ name }}-{{ option.value }}">
|
||||
<input type="radio"
|
||||
name="{{ name }}"
|
||||
id="field-{{ name }}-{{ option.value }}"
|
||||
value="{{ option.value }}"
|
||||
{% if option.note %}aria-describedby="description-{{ name }}-{{ option.value }}"{% endif %}
|
||||
>{{ option.label }}</label>
|
||||
{% else %}
|
||||
<label for="field-{{ name }}-{{ option }}">
|
||||
<input type="radio"
|
||||
name="{{ name }}"
|
||||
id="field-{{ name }}-{{ option }}"
|
||||
value="{{ option }}"
|
||||
>{{ option }}</label>
|
||||
{% endif %}
|
||||
{% if option.note %}
|
||||
<br>
|
||||
{{ description( ( name + '-' + option.value ), option.note ) }}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if data.description %}
|
||||
{{ description( name, data.description ) }}
|
||||
{% endif %}
|
||||
</fieldset>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro checkboxes( label, name, options, data ) %}
|
||||
<fieldset>
|
||||
<legend
|
||||
{% if data.description %}aria-describedby="description-{{ name }}"{% endif %}
|
||||
>{{ label }}</legend>
|
||||
<ul class="field-list__field-group__list">
|
||||
{% for option in options %}
|
||||
<li>
|
||||
{% if option.value %}
|
||||
<label for="field-{{ name }}-{{ option.value }}">
|
||||
<input type="checkbox"
|
||||
name="{{ name }}[]"
|
||||
id="field-{{ name }}-{{ option.value }}"
|
||||
value="{{ option.value }}"
|
||||
{% if option.note %}aria-describedby="description-{{ name }}-{{ option.value }}"{% endif %}
|
||||
>{{ option.label }}</label>
|
||||
{% else %}
|
||||
<label for="field-{{ name }}-{{ option }}">
|
||||
<input type="checkbox"
|
||||
name="{{ name }}[]"
|
||||
id="field-{{ name }}-{{ option }}"
|
||||
value="{{ option }}"
|
||||
>{{ option }}</label>
|
||||
{% endif %}
|
||||
{% if option.note %}
|
||||
<br>
|
||||
{{ description( ( name + '-' + option.value ), option.note ) }}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if data.description %}
|
||||
{{ description( name, data.description ) }}
|
||||
{% endif %}
|
||||
</fieldset>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro description( id, html ) %}
|
||||
<em class="[ field-list__field-group__description ]" id="description-{{ id }}">{{ html | safe }}</em>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro hidden_field( name, value ) %}
|
||||
<input type="hidden" name="{{ name }}" id="field-{{ name }}" value="{{ value }}">
|
||||
{% endmacro %}
|
||||
|
||||
{% macro button( text ) %}
|
||||
<button type="submit" class="[ button ] [ font-base text-base weight-bold ]">{{ text }}</button>
|
||||
{% endmacro %}
|
4
src/_includes/macros/site.njk
Normal file
@ -0,0 +1,4 @@
|
||||
{# ========================
|
||||
Site-specific Macros
|
||||
======================== #}
|
||||
|
22
src/_includes/partials/components/contact-form.njk
Normal file
@ -0,0 +1,22 @@
|
||||
{% from "macros/form.njk" import label, field, textarea, button %}
|
||||
|
||||
<form name="contact" method="POST" data-netlify="true" action="/thank-you" netlify-honeypot="bot-field">
|
||||
<ol class="[ field-list ]">
|
||||
<li class="[ field-list__field-group ]">
|
||||
{{ label("What’s your name?", "name") }}
|
||||
{{ field( "text", "name", { required: true, placeholder: "Katherine Johnson", autocomplete: "name", autocorrect: "off", autocapitalize: "off" } ) }}
|
||||
</li>
|
||||
<li class="[ field-list__field-group ]">
|
||||
{{ label("What’s your email address?", "email") }}
|
||||
{{ field( "email", "email", { required: true, placeholder: "katherine@johnson.tld", autocomplete: "email" } ) }}
|
||||
</li>
|
||||
<li class="[ field-list__field-group ]">
|
||||
{{ label("What’s on your mind?", "message") }}
|
||||
{{ textarea( "message", { required: true, autocapitalize: "sentences", spellcheck: "true" } ) }}
|
||||
</li>
|
||||
<li hidden>
|
||||
<label>Don’t fill this out if you're human: <input name="bot-field" /></label>
|
||||
</li>
|
||||
</ol>
|
||||
{{ button("Send message") }}
|
||||
</form>
|
10
src/_includes/partials/components/intro.njk
Normal file
@ -0,0 +1,10 @@
|
||||
<header class="[ intro ]">
|
||||
<div class="[ inner-wrapper ]">
|
||||
<h1 class="[ intro__heading ]">{{ brandHeading }}</h1>
|
||||
{% if introSummary %}
|
||||
<div class="[ intro__summary ] [ sf-flow ] [ leading-mid measure-short ]">{{ introSummary | safe }}</div>
|
||||
{% endif %}
|
||||
<a role="button" href="/README" class="btn btn-secondary">Une CAE c'est quoi ?</button>
|
||||
<a role="button" href="/README" class="btn btn-primary">Nous rejoindre</button>
|
||||
</div>
|
||||
</header>
|
22
src/_includes/partials/components/nav.njk
Normal file
@ -0,0 +1,22 @@
|
||||
{% if navigation.items %}
|
||||
<nav class="nav" aria-label="{{ariaLabel}}">
|
||||
<ul class="[ nav__list ] [ box-flex align-center md:space-before ]">
|
||||
{% for item in navigation.items %}
|
||||
{% set relAttribute = '' %}
|
||||
{% set currentAttribute = '' %}
|
||||
|
||||
{% if item.rel %}
|
||||
{% set relAttribute = ' rel="' + item.rel + '"' %}
|
||||
{% endif %}
|
||||
|
||||
{% if page.url == item.url %}
|
||||
{% set currentAttribute = ' aria-current="page"' %}
|
||||
{% endif %}
|
||||
|
||||
<li class="nav__item">
|
||||
<a href="{{ item.url | url }}"{{ relAttribute | safe }}{{ currentAttribute | safe }}>{{ item.text }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
25
src/_includes/partials/components/news-list.njk
Normal file
@ -0,0 +1,25 @@
|
||||
{% if newsListItems.length %}
|
||||
<section class="[ news-list ]">
|
||||
<svg aria-hidden="true" viewBox="0 0 1440 349" width="auto" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="#282156" d="M1440 154H0v195h1440z"/><path d="M1440 54.078l-48 12.41c-48 12.41-144 37.23-240 45.53-96 7.989-192 .232-288-29.01C768 54.079 672 4.438 576 .327c-96-4.421-192 37.463-288 45.452-96 8.3-192-16.52-240-28.931L0 4.437V203h1440V54.078z" fill="#282156"/></svg>
|
||||
<div class="[ wrapper ]">
|
||||
<div class="news-list__inner">
|
||||
<h2 class="[ news-list__heading ]">{{ newsListHeading }}</h2>
|
||||
<ol class="[ news-list__items ]" reversed>
|
||||
{% for item in newsListItems %}
|
||||
{% if item.date.getTime() <= global.now %}
|
||||
<li class="news-list__item">
|
||||
<h3 class="news-list__item-heading">
|
||||
<a href="{{ item.url | url }}" class="news-list__link" rel="bookmark">{{ item.data.title }}</a>
|
||||
</h3>
|
||||
<p class="news-list__item-date">
|
||||
<time datetime="{{ item.date | w3DateFilter }}">{{ item.date | dateFilter }}</time>
|
||||
</p>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ol>
|
||||
<a href="/" class="news-list__see-all">Voir tout</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
23
src/_includes/partials/components/pagination.njk
Normal file
@ -0,0 +1,23 @@
|
||||
{% set paginationLinkTokens = 'leading-tight text-500 weight-mid box-inline-flex align-center pad-bottom-300' %}
|
||||
|
||||
{% if paginationNextUrl or paginationPrevUrl %}
|
||||
<hr />
|
||||
<div class="inner-wrapper">
|
||||
<footer class="[ pagination ] [ pad-bottom-900 ]">
|
||||
<nav class="[ pagination__nav ] [ box-flex space-between align-center ]">
|
||||
{% if paginationPrevUrl %}
|
||||
<a href="{{ paginationPrevUrl }}" class="{{ paginationLinkTokens }}" data-direction="backwards">
|
||||
<span>{{ paginationPrevText if paginationPrevText else 'Previous' }}</span>
|
||||
{% include "icons/arrow.svg" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if paginationNextUrl %}
|
||||
<a href="{{ paginationNextUrl }}" class="{{ paginationLinkTokens }}" data-direction="forwards">
|
||||
<span>{{ paginationNextText if paginationNextText else 'Next' }}</span>
|
||||
{% include "icons/arrow.svg" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
</footer>
|
||||
</div>
|
||||
{% endif %}
|
21
src/_includes/partials/components/post-list.njk
Normal file
@ -0,0 +1,21 @@
|
||||
{% if postListItems.length %}
|
||||
<section class="[ post-list ] [ pad-top-700 gap-bottom-900 ]">
|
||||
<div class="[ inner-wrapper ] [ sf-flow ]">
|
||||
<h2 class="[ post-list__heading ]">{{ postListHeading }}</h2>
|
||||
<ol class="[ post-list__items ] [ sf-flow ] [ pad-top-300 ]" reversed>
|
||||
{% for item in postListItems %}
|
||||
{% if item.date.getTime() <= global.now %}
|
||||
<li class="post-list__item">
|
||||
<h3 class="font-base leading-tight text-600 weight-mid">
|
||||
<a href="{{ item.url }}" class="post-list__link" rel="bookmark">{{ item.data.title }}</a>
|
||||
</h3>
|
||||
<p class="text-500 gap-top-300 weight-mid">
|
||||
<time datetime="{{ item.date | w3DateFilter }}">{{ item.date | dateFilter }}</time>
|
||||
</p>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
5
src/_includes/partials/components/presentation.njk
Normal file
@ -0,0 +1,5 @@
|
||||
<section class="[ presentation ]">
|
||||
<div class="[ wrapper ]">
|
||||
{{ presentation | safe }}
|
||||
</div>
|
||||
</section>
|
41
src/_includes/partials/global/meta-info.njk
Normal file
@ -0,0 +1,41 @@
|
||||
{% set pageTitle = site.name + ' - ' + title %}
|
||||
{% set pageDesc = '' %}
|
||||
{% set siteTitle = site.name %}
|
||||
{% set currentUrl = site.url + page.url %}
|
||||
|
||||
{% if metaTitle %}
|
||||
{% set pageTitle = metaTitle %}
|
||||
{% endif %}
|
||||
|
||||
{% if metaDesc %}
|
||||
{% set pageDesc = metaDesc %}
|
||||
{% endif %}
|
||||
|
||||
<title>{{ pageTitle }}</title>
|
||||
<link rel="canonical" href="{{ currentUrl }}" />
|
||||
|
||||
<meta property="og:site_name" content="{{ siteTitle }}" />
|
||||
<meta property="og:title" content="{{ pageTitle }}" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="{{ currentUrl }}" />
|
||||
|
||||
{% if site.authorHandle %}
|
||||
<meta name="twitter:creator" content="@{{ site.authorHandle | replace('@', '') }}" />
|
||||
{% endif %}
|
||||
|
||||
{% if metaDesc %}
|
||||
<meta name="description" content="{{ metaDesc }}" />
|
||||
<meta name="twitter:description" content="{{ metaDesc }}" />
|
||||
<meta property="og:description" content="{{ metaDesc }}" />
|
||||
{% endif %}
|
||||
|
||||
{% if socialImage %}
|
||||
<meta property="og:image" content="{{ socialImage }}" />
|
||||
<meta name="twitter:image" content="{{ socialImage }}" />
|
||||
<meta property="og:image:alt" content="Page image for {{ site.name }}" />
|
||||
<meta name="twitter:image:alt" content="Page image for {{ site.name }}" />
|
||||
{% endif %}
|
||||
|
||||
{% if site.paymentPointer %}
|
||||
<meta name="monetization" content="{{ site.paymentPointer }}" />
|
||||
{% endif %}
|
92
src/_includes/partials/global/service-worker.js
Normal file
@ -0,0 +1,92 @@
|
||||
const CACHE_KEYS = {
|
||||
PRE_CACHE: `precache-${VERSION}`,
|
||||
RUNTIME: `runtime-${VERSION}`
|
||||
};
|
||||
|
||||
// URLS that we don’t want to end up in the cache
|
||||
const EXCLUDED_URLS = [
|
||||
'admin',
|
||||
'.netlify',
|
||||
'https://identity.netlify.com/v1/netlify-identity-widget.js',
|
||||
'https://unpkg.com/netlify-cms@^2.9.3/dist/netlify-cms.js',
|
||||
'/contact',
|
||||
'/thank-you'
|
||||
];
|
||||
|
||||
// URLS that we want to be cached when the worker is installed
|
||||
const PRE_CACHE_URLS = ['/', '/fonts/VarelaRound-Regular.ttf', '/fonts/OpenSans-Bold.ttf', '/fonts/OpenSans-SemiBold.ttf', '/fonts/OpenSans-Regular.ttf'];
|
||||
|
||||
// You might want to bypass a certain host
|
||||
const IGNORED_HOSTS = ['localhost', 'unpkg.com', ];
|
||||
|
||||
/**
|
||||
* Takes an array of strings and puts them in a named cache store
|
||||
*
|
||||
* @param {String} cacheName
|
||||
* @param {Array} items=[]
|
||||
*/
|
||||
const addItemsToCache = function(cacheName, items = []) {
|
||||
caches.open(cacheName).then(cache => cache.addAll(items));
|
||||
};
|
||||
|
||||
self.addEventListener('install', evt => {
|
||||
self.skipWaiting();
|
||||
|
||||
addItemsToCache(CACHE_KEYS.PRE_CACHE, PRE_CACHE_URLS);
|
||||
});
|
||||
|
||||
self.addEventListener('activate', evt => {
|
||||
// Look for any old caches that don't match our set and clear them out
|
||||
evt.waitUntil(
|
||||
caches
|
||||
.keys()
|
||||
.then(cacheNames => {
|
||||
return cacheNames.filter(item => !Object.values(CACHE_KEYS).includes(item));
|
||||
})
|
||||
.then(itemsToDelete => {
|
||||
return Promise.all(
|
||||
itemsToDelete.map(item => {
|
||||
return caches.delete(item);
|
||||
})
|
||||
);
|
||||
})
|
||||
.then(() => self.clients.claim())
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', evt => {
|
||||
const {hostname} = new URL(evt.request.url);
|
||||
|
||||
// Check we don't want to ignore this host
|
||||
if (IGNORED_HOSTS.indexOf(hostname) >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check we don't want to ignore this URL
|
||||
if (EXCLUDED_URLS.some(page => evt.request.url.indexOf(page) > -1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
evt.respondWith(
|
||||
caches.match(evt.request).then(cachedResponse => {
|
||||
// Item found in cache so return
|
||||
if (cachedResponse) {
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
// Nothing found so load up the request from the network
|
||||
return caches.open(CACHE_KEYS.RUNTIME).then(cache => {
|
||||
return fetch(evt.request)
|
||||
.then(response => {
|
||||
// Put the new response in cache and return it
|
||||
return cache.put(evt.request, response.clone()).then(() => {
|
||||
return response;
|
||||
});
|
||||
})
|
||||
.catch(ex => {
|
||||
return;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
24
src/_includes/partials/global/site-foot.njk
Normal file
@ -0,0 +1,24 @@
|
||||
<footer role="contentinfo" class="[ site-foot ]">
|
||||
<div class="wrapper">
|
||||
<div class="[ site-foot__inner ]">
|
||||
<div class="">
|
||||
<h3>Mentions légales</h3>
|
||||
<p>Protection des données</p>
|
||||
</div>
|
||||
<div class="">
|
||||
<h3>Crédits</h3>
|
||||
<p>Design et intégration : <a href="{{site.designerHandle}}" target="_blank">{{site.designerName}}</a></p>
|
||||
<p>Illustrations : {{site.illustrators}}
|
||||
</div>
|
||||
<div class="">
|
||||
<h3>Contact</h3>
|
||||
<p>{{site.authorName}}</p>
|
||||
<p>{{site.authorAddress}}<br>{{site.authorCity}}</p>
|
||||
<ul>
|
||||
<a href="{{site.authorSocial.mastodon}}" class="social">Mastodon</a>
|
||||
<a href="{{site.authorSocial.twitter}}" class="social">Twitter</a>
|
||||
<a href="{{site.authorSocial.linkedin}}" class="social">Linkedin</a>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
13
src/_includes/partials/global/site-head.njk
Normal file
@ -0,0 +1,13 @@
|
||||
<a class="skip-link" href="#main-content">Skip to content</a>
|
||||
<header role="banner" class="[ site-head ]">
|
||||
<div class="wrapper">
|
||||
<div class="[ site-head__inner ] [ md:box-flex space-between align-center ]">
|
||||
<a href="{{ url }}" class="[ site-head__site-name ] [ leading-tight ]">
|
||||
<span class="visually-hidden">{{ site.name }} - Home</span>
|
||||
{% include "icons/astrolabe_logo.svg" %}
|
||||
</a>
|
||||
{% set ariaLabel = 'navigation' %}
|
||||
{% include "partials/components/nav.njk" %}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
7
src/_includes/partials/global/third-party-comments.njk
Normal file
@ -0,0 +1,7 @@
|
||||
<!-- ADD YOUR THIRD PARTY COMMENTS CODE HERE -->
|
||||
<!-- COMMENTO EXAMPLE
|
||||
<div id="commento"></div>
|
||||
<script defer
|
||||
src="https://cdn.commento.io/js/commento.js">
|
||||
</script>
|
||||
-->
|
4
src/archive.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: 'Posts Archive'
|
||||
layout: 'layouts/archive.njk'
|
||||
---
|
30
src/feed.njk
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
permalink: '/feed.xml'
|
||||
---
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>{{ site.name }}</title>
|
||||
<subtitle></subtitle>
|
||||
<link href="{{ site.url }}{{ permalink }}" rel="self"/>
|
||||
<link href="{{ site.url }}/"/>
|
||||
{% if collections.posts|length %}
|
||||
<updated>{{ collections.posts | rssLastUpdatedDate }}</updated>
|
||||
{% endif %}
|
||||
<id>{{ site.url }}</id>
|
||||
<author>
|
||||
<name>{{ site.authorName }}</name>
|
||||
<email>{{ site.authorEmail }}</email>
|
||||
</author>
|
||||
{% for post in collections.posts %}
|
||||
{% set absolutePostUrl %}{{ site.url }}{{ post.url | url }}{% endset %}
|
||||
<entry>
|
||||
<title>{{ post.data.title }}</title>
|
||||
<link href="{{ absolutePostUrl }}"/>
|
||||
<updated>{{ post.date | rssDate }}</updated>
|
||||
<id>{{ absolutePostUrl }}</id>
|
||||
<content type="html"><![CDATA[
|
||||
{{ post.templateContent | safe }}
|
||||
]]></content>
|
||||
</entry>
|
||||
{% endfor %}
|
||||
</feed>
|
17
src/filters/date-filter.js
Normal file
@ -0,0 +1,17 @@
|
||||
// Stolen from https://stackoverflow.com/a/31615643
|
||||
const appendSuffix = n => {
|
||||
var s = ['th', 'st', 'nd', 'rd'],
|
||||
v = n % 100;
|
||||
return n + (s[(v - 20) % 10] || s[v] || s[0]);
|
||||
};
|
||||
|
||||
module.exports = function dateFilter(value) {
|
||||
const dateObject = new Date(value);
|
||||
|
||||
// const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
||||
const months = ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juill.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'];
|
||||
const dayWithSuffix = appendSuffix(dateObject.getDate());
|
||||
|
||||
// return `${dayWithSuffix} ${months[dateObject.getMonth()]} ${dateObject.getFullYear()}`;
|
||||
return `${dateObject.getDate()} ${months[dateObject.getMonth()]} ${dateObject.getFullYear()}`;
|
||||
};
|
9
src/filters/markdown-filter.js
Normal file
@ -0,0 +1,9 @@
|
||||
const markdownIt = require('markdown-it')({
|
||||
html: true,
|
||||
breaks: true,
|
||||
linkify: true
|
||||
});
|
||||
|
||||
module.exports = function markdown(value) {
|
||||
return markdownIt.render(value);
|
||||
};
|
5
src/filters/w3-date-filter.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = function w3cDate(value) {
|
||||
const dateObject = new Date(value);
|
||||
|
||||
return dateObject.toISOString();
|
||||
};
|
BIN
src/fonts/open-sans-v17-latin-300.woff
Normal file
BIN
src/fonts/open-sans-v17-latin-600.woff
Normal file
BIN
src/fonts/open-sans-v17-latin-700.woff
Normal file
BIN
src/fonts/open-sans-v17-latin-regular.woff
Normal file
BIN
src/fonts/varela-round-v12-latin-regular.woff
Normal file
BIN
src/fonts/varela-v10-latin-regular.woff
Normal file
BIN
src/images/demo-image-1.jpg
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
src/images/demo-image-2.jpg
Normal file
After Width: | Height: | Size: 147 KiB |
BIN
src/images/favicon.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
1
src/images/gitlab.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="110" height="101" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M109.052 56.536l-5.704-17.493a2.415 2.415 0 00-.138-.47L91.766 3.412a4.54 4.54 0 00-1.669-2.251 4.555 4.555 0 00-2.674-.846 4.478 4.478 0 00-2.661.856 4.464 4.464 0 00-1.632 2.266L72.222 36.942H37.795L26.871 3.438a4.465 4.465 0 00-1.624-2.26 4.478 4.478 0 00-2.65-.862h-.025a4.555 4.555 0 00-4.331 3.125L6.788 38.643c0 .032-.026.057-.035.09L.946 56.538a6.485 6.485 0 002.364 7.272l50.17 36.386a2.57 2.57 0 003.032-.016l50.179-36.37a6.493 6.493 0 002.361-7.275zM34.061 42.085l13.984 42.96-33.57-42.96H34.06zm27.911 42.97l13.41-41.187.578-1.783h19.602L65.19 80.92l-3.218 4.133zM87.467 6.735l9.827 30.206h-19.67l9.844-30.206zm-16.91 35.33l-9.743 29.927L55 89.816l-15.534-47.75h31.09zM22.55 6.736l9.846 30.206H12.739l9.81-30.206zM6.33 59.668a1.38 1.38 0 01-.501-1.547l4.311-13.225 31.624 40.466L6.329 59.668zm97.345 0L68.238 85.352l.118-.154 31.505-40.302 4.312 13.219a1.383 1.383 0 01-.498 1.55" fill="#111"/></svg>
|
After Width: | Height: | Size: 998 B |
BIN
src/images/social-share.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
40
src/index.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
layout: home
|
||||
title: Accueil
|
||||
brandHeading: La Coopérative d'Activité et d'Emploi spécialisée en informatique !
|
||||
newsHeading: Actualité & Évenements
|
||||
metaDesc: 'Hylia is a lightweight Eleventy starter kit to help you to create your own blog or personal website.'
|
||||
---
|
||||
|
||||
<article>
|
||||
<div class="content">
|
||||
|
||||
## Qui sommes-nous ?
|
||||
Astrolabe CAE est une scop spécialisée dans la prestation de **services** autour des métiers du **numérique**.
|
||||
Notre objectif est de favoriser l’**autonomie** et l’**émancipation** de nos membres sur un modèle d’économie sociale et **solidaire**.
|
||||
</div>
|
||||
|
||||
![logo Gitlab](/images/gitlab.svg)
|
||||
</article>
|
||||
|
||||
<article>
|
||||
<div class="content">
|
||||
|
||||
## Communs numérique
|
||||
Chez Astrolabe nous aimons et faisons la promotion du **logiciel libre**. Nos sommes membres d’[Alliance Libre](http://www.alliance-libre.org/) et nous mettons nos documents et projets internes à disposition sur notre [gitlab]().
|
||||
</div>
|
||||
|
||||
![logo Gitlab](/images/gitlab.svg "test")
|
||||
</article>
|
||||
|
||||
<article>
|
||||
<div class="content">
|
||||
|
||||
## Des profils variés
|
||||
Nos coopérateurs possèdent des compétences propres allant de développement linux embarqué au web design et créent ainsi la **pluralité** de nos prestations.
|
||||
<br><br>
|
||||
Nous sommes également **distributeurs** de la solution logicielle [Naega](https://www.crealead.com/naega#bootstrap-fieldgroup-nav-item--prsentation).
|
||||
</div>
|
||||
|
||||
![logo Gitlab](/images/gitlab.svg)
|
||||
</article>
|
98
src/js/components/theme-toggle.js
Normal file
@ -0,0 +1,98 @@
|
||||
// For syntax highlighting only
|
||||
const html = String.raw;
|
||||
|
||||
class ThemeToggle extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.STORAGE_KEY = 'user-color-scheme';
|
||||
this.COLOR_MODE_KEY = '--color-mode';
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
}
|
||||
|
||||
getCSSCustomProp(propKey) {
|
||||
let response = getComputedStyle(document.documentElement).getPropertyValue(propKey);
|
||||
|
||||
// Tidy up the string if there’s something to work with
|
||||
if (response.length) {
|
||||
response = response.replace(/\'|"/g, '').trim();
|
||||
}
|
||||
|
||||
// Return the string response by default
|
||||
return response;
|
||||
}
|
||||
|
||||
applySetting(passedSetting) {
|
||||
let currentSetting = passedSetting || localStorage.getItem(this.STORAGE_KEY);
|
||||
|
||||
if (currentSetting) {
|
||||
document.documentElement.setAttribute('data-user-color-scheme', currentSetting);
|
||||
this.setButtonLabelAndStatus(currentSetting);
|
||||
} else {
|
||||
this.setButtonLabelAndStatus(this.getCSSCustomProp(this.COLOR_MODE_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
toggleSetting() {
|
||||
let currentSetting = localStorage.getItem(this.STORAGE_KEY);
|
||||
|
||||
switch (currentSetting) {
|
||||
case null:
|
||||
currentSetting =
|
||||
this.getCSSCustomProp(this.COLOR_MODE_KEY) === 'dark' ? 'light' : 'dark';
|
||||
break;
|
||||
case 'light':
|
||||
currentSetting = 'dark';
|
||||
break;
|
||||
case 'dark':
|
||||
currentSetting = 'light';
|
||||
break;
|
||||
}
|
||||
|
||||
localStorage.setItem(this.STORAGE_KEY, currentSetting);
|
||||
|
||||
return currentSetting;
|
||||
}
|
||||
|
||||
setButtonLabelAndStatus(currentSetting) {
|
||||
this.modeToggleButton.innerText = `${
|
||||
currentSetting === 'dark' ? 'Light' : 'Dark'
|
||||
} theme`;
|
||||
this.modeStatusElement.innerText = `Color mode is now "${currentSetting}"`;
|
||||
}
|
||||
|
||||
render() {
|
||||
this.innerHTML = html`
|
||||
<div class="[ theme-toggle ] [ md:ta-right gap-top-500 ]">
|
||||
<div role="status" class="[ visually-hidden ][ js-mode-status ]"></div>
|
||||
<button class="[ button ] [ font-base text-base weight-bold ] [ js-mode-toggle ]">
|
||||
Dark theme
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
this.afterRender();
|
||||
}
|
||||
|
||||
afterRender() {
|
||||
this.modeToggleButton = document.querySelector('.js-mode-toggle');
|
||||
this.modeStatusElement = document.querySelector('.js-mode-status');
|
||||
|
||||
this.modeToggleButton.addEventListener('click', evt => {
|
||||
evt.preventDefault();
|
||||
|
||||
this.applySetting(this.toggleSetting());
|
||||
});
|
||||
|
||||
this.applySetting();
|
||||
}
|
||||
}
|
||||
|
||||
if ('customElements' in window) {
|
||||
customElements.define('theme-toggle', ThemeToggle);
|
||||
}
|
||||
|
||||
export default ThemeToggle;
|
9
src/pages/contact.md
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
title: 'Contact'
|
||||
permalink: '/contact/index.html'
|
||||
layout: 'layouts/contact.njk'
|
||||
---
|
||||
|
||||
You can have a contact page which uses a basic form. The [code with the form fields lives here](https://github.com/hankchizljaw/hylia/blob/master/src/_includes/layouts/contact.njk).
|
||||
|
||||
To delete the contact form for this site, delete this page in the CMS or at `src/pages/contact.md`. You probably will also want to delete `src/pages/thank-you.md`.
|
3
src/pages/pages.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"layout": "layouts/page.njk"
|
||||
}
|
6
src/pages/thank-you.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
title: 'Thank you'
|
||||
permalink: '/thank-you/index.html'
|
||||
---
|
||||
|
||||
This is your thank you page where if someone fills in your contact form, they will be directed to. Make sure you add a nice message 🙂
|
64
src/posts/a-post-with-code-samples.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: A post with code samples
|
||||
date: '2019-12-18'
|
||||
tags:
|
||||
- demo-content
|
||||
- code
|
||||
- blog
|
||||
---
|
||||
The best way to demo a code post is to display a real life post, so check out this one from [andy-bell.design](https://andy-bell.design/wrote/creating-a-full-bleed-css-utility/) about a full bleed CSS utility.
|
||||
|
||||
- - -
|
||||
|
||||
Sometimes you want to break your components out of the constraints that they find themselves in. A common situation where this occurs is when you don’t have much control of the container that it exists in, such as a CMS main content area.
|
||||
|
||||
This is even more the case with editing tools such as the [WordPress Gutenberg editor](https://wordpress.org/gutenberg/), where in theory, you could pull in a component from a design system and utilise it in the main content of your web page. In these situations, it can be pretty darn handy to have a little utility that makes the element 100% of the viewport’s width _and_ still maintain its flow within its parent container.
|
||||
|
||||
This is when I normally pull the `.full-bleed` utility class out of my back pocket.
|
||||
|
||||
## The `.full-bleed` utility
|
||||
|
||||
It’s small, but hella mighty:
|
||||
|
||||
```css
|
||||
.full-bleed {
|
||||
width: 100vw;
|
||||
margin-left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
```
|
||||
|
||||
Here it is in a context where it makes a fancy `<aside>` and a `<figure>` element bleed out of their parent container.
|
||||
|
||||
<iframe height="300" style="width: 100%;" scrolling="no" title="Piccalilli CSS Utility — Issue #2 — Full bleed utility" src="//codepen.io/andybelldesign/embed/Nmxrwv/?height=300&theme-id=dark&default-tab=css,result" frameborder="no" allowtransparency="true" allowfullscreen="true">
|
||||
See the Pen <a href='https://codepen.io/andybelldesign/pen/Nmxrwv/'>Piccalilli CSS Utility — Issue #2 — Full bleed utility</a> by Andy Bell
|
||||
(<a href='https://codepen.io/andybelldesign'>@andybelldesign</a>) on <a href='https://codepen.io'>CodePen</a>.
|
||||
</iframe>
|
||||
|
||||
The `.full-bleed` utility gives those elements prominence and _importantly_ keeps their semantic place in the page. Just how I like it.
|
||||
|
||||
- - -
|
||||
|
||||