Compare commits
17 Commits
|
@ -6,3 +6,4 @@
|
|||
/.sass-cache/
|
||||
/build/
|
||||
*.scssc
|
||||
/Book.html
|
||||
|
|
|
@ -5,12 +5,11 @@ homepage: https://labs.phundrak.com/phundrak/org-website-backend
|
|||
author: Lucien Cartier-Tilet <lucien@phundrak.com>
|
||||
|
||||
environment:
|
||||
sdk: '>=2.7.0 <3.0.0'
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
html: '^0.14.0+3'
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^1.8.0
|
||||
build_web_compilers: ^2.9.0
|
||||
pedantic: ^1.9.0
|
||||
build_runner: ">=1.10.1 <2.0.0"
|
||||
build_web_compilers: ">=2.9.0 <3.0.0"
|
||||
pedantic: ">=1.9.0 <2.0.0"
|
||||
|
|
|
@ -4,7 +4,8 @@ import './theme.dart' show enableThemeChanger, setTheme;
|
|||
|
||||
Future<void> main() async {
|
||||
await setTheme();
|
||||
await reorganizeHtml()
|
||||
.then((_) => enableThemeChanger())
|
||||
.then((_) => createSitemap());
|
||||
await reorganizeHtml().then((_) {
|
||||
enableThemeChanger();
|
||||
createSitemap();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import 'dart:html';
|
||||
import 'dart:svg';
|
||||
import 'dart:html' show querySelector, Element, window;
|
||||
import 'dart:svg' show SvgElement;
|
||||
|
||||
// You will see here and there some 'tabindex' attributes added to various HTML
|
||||
// elements, and I’m sure you will ask "Why? They don’t serve any purpose, do
|
||||
|
@ -32,16 +32,10 @@ final icons = {
|
|||
'<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2.04C6.5 2.04 2 6.53 2 12.06C2 17.06 5.66 21.21 10.44 21.96V14.96H7.9V12.06H10.44V9.85C10.44 7.34 11.93 5.96 14.22 5.96C15.31 5.96 16.45 6.15 16.45 6.15V8.62H15.19C13.95 8.62 13.56 9.39 13.56 10.18V12.06H16.34L15.89 14.96H13.56V21.96A10 10 0 0 0 22 12.06C22 6.53 17.5 2.04 12 2.04Z" /></svg>'),
|
||||
'theme': SvgElement.svg(
|
||||
'<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="currentColor" d="M12,18V6A6,6 0 0,1 18,12A6,6 0 0,1 12,18M20,15.31L23.31,12L20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31Z" /></svg>'),
|
||||
'sun': SvgElement.svg(
|
||||
'<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="currentColor" d="M3.55,18.54L4.96,19.95L6.76,18.16L5.34,16.74M11,22.45C11.32,22.45 13,22.45 13,22.45V19.5H11M12,5.5A6,6 0 0,0 6,11.5A6,6 0 0,0 12,17.5A6,6 0 0,0 18,11.5C18,8.18 15.31,5.5 12,5.5M20,12.5H23V10.5H20M17.24,18.16L19.04,19.95L20.45,18.54L18.66,16.74M20.45,4.46L19.04,3.05L17.24,4.84L18.66,6.26M13,0.55H11V3.5H13M4,10.5H1V12.5H4M6.76,4.84L4.96,3.05L3.55,4.46L5.34,6.26L6.76,4.84Z" /></svg>'),
|
||||
'lightbulb': SvgElement.svg(
|
||||
'<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="currentColor" d="M12,6A6,6 0 0,1 18,12C18,14.22 16.79,16.16 15,17.2V19A1,1 0 0,1 14,20H10A1,1 0 0,1 9,19V17.2C7.21,16.16 6,14.22 6,12A6,6 0 0,1 12,6M14,21V22A1,1 0 0,1 13,23H11A1,1 0 0,1 10,22V21H14M20,11H23V13H20V11M1,11H4V13H1V11M13,1V4H11V1H13M4.92,3.5L7.05,5.64L5.63,7.05L3.5,4.93L4.92,3.5M16.95,5.63L19.07,3.5L20.5,4.93L18.37,7.05L16.95,5.63Z" /></svg>'),
|
||||
'moon': SvgElement.svg(
|
||||
'<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="currentColor" d="M17.75,4.09L15.22,6.03L16.13,9.09L13.5,7.28L10.87,9.09L11.78,6.03L9.25,4.09L12.44,4L13.5,1L14.56,4L17.75,4.09M21.25,11L19.61,12.25L20.2,14.23L18.5,13.06L16.8,14.23L17.39,12.25L15.75,11L17.81,10.95L18.5,9L19.19,10.95L21.25,11M18.97,15.95C19.8,15.87 20.69,17.05 20.16,17.8C19.84,18.25 19.5,18.67 19.08,19.07C15.17,23 8.84,23 4.94,19.07C1.03,15.17 1.03,8.83 4.94,4.93C5.34,4.53 5.76,4.17 6.21,3.85C6.96,3.32 8.14,4.21 8.06,5.04C7.79,7.9 8.75,10.87 10.95,13.06C13.14,15.26 16.1,16.22 18.97,15.95M17.33,17.97C14.5,17.81 11.7,16.64 9.53,14.5C7.36,12.31 6.2,9.5 6.04,6.68C3.23,9.82 3.34,14.64 6.35,17.66C9.37,20.67 14.19,20.78 17.33,17.97Z" /></svg>'),
|
||||
};
|
||||
|
||||
// Get the current page’s title
|
||||
String getPageTitle() => querySelector('title').text;
|
||||
String getPageTitle() => querySelector('title')!.text!;
|
||||
|
||||
// Create the home button
|
||||
Future<Element> makeHome() async {
|
||||
|
@ -51,29 +45,27 @@ Future<Element> makeHome() async {
|
|||
'afterBegin',
|
||||
Element.a()
|
||||
..attributes['href'] = '/'
|
||||
..append(makeIcon(icons['home'])));
|
||||
..append(makeIcon(icons['home']!)));
|
||||
}
|
||||
|
||||
// Create a clickable icon
|
||||
// `t_elem` must be an SVG declared in the above `icons` variable.
|
||||
Element makeIcon(SvgElement t_elem) {
|
||||
final icon = t_elem..classes.add('nav-icon');
|
||||
return icon;
|
||||
return t_elem..classes.add('nav-icon');
|
||||
}
|
||||
|
||||
// Create the dropdown sitemap
|
||||
Future<Element> makePages() async {
|
||||
var pages = Element.ul()
|
||||
..attributes['id'] = 'drop-page'
|
||||
..classes.add('dropdown');
|
||||
return Element.li()
|
||||
..attributes['tabindex'] = '0'
|
||||
..append(Element.a()
|
||||
..attributes['tabindex'] = '-1'
|
||||
..attributes['href'] = 'javascript:void(0)'
|
||||
..append(makeIcon(icons['pages'])))
|
||||
..append(makeIcon(icons['pages']!)))
|
||||
..classes.addAll(['nav-item', 'has-dropdown'])
|
||||
..append(pages);
|
||||
..append(Element.ul()
|
||||
..attributes['id'] = 'drop-page'
|
||||
..classes.add('dropdown'));
|
||||
}
|
||||
|
||||
// Create the array of share icons
|
||||
|
@ -95,32 +87,34 @@ Future<Element> makeShare() async {
|
|||
..append(Element.a()
|
||||
..attributes['href'] = 'javascript:void(0)'
|
||||
..attributes['tabindex'] = '-1'
|
||||
..append(makeIcon(icons['share'])))
|
||||
..append(makeIcon(icons['share']!)))
|
||||
..append(Element.ul()
|
||||
..classes.add('dropdown')
|
||||
..attributes['id'] = 'drop-share'
|
||||
..append(makeShareLink(
|
||||
makeIcon(icons['twitter']),
|
||||
makeIcon(icons['twitter']!),
|
||||
'https://twitter.com/share?text=${getPageTitle()}'
|
||||
'&url=${window.location.href}'))
|
||||
..append(makeShareLink(makeIcon(icons['reddit']),
|
||||
..append(makeShareLink(makeIcon(icons['reddit']!),
|
||||
'https://www.reddit.com/submit?title=${getPageTitle()}s&url=${window.location.href}'))
|
||||
..append(makeShareLink(makeIcon(icons['email']),
|
||||
'mailto:?subject=${getPageTitle}&body=${window.location.href}'))
|
||||
..append(makeShareLink(makeIcon(icons['email']!),
|
||||
'mailto:?subject=$getPageTitle&body=${window.location.href}'))
|
||||
..append(makeShareLink(
|
||||
makeIcon(icons['linkedin']),
|
||||
makeIcon(icons['linkedin']!),
|
||||
'https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}'
|
||||
'&title=${getPageTitle()}'))
|
||||
..append(makeShareLink(makeIcon(icons['facebook']),
|
||||
..append(makeShareLink(makeIcon(icons['facebook']!),
|
||||
'https://www.facebook.com/sharer/sharer.php?u=${window.location.href}')));
|
||||
}
|
||||
|
||||
// Create the theme changer
|
||||
Future<Element> makeThemeChanger() async {
|
||||
Element makeThemeItem(String t_btnId, [Element t_icon]) {
|
||||
Element makeThemeItem(String t_btnId) {
|
||||
return Element.li()
|
||||
..classes.add('dropdown-item')
|
||||
..append(Element.span()..attributes['id'] = t_btnId);
|
||||
..append(Element.span()
|
||||
..attributes['id'] = t_btnId
|
||||
..classes.add('themeBtn'));
|
||||
}
|
||||
|
||||
return Element.li()
|
||||
|
@ -131,13 +125,13 @@ Future<Element> makeThemeChanger() async {
|
|||
..attributes['tabindex'] = '-1'
|
||||
..append(Element.span()
|
||||
..style.verticalAlign = 'top'
|
||||
..append(makeIcon(icons['theme']))))
|
||||
..append(makeIcon(icons['theme']!))))
|
||||
..append(Element.ul()
|
||||
..classes.add('dropdown')
|
||||
..attributes['id'] = 'theme-dropdown'
|
||||
..append(makeThemeItem('lightBtn', makeIcon(icons['sun'])))
|
||||
..append(makeThemeItem('darkBtn', makeIcon(icons['lightbulb'])))
|
||||
..append(makeThemeItem('blackBtn', makeIcon(icons['moon']))));
|
||||
..append(makeThemeItem('lightBtn'))
|
||||
..append(makeThemeItem('darkBtn'))
|
||||
..append(makeThemeItem('blackBtn')));
|
||||
}
|
||||
|
||||
// Create the dropdown table of contents
|
||||
|
@ -149,7 +143,7 @@ Future<Element> makeToc() async {
|
|||
..append(Element.a()
|
||||
..attributes['tabindex'] = '-1'
|
||||
..attributes['href'] = 'javascript:void(0)'
|
||||
..append(makeIcon(icons['toc'])));
|
||||
..append(makeIcon(icons['toc']!)));
|
||||
}
|
||||
|
||||
// Add a navbar atop of the HTML body, containing:
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import 'dart:html' as html show HttpRequest, Element, querySelector;
|
||||
|
||||
import 'package:html/parser.dart' show parse;
|
||||
import 'package:html/dom.dart' as dom show Element;
|
||||
import 'dart:html' show HttpRequest, Element, querySelector;
|
||||
|
||||
final excluded_keywords = {'index', 'CONTRIBUTING', 'LICENSE', 'README'};
|
||||
|
||||
|
@ -9,7 +6,7 @@ final excluded_keywords = {'index', 'CONTRIBUTING', 'LICENSE', 'README'};
|
|||
Future<String> fetchRemoteSitemap() async {
|
||||
const path = '/sitemap.html';
|
||||
try {
|
||||
return await html.HttpRequest.getString(path);
|
||||
return await HttpRequest.getString(path);
|
||||
} catch (e) {
|
||||
print('Couldn’t open $path');
|
||||
}
|
||||
|
@ -17,47 +14,48 @@ Future<String> fetchRemoteSitemap() async {
|
|||
}
|
||||
|
||||
// Parse the list of elements and detect pages from this list
|
||||
Map<String, String> detectPages(List<dom.Element> t_sitemap,
|
||||
[String t_prefix, Map<String, String> t_links]) {
|
||||
Map<String, String> detectPages(List<Element> t_sitemap,
|
||||
[String? t_prefix, Map<String, String>? t_links]) {
|
||||
t_links ??= <String, String>{};
|
||||
|
||||
// parse each element in sitemap
|
||||
for (var elem in t_sitemap) {
|
||||
// if it’s a link
|
||||
if (elem.innerHtml.startsWith('<a')) {
|
||||
elem = elem.firstChild;
|
||||
final url = elem.attributes['href'];
|
||||
final text = elem.firstChild.text;
|
||||
if (elem.innerHtml!.startsWith('<a')) {
|
||||
elem = elem.children[0];
|
||||
final url = elem.attributes['href']!;
|
||||
final text = elem.children[0].text;
|
||||
if (excluded_keywords.contains(text) ||
|
||||
excluded_keywords.contains(url.substring(0, url.length - 5))) {
|
||||
continue;
|
||||
}
|
||||
t_links['/$url'] = (t_prefix == null) ? text : '$text ($t_prefix)';
|
||||
t_links!['/$url'] = ((t_prefix == null) ? text : '$text ($t_prefix)')!;
|
||||
} else {
|
||||
final prefix = (t_prefix == null)
|
||||
? elem.firstChild.text.replaceAll('\n', '')
|
||||
: '$t_prefix / ${elem.firstChild.text}'.replaceAll('\n', '');
|
||||
? elem.firstChild!.text!.replaceAll('\n', '')
|
||||
: '$t_prefix / ${elem.firstChild!.text}'.replaceAll('\n', '');
|
||||
t_links = detectPages(elem.children[0].children, prefix, t_links);
|
||||
}
|
||||
}
|
||||
return t_links;
|
||||
return t_links!;
|
||||
}
|
||||
|
||||
// This function returns a Map which contains all links to languages detected
|
||||
// from the sitemap.
|
||||
Future<Map<String, String>> parseSitemap() async {
|
||||
final content = await fetchRemoteSitemap();
|
||||
final sitemap = parse(content).getElementsByClassName('org-ul')[0].children;
|
||||
return detectPages(sitemap);
|
||||
final sitemap = Element.ul()..innerHtml = content;
|
||||
final sitemapNodes = sitemap.querySelector('ul')!.children;
|
||||
return detectPages(sitemapNodes);
|
||||
}
|
||||
|
||||
Future<void> createSitemap() async {
|
||||
final sitemap = await parseSitemap();
|
||||
final pages = html.querySelector('#drop-page');
|
||||
final pages = querySelector('#drop-page')!;
|
||||
sitemap.forEach((url, name) {
|
||||
final link = html.Element.li()
|
||||
final link = Element.li()
|
||||
..classes.add('dropdown-item')
|
||||
..append(html.Element.a()
|
||||
..append(Element.a()
|
||||
..attributes['href'] = url
|
||||
..innerText = name);
|
||||
pages.append(link);
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
import 'dart:html';
|
||||
import 'dart:html'
|
||||
show DivElement, Element, querySelector, querySelectorAll, window;
|
||||
|
||||
import './navbar.dart' show makeNavbar;
|
||||
|
||||
const image_header = '/img/icon.png';
|
||||
const image_header = '/img/icon.webp';
|
||||
|
||||
Future<void> makeDecorativeButtonsOrgSrc() async {
|
||||
for (var pre in querySelectorAll('.org-src-container')) {
|
||||
pre
|
||||
..append(Element.div()..attributes['class'] = 'closeButton')
|
||||
..append(Element.div()..attributes['class'] = 'minButton')
|
||||
..append(Element.div()..attributes['class'] = 'maxButton')
|
||||
..append(Element.div()..attributes['class'] = 'floatButton');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Element> makeHeader() async {
|
||||
var header = Element.tag('header');
|
||||
|
@ -10,9 +21,9 @@ Future<Element> makeHeader() async {
|
|||
..append(Element.img()
|
||||
..attributes['src'] = image_header
|
||||
..attributes['alt'] = 'Logo'
|
||||
..attributes['heigh'] = '150px'
|
||||
..attributes['height'] = '150px'
|
||||
..attributes['width'] = '150px')
|
||||
..append(querySelector('h1'));
|
||||
..append(querySelector('h1')!);
|
||||
final subt = header.querySelector('.subtitle');
|
||||
if (subt != null) {
|
||||
header.append(subt);
|
||||
|
@ -31,8 +42,8 @@ Future<void> wrapTables() async {
|
|||
// All images that are not nested inside a link will be linkified to themselves.
|
||||
Future<void> linkifyImg() async {
|
||||
querySelectorAll('img').forEach((img) {
|
||||
if (img.parent.tagName == 'P') {
|
||||
final link = Element.a()..attributes['href'] = img.attributes['src'];
|
||||
if (img.parent!.tagName == 'P') {
|
||||
final link = Element.a()..attributes['href'] = img.attributes['src']!;
|
||||
img.insertAdjacentElement('beforeBegin', link);
|
||||
link.append(img);
|
||||
}
|
||||
|
@ -40,12 +51,22 @@ Future<void> linkifyImg() async {
|
|||
}
|
||||
|
||||
Future<void> reorganizeHtml() async {
|
||||
final ls = window.localStorage;
|
||||
final lastUpdate = '20210330';
|
||||
if (ls['last-update'] != lastUpdate) {
|
||||
ls['last-update'] = lastUpdate;
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
// Make navbar
|
||||
final navbar = await makeNavbar();
|
||||
|
||||
// Make header
|
||||
final header = await makeHeader();
|
||||
|
||||
// Add decorative divs to source block wrappers
|
||||
await makeDecorativeButtonsOrgSrc();
|
||||
|
||||
// wrap tables in container for better SCSS display
|
||||
await wrapTables();
|
||||
|
||||
|
@ -53,10 +74,10 @@ Future<void> reorganizeHtml() async {
|
|||
await linkifyImg();
|
||||
|
||||
// Add navbar to page
|
||||
querySelector('body').insertAdjacentElement('afterBegin', navbar);
|
||||
querySelector('body')!.insertAdjacentElement('afterBegin', navbar);
|
||||
|
||||
// Add headet to page
|
||||
querySelector('#content').insertAdjacentElement('beforeBegin', header);
|
||||
querySelector('#content')!.insertAdjacentElement('beforeBegin', header);
|
||||
|
||||
// Add correct class to TOC
|
||||
final toc = (querySelector('#table-of-contents') ??
|
||||
|
@ -64,7 +85,7 @@ Future<void> reorganizeHtml() async {
|
|||
..attributes['id'] = 'table-of-contents'
|
||||
..innerText = 'Table of Contents Unavailable'))
|
||||
..classes.add('dropdown');
|
||||
navbar.querySelector('#toc-drop').append(toc);
|
||||
navbar.querySelector('#toc-drop')!.append(toc);
|
||||
|
||||
// Remove all <br> tags from HTML
|
||||
querySelectorAll('br').forEach((br) => br.remove());
|
||||
|
|
|
@ -1,53 +1,20 @@
|
|||
import 'dart:html';
|
||||
|
||||
class Theme {
|
||||
String _name;
|
||||
String _icon;
|
||||
|
||||
Theme(String t_name, String t_icon) {
|
||||
_name = t_name;
|
||||
_icon = t_icon;
|
||||
}
|
||||
|
||||
String getIcon() => _icon;
|
||||
String getName() => _name;
|
||||
}
|
||||
|
||||
final themes = {
|
||||
'light': Theme('light', 'fa-sun'),
|
||||
'dark': Theme('dark', 'fa-lightbulb'),
|
||||
'black': Theme('black', 'fa-moon')
|
||||
};
|
||||
import 'dart:html' show window, querySelector;
|
||||
|
||||
final localStorage = window.localStorage;
|
||||
|
||||
Future<void> setTheme([String? theme]) async {
|
||||
theme ??= localStorage['theme'] ??
|
||||
(window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
? 'dark'
|
||||
: 'light');
|
||||
localStorage['theme'] = theme;
|
||||
querySelector('body')!
|
||||
..classes.clear()
|
||||
..classes.add(theme);
|
||||
}
|
||||
|
||||
void enableThemeChanger() {
|
||||
final darkBtn = querySelector('#darkBtn');
|
||||
final lightBtn = querySelector('#lightBtn');
|
||||
final blackBtn = querySelector('#blackBtn');
|
||||
|
||||
lightBtn.onClick.listen((_) => switchTheme(themes['light']));
|
||||
darkBtn.onClick.listen((_) => switchTheme(themes['dark']));
|
||||
blackBtn.onClick.listen((_) => switchTheme(themes['black']));
|
||||
}
|
||||
|
||||
Future<void> setTheme() async {
|
||||
final currentTheme = themes[localStorage['theme']] ??
|
||||
() {
|
||||
final devicePrefersDark =
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
return themes[devicePrefersDark ? 'dark' : 'light'];
|
||||
}();
|
||||
querySelector('body')
|
||||
..classes.clear()
|
||||
..classes.add(currentTheme.getName());
|
||||
}
|
||||
|
||||
void switchTheme(Theme currentTheme) {
|
||||
// Set HTML theme
|
||||
querySelector('body')
|
||||
..classes.clear()
|
||||
..classes.add(currentTheme.getName());
|
||||
// Set storage theme
|
||||
localStorage['theme'] = currentTheme.getName();
|
||||
final themes = <String>['light', 'dark', 'black'];
|
||||
themes.forEach((theme) =>
|
||||
querySelector('#${theme}Btn')!.onClick.listen((_) => setTheme(theme)));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
@import "themes.scss";
|
||||
@import "style.scss";
|
|
@ -1,4 +1,4 @@
|
|||
/* Variables *****************************************************************/
|
||||
// Variables //////////////////////////////////////////////////////////////////
|
||||
|
||||
$switch-small-screen: "only screen and (max-width: 600px)";
|
||||
$switch-smaller-screen: "only screen and (max-width: 400px)";
|
||||
|
@ -6,262 +6,7 @@ $switch-smaller-screen: "only screen and (max-width: 400px)";
|
|||
$navbar-height: 70px;
|
||||
$postamble-height: 55px;
|
||||
|
||||
$tooltip-underline-size: 3px;
|
||||
|
||||
// Themes /////////////////////////////////////////////////////////////////////
|
||||
|
||||
$dark: rgba( 52, 73, 94, 1);
|
||||
$black: rgba( 0, 0, 0, 1);
|
||||
$accent1: rgba( 93, 115, 126, 1);
|
||||
$accent2: rgba( 92, 172, 126, 1);
|
||||
$accent3: rgba(197, 193, 155, 1);
|
||||
$light: #eee;
|
||||
$grey1: #f8f8f8;
|
||||
$grey2: #dbe1e8;
|
||||
$grey3: #b2becd;
|
||||
$grey4: #6c7983;
|
||||
$grey5: #454e56;
|
||||
$grey6: #12181b;
|
||||
|
||||
// Accent 1
|
||||
// Black
|
||||
$gradient-accent1-black-left: linear-gradient(to left, $black, $accent1, $accent1);
|
||||
$gradient-accent1-black-right: linear-gradient(to right, $black, $accent1, $accent1);
|
||||
// Dark
|
||||
$gradient-accent1-dark-left: linear-gradient(to left, $dark, $accent1);
|
||||
$gradient-accent1-dark-right: linear-gradient(to right, $dark, $accent1);
|
||||
// Light
|
||||
$gradient-accent1-light-left: linear-gradient(to left, $light, $accent1);
|
||||
$gradient-accent1-light-right: linear-gradient(to right, $light, $accent1);
|
||||
// Accent 2
|
||||
// Black
|
||||
$gradient-accent2-black-left: linear-gradient(to left, $black, $accent2, $accent2);
|
||||
$gradient-accent2-black-right: linear-gradient(to right, $black, $accent2, $accent2);
|
||||
// Dark
|
||||
$gradient-accent2-dark-left: linear-gradient(to left, $dark, $accent2);
|
||||
$gradient-accent2-dark-right: linear-gradient(to right, $dark, $accent2);
|
||||
// Light
|
||||
$gradient-accent2-light-left: linear-gradient(to left, $light, $accent2);
|
||||
$gradient-accent2-light-right: linear-gradient(to right, $light, $accent2);
|
||||
// Accent 3
|
||||
// Black
|
||||
$gradient-accent3-black-left: linear-gradient(to left, $black, $accent3, $accent3);
|
||||
$gradient-accent3-black-right: linear-gradient(to right, $black, $accent3, $accent3);
|
||||
// Dark
|
||||
$gradient-accent3-dark-left: linear-gradient(to left, $dark, $accent3);
|
||||
$gradient-accent3-dark-right: linear-gradient(to right, $dark, $accent3);
|
||||
// Light
|
||||
$gradient-accent3-light-left: linear-gradient(to left, $light, $accent3);
|
||||
$gradient-accent3-light-right: linear-gradient(to right, $light, $accent3);
|
||||
|
||||
.light {
|
||||
$bg-nav: $gradient-accent3-light-right;
|
||||
$border-color: $accent1;
|
||||
|
||||
color: $dark;
|
||||
background: $light;
|
||||
|
||||
transition: background 500ms ease-in-out, color 1s ease-in-out;
|
||||
|
||||
pre {
|
||||
box-shadow: 3px 5px $dark;
|
||||
border-color: $light;
|
||||
}
|
||||
|
||||
pre.src {
|
||||
&::before {
|
||||
background-color: $light;
|
||||
color: $dark;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar, header {
|
||||
background: $bg-nav;
|
||||
}
|
||||
|
||||
.navbar svg {
|
||||
fill: $dark;
|
||||
}
|
||||
|
||||
.status {
|
||||
background: $gradient-accent3-light-left;
|
||||
color: $dark;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
border-bottom: $tooltip-underline-size dotted $accent3;
|
||||
|
||||
.tooltiptext {
|
||||
background-color: $accent3;
|
||||
color: $dark;
|
||||
|
||||
&::after {
|
||||
border-color: $accent3 transparent transparent transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
background: $accent3;
|
||||
color: $dark;
|
||||
}
|
||||
|
||||
#content {
|
||||
a {
|
||||
box-shadow: inset 0 -3px 0 $accent3;
|
||||
transition: box-shadow 300ms ease-in-out;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 -23px 0 $accent3;
|
||||
transition: box-shadow 300ms ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid $dark;
|
||||
}
|
||||
|
||||
th {
|
||||
background: darken($light, 5%);
|
||||
}
|
||||
|
||||
.gentree {
|
||||
filter: invert(0%);
|
||||
transition: filter 1s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.dark, .black {
|
||||
$bg-nav: $gradient-accent2-dark-right;
|
||||
$border-color: $dark;
|
||||
|
||||
color: $light;
|
||||
background: $dark;
|
||||
|
||||
transition: background 500ms ease-in-out, color 1s ease-in-out;
|
||||
|
||||
pre {
|
||||
box-shadow: 3px 3px $dark;
|
||||
border: none;
|
||||
}
|
||||
|
||||
pre.src {
|
||||
&::before {
|
||||
background-color: $dark;
|
||||
color: $light;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar, header {
|
||||
background: $bg-nav;
|
||||
}
|
||||
|
||||
.navbar svg {
|
||||
fill: $light;
|
||||
}
|
||||
|
||||
.status {
|
||||
background: $gradient-accent2-dark-left;
|
||||
color: $light;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
border-bottom: $tooltip-underline-size dotted $accent1;
|
||||
|
||||
.tooltiptext {
|
||||
background-color: $accent1;
|
||||
color: $light;
|
||||
|
||||
&::after {
|
||||
border-color: $accent1 transparent transparent transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
background: $dark;
|
||||
color: $light;
|
||||
}
|
||||
|
||||
#content {
|
||||
a {
|
||||
box-shadow: inset 0 -3px 0 $accent2;
|
||||
transition: box-shadow 300ms ease-in-out;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 -23px 0 $accent2;
|
||||
transition: box-shadow 300ms ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid $accent1;
|
||||
}
|
||||
|
||||
th {
|
||||
background: darken($dark, 2.5%);
|
||||
}
|
||||
|
||||
.gentree {
|
||||
filter: invert(100%);
|
||||
transition: filter 1s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.black {
|
||||
$bg-nav: $gradient-accent1-black-right;
|
||||
|
||||
background: $black;
|
||||
|
||||
pre {
|
||||
box-shadow: 3px 3px $light;
|
||||
border: none;
|
||||
}
|
||||
|
||||
pre.src {
|
||||
&::before {
|
||||
background-color: $black;
|
||||
color: $light;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar, header {
|
||||
background: $bg-nav;
|
||||
}
|
||||
|
||||
.status {
|
||||
background: $gradient-accent1-black-left;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
background: $dark;
|
||||
color: $light;
|
||||
}
|
||||
|
||||
#content {
|
||||
a {
|
||||
box-shadow: inset 0 -3px 0 $accent1;
|
||||
transition: box-shadow 300ms ease-in-out;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 -23px 0 $accent1;
|
||||
transition: box-shadow 300ms ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid $light;
|
||||
}
|
||||
|
||||
th {
|
||||
background: lighten($black, 15%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Style *********************************************************************/
|
||||
// Style //////////////////////////////////////////////////////////////////////
|
||||
|
||||
* {
|
||||
outline: none;
|
||||
|
@ -343,7 +88,6 @@ header {
|
|||
align-items: center;
|
||||
justify-content: space-around;
|
||||
min-height: 3rem;
|
||||
margin-top: 1rem;
|
||||
padding: 0.5rem;
|
||||
top: 0;
|
||||
|
||||
|
@ -363,22 +107,22 @@ header {
|
|||
}
|
||||
|
||||
#table-of-contents, #drop-page {
|
||||
top: $navbar-height / 1.3;
|
||||
top: $navbar-height;
|
||||
opacity: 1;
|
||||
z-index: 5;
|
||||
height: 500%;
|
||||
height: 80vh;
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#theme-dropdown {
|
||||
width: 150px;
|
||||
width: 250px;
|
||||
flex-direction: row;
|
||||
transform: translateX(-75%);
|
||||
}
|
||||
|
||||
#lightBtn, #darkBtn, #blackBtn {
|
||||
.themeBtn {
|
||||
content: ' ';
|
||||
border: 2px solid white;
|
||||
border-radius: 50%;
|
||||
|
@ -389,18 +133,6 @@ header {
|
|||
margin-right: 10px;
|
||||
}
|
||||
|
||||
#lightBtn {
|
||||
background: $light;
|
||||
}
|
||||
|
||||
#darkBtn {
|
||||
background: $dark;
|
||||
}
|
||||
|
||||
#blackBtn {
|
||||
background: $black;
|
||||
}
|
||||
|
||||
#drop-page, #table-of-contents {
|
||||
flex-direction: column;
|
||||
|
||||
|
@ -420,7 +152,7 @@ header {
|
|||
}
|
||||
}
|
||||
|
||||
#drop-share, #drop-page {
|
||||
#drop-share {
|
||||
li {
|
||||
padding: 10px;
|
||||
}
|
||||
|
@ -507,7 +239,10 @@ header {
|
|||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
text-align: center;
|
||||
font-family: serif;
|
||||
font-style: italic;
|
||||
margin-left: 2em;
|
||||
margin-right: 60px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
|
@ -597,9 +332,17 @@ th, td {
|
|||
padding: 10px;
|
||||
}
|
||||
|
||||
img {
|
||||
img, svg {
|
||||
max-height: 600px;
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
header > img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border-radius: 75px;
|
||||
}
|
||||
|
||||
.nav-icon {
|
||||
|
@ -615,8 +358,72 @@ ul {
|
|||
padding-inline-start: 20px;
|
||||
}
|
||||
|
||||
pre.src {
|
||||
background: $dark;
|
||||
color: $light;
|
||||
.org-src-container,
|
||||
pre {
|
||||
border-radius: .5em;
|
||||
}
|
||||
|
||||
.org-src-container {
|
||||
position: relative;
|
||||
padding-left: 1em;
|
||||
box-shadow: 3px 3px 10px rgba(0,0,0,.3);
|
||||
min-height: 5.5em;
|
||||
margin: 0 auto;
|
||||
width: -moz-fit-content;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
pre {
|
||||
width: -moz-fit-content;
|
||||
width: fit-content;
|
||||
border: none;
|
||||
box-shadow: none !important;
|
||||
margin: .5em;
|
||||
padding: 2.75em 1.5em !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
pre.src::before {
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
pre.src-fish::before {
|
||||
content: 'fish';
|
||||
}
|
||||
|
||||
pre.src-rust::before {
|
||||
content: 'Rust';
|
||||
}
|
||||
|
||||
.closeButton,
|
||||
.minButton,
|
||||
.maxButton,
|
||||
.floatButton {
|
||||
position: absolute;
|
||||
position: absolute;
|
||||
width: .8em;
|
||||
height: .8em;
|
||||
border-radius: .4em;
|
||||
z-index: 2;
|
||||
left: .3em;
|
||||
}
|
||||
|
||||
.closeButton {
|
||||
top: .3em;
|
||||
}
|
||||
|
||||
.minButton {
|
||||
top: 1.4em;
|
||||
}
|
||||
|
||||
.maxButton {
|
||||
top: 2.5em;
|
||||
}
|
||||
|
||||
.floatButton {
|
||||
bottom: .3em;
|
||||
}
|
||||
|
||||
.twitter-tweet {
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
// Variables //////////////////////////////////////////////////////////////////
|
||||
|
||||
$tooltip-underline-size: 3px;
|
||||
|
||||
// Themes /////////////////////////////////////////////////////////////////////
|
||||
|
||||
$nord0: #2e3440;
|
||||
$nord1: #3b4252;
|
||||
$nord2: #434c5e;
|
||||
$nord3: #4c566a;
|
||||
$nord4: #d8dee9;
|
||||
$nord5: #e5e9f0;
|
||||
$nord6: #eceff4;
|
||||
$nord7: #8fbcbb;
|
||||
$nord8: #88c0d0;
|
||||
$nord9: #81a1c1;
|
||||
$nord10: #5e81ac;
|
||||
$nord11: #bf616a;
|
||||
$nord12: #d08770;
|
||||
$nord13: #ebcb8b;
|
||||
$nord14: #a3be8c;
|
||||
$nord15: #b48ead;
|
||||
$dark: $nord1;
|
||||
$light: $nord5;
|
||||
$accent1: $nord7;
|
||||
$accent2: $nord9;
|
||||
$accent3: $nord8;
|
||||
|
||||
.light {
|
||||
$border-color: $accent1;
|
||||
|
||||
color: $dark;
|
||||
background: $light;
|
||||
|
||||
$bg-nav: linear-gradient(to right, $nord6, $nord4);
|
||||
.navbar, header, .dropdown {
|
||||
background: $bg-nav;
|
||||
color: $dark;
|
||||
}
|
||||
|
||||
.navbar svg {
|
||||
fill: $dark;
|
||||
}
|
||||
|
||||
transition: background 500ms ease-in-out, color 1s ease-in-out;
|
||||
|
||||
pre {
|
||||
border-color: $light;
|
||||
}
|
||||
|
||||
pre.src, pre.example {
|
||||
&::before {
|
||||
background-color: $nord6;
|
||||
color: $dark;
|
||||
}
|
||||
}
|
||||
|
||||
pre.src, pre.example, .org-src-container {
|
||||
background: $light;
|
||||
color: $dark;
|
||||
}
|
||||
|
||||
.status {
|
||||
background: $bg-nav;
|
||||
color: $dark;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
border-bottom: $tooltip-underline-size dotted $accent3;
|
||||
|
||||
.tooltiptext {
|
||||
background-color: $accent3;
|
||||
color: $dark;
|
||||
|
||||
&::after {
|
||||
border-color: $accent3 transparent transparent transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#content {
|
||||
a {
|
||||
box-shadow: inset 0 -3px 0 $accent3;
|
||||
transition: box-shadow 300ms ease-in-out;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 -23px 0 $accent3;
|
||||
transition: box-shadow 300ms ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid $dark;
|
||||
}
|
||||
|
||||
th {
|
||||
background: darken($light, 5%);
|
||||
}
|
||||
|
||||
.gentree {
|
||||
filter: invert(0%);
|
||||
transition: filter 1s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.black, .dark {
|
||||
$border-color: $nord1;
|
||||
|
||||
color: $nord6;
|
||||
background: $nord0;
|
||||
|
||||
$bg-nav: linear-gradient(to right, $nord3, $nord1);
|
||||
.navbar, header, .dropdown {
|
||||
background: $bg-nav;
|
||||
color: $light;
|
||||
}
|
||||
|
||||
.navbar svg {
|
||||
fill: $light;
|
||||
}
|
||||
|
||||
transition: background 500ms ease-in-out, color 1s ease-in-out;
|
||||
|
||||
pre {
|
||||
border: none;
|
||||
}
|
||||
|
||||
pre.src, pre.example {
|
||||
&::before {
|
||||
background-color: $nord0;
|
||||
color: $nord6;
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
background: $bg-nav;
|
||||
color: $nord6;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
border-bottom: $tooltip-underline-size dotted $nord7;
|
||||
|
||||
.tooltiptext {
|
||||
background-color: $nord7;
|
||||
color: $nord6;
|
||||
|
||||
&::after {
|
||||
border-color: $nord7 transparent transparent transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#content {
|
||||
a {
|
||||
box-shadow: inset 0 -3px 0 $nord7;
|
||||
transition: box-shadow 300ms ease-in-out;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 -23px 0 $nord7;
|
||||
transition: box-shadow 300ms ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid $nord7;
|
||||
}
|
||||
|
||||
th {
|
||||
background: darken($nord0, 2.5%);
|
||||
}
|
||||
|
||||
.gentree {
|
||||
filter: invert(100%);
|
||||
transition: filter 1s ease-in-out;
|
||||
}
|
||||
|
||||
pre.src, pre.example, .org-src-container {
|
||||
background: $nord1;
|
||||
color: $nord5;
|
||||
}
|
||||
}
|
||||
|
||||
.black {
|
||||
background: black;
|
||||
color: $nord4;
|
||||
|
||||
$bg-nav: linear-gradient(to right, $nord2, $nord0);
|
||||
.navbar, header, .dropdown {
|
||||
background: $bg-nav;
|
||||
}
|
||||
|
||||
pre.src, pre.example, .org-src-container {
|
||||
background: $nord0;
|
||||
color: $nord4;
|
||||
}
|
||||
}
|
||||
|
||||
#lightBtn {
|
||||
background: $light;
|
||||
}
|
||||
|
||||
#darkBtn {
|
||||
background: $nord0;
|
||||
}
|
||||
|
||||
#blackBtn {
|
||||
background: black;
|
||||
}
|
||||
|
||||
pre {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.closeButton {
|
||||
background-color: $nord11;
|
||||
}
|
||||
|
||||
.minButton {
|
||||
background-color: $nord12;
|
||||
}
|
||||
|
||||
.maxButton {
|
||||
background-color: $nord14;
|
||||
}
|
||||
|
||||
.floatButton {
|
||||
background-color: $nord15;
|
||||
}
|
Reference in New Issue