Imported from https://github.com/nmasse-itix/hugo-theme-itix (main, 7d4207e).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YNHsWYTXPThURz6TbVS1j3
master
@ -0,0 +1,21 @@ |
|||||
|
MIT License |
||||
|
|
||||
|
Copyright (c) 2020 Nicolas Massé |
||||
|
|
||||
|
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. |
||||
@ -0,0 +1 @@ |
|||||
|
# Theme for www.itix.fr |
||||
@ -0,0 +1 @@ |
|||||
|
chroma.css |
||||
@ -0,0 +1,859 @@ |
|||||
|
:root { |
||||
|
/* |
||||
|
* Theme colors |
||||
|
*/ |
||||
|
--main-color: #1870c9; /* Adjusted to ensure a 4.5:1 contrast ratio for accessibility */ |
||||
|
--main-background-color: #fcfcfc; |
||||
|
--alternate-text-color: #145ca4; |
||||
|
--main-text-color: #092949; /* 50% darker than main-color */ |
||||
|
--active-menu-background-color: #f4f8fb; |
||||
|
--active-menu-color: #0e4377; |
||||
|
--active-menu-border-color: #74abe3; |
||||
|
--hover-menu-background-color: #f4f8fb; |
||||
|
--hover-menu-color: #0e4377; |
||||
|
--hover-menu-border-color: #74abe3; |
||||
|
--post-metadata-color: #555; |
||||
|
--text-selection-background-color: #a2c7ec; |
||||
|
--quote-background-color: #f0f5fa; |
||||
|
--quote-border-color: #589bdd; |
||||
|
--codeblock-background-color: #ebf2f9; |
||||
|
--toc-background-color: #f0f5fa; |
||||
|
--pagination-disabled-color: #555; |
||||
|
--table-border-color: #092949; |
||||
|
|
||||
|
/* |
||||
|
* Layout |
||||
|
*/ |
||||
|
--menu-container-width: 25%; |
||||
|
--toolbar-container-width: 25%; |
||||
|
|
||||
|
/* |
||||
|
* Fonts |
||||
|
*/ |
||||
|
--default-font-list: "Source Serif Pro", serif; |
||||
|
--mono-font-list: "JetBrains Mono", monospace; |
||||
|
--sans-preferred-font-list: "Source Sans Pro", sans-serif; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Fonts |
||||
|
*/ |
||||
|
@font-face{ |
||||
|
font-family: 'JetBrains Mono'; |
||||
|
src: url('/fonts/JetBrainsMono-Regular.woff2') format('woff2'), |
||||
|
url('/fonts/JetBrainsMono-Regular.woff') format('woff'), |
||||
|
url('/fonts/JetBrainsMono-Regular.ttf') format('truetype'); |
||||
|
font-weight: 400; |
||||
|
font-style: normal; |
||||
|
|
||||
|
/* |
||||
|
* Core Web Vitals / Cumulative Layout Shift. |
||||
|
* |
||||
|
* Avoid showing invisible text while custom fonts load. |
||||
|
*/ |
||||
|
font-display: swap; |
||||
|
} |
||||
|
|
||||
|
@font-face{ |
||||
|
font-family: 'Source Serif Pro'; |
||||
|
src: url('/fonts/SourceSerifPro-Regular.ttf') format('truetype'); |
||||
|
font-weight: 400; |
||||
|
font-style: normal; |
||||
|
|
||||
|
/* |
||||
|
* Core Web Vitals / Cumulative Layout Shift. |
||||
|
* |
||||
|
* Avoid showing invisible text while custom fonts load. |
||||
|
*/ |
||||
|
font-display: swap; |
||||
|
} |
||||
|
|
||||
|
@font-face{ |
||||
|
font-family: 'Source Sans Pro'; |
||||
|
src: url('/fonts/SourceSansPro-Regular.ttf') format('truetype'); |
||||
|
font-weight: 400; |
||||
|
font-style: normal; |
||||
|
|
||||
|
/* |
||||
|
* Core Web Vitals / Cumulative Layout Shift. |
||||
|
* |
||||
|
* Avoid showing invisible text while custom fonts load. |
||||
|
*/ |
||||
|
font-display: swap; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* General settings |
||||
|
*/ |
||||
|
|
||||
|
::selection { |
||||
|
/* Text selection uses the theme main color with some transparency */ |
||||
|
background: var(--text-selection-background-color); |
||||
|
} |
||||
|
|
||||
|
body { |
||||
|
background: var(--main-background-color); |
||||
|
padding: 0; |
||||
|
margin: 0; |
||||
|
font-family: var(--default-font-list); |
||||
|
color: var(--main-text-color); |
||||
|
} |
||||
|
|
||||
|
* { |
||||
|
/* By default in the CSS box model, the width and height you assign to an |
||||
|
* element is applied only to the element's content box. If the element has |
||||
|
* any border or padding, this is then added to the width and height to arrive |
||||
|
* at the size of the box that's rendered on the screen. This means that when |
||||
|
* you set width and height, you have to adjust the value you give to allow |
||||
|
* for any border or padding that may be added. |
||||
|
* |
||||
|
* border-box tells the browser to account for any border and padding in the |
||||
|
* values you specify for an element's width and height. If you set an element's |
||||
|
* width to 100 pixels, that 100 pixels will include any border or padding you |
||||
|
* added, and the content box will shrink to absorb that extra width. |
||||
|
* This typically makes it much easier to size elements. |
||||
|
*/ |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Heading and figure numbering |
||||
|
*/ |
||||
|
|
||||
|
main, #TableOfContents { |
||||
|
/* |
||||
|
* all counters need to be specified on one single line |
||||
|
* and they have to be reset on an enclosing element |
||||
|
*/ |
||||
|
counter-reset: h2 figcaption; |
||||
|
} |
||||
|
|
||||
|
h2::before, #TableOfContents > ul > li::before { |
||||
|
content: counter(h2) ".\0000a0\0000a0"; /* \0000a0 => Non-breakable space */ |
||||
|
counter-increment: h2; |
||||
|
} |
||||
|
|
||||
|
h2, #TableOfContents > ul > li { |
||||
|
counter-reset: h3; |
||||
|
} |
||||
|
|
||||
|
h3::before, #TableOfContents > ul > li > ul > li::before { |
||||
|
content: counter(h2) "." counter(h3) ".\0000a0\0000a0"; |
||||
|
counter-increment: h3; |
||||
|
} |
||||
|
|
||||
|
figcaption::before { |
||||
|
/* |
||||
|
* When the numbering is done in CSS, we cannot honor typographical |
||||
|
* conventions of the user language. So, here I chose the english convention |
||||
|
* with no space before the colon and a space after. |
||||
|
*/ |
||||
|
content: "Figure " counter(figcaption) ": "; |
||||
|
counter-increment: figcaption; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Main content formatting |
||||
|
*/ |
||||
|
|
||||
|
h1, h2, h3 { |
||||
|
font-weight: bold; |
||||
|
line-height: 1.5em; |
||||
|
} |
||||
|
|
||||
|
h1, h2, h3, h4, h5, h6 { |
||||
|
margin: 20px 0 20px 0; |
||||
|
} |
||||
|
|
||||
|
h1 { |
||||
|
font-size: 30px; |
||||
|
} |
||||
|
|
||||
|
h2 { |
||||
|
font-size: 24px; |
||||
|
} |
||||
|
|
||||
|
h3 { |
||||
|
font-size: 21px; |
||||
|
} |
||||
|
|
||||
|
h4 { |
||||
|
font-size: 21px; |
||||
|
} |
||||
|
|
||||
|
h5 { |
||||
|
font-size: 20px; |
||||
|
} |
||||
|
|
||||
|
h6 { |
||||
|
font-size: 19px; |
||||
|
} |
||||
|
|
||||
|
figure { |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
figure figcaption { |
||||
|
font-style: italic; |
||||
|
} |
||||
|
|
||||
|
ul { |
||||
|
list-style-type: "\2013\0000a0"; |
||||
|
list-style-position: outside; |
||||
|
} |
||||
|
|
||||
|
textarea, |
||||
|
select, |
||||
|
input, |
||||
|
button { |
||||
|
outline: none !important; |
||||
|
} |
||||
|
|
||||
|
main table { |
||||
|
table-layout: fixed; |
||||
|
overflow-x: scroll; |
||||
|
border-collapse: collapse; |
||||
|
width: 100%; |
||||
|
table-layout: auto; |
||||
|
} |
||||
|
|
||||
|
main table td, main table th { |
||||
|
border: 1px solid var(--table-border-color); |
||||
|
padding: 0.2rem 0.5rem; |
||||
|
} |
||||
|
|
||||
|
button { |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
blockquote { |
||||
|
padding: 10px 20px; |
||||
|
border-left: 3px solid var(--quote-border-color); |
||||
|
color: var(--alternate-text-color); |
||||
|
background: var(--quote-background-color); |
||||
|
} |
||||
|
|
||||
|
blockquote p { |
||||
|
margin-bottom: 0; |
||||
|
} |
||||
|
|
||||
|
blockquote * { |
||||
|
color: var(--alternate-text-color); |
||||
|
} |
||||
|
|
||||
|
a { |
||||
|
color: var(--main-color); |
||||
|
} |
||||
|
|
||||
|
a:hover { |
||||
|
color: var(--alternate-text-color); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Code block |
||||
|
*/ |
||||
|
|
||||
|
pre.chroma { |
||||
|
/* Overide the default chroma background color with ours */ |
||||
|
background: var(--codeblock-background-color); |
||||
|
} |
||||
|
|
||||
|
/* Code block (three backticks in markdown) */ |
||||
|
pre { |
||||
|
background: var(--codeblock-background-color); |
||||
|
padding: 12px 15px; |
||||
|
border-radius: 5px; |
||||
|
font-family: var(--mono-font-list); |
||||
|
|
||||
|
/* Do not wrap lines of code */ |
||||
|
overflow-x: hidden; |
||||
|
|
||||
|
/* Hide scrollbar for IE, Edge and Firefox */ |
||||
|
-ms-overflow-style: none; /* IE and Edge */ |
||||
|
scrollbar-width: none; /* Firefox */ |
||||
|
} |
||||
|
|
||||
|
/* Hide scrollbar for Chrome, Safari and Opera */ |
||||
|
pre::-webkit-scrollbar { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
/* Inline code (single backticks in markdown) */ |
||||
|
code { |
||||
|
color: var(--alternate-text-color); |
||||
|
background: var(--codeblock-background-color) !important; |
||||
|
padding: 2px 5px; |
||||
|
border-radius: 3px; |
||||
|
font-family: var(--mono-font-list); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* And because there is a code tag inside a pre tag for Markdown code blocks, |
||||
|
* we need to overide some properties |
||||
|
*/ |
||||
|
pre code { |
||||
|
background: none !important; |
||||
|
font-family: var(--mono-font-list) !important; |
||||
|
padding: 0; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Highlighted file has a wrapping div. Some properties are redefined for it |
||||
|
* and reset to their default value for its children. |
||||
|
*/ |
||||
|
.highlightedFile { |
||||
|
background: var(--codeblock-background-color); |
||||
|
border-radius: 5px; |
||||
|
} |
||||
|
|
||||
|
.highlightedFile .filename { |
||||
|
border-bottom: 2px solid var(--hover-menu-border-color); |
||||
|
font-family: var(--sans-preferred-font-list) !important; |
||||
|
font-size: larger; |
||||
|
padding: 12px 15px; |
||||
|
} |
||||
|
|
||||
|
.highlightedFile pre { |
||||
|
background: inherit; |
||||
|
border-radius: inherit; |
||||
|
padding: 12px 15px; |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
pre:hover { |
||||
|
/* Show the horizontal scroll bar when hovering code (if needed) */ |
||||
|
overflow-x: auto; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* i18n |
||||
|
*/ |
||||
|
.tiny-flag { |
||||
|
vertical-align: middle; |
||||
|
margin-left: 5px; |
||||
|
margin-right: 5px; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Pagination |
||||
|
*/ |
||||
|
.pagination { |
||||
|
list-style: none; |
||||
|
padding: 0; |
||||
|
text-align: center; |
||||
|
font-size: larger; |
||||
|
} |
||||
|
|
||||
|
.pagination .page-item { |
||||
|
display: inline; |
||||
|
margin: 5px; |
||||
|
} |
||||
|
|
||||
|
.pagination .disabled { |
||||
|
color: var(--pagination-disabled-color); |
||||
|
} |
||||
|
|
||||
|
.pagination .active { |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Article list |
||||
|
*/ |
||||
|
|
||||
|
.article-list p { |
||||
|
/* Move the excerpt closer to the metadata */ |
||||
|
margin-top: 0.5em; |
||||
|
/* Add spacing around each item of the list */ |
||||
|
margin-bottom: 2.5em; |
||||
|
} |
||||
|
|
||||
|
.article-list h4 { |
||||
|
/* Move the title closer to the metadata */ |
||||
|
margin-bottom: 0.5em; |
||||
|
} |
||||
|
|
||||
|
.article-list .post-metadata { |
||||
|
/* Fade the metadata */ |
||||
|
color: var(--post-metadata-color); |
||||
|
} |
||||
|
|
||||
|
.article-list .continue-reading { |
||||
|
/* Leave some space between the excerpt and the "continue reading" link */ |
||||
|
margin-left: 0.5em; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Post Metadata (valid for the "list" and "single" views) |
||||
|
*/ |
||||
|
.post-metadata .material-icons { |
||||
|
vertical-align: sub; |
||||
|
margin-right: 3px; |
||||
|
margin-left: 5px; |
||||
|
max-height: 1rem; |
||||
|
} |
||||
|
|
||||
|
.post-metadata time { |
||||
|
/* Leave some space between publication date and taxonomies */ |
||||
|
margin-right: 20px; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
article .post-metadata { |
||||
|
/* Leave some space between the metadata and the title */ |
||||
|
margin-top: 20px; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Single post layout |
||||
|
*/ |
||||
|
article { |
||||
|
padding: 50px 35px 20px 35px; |
||||
|
font-size: 16px; |
||||
|
line-height: 1.5em; |
||||
|
} |
||||
|
|
||||
|
article img, article video { |
||||
|
max-width: 100%; |
||||
|
height: auto; |
||||
|
border-radius: 5px; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
article p { |
||||
|
text-align: justify; |
||||
|
text-justify: inter-word; |
||||
|
} |
||||
|
|
||||
|
article header { |
||||
|
padding-bottom: 30px; |
||||
|
font-style: normal; |
||||
|
line-height: 1.5em; |
||||
|
|
||||
|
/* Align the site title with the article title */ |
||||
|
padding-top: 11px; |
||||
|
} |
||||
|
|
||||
|
/* Article title */ |
||||
|
article header h1 { |
||||
|
font-size: 30px; |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
/* Article subtitle */ |
||||
|
article header h4 { |
||||
|
font-size: 18px; |
||||
|
opacity: 0.6; |
||||
|
padding: 0px 0 8px 0; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Menu (left side) |
||||
|
*/ |
||||
|
.menu-lang { |
||||
|
padding-right: 28px; |
||||
|
} |
||||
|
|
||||
|
.menu-head, .menu-link-list a, .menu-head:hover, .menu-link-list a:hover { |
||||
|
display: block; |
||||
|
text-decoration: none !important; |
||||
|
cursor: pointer; |
||||
|
border-right: 2px solid transparent; |
||||
|
} |
||||
|
|
||||
|
.menu-head.active, .menu-link-list a.active { |
||||
|
border-right: 2px solid var(--active-menu-border-color); |
||||
|
background: var(--active-menu-background-color); |
||||
|
color: var(--active-menu-color); |
||||
|
} |
||||
|
|
||||
|
.menu-head:hover, .menu-link-list a:hover { |
||||
|
border-right: 2px solid var(--hover-menu-border-color); |
||||
|
background: var(--hover-menu-background-color); |
||||
|
color: var(--hover-menu-color); |
||||
|
} |
||||
|
|
||||
|
.menu-footer { |
||||
|
padding: 20px 30px 0 20px; |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.menu-head { |
||||
|
padding: 30px 28px 30px 20px; |
||||
|
margin-bottom: 10px; |
||||
|
color: var(--main-text-color); |
||||
|
} |
||||
|
|
||||
|
.menu-title { |
||||
|
--menu-title-size: 30px; |
||||
|
font-size: var(--menu-title-size); |
||||
|
line-height: calc(var(--menu-title-size) * 1.4); |
||||
|
} |
||||
|
|
||||
|
.menu-subtitle { |
||||
|
margin-top: 8px; |
||||
|
font-size: 18px; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.menu-link-list { |
||||
|
flex-grow: 1; |
||||
|
} |
||||
|
|
||||
|
.menu-link-list a { |
||||
|
font-size: 20px; |
||||
|
margin-bottom: 10px; |
||||
|
padding: 8px 28px 8px 30px; |
||||
|
color: var(--main-text-color); |
||||
|
} |
||||
|
|
||||
|
.menu-content { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
height: 100vh; |
||||
|
width: var(--menu-container-width); |
||||
|
text-align: right; |
||||
|
font-family: var(--sans-preferred-font-list); |
||||
|
padding: 20px 0 50px 0; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: space-between; |
||||
|
|
||||
|
/* Below the hamburger menu but on top of the overlay */ |
||||
|
z-index: 253; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Hamburger menu |
||||
|
*/ |
||||
|
.menu input.hamburger-menu { |
||||
|
display: block; |
||||
|
width: 80px; |
||||
|
height: 72px; |
||||
|
position: fixed; |
||||
|
top: 0px; |
||||
|
left: 0px; |
||||
|
margin: 0; |
||||
|
|
||||
|
cursor: pointer; |
||||
|
|
||||
|
opacity: 0; /* hide this */ |
||||
|
z-index: 255; /* and place it over the hamburger */ |
||||
|
|
||||
|
-webkit-touch-callout: none; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Draw the hamburger |
||||
|
*/ |
||||
|
.menu div.hamburger-menu { |
||||
|
width: 32px; |
||||
|
height: 4px; |
||||
|
position: fixed; |
||||
|
left: 24px; |
||||
|
|
||||
|
background: var(--main-text-color); |
||||
|
border-radius: 3px; |
||||
|
|
||||
|
z-index: 254; |
||||
|
|
||||
|
transform-origin: center; |
||||
|
transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0), |
||||
|
opacity 0.55s ease; |
||||
|
} |
||||
|
|
||||
|
.menu div.hamburger-menu:nth-child(2) { |
||||
|
top: 25px; |
||||
|
} |
||||
|
|
||||
|
.menu div.hamburger-menu:nth-child(3) { |
||||
|
top: 34px; |
||||
|
} |
||||
|
|
||||
|
.menu div.hamburger-menu:nth-child(4) { |
||||
|
top: 43px; |
||||
|
} |
||||
|
|
||||
|
/* Transform all the slices of hamburger into a crossmark. */ |
||||
|
.menu input.hamburger-menu:checked ~ div.hamburger-menu:nth-child(2) { |
||||
|
opacity: 1; |
||||
|
transform: translate(0, 9px) rotate(45deg); |
||||
|
} |
||||
|
|
||||
|
/* But let's hide the middle one. */ |
||||
|
.menu input.hamburger-menu:checked ~ div.hamburger-menu:nth-child(3) { |
||||
|
opacity: 0; |
||||
|
transform: rotate(0deg) scale(0.2, 0.2); |
||||
|
} |
||||
|
|
||||
|
/* And the last one should go the other direction */ |
||||
|
.menu input.hamburger-menu:checked ~ div.hamburger-menu:nth-child(4) { |
||||
|
transform: translate(0, -9px) rotate(-45deg); |
||||
|
} |
||||
|
|
||||
|
/* On mobile browsers, keep a title displayed on top */ |
||||
|
.menu .mobile-title { |
||||
|
padding: 20px 80px 20px 80px; |
||||
|
margin: 0; |
||||
|
width: 100%; |
||||
|
height: 80px; |
||||
|
line-height: 40px; /* line-height = height - padding-top - padding-bottom */ |
||||
|
text-align: center; |
||||
|
font-size: calc(var(--heading1-size) - 3 * var(--heading-diff)); |
||||
|
font-weight: bold; |
||||
|
position: fixed; |
||||
|
box-shadow: 0 0 16px rgba(0, 0, 0, 0.12); |
||||
|
background-color: var(--main-background-color); |
||||
|
} |
||||
|
|
||||
|
/* But hide them by default. They will be uncovered when needed by media queries */ |
||||
|
.menu .hamburger-menu, .menu .mobile-title { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Toolbar (right side) |
||||
|
*/ |
||||
|
.toolbar { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
width: var(--toolbar-container-width); |
||||
|
font-family: var(--sans-preferred-font-list); |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: flex-end; |
||||
|
} |
||||
|
|
||||
|
.actions { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
margin-bottom: 50px; |
||||
|
margin-left: 30px; |
||||
|
} |
||||
|
|
||||
|
.actions .action { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
cursor: pointer; |
||||
|
margin-right: 10px; |
||||
|
} |
||||
|
|
||||
|
.actions a { |
||||
|
text-decoration: none; |
||||
|
color: var(--main-text-color); |
||||
|
} |
||||
|
|
||||
|
.actions a:visited { |
||||
|
color: var(--main-text-color); |
||||
|
} |
||||
|
|
||||
|
.actions .material-icons { |
||||
|
height: 2rem; |
||||
|
width: auto; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Search page |
||||
|
*/ |
||||
|
.search input { |
||||
|
width: 100%; |
||||
|
} |
||||
|
|
||||
|
@media screen { |
||||
|
/* |
||||
|
* Main part of the page (center) |
||||
|
* |
||||
|
* Enclosed in @media screen block because this style is not desired for |
||||
|
* printing. |
||||
|
*/ |
||||
|
main { |
||||
|
padding-left: var(--menu-container-width); |
||||
|
padding-right: var(--toolbar-container-width); |
||||
|
width: 100%; |
||||
|
|
||||
|
min-height: 100vh; |
||||
|
} |
||||
|
|
||||
|
/* Immediate children of main gets a left/right shadow */ |
||||
|
main > * { |
||||
|
box-shadow: 0 0 16px rgba(0, 0, 0, 0.12); |
||||
|
min-height: 100vh; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Table of content (within the toolbar on the right) |
||||
|
*/ |
||||
|
.toc { |
||||
|
float: right; |
||||
|
border-radius: 5px; |
||||
|
margin-left: 30px; |
||||
|
margin-right: 60px; |
||||
|
margin-top: 30px; |
||||
|
max-width: 260px; |
||||
|
max-height: 80vh; |
||||
|
overflow: auto; |
||||
|
background: var(--toc-background-color); |
||||
|
padding: 20px; |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
|
||||
|
.toc ul { |
||||
|
list-style: none; |
||||
|
padding: 0; |
||||
|
margin: 0; |
||||
|
line-height: 1.7em; |
||||
|
} |
||||
|
|
||||
|
.toc h4 { |
||||
|
text-align: center; |
||||
|
margin: 0 0 10px 0; |
||||
|
} |
||||
|
|
||||
|
/* Mathjax container */ |
||||
|
mjx-container { |
||||
|
overflow-y: hidden !important; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Reactive tweaks |
||||
|
*/ |
||||
|
@media screen and (max-width: 1440px) { |
||||
|
:root { |
||||
|
--menu-container-width: 20%; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@media screen and (max-width: 1280px) { |
||||
|
.toc { |
||||
|
display: none; |
||||
|
} |
||||
|
:root { |
||||
|
--toolbar-container-width: 5%; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@media screen and (max-width: 1140px) { |
||||
|
article { |
||||
|
padding: 30px 20px 20px 20px; |
||||
|
} |
||||
|
|
||||
|
main { |
||||
|
padding: 0; |
||||
|
min-height: unset; |
||||
|
} |
||||
|
|
||||
|
.toolbar { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.toc { |
||||
|
line-height: 2em; |
||||
|
float: none; |
||||
|
margin-top: 30px; |
||||
|
margin-left: 0; |
||||
|
margin-right: 0; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* On mobile devices, there are no :hover events. So we must always |
||||
|
* propose horizontal scrollbars when needed. |
||||
|
*/ |
||||
|
pre { |
||||
|
overflow-x: auto; |
||||
|
} |
||||
|
|
||||
|
.menu .hamburger-menu, .menu .mobile-title { |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* On mobile, leave some room above the article so that the title + hamburger |
||||
|
* menu do not hide the article title. |
||||
|
*/ |
||||
|
main > *:first-child { |
||||
|
padding-top: 110px; |
||||
|
} |
||||
|
|
||||
|
.menu .menu-content { |
||||
|
width: 300px; |
||||
|
left: -300px; |
||||
|
height: 100vh; |
||||
|
background-color: var(--main-background-color); |
||||
|
position: fixed; |
||||
|
transform: none; |
||||
|
transition: transform 0.2s linear; |
||||
|
} |
||||
|
|
||||
|
.menu .menu-overlay { |
||||
|
display: block; |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
width: 100vw; |
||||
|
height: 100vh; |
||||
|
transition: background-color 0.2s linear; |
||||
|
|
||||
|
/* |
||||
|
* Put the overlay on the bottom of the stack so that it does not catch |
||||
|
* click events. |
||||
|
*/ |
||||
|
z-index: -1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
* When the hamburger menu is clicked, show the menu content and enable |
||||
|
* the overlay that hides the article content. |
||||
|
*/ |
||||
|
.menu input.hamburger-menu:checked ~ .menu-content { |
||||
|
transform: translate(300px, 0); |
||||
|
} |
||||
|
|
||||
|
.menu input.hamburger-menu:checked ~ .menu-overlay { |
||||
|
/* Semi transparent background */ |
||||
|
background-color: rgba(0, 0, 0, 0.5); |
||||
|
|
||||
|
/* Below the hamburger menu, the menu content but over the article content */ |
||||
|
z-index: 250; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Leave some room between the list items in the term pages so that it is |
||||
|
* easier to click on mobile. Also makes Google happy. |
||||
|
*/ |
||||
|
.terms ul li { |
||||
|
line-height: 2em; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@media screen and (max-width: 512px) { |
||||
|
/* |
||||
|
* On mobile, hide some post metadata |
||||
|
*/ |
||||
|
.post-metadata .opensource, .post-metadata .topic, .post-metadata .reading-time { |
||||
|
display: none; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Tweaks for printing |
||||
|
*/ |
||||
|
@media print { |
||||
|
.menu, .menu-content, .hamburger-menu, .toolbar { |
||||
|
display: none !important; |
||||
|
} |
||||
|
|
||||
|
/* Since you cannot scroll horizontally on a paper, wrap the code blocks */ |
||||
|
pre { |
||||
|
white-space: pre-wrap; |
||||
|
word-break: break-all; |
||||
|
word-wrap: break-word; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
- id: last_modify_on |
||||
|
translation: Last modified on |
||||
|
- id: published_on |
||||
|
translation: Published on |
||||
|
- id: date_format |
||||
|
translation: "January 2, 2006" |
||||
|
- id: toc |
||||
|
translation: Table of contents |
||||
|
- id: back_to_top |
||||
|
translation: Top of the page |
||||
|
- id: minutes |
||||
|
translation: |
||||
|
one: '{{ .Count }} minute' |
||||
|
other: '{{ .Count }} minutes' |
||||
|
- id: continue_reading |
||||
|
translation: Continue reading |
||||
|
- id: articles_related_to |
||||
|
translation: Articles related to |
||||
|
- id: recent_articles |
||||
|
translation: Recent articles |
||||
|
- id: not_found |
||||
|
translation: This page does not exist! |
||||
|
- id: go_home |
||||
|
translation: Go Home |
||||
|
- id: search |
||||
|
translation: Search |
||||
|
- id: search_here |
||||
|
translation: Search something... |
||||
|
- id: type_blog |
||||
|
translation: Article |
||||
|
- id: type_writing |
||||
|
translation: Writing |
||||
|
- id: type_speaking |
||||
|
translation: Speaking |
||||
|
- id: type_page |
||||
|
translation: Misc. |
||||
|
- id: show_menu |
||||
|
translation: Show the menu |
||||
|
- id: file |
||||
|
translation: 'File "%s"' |
||||
|
- id: rss_feed |
||||
|
translation: 'RSS Feed' |
||||
@ -0,0 +1,42 @@ |
|||||
|
- id: last_modify_on |
||||
|
translation: Dernière modification le |
||||
|
- id: published_on |
||||
|
translation: Publié le |
||||
|
- id: date_format |
||||
|
translation: "02/01/2006" |
||||
|
- id: toc |
||||
|
translation: Sommaire |
||||
|
- id: back_to_top |
||||
|
translation: Retour en haut de la page |
||||
|
- id: minutes |
||||
|
translation: |
||||
|
one: '{{ .Count }} minute' |
||||
|
other: '{{ .Count }} minutes' |
||||
|
- id: continue_reading |
||||
|
translation: Continuer la lecture |
||||
|
- id: articles_related_to |
||||
|
translation: Articles concernant |
||||
|
- id: recent_articles |
||||
|
translation: Articles récents |
||||
|
- id: not_found |
||||
|
translation: Cette page n'existe pas ! |
||||
|
- id: go_home |
||||
|
translation: Retour à la page d'accueil |
||||
|
- id: search |
||||
|
translation: Recherche |
||||
|
- id: search_here |
||||
|
translation: Rechercher quelque chose... |
||||
|
- id: type_blog |
||||
|
translation: Article |
||||
|
- id: type_writing |
||||
|
translation: Publication |
||||
|
- id: type_speaking |
||||
|
translation: Conférence |
||||
|
- id: type_page |
||||
|
translation: Divers |
||||
|
- id: show_menu |
||||
|
translation: Afficher le menu |
||||
|
- id: file |
||||
|
translation: 'Fichier "%s"' |
||||
|
- id: rss_feed |
||||
|
translation: 'Flux RSS' |
||||
@ -0,0 +1,9 @@ |
|||||
|
{{ define "main" }} |
||||
|
<!-- The "404" layout prints the classical 404 error --> |
||||
|
<article class="post"> |
||||
|
<header> |
||||
|
<h1>{{ i18n "not_found" }}</h1> |
||||
|
</header> |
||||
|
<p><a href="{{ .Site.Home.RelPermalink }}">{{ i18n "go_home" }}</a></p> |
||||
|
</article> |
||||
|
{{ end }} |
||||
@ -0,0 +1,14 @@ |
|||||
|
<!-- the baseof.html layout is the entrypoint for every page --> |
||||
|
<!DOCTYPE html> |
||||
|
<html lang="{{ .Lang }}"> |
||||
|
{{ partial "head.html" . }} |
||||
|
<body> |
||||
|
<!-- HTML Anchor used by the button "back to top" --> |
||||
|
<a name="top"></a> |
||||
|
{{ partial "menu.html" . }} |
||||
|
{{ partial "toolbar.html" . }} |
||||
|
<main> |
||||
|
{{ block "main" . }}{{- end }} |
||||
|
</main> |
||||
|
</body> |
||||
|
</html> |
||||
@ -0,0 +1,214 @@ |
|||||
|
{{ define "main" }} |
||||
|
<!-- The "search/index.html" layout renders the search engine --> |
||||
|
<article class="search article-list"> |
||||
|
<header> |
||||
|
<h1>{{ .Title }}</h1> |
||||
|
{{- with .Description }} |
||||
|
<h4>{{ . }}</h4> |
||||
|
{{- end }} |
||||
|
</header> |
||||
|
{{ .Content }} |
||||
|
<input id="searchInput" tabindex="0" placeholder="{{ i18n "search_here" }}" autofocus> |
||||
|
<div id="searchResults"> |
||||
|
</div> |
||||
|
<div style="display: none;" id="image-store"> |
||||
|
{{- range $_, $file := (slice "en" "fr" "label" "link" "schedule") -}} |
||||
|
<div id="embedded-svg-{{ $file }}"> |
||||
|
{{- partial (printf "icons/%s.svg" $file) . -}} |
||||
|
</div> |
||||
|
{{- end }} |
||||
|
</div> |
||||
|
<script type="text/javascript"> |
||||
|
var searchResults = document.getElementById('searchResults'); // targets the <div> above |
||||
|
var searchInput = document.getElementById('searchInput'); // input box for search |
||||
|
var lastSearch = ""; |
||||
|
|
||||
|
// Helper function to create an element with attributes |
||||
|
function tag(name, attrs) { |
||||
|
var el = document.createElement(name.toString()); |
||||
|
|
||||
|
!!attrs && Object.keys(attrs).forEach(function(key) { |
||||
|
el.setAttribute(key, attrs[key]); |
||||
|
}); |
||||
|
|
||||
|
return el; |
||||
|
} |
||||
|
|
||||
|
function printSearchResult(result) { |
||||
|
var section = tag("section"); |
||||
|
|
||||
|
// |
||||
|
// Article headline |
||||
|
// |
||||
|
var a = tag("a", { href: result.item.permalink }); |
||||
|
a.textContent = result.item.title; |
||||
|
if (result.item.hasEnFlag) { |
||||
|
var uk_flag_svg = document.getElementById("embedded-svg-en"); |
||||
|
if (uk_flag_svg != null) { |
||||
|
var img = uk_flag_svg.firstChild.cloneNode(true); |
||||
|
a.appendChild(img); |
||||
|
} |
||||
|
} |
||||
|
var h4 = tag("h4"); |
||||
|
h4.textContent = result.item.type_label + " >> "; |
||||
|
h4.appendChild(a); |
||||
|
section.appendChild(h4); |
||||
|
|
||||
|
// |
||||
|
// Metadata |
||||
|
// |
||||
|
if (result.item.type != "page") { |
||||
|
var div = tag("div", { 'class': 'post-metadata'}); |
||||
|
var span_date = tag("span", { 'class': 'publication-date' }); |
||||
|
span_date.textContent = {{ i18n "published_on" }} + " " + result.item.date; |
||||
|
div.appendChild(span_date); |
||||
|
if (result.item.topics != null) { |
||||
|
result.item.topics.forEach(function (v) { |
||||
|
var topic_detail = taxonomies.topics[v]; |
||||
|
if (topic_detail == null) { |
||||
|
return; |
||||
|
} |
||||
|
var span = tag("span", { 'class': 'topic' }); |
||||
|
var link_svg = document.getElementById("embedded-svg-link"); |
||||
|
if (link_svg != null) { |
||||
|
var img = link_svg.firstChild.cloneNode(true); |
||||
|
span.appendChild(img); |
||||
|
} |
||||
|
var a = tag("a", { href: topic_detail.href }); |
||||
|
a.textContent = topic_detail.title; |
||||
|
span.appendChild(a); |
||||
|
div.appendChild(span); |
||||
|
}); |
||||
|
} |
||||
|
if (result.item.opensource != null) { |
||||
|
result.item.opensource.forEach(function (v) { |
||||
|
var opensource_detail = taxonomies.opensource[v]; |
||||
|
if (opensource_detail == null) { |
||||
|
return; |
||||
|
} |
||||
|
var span = tag("span", { 'class': 'opensource' }); |
||||
|
var label_svg = document.getElementById("embedded-svg-label"); |
||||
|
if (label_svg != null) { |
||||
|
var img = label_svg.firstChild.cloneNode(true); |
||||
|
span.appendChild(img); |
||||
|
} |
||||
|
var a = tag("a", { href: opensource_detail.href }); |
||||
|
a.textContent = opensource_detail.title; |
||||
|
span.appendChild(a); |
||||
|
div.appendChild(span); |
||||
|
}); |
||||
|
} |
||||
|
if (result.item.reading_time != null) { |
||||
|
var span = tag("span", { 'class': 'reading-time' }); |
||||
|
var schedule_svg = document.getElementById("embedded-svg-schedule"); |
||||
|
if (schedule_svg != null) { |
||||
|
var img = schedule_svg.firstChild.cloneNode(true); |
||||
|
span.appendChild(img); |
||||
|
} |
||||
|
var readingTime = document.createTextNode(result.item.reading_time); |
||||
|
span.appendChild(readingTime); |
||||
|
div.appendChild(span); |
||||
|
} |
||||
|
section.appendChild(div); |
||||
|
} |
||||
|
|
||||
|
var p = tag("p", {}); |
||||
|
p.textContent = result.item.summary; |
||||
|
var a = tag("a", { href: result.item.permalink, 'class': 'continue-reading' }); |
||||
|
a.textContent = {{ i18n "continue_reading" }}; |
||||
|
p.appendChild(a); |
||||
|
section.appendChild(p); |
||||
|
|
||||
|
searchResults.appendChild(section); |
||||
|
} |
||||
|
|
||||
|
function clearSearchResults() { |
||||
|
var child = searchResults.lastElementChild; |
||||
|
while (child) { |
||||
|
searchResults.removeChild(child); |
||||
|
child = searchResults.lastElementChild; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// |
||||
|
// load the search index |
||||
|
// |
||||
|
function fuseInit(searchDb) { |
||||
|
var options = { // fuse.js options; check fuse.js website for details |
||||
|
shouldSort: true, |
||||
|
ignoreLocation: true, |
||||
|
threshold: 0.4, |
||||
|
minMatchCharLength: 3, |
||||
|
keys: [ |
||||
|
'title', |
||||
|
'permalink', |
||||
|
'summary', |
||||
|
'topics', |
||||
|
'opensource' |
||||
|
] |
||||
|
}; |
||||
|
fuse = new Fuse(searchDb, options); // build the index from the json file |
||||
|
} |
||||
|
|
||||
|
// |
||||
|
// using the index loaded previously, run a search query (for "term") |
||||
|
// every time a letter is typed in the search box |
||||
|
// |
||||
|
function executeSearch(term) { |
||||
|
if (lastSearch == term) { |
||||
|
// Don't query Fuse if the search terms have not changed |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
clearSearchResults(); |
||||
|
let results = fuse.search(term); |
||||
|
results.slice(0, 20).forEach(printSearchResult); |
||||
|
lastSearch = term; |
||||
|
} |
||||
|
|
||||
|
// Fill-in details about taxonomies |
||||
|
{{- $.Scratch.Set "taxonomies" dict -}} |
||||
|
{{- range $name, $taxonomy := .Site.Taxonomies -}} |
||||
|
{{- $.Scratch.Set "taxonomy" dict -}} |
||||
|
{{- range (index $.Site.Taxonomies $name) -}} |
||||
|
{{- $.Scratch.SetInMap "taxonomy" .Page.Title (dict "href" .Page.RelPermalink "title" .Page.Title) -}} |
||||
|
{{- end -}} |
||||
|
{{- $.Scratch.SetInMap "taxonomies" $name ($.Scratch.Get "taxonomy") -}} |
||||
|
{{- end }} |
||||
|
var taxonomies = {{- $.Scratch.Get "taxonomies" | jsonify | safeJS -}}; |
||||
|
|
||||
|
// Fill-in the Search DB with site's content |
||||
|
{{- $.Scratch.Add "index" slice -}} |
||||
|
{{- range .Site.RegularPages -}} |
||||
|
{{- $.Scratch.Set "reading_time" nil -}} |
||||
|
{{- if eq .Type "blog" -}} |
||||
|
{{- $minutes := .ReadingTime -}} |
||||
|
{{- if gt $minutes 0 -}} |
||||
|
{{- $.Scratch.Set "reading_time" (i18n "minutes" $minutes) -}} |
||||
|
{{- end -}} |
||||
|
{{- end -}} |
||||
|
|
||||
|
{{- $.Scratch.Set "date" nil -}} |
||||
|
{{- if ne .Type "page" -}} |
||||
|
{{- $.Scratch.Set "date" (.Date.Format (i18n "date_format")) -}} |
||||
|
{{- end -}} |
||||
|
|
||||
|
{{ .Scratch.Set "en_article_in_fr_site" false }} |
||||
|
{{- partial "lang-detection.html" . -}} |
||||
|
{{- $.Scratch.Add "index" (dict "title" .Title "opensource" .Params.opensource "topics" .Params.topics "permalink" .Permalink "hasEnFlag" (.Scratch.Get "en_article_in_fr_site") "type" .Type "type_label" (i18n (print "type_" .Type)) "date" ($.Scratch.Get "date") "reading_time" ($.Scratch.Get "reading_time") "summary" (.Summary | plainify | htmlUnescape)) -}} |
||||
|
{{- end }} |
||||
|
var searchDb = {{- $.Scratch.Get "index" | jsonify | safeJS -}}; |
||||
|
|
||||
|
// Initialize the Fuse.io framework with the Search DB |
||||
|
fuseInit(searchDb); |
||||
|
|
||||
|
// |
||||
|
// execute search as each character is typed |
||||
|
// |
||||
|
searchInput.onkeyup = function(e) { |
||||
|
executeSearch(this.value); |
||||
|
} |
||||
|
|
||||
|
</script> |
||||
|
</article> |
||||
|
{{ end }} |
||||
@ -0,0 +1,14 @@ |
|||||
|
{{ define "main" }} |
||||
|
<!-- the section.html layout is used to render a list of articles under writing, speaking, etc. --> |
||||
|
<article class="section"> |
||||
|
<header> |
||||
|
<h1>{{ .Title }}</h1> |
||||
|
</header> |
||||
|
{{ .Content }} |
||||
|
<ul> |
||||
|
{{ range (sort .Pages "Date").Reverse }} |
||||
|
<li><a href="{{.RelPermalink}}">{{ .Title }}</a></li> |
||||
|
{{ end }} |
||||
|
</ul> |
||||
|
</article> |
||||
|
{{ end }} |
||||
@ -0,0 +1,18 @@ |
|||||
|
{{ define "main" }} |
||||
|
<!-- The "single" layout prints a single post --> |
||||
|
{{- partial "lang-detection.html" . -}} |
||||
|
<article class="post" {{ if .Scratch.Get "en_article_in_fr_site" }}lang="en"{{ end }}> |
||||
|
<header> |
||||
|
<h1>{{ .Title }}</h1> |
||||
|
{{- with .Description }} |
||||
|
<h4>{{ . }}</h4> |
||||
|
{{- end }} |
||||
|
{{ partial "post-metadata.html" (dict "current" . "parent" .) -}} |
||||
|
</header> |
||||
|
{{ .Content }} |
||||
|
{{- if and (not .Lastmod.IsZero) (ne .Lastmod .PublishDate) }} |
||||
|
<hr width="100%" id="EOF"> |
||||
|
<p>{{ i18n "last_modify_on" }} {{ .Lastmod.Format (i18n "date_format") }}</p> |
||||
|
{{- end }} |
||||
|
</article> |
||||
|
{{ end }} |
||||
@ -0,0 +1,14 @@ |
|||||
|
{{ define "main" }} |
||||
|
<!-- the taxonomy.html layout is used to render the list of posts having a certain tag, topic, etc. --> |
||||
|
<article class="article-list"> |
||||
|
<header> |
||||
|
<h1>{{ .Title }}</h1> |
||||
|
</header> |
||||
|
{{ i18n "articles_related_to" }} <a href="{{.Parent.RelPermalink}}">{{.Parent.Title}}</a> / <a href="{{.RelPermalink}}">{{ .Title }}</a>: |
||||
|
{{ .Content }} |
||||
|
{{ range (.Paginate (sort .Pages "Date").Reverse).Pages }} |
||||
|
{{- partial "article-headline.html" (dict "current" . "parent" $.Page) -}} |
||||
|
{{ end }} |
||||
|
{{ template "_internal/pagination.html" . }} |
||||
|
</article> |
||||
|
{{ end }} |
||||
@ -0,0 +1,14 @@ |
|||||
|
{{ define "main" }} |
||||
|
<!-- the terms.html layout is used to render the list of values of a certain tag, topic, etc. --> |
||||
|
<article class="terms"> |
||||
|
<header> |
||||
|
<h1>{{ .Title }}</h1> |
||||
|
</header> |
||||
|
{{ .Content }} |
||||
|
<ul> |
||||
|
{{ range sort .Pages "Title" }} |
||||
|
<li><a href="{{.RelPermalink}}">{{ .Title }}</a></li> |
||||
|
{{ end }} |
||||
|
</ul> |
||||
|
</article> |
||||
|
{{ end }} |
||||
@ -0,0 +1,14 @@ |
|||||
|
{{ define "main" }} |
||||
|
<!-- the blog/list.html layout is used to render the list of posts under "blog" --> |
||||
|
<article class="article-list"> |
||||
|
<header> |
||||
|
<h1>Articles</h1> |
||||
|
</header> |
||||
|
{{ .Content }} |
||||
|
|
||||
|
{{ range (.Paginate (sort .Pages "Date").Reverse).Pages }} |
||||
|
{{- partial "article-headline.html" (dict "current" . "parent" $.Page) -}} |
||||
|
{{ end }} |
||||
|
{{ template "_internal/pagination.html" . }} |
||||
|
</article> |
||||
|
{{ end }} |
||||
@ -0,0 +1,24 @@ |
|||||
|
{{ define "main" }} |
||||
|
<!-- the index.html layout is used only to render the home page --> |
||||
|
<div> |
||||
|
<article class="bio"> |
||||
|
<!-- |
||||
|
<header> |
||||
|
<h1>{{ .Title }}</h1> |
||||
|
{{ if .Params.description }} |
||||
|
<h2>{{ .Params.description }}</h2> |
||||
|
{{ end }} |
||||
|
</header> |
||||
|
--> |
||||
|
{{ .Content }} |
||||
|
</article> |
||||
|
<article class="article-list"> |
||||
|
<header> |
||||
|
<h1>{{ i18n "recent_articles" }}</h1> |
||||
|
</header> |
||||
|
{{ range first 5 (sort ((.Site.GetPage "/blog").Pages) "Date").Reverse }} |
||||
|
{{- partial "article-headline.html" (dict "current" . "parent" $.Page) -}} |
||||
|
{{ end }} |
||||
|
</article> |
||||
|
</div> |
||||
|
{{ end }} |
||||
@ -0,0 +1,11 @@ |
|||||
|
|
||||
|
<section> |
||||
|
<h4><a href="{{ .current.RelPermalink }}">{{ .current.Title }} |
||||
|
{{- partial "lang-detection.html" .current -}} |
||||
|
{{ if .current.Scratch.Get "en_article_in_fr_site" }} |
||||
|
{{- partial "icons/en.svg" . -}} |
||||
|
{{ end }} |
||||
|
</a></h4> |
||||
|
{{- partial "post-metadata.html" . -}} |
||||
|
<p>{{ .current.Summary | plainify | htmlUnescape }} <a href="{{ .current.RelPermalink }}" class="continue-reading">{{ i18n "continue_reading" }}</a></p> |
||||
|
</section> |
||||
@ -0,0 +1,146 @@ |
|||||
|
<head> |
||||
|
<title>{{.Title}}</title> |
||||
|
<meta charset="utf-8"> |
||||
|
|
||||
|
<!-- |
||||
|
-- Package all CSS files together and minify them. |
||||
|
-- The page loading time should improve. |
||||
|
--> |
||||
|
{{ $chroma := resources.Get "css/chroma.css" }} |
||||
|
{{ $itix := resources.Get "css/itix.css" }} |
||||
|
{{ $css := slice $chroma $itix | resources.Concat "css/itix.css" | resources.Minify | resources.Fingerprint "sha512" }} |
||||
|
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}"> |
||||
|
|
||||
|
<!-- |
||||
|
-- Core Web Vitals / Cumulative Layout Shift. |
||||
|
-- |
||||
|
-- Preload all fonts and images to reduce layout shifts. |
||||
|
--> |
||||
|
<link rel="preload" href="/fonts/JetBrainsMono-Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous"> |
||||
|
<link rel="preload" href="/fonts/JetBrainsMono-Regular.woff" as="font" type="font/woff" crossorigin="anonymous"> |
||||
|
<link rel="preload" href="/fonts/JetBrainsMono-Regular.ttf" as="font" type="font/ttf" crossorigin="anonymous"> |
||||
|
<link rel="preload" href="/fonts/SourceSerifPro-Regular.ttf" as="font" type="font/ttf" crossorigin="anonymous"> |
||||
|
<link rel="preload" href="/fonts/SourceSansPro-Regular.ttf" as="font" type="font/ttf" crossorigin="anonymous"> |
||||
|
|
||||
|
<!-- |
||||
|
-- Add a reference to the favicon.ico. |
||||
|
-- The file needs to be added in the "static" directory. |
||||
|
--> |
||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico"> |
||||
|
|
||||
|
<!-- |
||||
|
-- Ensure the <meta name=description> tag is never empty since it is used |
||||
|
-- in the SEO score. |
||||
|
--> |
||||
|
{{- if .IsHome }} |
||||
|
{{- with .Site.Params.description }} |
||||
|
<meta name="description" content="{{ . }}"> |
||||
|
{{- else }} |
||||
|
<meta name="description" content="{{ .Title }}"> |
||||
|
{{- end }} |
||||
|
{{- else }} |
||||
|
{{- with .Params.description }} |
||||
|
<meta name="description" content="{{ . }}"> |
||||
|
{{- else }} |
||||
|
<meta name="description" content="{{ .Title }}"> |
||||
|
{{- end }} |
||||
|
{{- end }} |
||||
|
|
||||
|
<!-- Add all the relevant RSS Feed URLs --> |
||||
|
{{ with .OutputFormats.Get "rss" -}} |
||||
|
{{ printf `<link rel=%q type=%q href=%q title=%q>` .Rel .MediaType.Type .Permalink site.Title | safeHTML }} |
||||
|
{{ end }} |
||||
|
|
||||
|
<!-- Tell IE to use the Edge engine --> |
||||
|
<meta name="X-UA-Compatible" content="IE=edge"> |
||||
|
|
||||
|
<!-- |
||||
|
-- The viewport is the user's visible area of a web page. |
||||
|
-- The viewport varies with the device, and will be smaller on a mobile phone |
||||
|
-- than on a computer screen. |
||||
|
-- |
||||
|
-- This meta tag let web designers take control over the viewport. |
||||
|
-- |
||||
|
-- The width property controls the size of the viewport. It can be set to |
||||
|
-- the special value device-width, which is the width of the screen in CSS |
||||
|
-- pixels at a scale of 100%. |
||||
|
-- |
||||
|
-- The initial-scale=1.0 part sets the initial zoom level when the page |
||||
|
-- is first loaded by the browser. |
||||
|
--> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
|
||||
|
{{ template "_internal/opengraph.html" . }} |
||||
|
{{ template "_internal/twitter_cards.html" . }} |
||||
|
|
||||
|
<!-- The search page is the only one to require Javascript --> |
||||
|
{{ if eq .Type "search" }} |
||||
|
<!-- |
||||
|
-- Download and copy over fuse.js file from fusejs.io. |
||||
|
-- I used the UMD build, minified, version 6.4.3 |
||||
|
--> |
||||
|
<script src="/js/fuse.js"></script> |
||||
|
{{ end }} |
||||
|
|
||||
|
{{- if .Site.Params.enablePlausible -}} |
||||
|
<script defer data-domain="itix.fr" src="https://plausible.io/js/plausible.js"></script> |
||||
|
{{- end -}} |
||||
|
|
||||
|
{{- if .Params.enableMathJax -}} |
||||
|
{{- partial "mathjax.html" . -}} |
||||
|
{{- end -}} |
||||
|
|
||||
|
<!-- Deal with the case of english articles published in the french site --> |
||||
|
{{- partial "lang-detection.html" . -}} |
||||
|
{{- if .IsTranslated -}} |
||||
|
{{- range .Translations -}} |
||||
|
{{- if .Scratch.Get "en_article_in_fr_site" -}} |
||||
|
<!-- |
||||
|
-- It's an english article published in the french site |
||||
|
-- Tell Google not to index it and link to the original article. |
||||
|
-- |
||||
|
-- See https://developers.google.com/search/docs/advanced/crawling/consolidate-duplicate-urls |
||||
|
--> |
||||
|
<link rel="canonical" href="{{ .Permalink }}"> |
||||
|
<meta name="robots" content="noindex"> |
||||
|
{{ else }} |
||||
|
<!-- Otherwise, just link to the available translations, if any. --> |
||||
|
<link rel="alternate" hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}" title="{{ .Language.LanguageName }}"> |
||||
|
{{ end -}} |
||||
|
{{- end -}} |
||||
|
{{- end -}} |
||||
|
|
||||
|
<!-- |
||||
|
-- Structured Data can be tested using the Google Search Console. |
||||
|
-- https://search.google.com/test/rich-results |
||||
|
--> |
||||
|
{{- if .IsHome -}} |
||||
|
{{- $.Scratch.Set "structured_data" (dict "@context" "http://schema.org" "@type" "WebSite" "name" .Site.Title "url" .Site.BaseURL) -}} |
||||
|
{{- with .Site.Params.subtitle -}} |
||||
|
{{- $.Scratch.SetInMap "structured_data" "description" . -}} |
||||
|
{{- end -}} |
||||
|
{{- else if and .IsPage (eq .Section "blog") -}} |
||||
|
{{- $.Scratch.Set "structured_data" (dict "@context" "http://schema.org" "@type" "BlogPosting" "headline" .Title "image" (slice) "articleSection" .Section) -}} |
||||
|
{{- if and (eq .Lang "fr") (.Scratch.Get "en_article_in_fr_site") -}} |
||||
|
{{- $.Scratch.SetInMap "structured_data" "inLanguage" "en" -}} |
||||
|
{{- range first 1 .Translations -}} |
||||
|
{{- $.Scratch.SetInMap "structured_data" "mainEntityOfPage" (dict "@type" "WebPage" "@id" .Permalink) -}} |
||||
|
{{- end -}} |
||||
|
{{- else -}} |
||||
|
{{- $.Scratch.SetInMap "structured_data" "inLanguage" .Language.Lang -}} |
||||
|
{{- $.Scratch.SetInMap "structured_data" "mainEntityOfPage" (dict "@type" "WebPage" "@id" .Permalink) -}} |
||||
|
{{- end -}} |
||||
|
{{- if not .PublishDate.IsZero -}} |
||||
|
{{- $.Scratch.SetInMap "structured_data" "datePublished" .PublishDate -}} |
||||
|
{{- end -}} |
||||
|
{{- if and (not .Lastmod.IsZero) (ne .Lastmod .PublishDate) -}} |
||||
|
{{- $.Scratch.SetInMap "structured_data" "dateModified" .Lastmod -}} |
||||
|
{{- end -}} |
||||
|
{{- end -}} |
||||
|
{{- with $.Scratch.Get "structured_data" }} |
||||
|
<script type="application/ld+json"> |
||||
|
{{- . | jsonify | safeJS -}} |
||||
|
</script> |
||||
|
{{- end }} |
||||
|
|
||||
|
</head> |
||||
|
After Width: | Height: | Size: 676 B |
|
After Width: | Height: | Size: 249 B |
|
After Width: | Height: | Size: 317 B |
|
After Width: | Height: | Size: 395 B |
|
After Width: | Height: | Size: 350 B |
|
After Width: | Height: | Size: 384 B |
|
After Width: | Height: | Size: 420 B |
|
After Width: | Height: | Size: 232 B |
@ -0,0 +1,15 @@ |
|||||
|
{{ if and .IsTranslated (eq .Lang "fr") }} |
||||
|
<!-- Try to compare files by SH256 fingerprint. --> |
||||
|
{{ if and (index .AllTranslations 0).File (index .AllTranslations 1).File }} |
||||
|
{{ $file0 := readFile (index .AllTranslations 0).File.Filename }} |
||||
|
{{ $file1 := readFile (index .AllTranslations 1).File.Filename }} |
||||
|
{{ if eq (sha256 $file0) (sha256 $file1) }} |
||||
|
{{ .Scratch.Set "en_article_in_fr_site" true }} |
||||
|
{{ end }} |
||||
|
{{ else }} |
||||
|
<!-- Sometimes there is no file though. In that case, compare the content. --> |
||||
|
{{ if eq (index .AllTranslations 0).Plain (index .AllTranslations 1).Plain }} |
||||
|
{{ .Scratch.Set "en_article_in_fr_site" true }} |
||||
|
{{ end }} |
||||
|
{{ end }} |
||||
|
{{ end }} |
||||
@ -0,0 +1,36 @@ |
|||||
|
<!-- From https://note.qidong.name/2018/03/hugo-mathjax/ --> |
||||
|
<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js"></script> |
||||
|
<script> |
||||
|
MathJax = { |
||||
|
tex: { |
||||
|
inlineMath: [['$', '$'], ['\\(', '\\)']] |
||||
|
}, |
||||
|
svg: { |
||||
|
fontCache: 'global' |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
<script type="text/javascript" id="MathJax-script" |
||||
|
async |
||||
|
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"> |
||||
|
MathJax.Hub.Queue(function() { |
||||
|
// Fix <code> tags after MathJax finishes running. This is a |
||||
|
// hack to overcome a shortcoming of Markdown. Discussion at |
||||
|
// https://github.com/mojombo/jekyll/issues/199 |
||||
|
var all = MathJax.Hub.getAllJax(), i; |
||||
|
for(i = 0; i < all.length; i += 1) { |
||||
|
all[i].SourceElement().parentNode.className += ' has-jax'; |
||||
|
} |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
code.has-jax { |
||||
|
font: inherit; |
||||
|
font-size: 100%; |
||||
|
background: inherit; |
||||
|
border: inherit; |
||||
|
color: #515151; |
||||
|
} |
||||
|
</style> |
||||
|
|
||||
@ -0,0 +1,65 @@ |
|||||
|
|
||||
|
<nav class="menu"> |
||||
|
<!-- |
||||
|
-- A fake / hidden checkbox is used as click reciever, |
||||
|
-- so you can use the :checked selector on it. |
||||
|
--> |
||||
|
<input type="checkbox" class="hamburger-menu" id="show-menu" /> |
||||
|
|
||||
|
<!-- Some spans to draw a hamburger. --> |
||||
|
<div class="hamburger-menu"></div> |
||||
|
<div class="hamburger-menu"></div> |
||||
|
<div class="hamburger-menu"></div> |
||||
|
|
||||
|
<!-- Add a label for accessibility --> |
||||
|
<label class="hamburger-menu" for="show-menu" style="display: none;" >{{ i18n "show_menu" }}</label> |
||||
|
|
||||
|
<!-- And the site title for the mobile browsers --> |
||||
|
<div class="mobile-title">{{- .Site.Title -}}</div> |
||||
|
|
||||
|
<div class="menu-content"> |
||||
|
{{- if .IsHome }} |
||||
|
<a class="menu-head active" href="{{ .Site.Home.RelPermalink }}"> |
||||
|
{{ else }} |
||||
|
<a class="menu-head" href="{{ .Site.Home.RelPermalink }}"> |
||||
|
{{ end -}} |
||||
|
<div class="menu-title"> |
||||
|
{{- .Site.Title -}} |
||||
|
</div> |
||||
|
{{- with .Site.Params.subtitle -}} |
||||
|
<div class="menu-subtitle"> |
||||
|
{{- . -}} |
||||
|
</div> |
||||
|
{{- end -}} |
||||
|
</a> |
||||
|
|
||||
|
<div class="menu-link-list"> |
||||
|
{{- $currentPage := . -}} |
||||
|
{{- range .Site.Menus.main }} |
||||
|
<a class="{{ if $currentPage.IsMenuCurrent "main" . }}active{{ end }}" href="{{ .URL| relLangURL }}"> |
||||
|
{{- .Name -}} |
||||
|
</a> |
||||
|
{{- end }} |
||||
|
</div> |
||||
|
|
||||
|
<div class="menu-lang"> |
||||
|
{{- if .IsTranslated -}} |
||||
|
<!-- Try to redirect the user to the translated page if possible --> |
||||
|
{{- range .AllTranslations }} |
||||
|
<a href="{{ .RelPermalink }}">{{- partial (printf "icons/%s.svg" .Lang) . -}}</a> |
||||
|
{{- end -}} |
||||
|
{{- else -}} |
||||
|
<!-- Otherwise, redirect it to the homepage --> |
||||
|
{{- range site.Sites }} |
||||
|
<a href="{{ .Home.RelPermalink }}">{{- partial (printf "icons/%s.svg" .Language.Lang) . -}}</a> |
||||
|
{{- end -}} |
||||
|
{{- end }} |
||||
|
</div> |
||||
|
|
||||
|
<div class="menu-footer"> |
||||
|
© {{ .Site.Home.Date.Year }} {{.Site.Title}} |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="menu-overlay"> |
||||
|
</div> |
||||
|
</nav> |
||||
@ -0,0 +1,43 @@ |
|||||
|
<div class="post-metadata"> |
||||
|
<!-- Article publication date --> |
||||
|
{{- with .current.PublishDate }} |
||||
|
<span class="publication-date"> |
||||
|
{{ i18n "published_on" }} |
||||
|
<time itemprop="published-on" date-time="{{ .Format "2006-01-02" }}">{{ .Format (i18n "date_format") }}</time> |
||||
|
</span> |
||||
|
{{- end }} |
||||
|
|
||||
|
<!-- Expertise / Topics --> |
||||
|
{{ range .current.Params.topics -}} |
||||
|
<!-- Skip the item if we are on the term page presenting this item --> |
||||
|
{{- if or (not $.parent.Data.topic) (ne . $.parent.Data.Term) }} |
||||
|
<span class="topic"> |
||||
|
{{- partial "icons/link.svg" . -}}<a href="{{ "/topics/" | relLangURL }}{{ . | urlize }}/">{{ . }}</a> |
||||
|
</span> |
||||
|
{{- end -}} |
||||
|
{{- end }} |
||||
|
|
||||
|
<!-- Open Source communities --> |
||||
|
{{ range .current.Params.opensource -}} |
||||
|
<!-- Skip the item if we are on the term page presenting this item --> |
||||
|
{{- if or (not $.parent.Data.opensource) (ne . $.parent.Data.Term) }} |
||||
|
<span class="opensource"> |
||||
|
{{- partial "icons/label.svg" . -}}<a href="{{ "/opensource/" | relLangURL }}{{ . | urlize }}/">{{ . }}</a> |
||||
|
</span> |
||||
|
{{- end -}} |
||||
|
{{- end }} |
||||
|
|
||||
|
<!-- |
||||
|
-- The reading time is only displayed on blog posts. Other kind of |
||||
|
-- articles are too short to be relevant. |
||||
|
--> |
||||
|
{{- if eq .current.Type "blog" }} |
||||
|
<span class="reading-time"> |
||||
|
{{- partial "icons/schedule.svg" . -}} |
||||
|
{{- $minutes := .current.ReadingTime -}} |
||||
|
{{- if gt $minutes 0 -}} |
||||
|
{{- i18n "minutes" $minutes -}} |
||||
|
{{- end -}} |
||||
|
</span> |
||||
|
{{- end }} |
||||
|
</div> |
||||
@ -0,0 +1,23 @@ |
|||||
|
<aside class="toolbar"> |
||||
|
<!-- Sometimes Hugo will generate an empty TOC enclosed within a nav element. --> |
||||
|
<!-- 32 is the length of this empty output. --> |
||||
|
{{- if gt (len .TableOfContents) 32 }} |
||||
|
<div class="toc"> |
||||
|
<h4>{{ i18n "toc" }}</h4> |
||||
|
{{ .TableOfContents }} |
||||
|
</div> |
||||
|
{{- end }} |
||||
|
<div class="actions"> |
||||
|
<a href="#top" class="action" title="{{ i18n "back_to_top" }}"> |
||||
|
{{- partial "icons/vertical_align_top.svg" . -}} |
||||
|
</a> |
||||
|
<a href="{{ relref . "/search/index.md" }}" class="action" title="{{ i18n "search" }}"> |
||||
|
{{- partial "icons/search.svg" . -}} |
||||
|
</a> |
||||
|
{{ with .OutputFormats.Get "rss" -}} |
||||
|
<a href="{{ .Permalink }}" class="action" title="{{ i18n "rss_feed" }}"> |
||||
|
{{- partial "icons/rss_feed.svg" . -}} |
||||
|
</a> |
||||
|
{{ end }} |
||||
|
</div> |
||||
|
</aside> |
||||
@ -0,0 +1,7 @@ |
|||||
|
<!-- This shortcode renders an code block prefixed by a filename --> |
||||
|
<div class="highlightedFile"> |
||||
|
{{- with .Get 0 -}} |
||||
|
<div class="filename">{{ printf (i18n "file") . | safeHTML }}</div> |
||||
|
{{- end -}} |
||||
|
{{- highlight (trim .Inner "\n") (.Get 1) (.Get 2) -}} |
||||
|
</div> |
||||
@ -0,0 +1,7 @@ |
|||||
|
<!-- This shortcode renders an code block prefixed by a filename --> |
||||
|
<div class="highlightedFile"> |
||||
|
{{- with .Get 0 -}} |
||||
|
<div class="filename">{{ . | safeHTML }}</div> |
||||
|
{{- end -}} |
||||
|
{{- highlight (trim .Inner "\n") (.Get 1) (.Get 2) -}} |
||||
|
</div> |
||||
@ -0,0 +1,31 @@ |
|||||
|
<!-- This shortcode generates the HTML link to an internal resource, which can be translated or not. |
||||
|
-- It displays a country flag when the target page is in a different language than the current page. |
||||
|
-- Currently, this shortcode can only handle Hugo sites with two languages. --> |
||||
|
{{ $path := .Get "path" }} |
||||
|
{{ $currentLang := .Page.Lang }} |
||||
|
{{ $title := .Get "title" }} |
||||
|
{{ $sites := .Page.Sites }} |
||||
|
{{ if ne $currentLang (index .Page.Sites 0).Language.Lang }} |
||||
|
{{ $sites = collections.Reverse .Page.Sites }} |
||||
|
{{ end }} |
||||
|
{{ range $sites }} |
||||
|
{{ with .GetPage $path }} |
||||
|
<a href="{{ .RelPermalink }}"> |
||||
|
{{ if ne $title "" }} |
||||
|
{{ $title }} |
||||
|
{{ else }} |
||||
|
{{ .Title }} |
||||
|
{{ end }} |
||||
|
</a> |
||||
|
{{ if and (eq $currentLang "en") (eq .Lang "fr") }} |
||||
|
{{- partial "icons/fr.svg" . -}} |
||||
|
{{ end }} |
||||
|
{{ if (eq $currentLang "fr") }} |
||||
|
{{- partial "lang-detection.html" . -}} |
||||
|
{{ if .Scratch.Get "en_article_in_fr_site" }} |
||||
|
{{- partial "icons/en.svg" . -}} |
||||
|
{{ end }} |
||||
|
{{ end }} |
||||
|
{{ break }} |
||||
|
{{ end }} |
||||
|
{{ end }} |
||||
@ -0,0 +1,14 @@ |
|||||
|
{{ define "main" }} |
||||
|
<!-- the speaking/list.html layout is used to render the list of posts under "speaking" --> |
||||
|
<article class="article-list"> |
||||
|
<header> |
||||
|
<h1>{{ .Title }}</h1> |
||||
|
</header> |
||||
|
{{ .Content }} |
||||
|
<ul> |
||||
|
{{ range (sort .Pages "Date").Reverse }} |
||||
|
<li>{{ .Date.Format "January 2006" }} - <a href="{{.RelPermalink}}">{{ .Title }}</a></li> |
||||
|
{{ end }} |
||||
|
</ul> |
||||
|
</article> |
||||
|
{{ end }} |
||||
@ -0,0 +1,14 @@ |
|||||
|
{{ define "main" }} |
||||
|
<!-- the writing/list.html layout is used to render the list of posts under "writing" --> |
||||
|
<article class="article-list"> |
||||
|
<header> |
||||
|
<h1>{{ .Title }}</h1> |
||||
|
</header> |
||||
|
{{ .Content }} |
||||
|
<ul> |
||||
|
{{ range (sort .Pages "Date").Reverse }} |
||||
|
<li>{{ .Date.Format "January 2006" }} - <a href="{{.RelPermalink}}">{{ .Title }}</a></li> |
||||
|
{{ end }} |
||||
|
</ul> |
||||
|
</article> |
||||
|
{{ end }} |
||||
@ -0,0 +1,19 @@ |
|||||
|
name = "ITIX" |
||||
|
license = "MIT" |
||||
|
licenselink = "https://github.com/nmasse-itix/hugo-theme-itix/blob/master/LICENSE" |
||||
|
description = "Theme of my personal site: www.itix.fr" |
||||
|
homepage = "https://www.itix.fr/" |
||||
|
tags = ["blog"] |
||||
|
features = ["mobile","elegant"] |
||||
|
min_version = "0.59.0" |
||||
|
|
||||
|
[author] |
||||
|
name = "Nicolas Massé" |
||||
|
homepage = "https://www.itix.fr/" |
||||
|
|
||||
|
|
||||
|
# If porting an existing theme |
||||
|
[original] |
||||
|
name = "amazingrise" |
||||
|
homepage = "https://amazingrise.net/" |
||||
|
repo = "https://github.com/amazingrise/hugo-theme-diary" |
||||