Partially overhauled content system's metadata handling, Fixed & Added tools, Added missing resources, Other minor fixes, Added index compiler
Update .gitignore, .htaccess, and 48 more files...
This commit is contained in:
@@ -25,4 +25,7 @@ if($enable_gallery) {
|
||||
if($enable_waffle_iron) {
|
||||
echo('<link href="/resources/NibblePoker/css/snowflakes.min.css" rel="stylesheet"/>');
|
||||
}
|
||||
if($enable_debug_extras) {
|
||||
echo('<link href="/resources/NibblePoker/css/debugger.min.css" rel="stylesheet"/>');
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -24,4 +24,7 @@ if($enable_code_highlight) {
|
||||
if($enable_kitty_and_doggo_sounds) {
|
||||
echo('<script src="/resources/NibblePoker/js/nibblepoker-contributors.min.js"></script>');
|
||||
}
|
||||
if($enable_debug_extras) {
|
||||
echo('<script src="/resources/NibblePoker/js/nibblepoker-debug.min.js"></script>');
|
||||
}
|
||||
?>
|
||||
@@ -37,12 +37,11 @@ function printSidebarEntry($url, $title, $icon, $activeId) {
|
||||
<?php
|
||||
printSidebarEntry(l10n_url_abs('/content/?tags=application;web'), localize("sidebar.text.applications"), "fad fa-browser", "application");
|
||||
printSidebarEntry(l10n_url_abs('/content/?tags=library'), localize("sidebar.text.libraries"), "fad fa-puzzle-piece", "library");
|
||||
//printSidebarEntry(l10n_url_abs('/content/?tags=library'), localize("sidebar.text.libraries"), "fad fa-chart-scatter-3d", "library");
|
||||
printSidebarEntry(l10n_url_abs('/content/?tags=electronic'), localize("sidebar.text.electronics"), "fad fa-microchip", "electronic");
|
||||
?>
|
||||
<?php
|
||||
//printSidebarEntry(l10n_url_abs('/content/?tags=utility'), localize("sidebar.text.utilities"), "fad fa-toolbox", "utility");
|
||||
//printSidebarEntry(l10n_url_abs('/content/?tags=3d-print'), localize("sidebar.text.3d-print"), "fad fa-print", "3d-print");
|
||||
//<hr class="subtle">
|
||||
//printSidebarEntry(l10n_url_abs('/tools/'), localize("sidebar.text.tools"), "fad fa-tools", "tools");
|
||||
printSidebarEntry(l10n_url_abs('/tools/'), localize("sidebar.text.tools"), "fad fa-tools", "tools");
|
||||
?>
|
||||
<hr class="subtle">
|
||||
<?php
|
||||
|
||||
@@ -33,6 +33,7 @@ $enable_grids = false;
|
||||
$enable_code_highlight = false;
|
||||
$enable_gallery = false;
|
||||
$enable_kitty_and_doggo_sounds = false;
|
||||
$enable_debug_extras = false;
|
||||
|
||||
// Easter-egg optional features
|
||||
// > Belgium's independence day.
|
||||
|
||||
@@ -8,7 +8,7 @@ if(basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
|
||||
// Including required helpers.
|
||||
include_once 'commons/config.php';
|
||||
include_once 'commons/langs.php';
|
||||
include_once 'commons/content.php';
|
||||
include_once 'commons/content/manager.php';
|
||||
|
||||
// Required to make headings
|
||||
include_once 'commons/DOM/utils.php';
|
||||
@@ -872,7 +872,7 @@ class ComposerElement {
|
||||
|
||||
case ComposerElementTypes::TABLE:
|
||||
// Composing table.
|
||||
$htmlCode .= '<div class="overflow-x-scroll">';
|
||||
$htmlCode .= '<div class="overflow-x-auto">';
|
||||
$htmlCode .= '<table class="' . $this->get_modifiers_classes() . '">';
|
||||
|
||||
if(!is_null($this->head)) {
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
?>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
// Making sure the file is included and not accessed directly.
|
||||
if(basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
die();
|
||||
}
|
||||
|
||||
// Including required helpers.
|
||||
include_once 'commons/langs.php';
|
||||
|
||||
// Including subclasses.
|
||||
include_once 'commons/content/data/opengraph.php';
|
||||
include_once 'commons/content/data/twitter_card.php';
|
||||
|
||||
class ContentMetadata {
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
// Making sure the file is included and not accessed directly.
|
||||
if(basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
die();
|
||||
}
|
||||
|
||||
// Including required helpers.
|
||||
include_once 'commons/langs.php';
|
||||
|
||||
class OpenGraphData {
|
||||
public string $title;
|
||||
public string $description;
|
||||
public string $type;
|
||||
public string $url;
|
||||
public string $image;
|
||||
public string $image_type;
|
||||
|
||||
function __construct(array $title, array $description, string $type, string $url, string $image,
|
||||
string $image_type) {
|
||||
global $default_language;
|
||||
global $user_language;
|
||||
|
||||
$this->title = array_key_exists($user_language, $title) ? $title[$user_language] :
|
||||
(array_key_exists($default_language, $title) ? $title[$default_language] : $title[0]);
|
||||
$this->description = array_key_exists($user_language, $description) ? $description[$user_language] :
|
||||
(array_key_exists($default_language, $description) ? $description[$default_language] : $description[0]);
|
||||
|
||||
$this->type = $type;
|
||||
$this->url = $url;
|
||||
$this->image = $image;
|
||||
$this->image_type = $image_type;
|
||||
}
|
||||
|
||||
static function from_json(array $json_data): ?OpenGraphData {
|
||||
foreach(["title", "description", "type", "url", "image", "image_type"] as $wantedKey) {
|
||||
if(!key_exists($wantedKey, $json_data)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return new OpenGraphData(
|
||||
$json_data["title"],
|
||||
$json_data["description"],
|
||||
$json_data["type"],
|
||||
$json_data["url"],
|
||||
$json_data["image"],
|
||||
$json_data["image_type"]
|
||||
);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*enum Suit {
|
||||
case Hearts;
|
||||
case Diamonds;
|
||||
case Clubs;
|
||||
case Spades;
|
||||
}*/
|
||||
|
||||
// See: https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup
|
||||
/*class ContentTwitterMetadata {
|
||||
public string $title;
|
||||
public string $description;
|
||||
public string $type;
|
||||
public string $url;
|
||||
public string $image;
|
||||
public string $image_type;
|
||||
}*/
|
||||
|
||||
?>
|
||||
@@ -8,10 +8,10 @@ if(basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
|
||||
// Importing required scripts.
|
||||
include_once 'commons/langs.php';
|
||||
|
||||
abstract class ContentDisplayType {
|
||||
enum EContentDisplayType {
|
||||
const NONE = 0;
|
||||
const SEARCH = 1;
|
||||
const CONTENT = 2;
|
||||
const DISPLAY = 2;
|
||||
}
|
||||
|
||||
class ContentIndexEntry {
|
||||
@@ -57,7 +57,7 @@ class ContentManager {
|
||||
|
||||
function __construct(string $contentRootPath, string $requestedUrl, ?string $urlTags) {
|
||||
// Preparing default values
|
||||
$this->displayType = ContentDisplayType::NONE;
|
||||
$this->displayType = EContentDisplayType::NONE;
|
||||
$this->hasError = false;
|
||||
$this->errorMessageKey = "content.error.message.none";
|
||||
$this->requestedId = NULL;
|
||||
@@ -68,14 +68,21 @@ class ContentManager {
|
||||
// Doing some standard things
|
||||
$this->processUrl($requestedUrl, $urlTags);
|
||||
if(!$this->hasError) {
|
||||
if($this->displayType == ContentDisplayType::SEARCH) {
|
||||
if($this->displayType == EContentDisplayType::SEARCH) {
|
||||
$this->loadRootIndex(realpath($contentRootPath . "/index.json"));
|
||||
} elseif($this->displayType == ContentDisplayType::CONTENT) {
|
||||
} elseif($this->displayType == EContentDisplayType::DISPLAY) {
|
||||
$this->prepareContentFilePath($contentRootPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given url, and determines the display type.
|
||||
* If given, it also splits the tags and validates them.
|
||||
* @param string $requestedUrl
|
||||
* @param string|null $urlTags
|
||||
* @return void
|
||||
*/
|
||||
function processUrl(string $requestedUrl, ?string $urlTags): void {
|
||||
// Doing some dark magic whose inner workings are lost to times...
|
||||
$requestedUrlPart = explode(
|
||||
@@ -84,7 +91,7 @@ class ContentManager {
|
||||
)[0];
|
||||
|
||||
if(strcmp($requestedUrlPart, "/") == 0) {
|
||||
$this->displayType = ContentDisplayType::SEARCH;
|
||||
$this->displayType = EContentDisplayType::SEARCH;
|
||||
|
||||
if(is_null($urlTags)) {
|
||||
return;
|
||||
@@ -110,11 +117,16 @@ class ContentManager {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->displayType = ContentDisplayType::CONTENT;
|
||||
$this->displayType = EContentDisplayType::DISPLAY;
|
||||
$this->requestedId = ltrim(rtrim($requestedUrlPart, "/"), "/");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If currently in a "EContentDisplayType::SEARCH" context, load the index into memory.
|
||||
* @param string $rootIndexFilepath
|
||||
* @return void
|
||||
*/
|
||||
function loadRootIndex(string $rootIndexFilepath): void {
|
||||
// Loading the content index.
|
||||
$rawJsonContent = file_get_contents($rootIndexFilepath);
|
||||
@@ -162,6 +174,12 @@ class ContentManager {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* If currently in a "EContentDisplayType::DISPLAY" context, we prepare the path to the content definition.
|
||||
* This definition must be loaded afterward depending on the content's type. (content, tool, article, ...)
|
||||
* @param string $rootIndexFilepath
|
||||
* @return void
|
||||
*/
|
||||
function prepareContentFilePath(string $contentRootPath): void {
|
||||
// Sanitizing the requested ID.
|
||||
if(!ctype_alnum(str_replace("-", "", $this->requestedId))) {
|
||||
@@ -190,6 +208,12 @@ function get_content_file_path(string $contentRootPath, string $contentId): ?str
|
||||
}
|
||||
|
||||
// Functions for use in pages
|
||||
|
||||
/**
|
||||
* Prepares a ContentManager for the current page.
|
||||
* @param string $contentRootPath Root path for the relevant content ("<webRoot>/content", "<webRoot>/tools", ...)
|
||||
* @return ContentManager
|
||||
*/
|
||||
function getContentManager(string $contentRootPath): ContentManager {
|
||||
return new ContentManager(
|
||||
$contentRootPath,
|
||||
107
commons/content/metadata.php
Normal file
107
commons/content/metadata.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
// Making sure the file is included and not accessed directly.
|
||||
if(basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
die();
|
||||
}
|
||||
|
||||
// Including required helpers.
|
||||
include_once 'commons/langs.php';
|
||||
|
||||
/**
|
||||
* This class assumes that the Python-based preprocessor has
|
||||
* created and pre-validated all required fields for this object.
|
||||
*/
|
||||
class ContentMetadata {
|
||||
public string $metaTitleKey;
|
||||
public string $metaDescriptionKey;
|
||||
public string $metaAuthor;
|
||||
|
||||
public string $openGraphTitleKey;
|
||||
public string $openGraphDescriptionKey;
|
||||
public string $openGraphType;
|
||||
public string $openGraphUrl;
|
||||
public string $openGraphImage;
|
||||
public string $openGraphImageMime;
|
||||
|
||||
public string $twitterCardType;
|
||||
public string $twitterCardSite;
|
||||
public string $twitterCardTitleKey;
|
||||
public string $twitterCardDescriptionKey;
|
||||
public string $twitterCardImageUrl;
|
||||
public ?string $twitterCardImageAltKey;
|
||||
public string $twitterCardCreatorHandle;
|
||||
|
||||
/**
|
||||
* Prints all the HTML tags associated with that metadata.
|
||||
* @return void - Returns nothing
|
||||
*/
|
||||
public function renderHtml(): void {
|
||||
// Standard meta tags
|
||||
echo('<title>' . localize($this->metaTitleKey) . '</title>');
|
||||
echo('<meta name="description" content="' . localize($this->metaDescriptionKey) . '" />');
|
||||
echo('<meta name="author" content="' . $this->metaAuthor . '" />');
|
||||
|
||||
// OpenGraph tags
|
||||
echo('<meta property="og:title" content="' . localize($this->openGraphTitleKey) . '" />');
|
||||
echo('<meta property="og:description" content="' . localize($this->openGraphDescriptionKey) . '" />');
|
||||
echo('<meta property="og:type" content="' . $this->openGraphType . '" />');
|
||||
echo('<meta property="og:url" content="' . $this->openGraphUrl . '" />');
|
||||
echo('<meta property="og:image" content="' . $this->openGraphImage . '" />');
|
||||
echo('<meta property="og:image:type" content="' . $this->openGraphImageMime . '" />');
|
||||
|
||||
// Twitter tags
|
||||
echo('<meta name="twitter:card" content="' . $this->twitterCardType . '" />');
|
||||
echo('<meta name="twitter:site" content="' . $this->twitterCardSite . '" />');
|
||||
echo('<meta name="twitter:title" content="' . localize($this->twitterCardTitleKey) . '" />');
|
||||
echo('<meta name="twitter:description" content="' . localize($this->twitterCardDescriptionKey) . '" />');
|
||||
echo('<meta name="twitter:image" content="' . $this->twitterCardImageUrl . '" />');
|
||||
if(!is_null($this->twitterCardImageAltKey)) {
|
||||
echo('<meta name="twitter:image:alt" content="' . localize($this->twitterCardImageAltKey) . '" />');
|
||||
}
|
||||
echo('<meta name="twitter:creator" content="' . $this->twitterCardCreatorHandle . '" />');
|
||||
}
|
||||
|
||||
static function from_json(array $json_data): ?ContentMetadata {
|
||||
// Checking required fields
|
||||
foreach(["metaTitleKey", "metaDescriptionKey", "metaAuthor", "openGraphTitleKey", "openGraphDescriptionKey",
|
||||
"openGraphType", "openGraphUrl", "openGraphImage", "openGraphImageMime", "twitterCardType",
|
||||
"twitterCardSite", "twitterCardTitleKey", "twitterCardDescriptionKey", "twitterCardImageUrl",
|
||||
"twitterCardCreatorHandle"] as $wantedKey) {
|
||||
if(!key_exists($wantedKey, $json_data)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Preparing optional fields
|
||||
foreach(["twitterCardImageAltKey"] as $optionalKey) {
|
||||
if(!key_exists($optionalKey, $json_data)) {
|
||||
$json_data[$optionalKey] = null;
|
||||
}
|
||||
}
|
||||
|
||||
$metadata = new ContentMetadata();
|
||||
|
||||
$metadata->metaTitleKey = $json_data["metaTitleKey"];
|
||||
$metadata->metaDescriptionKey = $json_data["metaDescriptionKey"];
|
||||
$metadata->metaAuthor = $json_data["metaAuthor"];
|
||||
|
||||
$metadata->openGraphTitleKey = $json_data["openGraphTitleKey"];
|
||||
$metadata->openGraphDescriptionKey = $json_data["openGraphDescriptionKey"];
|
||||
$metadata->openGraphType = $json_data["openGraphType"];
|
||||
$metadata->openGraphUrl = $json_data["openGraphUrl"];
|
||||
$metadata->openGraphImage = $json_data["openGraphImage"];
|
||||
$metadata->openGraphImageMime = $json_data["openGraphImageMime"];
|
||||
|
||||
$metadata->twitterCardType = $json_data["twitterCardType"];
|
||||
$metadata->twitterCardSite = $json_data["twitterCardSite"];
|
||||
$metadata->twitterCardTitleKey = $json_data["twitterCardTitleKey"];
|
||||
$metadata->twitterCardDescriptionKey = $json_data["twitterCardDescriptionKey"];
|
||||
$metadata->twitterCardImageUrl = $json_data["twitterCardImageUrl"];
|
||||
$metadata->twitterCardImageAltKey = $json_data["twitterCardImageAltKey"];
|
||||
$metadata->twitterCardCreatorHandle = $json_data["twitterCardCreatorHandle"];
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -8,10 +8,12 @@ if(basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
|
||||
// Including required helpers.
|
||||
include_once 'commons/config.php';
|
||||
include_once 'commons/langs.php';
|
||||
include_once 'commons/content.php';
|
||||
|
||||
// Required to handle opengraph data
|
||||
include_once 'commons/content/opengraph.php';
|
||||
// Including the "ContentManager" to shut the IDE up.
|
||||
include_once 'commons/content/manager.php';
|
||||
|
||||
// Required to make the HTML meta-tags.
|
||||
include_once 'commons/content/metadata.php';
|
||||
|
||||
// Required to make headings
|
||||
include_once 'commons/DOM/utils.php';
|
||||
@@ -26,7 +28,7 @@ class ToolInfoFile {
|
||||
public string $icon;
|
||||
public string $titleKey;
|
||||
public ?string $subTitleKey;
|
||||
public OpenGraphData $openGraphData;
|
||||
//public OpenGraphData $openGraphData;
|
||||
|
||||
function __construct(string $domFile, ?string $langFile, ?array $codeFilesPaths, ?array $moduleFilesPaths,
|
||||
?array $styleFilesPaths, ?string $icon, ?string $titleKey, ?string $subTitleKey,
|
||||
@@ -39,7 +41,7 @@ class ToolInfoFile {
|
||||
$this->icon = is_null($icon) ? "fad fa-question" : $icon;
|
||||
$this->titleKey = is_null($titleKey) ? "unset" : $titleKey;
|
||||
$this->subTitleKey = $subTitleKey;
|
||||
$this->openGraphData = OpenGraphData::from_json($opengraph);
|
||||
//$this->openGraphData = OpenGraphData::from_json($opengraph);
|
||||
}
|
||||
|
||||
static function from_json(array $json_data): ?ToolInfoFile {
|
||||
@@ -103,7 +105,7 @@ class ToolInfoFile {
|
||||
abstract class ToolsContent {
|
||||
static function loadItemIndexFile(ContentManager $contentManager, string $contentRootPath): ?ToolInfoFile {
|
||||
// Preliminary check
|
||||
if(!$contentManager->displayType == ContentDisplayType::CONTENT) {
|
||||
if(!$contentManager->displayType == EContentDisplayType::DISPLAY) {
|
||||
$contentManager->hasError = true;
|
||||
$contentManager->errorMessageKey = "content.error.message.cannot.load.item.as.not.content";
|
||||
return null;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"sidebar.text.applications": "Applications",
|
||||
"sidebar.text.libraries": "Libraries",
|
||||
"sidebar.text.electronics": "Electronics",
|
||||
"sidebar.text.3d-print": "3D Printing",
|
||||
"sidebar.text.tools": "Tools",
|
||||
"sidebar.text.links": "Links",
|
||||
"sidebar.text.downloads": "Downloads",
|
||||
|
||||
7
commons/strings/en/test.json
Normal file
7
commons/strings/en/test.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"test.header.title": "Test Page",
|
||||
"test.controls": "Debugging options",
|
||||
"test.controls.borders": "Show/Hide borders",
|
||||
"test.app.card.demo": "Application card",
|
||||
"test.content.card.demo": "Content card"
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
"sidebar.text.applications": "Applications",
|
||||
"sidebar.text.libraries": "Librairies",
|
||||
"sidebar.text.electronics": "Électronique",
|
||||
"sidebar.text.3d-print": "Impression 3D",
|
||||
"sidebar.text.tools": "Outils",
|
||||
"sidebar.text.links": "Liens",
|
||||
"sidebar.text.downloads": "Téléchargements",
|
||||
|
||||
7
commons/strings/fr/test.json
Normal file
7
commons/strings/fr/test.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"test.header.title": "Page de test",
|
||||
"test.controls": "Options de débogage",
|
||||
"test.controls.borders": "Afficher/Cacher les bordures",
|
||||
"test.app.card.demo": "Vignette d'application",
|
||||
"test.content.card.demo": "Vignette de contenu"
|
||||
}
|
||||
Reference in New Issue
Block a user