diff --git a/.gitignore b/.gitignore index e749ffc..849e6d4 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ /vendor /node_modules /hanyuu.cfg +/public/assets +/assets/current.json +/public/error-*.html diff --git a/assets/errors.css/main.css b/assets/errors.css/main.css new file mode 100644 index 0000000..9886311 --- /dev/null +++ b/assets/errors.css/main.css @@ -0,0 +1,39 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + position: relative; +} + +html, body { + width: 100%; + height: 100%; +} + +body { + background-color: #111; + color: #fff; + font-size: 12px; + line-height: 20px; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; +} + +@media (prefers-color-scheme: light) { + body { + background-color: #ddd; + color: #000; + } +} + +.http-err { + padding: 40px 60px; +} +.http-err-title { + font-size: 3em; + line-height: 1.5em; + font-weight: 700; +} +.http-err-paragraph { + font-size: 1.2em; + line-height: 1.5em; +} diff --git a/public/assets/hanyuu.css b/assets/hanyuu.css/auth.css similarity index 77% rename from public/assets/hanyuu.css rename to assets/hanyuu.css/auth.css index e719060..dd6beeb 100644 --- a/public/assets/hanyuu.css +++ b/assets/hanyuu.css/auth.css @@ -1,46 +1,3 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; - position: relative; -} - -html, body { - width: 100%; - height: 100%; -} - -body { - background-color: #111; - color: #fff; - font: 12px/20px Verdana, Geneva, Arial, Helvetica, sans-serif; -} - -@media (prefers-color-scheme: light) { - body { - background-color: #ddd; - color: #000; - } -} - -[hidden], -.hidden { - display: none !important; -} - -.http-err { - padding: 40px 60px; -} -.http-err-title { - font-size: 3em; - line-height: 1.5em; - font-weight: 700; -} -.http-err-paragraph { - font-size: 1.2em; - line-height: 1.5em; -} - .auth { margin: 0 auto; padding: 10px; diff --git a/assets/hanyuu.css/main.css b/assets/hanyuu.css/main.css new file mode 100644 index 0000000..d4d7f28 --- /dev/null +++ b/assets/hanyuu.css/main.css @@ -0,0 +1,31 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + position: relative; +} + +html, body { + width: 100%; + height: 100%; +} + +body { + background-color: #111; + color: #fff; + font: 12px/20px Verdana, Geneva, Arial, Helvetica, sans-serif; +} + +@media (prefers-color-scheme: light) { + body { + background-color: #ddd; + color: #000; + } +} + +[hidden], +.hidden { + display: none !important; +} + +@include auth.css; diff --git a/assets/hanyuu.js/main.js b/assets/hanyuu.js/main.js new file mode 100644 index 0000000..ea03b5c --- /dev/null +++ b/assets/hanyuu.js/main.js @@ -0,0 +1 @@ +/* beans */ diff --git a/build.js b/build.js new file mode 100644 index 0000000..c2467b7 --- /dev/null +++ b/build.js @@ -0,0 +1,39 @@ +const assproc = require('@railcomm/assproc'); +const { join: pathJoin } = require('path'); +const fs = require('fs'); + +(async () => { + const isDebug = fs.existsSync(pathJoin(__dirname, '.debug')); + + const env = { + root: __dirname, + source: pathJoin(__dirname, 'assets'), + public: pathJoin(__dirname, 'public'), + debug: isDebug, + swc: { + es: 'es2021', + }, + }; + + const tasks = { + js: [ + { source: 'hanyuu.js', target: '/assets', name: 'hanyuu.{hash}.js', }, + ], + css: [ + { source: 'errors.css', target: '/', name: 'errors.css', }, + { source: 'hanyuu.css', target: '/assets', name: 'hanyuu.{hash}.css', }, + ], + twig: [ + { source: 'errors/400', target: '/', name: 'error-400.html', }, + { source: 'errors/401', target: '/', name: 'error-401.html', }, + { source: 'errors/403', target: '/', name: 'error-403.html', }, + { source: 'errors/404', target: '/', name: 'error-404.html', }, + { source: 'errors/500', target: '/', name: 'error-500.html', }, + { source: 'errors/503', target: '/', name: 'error-503.html', }, + ], + }; + + const files = await assproc.process(env, tasks); + + fs.writeFileSync(pathJoin(__dirname, 'assets/current.json'), JSON.stringify(files)); +})(); diff --git a/hanyuu.php b/hanyuu.php index 9a970a1..019f53d 100644 --- a/hanyuu.php +++ b/hanyuu.php @@ -10,6 +10,7 @@ define('HAU_STARTUP', microtime(true)); define('HAU_ROOT', __DIR__); define('HAU_CLI', PHP_SAPI === 'cli'); define('HAU_DEBUG', is_file(HAU_ROOT . '/.debug')); +define('HAU_DIR_ASSETS', HAU_ROOT . '/assets'); define('HAU_DIR_PUBLIC', HAU_ROOT . '/public'); define('HAU_DIR_SOURCE', HAU_ROOT . '/src'); define('HAU_DIR_MIGRATIONS', HAU_ROOT . '/database'); diff --git a/public/assets/hanyuu.js b/public/assets/hanyuu.js deleted file mode 100644 index e69de29..0000000 diff --git a/public/errors.css b/public/errors.css new file mode 100644 index 0000000..fe2ebd7 --- /dev/null +++ b/public/errors.css @@ -0,0 +1,35 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + position: relative; +} +html, body { + width: 100%; + height: 100%; +} +body { + background-color: #111; + color: #fff; + font-size: 12px; + line-height: 20px; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; +} +@media (prefers-color-scheme: light) { + body { + background-color: #ddd; + color: #000; + } +} +.http-err { + padding: 40px 60px; +} +.http-err-title { + font-size: 3em; + line-height: 1.5em; + font-weight: 700; +} +.http-err-paragraph { + font-size: 1.2em; + line-height: 1.5em; +} diff --git a/src/GitInfo.php b/src/GitInfo.php new file mode 100644 index 0000000..a369781 --- /dev/null +++ b/src/GitInfo.php @@ -0,0 +1,23 @@ +config = $config; $this->dbConn = $dbConn; - $this->siteInfo = new SiteInfo($config->scopeTo('site')); } @@ -37,6 +36,10 @@ class HanyuuContext { return new FsDbMigrationRepo(HAU_DIR_MIGRATIONS); } + public function getWebAssetInfo(): ?object { + return json_decode(file_get_contents(HAU_DIR_ASSETS . '/current.json')); + } + public function getTemplating(): SasaeEnvironment { if($this->templating === null) { $isDebug = Environment::isDebug(); @@ -46,10 +49,10 @@ class HanyuuContext { cache: null,//$isDebug ? null : ['Hanyuu', GitInfo::hash(true)], debug: $isDebug, ); + $this->templating->addExtension(new HanyuuSasaeExtension($this)); $this->templating->addGlobal('globals', [ 'siteInfo' => $this->siteInfo, - //'assetsInfo' => AssetsInfo::fromCurrent(), ]); } diff --git a/src/HanyuuSasaeExtension.php b/src/HanyuuSasaeExtension.php new file mode 100644 index 0000000..5077d80 --- /dev/null +++ b/src/HanyuuSasaeExtension.php @@ -0,0 +1,30 @@ +ctx = $ctx; + $this->assets = $ctx->getWebAssetInfo(); + } + + public function getFunctions() { + return [ + new TwigFunction('asset', $this->getAssetPath(...)), + new TwigFunction('git_commit_hash', GitInfo::hash(...)), + new TwigFunction('git_tag', GitInfo::tag(...)), + new TwigFunction('git_branch', GitInfo::branch(...)), + new TwigFunction('startup_time', fn(float $time = HAU_STARTUP) => microtime(true) - $time), + new TwigFunction('sql_query_count', $this->ctx->getDbQueryCount(...)), + ]; + } + + public function getAssetPath(string $name): string { + return $this->assets?->{$name} ?? ''; + } +} diff --git a/src/RoutingContext.php b/src/RoutingContext.php index df0739c..761e56f 100644 --- a/src/RoutingContext.php +++ b/src/RoutingContext.php @@ -10,7 +10,7 @@ class RoutingContext { public function __construct(SasaeEnvironment $templating) { $this->templating = $templating; - $this->router = new HttpRouter(errorHandler: new RoutingErrorHandler($templating)); + $this->router = new HttpRouter(errorHandler: new RoutingErrorHandler); $this->router->use('/', fn($resp) => $resp->setPoweredBy('Hanyuu')); } diff --git a/src/RoutingErrorHandler.php b/src/RoutingErrorHandler.php index eaa5054..dbf6d66 100644 --- a/src/RoutingErrorHandler.php +++ b/src/RoutingErrorHandler.php @@ -3,24 +3,14 @@ namespace Hanyuu; use Index\Http\{HttpResponseBuilder,HttpRequest}; use Index\Http\ErrorHandling\HtmlErrorHandler; -use Sasae\SasaeEnvironment; class RoutingErrorHandler extends HtmlErrorHandler { - public function __construct( - private SasaeEnvironment $templating - ) {} - #[\Override] public function handle(HttpResponseBuilder $response, HttpRequest $request, int $code, string $message): void { - if($code === 500 || $code === 503) { + $path = HAU_DIR_PUBLIC . sprintf('/error-%03d.html', $code); + if(is_file($path)) { $response->setTypeHTML(); - $response->setContent(file_get_contents(sprintf('%s/errors/%s.html', HAU_DIR_TEMPLATES, $code))); - return; - } - - if($code == 401 || $code === 403 || $code === 400) { - $response->setTypeHTML(); - $response->setContent($this->templating->render(sprintf('errors/%s', $code))); + $response->setContent(file_get_contents($path)); return; } diff --git a/templates/auth/login-tfa.twig b/templates/auth/login-tfa.twig deleted file mode 100644 index 97ada08..0000000 --- a/templates/auth/login-tfa.twig +++ /dev/null @@ -1,35 +0,0 @@ -{% extends 'auth/master.twig' %} - -{% block content %} -
-
-
- -
-
- -
- -
- -
- {% if 'totp' in auth_method_names %} - Authenticator app (TOTP) - {% endif %} - {% if 'u2f' in auth_method_names %} - Security key (U2F) - {% endif %} - {% if 'backup' in auth_method_names %} - Backup code - {% endif %} - Cancel -
-
-{% endblock %} diff --git a/templates/auth/login-totp.twig b/templates/auth/login-totp.twig deleted file mode 100644 index 7965fe6..0000000 --- a/templates/auth/login-totp.twig +++ /dev/null @@ -1,36 +0,0 @@ -{% extends 'auth/master.twig' %} - -{% block content %} -
-
-
- -
-
- -
- - - -
- -
- - Back -
-
-{% endblock %} diff --git a/templates/auth/login.twig b/templates/auth/login.twig deleted file mode 100644 index d2bc154..0000000 --- a/templates/auth/login.twig +++ /dev/null @@ -1,51 +0,0 @@ -{% extends 'auth/master.twig' %} - -{% set register_suffix = '' %} -{% set forgot_suffix = '' %} - -{% if user_name is not empty %} - {% set suffix = '?username=' ~ user_name %} - - {% if error_name == 'user_not_found' %} - {% set register_suffix = suffix %} - {% else %} - {% set forgot_suffix = suffix %} - {% endif %} -{% endif %} - -{% block content %} -
-
-
- -
-
- -
- - - -
- -
- - Forgot username? - Forgot password? - Create account -
-
-{% endblock %} diff --git a/templates/auth/master.twig b/templates/auth/master.twig deleted file mode 100644 index 08e6de8..0000000 --- a/templates/auth/master.twig +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'master.twig' %} - -{% block body %} -
-
- {{ globals.siteInfo.name }} -
- {% block content %}{% endblock %} -
-{% endblock %} diff --git a/templates/errors/500.html b/templates/errors/500.html deleted file mode 100644 index 3ffe87c..0000000 --- a/templates/errors/500.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Error 500 - - - -
-

Error 500

-

Something went horrendously wrong! Please report this if the error persists.

-
- - diff --git a/templates/errors/500.twig b/templates/errors/500.twig new file mode 100644 index 0000000..edd4ec0 --- /dev/null +++ b/templates/errors/500.twig @@ -0,0 +1,4 @@ +{% extends 'errors/master.twig' %} + +{% set http_error_title = 'Error 500' %} +{% set http_error_desc = 'Something went horrendously wrong! Please report this if the error persists.' %} diff --git a/templates/errors/503.html b/templates/errors/503.html deleted file mode 100644 index 7116aa9..0000000 --- a/templates/errors/503.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Error 503 - - - -
-

Under Construction

- -
- - diff --git a/templates/errors/503.twig b/templates/errors/503.twig new file mode 100644 index 0000000..fea9886 --- /dev/null +++ b/templates/errors/503.twig @@ -0,0 +1,4 @@ +{% extends 'errors/master.twig' %} + +{% set http_error_title = 'Under Construction' %} +{% set http_error_desc = '' %} diff --git a/templates/errors/master.twig b/templates/errors/master.twig index d44763f..9caaecc 100644 --- a/templates/errors/master.twig +++ b/templates/errors/master.twig @@ -1,8 +1,15 @@ -{% extends 'master.twig' %} - -{% block body %} -
-

{{ http_error_title|default('Unknown Error') }}

-

{{ http_error_title|default('No additional information is available.') }}

-
-{% endblock %} + + + + + + {{ http_error_title }} :: {{ globals.siteInfo.name }} + + + +
+

{{ http_error_title }}

+

{{ http_error_desc|raw }}

+
+ + diff --git a/tools/render-tpl b/tools/render-tpl new file mode 100755 index 0000000..3cd4693 --- /dev/null +++ b/tools/render-tpl @@ -0,0 +1,8 @@ +#!/usr/bin/env php +getTemplating(); +$path = implode(' ', array_slice($argv, 1)); + +echo $templating->render($path);