wip: 2025-02-11T11:47:18+0100 (1739270838)

This commit is contained in:
Victor Westerlund 2025-02-11 17:16:20 +01:00
parent e5a0a8169c
commit 4f0f2a57f5
90 changed files with 697 additions and 1177 deletions

View file

@ -0,0 +1,57 @@
<?php
use const VVWebsite\ICONS_DIR;
require_once VV::root("src/Consts.php");
$HTMLCodeDemoElement = new class {
public bool $valid = false;
public readonly array $files;
private readonly string $dir;
private readonly string $namespace;
public function __construct() {
$this->namespace = array_key_exists("id", $_GET) ? $_GET["id"] : null;
if ($this->namespace) {
$this->dir = "snippets/HTMLCodeDemoElement/{$this->namespace}/";
if (is_dir(VV::root($this->dir))) {
// Strip "." and ".."
$this->files = array_filter(scandir(VV::root($this->dir)), function (string $item) {
return substr($item, 0, 1) !== ".";
});
$this->valid = true;
}
}
}
public function file_path(string $file): string {
return $this->dir . $file;
}
}
?>
<code-demo>
<div class="header">
<?php foreach ($HTMLCodeDemoElement->files as $file): ?>
<button class="inline">
<?= VV::embed(ICONS_DIR . "languages/" . $file) ?>
<p><?= substr($file, 0, strlen($file) - 4) ?></p>
</button>
<?php endforeach; ?>
</div>
<div class="body">
<?php foreach ($HTMLCodeDemoElement->files as $file): ?>
<div>
<?= VV::include($HTMLCodeDemoElement->file_path($file)) ?>
</div>
<?php endforeach; ?>
</div>
</code-demo>
<script type="module" src="/assets/js/elements/HTMLCodeDemoElement.mjs"></script>

View file

@ -1,12 +0,0 @@
<style><?= VV::css("modules/docs/contribute/style.css") ?></style>
<section class="contribute">
<container>
<h1>Contribute? 💕</h1>
<p>Have you found a problem om this page? Would you like to help make this little project a bit better?</p>
<ul>
<li><a href="/"><button class="solid"><p>Quick-report a problem on this page</p></button></a></li>
<li><a href="/"><button class="shade"><p>Report a bug</p></button></a></li>
<li><a href="/"><button class="shade"><p>Learn how to contribute</p></button></a></li>
</ul>
</container>
</section>

View file

@ -1,29 +0,0 @@
section.contribute {
grid-area: contribute;
width: 100%;
background-color: rgba(var(--primer-color-deep), .1);
}
section.contribute container {
justify-content: center;
flex-direction: column;
}
section.contribute ul {
display: flex;
padding: var(--padding);
list-style: none;
gap: var(--padding);
}
/* # Size queries */
@media (max-width: 950px) {
section.contribute ul {
flex-direction: column;
}
section.contribute button {
width: 100%;
}
}

View file

@ -1,24 +0,0 @@
<ul>
<li><a href="/docs/API/JS/Navigation"><button><p><code>vegvisir.Navigation</code></p></button></a></li>
<ul>
<p>Instance variables</p>
<li><a href="/docs/API/JS/Navigation/abort"><button><p><code>Navigation.abort</code></p></button></a></li>
<li><a href="/docs/API/JS/Navigation/options"><button><p><code>Navigation.options</code></p></button></a></li>
</ul>
<ul>
<p>Instance methods</p>
<li><a href="/docs/API/JS/Navigation/constructor"><button><p><code>Navigation.constructor</code></p></button></a></li>
<li><a href="/docs/API/JS/Navigation/navigate"><button><p><code>Navigation.navigate()</code></p></button></a></li>
</ul>
<ul>
<p>Static variables</p>
<li><a href="/docs/API/JS/Navigation/MODE"><button><p><code>vegvisir.Navigation.MODE</code></p></button></a></li>
<li><a href="/docs/API/JS/Navigation/TARGET"><button><p><code>vegvisir.Navigation.TARGET</code></p></button></a></li>
<li><a href="/docs/API/JS/Navigation/EVENTS"><button><p><code>vegvisir.Navigation.EVENTS</code></p></button></a></li>
<li><a href="/docs/API/JS/Navigation/POSITION"><button><p><code>vegvisir.Navigation.POSITION</code></p></button></a></li>
</ul>
<ul>
<p>Static methods</p>
<li><a href="/docs/API/JS/Navigation/bindElements"><button><p><code>vegvisir.Navigation.bindElements()</code></p></button></a></li>
</ul>
</ul>

View file

@ -1,12 +0,0 @@
<ul>
<li><a href="/docs/API/PHP/VV"><button><p><code>VV</code></p></button></a></li>
<ul>
<p>Static methods</p>
<li><a href="/docs/API/PHP/VV/js"><button><p><code>VV::js()</code></p></button></a></li>
<li><a href="/docs/API/PHP/VV/css"><button><p><code>VV::css()</code></p></button></a></li>
<li><a href="/docs/API/PHP/VV/root"><button><p><code>VV::root()</code></p></button></a></li>
<li><a href="/docs/API/PHP/VV/embed"><button><p><code>VV::embed()</code></p></button></a></li>
<li><a href="/docs/API/PHP/VV/shell"><button><p><code>VV::shell()</code></p></button></a></li>
<li><a href="/docs/API/PHP/VV/include"><button><p><code>VV::include()</code></p></button></a></li>
</ul>
</ul>

View file

@ -1,33 +0,0 @@
<?php
enum Snippet: string {
// Path relative from root
private const REL_BASE_PATH = "modules/snippet/snippets/";
// Languages
case JAVASCRIPT = ".js";
case CSS = ".css";
case PLAINTEXT = ".txt";
case PHP = ".php";
public static function put(string $name, self $lang): string {
// Create path relative from base with filename and language extension (from enum value)
$path = VV::root(self::REL_BASE_PATH . $name . $lang->value);
// Bail out if snippet can't be found
if (!is_file($path)) {
return "<pre><code class='language-plaintext'>!REF#</code></pre>";
}
// Use enum name in lowercase as highlight.js lanuage definer
$output = "<pre><code class='language-" . strtolower($lang->name) . "'>";
$output .= htmlspecialchars(file_get_contents($path));
$output .= "</code></pre>";
return $output;
}
}
?>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"/>
<script type="module"><?= VV::js("modules/snippet/snippet.js") ?></script>

View file

@ -1,19 +0,0 @@
import hljs from "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/es/highlight.min.js";
import php from "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/es/languages/php.min.js";
import css from "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/es/languages/css.min.js";
import plaintext from "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/es/languages/plaintext.min.js";
import javascript from "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/es/languages/javascript.min.js";
hljs.registerLanguage("php", php);
hljs.registerLanguage("css", css);
hljs.registerLanguage("plaintext", plaintext);
hljs.registerLanguage("javascript", javascript);
// Initialize syntax highlighting for all code snippets on this page
const highlightElements = () => {
[...document.querySelectorAll("pre code")].forEach(element => hljs.highlightElement(element));
}
document.querySelector("[vv-shell-id='6ccb0465']").addEventListener(vegvisir.Navigation.EVENTS.FINISHED, () => highlightElements);
highlightElements();

View file

@ -1,3 +0,0 @@
{
target: HTMLElement
}

View file

@ -1,4 +0,0 @@
static Navigation.EVENTS = {
STARTED: "navstarted",
FINISHED: "navfinished"
}

View file

@ -1,3 +0,0 @@
document.addEventListener(vegvisir.Navigation.EVENTS.STARTED, (event) => {
console.log(event.detail.target);
});

View file

@ -1,4 +0,0 @@
static Navigation.MODE = {
REPLACE: "replace",
INSERT: "insert"
}

View file

@ -1,6 +0,0 @@
static Navigation.POSITION = {
AFTEREND: "afterend",
BEFOREEND: "beforeend",
AFTERBEGIN: "afterbegin",
BEFOREBEGIN: "beforebegin"
}

View file

@ -1,6 +0,0 @@
static Navigation.TARGET = {
TOP: "_top",
SELF: "_self",
BLANK: "_blank",
PARENT: "_parent"
};

View file

@ -1 +0,0 @@
<a href="/some-page" target="_self">Click here to replace this button with the contents of /some-page</a>

View file

@ -1,4 +0,0 @@
<div vv-loading="false" vv-page="/">
<p>...</p>
<a href="/some-page" target="_parent">Click here to replace this button and its siblings with /some-page</a>
</a>

View file

@ -1 +0,0 @@
Navigation.abort: AbortController

View file

@ -1 +0,0 @@
static Navigation.bindElements(): void

View file

@ -1,5 +0,0 @@
// The programatically appended anchor tag will not have Vegvisir event listeners on it yet
document.body.appendChild(document.createElement("a"));
// It will have Vegvisir event listeners after this method is called
vegvisir.Navigation.bindElements();

View file

@ -1,4 +0,0 @@
new globalThis.vegvisir.Navigation(
URL|String url = window.location,
Object options = vegvisir.Navigation.options
): Navigation

View file

@ -1,2 +0,0 @@
// Pathname string with leading slash
const nav = new vegvisir.Navigation("/some-page");

View file

@ -1,2 +0,0 @@
// Pathname string without leading slash and a search parameter
const nav = new vegvisir.Navigation("some-page?foo=bar");

View file

@ -1,6 +0,0 @@
// URL object with a pathname and search parameter
const url = new URL(window.location);
url.pathname = "/some-page";
url.searchParams.set("foo", "bar");
const nav = new vegvisir.Navigation(url);

View file

@ -1,4 +0,0 @@
const nav = new vegvisir.Navigation("/some-page");
// Will navigate the top shell to /some-page
nav.navigate();

View file

@ -1,5 +0,0 @@
const target = document.querySelector("#target");
const nav = new vegvisir.Navigation("/some-page");
// Will replace the contents of an element with id #target with the contents of /some-page
nav.navigate(target);

View file

@ -1,8 +0,0 @@
const target = document.querySelector("#target");
const nav = new vegvisir.Navigation("/some-page");
// Will place the contents of /some-page after the target element as a sibling
nav.navigate(target, vegvisir.Navigation.POSITION.AFTEREND);
// Tip: You can also pass an insertAdjacentElement position string directly
nav.navigate(target, "afterend");

View file

@ -1,5 +0,0 @@
Navigation.navigate(
target: HTMLELement = Navigation.#rootShellElement
position: Navigation.POSITION = Navigation.POSITION.BEFOREEND,
mode: Navigation.MODE = Navigation.MODE.REPLACE
): void

View file

@ -1,6 +0,0 @@
const target = document.querySelector("#update-this-element");
const button = document.querySelector("#click-me-to-refresh");
const nav = new vegvisir.Navigation("/page-with-new-content");
button.addEventListener("click", () => nav.navigate(target));

View file

@ -1,3 +0,0 @@
{
pushHistory: boolean
}

View file

@ -1,4 +0,0 @@
<style><?= VV::css("public/asssets/css/style.css") ?></style>
// Without file extension (appended automatically)
<style><?= VV::css("public/asssets/css/style.css") ?></style>

View file

@ -1 +0,0 @@
<style><?= VV::css("/var/www/other-project/.../style.css", true) ?></style>

View file

@ -1 +0,0 @@
"const hello = ()=>console.log('Hello world');hello()"

View file

@ -1,4 +0,0 @@
VV::css(
string $pathname,
bool $relative = true
): string

View file

@ -1,6 +0,0 @@
/* File: /var/www/my-website/public/assets/css/style.css */
p {
color: blue;
background-color: red;
}

View file

@ -1,4 +0,0 @@
// File: /var/www/my-website/public/index.php
<style><?= VV::js("public/assets/css/style.css") ?></style>
<p>Some content...</p>

View file

@ -1,4 +0,0 @@
<style><?= VV::css("public/asssets/css/style.css") ?></style>
// Without file extension (appended automatically)
<style><?= VV::css("public/asssets/css/style.css") ?></style>

View file

@ -1 +0,0 @@
<style><?= VV::css("/var/www/other-project/.../style.css", true) ?></style>

View file

@ -1 +0,0 @@
"const hello = ()=>console.log('Hello world');hello()"

View file

@ -1,4 +0,0 @@
VV::embed(
string $pathname,
bool $relative = true
): string

View file

@ -1,3 +0,0 @@
/* File: /var/www/my-website/public/assets/media/logo.svg */
<svg viewBox="0 0 0 0" xmlns="http://www.w3.org/2000/svg">...</svg>

View file

@ -1,5 +0,0 @@
// File: /var/www/my-website/shells/document.php
<header>
<?= VV::embed("public/assets/media/logo.svg") ?>
</header>

View file

@ -1,4 +0,0 @@
<?= VV::include("public/modules/banner.php") ?>
// Without file extension (appended automatically)
<?= VV::include("public/modules/banner") ?>

View file

@ -1 +0,0 @@
<?= VV::include("/var/www/other-project/.../banner.php", true) ?>

View file

@ -1 +0,0 @@
"const hello = ()=>console.log('Hello world');hello()"

View file

@ -1,4 +0,0 @@
VV::include(
string $pathname,
bool $relative = true
): never

View file

@ -1,5 +0,0 @@
/* File: /var/www/my-website/modules/banner.php */
<banner>
<p>Important text!</p>
</banner>

View file

@ -1,6 +0,0 @@
// File: /var/www/my-website/public/index.php
<header>
<p>Some header content</p>
<?= VV::include("modules/banner") ?>
</header>

View file

@ -1,4 +0,0 @@
<script><?= VV::js("public/asssets/js/script.js") ?></script>
// Without file extension (appended automatically)
<script><?= VV::js("public/asssets/js/script") ?></script>

View file

@ -1 +0,0 @@
<script><?= VV::js("/var/www/other-project/.../script.js", true) ?></script>

View file

@ -1 +0,0 @@
"const hello = ()=>console.log('Hello world');hello()"

View file

@ -1,4 +0,0 @@
VV::js(
string $pathname,
bool $relative = true
): string

View file

@ -1,5 +0,0 @@
// File: /var/www/my-website/public/assets/js/script.js
const hello = () => {
console.log("Hello world!");
}

View file

@ -1,4 +0,0 @@
// File: /var/www/my-website/public/index.php
<p>Some content...</p>
<script><?= VV::js("public/assets/js/script.js") ?></script>

View file

@ -1 +0,0 @@
VV::root("/src/databases");

View file

@ -1 +0,0 @@
"/var/www/my-website/src/databases"

View file

@ -1,9 +0,0 @@
// File: /var/www/my-website/src/MyClass.php
<?php
namespace MyWebsite\Src;
class MyClass {
// ...
}

View file

@ -1,11 +0,0 @@
// File: /var/www/my-website/public/index.php
<?php
use MyWebsite\Src\MyClass;
// Leading slash is optional!
require_once VV::root("/src/MyClass.php");
?>
<p>A normal Vegvisir page whch has access to MyClass</p>

View file

@ -1,3 +0,0 @@
VV::root(
string $pathname = ""
): string

View file

@ -1 +0,0 @@
<?= VV::shell("shells/docs") ?>

View file

@ -1,3 +0,0 @@
VV::shell(
string $pathname = ""
): never

View file

@ -1,4 +0,0 @@
// File: /var/www/my-website/public/some-page.php
<p>Inner content</p>
<?= VV::shell("shells/outer-content") ?>

View file

@ -1,5 +0,0 @@
// File: /var/www/my-website/shells/some-shell.php
<p>This paragraph will be above the wrapped content</p>
<vv-shell></vv-shell>
<p>This parahraph will be below the wrapped content</p>

View file

@ -1 +0,0 @@
git clone https://codeberg.org/vegvisir/vegvisir.git --depth 1

View file

@ -1 +0,0 @@
composer install --optimize-autoloader

View file

@ -1,16 +0,0 @@
# You might need to alter this block to suit your NGINX configuration
# The important thing is that all requests should be routed to /public/index.php
server {
listen 80;
server_name _;
root /var/www/vegvisir/public;
location / {
try_files /index.php =503;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
}

View file

@ -1 +0,0 @@
mkdir /var/www/my-website

View file

@ -1 +0,0 @@
cp -p /var/www/vegvisir/.env.example.ini /var/www/vegvisir/.env.ini

View file

@ -1,10 +0,0 @@
# /var/www/vegvisir/.env.ini
; +--------------------+
; | Base configuration |
; +--------------------+
; An absolute path to the root directory of your website
root_path = "/var/www/my-website"
...

View file

@ -1,267 +0,0 @@
:root {
--primer-color-deep: 0, 128, 255;
--primer-color-light: 135, 255, 255;
--color-deep: rgba(var(--primer-color-deep));
--color-light: rgba(var(--primer-color-light));
--border-style-width: 1px;
--border-style: solid var(--border-style-width) rgba(var(--primer-color-deep), .2);
--padding: 10px;
--running-size: 70px;
--max-width: 1400px;
}
/* # Cornerstones */
* {
margin: 0;
color: inherit;
font-size: inherit;
box-sizing: border-box;
font-family: monospace;
}
body {
font-size: 15px;
overflow-x: hidden;
overscroll-behavior: none;
}
body.menuOpen {
overflow: hidden;
}
a {
color: inherit;
display: contents;
text-decoration: none;
}
/* # Components */
:is(h1, h2, h3, p, li) > a {
--underline-tickness: 3px;
display: initial;
text-decoration: underline;
text-decoration-color: var(--color-accent);
text-underline-offset: var(--underline-tickness);
text-decoration-thickness: var(--underline-tickness);
}
@media (hover: hover) {
:is(h1, h2, h3, p, li) > a:hover {
text-decoration-color: var(--color-deep);
}
}
h1 {
font-size: 30px;
color: var(--color-accent);
}
h2 {
font-size: 25px;
}
h3 {
font-size: 18px;
}
/* ## Container */
container {
margin: auto;
height: 100%;
display: flex;
width: clamp(200px, 100%, 80vw);
max-width: var(--max-width);
align-items: center;
gap: var(--padding);
padding: var(--padding) 0;
}
container.split {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
container.split.reverse div:last-child {
order: -1;
}
container.split > div {
display: flex;
flex-direction: column;
align-items: baseline;
gap: var(--padding);
}
/* ## Button */
button {
border: unset;
fill: black;
cursor: pointer;
padding: 10px 15px;
border-radius: 4px;
background-color: rgba(0, 0, 0, 0);
border: solid var(--border-style-width) transparent;
}
button.solid {
fill: white;
color: white;
background-color: var(--color-deep);
}
button.shade {
background-color: rgba(0, 0, 0, .05);
}
@media (hover: hover) {
button:hover {
background-color: rgba(var(--primer-color-light), .3);
}
button.solid:hover {
color: var(--color-light);
background-color: var(--color-deep);
}
}
button svg {
fill: inherit;
width: 1em;
}
/* # Content */
/* ## Runners */
:is(header, footer) ul {
display: flex;
padding-left: 0;
list-style: none;
gap: var(--padding);
}
:is(header, footer) ul:last-of-type {
margin-left: auto;
}
:is(header, footer) container > button {
display: none;
margin-left: auto;
}
/* ### Header */
header {
--border-width: 2px;
top: 0px;
position: sticky;
background-color: white;
height: calc(var(--running-size) + var(--border-style-width));
border-bottom: var(--border-style);
z-index: 1000;
}
header .logo {
height: 40px;
padding: 5px;
border-radius: 4px;
background-color: var(--color-deep);
}
[vv-top-page="/"] header:not(.transparent) a[href="/"] button,
[vv-top-page="/help"] header a[href="/help"] button,
[vv-top-page^="/docs"] header a[href="/docs"] button,
[vv-top-page="/demos"] header a[href="/demos"] button,
[vv-top-page="/why"] header a[href="/why"] button {
font-weight: bold;
color: var(--color-deep);
border: var(--border-style);
}
/* ### Footer */
footer {
padding: var(--padding);
color: var(--color-light);
background-color: var(--color-deep);
}
/* ### Menu */
menu {
display: none;
position: fixed;
top: var(--running-size);
left: 0;
width: 100svw;
padding: calc(var(--padding) * 2);
height: calc(100svh - var(--running-size));
background-color: var(--color-deep);
}
body.menuOpen menu {
display: initial;
}
menu ul {
list-style: none;
padding-left: unset;
}
menu button {
color: white;
width: 100%;
margin-top: var(--padding);
}
/* # Size queries */
@media (max-width: 950px) {
container {
min-width: unset;
width: 100%;
padding: calc(var(--padding) * 2);
}
container.split {
display: flex;
flex-direction: column;
}
container.split.reverse {
flex-direction: column-reverse;
}
header ul button.solid,
:is(header, footer) ul:not(:last-of-type) {
display: none;
}
:is(header, footer) container > button {
display: initial;
}
footer :is(container, ul) {
flex-direction: column;
}
footer button,
footer ul:last-of-type {
width: 100%;
margin-left: unset;
}
}
@media (min-width: 950px) {
body.menuOpen menu {
display: none;
}
}

View file

@ -0,0 +1,70 @@
code-demo {
--primer-color-base: 31, 31, 31;
--color-base: rgb(var(--primer-color-base));
--height: calc(var(--padding) * 2.5);
min-width: 700px;
border-radius: 12px;
background-color: var(--color-base);
}
/* # Header */
code-demo .header {
display: flex;
height: var(--height);
border-bottom: solid 1px rgba(255, 255, 255, .1);
}
code-demo .header button.inline {
border: solid 1px rgba(255, 255, 255, .1);
border-bottom: unset;
border-radius: unset;
box-shadow: unset;
}
code-demo .header button.inline:hover {
box-shadow: unset;
}
code-demo .header button:first-child {
margin-left: var(--height);
}
code-demo .header button.inline + button.inline {
border-left: unset;
}
/* # Body */
code-demo .body {
padding: var(--padding);
}
/* # Syntax highliting */
code-demo .mtk1 { color: #cccccc; }
code-demo .mtk2 { color: #1f1f1f; }
code-demo .mtk3 { color: #d4d4d4; }
code-demo .mtk4 { color: #000080; }
code-demo .mtk5 { color: #6a9955; }
code-demo .mtk6 { color: #569cd6; }
code-demo .mtk7 { color: #b5cea8; }
code-demo .mtk8 { color: #646695; }
code-demo .mtk9 { color: #d7ba7d; }
code-demo .mtk10 { color: #9cdcfe; }
code-demo .mtk11 { color: #f44747; }
code-demo .mtk12 { color: #ce9178; }
code-demo .mtk13 { color: #6796e6; }
code-demo .mtk14 { color: #808080; }
code-demo .mtk15 { color: #d16969; }
code-demo .mtk16 { color: #dcdcaa; }
code-demo .mtk17 { color: #4ec9b0; }
code-demo .mtk18 { color: #c586c0; }
code-demo .mtk19 { color: #4fc1ff; }
code-demo .mtk20 { color: #c8c8c8; }
code-demo .mtk21 { color: #cd9731; }
code-demo .mtk22 { color: #b267e6; }
code-demo .mtki { font-style: italic; }
code-demo .mtkb { font-weight: bold; }
code-demo .mtks { text-decoration: line-through; }

View file

@ -0,0 +1,8 @@
@font-face {
font-family: "Roboto Mono";
src:
url("/assets/fonts/roboto-mono.woff2") format("woff2 supports variations"),
url("/assets/fonts/roboto-mono.woff2") format("woff2-variations")
;
font-weight: 100 900;
}

View file

@ -1,26 +0,0 @@
/* # WIP */
section#wip {
background-color: rgba(var(--primer-color-light), .3);
}
section#wip container {
flex-direction: column;
gap: var(--padding);
}
/* # Websites */
section#websites container {
flex-direction: column;
}
section#websites ul {
list-style: none;
padding-left: unset;
}
section#websites button {
margin-top: var(--padding);
width: 100%;
}

View file

@ -1,188 +1,53 @@
:root {
--wavelength: 20vw;
/* # Components */
section.split {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
body {
background-color: var(--color-deep);
}
section h2 {
color: white;
background-color: black;
}
header.transparent {
color: white;
background-color: transparent;
border-color: rgba(255, 255, 255, .1);
}
header.transparent .logo {
fill: var(--color-deep);
}
header.transparent button {
fill: white;
}
header.transparent button.solid {
fill: var(--color-deep);
color: var(--color-deep);
background-color: white;
section.split > div {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}
/* # Sections */
/* ## Divider */
section.divider {
width: 100%;
overflow: hidden;
line-height: 0;
background-color: white;
}
section.divider svg {
position: relative;
display: block;
width: calc(148% + 1.3px);
height: 79px;
}
section.divider .shape-fill {
fill: var(--color-deep);
}
/* ## Intro */
section#intro {
display: grid;
color: white;
min-height: 300px;
min-height: 70svh;
}
section#intro h1 {
font-size: 50px;
}
/* ### Compass */
section#intro div {
display: flex;
flex-direction: column;
justify-content: center;
align-items: baseline;
}
section#intro div.compass svg {
--size: 50svh;
/* ### Waves */
section.waves {
--easing: .2;
position: relative;
height: 300px;
user-select: none;
pointer-events: none;
z-index: -1;
}
section.waves img {
margin: auto;
margin-top: -14%;
width: 50%;
transform-origin: 50% 100%;
animation: ship 6s alternate infinite ease;
}
@keyframes ship {
0% {
transform: translate(0, -7px) rotate(-7deg);
}
100% {
transform: translate(5px, 10px) rotate(4deg);
}
}
section.waves .wave {
width: var(--size);
height: var(--size);
position: absolute;
width: 100%;
height: 100%;
transform: scale(1.5);
bottom: 70px;
animation: wave 7s alternate infinite cubic-bezier(var(--easing), 0, calc(1 - var(--easing)), 1);
}
@keyframes wave {
to { transform: scale(1.5) translateX(100px); }
section#intro div.compass svg.points {
opacity: .2;
animation: spin 10s alternate infinite linear;
}
section.waves + section {
background-color: #4ca6ff;
@keyframes spin {
to { transform: rotate(30deg); }
}
section.waves .wave:first-child {
background-image: url("/assets/media/waves/0.svg");
section#intro div.compass svg:nth-child(2) {
--size: calc(var(--size) - 30px);
animation-duration: 15s;
animation-direction: alternate-reverse;
}
section.waves .wave:last-child {
animation-duration: 5s;
background-image: url("/assets/media/waves/1.svg");
}
/* ## Softnav */
section#softnav {
color: white;
background: linear-gradient(0deg, rgba(0,128,255,1) 0%, rgba(76,166,255,1) 100%);
}
/* ## BYOE */
section.info {
background-color: white;
}
section.info container {
min-height: 400px;
}
section.info svg {
justify-self: center;
width: 400px;
}
/* ## Lead */
section#lead h1 {
color: white;
text-align: center;
font-weight: normal;
}
/* ## Free */
section#free {
box-shadow: inset 0 0 20px 20px white, inset 0 0 140px 20px white;
background-color: rgba(255, 255, 255, .9);
background-blend-mode: screen;
background-image: url("/assets/media/gnu.png");
}
/* # Size queries */
@media (max-width: 950px) {
section.waves {
display: none;
}
section.info container {
min-height: unset;
}
section.info svg {
width: 300px;
}
section#lead h1 {
font-size: 20px;
}
/* ## Assets */
section#assets {
height: 100svh;
}

View file

@ -1,15 +0,0 @@
/* # Sections */
/* ## Free */
section#freedom {
background-position: 50% 50%;
background-size: 400px;
background-color: var(--color-deep);
background-blend-mode: lighten;
background-image: url("/assets/media/gnu.png");
}
section#freedom svg {
filter: drop-shadow(0 0 40px rgba(255, 255, 255, .3));
}

324
public/assets/css/shell.css Normal file
View file

@ -0,0 +1,324 @@
:root {
--primer-color-accent: 0, 128, 255;
--color-accent: rgb(var(--primer-color-accent));
--padding: 20px;
--running-size: 80px;
}
/* # Cornerstones */
* {
margin: 0;
fill: inherit;
box-sizing: border-box;
font-family: "Roboto Mono", sans-serif;
color: inherit;
font-size: inherit;
}
::-webkit-scrollbar {
display: none;
}
body {
display: grid;
justify-items: center;
grid-template-rows: var(--running-size) 1fr;
overscroll-behavior: none;
background-color: white;
color: black;
overflow-x: hidden;
min-height: 100svh;
font-size: 15px;
}
body::before {
transition: 1s opacity;
content: "";
position: absolute;
top: -5%;
right: 0;
width: 20%;
height: 5%;
border-radius: 100%;
z-index: 1000;
box-shadow:
0 0 30svh 10svh rgba(var(--primer-color-accent), .2),
0 0 30svh 60svh rgba(var(--primer-color-accent), .1),
0 0 30svh 150svh rgba(var(--primer-color-accent), .02)
;
opacity: 0;
}
/* "enable" the corner glow effect on initial load when a page has been fully loaded */
body[vv-top-page]::before {
opacity: 1;
}
a {
display: contents;
color: inherit;
text-decoration: none;
}
/* ## vv-shell */
vv-shell {
width: 100%;
display: flex;
position: relative;
flex-direction: column;
}
/* # Components */
:is(h1, h2, h3, p, li) > a {
--underline-tickness: 3px;
display: initial;
text-decoration: underline;
text-decoration-thickness: var(--underline-tickness);
text-underline-offset: var(--underline-tickness);
text-decoration-color: var(--color-accent);
}
h1 {
font-size: 30px;
color: var(--color-accent);
}
h2 {
font-size: 30px;
}
h3 {
font-size: 25px;
}
/* ## Page transition */
[vv-loading] * {
transition: 200ms opacity;
}
[vv-loading="true"] * {
opacity: 0;
pointer-events: none;
}
[vv-loading="true"]::after {
content: "";
position: fixed;
top: 50%;
left: 50%;
width: 45px;
height: 49px;
background-size: contain;
image-rendering: pixelated;
transform: translate(-50%, -50%);
background-image: url("/assets/media/spinner.gif");
-webkit-filter: hue-rotate(var(--hue-accent));
filter: hue-rotate(var(--hue-accent));
}
/* ## Buttons */
button {
border: none;
background-color: transparent;
color: inherit;
fill: inherit;
cursor: pointer;
}
/* ### Inline */
button.inline {
gap: 10px;
display: flex;
border-radius: 7px;
align-items: center;
fill: var(--color-accent);
color: var(--color-accent);
padding: calc(var(--padding) / 1.5);
background: linear-gradient(139deg, rgba(0, 0, 0, 0) 0%, rgba(var(--primer-color-accent), .1) 100%);
}
button.inline:not(.solid, .sly) {
box-shadow:
0 0 0 2px rgba(var(--primer-color-accent), .1),
10px 7px 40px 3px rgba(var(--primer-color-accent), .06)
;
}
button.inline svg {
flex: none;
height: 1em;
}
button.inline svg:last-child {
width: 1.5em;
margin-left: auto;
}
button.inline svg.chevron:last-child {
transform: rotate(-90deg);
}
/* #### Solid */
button.inline.solid {
fill: white;
color: white;
border-color: var(--color-accent);
background-color: var(--color-accent);
border: solid 2px rgba(var(--primer-color-accent), 1);
}
/* #### Sly */
button.sly {
border-color: transparent;
background: transparent;
box-shadow: none;
}
button.sly > svg.chevron {
transition: 200ms width;
width: 0;
}
button.sly:hover > svg.chevron {
width: 1.5em;
}
/* ## Header */
header {
--border-style: solid 1px rgba(0, 0, 0, .07);
top: 0;
width: 100%;
z-index: 100;
display: grid;
position: sticky;
overflow: hidden;
align-items: stretch;
backdrop-filter: blur(20px);
height: var(--running-size);
border-bottom: var(--border-style);
-webkit-backdrop-filter: blur(20px);
grid-template-rows: var(--running-size);
background-color: rgba(255, 255, 255, .8);
grid-template-columns: var(--running-size) repeat(2, 1fr);
}
/* ### Nav */
header nav {
display: flex;
align-items: center;
padding: var(--padding);
justify-content: baseline;
}
header nav:last-of-type {
justify-content: end;
gap: calc(var(--padding) / 2);
}
/* ### Spacer */
header nav > div {
width: 2px;
height: 80%;
margin: 0 var(--padding);
background-color: rgba(0, 0, 0, .07);
}
/* ### Buttons */
header button {
--icon-size: 25px;
display: grid;
border-left: var(--border-style);
grid-template-columns: 1fr;
align-items: center;
justify-items: center;
padding: var(--padding);
gap: var(--padding);
fill: var(--color-accent);
font-size: 13px;
color: rgba(255, 255, 255, .5);
cursor: pointer;
}
header button:not(.logo) svg {
width: var(--icon-size);
}
header button.search p {
display: none;
}
/* # Feature queries */
@media (hover: hover) {
:is(h1, h2, h3, p, li) > a:hover {
text-underline-offset: 1px;
text-decoration-thickness: calc(var(--underline-tickness) * 2);
color: var(--color-accent);
}
/* # Components */
button.inline {
transition-duration: 300ms;
transition-property: background-color, border-color, box-shadow, color, fill;
}
button:hover {
border-color: rgba(255, 255, 255, .2);
background-color: rgba(255, 255, 255, .1);
}
button.inline:hover {
fill: var(--color-accent);
color: var(--color-accent);
}
button.inline:not(.solid):hover {
box-shadow:
0 0 0 2px rgba(var(--primer-color-accent), 1),
10px 7px 30px 3px rgba(var(--primer-color-accent), .07)
;
}
button.solid:hover {
border-color: rgba(var(--primer-color-accent), .2);
background-color: rgba(var(--primer-color-accent), .2);
box-shadow: 0 -10px 20px 10px rgba(var(--primer-color-accent), .05);
}
}
/* # Size queries */
@media (min-width: 700px) {
:root {
--header-search-size: 250px;
}
/* # Cornerstones */
body::before {
right: unset;
left: 0;
box-shadow:
0 0 30svh 10svh rgba(var(--primer-color-accent), .1),
0 0 30svh 60svh rgba(var(--primer-color-accent), .05),
0 0 30svh 150svh rgba(var(--primer-color-accent), .02)
;
}
}

View file

@ -1,274 +0,0 @@
body {
background-color: rgba(var(--primer-color-deep), .01);
}
[vv-shell-id="/"] {
display: grid;
min-height: calc(100svh - var(--running-size) - var(--border-style-width));
grid-template-areas:
"aside main"
"contribute contribute"
;
grid-template-columns: 400px 1fr;
grid-template-rows: 1fr 200px;
gap: calc(var(--padding) * 2);
margin: auto;
}
[vv-shell-id="6ccb0465"] {
grid-area: main;
display: flex;
flex-direction: column;
gap: calc(var(--padding) * 2);
margin-top: calc(var(--padding) * 2);
padding-right: calc(var(--padding) * 2);
}
hr {
border: unset;
border-top: var(--border-style);
}
/* # Aside */
aside {
grid-area: aside;
height: 100%;
display: flex;
flex-direction: column;
padding: var(--padding) 0;
padding-left: calc(var(--padding) * 2);
border-right: var(--border-style);
}
aside button {
width: calc(100% - (var(--padding) * 2));
text-align: left;
}
aside hr {
margin: calc(var(--padding) * 2) 0;
}
aside ul {
list-style: none;
padding-left: 0;
}
aside ul ul {
padding-left: var(--padding);
}
aside ul > p {
margin: var(--padding) 0;
}
/* ---- */
aside .cc + ul {
display: none;
}
aside .cc.php button {
background-color: rgba(122, 134, 184, .2);
}
aside .cc.js button {
background-color: rgba(240, 219, 79, .3);
}
[vv-page^="/docs/API/PHP"] aside .cc.php + ul,
[vv-page^="/docs/API/JS"] aside .cc.js + ul {
display: initial;
}
/* # Collapsible */
details {
border: 1px solid #aaa;
border-radius: 4px;
padding: 0.5em 0.5em 0;
}
summary {
margin: -0.5em -0.5em 0;
padding: 0.5em;
cursor: pointer;
}
details[open] {
width: 100%;
padding: 0.5em;
}
details[open] summary {
border-bottom: 1px solid #aaa;
margin-bottom: 0.5em;
}
/* # Sections */
/* ## Inset */
section.inset {
padding-left: var(--padding);
}
/* ## Markdown */
section.md container {
padding-top: 0;
flex-direction: column;
align-items: baseline;
}
section.md :is(h1, h2, h3) {
cursor: pointer;
}
section.md h1::before {
content: "#";
opacity: 1;
padding: 0 10px;
margin-right: .5em;
color: var(--color-light);
background-color: var(--color-deep);
}
section.md h2::before {
content: "#";
opacity: 1;
margin-right: .5em;
color: var(--color-deep);
}
/* ## Code inline */
:is(h1, h2, h3, a, p, quote) > code {
padding: 5px;
border-radius: 6px;
white-space: nowrap;
font-family: 'Courier New', monospace;
background-color: rgba(0, 0, 0, .05);
}
code.tag::before {
content: "<";
}
code.tag::after {
content: ">";
}
/* ## Code block */
section.md pre {
width: 100%;
max-width: calc(100svw - (var(--padding) * 4));
tab-size: 3;
overflow: scroll;
}
section.md pre code {
--copy-size: 37px;
--copy-inset: 5px;
--copy-border-size: 1px;
overflow: scroll;
position: relative;
padding-right: calc(var(--copy-size) + (var(--copy-inset) * 2) + var(--padding));
border-radius: 6px;
}
section.md pre code::after {
content: "📋";
display: grid;
font-size: 20px;
cursor: pointer;
position: absolute;
border-radius: 4px;
align-items: center;
justify-items: center;
top: var(--copy-inset);
width: var(--copy-size);
right: var(--copy-inset);
height: var(--copy-size);
border: solid 1px rgba(255, 255, 255, .1);
background-color: rgba(255, 255, 255, .1);
}
@media (hover: hover) {
section.md h1:hover::before {
background-color: black;
}
section.md :is(h1, h2, h3):hover::after {
content: " <- click to copy link";
font-size: .5em;
opacity: .5;
}
section.md pre code:hover::after {
border: solid 1px rgba(255, 255, 255, .3);
background-color: rgba(255, 255, 255, .2);
}
}
/* ## Menu */
section.menu {
display: none;
fill: white;
color: white;
grid-area: menu;
cursor: pointer;
background-color: rgba(var(--primer-color-deep), .8);
}
section.menu container svg {
width: 1em;
}
section.menu p::before {
content: "Open ";
}
/* # Size queries */
@media (max-width: 950px) {
[vv-shell-id="/"] {
grid-template-areas:
"menu"
"main"
"contribute"
;
grid-template-columns: 1fr;
grid-template-rows: var(--running-size) 1fr 300px;
}
body.docsMenuOpen [vv-shell-id="/"] {
grid-template-areas:
"menu"
"aside"
;
grid-template-rows: var(--running-size) 1fr;
}
body.docsMenuOpen [vv-shell-id="6ccb0465"],
body.docsMenuOpen section.contribute,
body:not(.docsMenuOpen) aside {
display: none;
}
/* ---- */
[vv-shell-id="6ccb0465"] {
margin-top: unset;
}
/* ---- */
section.menu {
display: initial;
}
}

View file

@ -0,0 +1,5 @@
footer {
width: 100%;
height: var(--running-size);
background-color: var(--color-accent);
}

Binary file not shown.

View file

@ -0,0 +1,32 @@
const PUBLIC_ELEMENT_STYLESHEET_DIR = "/assets/css/elements/";
export class CustomElement extends HTMLElement {
constructor() {
super();
}
/**
* Return a pathname to a custom element CSS stylesheet
* @param {String} stylesheet
* @returns {String}
*/
static #getElementStylesheetHref(stylesheet) {
return `${PUBLIC_ELEMENT_STYLESHEET_DIR}${stylesheet}.css`;
}
/**
* Include a stylesheet for a custom element
* @param {String} stylesheet
*/
importElementStylesheet(stylesheet) {
if (document.head.querySelector(`link[href="${CustomElement.#getElementStylesheetHref(stylesheet)}"]`)) {
return;
}
const element = document.createElement("link");
element.href = CustomElement.#getElementStylesheetHref(stylesheet);
element.rel = "stylesheet";
document.head.appendChild(element);
}
}

View file

@ -0,0 +1,13 @@
import { CustomElement } from "./CustomElement.mjs";
export const TAG_NAME = "code-demo";
class HTMLCodeDemoElement extends CustomElement {
constructor() {
super();
this.importElementStylesheet(this.constructor.name);
}
}
globalThis.customElements.define(TAG_NAME, HTMLCodeDemoElement);

View file

@ -0,0 +1 @@
<svg class="points" viewBox="0 0 170.34 170.34" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path style="fill:none;stroke:#000;stroke-width:8px;stroke-miterlimit:0;stroke-dashoffset:10px;stroke-opacity:1" d="M335.16 141.72a88.59 88.59 0 0 1 0 2.3m-.1 2.93c-.01.38-.03.77-.06 1.15m-.23 2.91-.13 1.15m-.38 2.9-.18 1.14m-.53 2.87-.23 1.13m-.68 2.85-.29 1.11m-.82 2.8c-.11.38-.23.74-.35 1.1m-.95 2.77-.4 1.08m-1.1 2.7-.46 1.07m-1.23 2.65-.51 1.03m-1.37 2.59-.56 1m-1.49 2.52-.61.97m-1.62 2.44-.66.95m-1.73 2.35-.71.9m-1.85 2.27-.75.88m-1.97 2.16-.79.84m-2.07 2.06-.83.8m-2.17 1.96-.87.75m-2.27 1.85-.9.71m-2.36 1.74-.94.66m-2.44 1.61-.98.62m-2.51 1.49-1 .56m-2.6 1.36c-.34.17-.68.35-1.03.51m-2.65 1.23-1.06.46m-2.7 1.1-1.09.4m-2.76.96-1.1.35m-2.8.82-1.12.29m-2.84.67-1.13.24m-2.88.53-1.14.18m-2.9.38-1.14.12m-2.91.24c-.39.02-.77.05-1.16.06m-2.92.1a88.59 88.59 0 0 1-2.3 0m-2.92-.1c-.39-.01-.77-.04-1.16-.06m-2.9-.24-1.16-.12m-2.9-.38-1.13-.18m-2.88-.53-1.13-.24m-2.84-.67-1.12-.3m-2.8-.81-1.1-.35m-2.76-.96-1.08-.4m-2.71-1.1-1.06-.46m-2.65-1.23-1.04-.5m-2.58-1.37-1-.56m-2.52-1.5-.98-.6m-2.44-1.62-.94-.66m-2.35-1.74-.91-.7m-2.27-1.86-.87-.75m-2.17-1.96-.83-.8m-2.07-2.06-.8-.84m-1.96-2.16-.75-.88m-1.85-2.26-.7-.91m-1.74-2.35-.66-.95m-1.62-2.44-.61-.97m-1.5-2.52-.55-1m-1.37-2.59-.5-1.03m-1.24-2.65-.46-1.06m-1.1-2.71-.4-1.08m-.95-2.76-.35-1.1m-.82-2.8-.3-1.12m-.67-2.85-.23-1.13m-.53-2.87-.18-1.14m-.38-2.9-.13-1.15m-.23-2.9-.07-1.16m-.1-2.92a88.59 88.59 0 0 1 0-2.3m.1-2.93.07-1.15m.23-2.91.13-1.15m.38-2.9.18-1.14m.53-2.87.23-1.13m.68-2.85.29-1.11m.82-2.8c.11-.38.23-.74.35-1.1m.95-2.77.4-1.08m1.1-2.7.46-1.07m1.23-2.65.51-1.03m1.37-2.59.56-1m1.49-2.52.61-.97m1.62-2.44.66-.95m1.73-2.35.71-.9m1.85-2.27.75-.88m1.96-2.16.8-.84m2.07-2.06.83-.8m2.17-1.96.87-.75m2.27-1.85.9-.71m2.36-1.74.94-.66m2.44-1.61.98-.62m2.51-1.49 1-.56m2.6-1.36c.34-.17.68-.35 1.03-.51m2.65-1.23 1.06-.46m2.7-1.1 1.09-.4m2.76-.96 1.1-.35m2.8-.82 1.12-.29m2.84-.67 1.13-.24m2.88-.53 1.14-.18m2.9-.38 1.14-.12m2.91-.24c.39-.02.77-.05 1.16-.06m2.92-.1a83.58 83.58 0 0 1 2.3 0m2.92.1c.39.01.77.04 1.16.06m2.9.24 1.16.12m2.9.38 1.13.18m2.88.53 1.13.24m2.84.67 1.12.3m2.8.81 1.1.35m2.76.96 1.08.4m2.71 1.1 1.06.46m2.65 1.23 1.04.5m2.58 1.37 1 .56m2.52 1.5.98.6m2.44 1.62.94.66m2.35 1.74.91.7m2.27 1.86.87.75m2.17 1.96.83.8m2.07 2.06.8.84m1.96 2.16.75.88m1.85 2.26.7.91m1.74 2.35.66.95m1.62 2.44.61.97m1.5 2.52.55 1m1.37 2.59.5 1.03m1.24 2.65.46 1.06m1.1 2.71.4 1.08m.95 2.76.35 1.1m.82 2.8.3 1.12m.67 2.85.23 1.13m.53 2.87.18 1.14m.38 2.9.13 1.15m.23 2.9.07 1.16m.1 2.92v1.16" transform="translate(-168.83 -57.7)"/></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1 @@
<svg class="compass" viewBox="0 0 113.53 111.01" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><g style="fill:#0080ff;fill-opacity:1"><g fill="none" style="fill:#0080ff;fill-opacity:1"><path class="solid" d="M12 22 0 0h24z" style="display:inline;fill:#0080ff;fill-opacity:1" transform="rotate(180 44.15 27.75) scale(2.52299)"/><path class="stroke" d="M12 17.82 20.63 2H3.37L12 17.82M12 22 0 0h24z" style="display:inline;fill:#0080ff;fill-opacity:1" transform="rotate(180 44.15 27.75) scale(2.52299)"/></g><g fill="none" style="fill:#0080ff;fill-opacity:1"><path class="solid" d="M12 22 0 0h24z" style="display:inline;fill:#0080ff;fill-opacity:1" transform="translate(27.75 55.5) scale(2.52299)"/><path class="stroke" d="M12 17.82 20.63 2H3.37L12 17.82M12 22 0 0h24z" style="display:inline;fill:#0080ff;fill-opacity:1" transform="translate(27.75 55.5) scale(2.52299)"/></g><g opacity=".5" style="fill:#0080ff;fill-opacity:1"><path class="solid" d="M24 22 12 0h24z" style="display:inline;fill:#0080ff;fill-opacity:1" transform="rotate(90 30.28 25.23) scale(2.52299)"/><path class="stroke" d="M24 17.82 32.63 2H15.37L24 17.82M24 22 12 0h24z" style="display:inline;fill:#0080ff;fill-opacity:1" transform="rotate(90 30.28 25.23) scale(2.52299)"/></g><g opacity=".5" style="fill:#0080ff;fill-opacity:1"><path class="solid" d="M24 22 12 0h24z" style="display:inline;fill:#0080ff;fill-opacity:1" transform="rotate(-90 87.05 29.02) scale(2.52299)"/><path class="stroke" d="M24 17.82 32.63 2H15.37L24 17.82M24 22 12 0h24z" style="display:inline;fill:#0080ff;fill-opacity:1" transform="rotate(-90 87.05 29.02) scale(2.52299)"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1 @@
<svg class="chevron" viewBox="0 0 78.743 46.968" xmlns="http://www.w3.org/2000/svg"><path d="m530.436 290.342 6.658 8.935c4.438 5.956 8.512 11.037 12.222 15.242 3.71 4.205 7.691 8.797 11.945 13.776a590.023 590.023 0 0 1 11.95 14.425c3.713 4.638 9.56 11.441 17.54 20.41 7.98 8.97 15.892 17.872 23.736 26.707a2267.256 2267.256 0 0 0 21.633 24.05c6.578 7.197 11.225 8.056 13.942 2.576 2.717-5.48 8.45-12.8 17.199-21.96 8.748-9.162 15.904-16.447 21.468-21.856a2287.547 2287.547 0 0 1 17.272-16.611 674.569 674.569 0 0 0 16.506-16.229c5.054-5.154 9.753-9.968 14.098-14.443 4.344-4.475 9.494-10.016 15.448-16.624 5.954-6.607 10.747-11.748 14.38-15.422 3.631-3.675 6.18-6.009 7.645-7.003a16.094 16.094 0 0 1 4.757-2.202 16.095 16.095 0 0 1 5.212-.568c1.768.096 3.474.47 5.12 1.126a16.094 16.094 0 0 1 4.492 2.701 16.094 16.094 0 0 1 3.394 3.995 16.094 16.094 0 0 1 1.941 4.87c.381 1.729.476 3.473.285 5.234a16.094 16.094 0 0 1-1.402 5.051 16.095 16.095 0 0 1-2.94 4.34c-15.004 15.842-39.417-8.906-22.252-23.487a16.094 16.094 0 0 1 4.491-2.703 16.094 16.094 0 0 1 5.12-1.127 16.095 16.095 0 0 1 5.211.567 16.095 16.095 0 0 1 4.758 2.2 16.094 16.094 0 0 1 3.805 3.606 16.094 16.094 0 0 1 2.456 4.631c.565 1.678.848 3.403.848 5.173 0 1.771-.283 3.495-.849 5.173a16.095 16.095 0 0 1-2.455 4.632l-1.606 2.112-5.37 4.582c-3.583 3.055-8.51 7.767-14.786 14.135a11933.445 11933.445 0 0 0-15.839 16.1c-4.284 4.364-8.943 9.26-13.975 14.688a75638.076 75638.076 0 0 1-15.826 17.063 2642.057 2642.057 0 0 0-15.89 17.273c-5.073 5.567-11.507 12.866-19.3 21.897-7.794 9.03-13.63 15.948-17.51 20.753a496.057 496.057 0 0 1-12.49 14.836c-4.447 5.085-9.976 7.77-16.588 8.052-6.612.283-12.583-2.325-17.913-7.822-5.33-5.498-11.117-11.861-17.361-19.091-6.245-7.23-11.274-13.11-15.087-17.64a385.872 385.872 0 0 0-11.496-13.06 905.91 905.91 0 0 1-12.117-13.426c-4.228-4.774-10.087-11.613-17.577-20.518-7.49-8.905-13.37-15.797-17.635-20.676-4.266-4.88-8.437-9.663-12.511-14.35-4.075-4.687-8.453-9.915-13.135-15.684-4.681-5.77-7.355-9.208-8.02-10.317a15.914 15.914 0 0 1-1.567-3.517 15.937 15.937 0 0 1 .724-11.305 15.914 15.914 0 0 1 2.003-3.288 15.914 15.914 0 0 1 2.733-2.713 15.913 15.913 0 0 1 3.302-1.98 15.914 15.914 0 0 1 3.68-1.132 15.914 15.914 0 0 1 3.845-.219c1.29.083 2.552.319 3.785.708 1.233.39 2.401.92 3.505 1.593a15.914 15.914 0 0 1 3.023 2.386l1.366 1.375z" transform="matrix(.26458 0 0 .26458 -132.758 -75.015)"/></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -1 +1 @@
<svg class="logo" viewBox="0 0 42.911 41.957" xmlns="http://www.w3.org/2000/svg"><g><path class="solid" d="M12 22 0 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(-.95357 0 0 -.95357 33.375 20.979)"/><path class="stroke" d="M12 17.823 20.63 2H3.37L12 17.823M12 22 0 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(-.95357 0 0 -.95357 33.375 20.979)"/></g><g fill="none" style="fill:#87ffff;fill-opacity:1"><path class="solid" d="M12 22 0 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(.95357 0 0 .95357 10.49 20.979)"/><path class="stroke" d="M12 17.823 20.63 2H3.37L12 17.823M12 22 0 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(.95357 0 0 .95357 10.49 20.979)"/></g><g opacity=".5" style="fill:#87ffff;fill-opacity:1"><path class="solid" d="M24 22 12 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="scale(.95357) rotate(90 12 10)"/><path class="stroke" d="M24 17.823 32.63 2H15.37L24 17.823M24 22 12 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="scale(.95357) rotate(90 12 10)"/></g><g opacity=".5" style="fill:#87ffff;fill-opacity:1"><path class="solid" d="M24 22 12 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(0 -.95357 .95357 0 21.932 43.864)"/><path class="stroke" d="M24 17.823 32.63 2H15.37L24 17.823M24 22 12 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(0 -.95357 .95357 0 21.932 43.864)"/></g></svg>
<svg viewBox="0 0 60.965 60.965" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path style="fill:#0080ff;fill-opacity:1;stroke-width:.529167" d="M0 0h135.467v135.467H0z" transform="matrix(.45004 0 0 .45004 0 0)"/><g style="fill:#87ffff;fill-opacity:1"><g fill="none" style="fill:#87ffff;fill-opacity:1"><path class="solid" d="M12 22 0 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(-.95357 0 0 -.95357 41.925 30.482)"/><path class="stroke" d="M12 17.823 20.63 2H3.37L12 17.823M12 22 0 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(-.95357 0 0 -.95357 41.925 30.482)"/></g><g fill="none" style="fill:#87ffff;fill-opacity:1"><path class="solid" d="M12 22 0 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(.95357 0 0 .95357 19.04 30.482)"/><path class="stroke" d="M12 17.823 20.63 2H3.37L12 17.823M12 22 0 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(.95357 0 0 .95357 19.04 30.482)"/></g><g opacity=".5" style="fill:#87ffff;fill-opacity:1"><path class="solid" d="M24 22 12 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(0 .95357 -.95357 0 29.529 7.597)"/><path class="stroke" d="M24 17.823 32.63 2H15.37L24 17.823M24 22 12 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(0 .95357 -.95357 0 29.529 7.597)"/></g><g opacity=".5" style="fill:#87ffff;fill-opacity:1"><path class="solid" d="M24 22 12 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(0 -.95357 .95357 0 30.482 53.368)"/><path class="stroke" d="M24 17.823 32.63 2H15.37L24 17.823M24 22 12 0h24z" style="display:inline;fill:#87ffff;fill-opacity:1" transform="matrix(0 -.95357 .95357 0 30.482 53.368)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -1,18 +0,0 @@
<style><?= VV::css("public/assets/css/pages/demos.css") ?></style>
<section id="wip">
<container>
<h1>WIP</h1>
<p>Sorry, this whole website is a work in progress.. this page especially so.</p>
</container>
</section>
<section id="websites">
<container>
<h1>Websites built with Vegvisir</h1>
<ul>
<li><a href="https://vlw.se" target="_blank"><button class="shade">https://vlw.se</button></a></li>
<li><a href="https://icellate.com" target="_blank"><button class="shade">https://icellate.com</button></a></li>
<li><a href="https://genemate.se" target="_blank"><button class="shade">https://genemate.se</button></a></li>
<li><a href="https://codeberg.org/vegvisir/website" target="_blank"><button class="shade">..and this website! (view source)</a></li>
</ul>
</container>
</section>

View file

@ -1,58 +1,33 @@
<?php
use const VVWebsite\MEDIA_DIR;
require_once VV::root("src/Consts.php");
?>
<style><?= VV::css("public/assets/css/pages/index.css") ?></style>
<section id="intro">
<container class="split">
<section id="intro" class="split">
<div>
<h2>Vegvisir</h2>
<h1>A PHP and JavaScript Web Framework</h1>
<p>that handles navigation and routing, and nothing else</p>
<h1>Vegvisir</h1>
<h2>is a PHP and JavaScript web framework with</h2>
<h1>native soft-navigation and asset injection</h1>
<h2>that also gives you</h2>
<h1>automatic soft-navigation from an MPA-like file structure</h1>
</div>
<div class="compass">
<?= VV::embed(MEDIA_DIR . "compass-points.svg") ?>
<?= VV::embed(MEDIA_DIR . "compass-points.svg") ?>
<?= VV::embed(MEDIA_DIR . "compass.svg") ?>
</div>
</container>
</section>
<section class="waves">
<div class="wave"></div>
<container class="split">
<div>&nbsp;</div>
<img src="assets/media/waves/shiponastick.svg">
</container>
<div class="wave"></div>
</section>
<section id="lead" class="deep">
<container>
<h1>This is a framework for building <strong>complete websites</strong> with automatic soft-navigation between pages that follow a traditional "multi-page" (MPA) file structure</h1>
</container>
</section>
<section id="softnav" class="info">
<container class="split">
<?= VV::embed("public/assets/media/replace.svg") ?>
<section id="assets" class="split">
<div>
<h1>Soft-navigation by design</h1>
<p>Vegvisir will automatically soft-navigate between your pages. Dive deeper and fetch only the parts of your site that haven't been loaded yet with the help of shells.</p>
<h1>Asset injection</h1>
<p>Vegvisir allows you to bundle your page JavaScript and CSS directly into a soft-navigated page using native PHP templating and the VV PHP class.</p>
</div>
</container>
</section>
<section class="divider">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
<path d="M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z" class="shape-fill"></path>
</svg>
</section>
<section id="byoe" class="info">
<container class="split reverse">
<?= VV::embed("public/assets/media/byoe.svg") ?>
<div>
<h1>TypeScript, Bootstrap, something else?</h1>
<p>No problem, Vegvisir's primary ethos is to not lock you down a specific paradigm. That is why Vegvisir will always try to interfere as little as possible with how and with what you build your website by being as simple as possible.</p>
<h2>Bring-Your-Own-Experience</h2>
<?= VV::include("elements/HTMLCodeDemoElement?id=index_assets") ?>
</div>
</container>
</section>
<section id="free" class="info">
<container class="split">
<?= VV::embed("public/assets/media/gnu.svg") ?>
<div>
<h1>It's a GNU!</h1>
<p>The big names in PHP frameworks are all licensed under the permissive MIT license. This legally allows those frameworks to be used to develop proprietary malware. Vegvisir is free to use and will always respects your rights.</p>
<h2>Free as in -dom AND beer</h2>
</div>
</container>
</section>
<?= VV::include("snippets/footer") ?>
<script><?= VV::js("public/assets/js/pages/index.js") ?></script>

96
public/shell.php Normal file
View file

@ -0,0 +1,96 @@
<?php
use const VVWebsite\{MEDIA_DIR, ICONS_DIR, DEFAULT_BUTTON_ICON};
require_once VV::root("src/Consts.php");
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta property="og:title" content="Vegvisir"/>
<meta property="og:type" content="website"/>
<meta property="og:description" content="A PHP and JavaScript Web Framework that handles navigation and routing, and nothing else."/>
<!--<meta property="og:image" content="https://vlw.se/assets/media/ogp.jpg"/>-->
<script>
<!--//--><![CDATA[//><!--
/**
* @licstart The following is the entire license notice for the JavaScript
* code in this page.
*
* Copyright (C) 2020 Free Software Foundation.
*
* The JavaScript code in this page is free software: you can redistribute
* it and/or modify it under the terms of the GNU General Public License
* (GNU GPL) as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version. The code is
* distributed WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU GPL
* for more details.
*
* As additional permission under GNU GPL version 3 section 7, you may
* distribute non-source (e.g., minimized or compacted) forms of that code
* without the copy of the GNU GPL normally required by section 4, provided
* you include this license notice and a URL through which recipients can
* access the Corresponding Source.
*
* @licend The above is the entire license notice for the JavaScript code
* in this page.
*/
//--><!]]>
</script>
<style><?= VV::css("public/assets/css/fonts") ?></style>
<style><?= VV::css("public/assets/css/shell") ?></style>
<title>Vegvisir</title>
<link rel="icon" href="/assets/media/logo.svg"/>
</head>
<body>
<header>
<a href="/"><?= VV::embed(MEDIA_DIR . "logo.svg") ?></a>
<nav>
<a href="/"><button class="inline sly">
<p>vegvisir</p>
</button></a>
<div></div>
<a href="/"><button class="inline sly">
<p>about</p>
<?= VV::embed(DEFAULT_BUTTON_ICON) ?>
</button></a>
<a href="/"><button class="inline sly">
<p>documentation</p>
<?= VV::embed(DEFAULT_BUTTON_ICON) ?>
</button></a>
<a href="/"><button class="inline sly">
<p>demos</p>
<?= VV::embed(DEFAULT_BUTTON_ICON) ?>
</button></a>
</nav>
<nav>
<a href="/"><button class="inline">
<?= VV::embed(ICONS_DIR . "email.svg") ?>
</button></a>
<a href="/"><button class="inline">
<?= VV::embed(ICONS_DIR . "matrix.svg") ?>
</button></a>
<a href="/"><button class="inline">
<?= VV::embed(ICONS_DIR . "codeberg.svg") ?>
</button></a>
<a href="/"><button class="inline solid">
<p>get vegvisir</p>
<?= VV::embed(DEFAULT_BUTTON_ICON) ?>
</button></a>
</nav>
</header>
<vv-shell></vv-shell>
<?= VV::init() ?>
<script type="module"><?= VV::js("public/assets/js/shell") ?></script>
</body>
</html>

View file

@ -0,0 +1 @@
<div><div style="top:0px;height:19px;" class="view-line"><span><span class="mtk14">&lt;</span><span class="mtk6">style</span><span class="mtk14">&gt;</span><span class="mtk6">&lt;?=</span><span class="mtk3">&nbsp;</span><span class="mtk17">VV</span><span class="mtk3">::</span><span class="mtk16">css</span><span class="mtk3">(</span><span class="mtk12">"demo.css"</span><span class="mtk3">)&nbsp;</span><span class="mtk6">?</span><span class="mtk6">&gt;</span><span class="mtk14">&lt;/</span><span class="mtk6">style</span><span class="mtk14">&gt;</span></span></div><div style="top:19px;height:19px;" class="view-line"><span><span class="mtk1">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="mtk14">&lt;</span><span class="mtk6">section</span><span class="mtk14">&gt;</span></span></div><div style="top:38px;height:19px;" class="view-line"><span><span class="mtk1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="mtk14">&lt;</span><span class="mtk6">h1</span><span class="mtk14">&gt;</span><span class="mtk1">Hello&nbsp;world</span><span class="mtk14">&lt;/</span><span class="mtk6">h1</span><span class="mtk14">&gt;</span></span></div><div style="top:57px;height:19px;" class="view-line"><span><span class="mtk1">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="mtk14">&lt;/</span><span class="mtk6">section</span><span class="mtk14">&gt;</span></span></div><div style="top:76px;height:19px;" class="view-line"><span><span class="mtk14">&lt;</span><span class="mtk6">script</span><span class="mtk14">&gt;</span><span class="mtk6">&lt;?=</span><span class="mtk3">&nbsp;</span><span class="mtk17">VV</span><span class="mtk3">::</span><span class="mtk16">css</span><span class="mtk3">(</span><span class="mtk12">"demo.js"</span><span class="mtk3">)&nbsp;</span><span class="mtk6">?</span><span class="mtk6">&gt;</span><span class="mtk14">&lt;/</span><span class="mtk6">script</span><span class="mtk14">&gt;</span></span></div></div>

18
snippets/footer.php Normal file
View file

@ -0,0 +1,18 @@
<style><?= VV::css("public/assets/css/snippets/footer") ?></style>
<footer>
<p>Copyleft <?= date("Y") ?> - All rights reversed</p>
<nav>
<a href="/"><button class="inline sly">
<p>vlw</p>
</button></a>
<a href="/"><button class="inline sly">
<p>license</p>
</button></a>
<a href="/"><button class="inline sly">
<p>website</p>
</button></a>
<a href="/"><button class="inline solid">
<p>contribute ❤️</p>
</button></a>
</nav>
</footer>

11
src/Consts.php Normal file
View file

@ -0,0 +1,11 @@
<?php
namespace VVWebsite;
/**
* # Media
* Constants related to media files
*/
const MEDIA_DIR = "/public/assets/media/";
const ICONS_DIR = MEDIA_DIR . "icons/";
const DEFAULT_BUTTON_ICON = ICONS_DIR . "chevron.svg";