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:
2024-04-18 17:29:08 +02:00
parent be941fccca
commit 2827d6f8f6
51 changed files with 3102 additions and 220 deletions

4
.gitignore vendored
View File

@@ -8,9 +8,13 @@ package-lock.json
# Static resources
resources/DecimalJs/
resources/DecimalJsLight/
resources/ExtGraphics/
resources/FontAwesomePro/
resources/PlotlyJs/
# Article drafts
articles/drafts/
# Compiled Stuff
*.min.php
*.min.js

View File

@@ -30,7 +30,8 @@ AddType text/typescript .ts
AddType text/javascript .js
AddType text/javascript .mjs
AddType application/wasm .wasm
AddType video/x-matroska mkv
AddType video/x-matroska .mkv
AddType text/css .css
# Correcting some default options for security and language/content redirection.
@@ -56,7 +57,7 @@ ErrorDocument 404 /error.php
# * https://www.a2hosting.com/kb/developer-corner/apache-web-server/turning-off-caching-using-htaccess
# Default: 12 hours
##Header set Cache-Control "max-age=43200, public, must-revalidate"
Header set Cache-Control "max-age=43200, public, must-revalidate"
# Static files: 1 Week
<FilesMatch "\.(?i:gif|jpe?g|png|ico|svg|woff2|ttf|woff|otf)$">
@@ -64,9 +65,9 @@ ErrorDocument 404 /error.php
</FilesMatch>
# Semi-static files: 1 Day
##<FilesMatch "\.(?i:css|js|mjs)$">
## Header set Cache-Control "max-age=86400, public, must-revalidate"
##</FilesMatch>
<FilesMatch "\.(?i:css|js|mjs)$">
Header set Cache-Control "max-age=86400, public, must-revalidate"
</FilesMatch>
# Disabling some caching rules for debugging
#Header set Pragma "no-cache"

View File

@@ -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"/>');
}
?>

View File

@@ -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>');
}
?>

View File

@@ -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

View File

@@ -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.

View File

@@ -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)) {

View File

@@ -1,3 +0,0 @@
<?php
?>

View File

@@ -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 {
}
?>

View File

@@ -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"]
);
}
}
?>

View File

@@ -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;
}*/
?>

View File

@@ -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,

View 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;
}
}
?>

View File

@@ -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;

View File

@@ -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",

View 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"
}

View File

@@ -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",

View 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"
}

View File

@@ -10,10 +10,14 @@ echo.
echo Handling the raw content files
echo ------------------------------
:content-compile
:content-compile-index
echo Compiling index files...
python content_index_maker.py ./content/raw_index/ ./content/index.json
:content-compile-items
echo Compiling content item files...
python content_item_converter.py ./content/raw_items/ ./content/items/
:content-end

View File

@@ -20,6 +20,8 @@ echo ^> resources\NibblePoker\js\nibblepoker-code.js
call "%~dp0node_modules\.bin\terser" nibblepoker-code.js -c -m -o nibblepoker-code.min.js
echo ^> resources\NibblePoker\js\nibblepoker-contributors.js
call "%~dp0node_modules\.bin\terser" nibblepoker-contributors.js -c -m -o nibblepoker-contributors.min.js
echo ^> resources\NibblePoker\js\nibblepoker-debug.js
call "%~dp0node_modules\.bin\terser" nibblepoker-debug.js -c -m -o nibblepoker-debug.min.js
echo ^> resources\NibblePoker\js\nibblepoker-splide.js
call "%~dp0node_modules\.bin\terser" nibblepoker-splide.js -c -m -o nibblepoker-splide.min.js
popd

View File

@@ -18,6 +18,8 @@ call "%~dp0node_modules\.bin\sass" nibblepoker.scss:../css/nibblepoker.css -q
call "%~dp0node_modules\.bin\sass" nibblepoker.scss:../css/nibblepoker.min.css -q --style compressed
call "%~dp0node_modules\.bin\sass" snowflakes.scss:../css/snowflakes.css -q
call "%~dp0node_modules\.bin\sass" snowflakes.scss:../css/snowflakes.min.css -q --style compressed
call "%~dp0node_modules\.bin\sass" debugger.scss:../css/debugger.css -q
call "%~dp0node_modules\.bin\sass" debugger.scss:../css/debugger.min.css -q --style compressed
popd
pushd %CD%
cd %~dp0\wiki\scss\

20
compile-tools.cmd Normal file
View File

@@ -0,0 +1,20 @@
@echo off
setlocal enabledelayedexpansion
:: Going into the script's directory
cd /D "%~dp0"
:content
echo.
echo Handling the raw tools files
echo -----------------------------
:content-compile-index
echo Compiling index files...
python content_index_maker.py ./tools/raw_index/ ./tools/index.json
:content-end
:end

View File

@@ -33,6 +33,14 @@ set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "contributors/"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "debug/"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "links/"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "privacy/"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/ExtGraphics/*.png"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/ExtGraphics/*.svg"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/ExtGraphics/*/*.png"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/ExtGraphics/*/*.svg"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/ExtGraphics/*/*/*.png"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/ExtGraphics/*/*/*.svg"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/ExtGraphics/*/*/*/*.png"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/ExtGraphics/*/*/*/*.svg"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/FontAwesomePro/5.15.3/"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/FontAwesomePro/6.5.1/"
set NP_ZIP_CONTENT=%NP_ZIP_CONTENT% "resources/HighlightJS/highlight.min.js" "resources/HighlightJS/src/styles/atom-one-dark.min.css"
@@ -66,5 +74,7 @@ echo ^> Done !
:archive-end
echo You can use the following command on the server:
echo ^> 7z x %NP_ZIP_NAME% ^&^& chmod 755 -R ./ ^&^& rm %NP_ZIP_NAME%
:end

View File

@@ -7,11 +7,11 @@ include_once 'commons/config.php';
include_once 'commons/langs.php';
// Preparing the content
include_once 'commons/content.php';
include_once 'commons/composer.php';
include_once 'commons/content/manager.php';
include_once 'commons/content/composer.php';
$contentManager = getContentManager($config_dir_content);
$content = NULL;
if(!$contentManager->hasError && $contentManager->displayType == ContentDisplayType::CONTENT) {
if(!$contentManager->hasError && $contentManager->displayType == EContentDisplayType::DISPLAY) {
$content = load_content_by_file_path($contentManager->contentFilepath);
if(is_null($content)) {
$contentManager->hasError = true;
@@ -55,7 +55,7 @@ if($contentManager->hasError) {
$content_head_description = $content_error_message;
$content_head_og_title = localize("content.error.og.title");
$content_head_og_description = $content_error_message;
} elseif($contentManager->displayType == ContentDisplayType::CONTENT) {
} elseif($contentManager->displayType == EContentDisplayType::DISPLAY) {
$content_head_title =
localize("content.item.head.title.prefix") .
$content->get_head_title() .
@@ -96,7 +96,7 @@ if($contentManager->hasError) {
break;
}
}
} elseif($contentManager->displayType == ContentDisplayType::SEARCH) {
} elseif($contentManager->displayType == EContentDisplayType::SEARCH) {
$content_head_title = localize("content.search.head.title");
$content_head_description = localize("content.search.head.description");
$content_head_og_title = localize("content.search.og.title");
@@ -130,14 +130,14 @@ include 'commons/DOM/sidebar.php';
echo('<span class="mx-s t-size-15">❱</span>');
echo(localize("content.error.header"));
echo('</span>');
} elseif($contentManager->displayType == ContentDisplayType::SEARCH) {
} elseif($contentManager->displayType == EContentDisplayType::SEARCH) {
echo('<i class="fad fa-briefcase t-size-16 mr-s t-muted"></i>');
echo(localize("content.header.base"));
echo('<span class="mobile-hide">');
echo('<span class="mx-s t-size-15">❱</span>');
echo(localize("content.search.header"));
echo('</span>');
} elseif($contentManager->displayType == ContentDisplayType::CONTENT) {
} elseif($contentManager->displayType == EContentDisplayType::DISPLAY) {
echo('<i class="fad fa-briefcase t-size-16 mr-s t-muted"></i>');
echo(localize("content.header.base"));
echo('<span class="mobile-hide">');
@@ -153,9 +153,9 @@ include 'commons/DOM/sidebar.php';
<?php
// Checking if an error occurred.
if($content_error_code != 200) {
if($contentManager->displayType == ContentDisplayType::SEARCH) {
if($contentManager->displayType == EContentDisplayType::SEARCH) {
printMainHeader(localize("content.error.heading.main.search"), "fad fa-exclamation-triangle");
} elseif($contentManager->displayType == ContentDisplayType::CONTENT) {
} elseif($contentManager->displayType == EContentDisplayType::DISPLAY) {
printMainHeader(localize("content.error.heading.main.content"), "fad fa-exclamation-triangle");
} else {
printMainHeader(localize("content.error.heading.main.fallback"), "fad fa-exclamation-triangle");
@@ -166,7 +166,7 @@ include 'commons/DOM/sidebar.php';
goto content_printing_end;
}
if($contentManager->displayType == ContentDisplayType::SEARCH) {
if($contentManager->displayType == EContentDisplayType::SEARCH) {
// We are handling a content search with at least one result.
// Making the header with the amount of results.
@@ -213,7 +213,7 @@ include 'commons/DOM/sidebar.php';
}
// TODO: Print the tags used in the search and others that may be available.
} elseif($contentManager->displayType == ContentDisplayType::CONTENT) {
} elseif($contentManager->displayType == EContentDisplayType::DISPLAY) {
// Printing the content
echo($content->get_html());
}

View File

@@ -35,6 +35,12 @@
"usage.p1": "Many usage examples can be found on GitHub in the \"<a href=\"https://github.com/aziascreations/CircuitPython-Ebyte-E32/tree/master/examples\">examples/</a>\" subfolder.<br>The examples cover all modes of operations for the modules, except for the <i>wake-up</i> and <i>power-saving</i> modes.",
"usage.p2": "However, if you want to get a feel on how to use it, I invite you to read the code below taken from the \"<a href=\"https://github.com/aziascreations/CircuitPython-Ebyte-E32/blob/master/examples/transmit_fixed/sender_unicast.py\">transmit_fixed/sender_unicast.py</a>\" example that is used to send a message in fixed mode to a specific device.",
"demo.title": "<abbr title=\"In-Real-Life\">IRL</abbr>&nbsp;Tests",
"demo.p1": "Some tests were conducted using this library with an <i>E32 443T20D</i> module transmitting at <i>10 mW / 10dBm</i> and <i>2.4 kbps</i>.",
"demo.p2": "The transmitting side used a handmade ??? antenna held up ~8-10 m above ground-level, and the receiving one was a basic ??? from a Baofeng radio held up ~2-3 m above the ground with the help of a wooden stick.",
"demo.p3": "The maximum observed range was around <i>1.7km / 1.05mi</i> with a clear <abbr title=\"Line-of-Sight\">LOS</abbr>.",
"demo.p4": "It could have probably been bigger if we hadn't ran out of beers and were ready to walk >8km to the next unobstructed point.",
"downloads.title": "Downloads",
"license.title": "License",
@@ -75,6 +81,11 @@
"usage.p1": "De nombreux exemples d'utilisation peuvent être trouvés sur GitHub dans le sous-dossier \"<a href=\"https://github.com/aziascreations/CircuitPython-Ebyte-E32/tree/master/examples\">examples/</a>\" du projet.<br>Les exemples couvrent tous les modes de fonctionnement des modules, à l'exception des modes <i>wake-up</i> et <i>power-saving</i>.",
"usage.p2": "Cependant, si vous souhaitez avoir un aperçu rapide, je vous invite à lire le code ci-dessous extrait de l'exemple \"<a href=\"https://github.com/aziascreations/CircuitPython-Ebyte-E32/blob/master/examples/transmit_fixed/sender_unicast.py\">transmit_fixed/sender_unicast.py</a>\" qui est utilisé pour envoyer un message en mode fixe à un récipient spécifique.",
"demo.title": "Essais&nbsp;<abbr title=\"dans la vraie vie\">IRL</abbr> ",
"demo.p1": "Des tests ont été effectués avec cette librairie en utilisant un module <i>E32 443T20D</i> émettant à <i>10 mW / 10 dBm</i> et <i>2,4 kbps</i>.",
"demo.p3": "La portée maximale observée était d'environ <i>1,7 km / 1,05 mi</i> avec une ligne de visée dégagée (<abbr title=\"Line-of-Sight\">LOS</abbr>).",
"demo.p4": "Elle aurait probablement pu être plus grande si nous n'avions pas épuisé nos réserves de bières sur la première partie de la marche, et si nous étions prêts à marcher plus de 8 km jusqu'au prochain point dégagé.\n",
"downloads.title": "Télechargements",
"license.title": "Licence",
@@ -179,7 +190,7 @@
"parts": [
{
"type": "code", "indent": 2,
"modifiers": ["horizontal-scroll", "code-block"],
"modifiers": ["horizontal-scroll-auto", "code-block"],
"language": "python", "copyable": true,
"code": [
"import board",
@@ -217,6 +228,27 @@
]
},
{"type": "h1", "content": "demo.title"},
{"type": "paragraph", "indent": 2, "content": "demo.p1"},
{"type": "paragraph", "indent": 2, "content": "demo.p3"},
{"type": "paragraph", "indent": 2, "content": "demo.p4"},
{
"type": "container", "padding": 2,
"modifiers": ["pb-0"],
"parts": [
{
"type": "gallery",
"modifiers": [],
"images": [
"/resources/NibblePoker/images/content/circuitpython-ebyte-e32/demo-01.jpg",
"/resources/NibblePoker/images/content/circuitpython-ebyte-e32/demo-02.jpg",
"/resources/NibblePoker/images/content/circuitpython-ebyte-e32/demo-03.jpg",
"/resources/NibblePoker/images/content/circuitpython-ebyte-e32/demo-04.jpg"
]
}
]
},
{"type": "h1", "content": "downloads.title"},
{
"type": "container", "padding": 2, "modifiers": ["pb-0"],
@@ -329,7 +361,7 @@
"parts": [
{
"type": "button", "modifiers": ["thin"],
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.6.0/nibblepoker-circuitpython-e32-driver_v0.6.0_py.zip",
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.6.0/nibblepoker-circuitpython-e32-driver_0.6.0_py.zip",
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i>&nbsp;&nbsp;10.39 KiB</span><i class=\"fas fa-download ml-s\"></i>",
"localize": false
}
@@ -340,7 +372,7 @@
"parts": [
{
"type": "button", "modifiers": ["thin"],
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.6.0/nibblepoker-circuitpython-e32-driver_v0.6.0_py-min.zip",
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.6.0/nibblepoker-circuitpython-e32-driver_0.6.0_py-min.zip",
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i>&nbsp;&nbsp;4.62 KiB</span><i class=\"fas fa-download ml-s\"></i>",
"localize": false
}
@@ -351,7 +383,7 @@
"parts": [
{
"type": "button", "modifiers": ["thin"],
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.6.0/nibblepoker-circuitpython-e32-driver_v0.6.0_mpy-8.zip",
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.6.0/nibblepoker-circuitpython-e32-driver_0.6.0_mpy-8.zip",
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i>&nbsp;&nbsp;6.10 KiB</span><i class=\"fas fa-download ml-s\"></i>",
"localize": false
}
@@ -362,7 +394,7 @@
"parts": [
{
"type": "button", "modifiers": ["thin"],
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.6.0/nibblepoker-circuitpython-e32-driver_v0.6.0_mpy-8-min.zip",
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.6.0/nibblepoker-circuitpython-e32-driver_0.6.0_mpy-8-min.zip",
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i>&nbsp;&nbsp;5.83 KiB</span><i class=\"fas fa-download ml-s\"></i>",
"localize": false
}
@@ -375,7 +407,7 @@
"parts": [
{
"type": "button", "modifiers": ["thin"],
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.4.0/nibblepoker-circuitpython-e32-driver_v0.4.0_py.zip",
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.4.0/nibblepoker-circuitpython-e32-driver_0.4.0_py.zip",
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i>&nbsp;&nbsp;19.96 KiB</span><i class=\"fas fa-download ml-s\"></i>",
"localize": false
}
@@ -386,7 +418,7 @@
"parts": [
{
"type": "button", "modifiers": ["thin"],
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.4.0/nibblepoker-circuitpython-e32-driver_v0.4.0_py-min.zip",
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.4.0/nibblepoker-circuitpython-e32-driver_0.4.0_py-min.zip",
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i>&nbsp;&nbsp;4.18 KiB</span><i class=\"fas fa-download ml-s\"></i>",
"localize": false
}
@@ -397,7 +429,7 @@
"parts": [
{
"type": "button", "modifiers": ["thin"],
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.4.0/nibblepoker-circuitpython-e32-driver_v0.4.0_mpy-8.zip",
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.4.0/nibblepoker-circuitpython-e32-driver_0.4.0_mpy-8.zip",
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i>&nbsp;&nbsp;5.27 KiB</span><i class=\"fas fa-download ml-s\"></i>",
"localize": false
}
@@ -408,7 +440,7 @@
"parts": [
{
"type": "button", "modifiers": ["thin"],
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.4.0/nibblepoker-circuitpython-e32-driver_v0.4.0_mpy-8-min.zip",
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.4.0/nibblepoker-circuitpython-e32-driver_0.4.0_mpy-8-min.zip",
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i>&nbsp;&nbsp;5.04 KiB</span><i class=\"fas fa-download ml-s\"></i>",
"localize": false
}

View File

@@ -81,7 +81,7 @@
"parts": [
{
"type": "code", "indent": 2,
"modifiers": ["horizontal-scroll", "code-block"],
"modifiers": ["horizontal-scroll-auto", "code-block"],
"language": "csharp", "copyable": true,
"code": [
"// Preparing options and root verb.",

84
content_item_converter.py Normal file
View File

@@ -0,0 +1,84 @@
#!/bin/python
import argparse
import json
import os
import sys
# Importing YAML parser safely
try:
import yaml
except ImportError:
print("You need to install the 'PyYAML' module to continue !")
sys.exit(10)
# Including nicer-looking print function if possible.
try:
from rich import print
except ImportError:
pass
# Preparing and parsing launch arguments
parser = argparse.ArgumentParser()
parser.add_argument("input", help="Input folder where the strings are located.")
parser.add_argument("output", help="Output folder where the converted files will be saved.")
# Fixing some issues with "argparse"
def argparse_error(message):
raise argparse.ArgumentError(None, message)
# Parsing launch options
parser.error = argparse_error
try:
args = parser.parse_args()
except argparse.ArgumentError as err:
print(f"\033[31m\033[1mError:\033[0m\033[31m {err.message.capitalize()}\033[39m")
print("\033[36m\033[1mUsage:\033[0m\033[36m content_index_maker.py <input_folder> <output_file>\033[39m")
sys.exit(1)
# Checking the given options are valid
if not (os.path.exists(args.input) and os.path.isdir(args.input)):
print(f"\033[31m\033[1mError:\033[0m\033[31m The given input directory '{args.input}' doesn't exist or is a file !\033[39m")
sys.exit(2)
if not (os.path.exists(args.output) and os.path.isdir(args.output)):
print(f"\033[31m\033[1mError:\033[0m\033[31m The given output '{args.output}' is a directory !\033[39m")
sys.exit(3)
# Starting the process
print(f"Compiling '{args.input}' to '{args.output}'...")
input_folder = os.path.abspath(args.input)
output_folder = os.path.abspath(args.output)
for item_filename in os.listdir(input_folder):
if item_filename.startswith("_") or not (item_filename.endswith(".yml") or item_filename.endswith(".yaml")):
continue
print("> Processing '{}'".format(item_filename))
with open(os.path.join(input_folder, item_filename), 'r') as f:
item_raw_data = yaml.safe_load(f)
# Grabbing the output ID
output_id = list(item_raw_data.keys())[0]
# Un-nesting the data
item_raw_data = item_raw_data[output_id]
# Converting content
def process_content(content_element) -> dict:
if type(content_element) is dict:
pass
return content_element
output_content = list()
for content_item in item_raw_data["content"]:
content_item = process_content(content_item)
output_content.append(content_item)
item_raw_data["content"] = output_content
print(item_raw_data)

View File

@@ -3,6 +3,9 @@ $start_time = microtime(true);
set_include_path('../');
include_once 'commons/config.php';
include_once 'commons/langs.php';
// Enable debugging extras
$enable_debug_extras = true;
?>
<!DOCTYPE html>
<html lang="<?php echo($user_language); ?>">
@@ -145,12 +148,12 @@ include 'commons/DOM/sidebar.php';
</tr>
<tr>
<td><?php echo(localize("content.commons.cpu")); ?> (JS)</td>
<td><kbd><?php echo("TODO"); ?></kbd></td>
<td><kbd class="data-cpu-arch"><?php echo("TODO"); ?></kbd></td>
</tr>
<tr>
<td><?php echo(localize("common.user-agent")); ?></td>
<td><?php
if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
if(isset($_SERVER['HTTP_USER_AGENT'])) {
echo('<kbd>' . htmlspecialchars($_SERVER['HTTP_USER_AGENT']) . '</kbd>');
} else {
echo('<i>' . localize("common.undefined") . '</i>');

View File

@@ -54,7 +54,7 @@ include 'commons/DOM/sidebar.php';
</p>
<p class="mt-s ml-s t-w-600 t-size-12">
<i class="fab fa-linkedin mr-xs"></i><a href="https://twitter.com/NibblePoker"><?php print(localize("links.linkedin.title")); ?></a>
<i class="fab fa-linkedin mr-xs"></i><a href="https://www.linkedin.com/in/herwin-bozet/"><?php print(localize("links.linkedin.title")); ?></a>
</p>
<p class="mt-xxs ml-l">
<?php print(localize("links.linkedin.text.1")); ?>

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 48 48"><path fill="#00549d" fill-rule="evenodd" d="M22.903,3.286c0.679-0.381,1.515-0.381,2.193,0 c3.355,1.883,13.451,7.551,16.807,9.434C42.582,13.1,43,13.804,43,14.566c0,3.766,0,15.101,0,18.867 c0,0.762-0.418,1.466-1.097,1.847c-3.355,1.883-13.451,7.551-16.807,9.434c-0.679,0.381-1.515,0.381-2.193,0 c-3.355-1.883-13.451-7.551-16.807-9.434C5.418,34.899,5,34.196,5,33.434c0-3.766,0-15.101,0-18.867 c0-0.762,0.418-1.466,1.097-1.847C9.451,10.837,19.549,5.169,22.903,3.286z" clip-rule="evenodd"/><path fill="#0086d4" fill-rule="evenodd" d="M5.304,34.404C5.038,34.048,5,33.71,5,33.255 c0-3.744,0-15.014,0-18.759c0-0.758,0.417-1.458,1.094-1.836c3.343-1.872,13.405-7.507,16.748-9.38 c0.677-0.379,1.594-0.371,2.271,0.008c3.343,1.872,13.371,7.459,16.714,9.331c0.27,0.152,0.476,0.335,0.66,0.576L5.304,34.404z" clip-rule="evenodd"/><path fill="#fff" fill-rule="evenodd" d="M24,10c7.727,0,14,6.273,14,14s-6.273,14-14,14 s-14-6.273-14-14S16.273,10,24,10z M24,17c3.863,0,7,3.136,7,7c0,3.863-3.137,7-7,7s-7-3.137-7-7C17,20.136,20.136,17,24,17z" clip-rule="evenodd"/><path fill="#0075c0" fill-rule="evenodd" d="M42.485,13.205c0.516,0.483,0.506,1.211,0.506,1.784 c0,3.795-0.032,14.589,0.009,18.384c0.004,0.396-0.127,0.813-0.323,1.127L23.593,24L42.485,13.205z" clip-rule="evenodd"/><path fill="#fff" fill-rule="evenodd" d="M31 21H33V27H31zM38 21H40V27H38z" clip-rule="evenodd"/><path fill="#fff" fill-rule="evenodd" d="M29 23H35V25H29zM36 23H42V25H36z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 48 48"><path fill="#283593" fill-rule="evenodd" d="M22.903,3.286c0.679-0.381,1.515-0.381,2.193,0 c3.355,1.883,13.451,7.551,16.807,9.434C42.582,13.1,43,13.804,43,14.566c0,3.766,0,15.101,0,18.867 c0,0.762-0.418,1.466-1.097,1.847c-3.355,1.883-13.451,7.551-16.807,9.434c-0.679,0.381-1.515,0.381-2.193,0 c-3.355-1.883-13.451-7.551-16.807-9.434C5.418,34.899,5,34.196,5,33.434c0-3.766,0-15.101,0-18.867 c0-0.762,0.418-1.466,1.097-1.847C9.451,10.837,19.549,5.169,22.903,3.286z" clip-rule="evenodd"/><path fill="#5c6bc0" fill-rule="evenodd" d="M5.304,34.404C5.038,34.048,5,33.71,5,33.255 c0-3.744,0-15.014,0-18.759c0-0.758,0.417-1.458,1.094-1.836c3.343-1.872,13.405-7.507,16.748-9.38 c0.677-0.379,1.594-0.371,2.271,0.008c3.343,1.872,13.371,7.459,16.714,9.331c0.27,0.152,0.476,0.335,0.66,0.576L5.304,34.404z" clip-rule="evenodd"/><path fill="#fff" fill-rule="evenodd" d="M24,10c7.727,0,14,6.273,14,14s-6.273,14-14,14 s-14-6.273-14-14S16.273,10,24,10z M24,17c3.863,0,7,3.136,7,7c0,3.863-3.137,7-7,7s-7-3.137-7-7C17,20.136,20.136,17,24,17z" clip-rule="evenodd"/><path fill="#3949ab" fill-rule="evenodd" d="M42.485,13.205c0.516,0.483,0.506,1.211,0.506,1.784 c0,3.795-0.032,14.589,0.009,18.384c0.004,0.396-0.127,0.813-0.323,1.127L23.593,24L42.485,13.205z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 48 48"><path fill="#37474f" fill-rule="evenodd" d="M22.903,3.286c0.679-0.381,1.515-0.381,2.193,0 c3.355,1.883,13.451,7.551,16.807,9.434C42.582,13.1,43,13.804,43,14.566c0,3.766,0,15.101,0,18.867 c0,0.762-0.418,1.466-1.097,1.847c-3.355,1.883-13.451,7.551-16.807,9.434c-0.679,0.381-1.515,0.381-2.193,0 c-3.355-1.883-13.451-7.551-16.807-9.434C5.418,34.899,5,34.196,5,33.434c0-3.766,0-15.101,0-18.867 c0-0.762,0.418-1.466,1.097-1.847C9.451,10.837,19.549,5.169,22.903,3.286z" clip-rule="evenodd"/><path fill="#546e7a" fill-rule="evenodd" d="M5.304,34.404C5.038,34.048,5,33.71,5,33.255 c0-3.744,0-15.014,0-18.759c0-0.758,0.417-1.458,1.094-1.836c3.343-1.872,13.405-7.507,16.748-9.38 c0.677-0.379,1.594-0.371,2.271,0.008c3.343,1.872,13.371,7.459,16.714,9.331c0.27,0.152,0.476,0.335,0.66,0.576L5.304,34.404z" clip-rule="evenodd"/><path fill="#fff" fill-rule="evenodd" d="M24,10c7.727,0,14,6.273,14,14s-6.273,14-14,14 s-14-6.273-14-14S16.273,10,24,10z M24,17c3.863,0,7,3.136,7,7c0,3.863-3.137,7-7,7s-7-3.137-7-7C17,20.136,20.136,17,24,17z" clip-rule="evenodd"/><path fill="#455a64" fill-rule="evenodd" d="M42.485,13.205c0.516,0.483,0.506,1.211,0.506,1.784 c0,3.795-0.032,14.589,0.009,18.384c0.004,0.396-0.127,0.813-0.323,1.127L23.593,24L42.485,13.205z" clip-rule="evenodd"/><path fill="#fff" fill-rule="evenodd" d="M34 20H35V28H34zM37 20H38V28H37z" clip-rule="evenodd"/><path fill="#fff" fill-rule="evenodd" d="M32 25H40V26H32zM32 22H40V23H32z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -0,0 +1,27 @@
const idButtonBorder = "test-toggle-borders";
const classBorderActive = "debug";
const classBorderInactive = "_debug";
function swapDebugClasses() {
const activeElements = document.querySelectorAll('.' + classBorderActive);
const inactiveElements = document.querySelectorAll('.' + classBorderInactive);
activeElements.forEach(element => {
element.classList.remove(classBorderActive);
element.classList.add(classBorderInactive);
});
inactiveElements.forEach(element => {
element.classList.remove(classBorderInactive);
element.classList.add(classBorderActive);
});
}
document.addEventListener("DOMContentLoaded", function() {
// Adding the action to the border button
const eBorderButton = document.getElementById(idButtonBorder);
if(eBorderButton !== null) {
eBorderButton.addEventListener("click", swapDebugClasses);
}
});

View File

@@ -111,4 +111,11 @@ document.addEventListener("DOMContentLoaded", () => {
//})
// TODO: Autodetect mobile screens, close it, and add classes to make it over the rest with dark modal bkgd.
// Printing the detected CPU architecture
const detectedCpuArch= getCpuArchitecture();
let cpuArchPrintouts = document.querySelectorAll(".data-cpu-arch");
cpuArchPrintouts.forEach(element => {
element.textContent = detectedCpuArch.name;
});
});

View File

@@ -0,0 +1,15 @@
.debug {
border: 1px dotted deeppink !important;
& *.debug {
border: 1px dotted yellow !important;
& *.debug {
border: 1px dotted cyan !important;
& *.debug {
border: 1px dotted lime !important;
& *.debug {
border: 1px dotted red !important;
}
}
}
}
}

View File

@@ -19,3 +19,19 @@
.content-error-text {
max-width: 700px;
}
// Image shown in the smaller inline content cards
.content-card-image {
width: calc(#{$content-search-image-size} * 0.75);
height: calc(#{$content-search-image-size} * 0.75);
float: left;
//filter: drop-shadow(0 0 0.2rem #000000CF);
//box-shadow: 0px 0px 20px 2px #000000CF inset;
}
// Should be a span with IMG tags inside it.
.app-card-icons {
&>img {
height: 1.25rem;
}
}

View File

@@ -19,6 +19,7 @@
.overflow-x-auto {
overflow-x: auto;
}
.overflow-x-scroll {
overflow-x: scroll;
}
@@ -29,22 +30,27 @@
height: #{$scrollbar-size};
background-color: transparent;
}
*::-webkit-scrollbar-track:vertical {
border-left: 1px solid #{$color-scrollbar-border};
}
/**::-webkit-scrollbar-track:horizontal {
border-top: 1px solid #{$color-scrollbar-border};
}*/
*::-webkit-scrollbar-thumb {
background-color: rgba(255, 255, 255, 0.25);
border: 0.4rem solid transparent;
background-clip: content-box;
border-radius: 1em;
}
*::-webkit-scrollbar-thumb:hover {
background-color: rgba(255, 255, 255, 0.4);
border-color: transparent;
}
*::-webkit-scrollbar-corner {
background-color: transparent;
border-left: 1px solid rgba(0, 0, 0, 0.1);

View File

@@ -4,8 +4,8 @@
.wedge {
position: absolute;
top: 0;
right: 0;
//top: 0;
//right: 0;
color: #{$color-text-regular-normal};
background-color: #{$color-background-button};
@@ -20,7 +20,7 @@
//transition: color 0.25s ease;
//transition-timing-function: cubic-bezier(.47,1.64,.41,.8);
&:hover {
&:hover:not(.no-hover) {
background-color: #{$color-background-button-hover};
}
@@ -30,28 +30,28 @@
&.primary {
background-color: #{$color-background-button-primary};
&:hover {
&:hover:not(.no-hover) {
background-color: #{$color-background-button-primary-hover};
}
}
&.success {
background-color: #{$color-background-button-success};
&:hover {
&:hover:not(.no-hover) {
background-color: #{$color-background-button-success-hover};
}
}
&.error {
background-color: #{$color-background-button-error};
&:hover {
&:hover:not(.no-hover) {
background-color: #{$color-background-button-error-hover};
}
}
&.warning {
background-color: #{$color-background-button-warning};
&:hover {
&:hover:not(.no-hover) {
background-color: #{$color-background-button-warning-hover};
}
}

110
test/index.php Normal file
View File

@@ -0,0 +1,110 @@
<?php
$start_time = microtime(true);
set_include_path('../');
include_once 'commons/config.php';
include_once 'commons/langs.php';
// Enable debugging extras
$enable_debug_extras = true;
?>
<!DOCTYPE html>
<html lang="<?php echo($user_language); ?>">
<head>
<?php include 'commons/DOM/head.php'; ?>
<title><?php print(localize('contact.head.title')); ?></title>
<meta name="description" content="<?php print(localize('contact.head.description')); ?>">
<meta property="og:title" content="<?php print(localize('contact.og.title')); ?>"/>
<meta property="og:type" content="website"/>
<meta property="og:url" content="<?php echo($host_uri . l10n_url_abs('/')); ?>"/>
<meta property="og:image" content="<?php echo($host_uri); ?>/resources/NibblePoker/images/logos/v2_opengraph.png"/>
<meta property="og:image:type" content="image/png"/>
<meta property="og:description" content="<?php print(localize('contact.og.description')); ?>"/>
</head>
<body>
<?php
include_once 'commons/DOM/utils.php';
$SIDEBAR_IDS = ['test'];
include 'commons/DOM/sidebar.php';
?>
<header class="w-full p-m pl-s">
<h1 class="t-size-17 t-w-500">
<i class="fa-duotone fa-vial-virus t-size-16 mr-s t-muted"></i><?php print(localize("test.header.title")); ?>
</h1>
<?php include 'commons/DOM/header-lang.php'; ?>
</header>
<main id="main" class="rl-m border border-r-0 p-l">
<?php printMainHeader(localize("test.controls"), "fa-duotone fa-vial-virus", ""); ?>
<div class="mt-xs mx-s gap-s">
<button id="test-toggle-borders" class="p-xs border r-s t-size-10">
<?php echo(localize("test.controls.borders")); ?>
</button>
</div>
<?php printMainHeader(localize("test.app.card.demo"), "fa-duotone fa-vial-virus", ".grid.col-2.col-medium-1"); ?>
<div class="grid col-2 col-medium-1 mt-xs mx-s gap-s debug">
<a class="casper-link" href="#disabled-link">
<div class="bkgd-blank-dark border r-l h-full debug p-relative">
<div class="p-xxs">
<img class="content-card-image border mr-xs mb-xxs r-l debug" src="/resources/NibblePoker/images/content/lscom/lscom-v2-text-01-bkgd-cli.png">
</div>
<h3 class="mb-xs debug">
DotNet-ListComPort
</h3>
<p class="debug">
CLI tool that can list COM ports with their name, friendly name and device name easily and cleanly.
</p>
<!--
<img src="/resources/ExtGraphics/Icons8/Color/Logos/windows_10.svg" alt="Windows" title="Windows 10+">
<img src="/resources/ExtGraphics/DevIcons/csharp-original.svg" alt="C#" title="C#">
<img src="/resources/ExtGraphics/Icons8/Color/Logos/git.svg" alt="Git" title="Git">
-->
<!--<div class="wedge wedge-br success js-code-copy border rtl-m rbr-m p-xxxs px-xs border-b-0 border-r-0 debug">
<i class="fad fa-download"></i>
</div>-->
<div class="wedge no-hover wedge-tr js-code-copy border rbl-m rtr-m px-xs border-t-0 border-r-0 debug">
<img src="/resources/ExtGraphics/Icons8/Color/Logos/windows_10.svg" alt="Windows" title="Windows 10+" class="app-card-detail-icon">
<img src="/resources/ExtGraphics/DevIcons/csharp-original.svg" alt="C#" title="C#" class="app-card-detail-icon">
<img src="/resources/ExtGraphics/Icons8/Color/Logos/git.svg" alt="Git" title="Git" class="app-card-detail-icon">
</div>
</div>
</a>
<div class="debug">b</div>
</div>
<?php printMainHeader(localize("test.content.card.demo"), "fa-duotone fa-vial-virus", ".grid.col-1"); ?>
<div class="p-s debug">
<a class="casper-link" href="#disabled-link">
<div class="content-search-entry debug">
<img class="content-search-image mr-s r-l debug" src="/resources/NibblePoker/images/content/lscom/lscom-v2-text-01-bkgd-cli.png">
<h3 class="mb-xs debug">DotNet-ListComPort</h3>
<p class="debug">
A simple CLI tool that can list COM ports with their name, friendly name and device name easily and cleanly.<br>
This tool is intended to replace the tedious task of having to use the <code>mode</code> command, and the <i>Device Manager</i> to find a newly plugged-in device that provides a COM port.
</p>
</div>
</a>
<p class="mt-xs debug">
<i class="fad fa-tags t-size-8 debug"></i>
<a href="#disabled-link" class="ml-xs debug">#application</a>
<a href="#disabled-link" class="ml-xs debug">#tool</a>
<a href="#disabled-link" class="ml-xs debug">#lscom</a>
<a href="#disabled-link" class="ml-xs debug">#dotnet</a>
<a href="#disabled-link" class="ml-xs debug">#windows</a>
</p>
</div>
</main>
<?php
include 'commons/DOM/footer.php';
include 'commons/DOM/scripts.php';
?>
</body>
</html>
<?php
$end_time = microtime(true);
if($print_execution_timer) {
echo("<!-- PHP execution took " . round(($end_time - $start_time) * 1000, 2) . " ms -->");
}
?>

View File

@@ -1,44 +1 @@
[
{
"id": "svg-to-png",
"title": {
"en": "SVG to PNG Converter",
"fr": "Convertisseur SVG vers PNG"
},
"preamble": {
"en": "TODO: Description",
"fr": "TODO: Description"
},
"_image": "",
"tags": ["converter", "svg", "png"],
"priority": 100
},
{
"id": "formula-wizard",
"title": {
"en": "Formula Wizard",
"fr": "Ensorceleur de formules"
},
"preamble": {
"en": "TODO: Description",
"fr": "TODO: Description"
},
"image": "/resources/NibblePoker/images/content/formula-wizard/v1.png",
"tags": ["converter"],
"priority": 200
},
{
"id": "b64-tools",
"title": {
"en": "Base64 Tools",
"fr": "Outils pour Base64"
},
"preamble": {
"en": "TODO: Description",
"fr": "TODO: Description"
},
"_image": "",
"tags": ["converter"],
"priority": 210
}
]
[{"title":{"en":"Formula Wizard","fr":"Ensorceleur de formules"},"preamble":{"en":"TODO: Description","fr":"TODO: Description"},"image":"/resources/NibblePoker/images/content/formula-wizard/v1.png","tags":["tool","converter"],"priority":1,"id":"formula-wizard"},{"title":{"en":"PNGs to ICO Converter","fr":"Convertisseur de PNGs vers ICO"},"preamble":{"en":"TODO: Description","fr":"TODO: Description"},"image":"/resources/NibblePoker/images/content/lscom/lscom-v2-text-01-bkgd-cli.png","tags":["tool","converter","icon","png"],"priority":100,"id":"png-ico-maker"}]

View File

@@ -6,12 +6,16 @@ set_include_path('../');
include_once 'commons/config.php';
include_once 'commons/langs.php';
// Preparing the content
include_once 'commons/content.php';
include_once 'commons/content/tools.php';
// Preparing the content manager to get the page's context.
include_once 'commons/content/manager.php';
$contentManager = getContentManager($config_dir_tools);
$toolInfo = NULL;
if(!$contentManager->hasError && $contentManager->displayType == ContentDisplayType::CONTENT) {
// Attempting to load the tool's data if relevant.
// If loaded, we can assume the standardized index wasn't loaded by "$contentManager".
include_once 'commons/content/tools.php';
$toolInfo = null;
if(!$contentManager->hasError && $contentManager->displayType == EContentDisplayType::DISPLAY) {
// Loading the definition and checking paths referenced in it.
$toolInfo = ToolsContent::loadItemIndexFile($contentManager, $config_dir_tools);
if(!is_null($toolInfo)) {
$toolInfo->validateFiles($contentManager);
@@ -33,11 +37,10 @@ if(!$contentManager->hasError && $contentManager->displayType == ContentDisplayT
}
$content_error_message = localize($contentManager->errorMessageKey);
// Checking if an error occurred while loading data and parsing the URL.
// And if not, enabling special features.
// Checking if an error occurred while loading data and/or parsing the URL.
$content_error_code = 200;
if($contentManager->hasError) {
// TODO: Add condition for the lack of data for an item.
// TODO: Add condition for the lack of data for an item. - What ?
if(is_null($contentManager->rootIndexEntries)) {
// Failed to get a display type or to extract types.
header("HTTP/1.1 400 Bad Request");
@@ -47,9 +50,6 @@ if($contentManager->hasError) {
header("HTTP/1.1 500 Internal Server Error");
$content_error_code = 500;
}
} else {
$enable_code_highlight = false;
$enable_gallery = true;
}
?>
<!DOCTYPE html>
@@ -59,7 +59,7 @@ if($contentManager->hasError) {
include 'commons/DOM/head.php';
// Preparing values for the head's tags.
if($contentManager->displayType == ContentDisplayType::SEARCH) {
if($contentManager->displayType == EContentDisplayType::SEARCH) {
$tool_head_title = localize('tools.head.description');
$tool_head_description = localize('tools.head.description');
$tool_head_og_title = localize('tools.og.title');
@@ -67,14 +67,22 @@ if($contentManager->hasError) {
$tool_head_og_image_url = $host_uri . "/resources/NibblePoker/images/logos/v2_opengraph.png";
$tool_head_og_image_type = "image/png";
$tool_head_og_type = "website";
} elseif($contentManager->displayType == ContentDisplayType::CONTENT) {
$tool_head_title = $toolInfo->openGraphData->title;
$tool_head_description = $toolInfo->openGraphData->description;
$tool_head_og_title = $toolInfo->openGraphData->title;
$tool_head_og_description = $toolInfo->openGraphData->description;
$tool_head_og_image_url = $host_uri . $toolInfo->openGraphData->image;
$tool_head_og_image_type = $toolInfo->openGraphData->image_type;
$tool_head_og_type = $toolInfo->openGraphData->type;
} elseif($contentManager->displayType == EContentDisplayType::DISPLAY) {
$tool_head_title = "???";
$tool_head_description = "???";
$tool_head_og_title = "???";
$tool_head_og_description = "???";
$tool_head_og_image_url = "???";
$tool_head_og_image_type = "???";
$tool_head_og_type = "???";
//$tool_head_title = $toolInfo->openGraphData->title;
//$tool_head_description = $toolInfo->openGraphData->description;
//$tool_head_og_title = $toolInfo->openGraphData->title;
//$tool_head_og_description = $toolInfo->openGraphData->description;
//$tool_head_og_image_url = $host_uri . $toolInfo->openGraphData->image;
//$tool_head_og_image_type = $toolInfo->openGraphData->image_type;
//$tool_head_og_type = $toolInfo->openGraphData->type;
}
?>
@@ -87,7 +95,7 @@ if($contentManager->hasError) {
<meta property="og:image:type" content="<?php echo($tool_head_og_image_type); ?>"/>
<meta property="og:description" content="<?php echo($tool_head_og_description); ?>"/>
<?php
if(!$contentManager->hasError && $contentManager->displayType == ContentDisplayType::CONTENT) {
if(!$contentManager->hasError && $contentManager->displayType == EContentDisplayType::DISPLAY) {
foreach($toolInfo->styleFilesPaths as $styleFilePath) {
echo('<link rel="stylesheet" href="'.substr($styleFilePath, strlen($dir_root)).'">');
}
@@ -110,9 +118,9 @@ include 'commons/DOM/sidebar.php';
<?php
// Checking if an error occurred.
if($content_error_code != 200) {
if($contentManager->displayType == ContentDisplayType::SEARCH) {
if($contentManager->displayType == EContentDisplayType::SEARCH) {
printMainHeader(localize("content.error.heading.main.search"), "fad fa-exclamation-triangle");
} elseif($contentManager->displayType == ContentDisplayType::CONTENT) {
} elseif($contentManager->displayType == EContentDisplayType::DISPLAY) {
printMainHeader(localize("content.error.heading.main.content"), "fad fa-exclamation-triangle");
} else {
printMainHeader(localize("content.error.heading.main.fallback"), "fad fa-exclamation-triangle");
@@ -123,7 +131,7 @@ include 'commons/DOM/sidebar.php';
goto content_printing_end;
}
if($contentManager->displayType == ContentDisplayType::SEARCH) {
if($contentManager->displayType == EContentDisplayType::SEARCH) {
// We are handling a content search with at least one result.
// Making the header with the amount of results.
@@ -169,7 +177,7 @@ include 'commons/DOM/sidebar.php';
}
// TODO: Print the tags used in the search and others that may be available.
} elseif($contentManager->displayType == ContentDisplayType::CONTENT) {
} elseif($contentManager->displayType == EContentDisplayType::DISPLAY) {
// Printing the main heading (Lifted from composer.php in the templates section)
echo(getMainHeader(
localize($toolInfo->titleKey),
@@ -198,7 +206,7 @@ include 'commons/DOM/footer.php';
include 'commons/DOM/scripts.php';
// Including the tool's scripts if required.
if(!$contentManager->hasError && $contentManager->displayType == ContentDisplayType::CONTENT) {
if(!$contentManager->hasError && $contentManager->displayType == EContentDisplayType::DISPLAY) {
foreach($toolInfo->codeFilesPaths as $codeFilePath) {
echo('<script src="'.substr($codeFilePath, strlen($dir_root)).'"></script>');
}