diff --git a/elements/HTMLCodeDemoElement.php b/elements/HTMLCodeDemoElement.php index e1b4f77..b85a61b 100644 --- a/elements/HTMLCodeDemoElement.php +++ b/elements/HTMLCodeDemoElement.php @@ -19,7 +19,7 @@ if (is_dir(VV::root($this->dir))) { // Strip "." and ".." - $this->files = array_filter(scandir(VV::root($this->dir)), function (string $item) { + $this->files = array_filter(scandir(VV::root($this->dir), SCANDIR_SORT_DESCENDING), function (string $item) { return substr($item, 0, 1) !== "."; }); @@ -28,6 +28,14 @@ } } + public static function name(string $file): string { + return substr($file, 0, strlen($file) - 4); + } + + public static function language(string $file): string { + return explode(".", $file, 3)[1]; + } + public function file_path(string $file): string { return $this->dir . $file; } @@ -37,8 +45,8 @@
files as $file): ?> - @@ -47,7 +55,7 @@
files as $file): ?> -
+
file_path($file)) ?>
diff --git a/public/assets/css/elements/HTMLCodeDemoElement.css b/public/assets/css/elements/HTMLCodeDemoElement.css index e156adf..4388e58 100644 --- a/public/assets/css/elements/HTMLCodeDemoElement.css +++ b/public/assets/css/elements/HTMLCodeDemoElement.css @@ -35,12 +35,51 @@ code-demo .header button.inline + button.inline { border-left: unset; } +/* ## Active */ + +code-demo .header button.active { + border-top: solid 4px var(--color-accent); + pointer-events: none; +} + +/* ## Languages */ + +code-demo .header button[data-lang="js"] { + --primer-color-accent: 241, 224, 90; + --color-accent: rgb(var(--primer-color-accent)); +} + +code-demo .header button[data-lang="css"] { + --primer-color-accent: 81, 154, 186; + --color-accent: rgb(var(--primer-color-accent)); +} + +code-demo .header button[data-lang="php"] { + --primer-color-accent: 160, 116, 196; + --color-accent: rgb(var(--primer-color-accent)); +} + +code-demo .header button[data-lang="html"] { + --primer-color-accent: 221, 120, 49; + --color-accent: rgb(var(--primer-color-accent)); +} + /* # Body */ code-demo .body { padding: var(--padding); } +/* ## Tabs */ + +code-demo .body [data-file] { + display: none; +} + +code-demo .body [data-file].active { + display: initial; +} + /* # Syntax highliting */ code-demo .mtk1 { color: #cccccc; } diff --git a/public/assets/css/pages/index.css b/public/assets/css/pages/index.css index 2363e13..923cb6a 100644 --- a/public/assets/css/pages/index.css +++ b/public/assets/css/pages/index.css @@ -1,17 +1,50 @@ +section { + min-height: 40svh; +} + /* # Components */ +/* ## Split */ + section.split { display: grid; + justify-items: center; grid-template-columns: repeat(2, 1fr); } section.split > div { + grid-row: 1; display: flex; align-items: center; flex-direction: column; justify-content: center; } +section.split.reverse > div:last-child { + grid-column: 1; +} + +section.split.reverse > div:first-child { + grid-column: 2; +} + +/* ### Text */ + +section.split .text { + width: 70%; + display: flex; + align-items: baseline; + flex-direction: column; +} + +/* ### Buttons */ + +section.split .buttons { + display: flex; + gap: var(--padding); + margin-top: var(--padding); +} + /* # Sections */ /* ## Intro */ @@ -48,6 +81,8 @@ section#intro div.compass svg:nth-child(2) { /* ## Assets */ -section#assets { - height: 100svh; +/* ## Freedom */ + +section#freedom > div > svg { + height: 300px; } \ No newline at end of file diff --git a/public/assets/css/snippets/docs/header.css b/public/assets/css/snippets/docs/header.css new file mode 100644 index 0000000..25eea4b --- /dev/null +++ b/public/assets/css/snippets/docs/header.css @@ -0,0 +1,59 @@ +/* # Overrides */ + +header { + position: relative; + border-bottom: none; +} + +/* # Sections */ + +/* ## Header */ + +section.header { + top: 0; + width: 100%; + display: flex; + color: white; + position: sticky; + overflow: hidden; + align-items: stretch; + height: calc(var(--running-size) - var(--padding)); + grid-template-rows: var(--running-size); + background-color: var(--color-accent); +} + +/* ### Nav */ + +section.header nav { + display: flex; + align-items: center; + padding: var(--padding); + justify-content: baseline; +} + +section.header nav:last-of-type { + justify-content: end; + gap: calc(var(--padding) / 2); +} + +/* ### Spacer */ + +section.header nav > div { + width: 2px; + height: 80%; + margin: 0 var(--padding); + background-color: rgba(0, 0, 0, .07); +} + +/* ### Buttons */ + +section.header button.inline:not(.solid):hover, +section.header button.inline { + fill: white; + color: white; +} + +section.header button.inline.solid { + color: var(--color-accent); + background-color: white; +} \ No newline at end of file diff --git a/public/assets/css/snippets/footer.css b/public/assets/css/snippets/footer.css index 73fd61f..9e04e1b 100644 --- a/public/assets/css/snippets/footer.css +++ b/public/assets/css/snippets/footer.css @@ -1,5 +1,48 @@ footer { width: 100%; + display: grid; + color: white; + position: sticky; + overflow: hidden; + align-items: stretch; height: var(--running-size); + grid-template-rows: var(--running-size); background-color: var(--color-accent); + grid-template-columns: repeat(2, 1fr); +} + +/* ### Nav */ + +footer nav { + display: flex; + align-items: center; + padding: var(--padding); + justify-content: baseline; +} + +footer nav:last-of-type { + justify-content: end; + gap: calc(var(--padding) / 2); +} + +/* ### Spacer */ + +footer nav > div { + width: 2px; + height: 80%; + margin: 0 var(--padding); + background-color: rgba(0, 0, 0, .07); +} + +/* ### Buttons */ + +footer button.inline:not(.solid):hover, +footer button.inline { + fill: white; + color: white; +} + +footer button.inline.solid { + color: var(--color-accent); + background-color: white; } \ No newline at end of file diff --git a/public/assets/js/elements/CustomElement.mjs b/public/assets/js/elements/CustomElement.mjs index 5499283..bf91ff6 100644 --- a/public/assets/js/elements/CustomElement.mjs +++ b/public/assets/js/elements/CustomElement.mjs @@ -29,4 +29,17 @@ export class CustomElement extends HTMLElement { document.head.appendChild(element); } + + connectedCallback() { + if ("connected" in this) { + this.connected(); + } + } + + disconnectedCallback() { + if ("disconnected" in this) { + this.disconnected(); + } + } + } \ No newline at end of file diff --git a/public/assets/js/elements/HTMLCodeDemoElement.mjs b/public/assets/js/elements/HTMLCodeDemoElement.mjs index 820b627..935aa85 100644 --- a/public/assets/js/elements/HTMLCodeDemoElement.mjs +++ b/public/assets/js/elements/HTMLCodeDemoElement.mjs @@ -2,12 +2,39 @@ import { CustomElement } from "./CustomElement.mjs"; export const TAG_NAME = "code-demo"; +const SELECTOR_HEADER_BUTTON = ".header button"; + class HTMLCodeDemoElement extends CustomElement { constructor() { super(); this.importElementStylesheet(this.constructor.name); } + + /** + * Set a tab as active by passing an HTMLElement with a data-lang attribute + * @param {HTMLElement} target + */ + #setActiveTab(target) { + [...this.querySelectorAll("[data-file]")].forEach(element => { + element.classList.remove("active"); + + // Set active if current element lang is target lang + if (element.dataset.file === target.dataset.file) { + element.classList.add("active"); + } + }); + } + + connected() { + // Bind event listeners for language tabs + [...this.querySelectorAll(SELECTOR_HEADER_BUTTON)].forEach(element => { + element.addEventListener("click", (event) => this.#setActiveTab(event.target.closest(SELECTOR_HEADER_BUTTON))) + }); + + // Make the first tab active on load + this.#setActiveTab(this.querySelector(SELECTOR_HEADER_BUTTON)); + } } globalThis.customElements.define(TAG_NAME, HTMLCodeDemoElement); \ No newline at end of file diff --git a/public/assets/media/icons/languages/css.svg b/public/assets/media/icons/languages/css.svg new file mode 100644 index 0000000..b19f6e1 --- /dev/null +++ b/public/assets/media/icons/languages/css.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/media/icons/languages/html.svg b/public/assets/media/icons/languages/html.svg new file mode 100644 index 0000000..b1b23b5 --- /dev/null +++ b/public/assets/media/icons/languages/html.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/media/icons/languages/js.svg b/public/assets/media/icons/languages/js.svg new file mode 100644 index 0000000..70a97c9 --- /dev/null +++ b/public/assets/media/icons/languages/js.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/media/icons/languages/php.svg b/public/assets/media/icons/languages/php.svg new file mode 100644 index 0000000..32c9700 --- /dev/null +++ b/public/assets/media/icons/languages/php.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/docs/index.php b/public/docs/index.php index 4a37ffd..1dc4b35 100644 --- a/public/docs/index.php +++ b/public/docs/index.php @@ -1,15 +1,7 @@ -
- -

Introduction

-

Vegvisir is a PHP and JavaScript web framework developed by Victor Westerlund as a hobby project.

-

This framework is not intended to replace the true-and-tested like Laravel, it would be interesting of course if it gained some users but my goal is to keep this project small and flexible.

-
-
-
- -

Scope

-

This documentation only covers the new experimental version of Vegvisir, which is version 3.

-

The older versions of Vegvisir can be found here. They lack proper documentation and function a bit differently than Vegvisir 3 which has been largely rewritten from scratch. The main addition to version 3 are what I call "shells".

-
-
- \ No newline at end of file + + \ No newline at end of file diff --git a/public/docs/installation.php b/public/docs/installation.php index 3640e61..f6a6587 100644 --- a/public/docs/installation.php +++ b/public/docs/installation.php @@ -1,85 +1,7 @@ - -
- -

Installation

-

In this guide we will be installing Vegvisir on a Debian-based system with NGINX as the web server. The process should be similar for other configurations as well.

-

Please contact me if you need help

-
-
-
- -

Prerequisites

-
    -
  • PHP 8.0 or newer (PHP 8.3 is recommended)
  • -
  • A web server (NGINX is used in this guide)
  • -
-
-
-
- -

Step 1: Clone the repo

-

Let's start by cloning Vegvisir to a folder. The code for Vegvisir will be separate from the code for your project.

- -

I have cloned this into the folder /var/www/vegvisir but you can put it wherever you want.

-
-
-
- -

Step 2: Install dependencies

-

Vegvisir only has one dependency, let's cd into our folder and install it with Composer.

- -
-
-
- -

Step 3: Configure virtual host

-

We will be pointing a virtual host to the /public/index.php file from the Vegvisir root directory.

-

Since your project files will live in a different directory, this can be set-and-forget.

- -
-
-
- -

Step 4: Create project folder

-

We're almost done here. We want to create a separate folder which will hold our project files.

-

Let's create a folder /var/www/my-website as an example - you can put this wherever you want!

- -
-
-
- -

Step 5: Point Vegvisir to project folder

-

Now let's finish up by pointing Vegvisir to the folder we just created.

-

Make a copy of the .env.example.ini file from Vegvisir's root directory and place it in the same spot as .env.ini

- -
-
-
- -

There is only one line we need to change inside the .env.ini file we just created. It should be the top most variable called root_path.

-

Change the value of this variable to an absolute path to your project root folder. In our case it will be /var/www/my-website.

- -
-
-
- -

Done!

-

That's all there is to it. Restart your webserver if you haven't and navigate to your published website.

-

If everything worked correctly, you should see a default landing page with a summary.

-
-
-
-
- -

Static assets

-

Vegvisir will automatically serve anything that isn't a .php file under /public in your project directory as a static asset. You can for example put your robots.txt file under /public/robots.txt and it will be returned as a text/plain document.

-

While this works fine for smaller assets, they still have to be passed through the PHP CGI. This process is a bit slower than serving assets with your web server directly - and might be a lot slower for larger files.

-

To fix this, let's add an optional location block to our NGINX configuration which will handle assets. The process should be similar for other web servers - contact me if you need help.

-
-
-
- -

Let's add the following location block to our NGINX virtual host that we set up in Step X.

-
-
- \ No newline at end of file + + \ No newline at end of file diff --git a/public/docs/API/JS/Navigation/EVENTS.php b/public/docs/v3.1.3/API/JS/Navigation/EVENTS.php similarity index 100% rename from public/docs/API/JS/Navigation/EVENTS.php rename to public/docs/v3.1.3/API/JS/Navigation/EVENTS.php diff --git a/public/docs/API/JS/Navigation/MODE.php b/public/docs/v3.1.3/API/JS/Navigation/MODE.php similarity index 100% rename from public/docs/API/JS/Navigation/MODE.php rename to public/docs/v3.1.3/API/JS/Navigation/MODE.php diff --git a/public/docs/API/JS/Navigation/POSITION.php b/public/docs/v3.1.3/API/JS/Navigation/POSITION.php similarity index 100% rename from public/docs/API/JS/Navigation/POSITION.php rename to public/docs/v3.1.3/API/JS/Navigation/POSITION.php diff --git a/public/docs/API/JS/Navigation/TARGET.php b/public/docs/v3.1.3/API/JS/Navigation/TARGET.php similarity index 100% rename from public/docs/API/JS/Navigation/TARGET.php rename to public/docs/v3.1.3/API/JS/Navigation/TARGET.php diff --git a/public/docs/API/JS/Navigation/abort.php b/public/docs/v3.1.3/API/JS/Navigation/abort.php similarity index 100% rename from public/docs/API/JS/Navigation/abort.php rename to public/docs/v3.1.3/API/JS/Navigation/abort.php diff --git a/public/docs/API/JS/Navigation/bindElements.php b/public/docs/v3.1.3/API/JS/Navigation/bindElements.php similarity index 100% rename from public/docs/API/JS/Navigation/bindElements.php rename to public/docs/v3.1.3/API/JS/Navigation/bindElements.php diff --git a/public/docs/API/JS/Navigation/constructor.php b/public/docs/v3.1.3/API/JS/Navigation/constructor.php similarity index 100% rename from public/docs/API/JS/Navigation/constructor.php rename to public/docs/v3.1.3/API/JS/Navigation/constructor.php diff --git a/public/docs/API/JS/Navigation/index.php b/public/docs/v3.1.3/API/JS/Navigation/index.php similarity index 100% rename from public/docs/API/JS/Navigation/index.php rename to public/docs/v3.1.3/API/JS/Navigation/index.php diff --git a/public/docs/API/JS/Navigation/navigate.php b/public/docs/v3.1.3/API/JS/Navigation/navigate.php similarity index 100% rename from public/docs/API/JS/Navigation/navigate.php rename to public/docs/v3.1.3/API/JS/Navigation/navigate.php diff --git a/public/docs/API/JS/Navigation/options.php b/public/docs/v3.1.3/API/JS/Navigation/options.php similarity index 100% rename from public/docs/API/JS/Navigation/options.php rename to public/docs/v3.1.3/API/JS/Navigation/options.php diff --git a/public/docs/API/JS/index.php b/public/docs/v3.1.3/API/JS/index.php similarity index 100% rename from public/docs/API/JS/index.php rename to public/docs/v3.1.3/API/JS/index.php diff --git a/public/docs/API/PHP/VV/css.php b/public/docs/v3.1.3/API/PHP/VV/css.php similarity index 100% rename from public/docs/API/PHP/VV/css.php rename to public/docs/v3.1.3/API/PHP/VV/css.php diff --git a/public/docs/API/PHP/VV/embed.php b/public/docs/v3.1.3/API/PHP/VV/embed.php similarity index 100% rename from public/docs/API/PHP/VV/embed.php rename to public/docs/v3.1.3/API/PHP/VV/embed.php diff --git a/public/docs/API/PHP/VV/include.php b/public/docs/v3.1.3/API/PHP/VV/include.php similarity index 100% rename from public/docs/API/PHP/VV/include.php rename to public/docs/v3.1.3/API/PHP/VV/include.php diff --git a/public/docs/API/PHP/VV/index.php b/public/docs/v3.1.3/API/PHP/VV/index.php similarity index 100% rename from public/docs/API/PHP/VV/index.php rename to public/docs/v3.1.3/API/PHP/VV/index.php diff --git a/public/docs/API/PHP/VV/js.php b/public/docs/v3.1.3/API/PHP/VV/js.php similarity index 100% rename from public/docs/API/PHP/VV/js.php rename to public/docs/v3.1.3/API/PHP/VV/js.php diff --git a/public/docs/API/PHP/VV/root.php b/public/docs/v3.1.3/API/PHP/VV/root.php similarity index 100% rename from public/docs/API/PHP/VV/root.php rename to public/docs/v3.1.3/API/PHP/VV/root.php diff --git a/public/docs/API/PHP/VV/shell.php b/public/docs/v3.1.3/API/PHP/VV/shell.php similarity index 100% rename from public/docs/API/PHP/VV/shell.php rename to public/docs/v3.1.3/API/PHP/VV/shell.php diff --git a/public/docs/API/PHP/index.php b/public/docs/v3.1.3/API/PHP/index.php similarity index 100% rename from public/docs/API/PHP/index.php rename to public/docs/v3.1.3/API/PHP/index.php diff --git a/public/docs/API/index.php b/public/docs/v3.1.3/API/index.php similarity index 100% rename from public/docs/API/index.php rename to public/docs/v3.1.3/API/index.php diff --git a/public/docs/v3.1.3/index.php b/public/docs/v3.1.3/index.php new file mode 100644 index 0000000..a278c91 --- /dev/null +++ b/public/docs/v3.1.3/index.php @@ -0,0 +1,18 @@ + +
+ +
+ +

Introduction

+

Vegvisir is a PHP and JavaScript web framework developed by Victor Westerlund as a hobby project.

+

This framework is not intended to replace the true-and-tested like Laravel, it would be interesting of course if it gained some users but my goal is to keep this project small and flexible.

+
+
+
+ +

Scope

+

This documentation only covers the new experimental version of Vegvisir, which is version 3.

+

The older versions of Vegvisir can be found here. They lack proper documentation and function a bit differently than Vegvisir 3 which has been largely rewritten from scratch. The main addition to version 3 are what I call "shells".

+
+
+
\ No newline at end of file diff --git a/public/docs/v3.1.3/installation.php b/public/docs/v3.1.3/installation.php new file mode 100644 index 0000000..db16866 --- /dev/null +++ b/public/docs/v3.1.3/installation.php @@ -0,0 +1,84 @@ + +
+ +

Installation

+

In this guide we will be installing Vegvisir on a Debian-based system with NGINX as the web server. The process should be similar for other configurations as well.

+

Please contact me if you need help

+
+
+
+ +

Prerequisites

+
    +
  • PHP 8.0 or newer (PHP 8.3 is recommended)
  • +
  • A web server (NGINX is used in this guide)
  • +
+
+
+
+ +

Step 1: Clone the repo

+

Let's start by cloning Vegvisir to a folder. The code for Vegvisir will be separate from the code for your project.

+ +

I have cloned this into the folder /var/www/vegvisir but you can put it wherever you want.

+
+
+
+ +

Step 2: Install dependencies

+

Vegvisir only has one dependency, let's cd into our folder and install it with Composer.

+ +
+
+
+ +

Step 3: Configure virtual host

+

We will be pointing a virtual host to the /public/index.php file from the Vegvisir root directory.

+

Since your project files will live in a different directory, this can be set-and-forget.

+ +
+
+
+ +

Step 4: Create project folder

+

We're almost done here. We want to create a separate folder which will hold our project files.

+

Let's create a folder /var/www/my-website as an example - you can put this wherever you want!

+ +
+
+
+ +

Step 5: Point Vegvisir to project folder

+

Now let's finish up by pointing Vegvisir to the folder we just created.

+

Make a copy of the .env.example.ini file from Vegvisir's root directory and place it in the same spot as .env.ini

+ +
+
+
+ +

There is only one line we need to change inside the .env.ini file we just created. It should be the top most variable called root_path.

+

Change the value of this variable to an absolute path to your project root folder. In our case it will be /var/www/my-website.

+ +
+
+
+ +

Done!

+

That's all there is to it. Restart your webserver if you haven't and navigate to your published website.

+

If everything worked correctly, you should see a default landing page with a summary.

+
+
+
+
+ +

Static assets

+

Vegvisir will automatically serve anything that isn't a .php file under /public in your project directory as a static asset. You can for example put your robots.txt file under /public/robots.txt and it will be returned as a text/plain document.

+

While this works fine for smaller assets, they still have to be passed through the PHP CGI. This process is a bit slower than serving assets with your web server directly - and might be a lot slower for larger files.

+

To fix this, let's add an optional location block to our NGINX configuration which will handle assets. The process should be similar for other web servers - contact me if you need help.

+
+
+
+ +

Let's add the following location block to our NGINX virtual host that we set up in Step X.

+
+
\ No newline at end of file diff --git a/public/error.php b/public/error.php new file mode 100644 index 0000000..ab85d6d --- /dev/null +++ b/public/error.php @@ -0,0 +1,3 @@ +
+

404 Not Found

+
\ No newline at end of file diff --git a/public/index.php b/public/index.php index f099a48..acbdacb 100644 --- a/public/index.php +++ b/public/index.php @@ -1,6 +1,6 @@
-
+

Asset injection

-

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.

+

Bundle your page JavaScript and CSS using native PHP templating and the VV PHP class directly into a automatically minified and soft-navigated page.

+
+
+
+

Automatic soft navigation

+

Vegvisir will automatically compile and soft-navigate between pages on your website without any modifications to your markdown. Even the file structure on disk follows an MPA-layout.

+ +
+
+ +
+
+
+
+

Respects your freedom

+

No tracking, no spying, fully available source that respects your freedom with GNU GPLv3.

+ +
+
+ +
+
\ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..14267e9 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Allow: / \ No newline at end of file diff --git a/public/shell.php b/public/shell.php index 26482b9..355c438 100644 --- a/public/shell.php +++ b/public/shell.php @@ -58,30 +58,30 @@

vegvisir

- - -