dark theme support
This commit is contained in:
parent
8979719a1a
commit
1c524efbf7
96
build_static.php
Executable file
96
build_static.php
Executable file
@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env php8.1
|
||||
<?php
|
||||
|
||||
function gethash(string $path): string {
|
||||
return substr(sha1(file_get_contents($path)), 0, 8);
|
||||
}
|
||||
|
||||
function sassc(string $src_file, string $dst_file): int {
|
||||
$cmd = 'sassc -t compressed '.escapeshellarg($src_file).' '.escapeshellarg($dst_file);
|
||||
exec($cmd, $output, $code);
|
||||
return $code;
|
||||
}
|
||||
|
||||
function clean_css(string $file) {
|
||||
$output = $file.'.out';
|
||||
if (file_exists($output))
|
||||
unlink($output);
|
||||
|
||||
$cmd = ROOT.'/node_modules/clean-css-cli/bin/cleancss -O2 "all:on;mergeSemantically:on;restructureRules:on" '.escapeshellarg($file).' > '.escapeshellarg($output);
|
||||
system($cmd);
|
||||
|
||||
if (file_exists($output)) {
|
||||
unlink($file);
|
||||
rename($output, $file);
|
||||
} else {
|
||||
fwrite(STDERR, "error: could not cleancss $file\n");
|
||||
}
|
||||
}
|
||||
|
||||
function dark_diff(string $light_file, string $dark_file): void {
|
||||
$temp_output = $dark_file.'.diff';
|
||||
$cmd = ROOT.'/dark-theme-diff.js '.escapeshellarg($light_file).' '.$dark_file.' > '.$temp_output;
|
||||
exec($cmd, $output, $code);
|
||||
if ($code != 0) {
|
||||
fwrite(STDERR, "dark_diff failed with code $code\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unlink($dark_file);
|
||||
rename($temp_output, $dark_file);
|
||||
}
|
||||
|
||||
require __DIR__.'/init.php';
|
||||
|
||||
function build_static(): void {
|
||||
$css_dir = ROOT.'/htdocs/css';
|
||||
$hashes = [];
|
||||
|
||||
if (!file_exists($css_dir))
|
||||
mkdir($css_dir);
|
||||
|
||||
// 1. scss -> css
|
||||
$themes = ['light', 'dark'];
|
||||
$entries = ['common', 'admin'];
|
||||
foreach ($themes as $theme) {
|
||||
foreach ($entries as $entry) {
|
||||
$input = ROOT.'/htdocs/scss/entries/'.$entry.'/'.$theme.'.scss';
|
||||
$output = $css_dir.'/'.$entry.($theme == 'dark' ? '_dark' : '').'.css';
|
||||
if (sassc($input, $output) != 0) {
|
||||
fwrite(STDERR, "error: could not compile entries/$entry/$theme.scss\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1.1. apply clean-css optimizations and transformations
|
||||
clean_css($output);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. generate dark theme diff
|
||||
foreach ($entries as $entry) {
|
||||
$light_file = $css_dir.'/'.$entry.'.css';
|
||||
$dark_file = str_replace('.css', '_dark.css', $light_file);
|
||||
dark_diff($light_file, $dark_file);
|
||||
}
|
||||
|
||||
// 3. calculate hashes
|
||||
foreach (['css', 'js'] as $type) {
|
||||
$reldir = ROOT.'/htdocs/';
|
||||
$entries = glob_recursive($reldir.$type.'/*.'.$type);
|
||||
if (empty($entries)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($entries as $file) {
|
||||
$name = preg_replace('/^'.preg_quote($reldir, '/').'/', '', $file);
|
||||
$hashes[$name] = gethash($file);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. write config-static.php
|
||||
$scfg = "<?php\n\n";
|
||||
$scfg .= "return ".var_export($hashes, true).";\n";
|
||||
|
||||
file_put_contents(ROOT.'/config-static.php', $scfg);
|
||||
}
|
||||
|
||||
build_static();
|
14
dark-theme-diff.js
Executable file
14
dark-theme-diff.js
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env node
|
||||
const {generateCSSPatch} = require('css-patch')
|
||||
const fs = require('fs')
|
||||
|
||||
const files = process.argv.slice(2)
|
||||
if (files.length !== 2) {
|
||||
console.log(`usage: ${process.argv[0]} file1 file2`)
|
||||
process.exit()
|
||||
}
|
||||
|
||||
const css1 = fs.readFileSync(files[0], 'utf-8')
|
||||
const css2 = fs.readFileSync(files[1], 'utf-8')
|
||||
|
||||
console.log(generateCSSPatch(css1, css2))
|
@ -25,7 +25,12 @@ git reset --hard
|
||||
git pull origin master
|
||||
|
||||
composer8.1 install --no-dev --optimize-autoloader --ignore-platform-reqs
|
||||
$PHP prepare_static.php
|
||||
|
||||
if [ ! -d node_modules ]; then
|
||||
npm i
|
||||
fi
|
||||
|
||||
$PHP build_static.php
|
||||
|
||||
cp "$DEV_DIR/config-local.php" .
|
||||
cat config-local.php | grep -v is_dev | tee config-local.php >/dev/null
|
||||
|
@ -39,11 +39,14 @@ class RequestDispatcher {
|
||||
}
|
||||
|
||||
$skin = new Skin();
|
||||
$skin->static[] = '/css/common-bundle.css';
|
||||
$skin->static[] = '/css/common.css';
|
||||
$skin->static[] = '/js/common.js';
|
||||
|
||||
$lang = LangData::getInstance();
|
||||
$skin->addLangKeys($lang->search('/^theme_/'));
|
||||
|
||||
/** @var RequestHandler $handler */
|
||||
$handler = new $handler_class($skin, LangData::getInstance(), $router_input);
|
||||
$handler = new $handler_class($skin, $lang, $router_input);
|
||||
$resp = $handler->beforeDispatch();
|
||||
if ($resp instanceof Response) {
|
||||
$resp->send();
|
||||
|
@ -23,11 +23,16 @@ class Skin {
|
||||
else
|
||||
$js = null;
|
||||
|
||||
$theme = ($_COOKIE['theme'] ?? 'auto');
|
||||
if (!in_array($theme, ['auto', 'dark', 'light']))
|
||||
$theme = 'auto';
|
||||
|
||||
$layout_ctx = new SkinContext('\\skin\\base');
|
||||
$lang = $this->getLang();
|
||||
$lang = !empty($lang) ? json_encode($lang, JSON_UNESCAPED_UNICODE) : '';
|
||||
return new Response(200, $layout_ctx->layout(
|
||||
static: $this->static,
|
||||
theme: $theme,
|
||||
title: $this->title,
|
||||
opts: $this->options,
|
||||
js: $js,
|
||||
|
@ -53,10 +53,12 @@ class SkinContext extends SkinBase {
|
||||
return call_user_func_array($fn, $arguments);
|
||||
}
|
||||
|
||||
public function __get(string $name) {
|
||||
public function &__get(string $name) {
|
||||
$fn = $this->ns.'\\'.$name;
|
||||
if (function_exists($fn))
|
||||
return [$this, $name];
|
||||
if (function_exists($fn)) {
|
||||
$f = [$this, $name];
|
||||
return $f;
|
||||
}
|
||||
|
||||
if (array_key_exists($name, $this->data))
|
||||
return $this->data[$name];
|
||||
|
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="9.474"><path d="M0 4.737l4.737 4.737 1.105-1.106L3 5.526h12V.79h-1.579v3.158H3l2.842-2.842L4.737 0z"/></svg>
|
Before Width: | Height: | Size: 168 B |
@ -14,6 +14,39 @@ if (!String.prototype.endsWith) {
|
||||
};
|
||||
}
|
||||
|
||||
if (!Object.assign) {
|
||||
Object.defineProperty(Object, 'assign', {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: function(target, firstSource) {
|
||||
'use strict';
|
||||
if (target === undefined || target === null) {
|
||||
throw new TypeError('Cannot convert first argument to object');
|
||||
}
|
||||
|
||||
var to = Object(target);
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var nextSource = arguments[i];
|
||||
if (nextSource === undefined || nextSource === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var keysArray = Object.keys(Object(nextSource));
|
||||
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
|
||||
var nextKey = keysArray[nextIndex];
|
||||
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
|
||||
if (desc !== undefined && desc.enumerable) {
|
||||
to[nextKey] = nextSource[nextKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
return to;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// AJAX
|
||||
//
|
||||
@ -87,7 +120,7 @@ if (!String.prototype.endsWith) {
|
||||
break;
|
||||
}
|
||||
|
||||
opts = extend({}, defaultOpts, opts);
|
||||
opts = Object.assign({}, defaultOpts, opts);
|
||||
|
||||
var xhr = createXMLHttpRequest();
|
||||
xhr.open(method, url);
|
||||
@ -244,11 +277,11 @@ function setCookie(name, value, days) {
|
||||
date.setTime(date.getTime() + (days*24*60*60*1000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
||||
document.cookie = name + "=" + (value || "") + expires + "; domain=" + window.appConfig.cookieHost + "; path=/";
|
||||
}
|
||||
|
||||
function unsetCookie(name) {
|
||||
document.cookie = name+'=; Max-Age=-99999999;';
|
||||
document.cookie = name + '=; Max-Age=-99999999; domain=' + window.appConfig.cookieHost + "; path=/";
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
@ -312,6 +345,34 @@ function escape(str) {
|
||||
return pre.innerHTML;
|
||||
}
|
||||
|
||||
function parseUrl(uri) {
|
||||
var parser = document.createElement('a');
|
||||
parser.href = uri;
|
||||
|
||||
return {
|
||||
protocol: parser.protocol, // => "http:"
|
||||
host: parser.host, // => "example.com:3000"
|
||||
hostname: parser.hostname, // => "example.com"
|
||||
port: parser.port, // => "3000"
|
||||
pathname: parser.pathname, // => "/pathname/"
|
||||
hash: parser.hash, // => "#hash"
|
||||
search: parser.search, // => "?search=test"
|
||||
origin: parser.origin, // => "http://example.com:3000"
|
||||
path: (parser.pathname || '') + (parser.search || '')
|
||||
}
|
||||
}
|
||||
|
||||
function once(fn, context) {
|
||||
var result;
|
||||
return function() {
|
||||
if (fn) {
|
||||
result = fn.apply(context || this, arguments);
|
||||
fn = null;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
@ -390,3 +451,229 @@ window.__lang = {};
|
||||
unsetCookie('is_retina');
|
||||
}
|
||||
})();
|
||||
|
||||
var StaticManager = {
|
||||
loadedStyles: [],
|
||||
versions: {},
|
||||
|
||||
setStyles: function(list, versions) {
|
||||
this.loadedStyles = list;
|
||||
this.versions = versions;
|
||||
},
|
||||
|
||||
loadStyle: function(name, theme, callback) {
|
||||
var url;
|
||||
if (!window.appConfig.devMode) {
|
||||
var filename = name + (theme === 'dark' ? '_dark' : '') + '.css';
|
||||
url = '/css/'+filename+'?'+this.versions[filename];
|
||||
} else {
|
||||
url = '/sass.php?name='+name+'&theme='+theme;
|
||||
}
|
||||
|
||||
var el = document.createElement('link');
|
||||
el.onerror = callback
|
||||
el.onload = callback
|
||||
el.setAttribute('rel', 'stylesheet');
|
||||
el.setAttribute('type', 'text/css');
|
||||
el.setAttribute('id', 'style_'+name+'_dark');
|
||||
el.setAttribute('href', url);
|
||||
|
||||
document.getElementsByTagName('head')[0].appendChild(el);
|
||||
}
|
||||
};
|
||||
|
||||
var ThemeSwitcher = (function() {
|
||||
/**
|
||||
* @type {string[]}
|
||||
*/
|
||||
var modes = ['auto', 'dark', 'light'];
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
var currentModeIndex = -1;
|
||||
|
||||
/**
|
||||
* @type {boolean|null}
|
||||
*/
|
||||
var systemState = null;
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isSystemModeSupported() {
|
||||
try {
|
||||
// crashes on:
|
||||
// Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; Lumia 630 Dual SIM) like Gecko
|
||||
// Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1
|
||||
// Mozilla/5.0 (iPad; CPU OS 12_5_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Mobile/15E148 Safari/604.1
|
||||
//
|
||||
// error examples:
|
||||
// - window.matchMedia("(prefers-color-scheme: dark)").addEventListener is not a function. (In 'window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",this.onSystemSettingChange.bind(this))', 'window.matchMedia("(prefers-color-scheme: dark)").addEventListener' is undefined)
|
||||
// - Object [object MediaQueryList] has no method 'addEventListener'
|
||||
return !!window['matchMedia']
|
||||
&& typeof window.matchMedia("(prefers-color-scheme: dark)").addEventListener === 'function';
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isDarkModeApplied() {
|
||||
var st = StaticManager.loadedStyles;
|
||||
for (var i = 0; i < st.length; i++) {
|
||||
var name = st[i];
|
||||
if (ge('style_'+name+'_dark'))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
function getSavedMode() {
|
||||
var val = getCookie('theme');
|
||||
if (!val)
|
||||
return modes[0];
|
||||
if (modes.indexOf(val) === -1) {
|
||||
console.error('[ThemeSwitcher getSavedMode] invalid cookie value')
|
||||
unsetCookie('theme')
|
||||
return modes[0]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} dark
|
||||
*/
|
||||
function changeTheme(dark) {
|
||||
addClass(document.body, 'theme-changing');
|
||||
|
||||
var onDone = function() {
|
||||
window.requestAnimationFrame(function() {
|
||||
removeClass(document.body, 'theme-changing');
|
||||
})
|
||||
};
|
||||
|
||||
window.requestAnimationFrame(function() {
|
||||
if (dark)
|
||||
enableDark(onDone);
|
||||
else
|
||||
disableDark(onDone);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function} callback
|
||||
*/
|
||||
function enableDark(callback) {
|
||||
var names = [];
|
||||
StaticManager.loadedStyles.forEach(function(name) {
|
||||
var el = ge('style_'+name+'_dark');
|
||||
if (el)
|
||||
return;
|
||||
names.push(name);
|
||||
});
|
||||
|
||||
var left = names.length;
|
||||
names.forEach(function(name) {
|
||||
StaticManager.loadStyle(name, 'dark', once(function(e) {
|
||||
left--;
|
||||
if (left === 0)
|
||||
callback();
|
||||
}));
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function} callback
|
||||
*/
|
||||
function disableDark(callback) {
|
||||
StaticManager.loadedStyles.forEach(function(name) {
|
||||
var el = ge('style_'+name+'_dark');
|
||||
if (el)
|
||||
el.remove();
|
||||
})
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} mode
|
||||
*/
|
||||
function setLabel(mode) {
|
||||
var labelEl = ge('theme-switcher-label');
|
||||
labelEl.innerHTML = escape(lang('theme_'+mode));
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
var cur = getSavedMode();
|
||||
currentModeIndex = modes.indexOf(cur);
|
||||
|
||||
var systemSupported = isSystemModeSupported();
|
||||
if (!systemSupported) {
|
||||
if (currentModeIndex === 0) {
|
||||
modes.shift(); // remove 'auto' from the list
|
||||
currentModeIndex = 1; // set to 'light'
|
||||
if (isDarkModeApplied())
|
||||
disableDark();
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* @param {boolean} dark
|
||||
*/
|
||||
var onSystemChange = function(dark) {
|
||||
var prevSystemState = systemState;
|
||||
systemState = dark;
|
||||
|
||||
if (modes[currentModeIndex] !== 'auto')
|
||||
return;
|
||||
|
||||
if (systemState !== prevSystemState)
|
||||
changeTheme(systemState);
|
||||
};
|
||||
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
|
||||
onSystemChange(e.matches === true)
|
||||
});
|
||||
|
||||
onSystemChange(window.matchMedia('(prefers-color-scheme: dark)').matches === true);
|
||||
}
|
||||
|
||||
setLabel(modes[currentModeIndex]);
|
||||
},
|
||||
|
||||
next: function(e) {
|
||||
if (hasClass(document.body, 'theme-changing')) {
|
||||
console.log('next: theme changing is in progress, ignoring...')
|
||||
return;
|
||||
}
|
||||
|
||||
currentModeIndex = (currentModeIndex + 1) % modes.length;
|
||||
switch (modes[currentModeIndex]) {
|
||||
case 'auto':
|
||||
if (systemState !== null)
|
||||
changeTheme(systemState);
|
||||
break;
|
||||
|
||||
case 'light':
|
||||
if (isDarkModeApplied())
|
||||
changeTheme(false);
|
||||
break;
|
||||
|
||||
case 'dark':
|
||||
if (!isDarkModeApplied())
|
||||
changeTheme(true);
|
||||
break;
|
||||
}
|
||||
|
||||
setLabel(modes[currentModeIndex]);
|
||||
setCookie('theme', modes[currentModeIndex]);
|
||||
|
||||
return cancelEvent(e);
|
||||
}
|
||||
};
|
||||
})();
|
@ -4,7 +4,14 @@ require __DIR__.'/../init.php';
|
||||
global $config;
|
||||
|
||||
$name = $_REQUEST['name'] ?? '';
|
||||
if (!$config['is_dev'] || !$name || !file_exists($path = ROOT.'/htdocs/scss/'.$name.'.scss')) {
|
||||
$theme = $_REQUEST['theme'] ?? '';
|
||||
|
||||
if ($theme != 'light' && $theme != 'dark') {
|
||||
http_response_code(403);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!$config['is_dev'] || !$name || !file_exists($path = ROOT.'/htdocs/scss/entries/'.$name.'/'.$theme.'.scss')) {
|
||||
// logError(__FILE__.': access denied');
|
||||
http_response_code(403);
|
||||
exit;
|
||||
|
@ -1,4 +1,4 @@
|
||||
@import 'vars';
|
||||
@import '../vars';
|
||||
|
||||
.blog-write-link-wrap {
|
||||
margin-bottom: $base-padding;
|
||||
@ -81,7 +81,7 @@
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.blog-upload-item-info {
|
||||
color: #888;
|
||||
color: $grey;
|
||||
font-size: $fs - 2px;
|
||||
}
|
||||
.blog-upload-item-note {
|
||||
@ -102,7 +102,7 @@
|
||||
}
|
||||
|
||||
.blog-post-date {
|
||||
color: #888;
|
||||
color: $grey;
|
||||
margin-top: 5px;
|
||||
font-size: $fs - 1px;
|
||||
> a {
|
||||
@ -168,7 +168,7 @@
|
||||
background-color: $code-block-bg;
|
||||
|
||||
span.term-prompt {
|
||||
color: #999;
|
||||
color: $light-grey;
|
||||
@include user-select(none);
|
||||
}
|
||||
}
|
||||
@ -177,7 +177,7 @@
|
||||
border-left: 3px #e0e0e0 solid;
|
||||
margin-left: 0;
|
||||
padding: 5px 0 5px 12px;
|
||||
color: #888;
|
||||
color: $grey;
|
||||
}
|
||||
|
||||
table.table-100 {
|
||||
@ -266,7 +266,7 @@
|
||||
.blog-post-comments {
|
||||
margin-top: $base-padding;
|
||||
padding: 12px 15px;
|
||||
border: 1px #e0e0e0 solid;
|
||||
border: 1px $border-color solid;
|
||||
@include radius(3px);
|
||||
}
|
||||
.blog-post-comments img {
|
||||
@ -317,7 +317,7 @@ td.blog-item-date-cell {
|
||||
padding-right: 10px;
|
||||
}
|
||||
.blog-item-date {
|
||||
color: #777;
|
||||
color: $grey;
|
||||
//text-transform: lowercase;
|
||||
}
|
||||
td.blog-item-title-cell {
|
||||
@ -344,6 +344,8 @@ td.blog-item-title-cell {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
a.blog-item-view-all-link {
|
||||
display: inline-block;
|
||||
padding: 4px 17px;
|
||||
@ -356,7 +358,7 @@ a.blog-item-view-all-link:hover {
|
||||
text-decoration: none;
|
||||
background-color: #ededed;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
.blog-tags {
|
||||
float: right;
|
||||
@ -374,7 +376,7 @@ a.blog-item-view-all-link:hover {
|
||||
font-size: $fs - 1px;
|
||||
}
|
||||
.blog-tag-item > a {
|
||||
color: #222;
|
||||
color: $fg;
|
||||
}
|
||||
.blog-tag-item-count {
|
||||
color: #aaa;
|
@ -1,4 +1,4 @@
|
||||
@import "vars";
|
||||
@import "../vars";
|
||||
|
||||
.clearfix:after {
|
||||
content: ".";
|
||||
@ -13,7 +13,7 @@ html, body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
//background-color: $bg;
|
||||
background-color: $bg;
|
||||
color: $fg;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
@ -35,13 +35,15 @@ body.full-width .base-width {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
input[type="text"], textarea {
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
box-sizing: border-box;
|
||||
border: 1px $input-border solid;
|
||||
border-radius: 0px;
|
||||
border-radius: 0;
|
||||
background-color: $input-bg;
|
||||
color: $fg;
|
||||
font-family: $ff;
|
||||
@ -49,14 +51,16 @@ input[type="text"], textarea {
|
||||
padding: 6px;
|
||||
outline: none;
|
||||
@include radius(3px);
|
||||
|
||||
&:focus {
|
||||
border-color: $input-border-focused;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
input[type="text"]:focus,
|
||||
textarea:focus {
|
||||
border-color: $input-border-focused;
|
||||
}
|
||||
|
||||
//input[type="checkbox"] {
|
||||
// margin-left: 0;
|
||||
//}
|
||||
@ -110,137 +114,6 @@ p, p code {
|
||||
padding: $base-padding 0;
|
||||
}
|
||||
|
||||
.head {
|
||||
padding: 0 $side-padding;
|
||||
}
|
||||
.head-inner {
|
||||
//padding: 13px 0;
|
||||
position: relative;
|
||||
border-bottom: 2px $border-color solid;
|
||||
}
|
||||
.head-logo {
|
||||
padding: 4px 0;
|
||||
font-family: $ffMono;
|
||||
font-size: 15px;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
background-color: transparent;
|
||||
@include transition(background-color, 0.03s);
|
||||
}
|
||||
.head-logo {
|
||||
padding: 16px 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
.head-logo:after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 40px;
|
||||
position: absolute;
|
||||
right: -40px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
border-left: 8px #fff solid;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(to left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%); /* W3C */
|
||||
}
|
||||
.head-logo > a {
|
||||
color: $fg;
|
||||
font-size: 14px;
|
||||
}
|
||||
.head-logo > a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.head-logo-enter {
|
||||
display: inline;
|
||||
opacity: 0;
|
||||
font-size: 11px;
|
||||
position: relative;
|
||||
background: #eee;
|
||||
padding: 2px 5px;
|
||||
color: #333;
|
||||
font-weight: normal;
|
||||
vertical-align: middle;
|
||||
top: -1px;
|
||||
@include transition(opacity, 0.03s);
|
||||
}
|
||||
.head-logo-enter-icon {
|
||||
width: 12px;
|
||||
height: 7px;
|
||||
display: inline-block;
|
||||
background: url(/img/enter.svg) 0 0 no-repeat;
|
||||
background-size: 12px 7px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.head-logo > a:hover .head-logo-enter {
|
||||
opacity: 1;
|
||||
}
|
||||
.head-logo-path {
|
||||
color: $fg;
|
||||
font-weight: bold;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
@include transition(color, 0.03s);
|
||||
}
|
||||
.head-logo > a:hover .head-logo-path:not(.alwayshover) {
|
||||
color: #aaa;
|
||||
}
|
||||
.head-logo-path:not(.neverhover):hover {
|
||||
color: #000 !important;
|
||||
}
|
||||
.head-logo-dolsign {
|
||||
color: $head-green-color;
|
||||
font-weight: normal;
|
||||
&.is_root {
|
||||
color: $head-red-color;
|
||||
}
|
||||
}
|
||||
.head-logo-cd {
|
||||
display: none;
|
||||
}
|
||||
.head-logo > a:hover .head-logo-cd {
|
||||
display: inline;
|
||||
}
|
||||
.head-logo-path-mapped {
|
||||
padding: 3px 5px;
|
||||
background: #f1f1f1;
|
||||
pointer-events: none;
|
||||
@include radius(3px);
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.head-items {
|
||||
float: right;
|
||||
color: #777; // color of separators
|
||||
//padding: 8px 0;
|
||||
}
|
||||
a.head-item {
|
||||
color: $fg;
|
||||
font-size: $fs - 1px;
|
||||
display: block;
|
||||
float: left;
|
||||
padding: 16px 0;
|
||||
}
|
||||
a.head-item > span {
|
||||
padding: 0 12px;
|
||||
border-right: 1px #d0d0d0 solid;
|
||||
}
|
||||
a.head-item > span > span {
|
||||
padding: 2px 0;
|
||||
}
|
||||
a.head-item:last-child > span {
|
||||
border-right: 0;
|
||||
padding-right: 1px;
|
||||
}
|
||||
/*a.head-item:first-child > span {
|
||||
padding-left: 2px;
|
||||
}*/
|
||||
a.head-item:hover {
|
||||
//color: $link-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
a.head-item:hover > span > span {
|
||||
border-bottom: 1px #d0d0d0 solid;
|
||||
}
|
||||
|
||||
table.contacts {
|
||||
border: 0;
|
||||
@ -257,17 +130,17 @@ table.contacts td {
|
||||
table.contacts td.label {
|
||||
text-align: right;
|
||||
width: 30%;
|
||||
color: #777;
|
||||
color: $dark-grey;
|
||||
}
|
||||
table.contacts td.value {
|
||||
text-align: left;
|
||||
padding-left: 8px;
|
||||
}
|
||||
table.contacts td.value span {
|
||||
background: #eee;
|
||||
background: $inline-code-block-bg;
|
||||
padding: 3px 7px 4px;
|
||||
border-radius: 3px;
|
||||
color: #333;
|
||||
color: $fg;
|
||||
font-family: $ffMono;
|
||||
font-size: $fs - 1px;
|
||||
}
|
||||
@ -283,13 +156,14 @@ table.contacts td pre {
|
||||
table.contacts div.note {
|
||||
font-size: $fs - 3px;
|
||||
padding-top: 2px;
|
||||
color: #777;
|
||||
color: $dark-grey;
|
||||
> a {
|
||||
color: #777;
|
||||
border-bottom: 1px #ccc solid;
|
||||
color: $dark-grey;
|
||||
border-bottom: 1px $border-color solid;
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
border-bottom-color: #999;
|
||||
color: $link-color;
|
||||
border-bottom-color: $link-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -360,11 +234,11 @@ table.contacts div.note {
|
||||
//font-weight: bold;
|
||||
}
|
||||
.md-file-attach-size {
|
||||
color: #888;
|
||||
color: $grey;
|
||||
margin-left: 2px;
|
||||
}
|
||||
.md-file-attach-note {
|
||||
color: #000;
|
||||
color: $fg;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
@ -402,7 +276,7 @@ table.contacts div.note {
|
||||
}
|
||||
.md-image-note {
|
||||
line-height: 150%;
|
||||
color: #777;
|
||||
color: $dark-grey;
|
||||
padding: 2px 0 4px;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
@import 'vars';
|
||||
@import '../vars';
|
||||
|
||||
$form-field-label-width: 120px;
|
||||
|
||||
@ -35,7 +35,7 @@ form { display: block; margin: 0; }
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
color: #888;
|
||||
color: $grey;
|
||||
}
|
||||
.form-field {
|
||||
//margin-left: $form-field-label-width + 10px;
|
157
htdocs/scss/app/head.scss
Normal file
157
htdocs/scss/app/head.scss
Normal file
@ -0,0 +1,157 @@
|
||||
.head {
|
||||
padding: 0 $side-padding;
|
||||
}
|
||||
.head-inner {
|
||||
//padding: 13px 0;
|
||||
position: relative;
|
||||
border-bottom: 2px $border-color solid;
|
||||
}
|
||||
.head-logo {
|
||||
padding: 4px 0;
|
||||
font-family: $ffMono;
|
||||
font-size: 15px;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
body:not(.theme-changing) .head-logo {
|
||||
@include transition(background-color, 0.03s);
|
||||
}
|
||||
.head-logo {
|
||||
padding: 16px 0;
|
||||
background-color: $bg;
|
||||
}
|
||||
.head-logo:after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 40px;
|
||||
position: absolute;
|
||||
right: -40px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
border-left: 8px $bg solid;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(to left, rgba($bg, 0) 0%, rgba($bg, 1) 100%); /* W3C */
|
||||
}
|
||||
.head-logo > a {
|
||||
color: $fg;
|
||||
font-size: 14px;
|
||||
}
|
||||
.head-logo > a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.head-logo-enter {
|
||||
background: $code-block-bg;
|
||||
color: $hljs_fg;
|
||||
display: inline;
|
||||
opacity: 0;
|
||||
font-size: 11px;
|
||||
position: relative;
|
||||
padding: 2px 5px;
|
||||
font-weight: normal;
|
||||
vertical-align: middle;
|
||||
top: -1px;
|
||||
}
|
||||
body:not(.theme-changing) .head-logo-enter {
|
||||
@include transition(opacity, 0.03s);
|
||||
}
|
||||
.head-logo-enter-icon {
|
||||
width: 12px;
|
||||
height: 7px;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
|
||||
> svg {
|
||||
path {
|
||||
fill: $hljs_fg;
|
||||
}
|
||||
}
|
||||
}
|
||||
.head-logo > a:hover .head-logo-enter {
|
||||
opacity: 1;
|
||||
}
|
||||
.head-logo-path {
|
||||
color: $fg;
|
||||
font-weight: bold;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
body:not(.theme-changing) .head-logo-path {
|
||||
@include transition(color, 0.03s);
|
||||
}
|
||||
.head-logo > a:hover .head-logo-path:not(.alwayshover) {
|
||||
color: $light_grey;
|
||||
}
|
||||
.head-logo-path:not(.neverhover):hover {
|
||||
color: $fg !important;
|
||||
}
|
||||
.head-logo-dolsign {
|
||||
color: $head_green_color;
|
||||
font-weight: normal;
|
||||
&.is_root {
|
||||
color: $head_red_color;
|
||||
}
|
||||
}
|
||||
.head-logo-cd {
|
||||
display: none;
|
||||
}
|
||||
.head-logo > a:hover .head-logo-cd {
|
||||
display: inline;
|
||||
}
|
||||
.head-logo-path-mapped {
|
||||
padding: 3px 5px;
|
||||
background: #f1f1f1;
|
||||
pointer-events: none;
|
||||
@include radius(3px);
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.head-items {
|
||||
float: right;
|
||||
color: #777; // color of separators
|
||||
//padding: 8px 0;
|
||||
}
|
||||
a.head-item {
|
||||
color: $fg;
|
||||
font-size: $fs - 1px;
|
||||
display: block;
|
||||
float: left;
|
||||
padding: 16px 0;
|
||||
|
||||
> span {
|
||||
position: relative;
|
||||
padding: 0 12px;
|
||||
border-right: 1px $head-items-separator solid;
|
||||
|
||||
> span {
|
||||
padding: 2px 0;
|
||||
|
||||
> span.moon-icon {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
||||
> svg path {
|
||||
fill: $fg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-theme-switcher > span {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
&:last-child > span {
|
||||
border-right: 0;
|
||||
padding-right: 1px;
|
||||
}
|
||||
}
|
||||
a.head-item:hover {
|
||||
//color: $link-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
a.head-item:hover > span > span {
|
||||
border-bottom: 1px $head-items-separator solid;
|
||||
}
|
1
htdocs/scss/app/hljs.scss
Normal file
1
htdocs/scss/app/hljs.scss
Normal file
@ -0,0 +1 @@
|
||||
@import "../hljs/github.css";
|
@ -1,4 +1,4 @@
|
||||
@import 'vars';
|
||||
@import '../vars';
|
||||
|
||||
textarea {
|
||||
-webkit-overflow-scrolling: touch;
|
3
htdocs/scss/bundle_admin.scss
Normal file
3
htdocs/scss/bundle_admin.scss
Normal file
@ -0,0 +1,3 @@
|
||||
.admin-page {
|
||||
line-height: 155%;
|
||||
}
|
10
htdocs/scss/bundle_common.scss
Normal file
10
htdocs/scss/bundle_common.scss
Normal file
@ -0,0 +1,10 @@
|
||||
@import "./app/common";
|
||||
@import "./app/head";
|
||||
@import "./app/blog";
|
||||
@import "./app/form";
|
||||
@import "./app/pages";
|
||||
@import "./hljs/github.scss";
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
@import "./app/mobile";
|
||||
}
|
46
htdocs/scss/colors/dark.scss
Normal file
46
htdocs/scss/colors/dark.scss
Normal file
@ -0,0 +1,46 @@
|
||||
$head_green_color: #0bad19;
|
||||
$head_red_color: #e23636;
|
||||
$link-color: #71abe5;
|
||||
|
||||
$grey: #798086;
|
||||
$dark-grey: $grey;
|
||||
$light-grey: $grey;
|
||||
$fg: #eee;
|
||||
$bg: #222;
|
||||
|
||||
$code-block-bg: #394146;
|
||||
$inline-code-block-bg: #394146;
|
||||
|
||||
$light-bg: #464c4e;
|
||||
$dark-bg: #272C2D;
|
||||
$dark-fg: #999;
|
||||
|
||||
$input-border: #48535a;
|
||||
$input-border-focused: #48535a;
|
||||
$input-bg: #30373b;
|
||||
$border-color: #48535a;
|
||||
|
||||
$error-block-bg: #f9eeee;
|
||||
$error-block-fg: #d13d3d;
|
||||
|
||||
$success-block-bg: #eff5f0;
|
||||
$success-block-fg: #2a6f34;
|
||||
|
||||
$head-items-separator: #5e6264;
|
||||
|
||||
// colors from https://github.com/Kelbster/highlightjs-material-dark-theme/blob/master/css/materialdark.css
|
||||
$hljs_fg: #CDD3D8;
|
||||
$hljs_bg: #2B2B2D;
|
||||
$hljs_quote: #6272a4;
|
||||
$hljs_string: #f1fa8c;
|
||||
$hljs_literal: #bd93f9;
|
||||
$hljs_title: #75A5FF;
|
||||
$hljs_keyword: #C792EA;
|
||||
$hljs_type: #da4939;
|
||||
$hljs_tag: #abb2bf;
|
||||
$hljs_regexp: #F77669;
|
||||
$hljs_symbol: #C792EA;
|
||||
$hljs_builtin: #C792EA;
|
||||
$hljs_meta: #75A5FF;
|
||||
$hljs_deletion: #e6e1dc;
|
||||
$hljs_addition: #144212;
|
46
htdocs/scss/colors/light.scss
Normal file
46
htdocs/scss/colors/light.scss
Normal file
@ -0,0 +1,46 @@
|
||||
$head_green_color: #0bad19;
|
||||
$head_red_color: #ce1a1a;
|
||||
$link-color: #116fd4;
|
||||
|
||||
$grey: #888;
|
||||
$dark-grey: #777;
|
||||
$light-grey: #999;
|
||||
$fg: #222;
|
||||
$bg: #fff;
|
||||
|
||||
$code-block-bg: #f3f3f3;
|
||||
$inline-code-block-bg: #f1f1f1;
|
||||
|
||||
$light-bg: #464c4e;
|
||||
$dark-bg: #272C2D;
|
||||
$dark-fg: #999;
|
||||
|
||||
$input-border: #e0e0e0;
|
||||
$input-border-focused: #e0e0e0;
|
||||
$input-bg: #f7f7f7;
|
||||
$border-color: #e0e0e0;
|
||||
|
||||
$error-block-bg: #f9eeee;
|
||||
$error-block-fg: #d13d3d;
|
||||
|
||||
$success-block-bg: #eff5f0;
|
||||
$success-block-fg: #2a6f34;
|
||||
|
||||
$head-items-separator: #d0d0d0;
|
||||
|
||||
// github.com style (c) Vasily Polovnyov <vast@whiteants.net>
|
||||
$hljs_fg: #333;
|
||||
$hljs_bg: #f8f8f8;
|
||||
$hljs_quote: #998;
|
||||
$hljs_string: #d14;
|
||||
$hljs_literal: #008080;
|
||||
$hljs_title: #900;
|
||||
$hljs_keyword: $hljs_fg;
|
||||
$hljs_type: #458;
|
||||
$hljs_tag: #000080;
|
||||
$hljs_regexp: #009926;
|
||||
$hljs_symbol: #990073;
|
||||
$hljs_builtin: #0086b3;
|
||||
$hljs_meta: #999;
|
||||
$hljs_deletion: #fdd;
|
||||
$hljs_addition: #dfd;
|
@ -1,9 +0,0 @@
|
||||
@import "./common.scss";
|
||||
@import "./blog.scss";
|
||||
@import "./form.scss";
|
||||
@import "./hljs/github.scss";
|
||||
@import "./pages.scss";
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
@import "./mobile.scss";
|
||||
}
|
2
htdocs/scss/entries/admin/dark.scss
Normal file
2
htdocs/scss/entries/admin/dark.scss
Normal file
@ -0,0 +1,2 @@
|
||||
@import '../../colors/dark';
|
||||
@import '../../bundle_admin';
|
2
htdocs/scss/entries/admin/light.scss
Normal file
2
htdocs/scss/entries/admin/light.scss
Normal file
@ -0,0 +1,2 @@
|
||||
@import '../../colors/light';
|
||||
@import '../../bundle_admin';
|
2
htdocs/scss/entries/common/dark.scss
Normal file
2
htdocs/scss/entries/common/dark.scss
Normal file
@ -0,0 +1,2 @@
|
||||
@import '../../colors/dark';
|
||||
@import '../../bundle_common';
|
2
htdocs/scss/entries/common/light.scss
Normal file
2
htdocs/scss/entries/common/light.scss
Normal file
@ -0,0 +1,2 @@
|
||||
@import '../../colors/light';
|
||||
@import '../../bundle_common';
|
@ -1 +0,0 @@
|
||||
@import "./hljs/github.css";
|
@ -1,27 +1,21 @@
|
||||
/*
|
||||
|
||||
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #333;
|
||||
background: #f8f8f8;
|
||||
color: $hljs_fg;
|
||||
background: $hljs_bg;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #998;
|
||||
color: $hljs_quote;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-subst {
|
||||
color: #333;
|
||||
color: $hljs_fg;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@ -30,18 +24,18 @@ github.com style (c) Vasily Polovnyov <vast@whiteants.net>
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-tag .hljs-attr {
|
||||
color: #008080;
|
||||
color: $hljs_literal;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-doctag {
|
||||
color: #d14;
|
||||
color: $hljs_string;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-selector-id {
|
||||
color: #900;
|
||||
color: $hljs_title;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@ -51,43 +45,43 @@ github.com style (c) Vasily Polovnyov <vast@whiteants.net>
|
||||
|
||||
.hljs-type,
|
||||
.hljs-class .hljs-title {
|
||||
color: #458;
|
||||
color: $hljs_type;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-attribute {
|
||||
color: #000080;
|
||||
color: $hljs_tag;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-regexp,
|
||||
.hljs-link {
|
||||
color: #009926;
|
||||
color: $hljs_regexp;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #990073;
|
||||
color: $hljs_symbol;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name {
|
||||
color: #0086b3;
|
||||
color: $hljs_builtin;
|
||||
}
|
||||
|
||||
.hljs-meta {
|
||||
color: #999;
|
||||
color: $hljs_meta;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background: #fdd;
|
||||
background: $hljs_deletion;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background: #dfd;
|
||||
background: $hljs_addition;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
|
@ -4,42 +4,9 @@ $ff: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif;
|
||||
$ffMono: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;
|
||||
|
||||
$base-width: 900px;
|
||||
//$sb-width: 120px;
|
||||
$side-padding: 25px;
|
||||
$base-padding: 18px;
|
||||
|
||||
$footer-height: 64px;
|
||||
$head-green-color: #0bad19;
|
||||
$head-red-color: #ce1a1a;
|
||||
$link-color: #116fd4;
|
||||
|
||||
$bg: #f7f7f7;
|
||||
$content-bg: #fff;
|
||||
$code-block-bg: #f3f3f3;
|
||||
$inline-code-block-bg: #f1f1f1;
|
||||
|
||||
$fg: #222;
|
||||
$blue1: #729fcf;
|
||||
$blue2: #3465a4;
|
||||
$blue3: #204a87;
|
||||
$orange1: #fcaf3e;
|
||||
$orange2: #f57900;
|
||||
$orange3: #ce5c00;
|
||||
|
||||
$light-bg: #464c4e;
|
||||
$dark-bg: #272C2D;
|
||||
$dark-fg: #999;
|
||||
|
||||
$input-border: #e0e0e0;
|
||||
$input-border-focused: #e0e0e0;
|
||||
$input-bg: #f7f7f7;
|
||||
$border-color: #e0e0e0;
|
||||
|
||||
$error-block-bg: #f9eeee;
|
||||
$error-block-fg: #d13d3d;
|
||||
|
||||
$success-block-bg: #eff5f0;
|
||||
$success-block-fg: #2a6f34;
|
||||
|
||||
@mixin radius($radius) {
|
||||
-o-border-radius: $radius;
|
||||
|
@ -20,6 +20,11 @@ return [
|
||||
'delete' => 'delete',
|
||||
'info_saved' => 'Information saved.',
|
||||
|
||||
// theme switcher
|
||||
'theme_auto' => 'auto',
|
||||
'theme_dark' => 'dark',
|
||||
'theme_light' => 'light',
|
||||
|
||||
// contacts
|
||||
'contacts_email' => 'email',
|
||||
'contacts_pgp' => 'OpenPGP public key',
|
||||
|
@ -142,7 +142,7 @@ class Upload extends Model {
|
||||
if (is_file($dir.'/'.$f))
|
||||
unlink($dir.'/'.$f);
|
||||
else
|
||||
logError('deleteAllImagePreviews: '.$dir.'/'.$f.' is not a file!');
|
||||
logError(__METHOD__.': '.$dir.'/'.$f.' is not a file!');
|
||||
$deleted++;
|
||||
}
|
||||
}
|
||||
|
647
package-lock.json
generated
Normal file
647
package-lock.json
generated
Normal file
@ -0,0 +1,647 @@
|
||||
{
|
||||
"name": "www",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"devDependencies": {
|
||||
"clean-css": "^5.3.0",
|
||||
"clean-css-cli": "^5.6.0",
|
||||
"css-patch": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/clean-css": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz",
|
||||
"integrity": "sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"source-map": "~0.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/clean-css-cli": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-css-cli/-/clean-css-cli-5.6.0.tgz",
|
||||
"integrity": "sha512-68vorNEG808D1QzeerO9AlwQVTuaR8YSK4aqwIsjJq0wDSyPH11ApHY0O+EQrdEGUZcN+d72v+Nn/gpxjAFewQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chokidar": "^3.5.2",
|
||||
"clean-css": "^5.3.0",
|
||||
"commander": "7.x",
|
||||
"glob": "^7.1.6"
|
||||
},
|
||||
"bin": {
|
||||
"cleancss": "bin/cleancss"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/css-patch": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/css-patch/-/css-patch-1.2.0.tgz",
|
||||
"integrity": "sha512-wCIyPGugTmf10KO39QLD3N+qIum0ljrj/8pJdULjjuXQ6oEeYd5+quMF7jIdnEL5Ftp0wmbvO8qPvAmzrw0EaA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"diff": "^5.0.0",
|
||||
"stylis": "^4.0.13"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
|
||||
"integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"picomatch": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/stylis": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.1.tgz",
|
||||
"integrity": "sha512-lVrM/bNdhVX2OgBFNa2YJ9Lxj7kPzylieHd3TNjuGE0Re9JB7joL5VUKOVH1kdNNJTgGPpT8hmwIAPLaSyEVFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"fsevents": "~2.3.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
}
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz",
|
||||
"integrity": "sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"source-map": "~0.6.0"
|
||||
}
|
||||
},
|
||||
"clean-css-cli": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-css-cli/-/clean-css-cli-5.6.0.tgz",
|
||||
"integrity": "sha512-68vorNEG808D1QzeerO9AlwQVTuaR8YSK4aqwIsjJq0wDSyPH11ApHY0O+EQrdEGUZcN+d72v+Nn/gpxjAFewQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chokidar": "^3.5.2",
|
||||
"clean-css": "^5.3.0",
|
||||
"commander": "7.x",
|
||||
"glob": "^7.1.6"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
},
|
||||
"css-patch": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/css-patch/-/css-patch-1.2.0.tgz",
|
||||
"integrity": "sha512-wCIyPGugTmf10KO39QLD3N+qIum0ljrj/8pJdULjjuXQ6oEeYd5+quMF7jIdnEL5Ftp0wmbvO8qPvAmzrw0EaA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"diff": "^5.0.0",
|
||||
"stylis": "^4.0.13"
|
||||
}
|
||||
},
|
||||
"diff": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
|
||||
"integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
|
||||
"dev": true
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-glob": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true
|
||||
},
|
||||
"picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"stylis": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.1.tgz",
|
||||
"integrity": "sha512-lVrM/bNdhVX2OgBFNa2YJ9Lxj7kPzylieHd3TNjuGE0Re9JB7joL5VUKOVH1kdNNJTgGPpT8hmwIAPLaSyEVFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
7
package.json
Normal file
7
package.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"clean-css": "^5.3.0",
|
||||
"clean-css-cli": "^5.6.0",
|
||||
"css-patch": "^1.2.0"
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env php8.1
|
||||
<?php
|
||||
|
||||
function gethash(string $path): string {
|
||||
return substr(sha1(file_get_contents($path)), 0, 8);
|
||||
}
|
||||
|
||||
function sassc(string $src_dir, string $dst_dir, string $file): int {
|
||||
$cmd = 'sassc -t expanded '.escapeshellarg($src_dir.'/'.$file).' '.escapeshellarg($dst_dir.'/'.preg_replace('/\.scss$/', '.css', $file));
|
||||
exec($cmd, $output, $code);
|
||||
return $code;
|
||||
}
|
||||
|
||||
require __DIR__.'/init.php';
|
||||
global $config;
|
||||
|
||||
function build_static(): void {
|
||||
$css_dir = ROOT.'/htdocs/css';
|
||||
$hashes = [];
|
||||
|
||||
if (!file_exists($css_dir))
|
||||
mkdir($css_dir);
|
||||
|
||||
$files = ['common-bundle.scss', 'admin.scss'];
|
||||
foreach ($files as $file) {
|
||||
if (sassc(ROOT.'/htdocs/scss', $css_dir, $file) != 0)
|
||||
fwrite(STDERR, "error: could not compile $file\n");
|
||||
}
|
||||
|
||||
foreach (['css', 'js'] as $type) {
|
||||
$reldir = ROOT.'/htdocs/';
|
||||
$files = glob_recursive($reldir.$type.'/*.'.$type);
|
||||
if (empty($files)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
$name = preg_replace('/^'.preg_quote($reldir, '/').'/', '', $file);
|
||||
$hashes[$name] = gethash($file);
|
||||
}
|
||||
}
|
||||
|
||||
$scfg = "<?php\n\n";
|
||||
$scfg .= "return ".var_export($hashes, true).";\n";
|
||||
|
||||
file_put_contents(ROOT.'/config-static.php', $scfg);
|
||||
}
|
||||
|
||||
build_static();
|
@ -2,7 +2,17 @@
|
||||
|
||||
namespace skin\base;
|
||||
|
||||
function layout($ctx, $title, $unsafe_body, $static, $meta, $js, $opts, $exec_time, $unsafe_lang) {
|
||||
use admin;
|
||||
use RequestDispatcher;
|
||||
|
||||
function layout($ctx, $title, $unsafe_body, $static, $meta, $js, $opts, $exec_time, $unsafe_lang, $theme) {
|
||||
global $config;
|
||||
$app_config = json_encode([
|
||||
'domain' => $config['domain'],
|
||||
'devMode' => $config['is_dev'],
|
||||
'cookieHost' => $config['cookie_host'],
|
||||
]);
|
||||
|
||||
return <<<HTML
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
@ -12,16 +22,16 @@ return <<<HTML
|
||||
<link rel="shortcut icon" href="/favicon.ico?4" type="image/x-icon">
|
||||
<link rel="alternate" type="application/rss+xml" href="/feed.rss">
|
||||
<title>{$title}</title>
|
||||
<script type="text/javascript">window.appConfig = {$app_config};</script>
|
||||
{$ctx->renderMeta($meta)}
|
||||
{$ctx->renderStatic($static)}
|
||||
{$ctx->renderStatic($static, $theme)}
|
||||
</head>
|
||||
<body{$ctx->if_true($opts['full_width'], ' class="full-width"')}>
|
||||
{$ctx->renderHeader(renderLogo($ctx, $opts['logo_path_map'], $opts['logo_link_map']))}
|
||||
{$ctx->renderHeader($theme, renderLogo($ctx, $opts['logo_path_map'], $opts['logo_link_map']))}
|
||||
<div class="page-content base-width">
|
||||
<div class="page-content-inner">{$unsafe_body}</div>
|
||||
</div>
|
||||
{$ctx->if_true($js != '' || !empty($lang) || $opts['dynlogo_enabled'],
|
||||
$ctx->renderScript, $js, $unsafe_lang, $opts['dynlogo_enabled'])}
|
||||
{$ctx->renderScript($js, $unsafe_lang, $opts['dynlogo_enabled'])}
|
||||
</body>
|
||||
</html>
|
||||
<!--
|
||||
@ -32,11 +42,18 @@ HTML;
|
||||
}
|
||||
|
||||
function renderScript($ctx, $unsafe_js, $unsafe_lang, $enable_dynlogo) {
|
||||
global $config;
|
||||
|
||||
$styles = json_encode($ctx->styleNames);
|
||||
$versions = !$config['is_dev'] ? json_encode($config['static']) : '{}';
|
||||
|
||||
return <<<HTML
|
||||
<script type="text/javascript">
|
||||
StaticManager.setStyles({$styles}, {$versions});
|
||||
{$ctx->if_true($unsafe_js, '(function(){'.$unsafe_js.'})();')}
|
||||
{$ctx->if_true($unsafe_lang, 'extend(__lang, '.$unsafe_lang.');')}
|
||||
{$ctx->if_true($enable_dynlogo, 'DynamicLogo.init();')}
|
||||
ThemeSwitcher.init();
|
||||
</script>
|
||||
HTML;
|
||||
}
|
||||
@ -53,26 +70,76 @@ function renderMeta($ctx, $meta) {
|
||||
}, $meta));
|
||||
}
|
||||
|
||||
function renderStatic($ctx, $static) {
|
||||
function renderStatic($ctx, $static, $theme) {
|
||||
global $config;
|
||||
$html = [];
|
||||
$dark = $theme == 'dark';
|
||||
$ctx->styleNames = [];
|
||||
foreach ($static as $name) {
|
||||
// list($name, $options) = $item;
|
||||
$version = $config['is_dev'] ? time() : $config['static'][substr($name, 1)] ?? 'notfound';
|
||||
if (str_ends_with($name, '.js'))
|
||||
$html[] = jsLink($name, $version);
|
||||
else if (str_ends_with($name, '.css'))
|
||||
$html[] = cssLink($name, $version/*, $options*/);
|
||||
else if (str_ends_with($name, '.css')) {
|
||||
$html[] = cssLink($name, 'light', $version, $style_name);
|
||||
$ctx->styleNames[] = $style_name;
|
||||
|
||||
if ($dark)
|
||||
$html[] = cssLink($name, 'dark', $version, $style_name);
|
||||
else if (!$config['is_dev'])
|
||||
$html[] = cssPrefetchLink(str_replace('.css', '_dark.css', $name), $version);
|
||||
}
|
||||
}
|
||||
return implode("\n", $html);
|
||||
}
|
||||
|
||||
function renderHeader($ctx, $unsafe_logo_html) {
|
||||
function jsLink(string $name, $version = null): string {
|
||||
if ($version !== null)
|
||||
$name .= '?'.$version;
|
||||
return '<script src="'.$name.'" type="text/javascript"></script>';
|
||||
}
|
||||
|
||||
function cssLink(string $name, string $theme, $version = null, &$bname = null): string {
|
||||
global $config;
|
||||
|
||||
$dname = dirname($name);
|
||||
$bname = basename($name);
|
||||
if (($pos = strrpos($bname, '.')))
|
||||
$bname = substr($bname, 0, $pos);
|
||||
|
||||
if ($config['is_dev']) {
|
||||
$href = '/sass.php?name='.urlencode($bname).'&theme='.$theme;
|
||||
} else {
|
||||
$href = $dname.'/'.$bname.($theme == 'dark' ? '_dark' : '').'.css'.($version !== null ? '?'.$version : '');
|
||||
}
|
||||
$id = 'style_'.$bname;
|
||||
if ($theme == 'dark')
|
||||
$id .= '_dark';
|
||||
return '<link rel="stylesheet" id="'.$id.'" type="text/css" href="'.$href.'">';
|
||||
}
|
||||
|
||||
function cssPrefetchLink(string $name, $verison = null): string {
|
||||
$url = $name;
|
||||
if ($verison)
|
||||
$url .= '?'.$verison;
|
||||
return <<<HTML
|
||||
<link rel="prefetch" href="{$url}" />
|
||||
HTML;
|
||||
}
|
||||
|
||||
function renderHeader($ctx, $theme, $unsafe_logo_html) {
|
||||
return <<<HTML
|
||||
<div class="head base-width">
|
||||
<div class="head-inner clearfix">
|
||||
<div class="head-logo">{$unsafe_logo_html}</div>
|
||||
<div class="head-items clearfix">
|
||||
<a class="head-item is-theme-switcher" href="javascript:void(0)" onclick="return ThemeSwitcher.next(event)">
|
||||
<span>
|
||||
<span>
|
||||
<span class="moon-icon">{$ctx->renderMoonIcon()}</span><span id="theme-switcher-label">{$theme}</span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
<a class="head-item" href="/"><span><span>blog</span></span></a>
|
||||
<a class="head-item" href="/projects/"><span><span>projects</span></span></a>
|
||||
<a class="head-item" href="https://git.ch1p.io/?s=idle"><span><span>git</span></span></a>
|
||||
@ -87,9 +154,9 @@ HTML;
|
||||
|
||||
// TODO rewrite this fcking crap
|
||||
function renderLogo($ctx, array $path_map = [], array $link_map = []): string {
|
||||
$uri = \RequestDispatcher::path();
|
||||
$uri = RequestDispatcher::path();
|
||||
|
||||
if (!\admin::isAdmin()) {
|
||||
if (!admin::isAdmin()) {
|
||||
$prompt_sign = '<span class="head-logo-dolsign">$</span>';
|
||||
} else {
|
||||
$prompt_sign = '<span class="head-logo-dolsign is_root">#</span>';
|
||||
@ -143,7 +210,7 @@ function renderLogo($ctx, array $path_map = [], array $link_map = []): string {
|
||||
$last_pos = $pos + 1;
|
||||
$close_tags++;
|
||||
}
|
||||
$html .= str_repeat('</span>', $close_tags).' '.$prompt_sign.' <span class="head-logo-cd">cd <span id="head_cd_text">~</span> <span class="head-logo-enter"><span class="head-logo-enter-icon"></span>Enter</span></span></a>';
|
||||
$html .= str_repeat('</span>', $close_tags).' '.$prompt_sign.' <span class="head-logo-cd">cd <span id="head_cd_text">~</span> <span class="head-logo-enter"><span class="head-logo-enter-icon">'.enterIcon().'</span>Enter</span></span></a>';
|
||||
|
||||
for ($i = count($path_parts)-1, $j = 0; $i >= 0; $i--, $j++) {
|
||||
if (isset($path_map[$j])) {
|
||||
@ -169,25 +236,16 @@ function renderLogo($ctx, array $path_map = [], array $link_map = []): string {
|
||||
return $html;
|
||||
}
|
||||
|
||||
function jsLink(string $name, $version = null): string {
|
||||
if ($version !== null)
|
||||
$name .= '?'.$version;
|
||||
return '<script src="'.$name.'" type="text/javascript"></script>';
|
||||
function enterIcon() {
|
||||
return <<<SVG
|
||||
<svg width="12" height="7" viewBox="0 0 9.6 5.172" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M.4 2.586l2.779 2.8.648-.654-1.667-1.68H9.2V.253h-.926V2.12H2.16L3.827.44 3.18-.214z"/>
|
||||
</svg>
|
||||
SVG;
|
||||
}
|
||||
|
||||
function cssLink(string $name, $version = null/*, $options = null*/): string {
|
||||
global $config;
|
||||
if ($config['is_dev']) {
|
||||
$bname = basename($name);
|
||||
if (($pos = strrpos($bname, '.')))
|
||||
$bname = substr($bname, 0, $pos);
|
||||
$href = '/sass.php?name='.urlencode($bname);
|
||||
} else {
|
||||
$href = $name.($version !== null ? '?'.$version : '');
|
||||
}
|
||||
$s = '<link rel="stylesheet" type="text/css" href="'.$href.'"';
|
||||
// if (!is_null($options))
|
||||
// $s .= ' media="'.$options.'"';
|
||||
$s .= '>';
|
||||
return $s;
|
||||
function renderMoonIcon($ctx) {
|
||||
return <<<SVG
|
||||
<svg width="18" height="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.54 10.37a5.4 5.4 0 01-6.91-6.91.59.59 0 00-.74-.75 6.66 6.66 0 00-2.47 1.54 6.6 6.6 0 1010.87 6.86.59.59 0 00-.75-.74zm-1.61 2.39a5.44 5.44 0 01-7.69-7.69 5.58 5.58 0 011-.76 6.55 6.55 0 007.47 7.47 5.15 5.15 0 01-.78.98z" fill-rule="evenodd" /></svg>
|
||||
SVG;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user