chore(engine): switch to eleventy

This commit is contained in:
Kazhnuz 2024-10-12 10:30:32 +02:00
parent 4443bea122
commit 65fd0a0dd8
114 changed files with 4493 additions and 8239 deletions

View file

@ -23,7 +23,7 @@ steps:
hosts: hosts:
from_secret: deploy_host from_secret: deploy_host
target: /var/www/rulebook.kobold.city target: /var/www/rulebook.kobold.city
source: dist/* source: _site/*
user: user:
from_secret: deploy_user from_secret: deploy_user
key: key:

View file

@ -1,15 +0,0 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier'
],
parserOptions: {
ecmaVersion: 'latest'
}
}

45
.gitignore vendored
View file

@ -1,28 +1,25 @@
# Logs # Generated files
logs package/generated*
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules # Ignore installed npm modules
.DS_Store node_modules/
dist
dist-ssr
coverage
*.local
/cypress/videos/ # Ignore build tool output, e.g. code coverage
/cypress/screenshots/ .nyc_output/
coverage/
# Editor directories and files # Ignore API documentation
.vscode/* api-docs/
!.vscode/extensions.json
# Ignore folders from source code editors
.vscode
.idea .idea
*.suo
*.ntvs* # Ignore eleventy output when doing manual tests
*.njsproj _site/
*.sln
*.sw? package-lock.json
# Ignore test files
.cache
test/stubs-layout-cache/_includes/*.js

View file

@ -1 +0,0 @@
{}

View file

@ -1,3 +0,0 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

View file

@ -5,31 +5,23 @@ Tout les changements notables au projet sont consignés dans ce fichier, afin de
Ce format est basé sur la norme [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), Ce format est basé sur la norme [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
et ce projet adhère au [Semantic Versioning](https://semver.org/spec/v2.0.0.html). et ce projet adhère au [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## En cours ## En cours - Pélican 0.3.0 (beta 1)
### Erratum 3 Refonte global du site en Eleventy, et simplification des règles pour n'être plus qu'une base.
Avec cette version sort la première version adaptée à Rulebook 3 de Erratum, mon JDR de fantasy urbaine. Cette version fait une adaptation aux règles de rulebook 3 et profite des nouvelles possibilités offertes par la nouvelle itérations des règles de bases. Le livre de règle de Erratum a également été simplifié pour ne contenir que les règles de ce dernier.
### Ajoutés ### Ajoutés
- Ajout règles sur les dieux TBD
- Ajout d'une différenciation entre magies communes et rares
- Ajout des postures alter
### Modifiés ### Modifiés
- Adaptation générales aux règles de rulebook TBD
- Amélioration des vertues
- Déplacement dans un site externe du lore
- Division des signes et magies en plusieurs page pour profiter de la place supplémentaire
- Modification des signes pour utiliser le nouveau système de classe
- Rééquilibrage global des signes
- Refonte du verseau pour être basé sur les flux plus que le temps
- Refonte signes doublés
- Revue de la liste des heraults
### Pélican 0.2.0 (alpha 2) ### Supprimés
- [site] Retrait de tout les éléments spécifiques à un JDR en particulier.
## Pélican 0.2.0 (alpha 2)
Refonte global du site en vueJS Refonte global du site en vueJS

11
_data/metadata.js Normal file
View file

@ -0,0 +1,11 @@
module.exports = {
title: "Système D100 Pélican",
url: "https://pelicanjdr.kazhnuz.space/",
language: "fr",
description: "Une base de JDR basé sur le système D100",
author: {
name: "Kazhnuz",
email: "kazhnuz@kobold.cafe",
url: "https://kazhnuz.space/"
}
}

View file

@ -0,0 +1,18 @@
---
layout: layouts/parent.njk
---
<h1>{{ eleventyNavigation.key }}</h1>
<aside>
<div id="more-info">
<h2>Sommaire</h2>
{{ content | toc | safe }}
</div>
</aside>
<main id="skip">
<div>
{{ content | safe }}
</div>
</main>

View file

@ -0,0 +1,8 @@
---
layout: layouts/parent.njk
---
<main id="skip">
<div>
{{ content | safe }}
</div>
</main>

View file

@ -0,0 +1,45 @@
<!doctype html>
<html lang="{{ metadata.language }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title or metadata.title }}</title>
<meta name="description" content="{{ description or metadata.description }}">
{#- Atom and JSON feeds included by default #}
<link rel="alternate" href="/feed/feed.xml" type="application/atom+xml" title="{{ metadata.title }}">
<link rel="alternate" href="/feed/feed.json" type="application/json" title="{{ metadata.title }}">
<link rel="icon" type="image/x-icon" href="/favicon.svg">
{#- Uncomment this if youd like folks to know that you used Eleventy to build your site! #}
<meta name="generator" content="{{ eleventy.generator }}">
{%- css %}{% include "public/css/index.css" %}{% endcss %}
<style>{% getBundle "css" %}</style>
</head>
<body>
<svg class="d-none" alt="">
<symbol id="icon-bars" viewBox="0 0 32 32">
<path d="M30 24v3c0 .6-.4 1-1 1h-26c-.6 0-1-.4-1-1v-3c0-.6.4-1 1-1h26c.6 0 1 .4 1 1zM30 15v3c0 .6-.4 1-1 1h-26c-.6 0-1-.4-1-1v-3c0-.6.4-1 1-1h26c.6 0 1 .4 1 1zM30 6v3c0 .6-.4 1-1 1h-26c-.6 0-1-.4-1-1v-3c0-.6.4-1 1-1h26c.6 0 1 .4 1 1z"></path>
</symbol>
</svg>
<a href="#skip" class="visually-hidden">Skip to main content</a>
<nav id="sidebar">
{{ collections.all | eleventyNavigation | eleventyNavigationToHtml({anchorClass: "itemLink",activeAnchorClass: "active",activeListItemClass: "active",activeKey: eleventyNavigation.key, listClass: "nav", listItemClass: "item"}) | safe }}
</nav>
<div class="wrapper">
{{ content | safe }}
<footer><a href="https://quarante-douze.net/"><img src="/img/qdouze.gif" alt="" /><span class="visually-hidden">Site hébergé par Fanstuff Garden.</span></a> <a href="https://creativecommons.org/licenses/by-sa/4.0/"><img src="/img/cc-by-sa.png" alt="" /><span class="visually-hidden">Tout le contenu de cette page est sous licence Creatve Common Attribution - Partage à l'identique.</span></a></footer>
</div>
<button id="mobile-button" class="menu-button"><svg class="icon icon-bars" alt=""><use xlink:href="#icon-bars"></use></svg> <span class="sr-only">Afficher le menu</span></button>
<script src="/js/mobile-sidebar.js"></script>
</body>
</html>

View file

@ -0,0 +1,28 @@
---
layout: layouts/parent.njk
---
{# Only include the syntax highlighter CSS on blog posts #}
{%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %}
{%- css %}{% include "public/css/prism-diff.css" %}{%- endcss %}
<h1>{{ title }}</h1>
<ul class="post-metadata">
<li><time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time></li>
{%- for tag in tags | filterTagList %}
{%- set tagUrl %}/tags/{{ tag | slugify }}/{% endset %}
<li><a href="{{ tagUrl }}" class="post-tag">{{ tag }}</a>{%- if not loop.last %}, {% endif %}</li>
{%- endfor %}
</ul>
{{ content | safe }}
{%- if collections.posts %}
{%- set previousPost = collections.posts | getPreviousCollectionItem %}
{%- set nextPost = collections.posts | getNextCollectionItem %}
{%- if nextPost or previousPost %}
<ul class="links-nextprev">
{%- if previousPost %}<li>Previous: <a href="{{ previousPost.url }}">{{ previousPost.data.title }}</a></li>{% endif %}
{%- if nextPost %}<li>Next: <a href="{{ nextPost.url }}">{{ nextPost.data.title }}</a></li>{% endif %}
</ul>
{%- endif %}
{%- endif %}

9
_includes/postslist.njk Normal file
View file

@ -0,0 +1,9 @@
{%- css %}.postlist { counter-reset: start-from {{ (postslistCounter or postslist.length) + 1 }} }{% endcss %}
<ol reversed class="postlist">
{% for post in postslist | reverse %}
<li class="postlist-item{% if post.url == url %} postlist-item-active{% endif %}">
<a href="{{ post.url }}" class="postlist-link">{% if post.data.title %}{{ post.data.title }}{% else %}<code>{{ post.url }}</code>{% endif %}</a>
<time class="postlist-date" datetime="{{ post.date | htmlDateString }}">{{ post.date | readableDate("LLLL yyyy") }}</time>
</li>
{% endfor %}
</ol>

4
_includes/websites.md Normal file
View file

@ -0,0 +1,4 @@
- Réseau
- [Press Garden](https://press.fanstuff.garden)
- <a href="https://piaille.fr/@breezemedia" rel="me">Breeze Media (fedi)</a>
- <a href="https://bsky.app/profile/breezemedia.bsky.social" rel="me">Breeze Media (bsky)</a>

View file

@ -1,3 +1,10 @@
---
layout: layouts/home.njk
eleventyNavigation:
key: Accueil
order: 0
---
# Bienvenue sur le site de Pélican # Bienvenue sur le site de Pélican
Pélican est un système générique de jeu de rôle basé sur le système D100, ayant pour objectif de créer un système de jeu de rôle simple mais efficace, se basant sur les dés les plus générique dun rôliste. Il ne s'agit cependant que d'une base de système, à partir de laquelle vous pourrez construire des systèmes adaptés à votre univers et vos concepts. Pélican est un système générique de jeu de rôle basé sur le système D100, ayant pour objectif de créer un système de jeu de rôle simple mais efficace, se basant sur les dés les plus générique dun rôliste. Il ne s'agit cependant que d'une base de système, à partir de laquelle vous pourrez construire des systèmes adaptés à votre univers et vos concepts.

50
eleventy.config.drafts.js Normal file
View file

@ -0,0 +1,50 @@
function eleventyComputedPermalink() {
// When using `addGlobalData` and you *want* to return a function, you must nest functions like this.
// `addGlobalData` acts like a global data file and runs the top level function it receives.
return (data) => {
// Always skip during non-watch/serve builds
if(data.draft && !process.env.BUILD_DRAFTS) {
return false;
}
return data.permalink;
}
};
function eleventyComputedExcludeFromCollections() {
// When using `addGlobalData` and you *want* to return a function, you must nest functions like this.
// `addGlobalData` acts like a global data file and runs the top level function it receives.
return (data) => {
// Always exclude from non-watch/serve builds
if(data.draft && !process.env.BUILD_DRAFTS) {
return true;
}
return data.eleventyExcludeFromCollections;
}
};
module.exports.eleventyComputedPermalink = eleventyComputedPermalink;
module.exports.eleventyComputedExcludeFromCollections = eleventyComputedExcludeFromCollections;
module.exports = eleventyConfig => {
eleventyConfig.addGlobalData("eleventyComputed.permalink", eleventyComputedPermalink);
eleventyConfig.addGlobalData("eleventyComputed.eleventyExcludeFromCollections", eleventyComputedExcludeFromCollections);
let logged = false;
eleventyConfig.on("eleventy.before", ({runMode}) => {
let text = "Excluding";
// Only show drafts in serve/watch modes
if(runMode === "serve" || runMode === "watch") {
process.env.BUILD_DRAFTS = true;
text = "Including";
}
// Only log once.
if(!logged) {
console.log( `[11ty/eleventy-base-blog] ${text} drafts.` );
}
logged = true;
});
}

34
eleventy.config.images.js Normal file
View file

@ -0,0 +1,34 @@
const path = require("path");
const eleventyImage = require("@11ty/eleventy-img");
module.exports = eleventyConfig => {
function relativeToInputPath(inputPath, relativeFilePath) {
let split = inputPath.split("/");
split.pop();
return path.resolve(split.join(path.sep), relativeFilePath);
}
// Eleventy Image shortcode
// https://www.11ty.dev/docs/plugins/image/
eleventyConfig.addAsyncShortcode("image", async function imageShortcode(src, alt, widths, sizes) {
// Full list of formats here: https://www.11ty.dev/docs/plugins/image/#output-formats
// Warning: Avif can be resource-intensive so take care!
let formats = ["avif", "webp", "auto"];
let file = relativeToInputPath(this.page.inputPath, src);
let metadata = await eleventyImage(file, {
widths: widths || ["auto"],
formats,
outputDir: path.join(eleventyConfig.dir.output, "img"), // Advanced usage note: `eleventyConfig.dir` works here because were using addPlugin.
});
// TODO loading=eager and fetchpriority=high
let imageAttributes = {
alt,
sizes,
loading: "lazy",
decoding: "async",
};
return eleventyImage.generateHTML(metadata, imageAttributes);
});
};

146
eleventy.config.js Normal file
View file

@ -0,0 +1,146 @@
const { DateTime } = require("luxon");
const markdownItAnchor = require("markdown-it-anchor");
const pluginRss = require("@11ty/eleventy-plugin-rss");
const pluginSyntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
const pluginBundle = require("@11ty/eleventy-plugin-bundle");
const pluginNavigation = require("@11ty/eleventy-navigation");
const { EleventyRenderPlugin } = require("@11ty/eleventy");
const { EleventyHtmlBasePlugin } = require("@11ty/eleventy");
const pluginDrafts = require("./eleventy.config.drafts.js");
const pluginImages = require("./eleventy.config.images.js");
const pluginTOC = require('eleventy-plugin-toc');
module.exports = function(eleventyConfig) {
// Copy the contents of the `public` folder to the output folder
// For example, `./public/css/` ends up in `_site/css/`
eleventyConfig.addPassthroughCopy({
"./public/": "/",
"./node_modules/prismjs/themes/prism-okaidia.css": "/css/prism-okaidia.css"
});
// Run Eleventy when these files change:
// https://www.11ty.dev/docs/watch-serve/#add-your-own-watch-targets
// Watch content images for the image pipeline.
eleventyConfig.addWatchTarget("content/**/*.{svg,webp,png,jpeg}");
// App plugins
eleventyConfig.addPlugin(pluginDrafts);
eleventyConfig.addPlugin(pluginImages);
// Official plugins
eleventyConfig.addPlugin(pluginRss);
eleventyConfig.addPlugin(pluginSyntaxHighlight, {
preAttributes: { tabindex: 0 }
});
eleventyConfig.addPlugin(pluginNavigation);
eleventyConfig.addPlugin(EleventyHtmlBasePlugin);
eleventyConfig.addPlugin(EleventyRenderPlugin);
eleventyConfig.addPlugin(pluginBundle);
eleventyConfig.addPlugin(pluginTOC, {
tags: ['h2'],
wrapper: 'div'
});
// Filters
eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => {
// Formatting tokens for Luxon: https://moment.github.io/luxon/#/formatting?id=table-of-tokens
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(format || "dd LLLL yyyy");
});
eleventyConfig.addFilter('htmlDateString', (dateObj) => {
// dateObj input: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
return DateTime.fromJSDate(dateObj, {zone: 'utc'}).toFormat('yyyy-LL-dd');
});
// Get the first `n` elements of a collection.
eleventyConfig.addFilter("head", (array, n) => {
if(!Array.isArray(array) || array.length === 0) {
return [];
}
if( n < 0 ) {
return array.slice(n);
}
return array.slice(0, n);
});
// Return the smallest number argument
eleventyConfig.addFilter("min", (...numbers) => {
return Math.min.apply(null, numbers);
});
// Return all the tags used in a collection
eleventyConfig.addFilter("getAllTags", collection => {
let tagSet = new Set();
for(let item of collection) {
(item.data.tags || []).forEach(tag => tagSet.add(tag));
}
return Array.from(tagSet);
});
eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
return (tags || []).filter(tag => ["all", "nav", "post", "posts"].indexOf(tag) === -1);
});
// Customize Markdown library settings:
eleventyConfig.amendLibrary("md", mdLib => {
mdLib.use(markdownItAnchor, {
permalink: markdownItAnchor.permalink.ariaHidden({
placement: "after",
class: "header-anchor",
symbol: "#",
ariaHidden: false,
}),
level: [1,2,3,4],
slugify: eleventyConfig.getFilter("slugify")
});
});
// Features to make your build faster (when you need them)
// If your passthrough copy gets heavy and cumbersome, add this line
// to emulate the file copy on the dev server. Learn more:
// https://www.11ty.dev/docs/copy/#emulate-passthrough-copy-during-serve
// eleventyConfig.setServerPassthroughCopyBehavior("passthrough");
return {
// Control which files Eleventy will process
// e.g.: *.md, *.njk, *.html, *.liquid
templateFormats: [
"md",
"njk",
"html",
"liquid",
],
// Pre-process *.md files with: (default: `liquid`)
markdownTemplateEngine: "njk",
// Pre-process *.html files with: (default: `liquid`)
htmlTemplateEngine: "njk",
// These are all optional:
dir: {
input: "content", // default: "."
includes: "../_includes", // default: "_includes"
data: "../_data", // default: "_data"
output: "_site"
},
// -----------------------------------------------------------------
// Optional items:
// -----------------------------------------------------------------
// If your site deploys to a subdirectory, change `pathPrefix`.
// Read more: https://www.11ty.dev/docs/config/#deploy-to-a-subdirectory-with-a-path-prefix
// When paired with the HTML <base> plugin https://www.11ty.dev/docs/plugins/html-base/
// it will transform any absolute URLs in your HTML to include this
// folder name and does **not** affect where things go in the output folder.
pathPrefix: "/",
};
};

1
env.d.ts vendored
View file

@ -1 +0,0 @@
/// <reference types="vite/client" />

View file

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bienvenue sur Pélican</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

5496
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,39 +1,40 @@
{ {
"name": "pelican-jdr", "name": "pelican-jdr",
"version": "0.0.0", "version": "0.2.0",
"private": true, "description": "Un systeme de jdr sous forme d'un site 11ty",
"scripts": { "scripts": {
"dev": "vite", "build": "npx @11ty/eleventy",
"build": "run-p type-check build-only", "build-ghpages": "npx @11ty/eleventy --pathprefix=/eleventy-base-blog/",
"preview": "vite preview", "start": "npx @11ty/eleventy --serve --quiet",
"build-only": "vite build", "debug": "DEBUG=Eleventy* npx @11ty/eleventy",
"type-check": "vue-tsc --noEmit", "debugstart": "DEBUG=Eleventy* npx @11ty/eleventy --serve --quiet",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore" "benchmark": "DEBUG=Eleventy:Benchmark* npx @11ty/eleventy"
},
"repository": {
"type": "git",
"url": "git://git.kobold.cafe/jdr-et-univers/pelicanjdr"
},
"author": {
"name": "Kazhnuz",
"email": "kazhnuz@kobold.cafe",
"url": "https://kazhnuz.space"
},
"license": "CC BY-SA",
"engines": {
"node": ">=14"
},
"homepage": "https://pelicanjdr.kazhnuz.space",
"devDependencies": {
"@11ty/eleventy": "^2.0.1",
"@11ty/eleventy-img": "^3.1.0",
"@11ty/eleventy-navigation": "^0.3.5",
"@11ty/eleventy-plugin-bundle": "^1.0.4",
"@11ty/eleventy-plugin-rss": "^1.2.0",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
"luxon": "^3.3.0",
"markdown-it-anchor": "^8.6.7"
}, },
"dependencies": { "dependencies": {
"@types/lodash": "^4.14.191", "eleventy-plugin-toc": "^1.1.5"
"@types/marked": "^4.0.8",
"axios": "^1.3.2",
"lodash": "^4.17.21",
"marked": "^4.2.12",
"pinia": "^2.0.28",
"sass": "^1.58.0",
"vue": "^3.2.45",
"vue-router": "^4.1.6"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.1.4",
"@types/node": "^18.11.12",
"@vitejs/plugin-vue": "^4.0.0",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.0",
"@vue/tsconfig": "^0.1.3",
"eslint": "^8.22.0",
"eslint-plugin-vue": "^9.3.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.7.1",
"typescript": "~4.7.4",
"vite": "^4.0.0",
"vue-tsc": "^1.0.12"
} }
} }

412
public/css/index.css Normal file
View file

@ -0,0 +1,412 @@
:root {
--color-gray-20: #e0e0e0;
--color-gray-50: #C0C0C0;
--color-gray-90: #002b36;
--sidebar-width: 280px;
--main-width: 800px;
/* --text-color is assigned to --color-gray-_ above */
--text-color-link: #4c2512;
--text-color-link-active: #4c2512;
--text-color-link-visited: #4c2512;
--text-color-title: #66350F;
--background-color: #FDF7E7;
--background-menu: #002b36;
--text-color: var(--color-gray-90);
--font-family: Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Cantarell,
Roboto,
Oxygen,
Ubuntu,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
--font-family-monospace: Consolas, Menlo, Monaco, Andale Mono WT, Andale Mono, Lucida Console, Lucida Sans Typewriter, DejaVu Sans Mono, Bitstream Vera Sans Mono, Liberation Mono, Nimbus Mono L, Courier New, Courier, monospace;
--font-family-logo: serif;
--font-family-title:serif;
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0 auto;
min-height:100%;
font-family: var(--font-family);
color: var(--text-color);
font-size: 16px;
}
body {
padding: 24px;
}
.wrapper {
max-width: var(--main-width);
margin: auto;
position: relative;
}
html {
overflow-y: scroll;
background-color: var(--background-color);
}
/* https://www.a11yproject.com/posts/how-to-hide-content/ */
.visually-hidden {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
a[href] {
color: var(--text-color-link);
text-decoration: underline dashed 1px;
border-radius: 0.1rem;
text-decoration: underline dashed 1px;
text-underline-offset: 0.1rem;
}
a[href]:visited {
color: var(--text-color-link-visited);
}
a[href]:hover,
a[href]:active {
color: var(--text-color-link-active);
background-color: rgba(0,0,0,0.1);
text-decoration: none;
}
blockquote {
opacity: 75%;
border-left: 3px solid currentColor;
padding-left: 12px;
}
/* Direct Links / Markdown Headers */
.header-anchor {
text-decoration: none;
font-style: normal;
font-size: 1em;
margin-left: .1em;
}
a[href].header-anchor,
a[href].header-anchor:visited {
color: transparent;
}
a[href].header-anchor:focus,
a[href].header-anchor:hover {
text-decoration: underline;
}
a[href].header-anchor:focus,
:hover > a[href].header-anchor {
color: #aaa;
}
header {
background:center center url("/img/back.jpg");
background-repeat: no-repeat;
background-size: cover;
border-radius:3px;
height:240px;
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.8);
display:flex;
align-items: center;
justify-content: center;
}
h1 {
color: var(--text-color-title);
font-family: var(--font-family-title);
font-size: 3rem;
line-height: 1;
}
header h1 {
text-align: center;
}
header h1 a[href] {
font-size:5.5rem;
text-shadow: -2px -2px 0 #000,
0 -2px 0 #000,
2px -2px 0 #000,
2px 0 0 #000,
2px 2px 0 #000,
0 2px 0 #000,
-2px 2px 0 #000,
-2px 0 0 #000,
.05em .1em 0 #000;
font-weight: 900;
color:white!important;
text-decoration: none;
text-transform: uppercase;
display: block;
line-height: 1;
margin: 0;
padding: 0;
}
.quadrillage {
display:grid;
grid-template-columns : 1fr 1fr;
column-gap: 1rem;
}
#sidebar {
position: fixed;
top: 0;
left: 0;
border-right: 1px solid black;
background-color: var(--background-menu);
padding:12px;
height:100%;
box-shadow: 1px 0px 1px 0px rgba(0,0,0,0.4);
}
#sidebar.shown {
left: 0;
}
#sidebar > ul > li {
margin:0;
padding:3px;
}
main {
line-height:1.5rem;
margin: auto;
}
main img {
display: block;
max-width: 100%;
height: auto;
margin: auto;
}
.card,
#sidebar ul>li,
#links ul>li {
background-color: var(--background-menu);
}
#sidebar ul > li,
#links ul > li {
list-style: none;
font-weight: bold;
}
#more-info ol > li,
#more-info ul > li {
list-style: none;
}
#sidebar ul > li li,
#links ul>li li,
#more-info li {
border-radius:0px;
padding:0px;
margin:0px;
font-weight: normal;
border:0;
box-shadow: none;
}
ul.nav,
#sidebar ul li ul,
#links ul li ul,
#more-info ol {
padding:0;
margin:0;
list-style: none;
}
#sidebar ul li a,
#more-info ol li a {
display:block;
width:100%;
text-decoration:dashed;
color: white;
border-radius:3px;
padding:6px;
}
#more-info ol li a {
color: var(--text-color);
}
#links ul li > p {
padding: 3px;
margin:0;
}
#more-info h2 {
padding: 3px;
margin: 0;
font-size: 1rem;
}
#sidebar ul li li a,
#links ul li li a,
#more-info ol li a {
padding-left:18px;
}
#sidebar ul li a.active,
#sidebar ul li a:hover {
background-color: rgba(255, 255, 255, 0.3);
}
#more-info ol li a:hover,
#more-info ol li a.active {
background-color:rgba(0,0,0,0.1);
}
aside {
position: absolute;
top: 1px;
right: -264px;
height: 100%;
}
#more-info {
position: sticky;
top:12px;
border-left: 3px solid var(--text-color-title);
padding: 6px;
}
#sidebar {
min-width:var(--sidebar-width);
width:var(--sidebar-width);
z-index:10;
}
#more-info {
min-width: 240px;
width: 240px;
}
footer {
text-align:right;
width: 100%;
}
iframe {
border: none;
}
.menu-button {
display: none;
}
@media screen and (max-width: 1400px) {
.wrapper {
margin-left: var(--sidebar-width);
position: relative;
}
aside {
position: static !important;
}
#more-info {
position: static;
border-left: 3px solid #e03131;
padding: 6px;
}
}
.d-none {
display: none;
}
.icon {
display: inline-block;
width: 1em;
height: 1em;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
color: currentColor;
position: relative;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
opacity: 0;
transition-delay: .8s;
transition-property: opacity;
transition-duration: 0.2s;
}
@media screen and (max-width: 1000px) {
#sidebar {
left: calc(-1* var(--sidebar-width));
}
.wrapper {
margin: .5rem;
}
.menu-button {
position: fixed;
bottom: 24px;
right: 24px;
background-color: rgba(0, 0, 0, 0.4);
color: white;
padding: 0.75em;
border: none;
font-size: 1.2rem;
display: flex;
align-content: center;
justify-content: center;
aspect-ratio: 1;
border-radius: 999px;
z-index: 12;
}
.menu-button:hover {
background-color: var(--text-color-link);
}
}
@media screen and (max-width: 600px) {
header h1 a[href] {
font-size: 5rem;
}
}
@media screen and (max-width: 460px) {
header h1 a[href] {
font-size: 4.5rem;
}
}
@media screen and (max-width: 390px) {
header h1 a[href] {
font-size: 4rem;
}
}

View file

@ -0,0 +1,10 @@
document.getElementById('mobile-button').addEventListener('click', function () {
const sidebar = document.getElementById('sidebar');
if (!sidebar.classList.contains('shown')) {
sidebar.classList.remove('hidden');
sidebar.classList.add('shown');
} else {
sidebar.classList.remove('shown');
sidebar.classList.add('hidden');
}
});

View file

@ -1,32 +0,0 @@
<script setup lang="ts">
import { RouterView } from "vue-router";
import TopBar from "./components/layout/TopBar.vue";
import SideBar from "./components/layout/SideBar.vue";
import TableOfContent from "./components/layout/TableOfContent.vue";
import { useConfigStore } from "./stores/config";
import { onMounted, ref } from "vue";
import axios from "axios";
const store = useConfigStore();
const loaded = ref(false);
onMounted(() => {
axios.get(`/pelican.json`).then((response) => {
store.setConfig(response.data);
loaded.value = true;
});
});
</script>
<template>
<TopBar id="topbar" />
<div id="wrapper">
<SideBar />
<div id="page">
<div id="content" class="pt-1">
<RouterView v-if="loaded" />
</div>
</div>
<TableOfContent />
</div>
</template>

View file

@ -1,74 +0,0 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
position: relative;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition: color 0.5s, background-color 0.5s;
line-height: 1.6;
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69" xmlns:v="https://vecta.io/nano"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

Before

Width:  |  Height:  |  Size: 308 B

View file

@ -1,35 +0,0 @@
@import './base.css';
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
}

View file

@ -1,52 +0,0 @@
<script setup lang="ts">
import { ref, onMounted, onBeforeUpdate } from "vue";
import axios from "axios";
import MarkdownRender from "./markdown/MarkdownRender.vue";
const props = defineProps<{
path: string;
order?: number;
}>();
const loadedPage = ref("");
const markdown = ref("");
function refresh() {
const markdownFileUrl = `/${props.path}.md`;
if (loadedPage.value === markdownFileUrl) {
return;
}
loadedPage.value = markdownFileUrl;
console.log(`Chargement de l'URL ${markdownFileUrl}`);
axios
.get(markdownFileUrl)
.then((response) => {
markdown.value = response.data;
})
.catch(
() =>
(markdown.value =
"# 404 Not Found \n \n La page recherchée n'a pas pu être trouvée")
);
}
onMounted(() => {
refresh();
});
onBeforeUpdate(() => {
refresh();
});
</script>
<template>
<article>
<MarkdownRender
:markdown="markdown"
:order="order"
v-if="markdown !== ''"
></MarkdownRender>
<slot></slot>
</article>
</template>

View file

@ -1,36 +0,0 @@
<script setup lang="ts">
import { useConfigStore } from "@/stores/config";
import { computed } from "vue";
const store = useConfigStore();
const sidebar = computed(() => {
return store.getSidebar() ?? [{ title: "", id: 0, links: [] }];
});
const linkBase = computed(() => {
if (store.isJdrLoaded()) {
return `jdr/${store.currentJdr}`;
} else {
return `jdr`;
}
});
</script>
<template>
<aside id="sidebar" class="bg-dark fg-light menu">
<h1 class="title-5 fg-light">Navigation</h1>
<ul v-for="item in sidebar" :key="item.id">
<div class="menu-divider" v-if="item.title">{{ item.title }}</div>
<li v-for="(link, index) in item.links" :key="index">
<router-link
:to="`/${linkBase}/${link.path}`"
class="menu-item"
:replace="true"
v-if="!link.isHidden"
>{{ link.title }}</router-link
>
</li>
</ul>
</aside>
</template>

View file

@ -1,22 +0,0 @@
<script setup lang="ts">
import { useTocStore } from "../../stores/toc";
import { computed } from "vue";
const toc = useTocStore();
const tocList = computed(() => {
return toc.getToc();
});
</script>
<template>
<div class="card" id="toc" v-if="tocList.length > 1">
<div class="card-header bg-primary">Sommaire</div>
<ul class="menu fg-dark">
<li v-for="(tocLine, index) in tocList" :key="index">
<router-link :to="`#${tocLine.anchor}`"
><span v-html="tocLine.text"></span
></router-link>
</li>
</ul>
</div>
</template>

View file

@ -1,27 +0,0 @@
<template>
<header class="bg-primary" id="topbar">
<div class="menu toolbar fg-light d-block d-flex-sm">
<ul>
<li><router-link to="/" class="menu-item">Home</router-link></li>
<li>
<router-link to="/about" class="menu-item">À propos</router-link>
</li>
</ul>
<ul class="f-end">
<li>
<router-link to="/fiches" class="menu-item">Fiches</router-link>
</li>
<li>
<a
href="https://git.kobold.cafe/pelican/pelican-jdr"
class="menu-item"
>Sources</a
>
</li>
<li>
<a href="https://kazhnuz.space" class="menu-item">Retour</a>
</li>
</ul>
</div>
</header>
</template>

View file

@ -1,122 +0,0 @@
<script setup lang="ts">
import { ref, onMounted, onBeforeUpdate, watch } from "vue";
import { marked } from "marked";
import { useTocStore } from "../../stores/toc";
import { useRoute } from "vue-router";
import { useConfigStore } from "@/stores/config";
const props = defineProps<{
markdown: string;
order?: number;
}>();
const htmlContent = ref("");
var specialQuote: Map<string, { class: string; text: string }> = new Map();
specialQuote.set("NOTE", { class: "info", text: "Information :" });
specialQuote.set("SUCCESS", { class: "success", text: "Success :" });
specialQuote.set("WARNING", { class: "warning", text: "Warning :" });
specialQuote.set("DANGER", { class: "danger", text: "Danger :" });
var renderer = new marked.Renderer();
const toc = useTocStore();
const config = useConfigStore();
const route = useRoute();
var tocNbr = 1;
renderer.heading = function (text, level, raw) {
var anchor = "#" + raw.toLowerCase().replace(/[^\w]+/g, "-");
if (level === 2) {
toc.addTocLine(route.path, {
anchor: anchor,
order: (props.order ?? 1) * 100 + tocNbr,
text: text,
});
tocNbr++;
}
return `<h${level} id="${anchor}">${text}</h${level}>\n`;
};
renderer.blockquote = function (quote) {
var bqClass = "";
var newQuote = quote;
for (const [key, quoteData] of specialQuote) {
if (quote.includes(`[!${key}]`)) {
bqClass = `bg-${quoteData?.class}`;
newQuote = newQuote.replace(
`[!${key}]`,
`<strong>${quoteData?.text}</strong>`
);
}
}
newQuote = newQuote.replace("\n", "<br />");
return `<blockquote class="${bqClass}">${newQuote}</blockquote>`;
};
const variable = {
name: "variable",
level: "inline", // Is this a block-level or inline-level tokenizer?
start(src: string) {
return src.match(/{{/)?.index;
}, // Hint to Marked.js to stop and check for a match
tokenizer(
src: string
): { type: string; raw: string; [index: string]: any } | undefined {
const rule = /\{\{([A-Za-z0-9_]+)\}\}/; // Regex for the complete token, anchor to string start
const match = rule.exec(src);
if (match) {
return {
// Token to generate
type: "variable", // Should match "name" above
raw: match[0], // Text to consume from the source
["varName"]: match[1],
};
}
},
renderer(token: { type: string; raw: string; [index: string]: any }): string {
const varName = token["varName"] as string | null;
const value = `${config.getVar(varName ?? "")}`;
return value;
},
};
marked.setOptions({
renderer: renderer,
});
marked.use({ extensions: [variable] });
function render() {
tocNbr = 1;
if (htmlContent.value === "") {
htmlContent.value = marked.parse(props.markdown);
}
}
function forceRender(markdown: string) {
htmlContent.value = marked.parse(markdown);
}
onMounted(() => {
render();
});
onBeforeUpdate(() => {
render();
});
watch(
() => props.markdown,
(newMd) => {
forceRender(newMd);
}
);
</script>
<template>
<article>
<div v-html="htmlContent" class="markdown"></div>
<slot></slot>
</article>
</template>

View file

@ -1,50 +0,0 @@
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import type { TableField, TableItem } from "@/utils/tables/types";
import type { PropType } from "vue";
import axios from "axios";
import TableRenderer from "./TableRenderer.vue";
const props = defineProps({
fields: {
type: Array as PropType<TableField[]>,
default: () => [],
},
files: {
type: Array as PropType<string[]>,
default: () => [],
},
category: {
type: String,
default: "",
},
});
const toLoad = ref(1);
const items = ref([] as TableItem[]);
onMounted(() => {
setTimeout(() => {
refresh();
}, 100);
});
function refresh() {
toLoad.value = props.files.length;
for (const file of props.files) {
const listItems = `/jdr/${props.category}/${file}.json`;
axios.get(listItems).then((response) => {
toLoad.value = toLoad.value - 1;
items.value = items.value.concat(response.data);
});
}
}
</script>
<template>
<TableRenderer
:fields="fields"
:items="items"
v-if="toLoad === 0"
></TableRenderer>
</template>

View file

@ -1,141 +0,0 @@
<script lang="ts" setup>
import { computed, reactive, onMounted } from "vue";
import PaginatedFilteredTable from "@/utils/tables/PaginatedFilteredTable";
import type { TableField, TableItem } from "@/utils/tables/types";
import type { PropType } from "vue";
import PageList from "./pagination/PageList.vue";
import TagList from "./TagList.vue";
const props = defineProps({
fields: {
type: Array as PropType<TableField[]>,
default: () => [],
},
items: {
type: Array as PropType<TableItem[]>,
default: () => [],
},
});
const DEFAULT_MAX_ITEM_BY_PAGE = 10;
const table = reactive(new PaginatedFilteredTable(DEFAULT_MAX_ITEM_BY_PAGE));
const filtersFieldMap = computed(() => {
return table?.filteredTable?.filtersFieldMap;
});
const displayedFieldKeys = computed(() => {
return table?.filteredTable?.table.displayedFieldKeys;
});
const paginatedList = computed(() => {
return table?.items;
});
onMounted(() => {
table.fields = props.fields;
table.addItems(props.items);
table.currentPage = 0;
});
function switchFilter(filterSet: string | number, filterName: string | number) {
table.switchFilter(filterSet as string, filterName as string);
}
function removeFilter(filterSet: string | number) {
table.removeAllFilters(filterSet as string);
}
const currentPage = computed(() => {
return table?.currentPage;
});
const getTotalPage = computed(() => {
return table?.pageNumber;
});
function goTo(page: number) {
table.currentPage = page - 1;
}
</script>
<template>
<div class="d-flex f-between">
<div>
<input
v-model="table.textSearch"
class="btn-small"
placeholder="Rechercher"
/>
</div>
<div class="d-flex f-end">
<TagList
:filtersFieldMap="filtersFieldMap"
@remove-filter="removeFilter"
@switch-filter="switchFilter"
></TagList>
</div>
</div>
<table class="mb-0 table-auto">
<thead>
<tr>
<th v-for="field in fields" :key="field.key">
{{ field.label }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) of paginatedList" :key="index">
<td v-for="(key, index2) in displayedFieldKeys" :key="index2">
{{ item[key] }}
</td>
</tr>
</tbody>
</table>
<div class="d-flex f-between">
<div>
<span>Lignes par page </span>
<select
class="btn-small btn-outline"
v-model.number="table.pageLenght"
@change="table.currentPage = 0"
>
<option>5</option>
<option>10</option>
<option>15</option>
<option>25</option>
<option>50</option>
</select>
</div>
<PageList
:current-page="currentPage + 1"
:page-nbr="getTotalPage + 1"
@set-page="goTo"
></PageList>
</div>
</template>
<style lang="scss" scoped>
.small-text {
font-size: 0.8rem;
padding-bottom: 0.5rem;
}
table:not(:last-child) {
font-size: 0.8rem;
margin-bottom: 0.5rem;
}
.pages {
font-weight: 600;
}
input,
.btn-outline {
border: 1px solid rgba(0, 0, 0, 0.2);
margin-bottom: 0.5rem;
margin-left: 0;
margin-right: 0;
}
</style>

View file

@ -1,112 +0,0 @@
<script lang="ts" setup>
import type { FilterFieldsMap } from "@/utils/tables/types";
import { ref, defineProps, computed } from "vue";
const props = defineProps<{
filtersFieldMap: FilterFieldsMap;
}>();
const emit = defineEmits(["switchFilter", "removeFilter"]);
const computedFieldMap = computed(() => {
return props.filtersFieldMap ?? [];
});
const haveElement = computed(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const _key in props.filtersFieldMap) {
return true;
}
return false;
});
const tagNumber = computed(() => {
var i = 0;
for (const key in props.filtersFieldMap) {
const filters = props.filtersFieldMap[key].filters;
for (const key2 in filters) {
if (filters[key2] === true) {
i++;
}
}
}
return i;
});
const showPopover = ref(false);
function switchFilter(filterSet: string | number, filterName: string | number) {
emit("switchFilter", filterSet as string, filterName as string);
}
function removeFilter(filterSet: string | number) {
emit("removeFilter", filterSet as string);
}
</script>
<template>
<div class="taglist" v-if="haveElement">
<button class="btn-small btn-outline" @click="showPopover = !showPopover">
<strong>Tags</strong>
<span
class="badge pills"
:class="{ 'bg-grey': tagNumber <= 0, 'bg-secondary': tagNumber > 0 }"
>{{ tagNumber }} tag(s)</span
>
</button>
<div class="card menu fg-dark" v-if="showPopover">
<div
class="small-text"
v-for="(filter, key) in computedFieldMap"
:key="key"
>
<p class="m-0 p-0">
<strong>{{ filter.title }} : </strong>
</p>
<div>
<button
v-for="(isTrue, filterName) in filter.filters"
:key="filterName"
class="btn-small mb-0"
:class="{ 'btn-grey': !isTrue, 'btn-primary': isTrue }"
@click="switchFilter(key, filterName)"
>
{{ filterName }}
</button>
<button class="btn-small btn-danger mb-0" @click="removeFilter(key)">
Vider filtres
</button>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.taglist {
position: relative;
}
.card {
position: absolute;
width: 480px;
box-shadow: 0px 1px 1px 1px rgba(0, 0, 0, 0.3);
background-color: white;
right: 0;
}
.btn-outline {
border: 1px solid rgba(0, 0, 0, 0.2);
&:hover {
background-color: rgba(0, 0, 0, 0.05);
}
margin-bottom: 0.5rem;
margin-left: 0;
margin-right: 0;
}
.badge {
font-size: 0.8em;
border-radius: 999px;
}
</style>

View file

@ -1,22 +0,0 @@
<script setup lang="ts">
import { computed } from "vue";
const props = defineProps<{
page: number;
currentPage: number;
}>();
const isPage = computed(() => {
return props.page === props.currentPage;
});
</script>
<template>
<button
class="btn-small btn-pagination"
:class="{ 'btn-secondary': !isPage, 'bg-primary': isPage }"
:disabled="isPage"
>
{{ page }}
</button>
</template>

View file

@ -1,161 +0,0 @@
<script setup lang="ts">
import { computed } from "vue";
import PageButton from "./PageButton.vue";
const PAGE_NUMBER = 7;
const props = defineProps<{
pageNbr: number;
currentPage: number;
}>();
const emit = defineEmits(["setPage"]);
const pageToDraw = computed(() => {
return Math.min(props.pageNbr, PAGE_NUMBER);
});
const isAtStart = computed(() => {
return props.currentPage < 4;
});
const isAtEnd = computed(() => {
return props.currentPage > props.pageNbr - 2;
});
function setPage(page: number) {
emit("setPage", page);
}
</script>
<template>
<div>
<button
class="btn-small btn-navig"
:disabled="currentPage <= 1"
:class="{ 'btn-secondary': currentPage > 1, 'bg-grey': currentPage <= 1 }"
@click="setPage(currentPage - 1)"
>
</button>
<span v-if="pageNbr <= PAGE_NUMBER">
<span v-for="index in pageToDraw" :key="index">
<PageButton
@click="setPage(index)"
:current-page="currentPage"
:page="index"
></PageButton>
</span>
</span>
<span v-else-if="isAtStart">
<PageButton
:current-page="currentPage"
:page="1"
@click="setPage(1)"
></PageButton>
<PageButton
:current-page="currentPage"
:page="2"
@click="setPage(2)"
></PageButton>
<PageButton
:current-page="currentPage"
:page="3"
@click="setPage(3)"
></PageButton>
<PageButton
:current-page="currentPage"
:page="4"
@click="setPage(4)"
></PageButton>
<PageButton
:current-page="currentPage"
:page="5"
@click="setPage(5)"
></PageButton>
<button disabled class="btn-small btn-pagination bg-grey disabled">
</button>
<PageButton
:current-page="currentPage"
:page="pageNbr"
@click="setPage(pageNbr)"
></PageButton>
</span>
<span v-else-if="isAtEnd">
<PageButton
:current-page="currentPage"
:page="1"
@click="setPage(1)"
></PageButton>
<button disabled class="btn-small bg-grey btn-pagination disabled">
</button>
<PageButton
:current-page="currentPage"
:page="pageNbr - 4"
@click="setPage(pageNbr - 4)"
></PageButton>
<PageButton
:current-page="currentPage"
:page="pageNbr - 3"
@click="setPage(pageNbr - 3)"
></PageButton>
<PageButton
:current-page="currentPage"
:page="pageNbr - 2"
@click="setPage(pageNbr - 2)"
></PageButton>
<PageButton
:current-page="currentPage"
:page="pageNbr - 1"
@click="setPage(pageNbr - 1)"
></PageButton>
<PageButton
:current-page="currentPage"
:page="pageNbr"
@click="setPage(pageNbr)"
></PageButton>
</span>
<span v-else>
<PageButton
:current-page="currentPage"
:page="1"
@click="setPage(1)"
></PageButton>
<button disabled class="btn-small bg-grey btn-pagination disabled">
</button>
<PageButton
:current-page="currentPage"
:page="currentPage - 1"
@click="setPage(currentPage - 1)"
></PageButton>
<PageButton :current-page="currentPage" :page="currentPage"></PageButton>
<PageButton
:current-page="currentPage"
:page="currentPage + 1"
@click="setPage(currentPage + 1)"
></PageButton>
<button disabled class="btn-small bg-grey btn-pagination disabled">
</button>
<PageButton
:current-page="currentPage"
:page="pageNbr"
@click="setPage(pageNbr)"
></PageButton>
</span>
<button
class="btn-small btn-navig"
:disabled="currentPage >= pageNbr"
:class="{
'btn-secondary': currentPage < pageNbr,
'bg-grey': currentPage >= pageNbr,
}"
@click="setPage(currentPage + 1)"
>
</button>
</div>
</template>

View file

@ -1,60 +0,0 @@
const objectFields = [
{ key: "nom", label: "Nom", canBeSearched: true },
{ key: "type", label: "Type", canBeFiltered: true },
{ key: "rarete", label: "Rareté", canBeFiltered: true },
{ key: "effet", label: "Effet", canBeSearched: true },
{ key: "cout", label: "Cout" },
];
const equipMainsFields = [
{ key: "nom", label: "Nom", canBeSearched: true },
{ key: "type", label: "Type", canBeFiltered: true },
{ key: "mains", label: "Mains", canBeFiltered: true },
{ key: "effet", label: "Effet", canBeSearched: true },
{ key: "force", label: "Force" },
{ key: "cout", label: "Cout" },
];
const tenuesFields = [
{ key: "nom", label: "Nom", canBeSearched: true },
{ key: "effet", label: "Effet", canBeSearched: true },
{ key: "armure", label: "Armure" },
{ key: "cout", label: "cout" },
];
const effetsFields = [
{ key: "nom", label: "Nom", canBeSearched: true },
{ key: "effet", label: "Effet", canBeSearched: true },
{ key: "surcout", label: "Surcout" },
];
const accessoiresFields = [
{ key: "nom", label: "Nom", canBeSearched: true },
{ key: "effet", label: "Effet", canBeSearched: true },
{ key: "cout", label: "Cout" },
];
const elementsFields = [
{ key: "nom", label: "Nom", canBeSearched: true },
{ key: "type", label: "Type", canBeFiltered: true },
{ key: "effet", label: "Effet", canBeSearched: true },
{ key: "oppose", label: "Opposé" },
];
const terrainsFields = [
{ key: "nom", label: "Nom", canBeSearched: true },
{ key: "type", label: "Type", canBeFiltered: true },
{ key: "nomTerrain", label: "Nom du Terrain", canBeSearched: true },
{ key: "effetTerrain", label: "Effet", canBeSearched: true },
{ key: "oppose", label: "Affaibli" },
];
export {
objectFields,
equipMainsFields,
tenuesFields,
effetsFields,
accessoiresFields,
elementsFields,
terrainsFields,
};

View file

@ -1,14 +0,0 @@
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import router from "./router";
import "./styles/style.scss";
const app = createApp(App);
app.use(createPinia());
app.use(router);
app.mount("#app");

View file

@ -1,62 +0,0 @@
import { createRouter, createWebHashHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
import RuleView from "../views/RuleView.vue";
import JdrView from "../views/JdrView.vue";
import FichesView from "../views/FichesView.vue";
import ObjetsView from "../views/ObjetsView.vue";
import EquipView from "../views/EquipView.vue";
import ElementsView from "../views/ElementsView.vue";
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
name: "home",
component: HomeView,
},
{
path: "/jdr/:jdr/rules/:category/:filepath",
component: RuleView,
},
{
path: "/jdr/:jdr/",
component: JdrView,
},
{
path: "/fiches",
component: FichesView,
},
{
path: "/about",
name: "about",
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import("../views/AboutView.vue"),
},
{
path: "/jdr/:jdr/inventaire/objets/",
component: ObjetsView,
},
{
path: "/jdr/:jdr/inventaire/equipements/",
component: EquipView,
},
{
path: "/jdr/:jdr/elements/",
component: ElementsView,
},
],
scrollBehavior(to, from, savedPosition) {
if (to.hash) {
return {
el: to.hash,
behavior: "smooth",
top: 64,
};
}
},
});
export default router;

View file

@ -1,95 +0,0 @@
import { ref } from "vue";
import { defineStore } from "pinia";
import type PelicanConfig from "@/types/PelicanConfig";
import type LinkList from "@/types/LinkList";
import type JdrConfig from "@/types/JdrConfig";
import axios from "axios";
import { cloneDeep } from "lodash";
export const useConfigStore = defineStore("config", () => {
const config = ref(null as PelicanConfig | null);
const currentJdr = ref("");
const jdrConfig = ref(null as JdrConfig | null);
const sidebar = ref([{ id: 0, links: [] }] as LinkList[]);
function computeSidebar() {
const baseSideBar = cloneDeep(config.value?.sidebar ?? []);
for (const cat of jdrConfig.value?.sidebar ?? []) {
const sidebarItem = baseSideBar.find((a) => a.id === cat.id);
if (sidebarItem) {
sidebarItem.links = sidebarItem.links.concat(cat.links);
} else {
baseSideBar.push(cat);
}
}
for (const hideLink of jdrConfig.value?.hideLinks ?? []) {
const sidebarItem = baseSideBar.find((a) => a.id === hideLink.menu);
if (sidebarItem) {
const link = sidebarItem.links.find((a) => a.path === hideLink.link);
if (link) {
link.isHidden = true;
}
}
}
return baseSideBar;
}
function setConfig(newConfig: PelicanConfig) {
config.value = newConfig;
sidebar.value = computeSidebar();
}
function loadJdr(newJdr: string) {
if (newJdr !== currentJdr.value) {
axios.get(`/jdr/${newJdr}.json`).then((response) => {
jdrConfig.value = response.data;
currentJdr.value = newJdr;
sidebar.value = computeSidebar();
});
}
}
function resetJdr() {
jdrConfig.value = null;
currentJdr.value = "";
sidebar.value = [{ id: 0, links: [] }];
}
function isJdrLoaded(): boolean {
return currentJdr.value !== "";
}
function getSidebar(): LinkList[] {
if (isJdrLoaded()) {
return sidebar.value;
} else {
return (
config.value?.jdr?.sort((a, b) => a.id - b.id) ?? [{ id: 0, links: [] }]
);
}
}
function getVar(name?: string): string {
if (name) {
for (const varData of jdrConfig?.value?.vars ?? []) {
if (varData.name === name) {
return varData.value;
}
}
}
return "";
}
return {
config,
currentJdr,
jdrConfig,
setConfig,
getSidebar,
loadJdr,
resetJdr,
isJdrLoaded,
getVar,
};
});

View file

@ -1,27 +0,0 @@
import { ref } from "vue";
import { defineStore } from "pinia";
import type TocLine from "@/types/TocLine";
export const useTocStore = defineStore("toc", () => {
const currentPage = ref("");
const tocLines = ref([] as TocLine[]);
function addTocLine(page: string, line: TocLine) {
if (page !== currentPage.value) {
tocLines.value = [];
currentPage.value = page;
}
tocLines.value.push(line);
}
function getToc(): TocLine[] {
return tocLines.value.sort((a, b) => a.order - b.order);
}
function resetToc() {
tocLines.value = [];
currentPage.value = "";
}
return { currentPage, tocLines, addTocLine, getToc, resetToc };
});

View file

@ -1,9 +0,0 @@
/* 0. CORE
** All the basic functions from the stylesheet
*/
@import 'core/normalize';
@import 'core/box-sizing';
@import 'core/typography';
@import 'core/containers';
@import 'core/columns';

View file

@ -1,12 +0,0 @@
// DEFINITIONS
// Global definitions and variables of the stylesheet
// With them, you can customize easily how the style look
// Look at each component inside the definitions subfolder to customize the
// styles
@import 'definitions/palette';
@import 'definitions/shadows';
@import 'definitions/fonts';
@import 'definitions/borders';
@import 'definitions/sizing';

View file

@ -1,2 +0,0 @@
// DEPENDECIES
// Other style used as dependencies

View file

@ -1,18 +0,0 @@
/* --- 04. COMPOSANTS --- */
/*
* Les différents composants réutilisables de la page.
*
*/
@import 'components/buttons';
@import 'components/btn-groups';
@import 'components/breadcrumb';
@import 'components/pagination';
@import 'components/cards';
@import 'components/menus';
@import 'components/toasts';
@import 'components/tables';
//@import 'components/previews';
@import 'components/sidebar';
@import 'components/input';

View file

@ -1,8 +0,0 @@
/* 4 - Custom styling
* Styles that are custom to this particular theme
**/
@import 'custom/global';
//@import 'custom/previews';
//@import 'custom/featured';
@import 'custom/article';

View file

@ -1,10 +0,0 @@
// MIXINS
// Include every mixins files
@import 'mixins/colors';
@import 'mixins/responsive';
@import 'mixins/borders';
@import 'mixins/shape';
@import 'mixins/btns';
@import 'mixins/panels';
@import 'mixins/li';

View file

@ -1,12 +0,0 @@
/* 1. Utils
** All the utilities class of the stylesheet
*/
@import 'utils/a11y';
@import 'utils/align';
@import 'utils/borders';
@import 'utils/colorize';
@import 'utils/lists';
@import 'utils/sizing';
@import 'utils/flex';
@import 'utils/display';

View file

@ -1,6 +0,0 @@
.badge {
@include button(0rem);
padding-left: $button_small;
padding-right: $button_small;
text-decoration:none!important;
}

View file

@ -1,39 +0,0 @@
/* ------------------ BREADCRUMB ------------------- */
ul.breadcrumb, ol.breadcrumb, .breadcrumb {
padding-top: 0em;
background-color:transparent;
margin: 0;
padding-bottom:$lineheight;
@include li-flex();
}
.breadcrumb li.breadcrumb-item {
padding:0;
margin:0!important;
&:before {
display:none;
}
a, & > span {
display:inline-block;
@include button($button-large);
@include button-fullcontrol($color-background-alt, accentuate($color-background-alt), get-color("dark2"));
margin:0 $button-group-margin 0 $button-group-margin;
&.active {
@include button-fullcontrol($color-secondary, $color-secondary, $color-font-light);
}
}
&:not(:first-child) a, &:not(:first-child) > span {
border-top-left-radius: 0;
border-bottom-left-radius:0;
}
&:not(:last-child) a, &:not(:last-child) > span {
border-top-right-radius: 0;
border-bottom-right-radius:0;
}
}

View file

@ -1,26 +0,0 @@
// BUTTONS GROUPS
.btn-toolbar {
padding: 0 $button-large;
}
.btn-group {
& > .btn {
@include border-radius($btn-radius);
margin:0 $button-group-margin 0 $button-group-margin!important;
}
&:not(:first-child) > .btn {
border-top-left-radius: 0;
border-bottom-left-radius:0;
&:before {
content: " "!important;
border-left:1px solid rgba(0,0,0,0.2);
}
}
&:not(:last-child) > .btn {
border-top-right-radius: 0;
border-bottom-right-radius:0;
}
}

View file

@ -1,35 +0,0 @@
/*
* 3. Buttons and labels
* All clickable elements
*
*/
.btn {
@include button($button_large);
&:hover, &:active {
@include borders();
}
p &:last-child {
margin-bottom:0;
}
}
.btn-small, .badge {
@include button($button_small);
padding-left: $button_small;
padding-right: $button_small;
text-decoration:none;
}
// COLORIZE BUTTONS
strong.btn-fake {
@include button($button_large);
@include button-fullcontrol(transparent, transparent, rgba(0,0,0,1));
}
.btn-readmore, .btn-link {
@include button-fullcontrol(transparent, accentuate($color-background-alt), $color-primary);
@include prefer-no-borders();
}

View file

@ -1,76 +0,0 @@
/*
* 2. Cards and containers
* All elements that are supposed to contain other stuff
*
*
*/
$card-bigpad: $lineheight;
$card-smallpad: $lineheight_half;
.card {
@include panel($card-bigpad);
display: flex;
flex-direction: column;
color:$color-font;
&-body {
padding:0!important;
}
&-header {
@include panel-header($card-bigpad);
.fa {
margin-right: 0.5em;
}
}
}
/* CARD LIST - Make a list part of a card */
@mixin list-symbol($symbol) {
li.list-element {
list-style: none;
&::before {
font-family: "ForkAwesome";
content:$symbol;
padding-right:$lineheight_half;
}
}
}
@mixin list-color($color) {
li.list-element {
&::before {
color: $color;
}
}
}
ul.card-list, .card > ul {
padding:0;
margin:0;
li.list-element {
line-height:$lineheight;
padding-right:$lineheight_half;
padding-left:$lineheight_quarter;
padding-top:$lineheight_quarter;
padding-bottom:$lineheight_quarter;
margin:0;
}
}
.list {
&-check {@include list-symbol("\f00c");}
&-cross {@include list-symbol("\f00d");}
&-danger{@include list-color($color-danger);}
&-success{@include list-color($color-success);}
}
.smallcard {
&-header {
@include panel-header($card-bigpad);
}
}

View file

@ -1,9 +0,0 @@
input,
textarea {
width: 100%;
background-color: $color-background;
border-radius: $btn-radius;
border: 0px solid rgba(0, 0, 0, 0);
padding: $lineheight/4;
line-height: $lineheight;
}

View file

@ -1,105 +0,0 @@
/* Menu handling */
.menu {
display: flex;
flex-direction: column;
padding: $lineheight/4;
ul,
li {
list-style: none;
padding: 0;
margin: 0;
}
a,
a:visited {
@include shape-style($lineheight_half);
display: flex;
line-height: $lineheight;
padding: $lineheight_quarter;
margin: 0;
justify-content: space-between;
align-items: center;
word-wrap: none;
text-overflow: ellipsis;
overflow: hidden;
@include shape-style($lineheight_half);
//@include button-hover();
@include prefer-no-borders();
.badge {
margin: 0;
}
}
&.fg-light,
.fg-light & {
a {
color: $color-font-light;
&.router-link-exact-active {
background-color: transparentize($color-font-light, 0.85);
}
&:hover,
&:active {
background-color: transparentize($color-font-light, 0.7);
}
}
}
&.fg-dark,
.fg-dark & {
a {
color: $color-font;
&:hover,
&:active {
background-color: transparentize($color-font, 0.85);
}
}
}
}
.toolbar {
flex-direction: row;
ul {
display: flex;
flex-direction: row;
flex-grow: 1;
}
li {
text-align: center;
a,
span,
em,
strong,
&.toolbar-element {
display: block;
padding: $lineheight/3;
padding-left: $lineheight/2;
padding-right: $lineheight/2;
}
}
}
.menu-divider {
position: relative;
left: -$lineheight_quarter;
font-weight: $fontweight_hyper;
padding-top: $lineheight_quarter;
padding-bottom: $lineheight_quarter;
}
.menu-label {
@include shape-style($button_small);
@include button-hover();
padding-left: $button_small;
padding-right: $button_small;
}

View file

@ -1,25 +0,0 @@
nav.pagination {
padding-bottom:$lineheight;
.nav-links {
text-align: center;
width:100%;
}
.page-numbers, .next, .prev {
@include button($button_small);
padding-left: $button_small;
padding-right: $button_small;
margin-right : $button_small / 8;
margin-left: $button_small / 8;
&:not(.current) {
@include button-color($color-background-alt);
}
&.current {
@include background-color($color-primary);
&:hover {
@include background-color($color-primary);
}
}
}
}

View file

@ -1,268 +0,0 @@
/*
* 4. Previews
* Special style for previews cards
*
*/
$preview-height: 8*$lineheight;
$preview-content-height:165px;
$comment-peek-height:0px;
$comment-height:30px;
.preview-grid {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-gap: $lineheight;
padding-bottom: $lineheight;
@include md() {
grid-template-columns: 1fr 1fr;
}
@include xl() {
grid-template-columns: 1fr 1fr 1fr;
}
@include xxl() {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
}
.preview-container {
width:100%;
}
@media(max-width:767px){}
@media(min-width:768px){}
@media(min-width:992px){
.prev-col-2 .preview-container {
width:50%;
}
.prev-col-3 .preview-container {
width:33%;
}
.prev-col-4 .preview-container {
width:25%;
}
}
.card-preview {
padding:0;
width:100%;
margin:auto;
box-shadow: $large-shadow, $inset-shadow;
}
.preview-link {
padding:0;
background-color: transparent;
margin:0!important;
}
.preview-item {
height: $preview-height;
font-size:0.9rem;
line-height: $lineheight !important;
text-align:justify;
background-color:rgba(0,0,0,0.00);
color:dim(getFontColor());
position: relative;
display: flex;
-ms-flex-align: center !important;
align-items: center !important;
justify-content: center;
.preview-overlay {
height: 100%;
width: 100%;
top: 0;
left: 0;
position: absolute;
padding-top: $card-header-vmargin/2;
backdrop-filter: none;
transition: background-color 0.3s;
@include border-radius($card-radius);
h1, h2, h3, h4, h5, h6 {
color: $color-font-light;
font-size: 1rem;
line-height: $lineheight;
font-weight:$fontweight_big;
}
.card-header {
font-family: $basefont;
font-size: 1rem;
@include panel-header($lineheight_half);
@include colorize-shape($color-primary);
color:getTextColorFromBackground($color-primary);
font-weight: $fontweight_big;
margin-top:0px;
}
}
&:hover {
.preview-overlay {
backdrop-filter: blur(2px);
background-color:rgba(0,0,0,0.4);
.metadata-pills {
opacity: .9;
transition: opacity .5s, height .5s;
height:$preview-content-height - $comment-height;
}
}
}
}
.preview-content {
max-height: $preview-height;
overflow:hidden;
background-size: cover;
min-height:100%;
min-width:100%;
@include border-radius($card-radius);
font-size:0.85rem;
line-height:1.25rem;
h1, h2, h3, h4, h5, h6 {
margin-bottom:0px;
max-width:100%;
display:none;
}
& > p {
width:100%;
margin:auto;
& > img {
max-width:100%;
height:auto;
vertical-align:middle;
margin:auto;
text-align:center;
}
&.p-img {
text-align:center;
margin:auto;
padding:auto;
display: block;
width:100%;
}
}
}
.preview-metadata {
color: $color-font-light;
height:$preview-content-height;
overflow: hidden;
@include border-radius($card-radius);
.metadata-pills {
height:$preview-content-height - $comment-peek-height;
opacity: 0;
transition: opacity .3s, height .3s;
display:flex;
justify-content:space-between;
padding-left: $lineheight/2;
padding-right: $lineheight/2;
font-size:0.9em;
}
}
.card-preview.head-info {
.comment-text {
background-color:$color-secondary;
}
}
.card-preview.card-grey {
.comment-text {
background-color:$color-muted;
}
}
.comment-text {
color: $color-font-light;
background-color:$color-primary;
text-align: center;
}
.card-preview time {
margin-bottom:0.4em;
display:block;
}
// Author area
.author-area {
display:flex;
img.author-avatar, img.avatar {
display:block;
height: $lineheight*3;
width:auto;
border-radius:100%;
padding:0;
margin:0;
margin-right:$lineheight;
}
.author-metadata {
align-items:center;
display:flex;
flex-direction:column;
justify-content: center;
align-items: flex-start;
}
.author-date {
font-style:italic;
}
&:not(:last-child) {
margin-bottom:$lineheight;
}
}
.pigimg {
display:block;
max-width: 100%;
height:auto;
margin:auto;
}
.avatar {
background: transparent;
}
.mwarea {
padding-bottom: $lineheight;
.avatar {
width:80%;
height:auto;
display:block;
margin:auto;
}
}
.cover {
width:100%;
height:auto;
@include border-radius($card-radius);
}
.roman {
@include md() {
width:80%;
position:relative;
top:-240px;
margin:auto;
}
}

View file

@ -1,21 +0,0 @@
.sidebar-container {
width:100%;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
row-gap: $lineheight;
column-gap: $lineheight*2;
grid-template-areas:
"side"
"main";
@include lg() {
grid-template-columns: 360px auto;
grid-template-areas: "side main";
}
.sidebar {
padding:1rem;
}
}

View file

@ -1,63 +0,0 @@
/* TABLE
* Style tables
*/
table {
border-collapse: collapse;
border-spacing: 0;
&:not(:last-child) {
margin-bottom: 1.5rem;
}
}
th, td {
padding: 0.325rem;
border:0;
margin:0;
}
th {
vertical-align: center;
font-weight: $fontweight_hyper;
background-color:$color-primary;
color:white;
}
td {
background-color:$color-background-alt;
tr:nth-child(even) & {
background-color: darken($color-background-alt, 7.5%);
}
}
thead {
th:first-child {
border-top-left-radius: 10px;
}
th:last-child {
border-top-right-radius: 10px;
}
&:last-child {
th {
text-align: center;
&:first-child {
border-bottom-left-radius: 10px;
}
&:last-child {
border-bottom-right-radius: 10px;
}
}
}
}
tr:last-child td:first-child {
border-bottom-left-radius: 10px;
}
tr:last-child td:last-child {
border-bottom-right-radius: 10px;
}

View file

@ -1,11 +0,0 @@
.toast {
@include panel($card-smallpad);
padding:$card-smallpad;
font-size: 0.8rem;
a:not(:hover) {
background-color: rgba(0,0,0,0.2)!important;
}
a {
margin: 0;
}
}

View file

@ -1,18 +0,0 @@
/* 0.2 - Box-sizing
* Make sure that everything have its box-sizing to border-box
**/
*,
*::before,
*::after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
}
body {
overflow-x: hidden;
text-rendering: optimizeLegibility;
}

View file

@ -1,68 +0,0 @@
@mixin column($size) {
grid-column: span $size;
width:100%;
margin:0;
& > *:last-child {
margin-bottom:0!important;
}
}
@mixin column-list() {
&-1 {@include column(1);}
&-2 {@include column(2);}
&-3 {@include column(3);}
&-4 {@include column(4);}
&-5 {@include column(5);}
&-6 {@include column(6);}
&-7 {@include column(7);}
&-8 {@include column(8);}
&-9 {@include column(9);}
&-10 {@include column(10);}
&-11 {@include column(11);}
&-12 {@include column(12);}
}
.columns {
display:grid;
grid-gap:$lineheight;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: auto;
padding:$lineheight;
&-nogap {
grid-gap:0px;
}
}
.column {
@include column(12);
}
.col {
@include column-list();
&-sm {
@include sm() {
@include column-list();
}
}
&-md {
@include md() {
@include column-list();
}
}
&-lg {
@include lg() {
@include column-list();
}
}
&-xl {
@include xl() {
@include column-list();
}
}
&-xxl {
@include xxl() {
@include column-list();
}
}
}

View file

@ -1,11 +0,0 @@
#wrapper {
background-color: $color-background;
}
.container-big {
@include container($container-size-large, $lineheight);
}
.container, .container-onecolumn {
@include container($container-size, $lineheight);
}

View file

@ -1,349 +0,0 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

View file

@ -1,190 +0,0 @@
/* 0.3 - Typography
* This part of the (s)css handle everything related to the typography
* like paragraphs, blockquote, etc.
**/
/* 2.2 - Global Typography */
@mixin paragraph() {
padding:0;
padding-bottom: $lineheight;
margin: 0;
}
html, body {
font-family: $basefont;
text-align: left;
font-size: $fontsize;
line-height: $lineheight;
color: getFontColor();
font-weight: $fontweight_base;
}
strong {
font-weight: $fontweight_bold;
}
em {
font-style: italic;
font-weight: $fontweight_base;
}
a, a:visited, mark {
text-decoration: none;
padding: 0.05rem 0.25rem;
border-radius: 0.1rem;
}
a, a:visited {
@include background-color($color-link);
&:hover, &:active, &:focus {
color: $color-link;
background-color: transparent;
}
&:focus {
outline-color: currentColor;
outline-style: dashed;
outline-width: 2px;
}
}
mark {
background-color: lighten($color-mark, 30%);
color: inherit;
}
p, ul, ol {
@include paragraph();
&:last-child {
padding-bottom:0;
}
}
ul, ol {
list-style: disc;
ul, ol {
padding-bottom:0;
margin:0;
}
li {
margin:0;
margin-left: $lineheight;
line-height: $lineheight;
}
}
::selection, ::-moz-selection {
@include background-color($color-selection);
}
/* 2.3 - Titles */
@mixin newTitle($size, $weight) {
$lineNumber: ceil($size / 1.5);
font-size: $size * 1rem;
line-height: $lineNumber * $lineheight;
font-weight: $weight;
}
h1, h2, h3, h4, h5, h6, h7 {
font-family: $basefont;
text-align: left;
font-size: 1em;
padding:0;
margin:0;
font-weight: $fontweight_base;
padding-bottom: $lineheight;
}
sup, sub {
& > a {
color: $color-link;
background-color:transparent;
&:hover, &:focus, &:active {
color: darken($color-link, 10%);
}
}
}
.main-title {
font-family: $titlefont;
@include newTitle(3.815, $fontweight_hyper);
}
h1, .title-1 {
font-family: $titlefont;
@include newTitle(2.441, $fontweight_hyper);
color: $color-primary;
}
h2, .title-2 {
@include newTitle(2.441, $fontweight_big);
}
h3, .title-3 {
@include newTitle(1.953, $fontweight_bold);
}
h4, .title-4 {
@include newTitle(1.563, $fontweight_hyper);
}
h5, .title-5 {
@include newTitle(1.25, $fontweight_bold);
}
h6, .title-6 {
@include newTitle(1, $fontweight_hyper);
}
/* 2.4 - hr */
hr {
border: 0px solid rgba(1, 1, 1, 0.15);
border-bottom: 1px;
margin: 1.5em;
}
/* 2.5 - Wells and quotes */
@mixin well() {
border: 0;
border-radius: $well-radius;
margin: 0 0 $lineheight 0;
padding: $lineheight 1rem $lineheight 1rem;
max-width: 100%;
font-style: italic;
@include background-color($color-background-alt);
box-shadow: $narrow-shadow;
}
blockquote, .quote {
&:before {
content:"";
}
}
blockquote, .quote, .well, pre, .pre, .well-pre {
@include well();
}
code {
background:transparent;
color: $color-danger;
}
.small-text {
font-size: 0.9em;
}
/* 2.6 - Special styling */
.time {
font-style: italic;
text-align: right;
width: 100%;
display: block;
}

View file

@ -1,39 +0,0 @@
article:last-child {
padding-bottom:1.5rem;
}
article .table-auto table, table.table-auto {
display: table;
width: 100%;
table-layout: auto;
}
table {
display: table;
width: 100%;
table-layout: fixed;
}
.btn-pagination, .btn-navig {
margin:0;
border-radius: 0;
width: 2rem;
}
.btn-navig:first-child {
border-top-left-radius: $btn-radius;
border-bottom-left-radius: $btn-radius;
}
.btn-navig:last-child {
border-top-right-radius: $btn-radius;
border-bottom-right-radius: $btn-radius;
}
article th {
height: 34px;
}
article tr:nth-child(2n) {
background-color: #fff;
}

View file

@ -1,48 +0,0 @@
#featured-articles {
display:grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-gap: $lineheight;
padding-bottom: $lineheight;
@include lg() {
grid-template-columns: 1fr 1fr 1fr;
}
}
.preview-featured {
font-size: 0.8rem;
.preview-link {
display: block;
padding:0;
border-radius: $card-radius;
overflow: hidden;
.preview-item {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
background-size:100% auto;
background-position: center center;
transition: background-size .5s;
&:hover {
background-size: 120% auto;
}
}
}
.preview-overlay {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
height:100%;
color: white !important;
background: linear-gradient(to top, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0) 60%);
padding:$lineheight / 8;
h2 {
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.7);
}
}
}

View file

@ -1,51 +0,0 @@
#topbar {
position:fixed;
width:100%;
z-index:2;
font-size: 0.85rem;
}
#wrapper {
padding-top:3rem;
display:flex;
min-height:100vh;
}
#sidebar {
padding-top:1rem;
padding-left:0.75rem;
width:17rem;
position: fixed;
height: calc(100vh - 3rem);
overflow: scroll;
h1 {
text-align:center;
padding-bottom:.5rem;
}
.menu-item {
margin:3px;
}
font-size:0.85rem;
}
#page {
flex-grow:1;
padding-left:18rem;
padding-right: 18rem;
}
#toc {
position: fixed;
top: 4rem;
right: 1rem;
width: 16rem;
.menu {
padding-left:0.5rem;
padding-right:0.5rem;
}
}
#content {
max-width:1000px;
margin:auto;
}

View file

@ -1,79 +0,0 @@
.preview-grid {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-gap: $lineheight;
padding-bottom: $lineheight;
@include md() {
grid-template-columns: 1fr 1fr;
}
@include xl() {
grid-template-columns: 1fr 1fr 1fr;
}
@include xxl() {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
}
.preview-list {
@include sm() {
.preview-thumbnail a {
width: 240px;
margin-right: $lineheight /2;
}
.preview {
display: flex;
align-items: center;
margin-bottom: $lineheight;
}
}
@include xl() {
.preview-thumbnail a {
width: 320px;
}
}
}
.preview {
font-size: 0.8rem;
}
.preview-thumbnail a {
display:block;
width: 100%;
background-color:transparent;
margin:auto;
object-fit: cover;
padding:0;
line-height:0;
img {
width:100%;
object-fit: cover;
height: auto;
aspect-ratio: 16/9;
border-radius: $card-radius;
}
}
.preview h2, .preview-featured h2 {
font-size:1.25rem;
line-height: 1.5rem;
font-family: $titlefont;
font-weight: 800;
height:3rem;
a {
background-color:transparent!important;
color:$color-font;
}
}
.preview-excerpt {
margin-top: $lineheight / 2;
font-size:0.8rem;
line-height:1.25rem;
color:transparentize($color-font, 0.2);
}

View file

@ -1,6 +0,0 @@
// BORDERS AND BORDER-RADIUSES
$card-radius: 8px;
$btn-radius: 4px;
$well-radius: $btn-radius;
$border-size: 0px;

View file

@ -1,12 +0,0 @@
// FONTS
// Define how looks the text
$fontsize: 4.75mm;
$fontweight_big: 300;
$fontweight_base: 400;
$fontweight_bold: 600;
$fontweight_hyper: 800;
$basefont: Open Sans, sans-serif;
$titlefont: Open Sans, sans-serif;

View file

@ -1,83 +0,0 @@
/* --- 00. PALETTE --- */
/*
* Les définitions globales des couleurs du theme.
*
* Elle permettent de définir rapidement à la fois les couleurs
* de base qui seront utilisée pour tout le theme, mais
* également celles spécifiques pour certains sujets (liens, texte)
*
*/
$whiteness_value: 0.8;
// Couleurs de base du theme :
$palette: (
"brown":#876445,
"blue":#1c7ed6,
"violet":#6741d9,
"red":#e03131,
"orange":#e67700,
"green":#37b24d,
"skyblue":#1098ad,
"dark": #343a40,
"light":#fefefe,
"yellow":#fcc419,
"grey":#adb5bd,
"dark2":#212529,
"light2":#f1f3f5);
$semantics: (
"primary":"brown",
"secondary":"dark",
"warning":"orange",
"danger":"red",
"info":"skyblue",
"success":"green",
"muted":"grey");
$helpers: (
"font":"dark2",
"font-light":"light",
"background":"light",
"background-alt":"light2",
"link":"brown",
"selection":"brown",
"mark":"yellow",
);
@function get-color($name) {
@if map-has-key($helpers, $name) {
@return map-get($palette, map-get($helpers, $name));
} @else {
@if map-has-key($semantics, $name) {
@return map-get($palette, map-get($semantics, $name));
} @else {
@return map-get($palette, $name);
}
}
}
// **Couleurs du theme**
// Ne pas retirer ces couleurs, qui
// sont essentielle pour que le framework functionne.
// Pour les modifier, modifier le contenu du tableau $semantics.
$color-link: get-color("link");
$color-selection: get-color("selection");
$color-mark: get-color("mark");
$color-font: get-color("font");
$color-font-light: get-color("font-light");
$color-primary: get-color("primary");
$color-secondary: get-color("secondary");
$color-warning: get-color("warning");
$color-danger: get-color("danger");
$color-info: get-color("info");
$color-success: get-color("success");
$color-muted: get-color("muted");
$color-background: get-color("background");
$color-background-alt: get-color("background-alt");

View file

@ -1,8 +0,0 @@
// SHADOWS
// Define how looks the shadows and the relief effects
$large-shadow: 0px 2px 4px rgba(0, 0, 0, 0);
$narrow-shadow: 0px 1px 2px rgba(0, 0, 0, 0);
$inset-shadow: inset 0px -2px 0px rgba(0, 0, 0, 0);
$inset-shadow-inverted: inset 0px 2px 0px rgba(0, 0, 0, 0);
$inset-relief: inset 0px 2px 0px rgba(255, 255, 255, 0);

View file

@ -1,34 +0,0 @@
// SIZING
// All the spacing and sizing variables
$baseline: 1.5;
$lineheight: $baseline * 1rem;
$lineheight_half: $lineheight/2;
$lineheight_quarter: $lineheight/4;
$card-header-vmargin: 0px;
$card-header-hmargin: 0px;
$card-header-padding: $lineheight;
$card-header-width: 100%;
$card-header-position:0px;
// Buttons
$button_large: $lineheight;
$button_small: $lineheight_quarter;
$button-group-margin: 0;
// Responsives sizes
// - sm : Small tablets and large smartphones (landscape view)
// - md : Small tablets (portrait view)
// - lg : Tablets and small desktops
// - xl : Large tablets and desktops
// - xxl : Very large desktops
$screen-sm-min: 576px;
$screen-md-min: 768px;
$screen-lg-min: 992px;
$screen-xl-min: 1200px;
$screen-xxl-min: 1600px;
// Containers size
$container-size: $screen-xl-min;
$container-size-large: $screen-xxl-min;

View file

@ -1,15 +0,0 @@
// Border, border radius and margin
@mixin borders() {
border: $border-size solid rgba(0, 0, 0, 0.3)
}
@mixin prefer-no-borders() {
&:not(:hover) {
border-color:transparent;
}
}
@mixin border-radius($border-radius) {
border-radius: $border-radius $border-radius $border-radius $border-radius;
}

View file

@ -1,51 +0,0 @@
@mixin button($size) {
@include button-layout($size);
@include shape-style($size);
@include button-hover();
font-weight: $fontweight_base;
}
@mixin button-layout($size) {
padding: $size;
padding-top: $size/3;
padding-bottom: $size/3;
margin:$size/2;
margin-top: $size/3;
margin-bottom: $lineheight;
//font-size: 4.75mm;
line-height:$lineheight;
height:auto;
}
@mixin button-hover() {
transition: background-color .2s, border .2s, box-shadow .2s, color .2s;
&:focus {
outline: none;
box-shadow: $narrow-shadow, $inset-shadow, 0px 0px 0px 2px rgba(0, 0, 0, 0);
&:before {
box-shadow: $narrow-shadow, $inset-shadow, 0px 0px 0px 2px rgba(0, 0, 0, 0.3);
outline: none;
}
}
}
@mixin button-fullcontrol($background-color, $hover-color, $text-color) {
@include colorize-shape($background-color);
color:$text-color;
&:visited {
@include colorize-shape($background-color);
color:$text-color;
}
&, &:visited, &:not(.disabled):not(:disabled) {
&:hover, &:active, &:focus {
@include colorize-shape($hover-color);
color:lighten($text-color, 5%);
}
}
}
@mixin button-color($background-color) {
@include button-fullcontrol($background-color, mix($background-color, getTextColorFromBackground($background-color), 85%), getTextColorFromBackground($background-color));
box-shadow: $narrow-shadow;
}

View file

@ -1,61 +0,0 @@
/* --- 00. COLORS --- */
/*
* La gestion des couleurs dans le theme. Cette partie de la stylesheet est
* automatique et n'a pas besoin d'être modifiée
*/
// FUNCTIONS TO GET MORE EASILY COLORS
@function list-colors() {
$newmap: map-merge($palette, $semantics);
@return $newmap;
}
@function luminance($color) {
$c_red: red($color);
$c_grn: green($color);
$c_blu: blue($color);
$luminance: $c_red*0.299 + $c_grn*0.587 + $c_blu*0.114;
@return $luminance
}
@function getFontColor() {
@return getTextColorFromBackground(get-color("background-alt"));
}
@function getTextColorFromBackground($background-color) {
@if (luminance($background-color) < 255 * $whiteness_value) {
@return $color-font-light;
} @else {
@return $color-font;
}
}
@function accentuate($color) {
@if (luminance($color) > 64) {
@return darken($color, 7.5%);
} @else {
@return lighten($color, 4%);
}
}
@function dim($color) {
@if (luminance($color) > 255 * $whiteness_value) {
@return transparentize($color, 0.8);
} @else {
@return transparentize($color, 0.6);
}
}
// fonction texte et background
@mixin text-color($text-color) {
color: $text-color;
}
@mixin background-color($background-color) {
background-color: $background-color;
color: getTextColorFromBackground($background-color);
}

View file

@ -1,13 +0,0 @@
@mixin li-no-margin() {
li {
margin: 0;
}
}
@mixin li-flex() {
display:flex;
flex-direction: row;
align-items: flex-start;
@include li-no-margin();
list-style: none;
}

View file

@ -1,64 +0,0 @@
@mixin panel($size) {
@include border-radius($card-radius);
background-color: $color-background-alt;
box-shadow: $large-shadow;
border: none;
margin:0;
margin-bottom:$lineheight;
& > * {
margin-left: $size / 2;
margin-right: $size / 2;
&:first-child {
margin-top: $size;
&.card-header {
margin-top:$card-header-vmargin;
}
}
&:last-child {
margin-bottom: $size;
&.card-header {
margin-bottom:$card-header-vmargin;
}
}
}
}
@mixin panel-header($size) {
font-size:1.1em;
font-weight: $fontweight_big;
padding: $size/2;
padding-left:$card-header-padding;
padding-right:$card-header-padding;
padding-bottom: $size/2!important;
margin:$card-header-hmargin;
margin-bottom:$lineheight_half;
margin-top:$lineheight_half;
line-height:$lineheight;
white-space: nowrap;
position:relative;
left: $card-header-position;
width:$card-header-width;
@include shape-style($size);
border-radius:0;
&:first-child {
border-top-left-radius: $card-radius;
border-top-right-radius: $card-radius;
}
&:last-child {
border-bottom-left-radius: $card-radius;
border-bottom-right-radius: $card-radius;
}
h1, h2, h3, h4, h5, h6, h7, h8, h9, h10 {
font-family:$basefont;
font-size:1rem;
padding:0px;
margin:0px;
color:$color-font-light;
font-weight: $fontweight_big;
line-height:$lineheight;
}
}

View file

@ -1,84 +0,0 @@
// MIXINS RESPONSIVES
// Small devices
@mixin sm {
@media (min-width: #{$screen-sm-min}) {
@content;
}
}
// Medium devices
@mixin md {
@media (min-width: #{$screen-md-min}) {
@content;
}
}
// Large devices
@mixin lg {
@media (min-width: #{$screen-lg-min}) {
@content;
}
}
// Extra large devices
@mixin xl {
@media (min-width: #{$screen-xl-min}) {
@content;
}
}
// Extra large desktops
@mixin xxl {
@media (min-width: #{$screen-xxl-min}) {
@content;
}
}
// Custom devices
@mixin rwd($screen) {
@media (min-width: $screen+'px' ) {
@content;
}
}
@mixin container($size, $padding) {
padding-left: $padding;
padding-right: $padding;
max-width: $size;
margin:auto;
}
@mixin responsive() {
@content;
&-sm {
@include sm() {
@content;
}
}
&-md {
@include md() {
@content;
}
}
&-lg {
@include lg() {
@content;
}
}
&-xl {
@include xl() {
@content;
}
}
&-xxl {
@include xxl() {
@content;
}
}
}

View file

@ -1,10 +0,0 @@
@mixin shape-style($size) {
@include borders();
@include border-radius($btn-radius);
background-color:transparent;
}
@mixin colorize-shape($background-color) {
background-color: $background-color;
}

View file

@ -1,23 +0,0 @@
/*
Theme Name: Quarante-Douze
Theme URI: https://git.kobold.cafe/quarante-douze/qdouze2-wordpress-theme
Author: Kazhnuz
Author URI: https://kazhnuz.space
Description: The default theme for Quarante-Douze, my tech blog.
Version: 0.1
License: GNU General Public License v3 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Tags: blog, two-columns, right-sidebar
Text Domain: qdouze2-wordpress-theme
This theme is licensed under the GPLv3.
*/
@import 'dep';
@import 'definitions';
@import 'mixins';
@import 'core';
@import 'drawing';
@import 'utils';
@import 'global';

View file

@ -1,8 +0,0 @@
/* 1.0 - Accessibility classes
* Some classes to help accessibility
**/
.screen-reader-text {
visibility: collapse;
font-size:0;
}

View file

@ -1,14 +0,0 @@
/* 1.1 - Alignement classes
* Handle easily alignement and flexboxes
**/
.flex-that {
display: flex;
justify-content: space-between;
}
.align {
&-center {text-align: center;text-indent: 0!important;}
&-left {text-align: left;}
&-right {text-align: right;}
}

View file

@ -1,8 +0,0 @@
.round, .pill {
border-radius: 9999px;
}
.no-borders {
border-width:0px;
border-style:none;
}

View file

@ -1,85 +0,0 @@
/* 1.2 - Colorization classes
* Colorize some aspect of a class
**/
@mixin heading-color($background-color) {
& .card-header,
& .menu-header,
&.header-bg th {
@include colorize-shape($background-color);
color: getTextColorFromBackground($background-color);
}
th {
color: $background-color;
}
}
@mixin bg-color($background-color) {
@include background-color($background-color);
&>a,
&>a:visited {
color: $background-color;
background-color: getTextColorFromBackground($background-color);
&:hover,
&:active,
&:visited {
color: getTextColorFromBackground($background-color);
background: none;
}
}
}
.bg {
@each $name,
$color in list-colors() {
&-#{$name} {
@include bg-color(get-color($name));
&:hover {
@include bg-color(get-color($name));
}
}
}
}
.text {
@each $name,
$color in list-colors() {
&-#{$name} {
@include text-color(get-color($name));
}
}
}
.btn {
@each $name,
$color in list-colors() {
&-#{$name} {
@include button-color(get-color($name));
}
}
}
.head {
@each $name,
$color in list-colors() {
&-#{$name} {
@include heading-color(get-color($name));
}
}
}
.fg-light {
color: $color-font-light;
}
.fg-dark {
color: $color-font;
}

View file

@ -1,17 +0,0 @@
.d-block {
@include responsive() {
display: block!important;
}
}
.d-none {
@include responsive() {
display: none!important;
}
}
.d-flex {
@include responsive() {
display: flex!important;
}
}

View file

@ -1,35 +0,0 @@
.f-column {
display:flex;
flex-direction: column;
&.reverse {
flex-direction:column-reverse;
}
}
.f-row {
display:flex;
flex-direction: row;
&.reverse {
flex-direction:row-reverse;
}
}
.f-start {
justify-content: flex-start;
}
.f-end {
justify-content: flex-end;
}
.f-center {
justify-content: center;
}
.f-around {
justify-content: space-around;
}
.f-between {
justify-content: space-between;
}

View file

@ -1,7 +0,0 @@
/* 1.3 - List classes
* Handle more easily list
**/
.no-pills {
list-style:none;
}

View file

@ -1,61 +0,0 @@
/* 1.3 - Sizing classes
* Handle sizing and margin
**/
@mixin addmargins($name, $size) {
&-#{$name} {
margin:$size;
}
&b-#{$name} {
margin-bottom:$size;
}
&r-#{$name} {
margin-right:$size;
}
&l-#{$name} {
margin-left:$size;
}
&t-#{$name} {
margin-top:$size;
}
}
@mixin addpaddings($name, $size) {
&-#{$name} {
padding:$size;
}
&b-#{$name} {
padding-bottom:$size;
}
&r-#{$name} {
padding-right:$size;
}
&l-#{$name} {
padding-left:$size;
}
&t-#{$name} {
padding-top:$size;
}
}
.m {
@include addmargins("half", $lineheight * .5);
@for $i from 0 through 4 {
@include addmargins($i, $lineheight*$i)
}
}
.p {
@include addpaddings("half", $lineheight * .5);
@for $i from 0 through 4 {
@include addpaddings($i, $lineheight*$i)
}
}

View file

@ -1,4 +0,0 @@
export default interface HideLink {
menu: number;
link: string;
}

View file

@ -1,16 +0,0 @@
import type HideLink from "./HideLink";
import type LinkList from "./LinkList";
export default interface JdrConfig {
name: string;
sidebar: LinkList[];
hideLinks: HideLink[];
vars: { name: string; value: string }[];
objects: string[];
equipMains: string[];
effetsMains: string[];
tenues: string[];
effetsTenues: string[];
accessoires: string[];
elements: string[];
}

View file

@ -1,5 +0,0 @@
export default interface Link {
title: string;
path: string;
isHidden?: boolean;
}

View file

@ -1,7 +0,0 @@
import type Link from "./Link";
export default interface LinkList {
title?: string;
id: number;
links: Link[];
}

View file

@ -1,9 +0,0 @@
import type Link from "./Link";
import type LinkList from "./LinkList";
export default interface PelicanConfig {
version: string;
sidebar: LinkList[];
jdr: LinkList[];
fiches: Link[];
}

View file

@ -1,5 +0,0 @@
export default interface TocLine {
order: number;
text: string;
anchor: string;
}

View file

@ -1,116 +0,0 @@
import SimpleHtmlTable from "./SimpleHtmlTable";
import { forEachCols, getColumn } from "./tableUtils";
import type { FilterFieldsMap, Filters, TableField, TableItem } from "./types";
export default class FilteredHtmlTable {
table: SimpleHtmlTable;
filtersFieldMap: FilterFieldsMap = {};
textSearch = "";
constructor() {
this.table = new SimpleHtmlTable();
}
private initFilters() {
this.filtersFieldMap = {};
for (const field of this.table.fields) {
if (field.canBeFiltered) {
// Create a filter for the field, that'll contain every
// filters possible for the field
this.filtersFieldMap[field.key] = {
title: field.label,
filters: {} as Filters,
};
}
}
}
set fields(fields: TableField[]) {
this.table.fields = fields;
this.initFilters();
}
addItems(rows: TableItem[]) {
this.table.addItems(rows);
forEachCols(rows, (colName: string, col: string) => {
this.setFilterableValue(colName, col);
});
}
get items() {
let filteredItem = this.table.items as TableItem[];
for (const fieldKey in this.filtersFieldMap) {
if (this.haveFilter(fieldKey)) {
filteredItem = filteredItem.filter((row) => {
const filters = this.getFiltersForField(fieldKey);
return !filters || filters[getColumn(row, fieldKey) as string];
});
}
}
if (this.textSearch !== "") {
filteredItem = filteredItem.filter((row) => {
for (const field of this.table.fields) {
if (field.canBeSearched) {
if ((row[field.key] as string).includes(this.textSearch)) {
return true;
}
}
}
return false;
});
}
return filteredItem;
}
search(query: string) {
return this.items.filter((row) => {
for (const field of this.table.fields) {
if (field.canBeSearched) {
if ((row[field.key] as string).includes(query)) {
return true;
}
}
}
return false;
});
}
private setFilterableValue(fieldKey: string, filterableValue: string) {
const filters = this.getFiltersForField(fieldKey);
if (filters) {
filters[filterableValue] = false;
}
}
private getFiltersForField(fieldKey: string) {
if (this.filtersFieldMap[fieldKey]) {
return this.filtersFieldMap[fieldKey].filters;
}
}
private haveFilter(fieldKey: string) {
for (const val in this.getFiltersForField(fieldKey)) {
if (this.filtersFieldMap[fieldKey].filters[val]) {
return true;
}
}
return false;
}
public switchFilter(fieldKey: string, filterValue: string) {
const filters = this.getFiltersForField(fieldKey);
if (filters && filters[filterValue] !== undefined) {
filters[filterValue] = !filters[filterValue];
}
}
public removeAllFilters(fieldKey: string) {
const filters = this.getFiltersForField(fieldKey);
for (const filterValue in filters) {
filters[filterValue] = false;
}
}
}

View file

@ -1,80 +0,0 @@
import FilteredHtmlTable from "./FilteredHtmlTable";
import type { TableField, TableItem } from "./types";
export interface PaginatedTable {
filteredTable: FilteredHtmlTable;
pageLenght: number;
currentPage: number;
pageNumber: number;
items: TableItem[];
textSearch: string;
}
export default class PaginatedFilteredTable implements PaginatedTable {
filteredTable: FilteredHtmlTable;
pageLenght: number;
currentPage = 0;
constructor(pageLenght: number) {
this.filteredTable = new FilteredHtmlTable();
this.pageLenght = pageLenght;
}
get pageNumber() {
return Math.floor((this.filteredTable.items.length - 1) / this.pageLenght);
}
get items() {
let items = this.filteredTable.items as TableItem[];
items = items.filter((value, index) => {
const pageBegin = this.currentPage * this.pageLenght;
return index >= pageBegin && index < pageBegin + this.pageLenght;
});
return items;
}
set fields(fields: TableField[]) {
this.filteredTable.fields = fields;
}
set textSearch(textSearch: string) {
this.currentPage = 0;
this.filteredTable.textSearch = textSearch;
}
get textSearch() {
return this.filteredTable.textSearch;
}
public addItems(items: TableItem[]) {
this.filteredTable.addItems(items);
}
public search(query: string) {
return this.filteredTable.search(query);
}
public canGo(rel: number) {
return (
this.currentPage + rel >= 0 && this.currentPage + rel <= this.pageNumber
);
}
public go(rel: number) {
if (this.canGo(rel)) {
this.currentPage = this.currentPage + rel;
}
}
public switchFilter(fieldKey: string, filterValue: string) {
this.filteredTable.switchFilter(fieldKey, filterValue);
this.currentPage = 0;
}
public removeAllFilters(fieldKey: string) {
this.filteredTable.removeAllFilters(fieldKey);
this.currentPage = 0;
}
}

Some files were not shown because too many files have changed in this diff Show more