summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build/article.mjs31
-rw-r--r--src/build/i18n.mjs85
-rw-r--r--src/build/index.mjs208
-rw-r--r--src/build/list-articles.mjs7
-rw-r--r--src/build/loadMD.mjs79
-rw-r--r--src/build/rss.mjs26
-rw-r--r--src/build/special_box.mjs15
-rw-r--r--src/build/to-html.mjs12
-rw-r--r--src/build/utils.mjs10
-rwxr-xr-xsrc/css/_contenu.scss451
-rwxr-xr-xsrc/css/_sommaire.scss110
-rw-r--r--src/css/_style.scss66
-rwxr-xr-xsrc/css/design.scss168
-rw-r--r--src/img/computer.svg2
-rw-r--r--src/img/ic_note_black_48px.svg4
-rw-r--r--src/img/image-formats.svg118
-rw-r--r--src/img/lt.svg9
-rw-r--r--src/img/masto.svg1
-rw-r--r--src/img/mastodon.svg4
-rw-r--r--src/img/moon.svg1
-rw-r--r--src/img/sun.svg1
-rw-r--r--src/js/love.js125
-rw-r--r--src/js/sidenotes.js2
-rw-r--r--src/js/theme.js126
-rw-r--r--src/js/zen.js36
-rw-r--r--src/templates/article.tmpl8
-rw-r--r--src/templates/header.tmpl4
-rw-r--r--src/templates/hid.tmpl1
-rw-r--r--src/templates/index.tmpl4
-rw-r--r--src/templates/left.tmpl24
-rw-r--r--src/templates/likes.tmpl19
-rw-r--r--src/templates/tag.tmpl25
32 files changed, 1494 insertions, 288 deletions
diff --git a/src/build/article.mjs b/src/build/article.mjs
new file mode 100644
index 0000000..1a7b09b
--- /dev/null
+++ b/src/build/article.mjs
@@ -0,0 +1,31 @@
+// Set of functions to handle articles
+
+function getArticleYear(article) {
+ if (article.metaData.pubDate.getFullYear) {
+ return article.metaData.pubDate.getFullYear();
+ }
+
+ if (article.metaData.pubDate.getUTCFullYear) {
+ return article.metaData.pubDate.getUTCFullYear();
+ }
+
+ return 0;
+}
+
+function getArticleDate(article) {
+ if (article.metaData.pubDate.getDate) {
+ return article.metaData.pubDate.getFullYear() * 100 + article.metaData.pubDate.getDate();
+ }
+
+ if (article.metaData.pubDate.getUTCDate) {
+ return article.metaData.pubDate.getUTCFullYear() * 100 + article.metaData.pubDate.getDate();
+ }
+
+ return 0;
+}
+
+function cmpArticles(a, b) {
+ return getArticleDate(b) - getArticleDate(a);
+}
+
+export {getArticleDate, getArticleYear, cmpArticles};
diff --git a/src/build/i18n.mjs b/src/build/i18n.mjs
new file mode 100644
index 0000000..d1cebe6
--- /dev/null
+++ b/src/build/i18n.mjs
@@ -0,0 +1,85 @@
+
+const i18n = {
+ fr: {
+ intro: {
+ 'description': 'Éternel étudiant en Math-Info.',
+ 'about': 'Autodidacte passionné,<br><span class="type_wrap"><span class="type">désormais ingénieur.</span></span>',
+ 'about_tags': 'GNU\\Linux, C, C++, Python, Math, autohébergement, décentralisation, P2P, commun, ... <br> ',
+ },
+ title: {
+ 'main': 'ache: Blog personnel',
+ 'home': 'L\'accueil',
+ 'git': 'Dépôt git personnel',
+ 'mastodon': 'Mon mastodon',
+ },
+ articles: [
+ 'framasoft-et-les-mascottes-du-libre.md',
+ 'les-trains-et-la-publicité.md',
+ 'formats-images-web.md',
+ 'bizarreries-du-langage-c.md',
+ 'retour-sur-laoc-2021-semaine-1.md',
+ '2FA-discord-sur-pc.md',
+ 'duckduckgo-google-en-mieux.md',
+ ],
+ rss: {
+ 'title': 'ache: Blog personnel',
+ 'quick_description': 'Programmation, Algorithmique, Système, *pick you poison*',
+ 'description': `<b>Ceci est un flux RSS</b> à destination des agrégateurs de contenu.<br>\nEn tant qu'être humain vous cherchez certainement <a href="https://ache.one/fr/">mon site web</a>.`
+ },
+ toc_keyword: "Sommaire",
+ tag_desc: "Liste des articles ayant le tag",
+ index_desc: "Blog personnel à propos de programmation, logiciel libre et autohébergement. Essayons de rendre le monde meilleur.",
+ like_title: "Si vous avez aimez cet article cliquez sur le cœur !",
+ like_text: "Vous pouvez même envoyez plusieurs cœurs ! <br><span class=\"likesNotes\">Le délais d'attente entre deux cœurs double à chaque fois.</span>",
+ },
+ en: {
+ intro: {
+ 'description': 'Eternal student in computer science.',
+ 'quick_description': 'Programmation, Algorithmique, Système, *pick you poison*',
+ 'about': 'Self-taught developper,<br><span class="type_wrap"><span class="type">now engineer.</span></span>',
+ 'about_tags': 'GNU\\Linux, C, C++, Python, Math, self-hosted, dececntralisation, P2P, ... <br>',
+ },
+ title: {
+ 'main': 'ache: Personal blog',
+ 'home': 'Home',
+ 'git': 'Personnel git repository',
+ 'mastodon': 'Mastodon account',
+ },
+ articles: [
+ 'rail-and-advertising.md',
+ 'web-image-formats.md',
+ 'c-language-quirks.md',
+ ],
+ rss: {
+ 'title': 'ache: Personal blog',
+ 'description': `<b>This is a RSS feed</b> for content agreagator.<br>\nAs a human being, you are certainly looking for <a href="https://ache.one/en/">my website</a>.`
+ },
+ toc_keyword: "Table of contents",
+ tag_desc: "List of articles with the tag",
+ index_desc: "Personal blog about programming, free software and self-hosting. Let's try to make the world a better place.",
+ like_title: "If you liked this article click on the heart!",
+ like_text: "You can even send multiple hearts! <br><span class=\"likesNotes\">The waiting time between two hearts doubles each time.</span>",
+ }
+}
+
+const lang_desc = {
+ fr: "Version Française",
+ en: "English version",
+}
+
+export function addDescription(alt_lang) {
+ if (alt_lang) {
+ alt_lang.forEach(e => {
+ e.description = lang_desc[e.lang]
+ });
+ }
+
+ return alt_lang;
+}
+
+export function getTocHeading() {
+ return Object.entries(i18n).map(([_, v]) => v.toc_keyword).join('|');
+}
+
+
+export default i18n;
diff --git a/src/build/index.mjs b/src/build/index.mjs
index c7e1cf7..a14cdc7 100644
--- a/src/build/index.mjs
+++ b/src/build/index.mjs
@@ -1,104 +1,150 @@
+import process from 'node:process';
import fs from 'node:fs';
import mustache from 'mustache';
-import {u} from 'unist-builder';
-import {h} from 'hastscript';
-import {select} from 'hast-util-select';
-import {toString as hastToString} from 'mdast-util-to-string';
-import cssesc from 'cssesc';
-
-import {toHtmlRaw, toString, toMdRaw, mdToHtmlRaw} from './to-html.mjs';
import loadSVG from './load-svg.mjs';
-import listArticles from './list-articles.mjs';
import getRSS from './rss.mjs';
-import toml from '@ltd/j-toml';
-
-const loadMD = (listFile, suffix) => {
- const listContent = [];
- for (const file of listFile) {
- console.log(`Working on ${file}`);
- const content = fs.readFileSync(`${suffix}/${file}`, 'utf8');
- const mdRaw = toMdRaw(content);
- const tomlStringValue = mdRaw.children[0].value;
- const metaData = toml.parse(tomlStringValue);
- const newHTML = mdToHtmlRaw(mdRaw);
-
- const htmlContent = newHTML;
- const htmlRender = toString(htmlContent);
-
- const titleHtml = select('h1', htmlContent);
- const intro = select('p', htmlContent);
- intro.children = intro.children.filter(child => child.tagName !== 'br');
-
- const logo = select('img', intro);
- logo.properties.src = `${suffix}/${logo.properties.src}`;
- logo.properties.height = '150';
- logo.properties.width = '150';
- titleHtml.children[0].properties.href = `${suffix}/${file.slice(0, -3)}`;
-
- const title = hastToString(titleHtml);
- const domTitle = cssesc(title.replace(/\s+/g, '-').replace(/['"#@]/, '').toLowerCase()); // Maybe encodeURI
-
- const readMore = h('a', 'Lire plus...');
-
- readMore.properties.href = `${suffix}/${file.slice(0, -3)}`;
-
- listContent.push({
- name: file.slice(0, -3),
- content: htmlRender,
- intro: toString(u('root', [titleHtml, intro, readMore])),
- introDesc: hastToString(intro),
- imageUrl: logo.properties.src,
- metaData,
- title,
- domTitle,
- });
- }
+import loadMD from './loadMD.mjs';
+import {cmpArticles} from './article.mjs';
+import i18n from './i18n.mjs';
+import {addDescription} from './i18n.mjs';
+import {minifyHTML} from './utils.mjs';
+
+import { SitemapStream, streamToPromise } from 'sitemap'
+import { Readable } from 'stream'
- return listContent;
-};
const leftPanelTmpl = fs.readFileSync('src/templates/left.tmpl', 'utf8');
+const likesTmpl = fs.readFileSync('src/templates/likes.tmpl', 'utf8');
const headerTmpl = fs.readFileSync('src/templates/header.tmpl', 'utf8');
const articleTmpl = fs.readFileSync('src/templates/article.tmpl', 'utf8');
const indexTmpl = fs.readFileSync('src/templates/index.tmpl', 'utf8');
+const tagTmpl = fs.readFileSync('src/templates/tag.tmpl', 'utf8');
+const hidTmpl = fs.readFileSync('src/templates/hid.tmpl', 'utf8');
const baseUrl = 'https://ache.one/';
const partials = {
header: headerTmpl,
leftPanel: leftPanelTmpl,
+ likesButton: likesTmpl,
+ hid: hidTmpl,
};
+// Load global variables
const svg = loadSVG();
-const articles = loadMD(listArticles, 'articles');
+let links = [];
+
+for (const lang in i18n) {
+ const tagsArticle = new Map();
+ const filter = process.argv.slice(2);
+ const listArticle = (filter.length > 0) ? i18n[lang].articles.filter((article) => filter.includes(article.name)) : i18n[lang].articles;
+ const articles = loadMD(listArticle, 'articles', lang);
+
+ for (const article of articles) {
+ const context = {
+ svg,
+ page_title: `${article.title} - ache`,
+ title: i18n[lang].title,
+ intro: i18n[lang].intro,
+ lang,
+ canonical: `${baseUrl}${article.url.slice(1)}`,
+ content: article.content,
+ title: i18n[lang].title,
+ metaData: article.metaData,
+ alt_lang: addDescription(article.metaData.alt_lang),
+ description: article.intro,
+
+ like_title: i18n[lang].like_title,
+ like_text: i18n[lang].like_text,
+ };
+ const output = mustache.render(articleTmpl, context, partials);
+
+ console.log(`Create : ${article.title}`);
+ fs.writeFileSync(`articles/${article.name}.html`, minifyHTML(output));
+ links.push({url: context.canonical, changefreq: 'yearly', priority: 0.6, img: [{url: article.imageUrl}]})
+
+ for (const tag of article.metaData.tags) {
+ if (tagsArticle.has(tag)) {
+ tagsArticle.get(tag).push(article);
+ } else {
+ tagsArticle.set(tag, [article]);
+ }
+ }
+ }
-for (const article of articles) {
- const context = {
- svg,
- title: `${article.title} - ache`,
- canonical: baseUrl + article.domTitle,
- content: article.content,
- domTitle: article.domTitle,
- };
- const output = mustache.render(articleTmpl, context, partials);
+// Set of pages language dependant
+ try {
+ fs.mkdirSync(`${lang}/tag`, {recursive: true});
+ } catch {
+ fs.rmSync(`${lang}/tag`, {force: true, recursive: true});
+ fs.mkdirSync(`${lang}/tag`, {recursive: true});
+ }
- console.log(`Create : ${article.title}`);
- fs.writeFileSync(`articles/${article.name}.html`, output);
-}
+ for (const [tag, articles] of tagsArticle.entries()) {
+ console.log(`Create tag page : ${lang}/${tag}.html`);
+ articles.sort(cmpArticles);
+
+ const context = {
+ svg,
+ page_title: `ache - Tag: ${tag}`,
+ title: i18n[lang].title,
+ intro: i18n[lang].intro,
+ lang,
+ tag,
+ articles,
+ description: `${i18n[lang]['tag_desc']} ${tag}.`,
+ };
+
+ const output = mustache.render(tagTmpl, context, partials);
+ fs.writeFileSync(`${lang}/tag/${tag}.html`, minifyHTML(output));
+ links.push({url: `${baseUrl}${lang}/tag/${tag}`, changefreq: 'monthly', priority: 0.3})
+ }
-console.log('Create : rss.xml');
-const xmlFeed = getRSS(articles, baseUrl);
-fs.writeFileSync('rss.xml', xmlFeed);
-
-{
- const context = {
- title: 'ache: Blog personnel',
- canonical: baseUrl,
- svg,
- articles,
- };
-
- console.log('Create : Home page');
- const output = mustache.render(indexTmpl, context, partials);
- fs.writeFileSync('index.html', output);
+ console.log(`Create RSS Flux: ${lang}/rss.xml`);
+ const xmlFeed = getRSS(articles, baseUrl, lang);
+ fs.writeFileSync(`${lang}/rss.xml`, xmlFeed);
+ links.push({url: `${baseUrl}${lang}/rss.xml`, changefreq: 'monthly', priority: 0.3})
+
+ {
+ const alt_lang = {
+ fr: {
+ lang: 'en',
+ url: '/en/',
+ },
+ en: {
+ lang: 'fr',
+ url: '/fr/',
+ },
+ };
+ const context = {
+ page_title: i18n[lang].title.main,
+ title: i18n[lang].title,
+ intro: i18n[lang].intro,
+ lang,
+ canonical: `${baseUrl}${lang}`,
+ svg,
+ articles,
+ alt_lang: [alt_lang[lang]],
+ description: i18n[lang].index_desc,
+ };
+
+ console.log(`Create : Home page ${lang}`);
+ const output = mustache.render(indexTmpl, context, partials);
+ fs.writeFileSync(`${lang}/index.html`, minifyHTML(output));
+ links.push({url: `${baseUrl}${lang}`, changefreq: 'monthly', priority: 0.7, img: [{url: "https://ache.one/res/ache.svg"}]})
+ }
}
+
+console.log(`Create: sitemap.xml`);
+
+// Create a stream to write to
+const stream = new SitemapStream({hostname: 'https://ache.one'});
+
+// Return a promise that resolves with your XML string
+streamToPromise(
+ Readable.from(links)
+ .pipe(stream))
+ .then(data => data.toString())
+ .then(sitemapXML => fs.writeFileSync("sitemap.xml", sitemapXML)
+);
+
diff --git a/src/build/list-articles.mjs b/src/build/list-articles.mjs
deleted file mode 100644
index d327573..0000000
--- a/src/build/list-articles.mjs
+++ /dev/null
@@ -1,7 +0,0 @@
-const listArticles = [
- 'bizarreries-du-langage-c.md',
- 'retour-sur-laoc-2021-semaine-1.md',
- '2FA-discord-sur-pc.md',
- 'duckduckgo-google-en-mieux.md',
-];
-export default listArticles;
diff --git a/src/build/loadMD.mjs b/src/build/loadMD.mjs
new file mode 100644
index 0000000..6ba4f76
--- /dev/null
+++ b/src/build/loadMD.mjs
@@ -0,0 +1,79 @@
+import fs from 'node:fs';
+import {u} from 'unist-builder';
+import {h} from 'hastscript';
+import {select} from 'hast-util-select';
+import {toString as hastToString} from 'mdast-util-to-string';
+import cssesc from 'cssesc';
+import toml from '@ltd/j-toml';
+
+import {toString, toMdRaw, mdToHtmlRaw} from './to-html.mjs';
+import {getArticleYear} from './article.mjs';
+import i18n from './i18n.mjs';
+
+const loadMD = (listFile, suffix, lang) => {
+ const listContent = [];
+ for (const file of listFile) {
+ console.log(`Working on ${file}`);
+ const content = fs.readFileSync(`${suffix}/${file}`, 'utf8');
+ const mdRaw = toMdRaw(content);
+ const tomlStringValue = mdRaw.children[0].value;
+ const metaData = toml.parse(tomlStringValue);
+ const newHTML = mdToHtmlRaw(mdRaw);
+
+ const htmlContent = newHTML;
+ const htmlRender = toString(htmlContent);
+
+ const titleHtml = select('h1', htmlContent);
+ const intro = select('p', htmlContent);
+ intro.children = intro.children.filter(child => child.tagName !== 'br');
+
+ const logo = select('img', intro);
+ if (logo && logo?.properties) {
+ if (logo.properties.src[0] != '/') {
+ logo.properties.src = `/${suffix}/${logo.properties.src}`;
+ }
+ logo.properties.height = '150';
+ logo.properties.width = '150';
+ }
+
+ const logoP = select('source', intro);
+ if (logoP !== null) {
+ logoP.properties.srcSet = `/${suffix}/${logoP.properties.srcSet}`;
+ }
+
+ titleHtml.children[0].properties.href = `/${suffix}/${file.slice(0, -3)}`;
+
+ const title = hastToString(titleHtml);
+ const domTitle = cssesc(title.replace(/\s+/g, '-').replace(/['"#@]/, '').toLowerCase()); // Maybe encodeURI
+
+ const readMore = h('a', i18n[lang]['read_more']);
+
+ readMore.properties.href = `/${suffix}/${file.slice(0, -3)}`;
+ const pubYear = getArticleYear({metaData});
+
+ if (metaData.pubDate) {
+ try {
+ metaData.pubDateISO = metaData.pubDate.toISOString();
+ } catch (error) {
+ console.error(`Error on file ${file} with pubDate (${metaData.pubDate}): ${error}`);
+ }
+ }
+
+ listContent.push({
+ name: file.slice(0, -3),
+ content: htmlRender,
+ intro: toString(u('root', [titleHtml, intro, readMore])),
+ introDesc: hastToString(intro),
+ imageUrl: logo?.properties?.src || '',
+ metaData,
+ pubYear,
+ title,
+ domTitle,
+ url: `/${suffix}/${file.slice(0, -3)}`,
+ });
+ }
+
+ return listContent;
+};
+
+export default loadMD;
diff --git a/src/build/rss.mjs b/src/build/rss.mjs
index e890152..6394af5 100644
--- a/src/build/rss.mjs
+++ b/src/build/rss.mjs
@@ -1,37 +1,43 @@
import RSS from 'rss';
+import i18n from './i18n.mjs';
-const getRSS = (articles, baseUrl) => {
+const getRSS = (articles, baseUrl, lang) => {
+ console.log(i18n[lang]['rss']['title']);
const rssFeed = new RSS({
- title: 'ache: Blog personnel',
- description: 'Programmation, Algorithmique, Système, *pick you poison*',
+ title: i18n[lang]['rss']['title'],
+ description: i18n[lang]['rss']['description'],
// eslint-disable-next-line camelcase
+ custom_namespaces: {
+ 'visible_description': i18n[lang]['rss']['description']
+ },
+ site_url: "https://ache.one",
feed_url: `${baseUrl}rss.xml`,
canonical: `${baseUrl}rss.xml`,
// eslint-disable-next-line camelcase
site_url: baseUrl,
// eslint-disable-next-line camelcase
image_url: `${baseUrl}ache.svg`,
- language: 'fr',
- pubDate: (new Date().toLocaleString()),
+ language: lang,
+ pubDate: Date(),
ttl: '1440',
- // eslint-disable-next-line camelcase
- custom_elements: ['<?xml-stylesheet type="text/css" href="http://localhost:8080/s/css/style.css" ?>'],
});
for (const article of articles.slice(0, 10)) {
+ let image_url = (article.imageUrl[0] != '/') ? `/${article.imageUrl}` : article.imageUrl;
+
rssFeed.item({
title: article.title,
description: '<article>' + article.content + '</article>',
// eslint-disable-next-line camelcase
- image_url: article.imageUrl,
+ image_url,
url: `${baseUrl}articles/${article.name}`,
guid: article.domTitle,
author: 'ache',
- date: article.metaData.pubDate.toISOString(),
+ date: article.metaData.pubDateISO,
categories: article.metaData.tags,
// eslint-disable-next-line camelcase
custom_elements: [
- {logo: article.imageUrl},
+ {logo: image_url},
{intro: article.introDesc},
],
});
diff --git a/src/build/special_box.mjs b/src/build/special_box.mjs
index 0b284ec..1457a98 100644
--- a/src/build/special_box.mjs
+++ b/src/build/special_box.mjs
@@ -10,6 +10,7 @@ export default function specialBox() {
if (node.type === 'containerDirective' && (
node.name === 'attention'
|| node.name === 'question'
+ || node.name === 'note'
|| node.name === 'information')) {
const data = node.data || (node.data = {});
@@ -18,6 +19,20 @@ export default function specialBox() {
className: 'special-box ' + node.name,
};
}
+ if (node.type === 'containerDirective' && node.name === 'details') {
+ if(node.children.length > 0 && node.children[0].type == "paragraph") {
+ node.children[0] = {
+ type: "containerDirective",
+ data: {
+ hName: 'summary'
+ },
+ children: node.children[0].children
+ };
+
+ const data = node.data || (node.data = {});
+ data.hName = 'details';
+ }
+ }
});
};
}
diff --git a/src/build/to-html.mjs b/src/build/to-html.mjs
index 4bc3c06..786f91d 100644
--- a/src/build/to-html.mjs
+++ b/src/build/to-html.mjs
@@ -7,6 +7,7 @@ import remarkMath from 'remark-math';
import remarkFrontmatter from 'remark-frontmatter';
import remarkRehype from 'remark-rehype';
import rehypeSlug from 'rehype-slug';
+import rehypePicture from 'rehype-picture'
import rehypeKaTeX from 'rehype-katex';
import rehypeRaw from 'rehype-raw';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
@@ -14,6 +15,7 @@ import rehypeStringify from 'rehype-stringify';
import rehypeHighlight from 'rehype-highlight';
import remarkSpecialBox from './special_box.mjs';
import remarkRemoveFootnoteHeader from './remove-footnote-header.mjs';
+import {getTocHeading} from './i18n.mjs';
const autoLinkOption = {
behavior: 'wrap',
@@ -23,10 +25,14 @@ const autoLinkOption = {
},
};
+const pictureOptions = {
+ 'png': {avif: 'image/avif'}
+}
+
const generator = unified()
.use(remarkParse)
.use(remarkGfm)
- .use(remarkToc, {heading: 'Sommaire', tight: true, ordered: true})
+ .use(remarkToc, {heading: getTocHeading(), tight: true, ordered: true})
.use(remarkMath)
.use(remarkDirective)
.use(remarkSpecialBox)
@@ -34,6 +40,7 @@ const generator = unified()
.use(remarkRehype, {allowDangerousHtml: true})
.use(rehypeRaw)
.use(remarkRemoveFootnoteHeader)
+ .use(rehypePicture, pictureOptions)
.use(rehypeKaTeX)
.use(rehypeSlug)
.use(rehypeHighlight)
@@ -43,7 +50,7 @@ const generator = unified()
const generatorMd = unified()
.use(remarkParse)
.use(remarkGfm)
- .use(remarkToc, {heading: 'Sommaire', tight: true, ordered: true})
+ .use(remarkToc, {heading: getTocHeading(), tight: true, ordered: true})
.use(remarkMath)
.use(remarkDirective)
.use(remarkSpecialBox)
@@ -53,6 +60,7 @@ const generatorHTML = unified()
.use(remarkRehype, {allowDangerousHtml: true})
.use(rehypeRaw)
.use(remarkRemoveFootnoteHeader)
+ .use(rehypePicture, pictureOptions)
.use(rehypeKaTeX)
.use(rehypeSlug)
.use(rehypeHighlight)
diff --git a/src/build/utils.mjs b/src/build/utils.mjs
new file mode 100644
index 0000000..fa85ee6
--- /dev/null
+++ b/src/build/utils.mjs
@@ -0,0 +1,10 @@
+import { minify } from 'html-minifier';
+
+export const minifyHTML = (html) => minify(html, {
+ removeAttributeQuotes: true,
+ removeComments: true,
+ minifyJS: true,
+ minifyCSS: true,
+ collapseWhitespace: true,
+ collapseBooleanAttributes: true,
+})
diff --git a/src/css/_contenu.scss b/src/css/_contenu.scss
index 53c131f..ee809ca 100755
--- a/src/css/_contenu.scss
+++ b/src/css/_contenu.scss
@@ -1,53 +1,48 @@
article {
-/*
- margin-left: #{"max(0px, (100vw - var(--width_panel) - 10px - 950px - 6vw - 2px - 15px)*11/24)"};
- margin-right: #{"max(0px, (100vw - var(--width_panel) - 10px - 950px - 6vw - 2px - 15px)*13/24)"};
-*/
margin: auto 0 0 0;
- a {
- color: #7C54CB;
- text-decoration: none;
- &:hover, &:focus {
- text-decoration: underline;
- text-decoration-style: dashed;
- }
- }
+ font-family: Nimbus sans, Fira Code, Helvetica, get a font bro, Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
+ line-height: 1.5rem;
+ font-size: 1rem;
- font-family: "noto serif", 'Georgia', serif;
position: relative;
- max-width: 950px; ;
- line-height: 1.6rem;
+ max-width: 950px;
.pubdate {
- position: absolute;
- top: 0;
- right: 0;
- margin: 55px 10px;
- transform: rotate(20deg);
- text-shadow: 1px 1px 0.2px green;
- overflow: clip;
- color: pink;
text-align: right;
+ line-height: 1.65;
}
ul {
line-height: 1.6;
}
+ h1, h2, h3 {
+ font-family: Palatino Linotype, Bookman Old Style, Fira Code, get a font bro, Times;
+ }
+
+ h1, h2, h3, h4 {
+ margin: 2.5rem 0 1rem 0;
+ }
+ p {
+ margin: 0.5rem 0;
+ }
+
h1 {
- font-size: 3rem;
+ font-size: 2rem;
line-height: 3rem;
- color: #605;
+ margin: 0.5rem 0;
}
h2 {
- font-size: 2rem;
+ font-size: 1.6rem;
line-height: 3rem;
- color: #551;
}
h3 {
- font-size: 1.6rem;
+ font-size: 1.3rem;
+ line-height: 3rem;
+ }
+ h4 {
+ font-size: 1.1rem;
line-height: 3rem;
- color: #660;
}
.anchor {
@@ -67,21 +62,31 @@ article {
}
> p:first-of-type {
- color: #944040;
> img {
height: 150px;
+ width: 150px;
float: right;
+ position: relative;
+ top: -25px;
+ }
+ > img:not([src$="-inv.svg"]) {
+ filter: revert;
+ }
+ > picture {
+ height: 150px;
+ width: 150px;
+ float: right;
+ position: relative;
+ top: -25px;
}
@media #{$gt-gsm} {
margin-top: 2.5% 0;
}
}
-
-
@media #{$gt-gsm} {
ul {
- line-height: 1.4;
+ line-height: 1.5;
}
float: none;
@@ -103,10 +108,22 @@ article {
transition: margin-left 0.5s ease-out 0.25s;
}
}
+ li.task-list-item {
+ list-style-type: "- ";
+ input[type='checkbox'] {
+ width: 20px;
+ height: 20px;
+ }
+ }
li p {
display: inline;
}
- ol {
+ #sommaire + ol, #table-of-contents + ol {
+ line-height: 1.6rem;
+ @media #{$gt-gsm} {
+ line-height: 1.4em;
+ }
+
li {
list-style-type: upper-roman;
}
@@ -115,7 +132,6 @@ article {
}
}
.footnotes {
- color: #504d4d;
font-size: 0.8em;
li {
padding-bottom: 15px;
@@ -124,14 +140,33 @@ article {
ol p {
display: inline;
}
+
+ @mixin lightMode {
+ color: #504d4d;
+ }
+ @mixin darkMode {
+ color: #E0DDDD;
+ }
+
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
+ &.light{ @include lightMode; }
+ &.dark { @include darkMode; }
+
+ }
+
+ blockquote {
+ padding: 1px 2%;
+
+ border-left: 5px solid #ccc;
}
- font-size: 1.3rem;
h1 h2 h3 {
line-height: initial;
}
-
-
+ h1, h2, h3, h4, h5 {
+ text-indent: -10px;
+ }
@media #{$gsm} {
margin: 0;
@@ -142,38 +177,88 @@ article {
font-size: 0.9rem;
}
}
+ @media #{$big-laptop} {
+ pre code {
+ width: 110%;
+ margin: 0 -10%;
+ }
+ }
+ @mixin lightMode {
+ .pubDate {
+ color: #606060;
+ }
+ blockquote {
+ color: #504d4d;
+ }
+
+ h4, h5, h6 {
+ color: black;
+ }
+ img {
+ filter: none;
+ }
+ color: initial;
+
+ > p:first-of-type {
+ > img[src$=".jpg"], > img[src$=".png"], > img[src$=".avif"] {
+ filter: none;
+ }
+ }
+ }
@mixin darkMode {
- h1, h2, h3, h4, h5 {
+ .pubDate {
+ color: #606060;
+ }
+ blockquote {
+ color: #E0DDDD;
+ }
+
+ h4, h5, h6 {
color: #EFEFEF;
- text-indent: -10px;
}
- img {
+ img:not(.no-dark) {
filter: invert(1);
}
color: #EFEFEF;
> p:first-of-type {
- color: #6bbfbf;
- > img {
+ > img[src$=".jpg"], > img[src$=".png"], > img[src$=".avif"] {
filter: invert(0);
}
}
}
- @media (prefers-color-scheme: dark) { @include darkMode; } &.dark { @include darkMode; }
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
+ &.light{ @include lightMode; }
+ &.dark { @include darkMode; }
+
+ iframe, img, div, video, svg, image {
+ border: none;
+ margin: 0 auto;
+ @media #{$big-laptop} {
+ &.big {
+ width: 118%;
+ max-width: 118%;
+ margin: 0 -10%;
+ }
+ }
+ }
}
.keybs {
- border: 1px solid gray;
font-size: 1em;
- box-shadow: 1px 0 1px 0 #eee,0 2px 0 2px #ccc,0 2px 0 3px #444;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
margin: 2px 3px;
padding: 1px 5px;
white-space: nowrap;
+
+ // Theme style
+ border: 1px solid gray;
+ box-shadow: 1px 0 1px 0 #eee,0 2px 0 2px #ccc,0 2px 0 3px #444;
}
.marge {
@@ -185,16 +270,31 @@ article {
}
}
.sidenotes {
- margin: 10px 10px 0 0;
+ margin: 10px 10px 0 10%;
text-align: justify;
+
@media #{$tab} {
display: none;
}
+ @mixin lightMode {
+ color: #333333;
+ sup {
+ color: black;
+ }
+ }
+
@mixin darkMode {
color: #eee;
+ sup {
+ color: white;
+ }
}
- @media (prefers-color-scheme: dark) { @include darkMode; } &.dark { @include darkMode; }
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
+ &.light{ @include lightMode; }
+ &.dark { @include darkMode; }
+
transition: width 0.25s ease-out 0.25s;
position: relative;
max-width: 475px;
@@ -204,13 +304,254 @@ article {
.sidenote {
position: absolute;
font-style: oblique;
- font-size: 1.05rem;
+ font-size: 0.8rem;
}
}
-code {
- color: #a00;
- background: #e2e2e2;
- border: 0px;
- border-radius: 8px;
- padding: 0 5px;
+
+section.likes {
+ display: flex;
+ justify-content: center;
+ margin: 3rem 0 1rem 0;
+
+ @mixin lightMode {
+ .likesBox {
+ background-color: #CDE3EC;
+ .likesNotes {
+ color: #555;
+ }
+ .icon {
+ .nbLikes {
+ color: #00324D;
+ }
+ }
+ }
+ }
+ @mixin darkMode {
+ .likesBox {
+ background-color: #3C3C7C;
+ .likesNotes {
+ color: #CCC;
+ }
+ .icon {
+ .nbLikes {
+ color: #F0D5AD;
+ }
+ }
+ }
+ }
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
+ &.light{ @include lightMode; }
+ &.dark { @include darkMode; }
+
+ .likesBox {
+ padding: 20px;
+ border-radius: 8px;
+ display: flex;
+
+
+ .likesTitle {
+ font: monospace;
+ font-weight: 800;
+ }
+ .likesText {
+ font-size: 0.8em;
+ }
+ .likesNotes {
+ font-size: 0.8em;
+ &.err {
+ color: red;
+ }
+ }
+
+
+ .layout {
+ display: flex;
+ align-items: center;
+ .icon {
+ fill: transparent;
+ stroke: pink;
+ stroke-width: 20;
+ cursor: pointer;
+ position: relative;
+ svg {
+ overflow: visible;
+ width: 10rem;
+ }
+
+ path {
+ stroke-dashoffset: 0;
+ stroke-dasharray: 1550;
+ transform-origin: center;
+ }
+
+ .hear-main {
+ z-index: 2;
+ }
+ .heart-background {
+ position: absolute;
+ left: 0;
+ right: 0;
+ z-index: 1;
+ stroke: none;
+ }
+ .heart-main path.anim {
+ animation: stroke-animation 1.5s ease-in-out forwards;
+ }
+
+ .heart-main ~ .heart-background path.anim-click {
+ animation: fade-animation 0.35s ease-in-out forwards;
+ }
+ .nbLikes {
+ font-family: Source Sans Pro,Segoe UI,Trebuchet MS,Helvetica,Helvetica Neue,Arial,sans-serif;
+ text-align: center;
+ position: relative;
+ top: -10px;
+ height: 0;
+ }
+ }
+ }
+
+ @keyframes stroke-animation {
+ 0% {
+ fill: transparent;
+ transform: scale(1);
+ }
+ 30% {
+ fill: pink;
+ transform: scale(1.25);
+ }
+ 50% {
+ transform: scale(1);
+ }
+ 100% {
+ stroke-dashoffset: 0;
+ fill: pink;
+ }
+ }
+
+ @keyframes fade-animation {
+ 0% {
+ fill: transparent;
+ transform: scale(1);
+ }
+ 13% {
+ fill: lightpink;
+ transform: scale(1.2);
+ opacity: 1;
+ }
+ 66% {
+ opacity: 0.8;
+ }
+ 100% {
+ transform: scale(2);
+ opacity: 0;
+ }
+ }
+ }
}
+.alt-lang {
+ a {
+ padding-right: 20px;
+ }
+ font-size: 1.15rem;
+ text-transform: lowercase;
+ font-weight: bolder;
+ position: relative;
+ top: -3px;
+ font-family: Source Sans Pro,Segoe UI,Trebuchet MS,Helvetica,Helvetica Neue,Arial,sans-serif;
+}
+
+.tags {
+ display: flex;
+ gap: 10px;
+ flex-flow: row-reverse;
+ flex-wrap: wrap;
+ font-size: 1rem;
+ line-height: 1.65;
+
+ .tag {
+ padding: 0px 8px;
+ border-radius: 3px;
+
+ // Theme style
+
+ @mixin lightMode {
+ background-color: #DDD;
+ color: #333;
+ }
+ @mixin darkMode {
+ background-color: #444;
+ color: #eee;
+ }
+
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
+ &.light{ @include lightMode; }
+ &.dark { @include darkMode; }
+ }
+}
+
+/* Used only on tag's pages */
+.articleList {
+ list-style-type: none;
+ font-size: 1.2em;
+ text-indent: -65px;
+
+ font-family: palatino, Times, serif;
+
+ position: relative;
+ top: -3px;
+ left: -60px;
+
+ .pubYear {
+ color: #777;
+ margin: 0 10px;
+ }
+}
+
+
+/* Used only on tag's pages */
+.inline-tag {
+ position: relative;
+ top: -3px;
+ font-size: 0.7em;
+ background-color: #DDD;
+ padding: 3px 8px;
+ border-radius: 3px;
+ margin: 0 5px;
+
+ @mixin lightMode {
+ background-color: #DDD;
+ color: #333;
+ }
+ @mixin darkMode {
+ background-color: #444;
+ color: #eee;
+ }
+
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
+ &.light{ @include lightMode; }
+ &.dark { @include darkMode; }
+}
+
+
+video::cue {
+ background-position: top;
+ background-origin: border-box;
+ position: 90%;
+}
+
+video::cue(.back) {
+ font-style: oblique;
+ opacity: 0.85;
+ font-size: 0.7em;
+ line-height: 0.9;
+ padding-bottom: 5em;
+}
+
+hr {
+ margin: 2.5rem 0;
+}
+
diff --git a/src/css/_sommaire.scss b/src/css/_sommaire.scss
index c920bb3..0eadd0b 100755
--- a/src/css/_sommaire.scss
+++ b/src/css/_sommaire.scss
@@ -1,44 +1,92 @@
.sommaire_blien {
line-height: 1.45rem;
- color: #121311;
font-size: 0.8em;
font-weight: bold;
- font-family: monospace, serif;
- text-shadow: 0 1px 0 #DDD;
- color: #686868;
+
+ /* Theme style */
+ color: #121311;
+
&:before {
content: "/";
}
a {
- color: #686868;
outline: none;
text-decoration: none;
}
a:hover, a:focus {
+ /* Theme style */
color: #BBAABB;
}
}
#side-bar {
text-align: center;
+ font-family: ui-monospace, Menlo, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Cousine", Courier New, monospace, sans-serif;
ul {
columns: 2;
list-style-type: none;
padding-left: 0;
}
+ @mixin lightMode {
+ background: #F5F6F5;
+ color: inherit;
+
+ #logo-ache {
+ &:hover {
+ filter: drop-shadow(0px 0px 6px rgba(0, 0, 0, 0.4));
+ }
+ filter: none;
+ }
+ #ache a {
+ text-decoration: none;
+ color: inherit;
+ &:hover {
+ text-shadow: 0px 2px 8px rgba(0, 0, 0, 0.4);
+ text-decoration: underline royalblue 10%;
+ text-undefline-offset: 5px;
+ }
+ text-shadow: none;
+ }
+ #desc_intro {
+ text-shadow: 0 1px 0 #DDD;
+ }
+ .sommaire_blien {
+ text-shadow: 0 1px 0 #444;
+ color: #686868;
+ a {
+ color: #686868;
+ }
+ }
+ .about {
+ color: #666;
+ }
+ }
+
@mixin darkMode {
background: #101110;
color: #FFF;
+
#logo-ache {
+ &:hover {
+ filter: drop-shadow(0px 0px 6px rgba(0, 0, 0, 0.4)) invert(1);
+ }
filter: invert(1);
}
+ #ache a {
+ text-decoration: none;
+ color: inherit;
+ &:hover {
+ text-shadow: 0px 2px 8px rgba(255, 255, 255, 0.9);
+ text-decoration: underline goldenrod 10%;
+ text-underline-offset: 5px;
+ }
+ text-shadow: none;
+ }
#desc_intro {
text-shadow: 2px 4px 0 #333;
}
- .about_bar {
- }
.sommaire_blien {
text-shadow: 0 1px 0 #444;
color: #F5F5F5;
@@ -50,13 +98,13 @@
color: #BBB;
}
}
- @media (prefers-color-scheme: dark) { @include darkMode; } &.dark { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ &.light { @include lightMode; }
+ &.dark { @include darkMode; }
- h1 {
- font-family: monospace, "Helvetica Neue", Arial, sans-serif;
- }
svg {
margin: 0 auto;
display: block;
@@ -69,6 +117,7 @@
height: 100%;
transition: left 0.5s ease-in 0.25s;
+ /* Theme style */
border-right: 3px solid rgba(51, 51, 51, 0.1);
&.hidden {
@@ -80,6 +129,8 @@
#desc_intro {
padding-left: 10px;
padding-right: 10px;
+
+ /* Theme style */
text-shadow: 2px 4px 0 #DDD;
}
#desc {
@@ -88,12 +139,9 @@
padding-left: 15px;
padding-right: 15px;
font-size: 1.05em;
- font-family: monospace, "Helvetica Neue", Arial, sans-serif;
}
.about {
font-size: 0.8em;
- color: #666;
- font-family: monospace;
align-items: center;
justify-content: center;
}
@@ -115,12 +163,13 @@
display: inline-block;
width: 20%;
text-align: left;
- color: #121311;
font-size: 0.8em;
font-weight: bold;
- font-family: monospace, serif;
- text-shadow: 0 1px 0 #DDD;
margin: auto;
+
+ /* Theme style */
+ color: #121311;
+ text-shadow: 0 1px 0 #DDD;
}
#ontheweb {
visibility: hidden;
@@ -144,30 +193,3 @@
}
}
}
-
-.lab {
- height: 200px;
- width: 100%;
-
- @media #{$gt-gsm} {
- position: absolute;
- left: 0;
- bottom: 0px;
- }
- @media screen and (max-height: 749px) {
- visibility: hidden;
- }
-}
-.lab a svg {
- opacity: 0.45;
-}
-.lab a svg:hover {
- opacity: 1;
-}
-/*
-<nav>
-<div id="sommaire_blien">Accueil</div>
-<div id="sommaire_blien">Blog</div>
-<div id="sommaire_blien">Liens</div>
-</nav>
- */
diff --git a/src/css/_style.scss b/src/css/_style.scss
index ac47ea6..060fe8f 100644
--- a/src/css/_style.scss
+++ b/src/css/_style.scss
@@ -13,18 +13,19 @@
.qcm_item p {margin: 0; padding: 0; display: inline;}
.qcm_check, .qcm_radio {padding-left: 32px;}
-blockquote {
- color: #504d4d;
- padding: 1px 2%;
- border-left: 5px solid #ccc;
-}
+
+details {
+ color: #424242;
+}
.special-box {
- background: #eee7da;
margin: 12.5px 12.5px;
- padding: 10px 0 10px 95px;
- color: #424242;
+ padding: 10px 0 10px 95px;
min-height: 60px;
+
+ /* Theme style */
+ background: #eee7da;
+ color: #424242;
}
.special-box:before{
content: "";
@@ -35,28 +36,44 @@ blockquote {
margin: 0 0 -48px -70px;
}
@mixin box($name, $bg) {
+ /* Theme style */
.#{$name} {
background: $bg;
padding-right: 4%;
padding-top: 2%;
font-family: monospace, serif;
- font-size: 14px;
- &:before {
- background-image: url("/s/imgM/ic_" + $name + "_black_48px.svg");
- }
+ font-size: 1rem;
+
+ background-image: url("/s/imgM/ic_" + $name + "_black_48px.svg");
+ background-position: 25px center;
+ background-repeat: no-repeat;
}
}
+
@include box('information', #daeaee);
-@include box('comment', #eea);
+@include box('note', #bed2ff);
@include box('attention', #eee7da);
@include box('question', #e2daee);
@include box('good', #aea);
@include box('bad', #eaa);
+details {
+ background-color: lightyellow;
+ border-radius: 20px;
+ margin: 40px;
+ padding: 25px;
+
+ summary {
+ cursor: pointer;
+ }
+}
+
.secret {
- background: #eee;
padding: 10px 0 10px 15px;
min-height: 20px;
+
+ /* Theme style */
+ background: #eee;
}
.hiden_block_quote {
display: none;
@@ -65,12 +82,14 @@ blockquote {
margin-top: 5px;
}
kbd {
- background-color: #f8f6ea;
padding: 2px 6px;
border-radius: 3px;
- border: 1px solid #e0dab6;
border-bottom-width: 3px;
+
+ /* Theme style */
text-shadow: 0 1px 0 #fff;
+ background-color: #f8f6ea;
+ border: 1px solid #e0dab6;
color: #5e551f;
}
.view {
@@ -88,19 +107,22 @@ kbd {
font-family : inherit;
font-size : 1em;
cursor : pointer;
+
> div {
width : 40px;
height : 24px;
- background : #c0c0c0 url('image.png') no-repeat center center;
line-height : 24px;
- border : 1px solid rgba(27, 31, 35, 0.2);
border-radius : 3px;
font-size: 12px;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+ /* Theme style */
+ border : 1px solid rgba(27, 31, 35, 0.2);
+ background : #c0c0c0 url('image.png') no-repeat center center;
color: #24292e;
background-color: #eff3f6;
background-image: linear-gradient(to top, #fafbfc 0%, #eff3f6 90%);
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+
}
> div > div {
font-weight: bold;
@@ -111,12 +133,16 @@ kbd {
}
@mixin state($border, $border-c) {
- border: 2px solid $border;
border-radius: 2px;
outline: none;
border-color: $border-c;
+
+ /* Theme style */
box-shadow: 0 0 5px $border-c;
+ border: 2px solid $border;
}
+
+/* Theme style */
.valid {
@include state(#c0392b, #9F9);
}
diff --git a/src/css/design.scss b/src/css/design.scss
index a83ce34..d98db42 100755
--- a/src/css/design.scss
+++ b/src/css/design.scss
@@ -2,7 +2,7 @@ $gsm: "screen and (max-width: 768px)";
$gt-gsm: "screen and (min-width: 768px)";
$tab: "screen and (max-width: 1024px)";
$laptop: "screen and (min-width: 1024px)";
-$big-laptop: "screen and (min-width: 1400px)";
+$big-laptop: "screen and (min-width: 1520px)";
$big-screen: "screen and (min-width: 1720px)";
@import 'contenu';
@@ -12,31 +12,64 @@ $big-screen: "screen and (min-width: 1720px)";
html {
- background: #f1f1f1;
+ @mixin lightMode {
+ background: #f1f1f1;
+ }
@mixin darkMode {
background: #222;
}
- @media (prefers-color-scheme: dark) { @include darkMode; } &.dark { @include darkMode; }
-}
-/*
- Disabled because of firefx bugs : <https://bugzilla.mozilla.org/show_bug.cgi?id=1712656>
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
-@media (prefers-color-scheme: dark) {
- html{background:#282328;filter:invert(0.98);}
- img,svg,.cp_embed_wrapper,pre{filter:invert(0.8);}
- #logo-ache {filter:invert(0);}
+ &.light { @include lightMode; }
+ &.dark { @include darkMode; }
}
-*/
body {
margin: 0;
line-height: 1.35;
- color: #333333;
word-wrap: break-word;
font-size: 16px;
+ a {
+ text-decoration: underline;
+ text-decoration-thickness: 10%;
+ text-decoration-style: dotted;
+
+ @mixin lightMode {
+ &:hover, &:focus {
+ text-shadow: 0 0 2px #999;
+ text-decoration-color: royalblue;
+ }
+
+ color: #458;
+ &:visited {
+ color: #444;
+ }
+ }
+ @mixin darkMode {
+ &:hover, &:focus {
+ text-shadow: 0 0 2px #FFF;
+ text-decoration-color: goldenrod;
+ }
+
+
+ color: #B7B7A7;
+ &:visited {
+ color: #C7C7C7;
+ }
+ }
+
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
+
+ &.light { @include lightMode; }
+ &.dark { @include darkMode; }
+ }
+
--width_panel: 100%;
+ --width_panel_bis: 0px;
@media #{$gt-gsm} {
--width_panel: 290px;
--width_panel_bis: 290px;
@@ -44,14 +77,8 @@ body {
#side-bar {
box-sizing: border-box;
-
- @mixin lightMode {
- background: #F5F6F5;
- }
- @media (prefers-color-scheme: light) { @include lightMode; } &.dark { @include lightMode; }
padding-top: 10px;
-
text-rendering: optimizelegibility;
width: var(--width_panel);
left: calc(var(--width_panel_bis) - var(--width_panel);
@@ -63,13 +90,13 @@ body {
transition: margin-left 0.25s ease-out 0.25s;
}
}
-#harr {
- cursor: pointer;
-}
.hide_arrow {
@media (prefers-color-scheme: dark) { filter: invert(1); }
+ @media (prefers-color-scheme: light) { filter: invert(0); }
+ &.light{ filter: invert(0); }
&.dark { filter: invert(1); }
+ cursor: pointer;
position: fixed;
display: none;
top: 30%;
@@ -112,9 +139,9 @@ ache {
margin-left: auto;
margin-right: auto;
}
-img {
+img, video {
display: block;
- margin: 0 auto;
+ margin: 15px 15px;
max-width: 100%;
}
table {
@@ -124,22 +151,65 @@ table {
p {
display: inline;
}
- th {
- background-color: lightblue;
+
+ @mixin lightMode {
+ th {
+ background-color: lightblue;
+ }
+ tr:nth-child(even) {
+ background-color: #DEDEFF99;
+ }
+ }
+ @mixin darkMode {
+ th {
+ background-color: darkslategrey;
+ }
+
+ tr:nth-child(even) {
+ background-color: darkslateblue;
+ }
}
+
+
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
+
+ &.light { @include lightMode; }
+ &.dark { @include darkMode; }
+
+}
+p code {
+ display: inline-block;
+ white-space: nowrap;
+}
+code {
+ border: 0px;
+ border-radius: 8px;
+ padding: 0 5px;
+ font-weight: 500;
+ font-family: Consolas, Liberation Mono, Monaco, Lucida Console, monospace;
+
+ @mixin lightMode {
+ color: #c22222;
+ background: #FFF;
+ }
+ @mixin darkMode {
+ color: red;
+ background: black;
+ }
+
+ @media (prefers-color-scheme: dark) { @include darkMode; }
+ @media (prefers-color-scheme: light) { @include lightMode; }
+
+ &.light { @include lightMode; }
+ &.dark { @include darkMode; }
+
+
}
table, th, td {
- border: 1px solid #dfe2e5;
padding: 7px 13px;
-}
-.suite {
- color: #686868;
- outline: none;
- text-decoration: none;
- font-size: 0.6em;
- font-weight: bold;
- font-family: monospace, serif;
- text-shadow: 0 1px 0 #DDD;
+
+ border: 1px solid #dfe2e5;
}
.decal_panel {
@@ -149,4 +219,30 @@ table, th, td {
}
transition: margin-left 0.25s ease-out 0.25s, grid-template-columns 0.25s ease-out 0.25s;
}
-
+#hid {
+ .moon, .sun {
+ display: none;
+ }
+ &.dark {
+ .sun {
+ display: unset;
+ }
+ }
+ &.light {
+ .moon {
+ display: unset;
+ }
+ }
+ position: fixed;
+ top: 10px;
+ right: 10vw;
+ .sun, .moon {
+ position: sticky;
+ top: 400px;
+ cursor: pointer;
+ opacity: 0.5;
+ &:hover {
+ opacity: 1;
+ }
+ }
+}
diff --git a/src/img/computer.svg b/src/img/computer.svg
index 8ed3927..cbefd6c 100644
--- a/src/img/computer.svg
+++ b/src/img/computer.svg
@@ -3,7 +3,7 @@
id="svg2"
width="555"
height="435"
- viewBox="0 0 555 435">
+ viewBox="150 25 350 330">
<defs
id="defs6">
<clipPath
diff --git a/src/img/ic_note_black_48px.svg b/src/img/ic_note_black_48px.svg
new file mode 100644
index 0000000..a96b381
--- /dev/null
+++ b/src/img/ic_note_black_48px.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="48">
+ <path d="M5 2h16v20H3V2h2zm14 18V4H5v16h14zM7 6h10v2H7V6zm10 4H7v2h10v-2zM7 14h7v2H7v-2z" fill="currentColor"/>
+</svg>
diff --git a/src/img/image-formats.svg b/src/img/image-formats.svg
new file mode 100644
index 0000000..7248f25
--- /dev/null
+++ b/src/img/image-formats.svg
@@ -0,0 +1,118 @@
+<svg height="800" width="800" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ viewBox="0 0 512 512" xml:space="preserve">
+ <style>
+text {
+ font-family: monospace;
+ font-weight: 800;
+ font-size: 80px;
+}
+.webp2 {
+ animation: webp2 7.5s infinite;
+}
+.jxl {
+ animation: jxl 7.5s infinite;
+}
+.avif {
+ animation: avif 7.5s infinite;
+}
+@keyframes webp2 {
+ 0% {
+ fill: #FFF0;
+ stroke: #FFFF;
+ stroke-dashoffset: 25%; stroke-dasharray: 0 50%; stroke-width: 4;
+ }
+ 23.33% {fill: rgba(72,138,20,0); stroke: #FFFF; }
+ 26.666% {fill: rgba(72,138,20,0); stroke: #FFFF; stroke-width: 5; }
+ 33.33% {
+ fill: #FFFF; stroke: rgba(54,95,160,0);
+ stroke-dashoffset: -25%; stroke-dasharray: 50% 0; stroke-width: 5;
+ }
+ 35% {
+ fill: #FFF0; stroke: rgba(54,95,160,0);
+ stroke-dashoffset: -25%; stroke-dasharray: 50% 0; stroke-width: 0;
+ }
+ 100% {
+ fill: #FFF0; stroke: rgba(54,95,160,0);
+ stroke-dashoffset: -25%; stroke-dasharray: 50% 0; stroke-width: 0;
+ }
+}
+@keyframes avif {
+ 0% {
+ fill: #FFF0;
+ stroke: #FFFF;
+ stroke-dashoffset: 25%; stroke-dasharray: 0 50%; stroke-width: 0;
+ }
+ 33.33% {
+ fill: #FFF0;
+ stroke: #FFFF;
+ stroke-dashoffset: 25%; stroke-dasharray: 0 50%; stroke-width: 4;
+ }
+ 56.66% {fill: rgba(72,138,20,0); stroke: #FFFF; }
+ 54% {fill: rgba(72,138,20,0); stroke: #FFFF; stroke-width: 5; }
+ 66.66% {
+ fill: #FFFF; stroke: rgba(54,95,160,0);
+ stroke-dashoffset: -25%; stroke-dasharray: 50% 0; stroke-width: 5;
+ }
+ 68% {
+ fill: #FFF0; stroke: rgba(54,95,160,0);
+ stroke-dashoffset: -25%; stroke-dasharray: 50% 0; stroke-width: 0;
+ }
+ 100% {
+ fill: #FFF0; stroke: rgba(54,95,160,0);
+ stroke-dashoffset: -25%; stroke-dasharray: 50% 0; stroke-width: 0;
+ }
+}
+@keyframes jxl {
+ 0% {
+ fill: #FFF0;
+ stroke: #FFFF;
+ stroke-dashoffset: 25%; stroke-dasharray: 0 50%; stroke-width: 0;
+ }
+ 66.66% {
+ fill: #FFF0;
+ stroke: #FFFF;
+ stroke-dashoffset: 25%; stroke-dasharray: 0 50%; stroke-width: 4;
+ }
+ 81% {fill: rgba(72,138,20,0); stroke: #FFFF; }
+ 87% {fill: rgba(72,138,20,0); stroke: #FFFF; stroke-width: 5; }
+ 100% {
+ fill: #FFFF; stroke: rgba(54,95,160,0);
+ stroke-dashoffset: -25%; stroke-dasharray: 50% 0; stroke-width: 5;
+ }
+}
+ </style>
+<path style="fill:#ECEDEF;" d="M100.641,0c-14.139,0-25.6,11.461-25.6,25.6v460.8c0,14.139,11.461,25.6,25.6,25.6h375.467
+ c14.139,0,25.6-11.461,25.6-25.6V85.333L416.375,0H100.641z"/>
+<path style="fill:#D9DCDF;" d="M441.975,85.333h59.733L416.375,0v59.733C416.375,73.872,427.836,85.333,441.975,85.333z"/>
+<path style="fill:#C6CACF;" d="M399.308,42.667H75.041v153.6h324.267c4.713,0,8.533-3.821,8.533-8.533V51.2
+ C407.841,46.487,404.02,42.667,399.308,42.667z"/>
+<path style="fill:#FF8C78;" d="M382.241,179.2H18.843c-7.602,0-11.41-9.191-6.034-14.567L75.041,102.4L12.809,40.167
+ C7.433,34.791,11.241,25.6,18.843,25.6h363.398c4.713,0,8.533,3.821,8.533,8.533v136.533
+ C390.775,175.379,386.954,179.2,382.241,179.2z"/>
+<g>
+ <text x="22%" y="27%" class="webp2">WebP2</text>
+ <text x="23%" y="27%" class="avif">AVIF</text>
+ <text x="27%" y="27%" class="jxl">JXL</text>
+</g>
+<path style="fill:#3C9FE8;" d="M399.308,477.867H177.441c-9.426,0-17.067-7.641-17.067-17.067V238.933
+ c0-9.426,7.641-17.067,17.067-17.067h221.867c9.426,0,17.067,7.641,17.067,17.067V460.8
+ C416.375,470.226,408.734,477.867,399.308,477.867z"/>
+<path style="fill:#8AC451;" d="M160.375,460.8c0,9.426,7.641,17.067,17.067,17.067h221.867c9.426,0,17.067-7.641,17.067-17.067
+ v-25.6h-256L160.375,460.8L160.375,460.8z"/>
+<circle style="fill:#FFD791;" cx="279.84" cy="281.6" r="42.667"/>
+<circle style="fill:#FFC44F;" cx="279.84" cy="281.6" r="25.6"/>
+<g>
+ <path style="fill:#C5E8FA;" d="M211.575,256h-17.067c-4.713,0-8.533-3.821-8.533-8.533c0-4.713,3.821-8.533,8.533-8.533h17.067
+ c4.713,0,8.533,3.821,8.533,8.533C220.108,252.179,216.288,256,211.575,256z"/>
+ <path style="fill:#C5E8FA;" d="M365.175,290.133h-17.067c-4.713,0-8.533-3.821-8.533-8.533c0-4.713,3.821-8.533,8.533-8.533h17.067
+ c4.713,0,8.533,3.821,8.533,8.533C373.708,286.313,369.888,290.133,365.175,290.133z"/>
+ <path style="fill:#C5E8FA;" d="M382.241,315.733h-17.067c-4.713,0-8.533-3.821-8.533-8.533s3.821-8.533,8.533-8.533h17.067
+ c4.713,0,8.533,3.821,8.533,8.533S386.955,315.733,382.241,315.733z"/>
+</g>
+<polygon style="fill:#C4DF64;" points="160.375,358.4 220.108,290.133 322.508,409.6 365.175,358.4 416.375,418.133 416.375,435.2
+ 160.375,435.2 "/>
+<g>
+ <polygon style="fill:#ECEDEF;" points="365.175,358.4 329.619,401.067 401.746,401.067 "/>
+ <polygon style="fill:#ECEDEF;" points="220.108,290.133 167.841,349.867 271.308,349.867 "/>
+</g>
+</svg> \ No newline at end of file
diff --git a/src/img/lt.svg b/src/img/lt.svg
index bf84f40..682e527 100644
--- a/src/img/lt.svg
+++ b/src/img/lt.svg
@@ -7,17 +7,16 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- viewBox="0 -256 1792 1792"
+ viewBox="-100 10 800 1100"
version="1.1"
inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
- width="70px"
- height="70px"
+ width="20px"
aria-label="hidden">
<g id="glob">
<path
- fill="orange"
+ fill="royalblue"
opacity="0.4"
- stroke="orange"
+ stroke="royalblue"
stroke-width="5"
d="m 627,992 q 0,-13 -10,-23 L 224,576 617,183 q 10,-10 10,-23 0,-13 -10,-23 L 567,87 Q 557,77 544,77 531,77 521,87 L 55,553 q -10,10 -10,23 0,13 10,23 l 466,466 q 10,10 23,10 13,0 23,-10 l 50,-50 q 10,-10 10,-23 z"
id="lt"
diff --git a/src/img/masto.svg b/src/img/masto.svg
deleted file mode 100644
index 1e057ad..0000000
--- a/src/img/masto.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"><desc>Mastodon Logo</desc><g transform="scale(0.08)"> <path fill="#777" d="M211.80734 139.0875c-3.18125 16.36625-28.4925 34.2775-57.5625 37.74875-15.15875 1.80875-30.08375 3.47125-45.99875 2.74125-26.0275-1.1925-46.565-6.2125-46.565-6.2125 0 2.53375.15625 4.94625.46875 7.2025 3.38375 25.68625 25.47 27.225 46.39125 27.9425 21.11625.7225 39.91875-5.20625 39.91875-5.20625l.8675 19.09s-14.77 7.93125-41.08125 9.39c-14.50875.7975-32.52375-.365-53.50625-5.91875C9.23234 213.82 1.40609 165.31125.20859 116.09125c-.365-14.61375-.14-28.39375-.14-39.91875 0-50.33 32.97625-65.0825 32.97625-65.0825C49.67234 3.45375 78.20359.2425 107.86484 0h.72875c29.66125.2425 58.21125 3.45375 74.8375 11.09 0 0 32.975 14.7525 32.975 65.0825 0 0 .41375 37.13375-4.59875 62.915" /> <path fill="#fff" d="M177.50984 80.077v60.94125h-24.14375v-59.15c0-12.46875-5.24625-18.7975-15.74-18.7975-11.6025 0-17.4175 7.5075-17.4175 22.3525v32.37625H96.20734V85.42325c0-14.845-5.81625-22.3525-17.41875-22.3525-10.49375 0-15.74 6.32875-15.74 18.7975v59.15H38.90484V80.077c0-12.455 3.17125-22.3525 9.54125-29.675 6.56875-7.3225 15.17125-11.07625 25.85-11.07625 12.355 0 21.71125 4.74875 27.8975 14.2475l6.01375 10.08125 6.015-10.08125c6.185-9.49875 15.54125-14.2475 27.8975-14.2475 10.6775 0 19.28 3.75375 25.85 11.07625 6.36875 7.3225 9.54 17.22 9.54 29.675"/> </g> </svg>
diff --git a/src/img/mastodon.svg b/src/img/mastodon.svg
new file mode 100644
index 0000000..c4f910f
--- /dev/null
+++ b/src/img/mastodon.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg"
+aria-label="Mastodon" role="img"
+viewBox="80 85 350 340" width="20" height="20"
+fill="#fff"><linearGradient id="b" y2="1"><stop offset="0" stop-color="#6364ff"/><stop offset="1" stop-color="#563acc"/></linearGradient><path fill="url(#b)" d="M317 381q-124 28-123-39 69 15 149 2 67-13 72-80 3-101-3-116-19-49-72-58-98-10-162 0-56 10-75 58-12 31-3 147 3 32 9 53 13 46 70 69 83 23 138-9"/><path d="M360 293h-36v-93q-1-26-29-23-20 3-20 34v47h-36v-47q0-31-20-34-30-3-30 28v88h-36v-91q1-51 44-60 33-5 51 21l9 15 9-15q16-26 51-21 43 9 43 60"/></svg> \ No newline at end of file
diff --git a/src/img/moon.svg b/src/img/moon.svg
new file mode 100644
index 0000000..251b499
--- /dev/null
+++ b/src/img/moon.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg> \ No newline at end of file
diff --git a/src/img/sun.svg b/src/img/sun.svg
new file mode 100644
index 0000000..5d95560
--- /dev/null
+++ b/src/img/sun.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="#DDD" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg> \ No newline at end of file
diff --git a/src/js/love.js b/src/js/love.js
new file mode 100644
index 0000000..66f47d4
--- /dev/null
+++ b/src/js/love.js
@@ -0,0 +1,125 @@
+window.addEventListener('DOMContentLoaded', () => {
+ // This script insert a love button at the end of an article page
+
+ const articles = document.querySelectorAll('article');
+
+ function getCurrentPageLang() {
+ return document.documentElement.lang || "en";
+ }
+ function getLikeEndPoint() {
+ let currentArticleName = window.location.pathname.split('/')[2];
+ if (currentArticleName.indexOf('.') > 0) {
+ currentArticleName = currentArticleName.slice(0, currentArticleName.lastIndexOf('.'))
+ }
+
+ return `${window.location.origin}/like/${currentArticleName}`;
+ }
+
+ const isAnArticle = articles.length === 1; // The front page have multiple articles.
+
+ if (isAnArticle) {
+ const article = articles[0];
+ const likes = article.querySelector('.likes');
+ const nbLikes = article.querySelector('.nbLikes');
+ const footnotes = article.querySelector('.footnotes');
+
+ likes.style="display: 'block';";
+ const updateNbLikes = () => {
+ fetch(getLikeEndPoint(), {
+ method: 'GET',
+ headers: {
+ 'i-love-what-you-do': '<3',
+ },
+ }).then((res) => {
+ if (res.ok) {
+ res.text().then((text) => nbLikes.textContent = text);
+ } else {
+ nbLikes.textContent = "";
+ }
+ });
+ };
+
+ updateNbLikes();
+
+ if (footnotes) {
+ // We want: article.insertBefore(likes, footnotes);
+ footnotes.before(likes);
+ }
+
+ const icon = likes.querySelector('.icon');
+ const messagesLike = likes.querySelector('.likesNotes');
+
+ icon.addEventListener('mouseover', () => {
+ for (const c of icon.children) {
+ const path = c.querySelector('path');
+ path?.classList.add('anim');
+ }
+ });
+
+ icon.addEventListener('mouseout', () => {
+ for (const c of icon.children) {
+ const path = c.querySelector('path');
+ path?.classList.remove('anim');
+ }
+ });
+
+ icon.addEventListener('click', () => {
+ const c = icon.children[1];
+ const lang = getCurrentPageLang();
+
+ const path = c.querySelector('path');
+
+ path.classList.add('anim-click');
+ path.getAnimations().forEach(anim => {
+ anim.cancel();
+ anim.play();
+ });
+
+ fetch(getLikeEndPoint(), {
+ method: 'POST',
+ headers: {
+ 'i-love-what-you-do': '<3',
+ 'lang': lang,
+ },
+ }).then(response => {
+ const t = response.text();
+
+ if (response.ok) {
+ messagesLike.classList.remove('err');
+ t.then(t => messagesLike.textContent = t);
+ updateNbLikes();
+ } else {
+ t.then(t => {
+ // In case of error, we want to be able to set the initial message back
+ const previousText = messagesLike.textContent;
+ const timeoutErr = 3000;
+ const wasAnError = messagesLike.classList.contains('err');
+
+ // Set the error
+ messagesLike.classList.add('err');
+ if (Math.floor(response.status / 100) == 4) {
+ messagesLike.textContent = t;
+ } else {
+ messagesLike.textContent = lang == 'fr' ? 'Désolé, le service est indisponible.' : 'Sorry, service unavailable.';
+ }
+
+ // Set the initial message back
+ if(!wasAnError) {
+ setTimeout(() => {
+ if(messagesLike.classList.contains('err')) {
+ messagesLike.classList.remove('err');
+ messagesLike.textContent = previousText;
+ }
+ }, timeoutErr);
+ }
+ });
+ }
+ }).catch(() => {
+ // In case of exception error. We don't want to set back the initial message.
+ messagesLike.classList.add('err');
+ messagesLike.textContent = lang == 'fr' ? 'Désolé, le service est indisponible.' : 'Sorry, service unavailable.';
+ messageText = '';
+ });
+ });
+ }
+});
diff --git a/src/js/sidenotes.js b/src/js/sidenotes.js
index 8ab99f9..851e11b 100644
--- a/src/js/sidenotes.js
+++ b/src/js/sidenotes.js
@@ -28,7 +28,7 @@ const resize = () => {
const newSidenotes = notes.map(sidenoteLi => {
const div = document.createElement('div');
const refName = sidenoteLi.querySelector('.data-footnote-backref').attributes.href.value;
- const refSideNode = article.querySelector(refName);
+ const refSideNode = article.querySelector(`#${CSS.escape(refName.slice(1))}`);
const sup = document.createElement('sup');
sup.textContent = refSideNode.textContent + ' ';
diff --git a/src/js/theme.js b/src/js/theme.js
new file mode 100644
index 0000000..8239c69
--- /dev/null
+++ b/src/js/theme.js
@@ -0,0 +1,126 @@
+window.addEventListener('DOMContentLoaded', () => {
+ const storageTheme = window.localStorage?.getItem('theme');
+ const preferesDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
+
+ let isDark = preferesDark;
+
+ const hid = document.querySelector('#hid');
+ const html = document.querySelector('html');
+ const aside = document.querySelector('#side-bar');
+ const sidenotes = document.querySelector('.sidenotes');
+ const footnotes = document.querySelector('.footnotes');
+ const harr = document.querySelector('#harr');
+ const links = document.querySelectorAll('a');
+ const likes = document.querySelectorAll('.likes');
+ const tables = document.querySelectorAll('table');
+ const codes = document.querySelectorAll('p code');
+
+ if (storageTheme === 'dark' || storageTheme === 'light') {
+ const theme = storageTheme;
+ isDark = storageTheme === 'dark';
+ hid.classList.add(theme);
+ html.classList.add(theme);
+ aside.classList.add(theme);
+ sidenotes.classList.add(theme);
+ harr.classList.add(theme);
+
+ if(footnotes) {
+ footnotes.classList.add(theme);
+ }
+
+ for (let link of links) {
+ link.classList.add(theme);
+ }
+ for (let likeBox of likes) {
+ likeBox.classList.add(theme);
+ }
+ for (let table of tables) {
+ table.classList.add(theme);
+ }
+ for (let code of codes) {
+ code.classList.add(theme);
+ }
+
+ for (const article of document.querySelectorAll('article')) {
+ article.classList.add(theme);
+ }
+
+ for (const article of document.querySelectorAll('article')) {
+ article.classList.add(theme);
+ }
+ }
+
+ function toogleTheme() {
+ const arg = isDark ? ['dark', 'light'] : ['light', 'dark'];
+ const theme = arg[1];
+
+ if (!hid.classList.replace(...arg)) {
+ hid.classList.add(theme);
+ }
+
+ if (!html.classList.replace(...arg)) {
+ html.classList.add(theme);
+ }
+
+ if (!aside.classList.replace(...arg)) {
+ aside.classList.add(theme);
+ }
+
+ if (!sidenotes.classList.replace(...arg)) {
+ sidenotes.classList.add(theme);
+ }
+ if (footnotes && !footnotes.classList.replace(...arg)) {
+ footnotes.classList.add(theme);
+ }
+
+
+
+ if (!harr.classList.replace(...arg)) {
+ harr.classList.add(theme);
+ }
+
+ for (let link of links) {
+ if (!link.classList.replace(...arg)) {
+ link.classList.add(theme);
+ }
+ }
+ for (let table of tables) {
+ if (!table.classList.replace(...arg)) {
+ table.classList.add(theme);
+ }
+ }
+ for (let code of codes) {
+ if (!code.classList.replace(...arg)) {
+ code.classList.add(theme);
+ }
+ }
+ for (let like of likes) {
+ if (!like.classList.replace(...arg)) {
+ like.classList.add(theme);
+ }
+ }
+
+ for (const article of document.querySelectorAll('article')) {
+ if (!article.classList.replace(...arg)) {
+ article.classList.add(theme);
+ }
+ }
+
+ isDark = !isDark;
+ if (window.localStorage) {
+ window.localStorage.setItem('theme', isDark ? 'dark' : 'light');
+ }
+ }
+
+ const sun = document.querySelector('.sun');
+ const moon = document.querySelector('.moon');
+
+ sun.addEventListener('click', toogleTheme);
+ moon.addEventListener('click', toogleTheme);
+
+ if (isDark) {
+ hid.classList.add('dark');
+ } else {
+ hid.classList.add('light');
+ }
+});
diff --git a/src/js/zen.js b/src/js/zen.js
index d897603..be5f7d7 100644
--- a/src/js/zen.js
+++ b/src/js/zen.js
@@ -1,17 +1,25 @@
window.addEventListener('DOMContentLoaded', () => {
let firstTime = window.location.pathname != '/' && window.pageYOffset < 800;
const toggleArrow = document.querySelector('#harr');
+ const hid = document.querySelector('#hid');
const initValue = document.body.style.getPropertyValue('--width_panel_bis');
toggleArrow.addEventListener('click', () => {
if (toggleArrow.classList.contains('hide_arrow_off')) {
+ firstTime = false;
showAbout();
+ showHID();
setTimeout(() => {
toggleArrow.classList.remove('hide_arrow_off');
}, 1000);
} else {
toggleArrow.classList.add('hide_arrow_off');
hideAbout();
+
+ // If the screen is smaller than 500px, hide the HID
+ if (window.screen.availWidth <= 500) {
+ hideHID();
+ }
}
});
@@ -23,20 +31,32 @@ window.addEventListener('DOMContentLoaded', () => {
document.body.style.setProperty('--width_panel_bis', initValue);
}
+ function hideHID() {
+ hid.style.setProperty('display', 'none');
+ }
+
+ function showHID() {
+ hid.style.setProperty('display', '');
+ }
+
window.addEventListener('scroll', () => {
+ if(!toggleArrow) return;
if (window.pageYOffset >= 800) {
- if (toggleArrow) {
- if (firstTime) {
- toggleArrow.click();
- firstTime = false;
- } else {
- toggleArrow.classList.add('hide_arrow_show');
- }
+ if (firstTime && document.body.style.getPropertyValue('--width_panel_bis') === initValue) {
+ toggleArrow.click();
+ firstTime = true;
}
+
+ toggleArrow.classList.add('hide_arrow_show');
// A hideAbout(header, articles);
- } else if (toggleArrow && !toggleArrow.classList.contains('hide_arrow_off')) {
+ } else if (!toggleArrow.classList.contains('hide_arrow_off')) {
// A showAbout(header, articles);
toggleArrow.classList.remove('hide_arrow_show');
}
+
+ if(firstTime && window.pageYOffset === 0 && document.body.style.getPropertyValue('--width_panel_bis') !== initValue) {
+ toggleArrow.click();
+ firstTime = true;
+ }
});
});
diff --git a/src/templates/article.tmpl b/src/templates/article.tmpl
index d67f34a..cd87f39 100644
--- a/src/templates/article.tmpl
+++ b/src/templates/article.tmpl
@@ -1,14 +1,18 @@
<!DOCTYPE html>
-<html lang="fr">
+<html lang="{{lang}}">
{{> header }}
<body>
<div class="decal_panel">
<div class="marge"></div>
<article class="post" id="{{domTitle}}_article">
+ <div class="tags">{{# metaData.tags }}<a href="/{{ lang }}/tag/{{{ . }}}" class="tag">{{{ . }}}</a>{{/ metaData.tags }}</div>
+ <div class="pubdate">{{ metaData.pubDateISO }}</div>
{{{ content }}}
+ {{> likesButton }}
</article>
<div class="sidenotes"></div>
</div>
- {{> leftPanel }}
+ {{>leftPanel }}
+ {{>hid }}
</body>
</html>
diff --git a/src/templates/header.tmpl b/src/templates/header.tmpl
index 433b130..e92da4a 100644
--- a/src/templates/header.tmpl
+++ b/src/templates/header.tmpl
@@ -1,6 +1,6 @@
<head>
<meta charset="utf-8" />
- <title>{{ title }}</title>
+ <title>{{ page_title }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="canonical" href="{{{ canonical }}}"/>
<link href="/s/css/style.css" rel="stylesheet"/>
@@ -8,6 +8,6 @@
<link href="/s/css/katex.css" rel="stylesheet"/>
</noscript>
<script src="/s/js/main.js" defer></script>
- <meta name= "description" content="ache: {{ description }} " />
+ <meta name= "description" content="{{ description }} " />
<link rel="alternate" type="application/rss+xml" href="/rss.xml">
</head>
diff --git a/src/templates/hid.tmpl b/src/templates/hid.tmpl
new file mode 100644
index 0000000..7f0ab78
--- /dev/null
+++ b/src/templates/hid.tmpl
@@ -0,0 +1 @@
+<div id="hid">{{# alt_lang }}<span role=button tabindex=0 class="alt-lang" aria-label="{{ description }}" title="{{ description }}"><a href="{{ url }}">{{ lang }}</a></span>{{/ alt_lang }}<div role=button tabindex=0 class=sun aria-label="light mode">{{{svg.sun}}}</div><div role=button tabindex=0 class=moon aria-label="dark mode">{{{svg.moon}}}</div></div>
diff --git a/src/templates/index.tmpl b/src/templates/index.tmpl
index db117c9..5ed2ed4 100644
--- a/src/templates/index.tmpl
+++ b/src/templates/index.tmpl
@@ -1,6 +1,5 @@
-
<!DOCTYPE html>
-<html lang="fr">
+<html lang="{{lang}}">
{{>header }}
<body>
{{#articles}}
@@ -13,5 +12,6 @@
</div>
{{/articles}}
{{> leftPanel }}
+ {{>hid }}
</body>
</html>
diff --git a/src/templates/left.tmpl b/src/templates/left.tmpl
index 985f356..c82c692 100644
--- a/src/templates/left.tmpl
+++ b/src/templates/left.tmpl
@@ -1,26 +1,28 @@
-<nav tabindex="0" id="harr" class="hide_arrow" role="button">
- {{{ svg.lt }}}
+<nav tabindex="0" id="harr" class="hide_arrow" role="button" aria-labe="switch on/off panel">
+ {{{ svg.lt }}}
</nav>
<aside id="side-bar">
+ <a href="/{{ lang }}/" class="button">
{{{ svg.ache }}}
- <h2> Ache </h2>
- <div id="desc"><div id="desc_intro">Éternel étudiant en Math-Info.<br><span class="about">Autodidacte passionné,<br><div class="type_wrap"><span class="type">désormais ingénieur.</span></div></span></div><br> <span class="about">GNU\Linux, C, C++, Python, Math, autohébergement, décentralisation, P2P, commun, ... <br> </span><br></div>
+ </a>
+ <h2 id="ache"><a href="/{{ lang}}/">Ache</a></h2>
+ <div id="desc"><div id="desc_intro">{{{ intro.description }}}<br><span class="about">{{{ intro.about }}}</span></div><br><span class="about">{{{ intro.about_tags }}}</span><br></div>
<nav>
<ul>
- <li class="sommaire_blien"><a href="/" title="L'accueil">home</a>
- </li><li class="sommaire_blien"><a href="http://git.ache.one/" title="Dépôt git personnel">git</a>
- </li>
+ <li class="sommaire_blien"><a href="/{{ lang }}" title="{{ title.home }}">home</a>
+ </li><li class="sommaire_blien"><a href="http://git.ache.one/" title="{{ title.git }}">git</a>
+ </li>
</ul>
</nav>
<nav id="ontheweb">
<ul>
- <li class="about_bar"><a href="https://twitter.com/arobase_che" title="Mon twitter abandonné">
- {{{ svg.twitter }}}
+ <li class="about_bar"><a rel="me" href="https://mastodon.xyz/@ache" title="{{ title.mosto }}">
+ {{{ svg.mastodon }}}
</a></li>
- <li class="about_bar"><a href="http://git.ache.one" title="Dépôt git personnel">
+ <li class="about_bar"><a href="https://git.ache.one" title="{{ title.git }}">
{{{ svg.git }}}
</a></li>
- <li class="about_bar"><a href="/rss.xml" title="Flux RSS">
+ <li class="about_bar"><a href="/{{ lang }}/rss.xml" title="Flux RSS">
{{{ svg.rss }}}
</a></li>
</ul>
diff --git a/src/templates/likes.tmpl b/src/templates/likes.tmpl
new file mode 100644
index 0000000..c81d936
--- /dev/null
+++ b/src/templates/likes.tmpl
@@ -0,0 +1,19 @@
+<section class="likes" style="display: none">
+ <span class="likesBox">
+ <div class="layout">
+ <div class="icon">
+ <svg class="heart-main" viewBox="0 0 512 512" title="heart" z-index="1" height="100">
+ <path d="M462.3 62.6C407.5 15.9 326 24.3 275.7 76.2L256 96.5l-19.7-20.3C186.1 24.3 104.5 15.9 49.7 62.6c-62.8 53.6-66.1 149.8-9.9 207.9l193.5 199.8c12.5 12.9 32.8 12.9 45.3 0l193.5-199.8c56.3-58.1 53-154.3-9.8-207.9z" class=""></path>
+ </svg>
+ <svg class="heart-background" viewBox="0 0 512 512" title="heart" z-index="1" height="100">
+ <path d="M462.3 62.6C407.5 15.9 326 24.3 275.7 76.2L256 96.5l-19.7-20.3C186.1 24.3 104.5 15.9 49.7 62.6c-62.8 53.6-66.1 149.8-9.9 207.9l193.5 199.8c12.5 12.9 32.8 12.9 45.3 0l193.5-199.8c56.3-58.1 53-154.3-9.8-207.9z" class=""></path>
+ </svg>
+ <div class="nbLikes"><div></div></div>
+ </div>
+ </div>
+ <div>
+ <span class="likesTitle">{{ like_title }}</span>
+ <p class="likesText">{{{ like_text }}}</p>
+ </div></span>
+
+ </section>
diff --git a/src/templates/tag.tmpl b/src/templates/tag.tmpl
new file mode 100644
index 0000000..f73365d
--- /dev/null
+++ b/src/templates/tag.tmpl
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="{{lang}}">
+ {{>header }}
+ <body>
+ <div class="decal_panel">
+ <div class="marge"></div>
+ <article class="post" id="{{domTitle}}_article">
+ <h1><a class="anchor" href="{{ canonical }}">Tag: {{ tag }}</a></h1>
+ <br>
+ <ul class="articleList">
+ {{# articles}}
+ <li><a href="{{ url }}"><span class="pubYear">{{ pubYear }}</span>{{ title }}</a>  
+ {{# metaData.tags }}
+ <a href="/{{ lang }}/tag/{{{ . }}}" class="inline-tag">{{{ . }}}</a>
+ {{/ metaData.tags }}
+ </li>
+ {{/ articles}}
+ </ul>
+ </article>
+ <div class="sidenotes"></div>
+ </div>
+ {{> leftPanel }}
+ <div id="hid"><div class="sun">{{{svg.sun}}}</div><div class="moon">{{{svg.moon}}}</div></div>
+ </body>
+</html>