This commit is contained in:
Ro 2021-11-08 13:56:42 -08:00
commit cecead05a1
17 changed files with 476 additions and 3775 deletions

View file

@ -21,32 +21,48 @@ class SettingsAPI
file_get_contents("../content/themes/" . $theme . "/theme.json"),
true
);
//if render flag is set and false, just render index page for one page sites
//otherwise, render all pages according to theme template files
$render = new Render();
if (isset($themeConfig["render"])) {
if (!$themeConfig["render"] || $themeConfig["render"] === "false") {
$render->renderIndex();
$result = [
"message" => "Index Rendered. HAND CLAPS",
"type" => "TASK_NONE",
];
//check to see if dynamic rendering is active
if (
isset($settings["global"]["dynamicRender"]) &&
$settings["global"]["dynamicRender"] === "true"
) {
$result = [
"message" => "Dynamic Render Active! You're good!",
"type" => "RENDER_SUCCESS",
];
} else {
$render = new Render();
if (isset($themeConfig["render"])) {
if (!$themeConfig["render"] || $themeConfig["render"] === "false") {
$render->renderIndex();
$result = [
"message" => "Index Rendered. HAND CLAPS",
"type" => "RENDER_SUCCESS",
];
} else {
$render->renderTags();
$render->renderArchive();
$render->renderPages();
$result = [
"message" => "Site Rendered. GOOD EFFORT",
"type" => "RENDER_SUCCESS",
];
}
} else {
// just incase the render flag is missing
$render->renderTags();
$render->renderArchive();
$render->renderPages();
$result = [
"message" => "Site Rendered. GOOD EFFORT",
"type" => "TASK_NONE",
"type" => "RENDER_SUCCESS",
];
}
} else {
$render->renderTags();
$render->renderArchive();
$render->renderPages();
$result = [
"message" => "Site Rendered. GOOD EFFORT",
"type" => "TASK_NONE",
];
}
//if render flag is set and false, just render index page for one page sites
//otherwise, render all pages according to theme template files
break;
case "add-avatar":
$result = ImagesAPI::uploadImage($request, "avatar");

View file

@ -24,13 +24,15 @@ class DashControl
$themes = $config->getThemes();
$template = "dash/settings.twig";
$member = Session::get("member");
$form_token = Session::get("form_token");
$updated = new \Moment\Moment($settings["global"]["last_backup"]);
$pageOptions = [
"title" => "Dash Settings",
"private" => $settings["global"]["private"],
"render" => $settings["global"]["renderOnSave"],
"renderOnSave" => $settings["global"]["renderOnSave"],
"background" => $settings["global"]["background"],
"member" => $member,
"ftoken" => $form_token,
"siteTitle" => $settings["global"]["title"],
"baseUrl" => $settings["global"]["base_url"],
"desc" => $settings["global"]["descriptions"],
@ -40,6 +42,11 @@ class DashControl
"apiStatus" => isset($settings["global"]["externalAPI"])
? $settings["global"]["externalAPI"]
: "false",
"dynamicRenderStatus" => isset(
$settings["global"]["dynamicRender"]
)
? $settings["global"]["dynamicRender"]
: "false",
"mailOption" => $settings["email"]["active"],
"mailConfig" => $settings["email"],
"status" => Session::active(),

View file

@ -2,6 +2,7 @@
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Views\Twig;
use function _\find;
class IndexControl
{
@ -11,9 +12,87 @@ class IndexControl
array $args
): ResponseInterface {
//unset($_SESSION);
$config = new Settings();
$settings = $config->getSettings();
$view = Twig::fromRequest($request);
$html = file_get_contents("../public/index.html");
$response->getBody()->write($html);
return $response;
//checks dynamic render flag for site render status
if ($settings["global"]["dynamicRender"]) {
if ($settings["global"]["dynamicRender"] == "true") {
$loader = new \Twig\Loader\FilesystemLoader("../content/themes");
$display = new \Twig\Environment($loader, []);
$template = "";
$pageOptions = [];
$pageInfo = [
"keywords" => isset($settings["global"]["keywords"])
? $settings["global"]["keywords"]
: "fipamo, blog, jamstack, php, markdown, js",
"description" => $settings["global"]["descriptions"],
"image" =>
$settings["global"]["base_url"] . $settings["global"]["background"],
"baseURL" => $settings["global"]["base_url"],
];
if (isset($args["first"])) {
switch ($args["first"]) {
case "tags":
$template = $settings["global"]["theme"] . "/tags.twig";
$tag = trim($args["second"]);
$taglist = Sorting::tags();
$item = find($taglist, ["tag_name" => $tag]);
$pageOptions = [
"title" => "Pages Tagged as " . $item["tag_name"],
"background" => $pageInfo["image"],
"tag_list" => $item["pages"],
"info" => $pageInfo,
"menu" => $settings["menu"],
"dynamicRender" => $settings["global"]["dynamicRender"],
];
break;
case "archives":
$archive = Sorting::archive();
$template = $settings["global"]["theme"] . "/archive.twig";
$pageOptions = [
"title" => "Archive",
"background" => $pageInfo["image"],
"archives" => $archive,
"info" => $pageInfo,
"menu" => $settings["menu"],
"dynamicRender" => $settings["global"]["dynamicRender"],
];
break;
default:
$template = $settings["global"]["theme"] . "/page.twig";
$book = new Book("../content/pages");
$page = $book->findPageBySlug($args["third"]);
$pageOptions = Sorting::page($page);
break;
}
} else {
//index
$template = $settings["global"]["theme"] . "/index.twig";
$book = new Book("../content/pages");
$page = $book->findPageBySlug();
$pageOptions = Sorting::page($page);
}
$html = $display->render($template, $pageOptions);
$response->getBody()->write($html);
return $response;
} else {
$view = Twig::fromRequest($request);
$html = file_get_contents("../public/index.html");
$response->getBody()->write($html);
return $response;
}
} else {
//if flag is not present, default to static html
$view = Twig::fromRequest($request);
$html = file_get_contents("../public/index.html");
$response->getBody()->write($html);
return $response;
}
}
}

View file

@ -33,6 +33,18 @@ class Book
return $page;
}
public function findPageBySlug(string $slug = null)
{
$content = $this->getContents();
if (isset($slug)) {
$page = find($content, ["slug" => $slug]);
} else {
$page = find($content, ["layout" => "index"]);
}
return $page;
}
public function editPage($task, $request)
{
$content = $this->getContents();
@ -142,8 +154,25 @@ class Book
$status = DocTools::writePages($task, $path, $writePath, $write);
if ($status) {
$config = new Settings();
$settings = $config->getSettings();
$message = "";
if (
$settings["global"]["renderOnSave"] == "true" &&
$settings["global"]["dynamicRender"] == "false"
) {
$render = new Render();
$render->renderTags();
$render->renderArchive();
$render->renderPages();
$message = "Filed edited and rendered. NOICE.";
} else {
$message = "File edited. Nice work";
}
$response = [
"message" => "File edited. Nice work",
"message" => $message,
"type" => $task == "write" ? "postUpdated" : "postAdded",
"id" => $uuid,
];

View file

@ -47,6 +47,7 @@ class Member
"email" => $found["email"],
"role" => $found["role"],
"avatar" => $found["avi"],
"key" => $found["key"],
];
Session::set("member", $member);
}

View file

@ -74,6 +74,7 @@ class Render
$featured = [];
$limit = 4;
foreach ($pages as $page) {
//TODO: Move page data organization to render to utility class
if (!$page["deleted"] && $page["published"]) {
if (count($recent) < $limit) {
array_push($recent, [

View file

@ -39,6 +39,7 @@ class Settings
$settings["global"]["renderOnSave"] = $data["global"]["renderOnSave"];
$settings["global"]["theme"] = $data["global"]["theme"];
$settings["global"]["externalAPI"] = $data["global"]["externalAPI"];
$settings["global"]["dynamicRender"] = $data["global"]["dynamicRender"];
Member::updateData("handle", $data["member"]["handle"]);
Member::updateData("email", $data["member"]["email"]);

View file

@ -1,4 +1,5 @@
<?php
use Mni\FrontYAML\Parser;
use function _\find;
use function _\filter;
@ -93,4 +94,138 @@ class Sorting
}
return self::$_archive;
}
public static function page($page)
{
$config = new Settings();
$settings = $config->getSettings();
$pageOption = [];
$pageInfo = [
"keywords" => isset($settings["global"]["keywords"])
? $settings["global"]["keywords"]
: "fipamo, blog, jamstack, php, markdown, js",
"description" => $settings["global"]["descriptions"],
"image" =>
$settings["global"]["base_url"] . $settings["global"]["background"],
"baseURL" => $settings["global"]["base_url"],
];
$taglist = explode(",", $page["tags"]);
$tags = [];
foreach ($taglist as $tag) {
$label = trim($tag);
array_push($tags, [
"label" => $label . " ",
"slug" => StringTools::safeString($label),
]);
}
$meta = [
"who" => $page["author"],
"when" => $page["created"],
"tags" => $tags,
];
//render markdown content and clean it
$parser = new Parser();
$rendered = $parser->parse($page["content"]);
$sanitizer = HtmlSanitizer\Sanitizer::create([
"extensions" => ["basic", "image", "list", "code"],
"tags" => [
"img" => [
"allowed_attributes" => ["src", "alt", "title", "class"],
"allowed_hosts" => null,
],
],
]);
$preclean = $sanitizer->sanitize($rendered->getContent());
//just clean renderd string for now, Sanitize doesn't like relative img urls
//so another option is needed
$cleaned = strip_tags($rendered->getContent(), [
"a",
"br",
"p",
"strong",
"br",
"img",
"iframe",
"ul",
"li",
"i",
"h1",
"h2",
"h3",
"pre",
"code",
]);
//$cleaned = preg_replace('/(?:\r\n|[\r\n]){2,}/', "\n\n", $cleaned);
//$cleaned = html_entity_decode($cleaned, ENT_QUOTES, "UTF-8");
//if page feature isn't empty, replace page info meta image
if ($page["feature"] != "" || $page["feature"] != null) {
$pageInfo["image"] = $pageInfo["baseURL"] . $page["feature"];
}
if ($page["layout"] == "index") {
//$template = $this->theme . "/index.twig";
//$location = "../public/index.html";
//$dir = null;
$recent = [];
$featured = [];
$limit = 4;
$pages = (new Book("../content/pages"))->getContents();
foreach ($pages as $item) {
//TODO: Move page data organization to render to utility class
if (!$item["deleted"] && $item["published"]) {
if (count($recent) < $limit) {
array_push($recent, [
"path" => $item["path"],
"slug" => $item["slug"],
"title" => $item["title"],
]);
}
if ($item["featured"] == true) {
if (count($featured) < $limit) {
array_push($featured, [
"path" => $item["path"],
"slug" => $item["slug"],
"title" => $item["title"],
]);
}
}
}
}
$pageOptions = [
"title" => $page["title"],
"background" => $page["feature"],
"content" => $cleaned,
"meta" => $meta,
"recent" => $recent,
"featured" => $featured,
"info" => $pageInfo,
"menu" => $settings["menu"],
"dynamicRender" => $settings["global"]["dynamicRender"],
];
} else {
//$template = $this->theme . "/page.twig";
//$location = "../public/" . $page["path"] . "/" . $page["slug"] . ".html";
//$dir = "../public/" . $page["path"];
$pageOptions = [
"title" => $page["title"],
"background" => $page["feature"],
"content" => $cleaned,
"meta" => $meta,
"info" => $pageInfo,
"menu" => $settings["menu"],
"dynamicRender" => $settings["global"]["dynamicRender"],
];
}
return $pageOptions;
}
}

View file

@ -1,17 +1,11 @@
{% extends "dash/_frame.twig" %}
{% if render %}
{% set renderOnSave = 'true' %}
{% else %}
{% set renderOnSave = 'false' %}
{% endif %}
{% block title %}
{{ title }}
{% endblock %}
{% block stylesheets %}
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=asdfdf">
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=cvvvb">
{% endblock %}
{% block mainContent %}
@ -26,60 +20,86 @@
<svg id="submit-update" class="icons">
<use id="submit-update" xlink:href="/assets/images/global/sprite.svg#entypo-publish"/>
</svg>
</button>
</button>
<button id="render-toggle" title="render on save toggle" data-render="{{ renderOnSave }}">
<svg id="render-toggle" class="icons">
<use id="submit-update" xlink:href="/assets/images/global/sprite.svg#entypo-circular-graph"/>
</svg>
</button>
</div>
</div>
<div id="site-background">
<label>Site Header</label>
<img id="background" src="{{background}}" alt="image for site background" for="background-upload"/>
<input id="background-upload" type="file" name="backgrond-upload" />
</div>
<div id="settings-index">
<div id="settings-index-wrapper">
<div id="member-settings" class="columns">
<div id="member-settings-1" class="column is-one-third">
<div id="member-avatar-drop">
<img id="avatar" src="{{member['avatar']}}" for="avatar-upload"/>
<input id="avatar-upload" type="file" name="avatar-upload" />
<div id="member-settings">
<div id="member-images" class="columns">
<div class="column is-one-third">
<div id="member-avatar-drop">
<img id="avatar" src="{{member['avatar']}}" for="avatar-upload"/>
<input id="avatar-upload" type="file" name="avatar-upload" />
</div>
</div>
<div class="column is-two-thirds">
<div id="site-background">
<img id="background" src="{{background}}" alt="image for site background" for="background-upload"/>
<input id="background-upload" type="file" name="backgrond-upload" />
</div>
</div>
</div>
<div id="member-meta" class="columns">
<div class="column is-one-third">
<input type='text' name='handle' id='settings-handle' placeholder='handle' value="{{member['handle']}}" autofocus />
<input type='text' name='email' id='settings-email' placeholder='email' value="{{member['email']}}" autofocus />
</div>
<div class="column is-one-third">
<input type='text' name='base-url' id='settings-url' placeholder='url' value="{{baseUrl}}" autofocus />
<input type='text' name='base-title' id='settings-title' placeholder='site title' value="{{siteTitle}}" autofocus />
</div>
<div class="column is-one-third">
<textarea id="settings-desc" type='text' name='settings_desc' class='settings-dec' placeholder='description stuff', autofocus>{{desc}}</textarea>
</div>
</div>
<div class="column is-three-fifths">
<div class="columns">
<div id="member-settings-2" class="column">
<input type='text' name='handle' id='settings-handle' placeholder='handle' value="{{member['handle']}}" autofocus />
<input type='text' name='email' id='settings-email' placeholder='email' value="{{member['email']}}" autofocus />
</div>
<div id="member-settings-3" class="column">
<input type='text' name='base-url' id='settings-url' placeholder='url' value="{{baseUrl}}" autofocus />
<input type='text' name='base-title' id='settings-title' placeholder='site title' value="{{siteTitle}}" autofocus />
</div>
</div>
<div id="feature-settings">
<div id="features" class="columns">
<div class="column">
<div id="feature-api">
{% if apiStatus is defined and apiStatus == "true" %}
<button id="api-access-toggle" title="allow external api" data-enabled="true">
<svg id="api-access-toggle" class="icons">
<use id="api-access-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-landline"/>
</svg>
</button>
<span id="api-status">EXTERNAL API ACCESS ENABLED</span>
{% else %}
<button id="api-access-toggle" title="allow external api" data-enabled="false">
<svg id="api-access-toggle" class="icons">
<use id="api-access-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-landline"/>
</svg>
</button>
<span id="api-status">EXTERNAL API ACCESS NOT ENABLED</span>
{% endif %}
</div>
</div>
<div class="columns">
<div class="column is-full">
<textarea id="settings-desc" type='text' name='settings_desc' class='settings-dec' placeholder='description stuff', autofocus>{{desc}}</textarea><br />
<label>YOUR API KEY</label><br />
<span id="key">{{member['key']}}</span>
</div>
</div>
</div>
</div>
<div id="member-utils" class="columns">
<div id="util-1" class="column is-one-third">
<button id="create-backup">BACK UP YOUR SITE</button><br />
</div>
<div id="util-2" class="column is-three-fifths">
{% if lastBackup != '' %}
<div class="backup-meta">
LAST BACK UP <a href="/api/v1/files">{{lastBackup}}</a><br />
<div class="column">
<div id="dynamic-api">
{% if dynamicRenderStatus is defined and dynamicRenderStatus == "true" %}
<button id="dynamic-render-toggle" title="allow external api" data-enabled="true">
<svg id="dynamic-render-toggle" class="icons">
<use id="dynamic-render-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-text-document-inverted"/>
</svg>
</button>
<span id="dynamic-render-status">DYNAMIC PAGE RENDERING</span>
{% else %}
<button id="dynamic-render-toggle" title="allow external api" data-enabled="false">
<svg id="dynamic-render-toggle" class="icons">
<use id="dynamic-render-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-text-document-inverted"/>
</svg>
</button>
<span id="dynamic-render-status">STATIC PAGE RENDERING</span>
{% endif %}
</div>
{% else %}
<span>span No back ups. Frowny face.</span>
{% endif %}
</div>
</div>
</div>
<div id="option-settings" class="columns">
@ -117,28 +137,44 @@
{% endapply %}
<button id="send-mail">TEST MAIL</button>
<br /><br />
<label>API SETTINGS</label><br />
<div id="settings-api">
{% if apiStatus is defined and apiStatus == "true" %}
<button id="api-access-toggle" title="allow external api" data-enabled="true">
<svg id="api-access-toggle" class="icons">
<use id="api-access-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-landline"/>
</svg>
</button>
<span id="api-status">EXTERNAL API ACCESS ENABLED</span>
{% else %}
<button id="api-access-toggle" title="allow external api" data-enabled="false">
<svg id="api-access-toggle" class="icons">
<use id="api-access-toggle" xlink:href="/assets/images/global/sprite.svg#entypo-landline"/>
</svg>
</button>
<span id="api-status">EXTERNAL API ACCESS NOT ENABLED</span>
{% endif %}
</div>
</div>
</div>
<div id="token-settings">
<div id="keys-tokens" class="columns">
<div class="column">
<label>API KEY</label>
<div id="member-api-key">
{{member['key']}}
</div>
</div>
<div class="column">
<label>FORM TOKEN</label>
<div id="form-token">
{{ftoken}}
</div>
</div>
</div>
</div>
<div id="backup-settings">
<div class="columns">
<div class="column">
<button id="create-backup">BACK UP YOUR SITE</button><br />
</div>
<div class="column">
{% if lastBackup != '' %}
<div class="backup-meta">
LAST BACK UP <a href="/api/v1/files">{{lastBackup}}</a><br />
</div>
{% else %}
<span>span No back ups. Frowny face.</span>
{% endif %}
</div>
</div>
</div>
</div>

View file

@ -9,7 +9,8 @@
"theme": "fipamo-default",
"display_limit": 5,
"last_backup": null,
"externalAPI": "false"
"externalAPI": "false",
"dynamicRender": "false"
},
"library_stats": {
"current_index": 1

View file

@ -23,7 +23,16 @@
{{data.full_month}}
</span>
{% for page in data.pages %}
<a href="{{ "/"~item.year~"/"~data.month~"/"~page.slug~".html" }}">{{page.title}}</a><br />
{% if dynamicRender is defined %}
{% if dynamicRender %}
<a href="{{ "/"~item.year~"/"~data.month~"/"~page.slug }}">{{page.title}}</a><br />
{% else %}
<a href="{{ "/"~item.year~"/"~data.month~"/"~page.slug~".html" }}">{{page.title}}</a><br />
{% endif %}
{% else %}
<a href="{{ "/"~item.year~"/"~data.month~"/"~page.slug~".html" }}">{{page.title}}</a><br />
{% endif %}
{% endfor %}
</div>

View file

@ -34,7 +34,16 @@
<div class="right">
{% if menu is defined %}
{% for link in menu %}
<a href="{{"/"~link.path~"/"~link.slug~".html"}}" class="menu-link">{{link.title}}</a><br />
{% if dynamicRender is defined %}
{% if dynamicRender %}
<a href="{{"/"~link.path~"/"~link.slug}}" class="menu-link">{{link.title}}</a><br />
{% else %}
<a href="{{"/"~link.path~"/"~link.slug~".html"}}" class="menu-link">{{link.title}}</a><br />
{% endif %}
{% else %}
<a href="{{"/"~link.path~"/"~link.slug~".html"}}" class="menu-link">{{link.title}}</a><br />
{% endif %}
{% endfor %}
{% endif %}
</div>
@ -50,7 +59,16 @@
<footer>
<div class="inner">
<a href="/archives.html">Archives</a><br />
{% if dynamicRender is defined %}
{% if dynamicRender %}
<a href="/archives">Archives</a><br />
{% else %}
<a href="/archives.html">Archives</a><br />
{% endif %}
{% else %}
<a href="/archives.html">Archives</a><br />
{% endif %}
© 2020 By Fipamo
</div>
</footer>

View file

@ -17,14 +17,31 @@
<div class="recent">
<span>RECENT</span><br />
{% for item in recent %}
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
{% if dynamicRender is defined %}
{% if dynamicRender %}
<a href="{{ "/"~item.path~"/"~item.slug}}"> {{item.title}} </a><br />
{% else %}
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
{% endif %}
{% else %}
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
{% endif %}
{% endfor %}
</div>
<div class="featured">
<span>FEATURED</span><br />
{% for item in featured %}
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
{% if dynamicRender is defined %}
{% if dynamicRender %}
<a href="{{ "/"~item.path~"/"~item.slug}}"> {{item.title}} </a><br />
{% else %}
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
{% endif %}
{% else %}
<a href="{{ "/"~item.path~"/"~item.slug~".html" }}"> {{item.title}} </a><br />
{% endif %}
{% endfor %}
</div>

View file

@ -18,7 +18,16 @@
{{meta['who']}} dropped this {{ meta['when'] }}<br />
<strong>tags: </strong>
{% for tag in meta['tags'] %}
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
{% if dynamicRender is defined %}
{% if dynamicRender %}
<a href="{{ "/tags/"~tag.slug }}">{{ tag.label }}</a>
{% else %}
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
{% endif %}
{% else %}
<a href="{{ "/tags/"~tag.slug~".html" }}">{{ tag.label }}</a>
{% endif %}
{% endfor %}
</div>
</div>

View file

@ -13,7 +13,17 @@
<article>
<div class="page">
{% for tag in tag_list %}
{% if dynamicRender is defined %}
{% if dynamicRender %}
<a href="{{"/"~tag.path~"/"~tag.slug}}">{{tag.title}}</a><br />
{% else %}
<a href="{{"/"~tag.path~"/"~tag.slug~".html"}}">{{tag.title}}</a><br />
{% endif %}
{% else %}
<a href="{{"/"~tag.path~"/"~tag.slug~".html"}}">{{tag.title}}</a><br />
{% endif %}
{% endfor %}
</div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long