Let there be code!
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
*/vendor
|
||||
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*/vendor
|
||||
docker-compose.yaml
|
||||
28
Dockerfile
Normal file
@@ -0,0 +1,28 @@
|
||||
# Start with the official composer image, copy application files and install
|
||||
# dependencies.
|
||||
FROM composer AS composer
|
||||
COPY web/ /app
|
||||
RUN composer install --no-dev \
|
||||
--optimize-autoloader \
|
||||
--no-interaction \
|
||||
--no-progress
|
||||
|
||||
# Switch to trafex/php-nginx image and copy application files into it.
|
||||
FROM trafex/php-nginx
|
||||
COPY --chown=nginx --from=composer /app /var/www/html
|
||||
|
||||
# The trafex/php-nginx image runs as "nobody" user so we need to switch to root
|
||||
# so we can make changes inside the container.
|
||||
USER root
|
||||
|
||||
# We need the following PHP extensions.
|
||||
RUN apk add php8-fileinfo
|
||||
|
||||
# Create the cache directories.
|
||||
RUN mkdir -p /var/www/cache/application \
|
||||
&& chown nobody:nobody /var/www/cache/application \
|
||||
&& mkdir -p /var/www/cache/icons \
|
||||
&& chown nobody:nobody /var/www/cache/icons
|
||||
|
||||
# Switch back to the nobody user so we're not running as root forever.
|
||||
USER nobody
|
||||
BIN
web/assets/backgrounds/animal-g3298dcb04_1920.jpg
Normal file
|
After Width: | Height: | Size: 370 KiB |
BIN
web/assets/backgrounds/budapest-g056b86516_1920.jpg
Normal file
|
After Width: | Height: | Size: 534 KiB |
BIN
web/assets/backgrounds/building-gad730b330_1920.jpg
Normal file
|
After Width: | Height: | Size: 780 KiB |
BIN
web/assets/backgrounds/nature-gbde25f3ce_1920.jpg
Normal file
|
After Width: | Height: | Size: 726 KiB |
BIN
web/assets/backgrounds/san-francisco-g1a7f2aef8_1920.jpg
Normal file
|
After Width: | Height: | Size: 304 KiB |
BIN
web/assets/backgrounds/sea-ga4cb2ef0b_1920.jpg
Normal file
|
After Width: | Height: | Size: 845 KiB |
BIN
web/assets/backgrounds/seagull-gc0701fe2f_1920.jpg
Normal file
|
After Width: | Height: | Size: 305 KiB |
100
web/assets/css/styles.css
Normal file
@@ -0,0 +1,100 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #fff;
|
||||
font-family: -apple-system,system-ui,Ubuntu,Roboto,"Open Sans","Segoe UI","Helvetica Neue";
|
||||
font-size: 1em;
|
||||
text-align: center;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.background {
|
||||
filter: brightness(0.55) blur(13px);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
transform: scale(1.07);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
body::after {
|
||||
content: '';
|
||||
position:fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
background-image: url(../images/overlay.png);
|
||||
opacity: 0.6;
|
||||
z-index: 2;
|
||||
}
|
||||
.content {
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content:center;
|
||||
}
|
||||
|
||||
.greeting {
|
||||
font-size: 2.5em;
|
||||
text-transform: capitalize;
|
||||
text-shadow: 1px 2px 14px #000000;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.sites, .sites li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
font-weight: 300;
|
||||
font-size: 14px;
|
||||
}
|
||||
.sites li {
|
||||
display: inline-block;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
.sites li a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sites .icon {
|
||||
display: block;
|
||||
background-color: #fff;
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
border-radius: 10px;
|
||||
border: .2em solid #fff;
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,.3);
|
||||
margin: 0 11px 7px 11px;
|
||||
padding: 15px;
|
||||
}
|
||||
.sites .icon:hover {
|
||||
border-color: #007aff;
|
||||
transition: border-color .1s;
|
||||
}
|
||||
|
||||
.sites .icon img {
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.sites .name {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-height: 3.3em;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
text-shadow: 1px 1px 2px #000000
|
||||
}
|
||||
BIN
web/assets/images/default-icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web/assets/images/overlay.png
Normal file
|
After Width: | Height: | Size: 76 B |
1
web/assets/js/index.js
Normal file
@@ -0,0 +1 @@
|
||||
console.log('yay');
|
||||
11
web/background-css.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
// Provided by composer for psr-4 style autoloading.
|
||||
require __DIR__ .'/vendor/autoload.php';
|
||||
|
||||
$config = new Jump\Config();
|
||||
|
||||
$backgroundfile = (new Jump\Background($config))->get_random_background_file();
|
||||
$backgroundgradient = 'linear-gradient(to bottom, #FC466B40, #425df530)';
|
||||
|
||||
header('Content-Type: text/css');
|
||||
echo '.background {background-image: '.$backgroundgradient.', url("'.$backgroundfile.'");}';
|
||||
26
web/classes/Background.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Jump;
|
||||
|
||||
class Background {
|
||||
|
||||
private string $backgroundsdirectory;
|
||||
private array $backgroundfiles;
|
||||
|
||||
public function __construct(Config $config) {
|
||||
$this->config = $config;
|
||||
$this->backgroundsdirectory = $config->get('backgroundsdir');
|
||||
$this->webaccessibledir = str_replace($config->get('wwwroot'), '', $config->get('backgroundsdir'));
|
||||
$this->enumerate_files();
|
||||
}
|
||||
|
||||
private function enumerate_files(): void {
|
||||
$this->backgroundfiles = array_diff(scandir($this->backgroundsdirectory), array('..', '.'));
|
||||
}
|
||||
|
||||
public function get_random_background_file(bool $includepath = true): string {
|
||||
return ($includepath ? $this->webaccessibledir : '')
|
||||
. '/'. $this->backgroundfiles[array_rand($this->backgroundfiles)];
|
||||
}
|
||||
|
||||
}
|
||||
77
web/classes/Cache.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Jump;
|
||||
|
||||
use Nette\Caching;
|
||||
|
||||
class Cache {
|
||||
|
||||
private Caching\Storages\FileStorage $storage;
|
||||
|
||||
/**
|
||||
* The definition of various caches used throughout the application.
|
||||
*
|
||||
* @var array Multidimensional array
|
||||
*/
|
||||
private array $caches;
|
||||
private Config $config;
|
||||
|
||||
/**
|
||||
* Creates file storage for cache and initialises cache objects for each
|
||||
* name/type specified in $caches definition.
|
||||
*/
|
||||
public function __construct(Config $config) {
|
||||
$this->config = $config;
|
||||
// Define the various caches used throughout the app.
|
||||
$this->caches = [
|
||||
'sites' => [
|
||||
'cache' => null,
|
||||
'expirationtype' => Caching\Cache::FILES,
|
||||
'expirationparams' => $config->get('sitesfile')
|
||||
],
|
||||
'templates/sites' => [
|
||||
'cache' => null,
|
||||
'expirationtype' => Caching\Cache::FILES,
|
||||
'expirationparams' => [
|
||||
__DIR__.'/../config.php',
|
||||
$config->get('sitesfile'),
|
||||
$config->get('templatedir').'/sites.mustache'
|
||||
]
|
||||
]
|
||||
];
|
||||
// Inititalise file storage for cache using cachedir path from config.
|
||||
$this->storage = new Caching\Storages\FileStorage($this->config->get('cachedir').'/application');
|
||||
// Initialise a cache object for each cache name/type specified in caches array.
|
||||
array_walk($this->caches, function(&$cachedef, $cachename) {
|
||||
$cachedef['cache'] = new Caching\Cache($this->storage, $cachename);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the specified item from the cache or generate it, mostly a wrapper
|
||||
* around Nette\Caching\Cache::load().
|
||||
*
|
||||
* @param string $cachename The name of a cache type, must match a key in $caches definition.
|
||||
* @param callable $callback The code from which the result should be stored in cache.
|
||||
* @return mixed The result of callback function retreieved from cache.
|
||||
*/
|
||||
public function load(string $cachename, callable $callback): mixed {
|
||||
// If cachebypass has been set in config.php then just execute the callback.
|
||||
if ($this->config->parse_bool($this->config->get('cachebypass'))) {
|
||||
return $callback();
|
||||
}
|
||||
// We can only work with caches that have already been defined.
|
||||
if (!array_key_exists($cachename, $this->caches)) {
|
||||
throw new \Exception('Cache name not found ('.$cachename.')');
|
||||
}
|
||||
// Retrieve the initialised cache object from $caches, defines the caches expiry
|
||||
// and executes the callback.
|
||||
return $this->caches[$cachename]['cache']->load($cachename,
|
||||
function (&$dependencies) use ($callback, $cachename) {
|
||||
$dependencies[$this->caches[$cachename]['expirationtype']] = $this->caches[$cachename]['expirationparams'];
|
||||
return $callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
92
web/classes/Config.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Jump;
|
||||
|
||||
use Exception;
|
||||
|
||||
class Config {
|
||||
|
||||
private \PHLAK\Config\Config $config;
|
||||
|
||||
/**
|
||||
* Required files and directories need that should not be configurable.
|
||||
*/
|
||||
private const BASE_APPLICATION_PATHS = [
|
||||
'backgroundsdir' => '/assets/backgrounds',
|
||||
'sitesfile' => '/sites/sites.json',
|
||||
'templatedir' => '/templates',
|
||||
];
|
||||
|
||||
/**
|
||||
* Configurable params we do expect to find in config.php
|
||||
*/
|
||||
private const CONFIG_PARAMS = [
|
||||
'sitename',
|
||||
'wwwroot',
|
||||
'cachebypass',
|
||||
'cachedir',
|
||||
'noindex',
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
$this->config = new \PHLAK\Config\Config(__DIR__.'/../config.php');
|
||||
$this->add_wwwroot_to_base_paths();
|
||||
if ($this->config_params_missing()) {
|
||||
throw new Exception('Config.php must always contain... '.implode(', ', self::CONFIG_PARAMS));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefixes the wwwroot string from config.php to the base application paths
|
||||
* so they can be located in the file system correctly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function add_wwwroot_to_base_paths(): void {
|
||||
$wwwroot = $this->config->get('wwwroot');
|
||||
foreach(self::BASE_APPLICATION_PATHS as $key => $value) {
|
||||
$this->config->set($key, $wwwroot.$value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any configuration params are missing in the list loaded
|
||||
* from the config.php.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function config_params_missing(): bool {
|
||||
return !!array_diff(
|
||||
array_keys($this->config->toArray()),
|
||||
array_merge(
|
||||
array_keys(self::BASE_APPLICATION_PATHS),
|
||||
self::CONFIG_PARAMS
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the config parameter provided in $key, first checks for its
|
||||
* existence.
|
||||
*
|
||||
* @param string $key The config parameter required.
|
||||
* @return mixed The selected value from the configuration array.
|
||||
*/
|
||||
public function get(string $key): mixed {
|
||||
if (!$this->config->has($key)) {
|
||||
throw new Exception('Config key does not exist... ('.$key.')');
|
||||
}
|
||||
return $this->config->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to converts a string to a boolean correctly, will return the parsed boolean
|
||||
* or null on failure.
|
||||
*
|
||||
* @param mixed $input A string representing a boolean value... "true", "yes", "no", "false" etc.
|
||||
* @return mixed Returns a proper boolean or null on failure.
|
||||
*/
|
||||
public function parse_bool(mixed $input): mixed {
|
||||
return filter_var($input,FILTER_VALIDATE_BOOLEAN,FILTER_NULL_ON_FAILURE);
|
||||
}
|
||||
|
||||
}
|
||||
25
web/classes/Greeting.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Jump;
|
||||
|
||||
class Greeting {
|
||||
private array $greetings;
|
||||
|
||||
public function __construct() {
|
||||
$this->greetings = [
|
||||
03 => 'morning',
|
||||
12 => 'afternoon',
|
||||
16 => 'evening',
|
||||
19 => 'night'
|
||||
];
|
||||
}
|
||||
|
||||
public function get_greeting(): string {
|
||||
krsort($this->greetings);
|
||||
foreach ($this->greetings as $key => $value) {
|
||||
if (date('H', time()) >= $key) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
web/classes/Main.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Jump;
|
||||
|
||||
class Main {
|
||||
|
||||
private Cache $cache;
|
||||
private Greeting $greeting;
|
||||
private \Mustache_Engine $mustache;
|
||||
private array $outputarray;
|
||||
private Sites $sites;
|
||||
|
||||
public function __construct() {
|
||||
$this->config = new Config();
|
||||
$this->greeting = new Greeting();
|
||||
$this->mustache = new \Mustache_Engine([
|
||||
'loader' => new \Mustache_Loader_FilesystemLoader($this->config->get('templatedir'))
|
||||
]);
|
||||
$this->cache = new Cache($this->config);
|
||||
$this->sites = new Sites($this->config, $this->cache);
|
||||
}
|
||||
|
||||
private function render_header(): string {
|
||||
$template = $this->mustache->loadTemplate('header');
|
||||
return $template->render([
|
||||
'noindex' => $this->config->parse_bool($this->config->get('noindex')),
|
||||
'sitename' => $this->config->get('sitename'),
|
||||
]);
|
||||
}
|
||||
|
||||
private function render_greeting(): string {
|
||||
$template = $this->mustache->loadTemplate('greeting');
|
||||
return $template->render([
|
||||
'greeting' => $this->greeting->get_greeting(),
|
||||
]);
|
||||
}
|
||||
|
||||
private function render_sites(): string {
|
||||
return $this->cache->load('templates/sites', function() {
|
||||
$template = $this->mustache->loadTemplate('sites');
|
||||
return $template->render([
|
||||
'hassites' => !empty($this->sites->get_sites()),
|
||||
'sites' => $this->sites->get_sites()
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
private function render_footer(): string {
|
||||
$template = $this->mustache->loadTemplate('footer');
|
||||
return $template->render();
|
||||
}
|
||||
|
||||
public function build_index_page(): void {
|
||||
$this->outputarray = [
|
||||
$this->render_header(),
|
||||
$this->render_greeting(),
|
||||
$this->render_sites(),
|
||||
$this->render_footer(),
|
||||
];
|
||||
}
|
||||
|
||||
public function get_output(): string {
|
||||
return implode('', $this->outputarray);
|
||||
}
|
||||
|
||||
}
|
||||
40
web/classes/Site.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Jump;
|
||||
|
||||
class Site {
|
||||
|
||||
public string $name;
|
||||
public bool $nofollow;
|
||||
public string $icon;
|
||||
public string $url;
|
||||
|
||||
public function __construct(array $sitearray) {
|
||||
if (!isset($sitearray['name'], $sitearray['url'])) {
|
||||
throw new \Exception('The array passed to Site() must contain the keys "name" and "url"!');
|
||||
}
|
||||
$this->name = $sitearray['name'];
|
||||
$this->url = $sitearray['url'];
|
||||
$this->nofollow = isset($sitearray['nofollow']) ? $sitearray['nofollow'] : false;
|
||||
$this->icon = isset($sitearray['icon']) ? $this->get_favicon_datauri($sitearray['icon']) : $this->get_favicon_datauri();
|
||||
}
|
||||
|
||||
public function get_favicon_datauri(?string $icon = null): string {
|
||||
if ($icon === null) {
|
||||
$favicon = new \Favicon\Favicon();
|
||||
$favicon->cache([
|
||||
'dir' => '/var/www/cache/icons/',
|
||||
'timeout' => 86400
|
||||
]);
|
||||
$rawimage = $favicon->get($this->url, \Favicon\FaviconDLType::RAW_IMAGE);
|
||||
if (!$rawimage) {
|
||||
$rawimage = file_get_contents(__DIR__ . '/../assets/images/default-icon.png');
|
||||
}
|
||||
} else {
|
||||
$rawimage = file_get_contents(__DIR__ . '/../sites/icons/'.$icon);
|
||||
}
|
||||
$mimetype = (new \finfo(FILEINFO_MIME_TYPE))->buffer($rawimage);
|
||||
return 'data:'.$mimetype.';base64,'.base64_encode($rawimage);
|
||||
}
|
||||
|
||||
}
|
||||
82
web/classes/Sites.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Jump;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Represents the sites defined in sites.json
|
||||
*
|
||||
* @author Dale Davies {@link https://www.daledavies.co.uk}
|
||||
*/
|
||||
class Sites {
|
||||
|
||||
private Cache $cache;
|
||||
private Config $config;
|
||||
private string $sitesfilelocation;
|
||||
private array $loadedsites;
|
||||
|
||||
/**
|
||||
* Automatically load sites.json on instantiation.
|
||||
*/
|
||||
public function __construct(Config $config, Cache $cache) {
|
||||
$this->config = $config;
|
||||
$this->loadedsites = [];
|
||||
$this->sitesfilelocation = $this->config->get('sitesfile');
|
||||
$this->cache = $cache;
|
||||
$this->load_sites_from_json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load the list of sites from site.json.
|
||||
*
|
||||
* Throws an exception if the file cannot be loaded, is empty, or cannot
|
||||
* be decoded to an array,
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception if sites.json cannot be found
|
||||
*/
|
||||
private function load_sites_from_json(): void {
|
||||
$this->loadedsites = $this->cache->load('sites', function() {
|
||||
$sites = [];
|
||||
$rawjson = file_get_contents($this->sitesfilelocation);
|
||||
if ($rawjson === false) {
|
||||
throw new Exception('There was a problem loading the sites.json file');
|
||||
}
|
||||
if ($rawjson === '') {
|
||||
throw new Exception('The sites.json file is empty');
|
||||
}
|
||||
$decodedjson = json_decode($rawjson, true);
|
||||
if (!is_array($decodedjson)) {
|
||||
throw new Exception('Provided sites json does not contain a top-level array');
|
||||
}
|
||||
foreach ($decodedjson as $array) {
|
||||
$sites[] = new Site($array);
|
||||
}
|
||||
return $sites;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the loaded sites.
|
||||
*
|
||||
* @return array of sites loaded from sites.json
|
||||
*/
|
||||
public function get_sites(): array {
|
||||
return $this->loadedsites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a URL, does that site exist in our list of sites?
|
||||
*
|
||||
* @param string $url The URL to search for.
|
||||
* @return Site|null
|
||||
*/
|
||||
public function get_site_by_url(string $url): Site {
|
||||
$found = array_search($url, array_column($this->get_sites(), 'url'));
|
||||
if (!$found) {
|
||||
throw new Exception('The site could not be found ('.$url.')');
|
||||
}
|
||||
return $this->loadedsites[$found];
|
||||
}
|
||||
}
|
||||
16
web/composer.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "daledavies/jump",
|
||||
"description": "A startpage for stuff",
|
||||
"type": "project",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Jump\\": "classes/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"mustache/mustache": "~2.5",
|
||||
"arthurhoaro/favicon": "~1.0",
|
||||
"nette/caching": "^3.1",
|
||||
"phlak/config": "^7.0"
|
||||
}
|
||||
}
|
||||
647
web/composer.lock
generated
Normal file
@@ -0,0 +1,647 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "7ea3804d37d3b0050903f4604d6a82ab",
|
||||
"packages": [
|
||||
{
|
||||
"name": "arthurhoaro/favicon",
|
||||
"version": "v1.3.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ArthurHoaro/favicon.git",
|
||||
"reference": "b1acd8b87d6b37e5251fe0559ed488a95078f5b9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ArthurHoaro/favicon/zipball/b1acd8b87d6b37e5251fe0559ed488a95078f5b9",
|
||||
"reference": "b1acd8b87d6b37e5251fe0559ed488a95078f5b9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-fileinfo": "*",
|
||||
"php": ">=5.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.8",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"weew/helpers-filesystem": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Favicon\\": "src/Favicon/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Chris Shiflett",
|
||||
"homepage": "http://shiflett.org/"
|
||||
},
|
||||
{
|
||||
"name": "Arthur Hoaro",
|
||||
"homepage": "http://hoa.ro"
|
||||
}
|
||||
],
|
||||
"description": "PHP Library used to discover favicon from given URL",
|
||||
"homepage": "https://github.com/ArthurHoaro/favicon",
|
||||
"keywords": [
|
||||
"favicon",
|
||||
"finder",
|
||||
"icon"
|
||||
],
|
||||
"time": "2021-08-06T05:41:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mustache/mustache",
|
||||
"version": "v2.14.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bobthecow/mustache.php.git",
|
||||
"reference": "579ffa5c96e1d292c060b3dd62811ff01ad8c24e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/579ffa5c96e1d292c060b3dd62811ff01ad8c24e",
|
||||
"reference": "579ffa5c96e1d292c060b3dd62811ff01ad8c24e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "~1.11",
|
||||
"phpunit/phpunit": "~3.7|~4.0|~5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Mustache": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Justin Hileman",
|
||||
"email": "justin@justinhileman.info",
|
||||
"homepage": "http://justinhileman.com"
|
||||
}
|
||||
],
|
||||
"description": "A Mustache implementation in PHP.",
|
||||
"homepage": "https://github.com/bobthecow/mustache.php",
|
||||
"keywords": [
|
||||
"mustache",
|
||||
"templating"
|
||||
],
|
||||
"time": "2022-01-21T06:08:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/caching",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/caching.git",
|
||||
"reference": "27d8f0048eb1a9c7e49e0268f39b2db7d3ce7ae9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/caching/zipball/27d8f0048eb1a9c7e49e0268f39b2db7d3ce7ae9",
|
||||
"reference": "27d8f0048eb1a9c7e49e0268f39b2db7d3ce7ae9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nette/finder": "^2.4 || ^3.0",
|
||||
"nette/utils": "^2.4 || ^3.0",
|
||||
"php": ">=7.2 <8.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"latte/latte": "^2.10",
|
||||
"nette/di": "^v3.0",
|
||||
"nette/tester": "^2.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"tracy/tracy": "^2.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "⏱ Nette Caching: library with easy-to-use API and many cache backends.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"journal",
|
||||
"memcached",
|
||||
"nette",
|
||||
"sqlite"
|
||||
],
|
||||
"time": "2021-08-24T23:45:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/finder",
|
||||
"version": "v2.5.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/finder.git",
|
||||
"reference": "64dc25b7929b731e72a1bc84a9e57727f5d5d3e8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/finder/zipball/64dc25b7929b731e72a1bc84a9e57727f5d5d3e8",
|
||||
"reference": "64dc25b7929b731e72a1bc84a9e57727f5d5d3e8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nette/utils": "^2.4 || ^3.0",
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"conflict": {
|
||||
"nette/nette": "<2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "^2.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"tracy/tracy": "^2.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "🔍 Nette Finder: find files and directories with an intuitive API.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"filesystem",
|
||||
"glob",
|
||||
"iterator",
|
||||
"nette"
|
||||
],
|
||||
"time": "2021-12-12T17:43:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/utils",
|
||||
"version": "v3.2.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/utils.git",
|
||||
"reference": "0af4e3de4df9f1543534beab255ccf459e7a2c99"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/0af4e3de4df9f1543534beab255ccf459e7a2c99",
|
||||
"reference": "0af4e3de4df9f1543534beab255ccf459e7a2c99",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2 <8.2"
|
||||
},
|
||||
"conflict": {
|
||||
"nette/di": "<3.0.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "~2.0",
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"tracy/tracy": "^2.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "to use Image",
|
||||
"ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()",
|
||||
"ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
|
||||
"ext-json": "to use Nette\\Utils\\Json",
|
||||
"ext-mbstring": "to use Strings::lower() etc...",
|
||||
"ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()",
|
||||
"ext-xml": "to use Strings::length() etc. when mbstring is not available"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"array",
|
||||
"core",
|
||||
"datetime",
|
||||
"images",
|
||||
"json",
|
||||
"nette",
|
||||
"paginator",
|
||||
"password",
|
||||
"slugify",
|
||||
"string",
|
||||
"unicode",
|
||||
"utf-8",
|
||||
"utility",
|
||||
"validation"
|
||||
],
|
||||
"time": "2022-01-24T11:29:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phlak/config",
|
||||
"version": "7.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHLAK/Config.git",
|
||||
"reference": "a67af04eef18eabfad06442c86ddf692ca5bab0e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHLAK/Config/zipball/a67af04eef18eabfad06442c86ddf692ca5bab0e",
|
||||
"reference": "a67af04eef18eabfad06442c86ddf692ca5bab0e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1",
|
||||
"symfony/yaml": "^3.0 || ^4.0 || ^5.0",
|
||||
"yosymfony/toml": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.16.1",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
|
||||
"psy/psysh": "^0.10",
|
||||
"vimeo/psalm": "^3.7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PHLAK\\Config\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Chris Kankiewicz",
|
||||
"email": "Chris@ChrisKankiewicz.com"
|
||||
}
|
||||
],
|
||||
"description": "Config loading and management",
|
||||
"time": "2020-03-16T18:49:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v2.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8",
|
||||
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.5-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"function.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "A generic function and convention to trigger deprecation notices",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2021-07-12T14:48:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.24.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"provide": {
|
||||
"ext-ctype": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ctype": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Ctype\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "BackEndTea@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"ctype",
|
||||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"time": "2021-10-20T20:35:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v5.4.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "e80f87d2c9495966768310fc531b487ce64237a2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/e80f87d2c9495966768310fc531b487ce64237a2",
|
||||
"reference": "e80f87d2c9495966768310fc531b487ce64237a2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/deprecation-contracts": "^2.1|^3",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "<5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^5.3|^6.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/console": "For validating YAML files using the lint command"
|
||||
},
|
||||
"bin": [
|
||||
"Resources/bin/yaml-lint"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Yaml\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2022-01-26T16:32:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "yosymfony/parser-utils",
|
||||
"version": "v2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/yosymfony/parser-utils.git",
|
||||
"reference": "00bec9a12722b21f2baf7f9db35f127e90c162c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/yosymfony/parser-utils/zipball/00bec9a12722b21f2baf7f9db35f127e90c162c9",
|
||||
"reference": "00bec9a12722b21f2baf7f9db35f127e90c162c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Yosymfony\\ParserUtils\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Victor Puertas",
|
||||
"email": "vpgugr@gmail.com",
|
||||
"homepage": "http://yosymfony.com"
|
||||
}
|
||||
],
|
||||
"description": "Parser utilities",
|
||||
"homepage": "http://github.com/yosymfony/toml",
|
||||
"keywords": [
|
||||
"lexer",
|
||||
"parser"
|
||||
],
|
||||
"time": "2018-06-29T15:31:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "yosymfony/toml",
|
||||
"version": "v1.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/yosymfony/toml.git",
|
||||
"reference": "bdab92ad920d0e36810a3a3e4a998d23f3498f8e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/yosymfony/toml/zipball/bdab92ad920d0e36810a3a3e4a998d23f3498f8e",
|
||||
"reference": "bdab92ad920d0e36810a3a3e4a998d23f3498f8e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1",
|
||||
"yosymfony/parser-utils": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Yosymfony\\Toml\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Victor Puertas",
|
||||
"email": "vpgugr@gmail.com",
|
||||
"homepage": "http://yosymfony.com"
|
||||
}
|
||||
],
|
||||
"description": "A PHP parser for TOML compatible with specification 0.4.0",
|
||||
"homepage": "http://github.com/yosymfony/toml",
|
||||
"keywords": [
|
||||
"mojombo",
|
||||
"parser",
|
||||
"toml"
|
||||
],
|
||||
"time": "2018-08-08T15:08:14+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": []
|
||||
}
|
||||
9
web/config.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
// Edit the configuration below to suit your requirements.
|
||||
return [
|
||||
'sitename' => getenv('SITENAME') ?: 'Jump',
|
||||
'wwwroot' => getenv('WWWROOT') ?: '/var/www/html',
|
||||
'cachebypass' => getenv('CACHEBYPASS') ?: false,
|
||||
'cachedir' => getenv('CACHEDIR') ?: '/var/www/cache',
|
||||
'noindex' => getenv('NOINDEX') ?: true,
|
||||
];
|
||||
8
web/index.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
// Provided by composer for psr-4 style autoloading.
|
||||
require __DIR__ .'/vendor/autoload.php';
|
||||
|
||||
// Initialise the application, then render and output its index page.
|
||||
$jumpapp = new Jump\Main();
|
||||
$jumpapp->build_index_page();
|
||||
echo $jumpapp->get_output();
|
||||
BIN
web/sites/icons/bitwarden.png
Normal file
|
After Width: | Height: | Size: 418 B |
BIN
web/sites/icons/gitea.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
web/sites/icons/nextcloud.png
Normal file
|
After Width: | Height: | Size: 706 B |
BIN
web/sites/icons/paperless.jpg
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
30
web/sites/sites.json
Normal file
@@ -0,0 +1,30 @@
|
||||
[
|
||||
{
|
||||
"name": "Bitwarden",
|
||||
"url" : "https://bitwarden.leannedale.co.uk",
|
||||
"nofollow": true,
|
||||
"icon": "bitwarden.png"
|
||||
},
|
||||
{
|
||||
"name": "Gitea",
|
||||
"url" : "https://git.leannedale.co.uk",
|
||||
"nofollow": true,
|
||||
"icon": "gitea.png"
|
||||
},
|
||||
{
|
||||
"name": "Nextcloud",
|
||||
"url" : "https://cloud.leannedale.co.uk",
|
||||
"nofollow": true,
|
||||
"icon": "nextcloud.png"
|
||||
},
|
||||
{
|
||||
"name": "Paperless",
|
||||
"url" : "https://paperless.leannedale.co.uk",
|
||||
"nofollow": true,
|
||||
"icon": "paperless.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Google",
|
||||
"url" : "https://www.google.com"
|
||||
}
|
||||
]
|
||||
5
web/templates/footer.mustache
Normal file
@@ -0,0 +1,5 @@
|
||||
</div>
|
||||
<div class="background fixed"></div>
|
||||
{{! <script src="/assets/js/index.js"></script> }}
|
||||
</body>
|
||||
</html>
|
||||
1
web/templates/greeting.mustache
Normal file
@@ -0,0 +1 @@
|
||||
<div class="greeting">Good {{greeting}}</div>
|
||||
16
web/templates/header.mustache
Normal file
@@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
{{# noindex}}<meta name="robots" content="noindex">{{/ noindex}}
|
||||
|
||||
<title>{{sitename}}</title>
|
||||
|
||||
<link rel="stylesheet" href="/assets/css/styles.css">
|
||||
<link rel="stylesheet" href="background-css.php">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="content fixed">
|
||||
14
web/templates/sites.mustache
Normal file
@@ -0,0 +1,14 @@
|
||||
{{# hassites}}
|
||||
<ul class="sites">
|
||||
{{# sites}}
|
||||
<li>
|
||||
<a {{# nofollow}}rel="nofollow"{{/ nofollow}} href="{{url}}">
|
||||
<span class="icon">
|
||||
<img src="{{icon}}">
|
||||
</span>
|
||||
<span class="name">{{name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
{{/ sites}}
|
||||
</ul>
|
||||
{{/ hassites}}
|
||||