Removed old PHP code, migrated to Python and Flask
Update .dockerignore, .env, and 503 more files...
This commit is contained in:
13
.dockerignore
Normal file
13
.dockerignore
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# IDEs
|
||||||
|
.vs/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
|
__pycache__/
|
||||||
|
|
||||||
|
# Development utilities
|
||||||
|
scripts/
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
docker-compose.yml
|
||||||
|
Dockerfile
|
13
.env
13
.env
@@ -1,9 +1,4 @@
|
|||||||
➖➖➖🟩🟩➖🟩🟩
|
DB_HOST="bWFpbi5kYi5uaWJibGVwb2tlci5sdQ=="
|
||||||
➖➖🟩🟩🟩🟩🟩🟩🟩
|
DB_DATABASE="c2l0ZS1yb290"
|
||||||
➖🟩🟩⬜⬛⬜⬜⬛🟩 🌫
|
DB_USER="cm9vdA=="
|
||||||
➖🟩🟩🟩🟩🟩🟩🟩 🌪️
|
DB_PASSWORD="SSBzd2VhciB0byBnb2QsIGlmIHlvdSBkYXJlIHNlbmQgbWUgb25lIG1vcmUgZnVja2luZyBlbWFpbCBhYm91dCB5b3VyIHNoaXQtdGllciBpbmZvcm1hdGlvbiBsZWFrIGRldGVjdGlvbiBzZXJ2aWNlcyBJIHdpbGwgcmFpbiBoZWxsIG9uIHlvdSBhbmQgeW91ciBjb21wYW55Lg0KWW91IHdvdWxkbid0IGJlIHRoZSBmaXJzdCBhbmQgeW91IHN1cmUgYXMgc2hpdCB3b24ndCBiZSB0aGUgbGFzdCAh"
|
||||||
🟩🟩🟩🟩🟫🟫🟫🟧⬜⬜⬜⬜⬛
|
|
||||||
🟩🟩🟩🟩🟩🟩🟩
|
|
||||||
🟦🟦🟦🟦🟦🟦🟦
|
|
||||||
|
|
||||||
🅑🅡🅤🅗 🅜🅞🅜🅔🅝🅣
|
|
||||||
|
51
.gitignore
vendored
51
.gitignore
vendored
@@ -1,50 +1,13 @@
|
|||||||
# IDE-related folders
|
# IDEs
|
||||||
|
.vs/
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
# Node.JS
|
|
||||||
node_modules/
|
|
||||||
package-lock.json
|
|
||||||
scripts/node_modules/
|
|
||||||
scripts/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
|
|
||||||
commons/strings.json
|
|
||||||
content/index.json
|
|
||||||
resources/NibblePoker/css/*.css
|
|
||||||
tools/items/formula-wizard/*.js
|
|
||||||
tools/items/formula-wizard/src/*.js
|
|
||||||
|
|
||||||
# Build artifacts
|
# Build artifacts
|
||||||
build*.7z
|
__pycache__/
|
||||||
|
|
||||||
# ???
|
# NodeJS' BS
|
||||||
# Source: https://github.com/sjmulder/nbt-js
|
node_modules/
|
||||||
tools/items/mc-art-viewer/nbt.js
|
|
||||||
|
|
||||||
# Others
|
# Internal stuff
|
||||||
*.pdn
|
*.pdn
|
||||||
*.min.json
|
*.ai
|
||||||
*.lnk
|
|
||||||
*.map
|
|
||||||
*.bak
|
|
||||||
*.exe
|
|
||||||
*.url
|
|
||||||
*.sqlite
|
|
||||||
*.conf
|
|
||||||
*.pyc
|
|
||||||
|
|
||||||
# Temporary
|
|
||||||
articles/*.txt
|
|
||||||
meow*.ogg
|
|
||||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,6 +0,0 @@
|
|||||||
[submodule "resources/SplideJs"]
|
|
||||||
path = resources/SplideJs
|
|
||||||
url = https://github.com/Splidejs/splide.git
|
|
||||||
[submodule "resources/HighlightJS"]
|
|
||||||
path = resources/HighlightJS
|
|
||||||
url = https://github.com/highlightjs/highlight.js.git
|
|
123
.htaccess
123
.htaccess
@@ -1,123 +0,0 @@
|
|||||||
# Preventing access to .htaccess
|
|
||||||
<Files ~ "^.*\.([Hh][Tt][Aa]|[Pp][Yy])">
|
|
||||||
Require all denied
|
|
||||||
</Files>
|
|
||||||
|
|
||||||
# Preventing access to wrongly copied .conf files
|
|
||||||
<Files ~ "^.*\.conf">
|
|
||||||
Require all denied
|
|
||||||
</Files>
|
|
||||||
|
|
||||||
|
|
||||||
# Redirecting HTTP traffic to HTTPS. (Keep commented on localhost !)
|
|
||||||
# This is handled by reverse-proxies, but it should still be enabled in production just to be safe.
|
|
||||||
#RewriteEngine On
|
|
||||||
#RewriteCond %{SERVER_PORT} 80
|
|
||||||
#RewriteRule ^(.*)$ https://nibblepoker.lu/$1 [R,L]
|
|
||||||
|
|
||||||
|
|
||||||
# Fixing some encoding issues on non-HTML files.
|
|
||||||
# Mostly affects the old privacy policies written in french. (Accents have issues in non-utf8 encodings !)
|
|
||||||
AddCharset utf-8 .css .txt .js .md .ts .mjs
|
|
||||||
#<Files ~ "\.txt?$">
|
|
||||||
# Header set Content-Type "text/plain; charset=utf-8"
|
|
||||||
#</Files>
|
|
||||||
#AddDefaultCharset utf-8
|
|
||||||
|
|
||||||
|
|
||||||
# Adding MIME types
|
|
||||||
AddType text/typescript .ts
|
|
||||||
AddType text/javascript .js
|
|
||||||
AddType text/javascript .mjs
|
|
||||||
AddType application/wasm .wasm
|
|
||||||
AddType video/x-matroska .mkv
|
|
||||||
AddType text/css .css
|
|
||||||
|
|
||||||
# Special case for Plik
|
|
||||||
<Files ~ "\.css?$">
|
|
||||||
Header set Content-Type "text/css; charset=utf-8"
|
|
||||||
</Files>
|
|
||||||
|
|
||||||
|
|
||||||
# Correcting some default options for security and language/content redirection.
|
|
||||||
# FollowSymlinks is also on since it's required for "mod_rewrite" and the server is jailed/containerized.
|
|
||||||
Options -Indexes +FollowSymlinks -ExecCGI
|
|
||||||
|
|
||||||
# Does nothing, thanks Apache...
|
|
||||||
ServerSignature Off
|
|
||||||
|
|
||||||
|
|
||||||
# Serving minified pages and/or pre-rendered ones first if available.
|
|
||||||
DirectoryIndex index.min.html index.min.php index.php index.html
|
|
||||||
|
|
||||||
|
|
||||||
# Custom error pages.
|
|
||||||
ErrorDocument 403 /error.php
|
|
||||||
ErrorDocument 404 /error.php
|
|
||||||
|
|
||||||
|
|
||||||
# Setting up browser's caching rules.
|
|
||||||
# See:
|
|
||||||
# * https://stackoverflow.com/a/13029007
|
|
||||||
# * 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"
|
|
||||||
|
|
||||||
# Static files: 1 Week
|
|
||||||
<FilesMatch "\.(?i:gif|jpe?g|png|ico|svg|woff2|ttf|woff|otf)$">
|
|
||||||
Header set Cache-Control "max-age=604800, public, must-revalidate"
|
|
||||||
</FilesMatch>
|
|
||||||
|
|
||||||
# Semi-static files: 1 Day
|
|
||||||
<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"
|
|
||||||
#Header set Expires 0
|
|
||||||
|
|
||||||
|
|
||||||
# Setting up GZIP.
|
|
||||||
# It's optional since reverse-proxies or caching layers will usually do it for us.
|
|
||||||
<ifModule mod_gzip.c>
|
|
||||||
mod_gzip_on Yes
|
|
||||||
mod_gzip_dechunk Yes
|
|
||||||
mod_gzip_item_include file \.(html?|txt|css|js|mjs|php|pl)$
|
|
||||||
mod_gzip_item_include handler ^cgi-script$
|
|
||||||
mod_gzip_item_include mime ^text/.*
|
|
||||||
mod_gzip_item_include mime ^application/x-javascript.*
|
|
||||||
mod_gzip_item_exclude mime ^image/.*
|
|
||||||
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
|
|
||||||
</ifModule>
|
|
||||||
|
|
||||||
|
|
||||||
# Setting some headers for security.
|
|
||||||
# Will cause "fail-safe crashes" if the "headers" module isn't enabled.
|
|
||||||
Header always set X-Frame-Options "deny"
|
|
||||||
# Header always set Content-Security-Policy "default-src 'self' files.nibblepoker.lu; img-src 'self' files.nibblepoker.lu data:; object-src 'none'; child-src 'self'; frame-ancestors 'none'; upgrade-insecure-requests; block-all-mixed-content"
|
|
||||||
Header always set X-XSS-Protection " 1; mode=block"
|
|
||||||
Header always set Referrer-Policy "no-referrer"
|
|
||||||
Header always set X-Content-Type-Options "nosniff"
|
|
||||||
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
|
||||||
#Header always set Cache-Control "max-age=300, public"
|
|
||||||
Header always set Access-Control-Allow-Origin "*"
|
|
||||||
Header always set Permissions-Policy "browsing-topics=(), interest-cohort=()"
|
|
||||||
|
|
||||||
# Removing some headers since they often raise BS alarms about too much back-end info being sent to clients.
|
|
||||||
# Note: These headers can actually be removed by most reverse-proxies.
|
|
||||||
Header unset X-Powered-By
|
|
||||||
|
|
||||||
|
|
||||||
# Handling all other redirections.
|
|
||||||
# Will cause "fail-safe crashes" if the "rewrite" module isn't enabled.
|
|
||||||
RewriteEngine On
|
|
||||||
|
|
||||||
# Serving normal pages when a specific language key is at the beginning of the requested path.
|
|
||||||
# We use a regex to match all supported languages and use the 3rd ground, `(.*)` as `$3`, as the "real" path.
|
|
||||||
RewriteRule ^((en|fr)/)(.*)$ /$3 [QSA]
|
|
||||||
|
|
||||||
# Handling requests for "robots.txt" and "sitemap.txt" via PHP.
|
|
||||||
RewriteRule ^(en/|fr/)?robots.txt$ robots.php [L]
|
|
||||||
RewriteRule ^(en/|fr/)?sitemap.txt$ sitemap.php [L]
|
|
10
Dockerfile
Normal file
10
Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
FROM python:alpine
|
||||||
|
|
||||||
|
WORKDIR /www
|
||||||
|
ADD ./ ./
|
||||||
|
|
||||||
|
RUN apk add --no-cache cargo
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
RUN pip install gunicorn
|
||||||
|
|
||||||
|
ENTRYPOINT ["top", "-b"]
|
160
about/index.php
160
about/index.php
@@ -1,160 +0,0 @@
|
|||||||
<?php
|
|
||||||
$start_time = microtime(true);
|
|
||||||
set_include_path('../');
|
|
||||||
include_once 'commons/config.php';
|
|
||||||
include_once 'commons/langs.php';
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="<?php echo($user_language); ?>">
|
|
||||||
<head>
|
|
||||||
<?php include 'commons/DOM/head.php'; ?>
|
|
||||||
<title><?php print(localize('about.head.title')); ?></title>
|
|
||||||
<meta name="description" content="<?php print(localize('about.head.description')); ?>">
|
|
||||||
<meta property="og:title" content="<?php print(localize('about.og.title')); ?>"/>
|
|
||||||
<meta property="og:type" content="website"/>
|
|
||||||
<meta property="og:url" content="<?php echo($host_uri . l10n_url_abs('/about/')); ?>"/>
|
|
||||||
<meta property="og:image" content="<?php echo($host_uri); ?>/resources/NibblePoker/images/logos/v2_opengraph_v2.png"/>
|
|
||||||
<meta property="og:image:type" content="image/png"/>
|
|
||||||
<meta property="og:description" content="<?php print(localize('about.og.description')); ?>"/>
|
|
||||||
</head>
|
|
||||||
<body class="layout-generic">
|
|
||||||
<?php
|
|
||||||
include_once 'commons/DOM/utils.php';
|
|
||||||
$SIDEBAR_IDS = ['about'];
|
|
||||||
include 'commons/DOM/sidebar.php';
|
|
||||||
?>
|
|
||||||
<header class="w-full p-m pl-s">
|
|
||||||
<h1 class="t-size-17 t-w-500">
|
|
||||||
<i class="fad fa-user t-size-16 mr-s t-muted"></i><?php print(localize("about.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("about.intro.title")); ?>
|
|
||||||
<img src="/resources/NibblePoker/images/about/profile-pic.jpg" alt="" class="r-r img-profile f-right m-xs ml-xxs" draggable="false">
|
|
||||||
<p class="mt-xs ml-s">
|
|
||||||
<?php print(localize("about.intro.text.01")); ?><br>
|
|
||||||
<?php print(localize("about.intro.text.02")); ?>
|
|
||||||
</p>
|
|
||||||
<p class="mt-xs ml-s">
|
|
||||||
<?php print(localize("about.intro.text.10")); ?><br>
|
|
||||||
<?php print(localize("about.intro.text.11")); ?>
|
|
||||||
</p>
|
|
||||||
<p class="mt-xs ml-s">
|
|
||||||
<?php print(localize("about.intro.text.20")); ?><br>
|
|
||||||
<?php print(localize("about.intro.text.21")); ?>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<?php printSubHeader(localize("about.tenets.title")); ?>
|
|
||||||
<p class="mt-xs ml-s t-bold">
|
|
||||||
<!-- TODO: This section -->
|
|
||||||
TODO
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<?php printSubHeader(localize("about.future.title")); ?>
|
|
||||||
<p class="mt-xs ml-s">
|
|
||||||
<?php print(localize("about.future.text.01")); ?><br>
|
|
||||||
<?php print(localize("about.future.text.02")); ?>
|
|
||||||
</p>
|
|
||||||
<p class="mt-xs ml-s">
|
|
||||||
<?php print(localize("about.future.text.10")); ?>
|
|
||||||
</p>
|
|
||||||
<p class="mt-xs ml-s">
|
|
||||||
<?php print(localize("about.future.text.20")); ?>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<?php printSubHeader(localize("about.financing.title")); ?>
|
|
||||||
<p class="mt-xxs ml-s">
|
|
||||||
<?php print(localize("about.financing.text.01")); ?><br>
|
|
||||||
<?php print(localize("about.financing.text.02")); ?>
|
|
||||||
</p>
|
|
||||||
<p class="mt-xs ml-s">
|
|
||||||
<?php print(localize("about.financing.text.10")); ?>
|
|
||||||
</p>
|
|
||||||
<p class="mt-xs ml-s">
|
|
||||||
<?php print(localize("about.financing.text.20")); ?><br>
|
|
||||||
<?php print(localize("about.financing.text.21")); ?>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="grid col-2 col-medium-1">
|
|
||||||
<table class="stylish r-s border o-hidden table-p-xs table-h-p-s table-v-center mt-s mx-s">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th><?php print(localize("about.financing.part.service")); ?></th>
|
|
||||||
<th><?php print(localize("about.financing.part.cost.yearly")); ?></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td><?php print(localize("about.financing.part.domain.lu")); ?></td>
|
|
||||||
<td><?php print(number_format(17,2, $lang_number_decimal, $lang_number_thousands)); ?> €</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><?php print(localize("about.financing.part.domain.com")); ?></td>
|
|
||||||
<td><?php print(number_format(14.5,2, $lang_number_decimal, $lang_number_thousands)); ?> €</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><?php print(localize("about.financing.part.proxy.europe")); ?></td>
|
|
||||||
<td><?php print(number_format(14.5,2, $lang_number_decimal, $lang_number_thousands)); ?> €</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><?php print(localize("about.financing.part.proxy.america")); ?></td>
|
|
||||||
<td><?php print(number_format(13,2, $lang_number_decimal, $lang_number_thousands)); ?> €</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><?php print(localize("about.financing.part.electricity")); ?></td>
|
|
||||||
<td>±<?php print(number_format(30,2, $lang_number_decimal, $lang_number_thousands)); ?> €</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><b class="f-right"><?php print(localize("about.financing.part.cost.yearly.total")); ?>:</b></td>
|
|
||||||
<td>±<?php print(number_format(
|
|
||||||
17 + 14.5 + 14.5 + 13 + 30,
|
|
||||||
2, $lang_number_decimal, $lang_number_thousands)
|
|
||||||
); ?> €
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="stylish r-s border o-hidden table-p-xs table-h-p-s table-v-center mt-s mx-s">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th><?php print(localize("about.financing.part.equipment")); ?></th>
|
|
||||||
<th><?php print(localize("about.financing.part.cost")); ?></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<?php print(localize("about.financing.part.nanopir4s")); ?>
|
|
||||||
</td>
|
|
||||||
<td>±<?php print(number_format(80,2, $lang_number_decimal, $lang_number_thousands)); ?> €</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><?php print(localize("about.financing.part.storage")); ?></td>
|
|
||||||
<td>±<?php print(number_format(10,2, $lang_number_decimal, $lang_number_thousands)); ?> €</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><b class="f-right"><?php print(localize("about.financing.part.cost.total")); ?>:</b></td>
|
|
||||||
<td>±<?php print(number_format(90, 2, $lang_number_decimal, $lang_number_thousands)); ?> €
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<p class="mt-xs ml-s t-super-muted t-center">
|
|
||||||
<?php print(localize("about.financing.text.isp")); ?>
|
|
||||||
</p>
|
|
||||||
</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 -->");
|
|
||||||
}
|
|
||||||
?>
|
|
383
app.py
Normal file
383
app.py
Normal file
@@ -0,0 +1,383 @@
|
|||||||
|
import mimetypes
|
||||||
|
import os
|
||||||
|
from html import escape
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from flask import Flask, request, send_from_directory, url_for, Response
|
||||||
|
from flask import render_template
|
||||||
|
from minify_html import minify
|
||||||
|
from werkzeug.exceptions import HTTPException
|
||||||
|
|
||||||
|
from website.content import reload_content_items, get_articles, get_projects, get_tools, sanitize_input_tags
|
||||||
|
from website.contributors import reload_contributors_data, get_contributors_data
|
||||||
|
from website.domains import ALLOWED_DOMAINS
|
||||||
|
from website.l10n.utils import get_user_lang, localize, reload_strings, l10n_url_abs, l10n_url_switch, L10N, \
|
||||||
|
DEFAULT_LANG
|
||||||
|
from website.renderers.button import render_button
|
||||||
|
from website.renderers.headings import render_heading, render_h2, render_h1, render_h3
|
||||||
|
from website.renderers.paragraph import render_paragraph
|
||||||
|
from website.renderers.splide import render_splide
|
||||||
|
from website.sidebar import reload_sidebar_entries, get_sidebar_entries
|
||||||
|
from website.sitemap import reload_sitemap_entries, get_sitemap_entries
|
||||||
|
|
||||||
|
# try:
|
||||||
|
# from rich import print
|
||||||
|
# except ImportError:
|
||||||
|
# pass
|
||||||
|
|
||||||
|
|
||||||
|
app = Flask(
|
||||||
|
import_name=__name__,
|
||||||
|
static_folder='static',
|
||||||
|
static_url_path='/',
|
||||||
|
template_folder='templates',
|
||||||
|
)
|
||||||
|
app.jinja_env.trim_blocks = True
|
||||||
|
app.jinja_env.lstrip_blocks = True
|
||||||
|
app.jinja_env.strip_trailing_newlines = True
|
||||||
|
|
||||||
|
mimetypes.add_type('application/javascript', '.mjs')
|
||||||
|
|
||||||
|
|
||||||
|
@app.after_request
|
||||||
|
def add_common_headers(response):
|
||||||
|
# print(response.headers)
|
||||||
|
|
||||||
|
response.headers['X-Frame-Options'] = "deny"
|
||||||
|
# #Header always set Content-Security-Policy "default-src 'self' files.nibblepoker.lu; img-src 'self'
|
||||||
|
# files.nibblepoker.lu data:; object-src 'none'; child-src 'self'; frame-ancestors 'none';
|
||||||
|
# upgrade-insecure-requests; block-all-mixed-content"
|
||||||
|
response.headers['X-XSS-Protection'] = "1; mode=block"
|
||||||
|
response.headers['Referrer-Policy'] = "no-referrer"
|
||||||
|
response.headers['X-Content-Type-Options'] = "nosniff"
|
||||||
|
response.headers['Strict-Transport-Security'] = "max-age=31536000; includeSubDomains; preload"
|
||||||
|
response.headers['Access-Control-Allow-Origin'] = "*"
|
||||||
|
response.headers['Permissions-Policy'] = "browsing-topics=(), interest-cohort=()"
|
||||||
|
|
||||||
|
if app.debug:
|
||||||
|
response.headers['Pragma'] = 'no-cache'
|
||||||
|
response.headers['Expires'] = '0'
|
||||||
|
else:
|
||||||
|
response.headers['Cache-Control'] = "max-age=300, public"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
# https://flask.palletsprojects.com/en/2.3.x/templating/#context-processors
|
||||||
|
@app.context_processor
|
||||||
|
def inject_processors():
|
||||||
|
return dict(
|
||||||
|
# Domain
|
||||||
|
domain_host=request.headers['Host'],
|
||||||
|
domain_tld=request.headers['Host'].split('.')[-1] if request.headers['Host'] in ALLOWED_DOMAINS else "lu",
|
||||||
|
domain_url_root=request.url_root,
|
||||||
|
# L10N
|
||||||
|
l10n=localize,
|
||||||
|
l10n_url_abs=l10n_url_abs,
|
||||||
|
l10n_url_switch=l10n_url_switch,
|
||||||
|
# Sidebar
|
||||||
|
get_sidebar_entries=get_sidebar_entries,
|
||||||
|
# Content
|
||||||
|
get_articles=get_articles,
|
||||||
|
get_projects=get_projects,
|
||||||
|
get_tools=get_tools,
|
||||||
|
# Renderers
|
||||||
|
render_button=render_button,
|
||||||
|
render_heading=render_heading,
|
||||||
|
render_h1=render_h1,
|
||||||
|
render_h2=render_h2,
|
||||||
|
render_h3=render_h3,
|
||||||
|
render_paragraph=render_paragraph,
|
||||||
|
render_splide=render_splide,
|
||||||
|
# Commons
|
||||||
|
url_for=url_for,
|
||||||
|
escape=escape,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/favicon.svg')
|
||||||
|
@app.route('/favicon.ico')
|
||||||
|
def route_favicon():
|
||||||
|
return send_from_directory(app.static_folder, 'favicon.ico', mimetype='image/vnd.microsoft.icon')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/robots.txt')
|
||||||
|
def route_robots_txt():
|
||||||
|
return Response(render_template("robots.jinja"), mimetype="")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/sitemap.txt')
|
||||||
|
def route_sitemap():
|
||||||
|
# FIXME: Add the domain !!!
|
||||||
|
return Response("\n".join(get_sitemap_entries()), mimetype="")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/', defaults={'lang': None})
|
||||||
|
@app.route('/en/', defaults={'lang': "en"})
|
||||||
|
@app.route('/fr/', defaults={'lang': "fr"})
|
||||||
|
def route_root(lang: Optional[str]):
|
||||||
|
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/root.jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
)).replace("> <", "><")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/contact/', defaults={'lang': None})
|
||||||
|
@app.route('/en/contact/', defaults={'lang': "en"})
|
||||||
|
@app.route('/fr/contact/', defaults={'lang': "fr"})
|
||||||
|
def route_contact(lang: Optional[str]):
|
||||||
|
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/contact.jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
)).replace("> <", "><")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/content/', defaults={'lang': None})
|
||||||
|
@app.route('/en/content/', defaults={'lang': "en"})
|
||||||
|
@app.route('/fr/content/', defaults={'lang': "fr"})
|
||||||
|
def route_content(lang: Optional[str]):
|
||||||
|
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
|
||||||
|
try:
|
||||||
|
requested_tags = sanitize_input_tags(request.args.get("tags", ""))
|
||||||
|
except ValueError:
|
||||||
|
requested_tags = None
|
||||||
|
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/project_index.jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
requested_tags=requested_tags,
|
||||||
|
)).replace("> <", "><")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/content/<project_id>/', defaults={'lang': None})
|
||||||
|
@app.route('/en/content/<project_id>/', defaults={'lang': "en"})
|
||||||
|
@app.route('/fr/content/<project_id>/', defaults={'lang': "fr"})
|
||||||
|
def route_content_project(lang: Optional[str], project_id: str):
|
||||||
|
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
|
||||||
|
error_key: Optional[str] = None
|
||||||
|
error_code: int = 200
|
||||||
|
if not project_id.replace("-", "").isalnum():
|
||||||
|
error_key = "content_id_alphanumeric"
|
||||||
|
error_code = 400
|
||||||
|
elif project_id not in get_projects().keys():
|
||||||
|
error_key = "content_id_not_exist"
|
||||||
|
error_code = 404
|
||||||
|
|
||||||
|
if error_key is not None:
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/error.jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
error_key=error_key,
|
||||||
|
error_code=error_code,
|
||||||
|
)).replace("> <", "><"), error_code
|
||||||
|
else:
|
||||||
|
return minify(render_template(
|
||||||
|
"projects/" + project_id + ".jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
project_data=get_projects().get(project_id),
|
||||||
|
project_id=project_id,
|
||||||
|
)).replace("> <", "><")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/tools/', defaults={'lang': None})
|
||||||
|
@app.route('/en/tools/', defaults={'lang': "en"})
|
||||||
|
@app.route('/fr/tools/', defaults={'lang': "fr"})
|
||||||
|
def route_tools_index(lang: Optional[str]):
|
||||||
|
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
|
||||||
|
try:
|
||||||
|
requested_tags = sanitize_input_tags(request.args.get("tags", ""))
|
||||||
|
except ValueError:
|
||||||
|
requested_tags = None
|
||||||
|
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/tools_index.jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
requested_tags=requested_tags,
|
||||||
|
)).replace("> <", "><")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/tools/<tool_id>/', defaults={'lang': None})
|
||||||
|
@app.route('/en/tools/<tool_id>/', defaults={'lang': "en"})
|
||||||
|
@app.route('/fr/tools/<tool_id>/', defaults={'lang': "fr"})
|
||||||
|
def route_tools_page(lang: Optional[str], tool_id: str):
|
||||||
|
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
|
||||||
|
error_key: Optional[str] = None
|
||||||
|
error_code: int = 200
|
||||||
|
if not tool_id.replace("-", "").isalnum():
|
||||||
|
error_key = "content_id_alphanumeric"
|
||||||
|
error_code = 400
|
||||||
|
elif tool_id not in get_tools().keys():
|
||||||
|
error_key = "content_id_not_exist"
|
||||||
|
error_code = 404
|
||||||
|
|
||||||
|
if error_key is not None:
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/error.jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
error_key=error_key,
|
||||||
|
error_code=error_code,
|
||||||
|
)).replace("> <", "><"), error_code
|
||||||
|
else:
|
||||||
|
return minify(render_template(
|
||||||
|
"tools/" + tool_id + ".jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
tool_data=get_tools().get(tool_id),
|
||||||
|
tool_id=tool_id,
|
||||||
|
)).replace("> <", "><")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/about/', defaults={'lang': None})
|
||||||
|
@app.route('/en/about/', defaults={'lang': "en"})
|
||||||
|
@app.route('/fr/about/', defaults={'lang': "fr"})
|
||||||
|
def route_about(lang: Optional[str]):
|
||||||
|
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/about.jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
)).replace("> <", "><")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/privacy/', defaults={'lang': None})
|
||||||
|
@app.route('/en/privacy/', defaults={'lang': "en"})
|
||||||
|
@app.route('/fr/privacy/', defaults={'lang': "fr"})
|
||||||
|
def route_privacy(lang: Optional[str]):
|
||||||
|
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/privacy.jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
)).replace("> <", "><")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/links/', defaults={'lang': None})
|
||||||
|
@app.route('/en/links/', defaults={'lang': "en"})
|
||||||
|
@app.route('/fr/links/', defaults={'lang': "fr"})
|
||||||
|
def route_links(lang: Optional[str]):
|
||||||
|
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/links.jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
)).replace("> <", "><")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/debug/', defaults={'lang': None})
|
||||||
|
@app.route('/en/debug/', defaults={'lang': "en"})
|
||||||
|
@app.route('/fr/debug/', defaults={'lang': "fr"})
|
||||||
|
def route_debug(lang: Optional[str]):
|
||||||
|
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/debug.jinja",
|
||||||
|
user_lang=user_lang,
|
||||||
|
raw_lang=lang,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
)).replace("> <", "><")
|
||||||
|
|
||||||
|
|
||||||
|
@app.errorhandler(Exception)
|
||||||
|
def handle_exception(e: Exception):
|
||||||
|
# FIXME: Use the user's lang !
|
||||||
|
# user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
|
||||||
|
|
||||||
|
error_code = 500
|
||||||
|
|
||||||
|
if isinstance(e, HTTPException):
|
||||||
|
error_code = e.code
|
||||||
|
|
||||||
|
return minify(render_template(
|
||||||
|
"pages/error.jinja",
|
||||||
|
user_lang=DEFAULT_LANG,
|
||||||
|
raw_lang=DEFAULT_LANG,
|
||||||
|
request_path=request.path,
|
||||||
|
standalone="standalone" in request.args,
|
||||||
|
error_key=str(e.code),
|
||||||
|
error_code=e.code,
|
||||||
|
)).replace("> <", "><"), error_code
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
reload_content_items()
|
||||||
|
reload_strings(os.path.join(os.getcwd(), "data/strings/"))
|
||||||
|
reload_sidebar_entries(os.path.join(os.getcwd(), "data/sidebar.yml"))
|
||||||
|
reload_contributors_data(os.path.join(os.getcwd(), "data/contributors.yml"))
|
||||||
|
reload_sitemap_entries(os.path.join(os.getcwd(), "data/sitemap.yml"))
|
||||||
|
|
||||||
|
# try:
|
||||||
|
# os.remove("data/strings/dumps.json")
|
||||||
|
# except OSError:
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
# try:
|
||||||
|
# with open("data/strings/dumps.json", "w") as f:
|
||||||
|
# f.write(json.dumps(L10N._langs_data, indent=2))
|
||||||
|
# except Exception as err:
|
||||||
|
# print(err)
|
||||||
|
|
||||||
|
# from waitress import serve
|
||||||
|
# serve(app, host='0.0.0.0', port=5000, threads=64)
|
||||||
|
|
||||||
|
app.run(
|
||||||
|
host="0.0.0.0",
|
||||||
|
port=5000,
|
||||||
|
debug=True,
|
||||||
|
#debug=False,
|
||||||
|
load_dotenv=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# return BeautifulSoup(render_template(
|
||||||
|
# "pages/root.jinja",
|
||||||
|
# lang=user_lang,
|
||||||
|
# raw_lang=lang,
|
||||||
|
# request_path=request.path,
|
||||||
|
# standalone="standalone" in request.args,
|
||||||
|
# ), features="html.parser").prettify()
|
||||||
|
|
||||||
|
# try:
|
||||||
|
# from minify_html import minify
|
||||||
|
# FORCE_NON_DEBUG = False
|
||||||
|
# except ImportError:
|
||||||
|
# from bs4 import BeautifulSoup
|
||||||
|
# FORCE_NON_DEBUG = True
|
||||||
|
#
|
||||||
|
# def minify(html):
|
||||||
|
# return BeautifulSoup(html, features="html.parser").prettify()
|
||||||
|
# debug=False if FORCE_NON_DEBUG else True,
|
@@ -1,6 +0,0 @@
|
|||||||
# Serving minified pages and/or pre-rendered ones first if available.
|
|
||||||
DirectoryIndex index.min.html index.min.php index.php index.html
|
|
||||||
|
|
||||||
# Redirecting any URL that starts with "/content" to the root of this folder.
|
|
||||||
RewriteEngine On
|
|
||||||
RewriteRule ^(.*) index.php [NC]
|
|
@@ -1,3 +0,0 @@
|
|||||||
[
|
|
||||||
|
|
||||||
]
|
|
@@ -1,43 +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();
|
|
||||||
}
|
|
||||||
|
|
||||||
include_once 'commons/langs.php';
|
|
||||||
?>
|
|
||||||
<footer class="d-flex flex-align-center w-full p-s py-xs">
|
|
||||||
<button id="sidebar-toggle-footer" class="p-xs border r-s t-size-10" aria-label="<?php echo(localize("footer.alt.sidebar.button")); ?>">
|
|
||||||
<i class="fa fa-bars px-xxs" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
<p class="flex-fill t-center t-size-10 t-w-500 t-muted">
|
|
||||||
<a class="a-hidden" href="<?php print(l10n_url_abs('/privacy/')); ?>">
|
|
||||||
<?php print(localize('footer.text.privacy')); ?>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<a href="<?php print(l10n_url_abs('/')); ?>">
|
|
||||||
<img id="logo-footer" src="/resources/NibblePoker/images/logos/v2_full_unshaded_original.svg"
|
|
||||||
alt="<?php echo(localize("footer.alt.logo")); ?>" draggable="false">
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
<?php
|
|
||||||
if($enable_waffle_iron) {
|
|
||||||
$emojis = ['🍟', '🧇', '🥔'];
|
|
||||||
shuffle($emojis);
|
|
||||||
echo('<div class="snowflakes" aria-hidden="true">');
|
|
||||||
for($i_waffle = 0; $i_waffle < 12; $i_waffle++) {
|
|
||||||
echo('<div class="snowflake"><div class="inner">' . ($emojis)[$i_waffle % 3] . '</div></div>');
|
|
||||||
}
|
|
||||||
echo('</div>');
|
|
||||||
}
|
|
||||||
if($enable_bouneschlupp_mode) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Implement those
|
|
||||||
//if($enable_gallery) {
|
|
||||||
// echo('<div id="modal-bkgd" hidden></div>');
|
|
||||||
// echo('<div id="modal-container" hidden></div>');
|
|
||||||
//}
|
|
||||||
?>
|
|
@@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
if($enable_kitty_and_doggo_sounds) {
|
|
||||||
echo('<link rel="prefetch" as="audio" href="/resources/NibblePoker/sounds/meow-test-01.ogg">');
|
|
||||||
echo('<link rel="prefetch" as="audio" href="/resources/NibblePoker/sounds/meow-test-02.ogg">');
|
|
||||||
}
|
|
||||||
?>
|
|
@@ -1,32 +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();
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
|
|
||||||
<meta name="viewport" content="width=device-width"/>
|
|
||||||
<meta name="author" content="Herwin Bozet">
|
|
||||||
<meta name="robots" content="index, follow">
|
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
||||||
<link rel="alternate icon" href="/favicon.ico">
|
|
||||||
<link rel="stylesheet" href="https://cdn.nibblepoker.lu/FontAwesomePro/6.5.1/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="https://cdn.nibblepoker.lu/NibblePoker/StandardCSS/nibblepoker.min.css">
|
|
||||||
<link rel="stylesheet" href="https://cdn.nibblepoker.lu/Quantum/Quantum.min.css">
|
|
||||||
<?php
|
|
||||||
if($enable_code_highlight) {
|
|
||||||
echo('<link href="/resources/HighlightJS/src/styles/atom-one-dark.min.css" rel="stylesheet"/>');
|
|
||||||
}
|
|
||||||
if($enable_gallery) {
|
|
||||||
echo('<link href="/resources/SplideJs/dist/css/splide.min.css" rel="stylesheet"/>');
|
|
||||||
}
|
|
||||||
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"/>');
|
|
||||||
}
|
|
||||||
?>
|
|
@@ -1,26 +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();
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<details id="lang-selector" class="border p-mxs px-s bkgd-blank-dark r-m">
|
|
||||||
<summary>
|
|
||||||
<i class="fad fa-language"></i>
|
|
||||||
<span class="mobile-hide t-w-500"> <?php print(localize("lang.menu.title")); ?></span>
|
|
||||||
<i class="fa fa-angle-down"></i>
|
|
||||||
</summary>
|
|
||||||
<div class="p-xs border bkgd-surround r-m t-w-500">
|
|
||||||
<a href="<?php echo(l10n_url_switch('en')); ?>" class="a-hidden">
|
|
||||||
<p class="mb-s px-xxs"><?php print(localize("lang.english")); ?></p>
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo(l10n_url_switch('fr')); ?>" class="a-hidden">
|
|
||||||
<p class="my-s px-xxs"><?php print(localize("lang.french")); ?></p>
|
|
||||||
</a>
|
|
||||||
<hr class="subtle m-0">
|
|
||||||
<a href="<?php echo(l10n_url_switch(NULL)); ?>" class="a-hidden">
|
|
||||||
<p class="mt-xs px-xxs"><?php print(localize("lang.automatic")); ?></p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</details>
|
|
@@ -1,30 +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();
|
|
||||||
}
|
|
||||||
|
|
||||||
if($enable_gallery) {
|
|
||||||
echo('<script src="/resources/SplideJs/dist/js/splide.min.js"></script>');
|
|
||||||
}
|
|
||||||
|
|
||||||
if($enable_code_highlight) {
|
|
||||||
echo('<script src="/resources/HighlightJS/highlight.min.js"></script>');
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<script src="/resources/NibblePoker/js/nibblepoker.min.js"></script>
|
|
||||||
<?php
|
|
||||||
if($enable_gallery) {
|
|
||||||
echo('<script src="/resources/NibblePoker/js/nibblepoker-splide.min.js"></script>');
|
|
||||||
}
|
|
||||||
if($enable_code_highlight) {
|
|
||||||
echo('<script src="/resources/NibblePoker/js/nibblepoker-code.min.js"></script>');
|
|
||||||
}
|
|
||||||
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>');
|
|
||||||
}
|
|
||||||
?>
|
|
@@ -1,61 +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();
|
|
||||||
}
|
|
||||||
|
|
||||||
include_once 'commons/langs.php';
|
|
||||||
|
|
||||||
if(!isset($SIDEBAR_IDS)) {
|
|
||||||
$SIDEBAR_IDS = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function printSidebarEntry($url, $title, $icon, $activeId) {
|
|
||||||
global $SIDEBAR_IDS;
|
|
||||||
echo('<a class="' . (in_array($activeId, $SIDEBAR_IDS) ? 'a-bland' : 'a-hidden') . '" href="' . $url . '">');
|
|
||||||
echo('<p class="t-size-18 t-w-500 py-xs sidebar-entry">');
|
|
||||||
echo('<i class="' . $icon . ' pr-xs t-size-12 t-half-muted"></i><span class="t-size-12">' . $title . '</span></p></a>');
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
<nav id="sidebar" class="sidebar p-m">
|
|
||||||
<a href="<?php print(l10n_url_abs('/')); ?>" class="no-select">
|
|
||||||
<img class="logo-sidebar-v2"
|
|
||||||
src="https://cdn.nibblepoker.lu/NibblePoker/Logos/v2_full_shaded_optimized.svg"
|
|
||||||
alt="<?php echo(localize("sidebar.alt.logo")); ?>"
|
|
||||||
draggable="false">
|
|
||||||
</a>
|
|
||||||
<p class="quantum t-logo-text mb-s mt-xxs t-muted t-ucase">
|
|
||||||
N<span class="t-super-muted">ibble</span>P<span class="t-super-muted">oker</span>
|
|
||||||
</p>
|
|
||||||
<hr class="subtle">
|
|
||||||
<?php
|
|
||||||
printSidebarEntry(l10n_url_abs('/'), localize("sidebar.text.home"), "fad fa-home", "home");
|
|
||||||
//printSidebarEntry(l10n_url_abs('/shop'), localize("sidebar.text.shop"), "fad fa-shopping-cart", "shop");
|
|
||||||
//printSidebarEntry(l10n_url_abs('/school'), localize("sidebar.text.school"), "fad fa-chalkboard-teacher", "school");
|
|
||||||
?>
|
|
||||||
<hr class="subtle">
|
|
||||||
<?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=electronic'), localize("sidebar.text.electronics"), "fad fa-microchip", "electronic");
|
|
||||||
//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");
|
|
||||||
?>
|
|
||||||
<hr class="subtle">
|
|
||||||
<?php
|
|
||||||
printSidebarEntry(l10n_url_abs('/links/'), localize("sidebar.text.links"), "fad fa-link", "links");
|
|
||||||
printSidebarEntry("https://files.nibblepoker.lu/", localize("sidebar.text.downloads"), "fad fa-download", "");
|
|
||||||
//printSidebarEntry("https://git.nibblepoker.lu/", localize("sidebar.text.gitea"), "fad fa-code", "");
|
|
||||||
//printSidebarEntry("https://wiki.nibblepoker.lu/", localize("sidebar.text.wiki"), "fad fa-books", "");
|
|
||||||
?>
|
|
||||||
<hr class="subtle">
|
|
||||||
<?php
|
|
||||||
printSidebarEntry(l10n_url_abs('/about/'), localize("sidebar.text.about"), "fad fa-user", "about");
|
|
||||||
//printSidebarEntry(l10n_url_abs('/contributors/'), localize("sidebar.text.contributors"), "fad fa-users", "contributors");
|
|
||||||
printSidebarEntry(l10n_url_abs('/contact/'), localize("sidebar.text.contact"), "fad fa-mailbox", "contact");
|
|
||||||
?>
|
|
||||||
</nav>
|
|
@@ -1,81 +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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used by 'printMainHeader()'.
|
|
||||||
$_npDomUtilsHeadingCount = 0;
|
|
||||||
|
|
||||||
function getMainHeader(string $text, ?string $iconId = null, ?string $rightText = null, ?string $anchorId = null,
|
|
||||||
bool $addTopMargin = true, ?string $backgroundClass = "bkgd-grid", int $hLevel = 2,
|
|
||||||
bool $autoWidth = false, bool $chungusMode = false, bool $makeSmaller = false): string {
|
|
||||||
if(is_null($backgroundClass)) {
|
|
||||||
$backgroundClass = "bkgd-grid";
|
|
||||||
}
|
|
||||||
|
|
||||||
$htmlCode = "";
|
|
||||||
|
|
||||||
if(!is_null($anchorId)) {
|
|
||||||
$htmlCode .= '<a class="bland-link" href="#' . $anchorId . '">';
|
|
||||||
}
|
|
||||||
|
|
||||||
$htmlCode .= '<div class="heading-main p-xs border r-s ' . ($addTopMargin > 0 ? "mt-l " : "") . $backgroundClass .
|
|
||||||
($autoWidth ? " d-inline-block" : "") . '"><h' . $hLevel . ' class="t-w-500 ' .
|
|
||||||
($chungusMode ? "t-size-16" : ($makeSmaller ? "t-size-11" : "t-size-14")) . '">';
|
|
||||||
|
|
||||||
// TODO: Add a simple and nicer divider.
|
|
||||||
if(!is_null($iconId)) {
|
|
||||||
$htmlCode .= '<i class="' . $iconId . ' t-muted ' . ($chungusMode ? "t-size-14" : "t-size-12") . '"></i>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$htmlCode .= $text;
|
|
||||||
|
|
||||||
if(!is_null($rightText)) {
|
|
||||||
$htmlCode .= '<span class="f-right mobile-hide ' . ($chungusMode ? "t-size-12 mr-xs" : "t-size-10 t-muted") . '">' . $rightText . '</span>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$htmlCode .= '</h' . $hLevel . '></div>';
|
|
||||||
|
|
||||||
if(!is_null($anchorId)) {
|
|
||||||
$htmlCode .= '</a>';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $htmlCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
function printMainHeader(string $text, ?string $iconId = null, ?string $rightText = null, ?string $anchorId = null,
|
|
||||||
?string $backgroundClass = "bkgd-grid"): void {
|
|
||||||
global $_npDomUtilsHeadingCount;
|
|
||||||
$_npDomUtilsHeadingCount++;
|
|
||||||
echo(getMainHeader(
|
|
||||||
$text,
|
|
||||||
$iconId,
|
|
||||||
$rightText,
|
|
||||||
$anchorId,
|
|
||||||
($_npDomUtilsHeadingCount > 1),
|
|
||||||
$backgroundClass
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function printSubHeader(string $text, ?string $anchorId = null, ?string $backgroundClass = "bkgd-math"): void {
|
|
||||||
if(is_null($backgroundClass)) {
|
|
||||||
$backgroundClass = "bkgd-math";
|
|
||||||
}
|
|
||||||
$headingText = getMainHeader(
|
|
||||||
$text,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
$anchorId,
|
|
||||||
69, // Forcing it as a non-first of main heading.
|
|
||||||
$backgroundClass,
|
|
||||||
3
|
|
||||||
);
|
|
||||||
|
|
||||||
$headingText = str_replace("t-size-14", "t-size-11", $headingText);
|
|
||||||
|
|
||||||
echo($headingText);
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@@ -1,44 +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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used for opengraph head tags & the debug page.
|
|
||||||
switch($_SERVER['SERVER_NAME']) {
|
|
||||||
case "nibblepoker.com":
|
|
||||||
$host = "nibblepoker.com";
|
|
||||||
$host_uri = "https://nibblepoker.com";
|
|
||||||
$host_tld = "com";
|
|
||||||
$cdn_uri = "https://cdn.nibblepoker.com";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$host = "nibblepoker.lu";
|
|
||||||
$host_uri = "https://nibblepoker.lu";
|
|
||||||
$host_tld = "lu";
|
|
||||||
$cdn_uri = "https://cdn.nibblepoker.lu";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$dir_commons = dirname(__FILE__);
|
|
||||||
$dir_root = realpath($dir_commons . "/../");
|
|
||||||
$config_dir_content = realpath($dir_commons . "/../" . "content/");
|
|
||||||
$config_dir_tools = realpath($dir_commons . "/../" . "tools/");
|
|
||||||
|
|
||||||
// Optional features
|
|
||||||
$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.
|
|
||||||
$enable_waffle_iron = date('m-d') === '07-21';
|
|
||||||
|
|
||||||
// > Luxembourg's national day.
|
|
||||||
$enable_bouneschlupp_mode = date('m-d') === '06-23';
|
|
||||||
|
|
||||||
// Debugging stuff
|
|
||||||
$print_execution_timer = false;
|
|
||||||
?>
|
|
@@ -1,3 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
?>
|
|
@@ -1,978 +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/config.php';
|
|
||||||
include_once 'commons/langs.php';
|
|
||||||
include_once 'commons/content/manager.php';
|
|
||||||
|
|
||||||
// Required to make headings
|
|
||||||
include_once 'commons/DOM/utils.php';
|
|
||||||
|
|
||||||
// Defining some options.
|
|
||||||
$USE_CONFIG_URI_FOR_OPENGRAPH = true;
|
|
||||||
$AUTO_DETECT_OPENGRAPH_MIME = true;
|
|
||||||
$LANG_FALLBACK_KEY_PREFIX = "";
|
|
||||||
|
|
||||||
// Defining the template types.
|
|
||||||
abstract class ComposerTemplates {
|
|
||||||
const RAW = "raw";
|
|
||||||
const ARTICLE_LEGACY = "article";
|
|
||||||
const GENERIC_PROJECT_README = "generic-project-readme";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all the constants present in the class.
|
|
||||||
* @return array All the constants in as "[[k, v], [k, v], ...]".
|
|
||||||
* @see https://www.php.net/manual/en/reflectionclass.getconstants.php
|
|
||||||
*/
|
|
||||||
static function getConstants(): array {
|
|
||||||
$oClass = new ReflectionClass(__CLASS__);
|
|
||||||
return $oClass->getConstants();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defining the different types of elements available.
|
|
||||||
abstract class ComposerElementTypes {
|
|
||||||
const UNSET = "unset";
|
|
||||||
const RAW = "raw";
|
|
||||||
const H1 = "h1";
|
|
||||||
const H2 = "h2";
|
|
||||||
const H3 = "h3";
|
|
||||||
const PARAGRAPH = "paragraph";
|
|
||||||
const BUTTON = "button";
|
|
||||||
const CODE = "code";
|
|
||||||
const HR = "hr";
|
|
||||||
const CONTAINER = "container";
|
|
||||||
const COLLAPSE = "collapse";
|
|
||||||
const SPACER = "spacer";
|
|
||||||
const IMAGE = "image";
|
|
||||||
const TABLE = "table";
|
|
||||||
const GRID = "grid";
|
|
||||||
const GALLERY = "gallery";
|
|
||||||
const VIDEO = "video";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all the constants present in the class.
|
|
||||||
* @return array All the constants in as "[[k, v], [k, v], ...]".
|
|
||||||
* @see https://www.php.net/manual/en/reflectionclass.getconstants.php
|
|
||||||
*/
|
|
||||||
static function getConstants(): array {
|
|
||||||
$oClass = new ReflectionClass(__CLASS__);
|
|
||||||
return $oClass->getConstants();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defining modifiers.
|
|
||||||
abstract class ComposerElementModifiers {
|
|
||||||
// Generic > Margin
|
|
||||||
const GENERIC_MARGIN_NO_TOP = ["mt-0", "mt-0"];
|
|
||||||
const GENERIC_MARGIN_NO_BOTTOM = ["mb-0", "mb-0"];
|
|
||||||
const GENERIC_MARGIN_NO_LEFT = ["ml-0", "ml-0"];
|
|
||||||
const GENERIC_MARGIN_NO_RIGHT = ["mr-0", "mr-0"];
|
|
||||||
const GENERIC_MARGIN_NO_X = ["mx-0", "mx-0"];
|
|
||||||
const GENERIC_MARGIN_NO_Y = ["my-0", "my-0"];
|
|
||||||
const GENERIC_MARGIN_NONE = ["m-0", "m-0" ];
|
|
||||||
|
|
||||||
// Generic > Padding
|
|
||||||
const GENERIC_PADDING_NO_TOP = ["pt-0", "pt-0"];
|
|
||||||
const GENERIC_PADDING_NO_BOTTOM = ["pb-0", "pb-0"];
|
|
||||||
const GENERIC_PADDING_NO_LEFT = ["pl-0", "pl-0"];
|
|
||||||
const GENERIC_PADDING_NO_RIGHT = ["pr-0", "pr-0"];
|
|
||||||
const GENERIC_PADDING_NO_X = ["px-0", "px-0"];
|
|
||||||
const GENERIC_PADDING_NO_Y = ["py-0", "py-0"];
|
|
||||||
const GENERIC_PADDING_NONE = ["p-0" , "p-0" ];
|
|
||||||
|
|
||||||
// Generic > Others
|
|
||||||
const GENERIC_FULL_WIDTH = ["w-full", "w-full"];
|
|
||||||
const GENERIC_BOLD = ["bold", "f-w-500"];
|
|
||||||
|
|
||||||
// Containers
|
|
||||||
const CONTAINER_SCROLL_HORIZONTAL = ["horizontal-scroll", "overflow-x-scroll hide-scrollbar"];
|
|
||||||
const CONTAINER_SCROLL_HORIZONTAL_AUTO = ["horizontal-scroll-auto", "overflow-x-auto"];
|
|
||||||
const CONTAINER_CARD = ["card", "card"];
|
|
||||||
|
|
||||||
// Buttons
|
|
||||||
const BUTTON_THIN = ["thin", ""];
|
|
||||||
const BUTTON_THICK = ["thick", ""];
|
|
||||||
const BUTTON_ROUNDED = ["rounded", ""];
|
|
||||||
const BUTTON_CIRCLE = ["circle", ""];
|
|
||||||
const BUTTON_DOWNLOAD_PRIMARY = ["download-primary", "primary"];
|
|
||||||
|
|
||||||
// Horizontal ruler
|
|
||||||
const HR_SUBTLE = ["subtle", "subtle"];
|
|
||||||
|
|
||||||
// Collapse
|
|
||||||
const DETAILS_NO_ROUNDING = ["no-rounding", ""];
|
|
||||||
const DETAILS_CLOSED = ["closed", ""];
|
|
||||||
|
|
||||||
// Tables
|
|
||||||
const TABLE_NO_OUTER_PADDING = ["no-outer-padding", "table-no-outer-padding"];
|
|
||||||
const TABLE_STRIPED = ["striped", "table-striped"];
|
|
||||||
const TABLE_HOVER = ["hover", "table-hover"];
|
|
||||||
const TABLE_INNER_BORDER = ["inner-bordered", "table-inner-bordered"];
|
|
||||||
const TABLE_OUTER_BORDER = ["outer-bordered", "table-outer-bordered"];
|
|
||||||
const TABLE_V2_STYLISH = ["stylish", "stylish r-s border o-hidden"];
|
|
||||||
const TABLE_V2_CELL_PADDING = ["auto-cell-padding", "table-p-xs table-h-p-s"];
|
|
||||||
const TABLE_V2_VERTICAL_ALIGN = ["v-center-cells", "table-v-center"];
|
|
||||||
|
|
||||||
// Code
|
|
||||||
const CODE_BLOCK = ["code-block", "w-full d-inline-block"];
|
|
||||||
|
|
||||||
// Other internal constants
|
|
||||||
const _INDEX_KEY = 0;
|
|
||||||
const _INDEX_CLASSES = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all the constants present in the class.
|
|
||||||
* @return array All the constants in as "[[k, v], [k, v], ...]".
|
|
||||||
* @see https://www.php.net/manual/en/reflectionclass.getconstants.php
|
|
||||||
*/
|
|
||||||
static function getConstants(): array {
|
|
||||||
$oClass = new ReflectionClass(__CLASS__);
|
|
||||||
return $oClass->getConstants();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the given modifier's constant's key
|
|
||||||
* @param array $modifier_data A modifier constant defined in "ComposerElementModifiers".
|
|
||||||
* @return string The modifier's key or an empty string if an error was encountered.
|
|
||||||
*/
|
|
||||||
static function get_modifier_key(array $modifier_data) : string {
|
|
||||||
return sizeof($modifier_data) >= 1 ? $modifier_data[ComposerElementModifiers::_INDEX_KEY] : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the given modifier's constant's classes
|
|
||||||
* @param array $modifier_data A modifier constant defined in "ComposerElementModifiers".
|
|
||||||
* @return string The modifier's classes or an empty string if an error was encountered.
|
|
||||||
*/
|
|
||||||
static function get_modifier_classes(array $modifier_data) : string {
|
|
||||||
return sizeof($modifier_data) >= 2 ? $modifier_data[ComposerElementModifiers::_INDEX_CLASSES] : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $modifier_key
|
|
||||||
* @return string The resolved DOM classes, or an empty string if the given modifier is unknown.
|
|
||||||
*/
|
|
||||||
static function get_classes_from_key(string $modifier_key) : string {
|
|
||||||
foreach(ComposerElementModifiers::getConstants() as $constant_values) {
|
|
||||||
if(!is_array($constant_values)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if($modifier_key == $constant_values[ComposerElementModifiers::_INDEX_KEY]) {
|
|
||||||
return $constant_values[ComposerElementModifiers::_INDEX_CLASSES];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static function is_modifier_in_modifiers(array $modifier_data, array $modifiers) : bool {
|
|
||||||
foreach($modifiers as $modifier) {
|
|
||||||
if($modifier_data[ComposerElementModifiers::_INDEX_KEY] == $modifier) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data classes
|
|
||||||
class ComposerContent {
|
|
||||||
public array $strings;
|
|
||||||
public ComposerContentMetadata $metadata;
|
|
||||||
public array $elements;
|
|
||||||
|
|
||||||
function __construct(array $strings, ComposerContentMetadata $metadata, array $elements) {
|
|
||||||
$this->strings = $strings;
|
|
||||||
$this->metadata = $metadata;
|
|
||||||
$this->elements = $elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function from_json(array $json_data) : ComposerContent {
|
|
||||||
global $default_language;
|
|
||||||
return new ComposerContent(
|
|
||||||
key_exists("strings", $json_data) ? $json_data["strings"] : array($default_language=>[]),
|
|
||||||
ComposerContentMetadata::from_json(
|
|
||||||
key_exists("metadata", $json_data) ? $json_data["metadata"] : array()
|
|
||||||
),
|
|
||||||
key_exists("elements", $json_data) ?
|
|
||||||
ComposerElement::from_json_array($json_data["elements"]) : array()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_html() : string {
|
|
||||||
$htmlCode = "";
|
|
||||||
|
|
||||||
// FIXME: Check for the template after the loop - Isn't it done already ?
|
|
||||||
|
|
||||||
foreach($this->elements as $element) {
|
|
||||||
/** @var ComposerElement $element */
|
|
||||||
$htmlCode .= $element->get_html($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->metadata->apply_template($this, $htmlCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_head_title() : string {
|
|
||||||
if(!is_null($this->metadata->head->title)) {
|
|
||||||
return localize_private($this->metadata->head->title, $this->strings, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return localize("content.default.head.title");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_head_description() : string {
|
|
||||||
if(!is_null($this->metadata->head->title)) {
|
|
||||||
return localize_private($this->metadata->head->description, $this->strings, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return localize("content.default.head.description");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_opengraph_tags(?string $title_prefix, ?string $type_override, ?string $url_override,
|
|
||||||
?string $image_url_override, ?string $image_url_fallback) : string {
|
|
||||||
global $host_uri;
|
|
||||||
|
|
||||||
$final_image_uri = (is_null($image_url_override) ? (is_null($this->metadata->opengraph->image) ?
|
|
||||||
$image_url_fallback : $this->metadata->opengraph->image) : $image_url_override);
|
|
||||||
|
|
||||||
return '<meta property="og:title" content="' . (is_null($title_prefix) ? '' : $title_prefix) .
|
|
||||||
(is_null($this->metadata->opengraph->title) ?
|
|
||||||
localize("content.default.opengraph.title") :
|
|
||||||
localize_private($this->metadata->opengraph->title, $this->strings, false)) .
|
|
||||||
'" /><meta property="og:description" content="' . (is_null($this->metadata->opengraph->description) ?
|
|
||||||
localize("content.default.opengraph.description") :
|
|
||||||
localize_private($this->metadata->opengraph->description, $this->strings, false)) .
|
|
||||||
'" /><meta property="og:type" content="' . (is_null($type_override) ?
|
|
||||||
(is_null($this->metadata->opengraph->type) ? "website" : $this->metadata->opengraph->type)
|
|
||||||
: $type_override) . '" /><meta property="og:url" content="' .
|
|
||||||
(is_null($url_override) ? (is_null($this->metadata->opengraph->url) ?
|
|
||||||
$host_uri : $this->metadata->opengraph->url) : $url_override) .
|
|
||||||
'" /><meta property="og:image" content="' . $final_image_uri . '"/>';
|
|
||||||
//<meta property="og:image:type" content="image/png"/>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ComposerContentMetadata {
|
|
||||||
public string $title;
|
|
||||||
public string $description;
|
|
||||||
public string $template;
|
|
||||||
public ComposerContentMetadataHead $head;
|
|
||||||
public ComposerContentMetadataOpengraph $opengraph;
|
|
||||||
public ?ComposerContentMetadataArticle $article;
|
|
||||||
|
|
||||||
function __construct(string $title, string $description, string $template, ComposerContentMetadataHead $head,
|
|
||||||
ComposerContentMetadataOpengraph $opengraph, ?ComposerContentMetadataArticle $article) {
|
|
||||||
$this->title = $title;
|
|
||||||
$this->description = $description;
|
|
||||||
$this->template = $template;
|
|
||||||
$this->head = $head;
|
|
||||||
$this->opengraph = $opengraph;
|
|
||||||
$this->article = $article;
|
|
||||||
|
|
||||||
// Safety checks.
|
|
||||||
if($this->template == ComposerTemplates::ARTICLE_LEGACY && is_null($this->article)) {
|
|
||||||
$this->article = ComposerContentMetadataArticle::from_json([]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static function from_json(array $json_data) : ComposerContentMetadata {
|
|
||||||
return new ComposerContentMetadata(
|
|
||||||
key_exists("title", $json_data) ? $json_data["title"] : "",
|
|
||||||
key_exists("description", $json_data) ? $json_data["description"] : "",
|
|
||||||
key_exists("template", $json_data) ? $json_data["template"] : "",
|
|
||||||
ComposerContentMetadataHead::from_json(
|
|
||||||
key_exists("head", $json_data) ? $json_data["head"] : array()
|
|
||||||
),
|
|
||||||
ComposerContentMetadataOpengraph::from_json(
|
|
||||||
key_exists("opengraph", $json_data) ? $json_data["opengraph"] : array()
|
|
||||||
),
|
|
||||||
key_exists("article", $json_data) ?
|
|
||||||
ComposerContentMetadataArticle::from_json($json_data["article"]) : null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function apply_template(ComposerContent $content_root, string $inner_html) : string {
|
|
||||||
switch($this->template) {
|
|
||||||
case ComposerTemplates::ARTICLE_LEGACY:
|
|
||||||
// FIXME: Is this even used anymore ?!?
|
|
||||||
$inner_html = '<div class="card p-0 mx-0"><div class="px-card py-10 border-bottom px-20">' .
|
|
||||||
'<div class="container-fluid"><h2 class="card-title font-size-18 m-0">' .
|
|
||||||
'<i class="' . $this->article->icon . '"></i> ' .
|
|
||||||
localize_private($this->article->title, $content_root->strings, false) .
|
|
||||||
'<span class="card-title font-size-18 m-0 text-super-muted float-right hidden-xs-and-down">' .
|
|
||||||
localize_private($this->article->subtitle, $content_root->strings, false) .
|
|
||||||
'</span></h2></div></div>' .
|
|
||||||
'<article id="content-item-container" class="py-01 pb-0 bg-light-lm rounded-bottom px-0 bg-very-dark title-bkgd">' .
|
|
||||||
$inner_html . '</article>' .
|
|
||||||
'<div class="px-20 py-10 bg-light-lm bg-dark-dm rounded-bottom border-top">' .
|
|
||||||
'<div class="content-tag-container"><i class="fad fa-tags"></i>';
|
|
||||||
|
|
||||||
if(sizeof($this->article->tags) > 0) {
|
|
||||||
foreach($this->article->tags as $tag) {
|
|
||||||
$inner_html .= '<a href="'.l10n_url_abs("/content/?tags=" . $tag .
|
|
||||||
'" class="content-tag">#' . $tag . '</a>');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$inner_html .= '<i>' . localize("content.error.message.data.no.tags") . '</i>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$inner_html .= '</div></div></div>';
|
|
||||||
break;
|
|
||||||
case ComposerTemplates::GENERIC_PROJECT_README:
|
|
||||||
// Prepending the heading
|
|
||||||
$inner_html = getMainHeader(
|
|
||||||
localize_private($this->article->title, $content_root->strings, false),
|
|
||||||
$this->article->icon,
|
|
||||||
localize_private($this->article->subtitle, $content_root->strings, false),
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
3,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
) . '<div class="px-xxs">' . $inner_html . '</div>';
|
|
||||||
|
|
||||||
// Grabbing the DOM for inside the tags bar
|
|
||||||
$_template_gpr_tags_dom = '<i class="fad fa-tags t-size-10"></i>';
|
|
||||||
if(sizeof($this->article->tags) > 0) {
|
|
||||||
foreach($this->article->tags as $tag) {
|
|
||||||
$_template_gpr_tags_dom .= '<a href="'.l10n_url_abs("/content/?tags=" . $tag .
|
|
||||||
'" class="ml-xs d-inline-block">#' . $tag . '</a>');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$_template_gpr_tags_dom .= '<i>' . localize("content.error.message.data.no.tags") . '</i>';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Printing the tags bar
|
|
||||||
$inner_html .= getMainHeader(
|
|
||||||
$_template_gpr_tags_dom,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
null,
|
|
||||||
6,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case ComposerTemplates::RAW:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $inner_html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ComposerContentMetadataHead {
|
|
||||||
public ?string $title;
|
|
||||||
public ?string $description;
|
|
||||||
|
|
||||||
function __construct(?string $title, ?string $description) {
|
|
||||||
$this->title = $title;
|
|
||||||
$this->description = $description;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function from_json(array $json_data) : ComposerContentMetadataHead {
|
|
||||||
return new ComposerContentMetadataHead(
|
|
||||||
key_exists("title", $json_data) ? $json_data["title"] : null,
|
|
||||||
key_exists("description", $json_data) ? $json_data["description"] : null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ComposerContentMetadataOpengraph {
|
|
||||||
public ?string $title;
|
|
||||||
public ?string $description;
|
|
||||||
public ?string $type;
|
|
||||||
public ?string $url;
|
|
||||||
public ?string $image;
|
|
||||||
public ?string $image_type;
|
|
||||||
|
|
||||||
function __construct(?string $title, ?string $description, ?string $type, ?string $url, ?string $image,
|
|
||||||
?string $image_type) {
|
|
||||||
$this->title = $title;
|
|
||||||
$this->description = $description;
|
|
||||||
$this->type = $type;
|
|
||||||
$this->url = $url;
|
|
||||||
$this->image = $image;
|
|
||||||
$this->image_type = $image_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function from_json(array $json_data) : ComposerContentMetadataOpengraph {
|
|
||||||
return new ComposerContentMetadataOpengraph(
|
|
||||||
key_exists("title", $json_data) ? $json_data["title"] : null,
|
|
||||||
key_exists("description", $json_data) ? $json_data["description"] : null,
|
|
||||||
key_exists("type", $json_data) ? $json_data["type"] : null,
|
|
||||||
key_exists("url", $json_data) ? $json_data["url"] : null,
|
|
||||||
key_exists("image", $json_data) ? $json_data["image"] : null,
|
|
||||||
key_exists("image_type", $json_data) ? $json_data["image_type"] : null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ComposerContentMetadataArticle {
|
|
||||||
public string $icon;
|
|
||||||
public string $title;
|
|
||||||
public string $subtitle;
|
|
||||||
public array $tags;
|
|
||||||
|
|
||||||
function __construct(string $icon, string $title, string $subtitle, array $tags) {
|
|
||||||
$this->icon = $icon;
|
|
||||||
$this->title = $title;
|
|
||||||
$this->subtitle = $subtitle;
|
|
||||||
$this->tags = $tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function from_json(array $json_data) : ComposerContentMetadataArticle {
|
|
||||||
return new ComposerContentMetadataArticle(
|
|
||||||
key_exists("icon", $json_data) ? $json_data["icon"] : "fad fa-question",
|
|
||||||
key_exists("title", $json_data) ?
|
|
||||||
$json_data["title"] : '<i>'.localize("content.error.message.data.no.title").'</i>',
|
|
||||||
key_exists("subtitle", $json_data) ? $json_data["subtitle"] : '',
|
|
||||||
key_exists("tags", $json_data) ? $json_data["tags"] : [],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __get($property) {
|
|
||||||
return is_null($this->$property) ? "" : $this->$property;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ComposerElement {
|
|
||||||
// Global parameters
|
|
||||||
private string $type;
|
|
||||||
private ?array $modifiers;
|
|
||||||
private ?string $link;
|
|
||||||
|
|
||||||
// Any direct element-container
|
|
||||||
private ?array $parts;
|
|
||||||
|
|
||||||
// Any direct text-container
|
|
||||||
private ?string $content;
|
|
||||||
private bool $localize;
|
|
||||||
|
|
||||||
// Generic modifier values
|
|
||||||
private ?int $padding;
|
|
||||||
private ?int $margin;
|
|
||||||
|
|
||||||
// Spacer's size
|
|
||||||
private ?int $size;
|
|
||||||
|
|
||||||
// Table's parameters
|
|
||||||
private ?array $head;
|
|
||||||
private ?array $body;
|
|
||||||
private int $colspan;
|
|
||||||
private int $rowspan;
|
|
||||||
|
|
||||||
// Paragraph and code's parameters
|
|
||||||
private ?int $indent;
|
|
||||||
|
|
||||||
// Code's parameters
|
|
||||||
private ?array $code;
|
|
||||||
private ?string $codeLanguage;
|
|
||||||
private bool $codeCopyable;
|
|
||||||
|
|
||||||
// Button's parameters
|
|
||||||
private ?string $color;
|
|
||||||
|
|
||||||
// Image and video's parameters
|
|
||||||
private ?string $source;
|
|
||||||
private ?string $thumbnail;
|
|
||||||
|
|
||||||
// Galleries parameters
|
|
||||||
private array $images;
|
|
||||||
|
|
||||||
// Screen readers parameters
|
|
||||||
private ?string $srTitle;
|
|
||||||
|
|
||||||
function __construct(string $type, ?array $modifiers, ?string $link, ?array $parts, ?string $content,
|
|
||||||
bool $localize, ?int $padding, ?int $margin, ?int $size, ?array $head, ?array $body,
|
|
||||||
int $colspan, int $rowspan, ?int $indent, ?array $code, ?string $codeLanguage,
|
|
||||||
bool $codeCopyable, ?string $color, ?string $source, ?string $thumbnail, ?array $images,
|
|
||||||
?string $srTitle) {
|
|
||||||
$this->type = $type;
|
|
||||||
$this->modifiers = $modifiers;
|
|
||||||
$this->link = $link;
|
|
||||||
$this->parts = $parts;
|
|
||||||
$this->content = $content;
|
|
||||||
$this->localize = $localize;
|
|
||||||
$this->padding = $padding;
|
|
||||||
$this->margin = $margin;
|
|
||||||
$this->size = $size;
|
|
||||||
$this->head = ComposerElement::from_json_array($head);
|
|
||||||
if(is_null($body)) {
|
|
||||||
$this->body = array();
|
|
||||||
} else {
|
|
||||||
$this->body = array_fill(0, sizeof($body), []);
|
|
||||||
for($body_row_index = 0; $body_row_index < sizeof($body); $body_row_index++) {
|
|
||||||
$this->body[$body_row_index] = ComposerElement::from_json_array($body[$body_row_index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->colspan = $colspan;
|
|
||||||
$this->rowspan = $rowspan;
|
|
||||||
$this->indent = $indent;
|
|
||||||
$this->code = $code;
|
|
||||||
$this->codeLanguage = $codeLanguage;
|
|
||||||
$this->codeCopyable = $codeCopyable;
|
|
||||||
$this->color = $color;
|
|
||||||
$this->source = $source;
|
|
||||||
$this->thumbnail = $thumbnail;
|
|
||||||
if(is_null($images)) {
|
|
||||||
$this->images = array();
|
|
||||||
} else {
|
|
||||||
$this->images = $images;
|
|
||||||
}
|
|
||||||
$this->srTitle = $srTitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function from_json_array(?array $json_dataArray) : array {
|
|
||||||
$parts = array();
|
|
||||||
if(!is_null($json_dataArray)) {
|
|
||||||
foreach($json_dataArray as $part) {
|
|
||||||
$parts[] = ComposerElement::from_json($part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $parts;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function from_json(array $json_data) : ComposerElement {
|
|
||||||
return new ComposerElement(
|
|
||||||
key_exists("type", $json_data) ? $json_data["type"] : ComposerElementTypes::UNSET,
|
|
||||||
key_exists("modifiers", $json_data) ? $json_data["modifiers"] : [],
|
|
||||||
key_exists("link", $json_data) ? $json_data["link"] : null,
|
|
||||||
key_exists("parts", $json_data) ? ComposerElement::from_json_array($json_data["parts"]) : null,
|
|
||||||
key_exists("content", $json_data) ? $json_data["content"] : null,
|
|
||||||
key_exists("localize", $json_data) ? $json_data["localize"] : true,
|
|
||||||
key_exists("padding", $json_data) ? $json_data["padding"] : null,
|
|
||||||
key_exists("margin", $json_data) ? $json_data["margin"] : null,
|
|
||||||
key_exists("size", $json_data) ? $json_data["size"] : null,
|
|
||||||
key_exists("head", $json_data) ? $json_data["head"] : null,
|
|
||||||
key_exists("body", $json_data) ? $json_data["body"] : null,
|
|
||||||
key_exists("colspan", $json_data) ? $json_data["colspan"] : 1,
|
|
||||||
key_exists("rowspan", $json_data) ? $json_data["rowspan"] : 1,
|
|
||||||
key_exists("indent", $json_data) ? $json_data["indent"] : null,
|
|
||||||
key_exists("code", $json_data) ? $json_data["code"] : null,
|
|
||||||
key_exists("language", $json_data) ? $json_data["language"] : null,
|
|
||||||
key_exists("copyable", $json_data) ? $json_data["copyable"] : false,
|
|
||||||
key_exists("color", $json_data) ? $json_data["color"] : null,
|
|
||||||
key_exists("source", $json_data) ? $json_data["source"] : null,
|
|
||||||
key_exists("thumbnail", $json_data) ? $json_data["thumbnail"] : null,
|
|
||||||
key_exists("images", $json_data) ? $json_data["images"] : null,
|
|
||||||
key_exists("sr_title", $json_data) ? $json_data["sr_title"] : null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes the "content" and "parts" class' variables and returns their interpreted content as HTML.
|
|
||||||
* @param ComposerContent $content_root The content in which this element is contained.
|
|
||||||
* @param bool $doLocalization Whether the "content" variable should be processed to return localized text.
|
|
||||||
* @param bool $doSubElements Whether the "parts" variable should be processed to return localized text.
|
|
||||||
* @param bool $stopIfLocalized Whether the process should return if some text was in the "content" variable.
|
|
||||||
* @return string The interpreted content as HTML.
|
|
||||||
*/
|
|
||||||
private function get_inner_html(ComposerContent $content_root, bool $doLocalization = true,
|
|
||||||
bool $doSubElements = true, bool $stopIfLocalized = true) : string {
|
|
||||||
global $LANG_FALLBACK_KEY_PREFIX;
|
|
||||||
|
|
||||||
$htmlCode = "";
|
|
||||||
$wasTextLocalized = false;
|
|
||||||
|
|
||||||
if($doLocalization) {
|
|
||||||
// Checking if "content" was declared.
|
|
||||||
if(is_null($this->content) && !$doSubElements) {
|
|
||||||
return "<p>error.no.inner.content</p>";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checking if there is something to process.
|
|
||||||
if(!empty($this->content)) {
|
|
||||||
$wasTextLocalized = true;
|
|
||||||
|
|
||||||
if(!$this->localize) {
|
|
||||||
$htmlCode .= $this->content;
|
|
||||||
} else {
|
|
||||||
// We can now localize the content key.
|
|
||||||
$htmlCode .= localize_private($this->content, $content_root->strings, true,
|
|
||||||
$LANG_FALLBACK_KEY_PREFIX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checking for early stop.
|
|
||||||
if($wasTextLocalized && $stopIfLocalized) {
|
|
||||||
return $htmlCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($doSubElements) {
|
|
||||||
// Checking if "parts" was declared.
|
|
||||||
if(is_null($this->parts)) {
|
|
||||||
if(!$wasTextLocalized) {
|
|
||||||
$htmlCode = "<p>error.no.inner.parts</p>";
|
|
||||||
}
|
|
||||||
return $htmlCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Appending each sub-element.
|
|
||||||
foreach($this->parts as $subElement) {
|
|
||||||
/** @var ComposerElement $subElement */
|
|
||||||
$htmlCode .= $subElement->get_html($content_root);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $htmlCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function get_inner_html_elements(ComposerContent $content_root) : string {
|
|
||||||
return $this->get_inner_html($content_root, false, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function get_inner_html_text(ComposerContent $content_root) : string {
|
|
||||||
return $this->get_inner_html($content_root, true, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function get_modifiers_classes() : string {
|
|
||||||
if(!is_null($this->modifiers)) {
|
|
||||||
$classes = "";
|
|
||||||
|
|
||||||
// Combining classes.
|
|
||||||
foreach($this->modifiers as $modifier) {
|
|
||||||
/** @var string $modifier */
|
|
||||||
$classes .= ComposerElementModifiers::get_classes_from_key($modifier) . ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removing redundant and useless spaces.
|
|
||||||
return preg_replace('/\s+/', ' ', trim($classes));
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes the element and returns its interpreted form as HTML.
|
|
||||||
* @param ComposerContent $content_root The content in which this element is contained.
|
|
||||||
* @return string The interpreted element as HTML.
|
|
||||||
*/
|
|
||||||
public function get_html(ComposerContent $content_root) : string {
|
|
||||||
$htmlCode = "";
|
|
||||||
|
|
||||||
// Setting up the link and its title if needed.
|
|
||||||
if(!is_null($this->link)) {
|
|
||||||
$htmlCode .= '<a href="' . $this->link . '"' .
|
|
||||||
($this->type == ComposerElementTypes::BUTTON ? 'class="bland-link button-link"' : '') .'>';
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($this->type) {
|
|
||||||
case ComposerElementTypes::UNSET:
|
|
||||||
$htmlCode .= "<p>error.element.type.unset !</p>";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::RAW:
|
|
||||||
$htmlCode .= $this->get_inner_html($content_root);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::H1:
|
|
||||||
$htmlCode .= getMainHeader(
|
|
||||||
$this->get_inner_html($content_root),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
!ComposerElementModifiers::is_modifier_in_modifiers(
|
|
||||||
ComposerElementModifiers::GENERIC_MARGIN_NO_TOP, $this->modifiers),
|
|
||||||
"bkgd-math", // heading-dyn-width-1
|
|
||||||
3,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::H2:
|
|
||||||
case ComposerElementTypes::H3:
|
|
||||||
// Defining the text's indent level.
|
|
||||||
$_paragraph_ident_level = is_null($this->indent) ? 0 : $this->indent;
|
|
||||||
|
|
||||||
// Defining the text's size.
|
|
||||||
$_headingFontSize = ($this->type == ComposerElementTypes::H3 ? '18' : (
|
|
||||||
$this->type == ComposerElementTypes::H2 ? '20' : '22'
|
|
||||||
));
|
|
||||||
|
|
||||||
// Composing heading.
|
|
||||||
$htmlCode .= '<' . strtolower($this->type) . ' class="font-weight-semi-bold font-size-' .
|
|
||||||
$_headingFontSize . ' m-0 ml-md-' . ($_paragraph_ident_level * 5) . '">' . $this->get_inner_html($content_root) . '</' . strtolower($this->type) .
|
|
||||||
'>';
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::PARAGRAPH:
|
|
||||||
// Defining the text's indent level.
|
|
||||||
// TODO: Join with others
|
|
||||||
$_paragraph_ident_level = is_null($this->indent) ? 0 : $this->indent;
|
|
||||||
$_paragraph_ident_level = $_paragraph_ident_level < 0 ? 0 : $_paragraph_ident_level;
|
|
||||||
$_paragraph_ident_level = $_paragraph_ident_level > 5 ? 5 : $_paragraph_ident_level;
|
|
||||||
$_paragraph_ident_level = (["", "ml-xs", "ml-s", "ml-m", "ml-l", "ml-xl"])[$_paragraph_ident_level];
|
|
||||||
|
|
||||||
// Calculating the vertical margin modifiers
|
|
||||||
$_paragraph_no_margin_top = ComposerElementModifiers::is_modifier_in_modifiers(
|
|
||||||
ComposerElementModifiers::GENERIC_MARGIN_NO_TOP, $this->modifiers);
|
|
||||||
if($_paragraph_no_margin_top) {
|
|
||||||
$_paragraph_margin_modifier = '';
|
|
||||||
} else {
|
|
||||||
$_paragraph_margin_modifier = 'mt-xs ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adding other tags manually
|
|
||||||
// FIXME: Use the standard functions FFS...
|
|
||||||
$_paragraph_margin_modifier .= (
|
|
||||||
ComposerElementModifiers::is_modifier_in_modifiers(
|
|
||||||
ComposerElementModifiers::GENERIC_BOLD, $this->modifiers)
|
|
||||||
) ? "t-w-500 " : "";
|
|
||||||
|
|
||||||
// Fixes some "overflowing" issue when indent is bigger than 2.
|
|
||||||
$_paragraph_margin_modifier .= "mr-s ";
|
|
||||||
|
|
||||||
// Composing the paragraph
|
|
||||||
$htmlCode .= '<p class="' . $_paragraph_margin_modifier . $_paragraph_ident_level .
|
|
||||||
'">' . $this->get_inner_html($content_root) . '</p>';
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::BUTTON:
|
|
||||||
// Composing the button.
|
|
||||||
$htmlCode .= '<button class="p-mxs r-s border b-light t-nowrap ' . (is_null($this->color) ? '' : 'btn-' . $this->color . ' ') .
|
|
||||||
$this->get_modifiers_classes() . '">' . $this->get_inner_html($content_root) . '</button>';
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::CODE:
|
|
||||||
// Defining the code's indent level.
|
|
||||||
$_paragraph_ident_level = is_null($this->indent) ? 0 : $this->indent;
|
|
||||||
|
|
||||||
// Defining the highlight language.
|
|
||||||
$_language_class = is_null($this->codeLanguage) ? "nohighlight" : "language-" . $this->codeLanguage;
|
|
||||||
|
|
||||||
// Parent container with a relative position to handle the wedge when the code itself is
|
|
||||||
// horizontally scrollable.
|
|
||||||
$htmlCode .= '<div class="p-relative">';
|
|
||||||
|
|
||||||
// Opening the code element.
|
|
||||||
// Note: The "mt-10" may have to be removed if it clashes with 'no-margin-top' !
|
|
||||||
$htmlCode .= '<div class="code ' . $this->get_modifiers_classes() .
|
|
||||||
' mt-10 position-relative ml-md-' . ($_paragraph_ident_level * 5) . ' ' . $_language_class . '">';
|
|
||||||
|
|
||||||
// Adding code lines.
|
|
||||||
if(!is_null($this->code)) {
|
|
||||||
foreach($this->code as $code_line) {
|
|
||||||
//$htmlCode .= htmlspecialchars($code_line) . '<br>'; // Old method (Not compatible with hljs)
|
|
||||||
$htmlCode .= '<span class="code-line t-nowrap">' .
|
|
||||||
str_replace(" ", " ", htmlspecialchars($code_line)) .
|
|
||||||
'</span><br>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->codeCopyable) {
|
|
||||||
//border-t-0 border-r-0
|
|
||||||
$htmlCode .= '<div class="wedge wedge-tr primary js-code-copy border rbl-m rtr-s p-xxxs px-xs" hidden>';
|
|
||||||
$htmlCode .= '<i class="fad fa-copy"></i> ';
|
|
||||||
$htmlCode .= '<span>' . localize("common.action.copy") . '</span>';
|
|
||||||
$htmlCode .= '<span hidden>' . localize("common.action.copied") . '</span>';
|
|
||||||
$htmlCode .= '</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Closing code element.
|
|
||||||
$htmlCode .= '</div>';
|
|
||||||
|
|
||||||
// Closing super container.
|
|
||||||
$htmlCode .= '</div>';
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::HR:
|
|
||||||
// Getting the modifiers' classes
|
|
||||||
$_hr_classes = $this->get_modifiers_classes();
|
|
||||||
|
|
||||||
// Composing the element.
|
|
||||||
if(empty($_hr_classes)) {
|
|
||||||
$htmlCode .= '<div class="sidebar-divider"></div>';
|
|
||||||
} else {
|
|
||||||
$htmlCode .= '<hr class="' . $_hr_classes . '">';
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::CONTAINER:
|
|
||||||
// Defining the padding's size.
|
|
||||||
$_container_padding = is_null($this->padding) ? 0 : $this->padding;
|
|
||||||
$_container_padding = $_container_padding < 0 ? 0 : $_container_padding;
|
|
||||||
$_container_padding = $_container_padding > 5 ? 5 : $_container_padding;
|
|
||||||
$_container_padding = (["", "p-xs ", "p-s ", "p-m ", "p-l ", "p-xl "])[$_container_padding];
|
|
||||||
|
|
||||||
// Composing the container.
|
|
||||||
$htmlCode .= '<div class="' . $_container_padding . $this->get_modifiers_classes() .
|
|
||||||
'">' . $this->get_inner_html($content_root) . '</div>';
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::COLLAPSE:
|
|
||||||
// Composing collapse.
|
|
||||||
$htmlCode .= '<details class="collapse-panel w-full' .
|
|
||||||
(ComposerElementModifiers::is_modifier_in_modifiers(
|
|
||||||
ComposerElementModifiers::GENERIC_MARGIN_NO_TOP, $this->modifiers
|
|
||||||
) ? ' ' . ComposerElementModifiers::get_modifier_classes(
|
|
||||||
ComposerElementModifiers::GENERIC_MARGIN_NO_TOP) : '') . '" ' .
|
|
||||||
(ComposerElementModifiers::is_modifier_in_modifiers(
|
|
||||||
ComposerElementModifiers::DETAILS_CLOSED, $this->modifiers
|
|
||||||
) ? "closed" : "open") . '>';
|
|
||||||
|
|
||||||
$htmlCode .= '<summary class="collapse-header p-10 px-15 text-truncate without-arrow' .
|
|
||||||
(ComposerElementModifiers::is_modifier_in_modifiers(
|
|
||||||
ComposerElementModifiers::DETAILS_NO_ROUNDING, $this->modifiers
|
|
||||||
) ? ' rounded-0' : '') . ' border-left-0 border-right-0">';
|
|
||||||
|
|
||||||
$_title = "title";
|
|
||||||
$_subtitle = "subtitle";
|
|
||||||
|
|
||||||
$htmlCode .= '<h4 class="font-size-16 m-0 align-middle no-select">' .
|
|
||||||
'<i class="fad fa-angle-down hidden-collapse-closed font-size-24"></i>' .
|
|
||||||
'<i class="fad fa-angle-up hidden-collapse-open font-size-24"></i>' .
|
|
||||||
'<span class="font-weight-semi-bold align-top"> '.$_title.
|
|
||||||
'<span class="ml-20 text-muted">'.$_subtitle.'</span></span></h4></summary>';
|
|
||||||
|
|
||||||
$htmlCode .= '<div class="collapse-content' .
|
|
||||||
(ComposerElementModifiers::is_modifier_in_modifiers(
|
|
||||||
ComposerElementModifiers::CONTAINER_SCROLL_HORIZONTAL, $this->modifiers
|
|
||||||
) ? " " . ComposerElementModifiers::get_modifier_classes(
|
|
||||||
ComposerElementModifiers::CONTAINER_SCROLL_HORIZONTAL ) : "") .
|
|
||||||
(ComposerElementModifiers::is_modifier_in_modifiers(
|
|
||||||
ComposerElementModifiers::GENERIC_PADDING_NONE, $this->modifiers
|
|
||||||
) ? " p-0 py-01" : "") .
|
|
||||||
(ComposerElementModifiers::is_modifier_in_modifiers(
|
|
||||||
ComposerElementModifiers::DETAILS_NO_ROUNDING, $this->modifiers
|
|
||||||
) ? " rounded-0" : "") . ' border-0 border-bottom">' .
|
|
||||||
$this->get_inner_html($content_root) . '</div></details>';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::SPACER:
|
|
||||||
// Defining the spacer's size.
|
|
||||||
$_spacer_size = is_null($this->size) ? 1 : $this->size;
|
|
||||||
|
|
||||||
// Composing spacer.
|
|
||||||
$htmlCode .= '<div class="m-0 pt-'.($_spacer_size*5).' pb-md-'.($_spacer_size*5).'"></div>';
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::IMAGE:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::TABLE:
|
|
||||||
// Composing table.
|
|
||||||
$htmlCode .= '<div class="overflow-x-auto">';
|
|
||||||
$htmlCode .= '<table class="' . $this->get_modifiers_classes() . '">';
|
|
||||||
|
|
||||||
if(!is_null($this->head)) {
|
|
||||||
$htmlCode .= '<thead><tr>';
|
|
||||||
foreach($this->head as $head_element) {
|
|
||||||
/** @var ComposerElement $head_element */
|
|
||||||
$htmlCode .= '<th>' . $head_element->get_html($content_root) . '</th>';
|
|
||||||
}
|
|
||||||
$htmlCode .= '</tr></thead>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_null($this->body)) {
|
|
||||||
$htmlCode .= '<tbody>';
|
|
||||||
|
|
||||||
for($body_row_index = 0; $body_row_index < sizeof($this->body); $body_row_index++) {
|
|
||||||
$htmlCode .= '<tr>';
|
|
||||||
|
|
||||||
foreach($this->body[$body_row_index] as $body_cell) {
|
|
||||||
/** @var ComposerElement $body_cell */
|
|
||||||
$htmlCode .= '<td' . ($body_cell->colspan > 1 ? ' colspan="' . $body_cell->colspan . '"' : '') .
|
|
||||||
($body_cell->rowspan > 1 ? ' rowspan="' . $body_cell->rowspan . '"' : '') . '>' .
|
|
||||||
$body_cell->get_html($content_root) . '</td>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$htmlCode .= '</tr>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$htmlCode .= '</tbody>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$htmlCode .= '</table>';
|
|
||||||
$htmlCode .= "</div>";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::GRID:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::GALLERY:
|
|
||||||
if(!is_null($this->srTitle)) {
|
|
||||||
$htmlCode .= '<section class="splide border bkgd-math" aria-label="' . $this->srTitle . '">';
|
|
||||||
$htmlCode .= '<h2 id="carousel-heading">' . $this->srTitle . '</h2>';
|
|
||||||
} else {
|
|
||||||
$htmlCode .= '<section class="splide border bkgd-math">';
|
|
||||||
}
|
|
||||||
|
|
||||||
$htmlCode .= '<div class="splide__track">';
|
|
||||||
$htmlCode .= '<ul class="splide__list">';
|
|
||||||
|
|
||||||
foreach($this->images as $galleryImageUrl) {
|
|
||||||
$htmlCode .= '<li class="splide__slide"><img src="'.$galleryImageUrl.'"></li>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$htmlCode .= '</ul></div></section>';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ComposerElementTypes::VIDEO:
|
|
||||||
// Composing the video element
|
|
||||||
$htmlCode .= '<video ' . (is_null($this->source) ? '' : 'src="' . $this->source . '" ') .
|
|
||||||
'class="' . $this->get_modifiers_classes() . ' r-l" ' .
|
|
||||||
(is_null($this->thumbnail) ? '' : 'poster="' . $this->thumbnail . '" ') .
|
|
||||||
'controls muted></video>';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
$htmlCode .= "<p>error.unknown !</p>";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_null($this->link)) {
|
|
||||||
$htmlCode .= '</a>';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $htmlCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Generic functions
|
|
||||||
function get_content_error(string $error_title_key, string $error_description_key) : ?ComposerContent {
|
|
||||||
// FIXME: Make this non-nullable !!!
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function load_content_by_file_path(string $file_path) : ?ComposerContent {
|
|
||||||
$content_json_data = json_decode(file_get_contents($file_path), true);
|
|
||||||
if(is_null($content_json_data)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return ComposerContent::from_json($content_json_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function load_content_by_id(string $content_id) : ?ComposerContent {
|
|
||||||
// FIXME: Find another way to get `$config_dir_content` here !
|
|
||||||
global $config_dir_content;
|
|
||||||
$content_file_path = get_content_file_path($config_dir_content, $content_id);
|
|
||||||
|
|
||||||
if(is_null($content_file_path)) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return load_content_by_file_path($content_file_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
@@ -1,233 +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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Importing required scripts.
|
|
||||||
include_once 'commons/langs.php';
|
|
||||||
|
|
||||||
enum EContentDisplayType {
|
|
||||||
/** No display type have or could be determined. */
|
|
||||||
case NONE;
|
|
||||||
|
|
||||||
/** The content index should be shown */
|
|
||||||
case SEARCH;
|
|
||||||
|
|
||||||
/** The page for a specific piece of content should be shown */
|
|
||||||
case DISPLAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ContentIndexEntry {
|
|
||||||
public string $id;
|
|
||||||
public ?array $title;
|
|
||||||
public ?array $preamble;
|
|
||||||
public string $image;
|
|
||||||
public array $tags;
|
|
||||||
public int $priority;
|
|
||||||
|
|
||||||
function __construct(string $id, ?array $title, ?array $preamble, ?string $image, ?array $tags, ?int $priority) {
|
|
||||||
$this->id = $id;
|
|
||||||
$this->title = $title;
|
|
||||||
$this->preamble = $preamble;
|
|
||||||
$this->image = is_null($image) ? "/resources/NibblePoker/images/placeholder.png" : $image;
|
|
||||||
$this->tags = is_null($tags) ? [] : $tags;
|
|
||||||
$this->priority = is_null($priority) ? 0 : $priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function from_json(array $json_data): ?ContentIndexEntry {
|
|
||||||
if(!key_exists("id", $json_data)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new ContentIndexEntry(
|
|
||||||
$json_data["id"],
|
|
||||||
key_exists("title", $json_data) ? $json_data["title"] : null,
|
|
||||||
key_exists("preamble", $json_data) ? $json_data["preamble"] : null,
|
|
||||||
key_exists("image", $json_data) ? $json_data["image"] : null,
|
|
||||||
key_exists("tags", $json_data) ? $json_data["tags"] : null,
|
|
||||||
key_exists("priority", $json_data) ? $json_data["priority"] : null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ContentManager {
|
|
||||||
public EContentDisplayType $displayType;
|
|
||||||
public bool $hasError;
|
|
||||||
public string $errorMessageKey;
|
|
||||||
public ?string $requestedId;
|
|
||||||
public ?array $requestedTags;
|
|
||||||
public ?array $rootIndexEntries;
|
|
||||||
public ?string $contentFilepath;
|
|
||||||
|
|
||||||
function __construct(string $contentRootPath, string $requestedUrl, ?string $urlTags) {
|
|
||||||
// Preparing default values
|
|
||||||
$this->displayType = EContentDisplayType::NONE;
|
|
||||||
$this->hasError = false;
|
|
||||||
$this->errorMessageKey = "content.error.message.none";
|
|
||||||
$this->requestedId = NULL;
|
|
||||||
$this->requestedTags = NULL;
|
|
||||||
$this->rootIndexEntries = NULL;
|
|
||||||
$this->contentFilepath = NULL;
|
|
||||||
|
|
||||||
// Doing some standard things
|
|
||||||
$this->processUrl($requestedUrl, $urlTags);
|
|
||||||
if(!$this->hasError) {
|
|
||||||
if($this->displayType == EContentDisplayType::SEARCH) {
|
|
||||||
$this->loadRootIndex(realpath($contentRootPath . "/index.json"));
|
|
||||||
} 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(
|
|
||||||
"?",
|
|
||||||
explode("#", preg_replace("^/(content|tools)^", "", $requestedUrl))[0]
|
|
||||||
)[0];
|
|
||||||
|
|
||||||
if(strcmp($requestedUrlPart, "/") == 0) {
|
|
||||||
$this->displayType = EContentDisplayType::SEARCH;
|
|
||||||
|
|
||||||
if(is_null($urlTags)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strlen($urlTags) > 256) {
|
|
||||||
$this->hasError = true;
|
|
||||||
$this->errorMessageKey = "content.error.message.tags.length";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$explodedTags = explode(";", $urlTags);
|
|
||||||
$this->requestedTags = count($explodedTags) > 0 ? array() : $this->requestedTags;
|
|
||||||
for($i = 0; $i < count($explodedTags); $i++) {
|
|
||||||
if(strlen($explodedTags[$i]) > 0) {
|
|
||||||
if(ctype_alnum($explodedTags[$i])) {
|
|
||||||
$this->requestedTags[] = $explodedTags[$i];
|
|
||||||
} else {
|
|
||||||
$this->hasError = true;
|
|
||||||
$this->errorMessageKey = "content.error.message.tags.alphanumeric";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$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);
|
|
||||||
$jsonContent = json_decode($rawJsonContent, true);
|
|
||||||
unset($rawJsonContent);
|
|
||||||
|
|
||||||
$this->rootIndexEntries = array();
|
|
||||||
for($i = 0; $i < count($jsonContent); $i++) {
|
|
||||||
// Filtering out unwanted entries and putting their data in a proper class.
|
|
||||||
if(!is_null($this->requestedTags)) {
|
|
||||||
if(count(array_intersect($jsonContent[$i]["tags"], $this->requestedTags)) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//if(count(array_intersect($jsonContent[$i]["tags"], $this->requestedTags)) == count($this->requestedTags)) {}
|
|
||||||
|
|
||||||
// Parsing the raw data into a structure.
|
|
||||||
$newIndexEntry = ContentIndexEntry::from_json($jsonContent[$i]);
|
|
||||||
|
|
||||||
// Checking if it was parsed properly
|
|
||||||
if(is_null($newIndexEntry)) {
|
|
||||||
$this->hasError = true;
|
|
||||||
$this->errorMessageKey = "content.error.message.failed.structure";
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
$this->rootIndexEntries[] = $newIndexEntry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($jsonContent);
|
|
||||||
|
|
||||||
// Checking if we found any content for the user.
|
|
||||||
if(count($this->rootIndexEntries) == 0) {
|
|
||||||
// No relevant article/page were found for the given tags.
|
|
||||||
$this->hasError = true;
|
|
||||||
$this->errorMessageKey = "content.error.message.detect.empty";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sorting entries based on their priority
|
|
||||||
usort($this->rootIndexEntries, function(ContentIndexEntry $a, ContentIndexEntry $b) {
|
|
||||||
if($a->priority == $b->priority) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ($a->priority > $b->priority) ? -1 : 1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 $contentRootPath
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function prepareContentFilePath(string $contentRootPath): void {
|
|
||||||
// Sanitizing the requested ID.
|
|
||||||
if(!ctype_alnum(str_replace("-", "", $this->requestedId))) {
|
|
||||||
$this->hasError = true;
|
|
||||||
$this->errorMessageKey = "content.error.message.id.alphanumeric";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preparing and checking the content's info index file.
|
|
||||||
$this->contentFilepath = ContentManager::getContentFilePath($contentRootPath, $this->requestedId);
|
|
||||||
|
|
||||||
if(empty($this->contentFilepath)) {
|
|
||||||
// File doesn't exist !
|
|
||||||
$this->hasError = true;
|
|
||||||
$this->errorMessageKey = "content.error.message.data.not.exist";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the path to the main JSON file for a desired piece of content.
|
|
||||||
* @param string $contentRootPath
|
|
||||||
* @param string $contentId
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
private static function getContentFilePath(string $contentRootPath, string $contentId): ?string {
|
|
||||||
if(ctype_alnum(str_replace("-", "", $contentId))) {
|
|
||||||
return realpath($contentRootPath . "/items/" . $contentId . ".json");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares a ContentManager for the current page.
|
|
||||||
* @param string $contentRootPath Root path for the relevant content ("<webRoot>/content", "<webRoot>/tools", ...)
|
|
||||||
* @return ContentManager
|
|
||||||
*/
|
|
||||||
public static function createContentManager(string $contentRootPath): ContentManager {
|
|
||||||
return new ContentManager(
|
|
||||||
$contentRootPath,
|
|
||||||
l10n_url_switch(NULL),
|
|
||||||
isset($_GET['tags']) ? htmlspecialchars($_GET['tags']) : NULL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@@ -1,107 +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';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
@@ -1,157 +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/config.php';
|
|
||||||
include_once 'commons/langs.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';
|
|
||||||
|
|
||||||
// Defining the template types.
|
|
||||||
class ToolInfoFile {
|
|
||||||
public string $domFile;
|
|
||||||
public ?string $langFile;
|
|
||||||
public array $codeFilesPaths;
|
|
||||||
public array $moduleFilesPaths;
|
|
||||||
public array $styleFilesPaths;
|
|
||||||
public string $icon;
|
|
||||||
public string $titleKey;
|
|
||||||
public ?string $subTitleKey;
|
|
||||||
//public OpenGraphData $openGraphData;
|
|
||||||
|
|
||||||
function __construct(string $domFile, ?string $langFile, ?array $codeFilesPaths, ?array $moduleFilesPaths,
|
|
||||||
?array $styleFilesPaths, ?string $icon, ?string $titleKey, ?string $subTitleKey,
|
|
||||||
array $opengraph) {
|
|
||||||
$this->domFile = $domFile;
|
|
||||||
$this->langFile = $langFile;
|
|
||||||
$this->codeFilesPaths = is_null($codeFilesPaths) ? array() : $codeFilesPaths;
|
|
||||||
$this->moduleFilesPaths = is_null($moduleFilesPaths) ? array() : $moduleFilesPaths;
|
|
||||||
$this->styleFilesPaths = is_null($styleFilesPaths) ? array() : $styleFilesPaths;
|
|
||||||
$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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function from_json(array $json_data): ?ToolInfoFile {
|
|
||||||
if(!key_exists("dom", $json_data)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new ToolInfoFile(
|
|
||||||
$json_data["dom"],
|
|
||||||
key_exists("lang", $json_data) ? $json_data["lang"] : null,
|
|
||||||
key_exists("code", $json_data) ? $json_data["code"] : null,
|
|
||||||
key_exists("module", $json_data) ? $json_data["module"] : null,
|
|
||||||
key_exists("styles", $json_data) ? $json_data["styles"] : null,
|
|
||||||
key_exists("icon", $json_data) ? $json_data["icon"] : null,
|
|
||||||
key_exists("title", $json_data) ? $json_data["title"] : null,
|
|
||||||
key_exists("subtitle", $json_data) ? $json_data["subtitle"] : null,
|
|
||||||
$json_data["opengraph"]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateFiles(ContentManager $contentManager): void {
|
|
||||||
if(!(file_exists($this->domFile) && is_file($this->domFile))) {
|
|
||||||
$contentManager->hasError = true;
|
|
||||||
$contentManager->errorMessageKey = "content.error.message.missing.file.dom";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_null($this->langFile)) {
|
|
||||||
if(!(file_exists($this->langFile) && is_file($this->langFile))) {
|
|
||||||
$contentManager->hasError = true;
|
|
||||||
$contentManager->errorMessageKey = "content.error.message.missing.file.lang";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($this->codeFilesPaths as $codeFilePath) {
|
|
||||||
if(!(file_exists($codeFilePath) && is_file($codeFilePath))) {
|
|
||||||
$contentManager->hasError = true;
|
|
||||||
$contentManager->errorMessageKey = "content.error.message.missing.file.code";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($this->moduleFilesPaths as $moduleFilePath) {
|
|
||||||
if(!(file_exists($moduleFilePath) && is_file($moduleFilePath))) {
|
|
||||||
$contentManager->hasError = true;
|
|
||||||
$contentManager->errorMessageKey = "content.error.message.missing.file.module";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($this->styleFilesPaths as $styleFilePath) {
|
|
||||||
if(!(file_exists($styleFilePath) && is_file($styleFilePath))) {
|
|
||||||
$contentManager->hasError = true;
|
|
||||||
$contentManager->errorMessageKey = "content.error.message.missing.file.style";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class ToolsContent {
|
|
||||||
static function loadItemIndexFile(ContentManager $contentManager, string $contentRootPath): ?ToolInfoFile {
|
|
||||||
// Preliminary check
|
|
||||||
if(!$contentManager->displayType == EContentDisplayType::DISPLAY) {
|
|
||||||
$contentManager->hasError = true;
|
|
||||||
$contentManager->errorMessageKey = "content.error.message.cannot.load.item.as.not.content";
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loading the index file
|
|
||||||
$itemIndexJsonData = json_decode(file_get_contents($contentManager->contentFilepath), true);
|
|
||||||
if(is_null($itemIndexJsonData)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
$toolInfo = ToolInfoFile::from_json($itemIndexJsonData);
|
|
||||||
unset($itemIndexJsonData);
|
|
||||||
|
|
||||||
// Making paths absolute
|
|
||||||
if(!is_null($toolInfo)) {
|
|
||||||
$toolInfo->domFile = realpath($contentRootPath . "/items/" . $toolInfo->domFile);
|
|
||||||
if(!is_null($toolInfo->langFile)) {
|
|
||||||
$toolInfo->langFile = realpath($contentRootPath . "/items/" . $toolInfo->langFile);
|
|
||||||
}
|
|
||||||
for($iCodeFilePath = 0; $iCodeFilePath < count($toolInfo->codeFilesPaths); $iCodeFilePath++) {
|
|
||||||
$toolInfo->codeFilesPaths[$iCodeFilePath] = realpath(
|
|
||||||
$contentRootPath . "/items/" . $toolInfo->codeFilesPaths[$iCodeFilePath]);
|
|
||||||
$toolInfo->codeFilesPaths[$iCodeFilePath] = str_replace(
|
|
||||||
"\\", "/", $toolInfo->codeFilesPaths[$iCodeFilePath]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for($iModuleFilePath = 0; $iModuleFilePath < count($toolInfo->moduleFilesPaths); $iModuleFilePath++) {
|
|
||||||
$toolInfo->moduleFilesPaths[$iModuleFilePath] = realpath(
|
|
||||||
$contentRootPath . "/items/" . $toolInfo->moduleFilesPaths[$iModuleFilePath]);
|
|
||||||
$toolInfo->moduleFilesPaths[$iModuleFilePath] = str_replace(
|
|
||||||
"\\", "/", $toolInfo->moduleFilesPaths[$iModuleFilePath]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for($iStyleFilePath = 0; $iStyleFilePath < count($toolInfo->styleFilesPaths); $iStyleFilePath++) {
|
|
||||||
$toolInfo->styleFilesPaths[$iStyleFilePath] = realpath(
|
|
||||||
$contentRootPath . "/items/" . $toolInfo->styleFilesPaths[$iStyleFilePath]);
|
|
||||||
$toolInfo->styleFilesPaths[$iStyleFilePath] = str_replace(
|
|
||||||
"\\", "/", $toolInfo->styleFilesPaths[$iStyleFilePath]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$contentManager->hasError = true;
|
|
||||||
$contentManager->errorMessageKey = "content.error.message.cannot.load";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $toolInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
@@ -1,156 +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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Make a note of which variables are being used from that file !
|
|
||||||
include_once 'commons/config.php';
|
|
||||||
|
|
||||||
// This helper requires PHP 8 or newer !
|
|
||||||
|
|
||||||
// Setting the default values.
|
|
||||||
$default_language = "en";
|
|
||||||
$user_language = "en";
|
|
||||||
$user_uri_language = "";
|
|
||||||
|
|
||||||
$lang_compilation_date = "1970-01-01T00:00:00Z";
|
|
||||||
//$lang_compilation_date = (new DateTime('2010-12-30 23:21:46'))->format(DateTimeInterface::ATOM);
|
|
||||||
|
|
||||||
// Preparing a function for later
|
|
||||||
function process_lang_header(string $accepted_lang_header, bool $filter_unsupported = true, bool $simplify_entries = true): array {
|
|
||||||
$accepted_languages = [];
|
|
||||||
|
|
||||||
foreach(explode(",", $accepted_lang_header) as $_client_lang_entry) {
|
|
||||||
$lang_entry_parts = explode(";", $_client_lang_entry);
|
|
||||||
|
|
||||||
// Modifying entries without a "q=<float>" part to have a '0.1' value
|
|
||||||
if(count($lang_entry_parts) == 1) {
|
|
||||||
$lang_entry_parts = [$lang_entry_parts[0], "0.1"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignoring unexpected entries
|
|
||||||
if(count($lang_entry_parts) != 2) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simplifying complex entries from "en-US" to "en".
|
|
||||||
// We'll ignore duplicates since it won't matter after sorting.
|
|
||||||
if($simplify_entries && strlen($lang_entry_parts[0]) > 2) {
|
|
||||||
$lang_entry_parts[0] = substr($lang_entry_parts[0], 0, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only allowing supported languages
|
|
||||||
if(!in_array($lang_entry_parts[0], ["en", "fr"]) && $filter_unsupported) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parsing the language's weight
|
|
||||||
$lang_entry_parts[1] = str_replace("q=", "", $lang_entry_parts[1]);
|
|
||||||
$lang_entry_weights = filter_var($lang_entry_parts[1], FILTER_VALIDATE_FLOAT);
|
|
||||||
if($lang_entry_weights === false || !is_float($lang_entry_weights)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Saving it for later
|
|
||||||
$accepted_languages[] = $lang_entry_parts;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $accepted_languages;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempting to detect the language through the URI
|
|
||||||
if(str_starts_with($_SERVER['REQUEST_URI'], "/en/")) {
|
|
||||||
$user_language = "en";
|
|
||||||
$user_uri_language = "/".$user_language;
|
|
||||||
} elseif(str_starts_with($_SERVER['REQUEST_URI'], "/fr/")) {
|
|
||||||
$user_language = "fr";
|
|
||||||
$user_uri_language = "/".$user_language;
|
|
||||||
} elseif(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
|
||||||
// Attempting to detect the language through the browser's headers.
|
|
||||||
$_client_languages = process_lang_header($_SERVER['HTTP_ACCEPT_LANGUAGE']);
|
|
||||||
|
|
||||||
// Sorting based on weight and selecting the preferred one.
|
|
||||||
if(count($_client_languages) > 0) {
|
|
||||||
usort($_client_languages, function(array $a, array $b) {
|
|
||||||
if($a[1] == $b[1]) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ($a[1] > $b[1]) ? -1 : 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
$user_language = $_client_languages[0][0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preparing other related variables
|
|
||||||
$lang_number_decimal = $user_language == "en" ? "." : ",";
|
|
||||||
$lang_number_thousands = $user_language == "en" ? "," : ".";
|
|
||||||
|
|
||||||
// Setting headers
|
|
||||||
header("Content-Language: " . $user_language);
|
|
||||||
|
|
||||||
// Reading and parsing the strings.json file
|
|
||||||
$lang_json = file_get_contents(realpath($dir_commons . "/strings.json"));
|
|
||||||
$lang_data = json_decode($lang_json, true);
|
|
||||||
|
|
||||||
if(array_key_exists("_compile_date", $lang_data)) {
|
|
||||||
$lang_compilation_date = $lang_data["_compile_date"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Localization functions
|
|
||||||
function localize_private(string $string_key, array $private_lang_data, bool $fallback_to_common = false,
|
|
||||||
string $fallback_prefix = "fallback.unknown") : string {
|
|
||||||
global $user_language, $default_language, $lang_data;
|
|
||||||
|
|
||||||
if(array_key_exists($user_language, $private_lang_data)) {
|
|
||||||
if(array_key_exists($string_key, $private_lang_data[$user_language])) {
|
|
||||||
// If found in direct array in user's language.
|
|
||||||
return $private_lang_data[$user_language][$string_key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(array_key_exists($default_language, $private_lang_data)) {
|
|
||||||
if(array_key_exists($string_key, $private_lang_data[$default_language])) {
|
|
||||||
// If found in direct array in default language.
|
|
||||||
return $private_lang_data[$default_language][$string_key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($fallback_to_common) {
|
|
||||||
// If we can attempt to fall back on the common lang file.
|
|
||||||
return localize_private($fallback_prefix . $string_key, $lang_data, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If nothing could be done, we simply return the key.
|
|
||||||
return $string_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
function localize($string_key, ?array $param_values = null) : string {
|
|
||||||
global $lang_data;
|
|
||||||
if(is_null($param_values)) {
|
|
||||||
return localize_private($string_key, $lang_data, false);
|
|
||||||
} else {
|
|
||||||
$localized_string = localize_private($string_key, $lang_data, false);
|
|
||||||
|
|
||||||
for($iStrParam = 0; $iStrParam < sizeof($param_values); $iStrParam++) {
|
|
||||||
$localized_string = str_replace("%" . $iStrParam, $param_values[$iStrParam], $localized_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $localized_string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function l10n_url_abs($url) : string {
|
|
||||||
global $user_uri_language;
|
|
||||||
return $user_uri_language . $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
function l10n_url_switch($lang) : string {
|
|
||||||
if(is_null($lang)) {
|
|
||||||
return preg_replace("^\/(lb|lu|fr|en)^", "", $_SERVER['REQUEST_URI']);
|
|
||||||
} else {
|
|
||||||
return "/".$lang.preg_replace("^\/(lb|lu|fr|en)^", "", $_SERVER['REQUEST_URI']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@@ -1,69 +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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Classes
|
|
||||||
class ListingFile {
|
|
||||||
public string $fileName;
|
|
||||||
public int $fileSize;
|
|
||||||
public string $absolutePath;
|
|
||||||
|
|
||||||
function __construct($fileName, $fileSize, $absolutePath) {
|
|
||||||
$this->fileName = $fileName;
|
|
||||||
$this->fileSize = $fileSize;
|
|
||||||
$this->absolutePath = $absolutePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ListingContainer {
|
|
||||||
public string $relativePath;
|
|
||||||
public array $subDirectories;
|
|
||||||
public array $files;
|
|
||||||
|
|
||||||
function __construct($relativePath) {
|
|
||||||
$this->relativePath = $relativePath;
|
|
||||||
$this->subDirectories = array();
|
|
||||||
$this->files = array();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Functions.
|
|
||||||
function getDirectoryContent(string $dirPath, array $filteringRegexes, int $recursiveBudget, bool $validatePermission): ListingContainer {
|
|
||||||
$returnedData = new ListingContainer("./");
|
|
||||||
|
|
||||||
if($recursiveBudget == 0) {
|
|
||||||
return $returnedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($validatePermission) {
|
|
||||||
if(!file_exists($dirPath . DIRECTORY_SEPARATOR . ".allow_listing")) {
|
|
||||||
$returnedData->files[] = new ListingFile(
|
|
||||||
"Directory listing isn't allowed !",
|
|
||||||
-1,
|
|
||||||
realpath($dirPath . DIRECTORY_SEPARATOR . ".allow_listing")
|
|
||||||
);
|
|
||||||
return $returnedData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (scandir($dirPath) as $key => $value) {
|
|
||||||
$path = realpath($dirPath . DIRECTORY_SEPARATOR . $value);
|
|
||||||
if(is_file($path)) {
|
|
||||||
$returnedData->files[] = new ListingFile(basename($path), filesize($path), realpath($path));
|
|
||||||
} elseif($value != "." && $value != "..") {
|
|
||||||
$returnedData->subDirectories[] = getDirectoryContent(
|
|
||||||
$path,
|
|
||||||
$filteringRegexes,
|
|
||||||
$recursiveBudget - 1,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $returnedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@@ -1,33 +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();
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_modal_id(string $id): string {
|
|
||||||
return "modal-".$id;
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_code_modal(string $id, string $title, string $text) {
|
|
||||||
echo('<div class="modal" id="'.get_modal_id($id).'" tabindex="-1" role="dialog">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content p-0">
|
|
||||||
<a href="#" class="close" role="button" aria-label="Close">
|
|
||||||
<span aria-hidden="true"><i class="fad fa-times"></i></span>
|
|
||||||
</a>
|
|
||||||
<h5 class="modal-title my-10 text-center">'.$title.'</h5>
|
|
||||||
<hr class="my-15">
|
|
||||||
<div class="card p-0 m-0 bg-very-dark mx-15">
|
|
||||||
<p id="modal-text-'.$id.'" class="text-monospace mx-15">'.$text.'</p>
|
|
||||||
</div>
|
|
||||||
<div class="text-right text-center my-15">
|
|
||||||
<a href="#" class="btn mr-20" role="button">'.localize("generic.button.close").'</a>
|
|
||||||
<a href="#" class="btn btn-primary disabled" role="button">'.localize("generic.button.copy").'</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>');
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@@ -1,76 +0,0 @@
|
|||||||
{
|
|
||||||
"about.head.title": "About - NibblePoker",
|
|
||||||
"about.head.description": "TODO: description",
|
|
||||||
"about.og.title": "NibblePoker - About",
|
|
||||||
"about.og.description": "TODO: description",
|
|
||||||
"about.header.title": "About",
|
|
||||||
|
|
||||||
|
|
||||||
"about.intro.title": "Introduction",
|
|
||||||
|
|
||||||
"about.intro.text.01": "My name is Herwin Bozet, I'm an experienced developer with extensive experience in PureBasic, Python, Java, VBA; and intermediate knowledge in C, Win32 APIs, embedded systems and general web development.",
|
|
||||||
"about.intro.text.02": "I've been programming for about 10 years now, and for the last 5 years I've been actively working on applying that experience to a variety of projects with the aim of helping programmers and people in their day-to-day life.",
|
|
||||||
|
|
||||||
"about.intro.text.10": "NibblePoker is, in essence, a simple moniker and the front-end for most of my public-focused work.",
|
|
||||||
"about.intro.text.11": "It houses all my work made and tailored for usage by other people.",
|
|
||||||
|
|
||||||
"about.intro.text.20": "This entire website, as well as all my work for it and other personal projects, is completely open-source and available under permissive <abbr title=\"Open Source Initiative\">OSI</abbr> approved licenses.",
|
|
||||||
"about.intro.text.21": "All of it is maintained, developed and expanded in my free time with the occasional help from people in the open-source community.",
|
|
||||||
|
|
||||||
|
|
||||||
"about.tenets.title": "Core tenets",
|
|
||||||
|
|
||||||
"about.tenets.text.01": "",
|
|
||||||
"about.tenets.text.02": "",
|
|
||||||
|
|
||||||
|
|
||||||
"about.future.title": "Future plans",
|
|
||||||
|
|
||||||
"about.future.text.01":"It is planned to turn NibblePoker into a <abbr title=\"Private company with limited liability\">SPRL</abbr> in a couple years if everything goes as planned.",
|
|
||||||
"about.future.text.02":"This would allow me to centralize many things and invest properly in my targetted fields to achieve my goals.",
|
|
||||||
"about.future.text.10":"The goal would be to create a small sustainable local business that offers a wide range of products and solutions covering <abbr title=\"Internet of things\">IoT</abbr> devices, programming, and technological independence ; All while including the required software and hardware components often lacking in such products and solutions.",
|
|
||||||
"about.future.text.20":"Ultimately, all this work and research would be made available to the public under open-source licenses, enabling anyone who wishes to learn, reuse, and resell open-source products, to do so in a similar way as companies like Adafruit do.",
|
|
||||||
|
|
||||||
|
|
||||||
"_about.nibblepoker.title": "The 'NibblePoker' name",
|
|
||||||
"_about.nibblepoker.text.01": "TODO",
|
|
||||||
"_about.nibblepoker.text.10": "TODO",
|
|
||||||
"_about.nibblepoker.text.11": "TODO",
|
|
||||||
"_about.nibblepoker.text.20": "TODO",
|
|
||||||
|
|
||||||
|
|
||||||
"about.financing.title": "Financing",
|
|
||||||
|
|
||||||
"about.financing.text.01": "This website, as well as the surrounding infrastructure, was made to cost as little as possible while not being reliant on any censor-happy companies.",
|
|
||||||
"about.financing.text.02": "Following my core tenets, I also wanted to retain some sort of \"technological sovereignty\", and therefore refuse to support or use companies that actively fight against legal free speech.",
|
|
||||||
|
|
||||||
"about.financing.text.10": "The details of the operating costs are provided below to illustrate the low price of such independence.",
|
|
||||||
|
|
||||||
"about.financing.text.20": "And for those of you who are more motivated, I hope to inspire you to at least try this kind of activity.",
|
|
||||||
"about.financing.text.21": "It may seem daunting at first, but for a fraction of the cost presented here, <b>and with a bit of motivation</b>, you can already accomplish a lot of things and gain valuable knowledge for a world as interconnected as ours.",
|
|
||||||
|
|
||||||
"about.financing.text.isp": "The main ISP bill isn't accounted for since this could run off some random public Wi-Fi.",
|
|
||||||
|
|
||||||
"about.financing.part.service": "Service",
|
|
||||||
"about.financing.part.cost": "Cost",
|
|
||||||
"about.financing.part.cost.total": "Total Cost",
|
|
||||||
"about.financing.part.equipment": "Equipment",
|
|
||||||
"about.financing.part.cost.yearly": "Yearly Cost",
|
|
||||||
"about.financing.part.cost.yearly.total": "Yearly Cost",
|
|
||||||
|
|
||||||
"about.financing.part.domain.lu": "<i>.lu</i> domain",
|
|
||||||
"about.financing.part.domain.com": "<i>.com</i> domain",
|
|
||||||
"about.financing.part.proxy.europe": "European reverse-proxy",
|
|
||||||
"about.financing.part.proxy.america": "American reverse-proxy",
|
|
||||||
"about.financing.part.proxy.asia": "Asian reverse-proxy",
|
|
||||||
"about.financing.part.emails": "Emails",
|
|
||||||
"about.financing.part.electricity": "Electricity",
|
|
||||||
"about.financing.part.nanopir4s": "NanoPi R4S",
|
|
||||||
"about.financing.part.nanopir4s.desc": "Handles all non public-facing tasks and services.",
|
|
||||||
"about.financing.part.storage": "Local storage",
|
|
||||||
|
|
||||||
|
|
||||||
"about.aziascreations.title": "The 'AziasCreations' name",
|
|
||||||
"_about.aziascreations.text.01": "TODO",
|
|
||||||
"_about.aziascreations.text.10": "TODO"
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"common.action.copy": "Copy",
|
|
||||||
"common.action.copied": "Copied",
|
|
||||||
|
|
||||||
"common.undefined": "Undefined",
|
|
||||||
"common.na": "N/A",
|
|
||||||
|
|
||||||
"common.yes": "Yes",
|
|
||||||
"common.no": "No",
|
|
||||||
|
|
||||||
"common.user-agent": "User-Agent"
|
|
||||||
}
|
|
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"contact.head.title": "Contact - NibblePoker",
|
|
||||||
"contact.head.description": "TODO: description",
|
|
||||||
"contact.og.title": "NibblePoker - Contact",
|
|
||||||
"contact.og.description": "TODO: description",
|
|
||||||
"contact.header.title": "Contact",
|
|
||||||
|
|
||||||
"contact.email.title": "Email",
|
|
||||||
"contact.email.compose": "Send an email to <i>herwin.bozet@gmail.com</i>",
|
|
||||||
|
|
||||||
"contact.twitter.title": "Twitter",
|
|
||||||
"contact.twitter.compose": "Compose DM to @NibblePoker on Twitter"
|
|
||||||
|
|
||||||
}
|
|
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"debug.head.title": "Debugger - NibblePoker",
|
|
||||||
"debug.head.description": "Debugging page used to analyse the behaviour of various mechanisms used by the website.",
|
|
||||||
"debug.og.title": "NibblePoker - Debugger",
|
|
||||||
"debug.og.description": "Debugging page used to analyse the behaviour of various mechanisms used by the website.",
|
|
||||||
"debug.header.title": "Debugger",
|
|
||||||
|
|
||||||
"debug.tables.field": "Field",
|
|
||||||
"debug.tables.value": "Value",
|
|
||||||
|
|
||||||
"debug.host.title": "Host Configuration",
|
|
||||||
"debug.host.requested": "Requested",
|
|
||||||
"debug.host.domain": "Domain",
|
|
||||||
"debug.host.uri": "URI",
|
|
||||||
"debug.host.tld": "TLD",
|
|
||||||
"debug.host.waffle": "Waffle Mode",
|
|
||||||
"debug.host.bouneschlupp": "Bouneschlupp Mode",
|
|
||||||
|
|
||||||
"debug.lang.title": "Localization System (L10N)",
|
|
||||||
"debug.lang.compile-date": "Compilation date",
|
|
||||||
"debug.lang.default": "Default language",
|
|
||||||
"debug.lang.user": "Active language",
|
|
||||||
"debug.lang.header.raw": "Raw HTTP header",
|
|
||||||
"debug.lang.header.processed": "Processed HTTP header",
|
|
||||||
|
|
||||||
"debug.client.title": "Client Information"
|
|
||||||
}
|
|
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"error.403.head.title": "403 - NibblePoker",
|
|
||||||
"error.403.head.description": "Access to the requested resource isn't unauthorized.",
|
|
||||||
"error.403.og.title": "NibblePoker - 403 Error",
|
|
||||||
"error.403.og.description": "Access to the requested resource isn't unauthorized.",
|
|
||||||
"error.403.header.title": "Error<span class=\"mx-s t-size-15\">❱</span>403 Error",
|
|
||||||
|
|
||||||
"error.404.head.title": "404 - NibblePoker",
|
|
||||||
"error.404.head.description": "The server couldn't find the requested resource.",
|
|
||||||
"error.404.og.title": "NibblePoker - 404 Error",
|
|
||||||
"error.404.og.description": "The server couldn't find the requested resource.",
|
|
||||||
"error.404.header.title": "Error<span class=\"mx-s t-size-15\">❱</span>404 Error",
|
|
||||||
|
|
||||||
"error.500.head.title": "500 - NibblePoker",
|
|
||||||
"error.500.head.description": "The server has encountered a situation it doesn't know how to handle.",
|
|
||||||
"error.500.og.title": "NibblePoker - 500 Error",
|
|
||||||
"error.500.og.description": "The server has encountered a situation it doesn't know how to handle.",
|
|
||||||
"error.500.header.title": "Error<span class=\"mx-s t-size-15\">❱</span>500 Error",
|
|
||||||
|
|
||||||
"error.title": "%0 Error",
|
|
||||||
|
|
||||||
"error.skit.pc.dead": "Drawing of an old PC with a face with crossed eyes."
|
|
||||||
}
|
|
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"footer.text.privacy": "Privacy policy",
|
|
||||||
"footer.alt.sidebar.button": "Open and close the navigation sidebar.",
|
|
||||||
"footer.alt.logo": "Website's logo"
|
|
||||||
}
|
|
@@ -1,39 +0,0 @@
|
|||||||
{
|
|
||||||
"home.head.title": "NibblePoker",
|
|
||||||
"home.head.description": "Collection of free and open-source handmade utilities and libraries ranging from a simple COM port lister to password remover and autonomous video archivers.",
|
|
||||||
"home.og.title": "NibblePoker",
|
|
||||||
"home.og.description": "Collection of free and open-source handmade utilities and libraries ranging from a simple COM port lister to password remover and autonomous video archivers.",
|
|
||||||
"home.header.title": "Homepage",
|
|
||||||
|
|
||||||
|
|
||||||
"home.intro.title": "Welcome to %0",
|
|
||||||
"home.intro.text.1": "This website contains a collection of my personal work through blog posts, software releases and other forms of media, all of which is accessible for free and under open-source friendly licenses.",
|
|
||||||
"home.intro.text.2": "If you wish to contact me, you can do so through the contact form linked in the sidebar or via the email address present on that page.",
|
|
||||||
|
|
||||||
|
|
||||||
"home.showcase.title": "Showcase",
|
|
||||||
|
|
||||||
|
|
||||||
"home.updates.title": "Updates",
|
|
||||||
|
|
||||||
"home.updates.text.privacy": "● Updated our privacy policy.",
|
|
||||||
|
|
||||||
"home.updates.4.date": "November 30 2023",
|
|
||||||
"home.updates.4.text.1": "● Centralized DNS servers & implemented GeoDNS.",
|
|
||||||
"home.updates.4.text.2": "● Added US CDN hosted by <a href=\"https://www.chicagovps.net/\">ChicagoVPS</a>.",
|
|
||||||
"home.updates.4.text.3": "● All other regions use the EU CDN hosted by <a href=\"https://www.ionos.fr/\">IONOS</a>.",
|
|
||||||
|
|
||||||
"home.updates.3.date": "November 12 2023",
|
|
||||||
"home.updates.3.text.1": "● Other services are back online.",
|
|
||||||
"home.updates.3.text.2": "● Changed our host to <a href=\"https://www.ionos.fr/\">IONOS</a>.",
|
|
||||||
"home.updates.3.text.3": "● Finished all side pages.",
|
|
||||||
|
|
||||||
"home.updates.2.date": "August 15 2023",
|
|
||||||
"home.updates.2.text.1": "● The website is back online.",
|
|
||||||
"home.updates.2.text.2": "● New and much lighter design.",
|
|
||||||
"home.updates.2.text.3": "● Changed our host to <a href=\"https://hostbrr.com/\">HostBrr</a>.",
|
|
||||||
"home.updates.2.text.4": "● Added a section for web-based tools.",
|
|
||||||
|
|
||||||
"home.updates.1.date": "September 9 2022",
|
|
||||||
"home.updates.1.text.1": "● Changed our host to v6Node."
|
|
||||||
}
|
|
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"lang.menu.title": "Language",
|
|
||||||
"lang.current": "English",
|
|
||||||
"lang.automatic": "Automatic",
|
|
||||||
"lang.english": "English",
|
|
||||||
"lang.french": "French",
|
|
||||||
"lang.german": "German",
|
|
||||||
"lang.luxembourgish": "Luxembourgish",
|
|
||||||
|
|
||||||
"_lang.english.639-3": "English (eng)",
|
|
||||||
"_lang.french.639-3": "French (fra)",
|
|
||||||
"_lang.luxembourgish.639-3": "Luxembourgish (ltz)"
|
|
||||||
}
|
|
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"links.head.title": "Links - NibblePoker",
|
|
||||||
"links.head.description": "TODO: description",
|
|
||||||
"links.og.title": "NibblePoker - Links",
|
|
||||||
"links.og.description": "TODO: description",
|
|
||||||
"links.header.title": "Links",
|
|
||||||
|
|
||||||
"links.social.title": "Social Networks",
|
|
||||||
"links.work.title": "Work & Freelancing",
|
|
||||||
"links.misc.title": "Miscellaneous",
|
|
||||||
|
|
||||||
"links.twitter.title": "Twitter <i>(@NibblePoker)</i>",
|
|
||||||
"links.twitter.text.1": "Random rambles about projects I'm working on.",
|
|
||||||
|
|
||||||
"links.github.title": "GitHub <i>(@aziascreations)</i>",
|
|
||||||
"links.github.text.1": "Private account containing all my personal projects.",
|
|
||||||
|
|
||||||
"links.github_pro.title": "GitHub <i>(@NibblePoker)</i>",
|
|
||||||
"links.github_pro.text.1": "Organization containing all the repositories related to this website.",
|
|
||||||
|
|
||||||
"links.linkedin.title": "LinkedIn",
|
|
||||||
"links.linkedin.text.1": "???",
|
|
||||||
|
|
||||||
"links.malt.title": "Malt",
|
|
||||||
"links.malt.text.1": "Any freelancing/consulting job can be conducted through their service.",
|
|
||||||
|
|
||||||
"links.gitea.title": "Self-hosted Gitea",
|
|
||||||
"links.gitea.text.1": "Contains all my projects and some mirrors from various sites.",
|
|
||||||
|
|
||||||
"links.files.title": "Public files & downloads",
|
|
||||||
"links.files.text.1": "Contains all files that can be downloaded on this website and other documentation.",
|
|
||||||
|
|
||||||
"links.archives.title": "Public archives",
|
|
||||||
"links.archives.text.1": "Contains various public archives."
|
|
||||||
}
|
|
@@ -1,86 +0,0 @@
|
|||||||
{
|
|
||||||
"privacy.head.title": "Privacy policy - NibblePoker",
|
|
||||||
"privacy.head.description": "Our privacy policy in a clear and easy to understand format.",
|
|
||||||
"privacy.og.title": "NibblePoker - Privacy Policy",
|
|
||||||
"privacy.og.description": "Our privacy policy in a clear and easy to understand format.",
|
|
||||||
"privacy.header.title": "Privacy policy",
|
|
||||||
|
|
||||||
"privacy.introduction.title": "Introduction",
|
|
||||||
"privacy.introduction.text.1": "This privacy policy is written in accordance with the 12th and 13th articles of the GDPR.",
|
|
||||||
"privacy.introduction.text.2": "If you wish to consult it, you can do so on the following websites:",
|
|
||||||
|
|
||||||
"privacy.contact.title": "How to contact us ?",
|
|
||||||
"privacy.contact.text.1": "If you wish to contact us for more information regarding our privacy policy, please contact us via the form included on the contact page, or at the following email address:",
|
|
||||||
|
|
||||||
"privacy.complaint.title": "How to contact the appropriate authorities ?",
|
|
||||||
"privacy.complaint.text.1": "Should you wish to report a complaint or if you feel that our privacy policy has not addressed your concern in a satisfactory manner, you may contact your national Data Protection Authority (DPA).",
|
|
||||||
"privacy.complaint.text.2": "More information on this procedure can be found on the following websites:",
|
|
||||||
|
|
||||||
"privacy.v2.data.title": "Data collection (Web)",
|
|
||||||
"privacy.v2.data.intro.1": "This websites only collects data through generic access logs in order to detect and block bad actors from accessing this website.",
|
|
||||||
"privacy.v2.data.intro.2": "None of the data collected is used for any other purpose, it is never shared with any other third-party and is never use in any sort of analytics.",
|
|
||||||
"privacy.v2.data.private.1": "Here is the list of private data being collected:",
|
|
||||||
"privacy.v2.data.private_list.1": "IP address",
|
|
||||||
"privacy.v2.data.private_list.2": "Browser's User-Agent",
|
|
||||||
"privacy.v2.data.non_private.1": "And here is the list of non-private data being collected:",
|
|
||||||
"privacy.v2.data.non_private_list.1": "Requested resource' URI",
|
|
||||||
"privacy.v2.data.non_private_list.2": "Date and time",
|
|
||||||
"privacy.v2.data.end.1": "Once the data has been logged in the access logs, it is automatically retrieved and processed by a locally-hosted applications every 30-60 seconds and then deleted from said logs.",
|
|
||||||
"privacy.v2.data.end.2": "This application compares this information against a list of known threat sources, targets and behaviours and if a match is found, the private information is stored for 7 days pending a manual review.",
|
|
||||||
"privacy.v2.data.end.3": "Once that 7 day period has elapsed, or once the report has been reviewed, all the relevant data is automatically deleted.",
|
|
||||||
"privacy.v2.data.end.4": "If your request wasn't flagged as potentially malicious, every data collected from it is thrown out instantly.",
|
|
||||||
"privacy.v2.data.end.5": "This process should normally never be triggered for regular traffic since most of the triggering actions are ones that should not be possible to accomplish through normal browsing.",
|
|
||||||
"privacy.v2.data.end.6": "However, this process isn't infallible and there is always an off chance that false positives may happen.",
|
|
||||||
|
|
||||||
"privacy.v2.data_dns.title": "Data collection (DNS)",
|
|
||||||
"privacy.v2.data_dns.intro.1": "Our <abbr title=\"Domain Name Service\">DNS</abbr> servers collects data through generic access logs in order to detect and block bad actors.",
|
|
||||||
"privacy.v2.data_dns.intro.2": "None of the data collected is used for any other purpose, it is never shared with any other third-party and is never use in any sort of analytics.",
|
|
||||||
"privacy.v2.data_dns.private.1": "Here is the list of private data being collected:",
|
|
||||||
"privacy.v2.data_dns.private_list.1": "IP address",
|
|
||||||
"privacy.v2.data_dns.non_private.1": "And here is the list of non-private data being collected:",
|
|
||||||
"privacy.v2.data_dns.non_private_list.1": "Requested DNS record",
|
|
||||||
"privacy.v2.data_dns.non_private_list.2": "Date and time",
|
|
||||||
"privacy.v2.data_dns.end.1": "All private data is deleted after a period of 7 days.",
|
|
||||||
|
|
||||||
"privacy.v2.update.title": "Changes to our privacy policy",
|
|
||||||
"privacy.v2.update.intro.1": "The content of this privacy policy was originally written on the 4th of December 2021 and was last updated on the 18th of March 2022.",
|
|
||||||
"privacy.v2.update.history.1.date": "2021/12/04",
|
|
||||||
"privacy.v2.update.history.1.desc.1": "Original version",
|
|
||||||
"privacy.v2.update.history.2.date": "2022/03/18",
|
|
||||||
"privacy.v2.update.history.2.desc.1": "Changed section on data collection to reflect new policy.",
|
|
||||||
"privacy.v2.update.history.2.desc.2": "Added mention about CloudFlare and linked to their privacy policy.",
|
|
||||||
"privacy.v2.update.history.2.desc.3": "Improved the <i>\"Changes to our privacy policy\"</i> section.",
|
|
||||||
"privacy.v2.update.history.3.date": "2022/09/09",
|
|
||||||
"privacy.v2.update.history.3.desc.1": "Changed references to external services to reflect the migration to v6Node.",
|
|
||||||
"privacy.v2.update.history.3.desc.1.1": "Added mention about v6Node and linked to their privacy policy.",
|
|
||||||
"privacy.v2.update.history.3.desc.1.2": "Removed mentions of CloudFlare.",
|
|
||||||
"privacy.v2.update.history.3.desc.2": "Changed the \"Cookies\" section to indicate that none should be used on public domains.",
|
|
||||||
"privacy.v2.update.history.4.date": "2023/11/11",
|
|
||||||
"privacy.v2.update.history.4.desc.1": "Changed references to external services to reflect the migration to IONOS.",
|
|
||||||
"privacy.v2.update.history.4.desc.1.1": "Removed mentions of v6Node.",
|
|
||||||
"privacy.v2.update.history.4.desc.2": "Changed section on data collection to reflect new timings & infrastructure.",
|
|
||||||
"privacy.v2.update.history.5.date": "2023/11/30",
|
|
||||||
"privacy.v2.update.history.5.desc.1": "Added a section regarding data collection through DNS servers.",
|
|
||||||
"privacy.v2.update.history.5.desc.2": "Changed references to external services to reflect the usage of ChicagoVPS",
|
|
||||||
"privacy.v2.update.end.2": "In the event of a change to our privacy policy, you will be informed explicitly, and a copy of previous versions of the policy will be available through this page.",
|
|
||||||
|
|
||||||
"privacy.v2.third.title": "Third Parties",
|
|
||||||
"privacy.v2.third.intro.1": "Our websites uses some <abbr title=\"Virtual private server\">VPS</abbr> provided by IONOS and ChicagoVPS in order to put in place a <abbr title=\"Content delivery network\">CDN</abbr> system.",
|
|
||||||
"privacy.v2.third.intro.2": "The goal of this system is to improve your browsing experience with the help of a private caching service and custom traffic filtering rules.",
|
|
||||||
"privacy.v2.third.intro.3": "No data should be collected on their side due to the nature of the server leased to us.",
|
|
||||||
"privacy.v2.third.intro.4": "If you'd wish to consult their privacy policy and their partners', you can do so by using the following URLs:",
|
|
||||||
|
|
||||||
"privacy.v2.cookies.title": "Cookies",
|
|
||||||
"privacy.v2.cookies.intro.1": "Our websites doesn't use nor store any cookies in your browser.",
|
|
||||||
|
|
||||||
"privacy.v2.personal.title": "Personal Measures & Convictions",
|
|
||||||
"privacy.v2.personal.disabled.intro": "While not required by any laws, we decided to improve your online privacy by disabling some features:",
|
|
||||||
"privacy.v2.personal.disabled.list.1": "Disabling hidden <a href=\"https://wikipedia.org/wiki/HTTP_referer\">HTTP Referer</a> system.",
|
|
||||||
"privacy.v2.personal.disabled.list.2": "Disabling Google's predatory <i>Topics API</i> and defunct <a href=\"https://www.eff.org/deeplinks/2021/03/googles-floc-terrible-idea\"><i>Cohort</i></a> ad-serving systems.",
|
|
||||||
"privacy.v2.personal.disabled.list.3": "Preventing any external third-party code from being injected into the page.",
|
|
||||||
"privacy.v2.personal.tracking.text.1": "It is our belief that the web and modern technology in general should never be used to track and spy on people in any way shape or form.",
|
|
||||||
"privacy.v2.personal.tracking.text.2": "We believe that any service that is in any way trying to force you to disable any ad-blocking or privacy-enhancing extensions should be avoided at all cost and shunned for their practices.",
|
|
||||||
"privacy.v2.personal.tracking.text.3": "Modern website should <b>never</b> break with those type of extensions unless they are purposefully built to track you to near-illegal extents, this excuse is only used to force you to accept these predatory practices.",
|
|
||||||
"_privacy.v2.personal.transparency.text.": "Additionally, we believe in the principles of transparency and openness [???]",
|
|
||||||
"privacy.v2.personal.recommendations": "We also strongly recommend you to read the <acronym title=\"European Union Agency for Cybersecurity\">ENISA</acronym>'s <i>Privacy considerations of online behavioural tracking report</i> in order to improve your online privacy."
|
|
||||||
}
|
|
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"sidebar.alt.logo": "Website's logo",
|
|
||||||
"sidebar.text.home": "Home",
|
|
||||||
"sidebar.text.shop": "Shop",
|
|
||||||
"sidebar.text.school": "Training",
|
|
||||||
"sidebar.text.projects": "Projects",
|
|
||||||
"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",
|
|
||||||
"sidebar.text.gitea": "Git Repos.",
|
|
||||||
"sidebar.text.wiki": "Wiki",
|
|
||||||
"sidebar.text.about": "About",
|
|
||||||
"sidebar.text.contributors": "Contributors",
|
|
||||||
"sidebar.text.contact": "Contact"
|
|
||||||
}
|
|
@@ -1,76 +0,0 @@
|
|||||||
{
|
|
||||||
"about.head.title": "À-propos - NibblePoker",
|
|
||||||
"about.head.description": "TODO: description",
|
|
||||||
"about.og.title": "NibblePoker - À-propos",
|
|
||||||
"about.og.description": "TODO: description",
|
|
||||||
"about.header.title": "À-propos",
|
|
||||||
|
|
||||||
|
|
||||||
"about.intro.title": "Introduction",
|
|
||||||
|
|
||||||
"about.intro.text.01": "Je m'appelle Herwin Bozet, et je suis un développeur expérimenté en PureBasic, Python, Java, VBA ; et de manière plus modérée en C, API Win32, systèmes embarqués et le développement web général.",
|
|
||||||
"about.intro.text.02": "Je programme depuis environ 10 ans, et au cours des 5 dernières années, j'ai activement travaillé à l'application de cette expérience à divers projets dans le but d'aider les programmeurs et les gens dans leur vie quotidienne.",
|
|
||||||
|
|
||||||
"about.intro.text.10": "NibblePoker est, en essence, un simple pseudonyme et une ombrelle sous laquelle la majeure partie de mon travail axé sur le public sera présente.",
|
|
||||||
"about.intro.text.11": "Il abrite l'ensemble de mon travail créé et adapté pour être utilisé par d'autres personnes.",
|
|
||||||
|
|
||||||
"about.intro.text.20": "L'ensemble de ce site web, ainsi que l'ensemble de mon travail et autres projets personnels réalisés pour lui, sont entièrement open-source et disponibles sous des licences permissives approuvées par l'<abbr title=\"Open Source Initiative\">OSI</abbr>.",
|
|
||||||
"about.intro.text.21": "Tout cela est maintenu, développé et étendu pendant mon temps libre, avec l'aide occasionnelle de personnes de la communauté open source.",
|
|
||||||
|
|
||||||
|
|
||||||
"about.tenets.title": "Principes fondamentaux",
|
|
||||||
|
|
||||||
"about.tenets.text.01": "",
|
|
||||||
"about.tenets.text.02": "",
|
|
||||||
|
|
||||||
|
|
||||||
"about.future.title": "Projet d'avenir",
|
|
||||||
|
|
||||||
"about.future.text.01":"Il est prévu que je décline NibblePoker en une petite <abbr title=\"Societé privée à responsibilité limitée\">SPRL</abbr> d'ici quelques années si tout se déroule comme prévu.\n",
|
|
||||||
"about.future.text.02":"Cela aura pour but de me permettre de centraliser plein de choses et d'investir correctement dans mes domaines de prédilection.",
|
|
||||||
"about.future.text.10":"La finalité serait de pouvoir créer un petit projet local d'entreprise durable, ainsi que de proposer une large gamme de produits et solutions couvrant les domaines de l'électronique connectée et intelligente, la programmation et l’indépendance technologique tout en incluant les composantes logicielles et physiques souvent manquantes dans de tels produits et solutions.",
|
|
||||||
"about.future.text.20":"Finalement tout ce travail et recherches seraient mis à disposition du public sous des licences open-source afin de permettre permettant à quiconque le souhaite d’apprendre, réutiliser et revendre des produits ouverts tels que le font des compagnies comme Adafruit.",
|
|
||||||
|
|
||||||
|
|
||||||
"_about.nibblepoker.title": "Le nom 'NibblePoker'",
|
|
||||||
"_about.nibblepoker.text.01": "Le surnom '<i>NibblePoker</i>' est un mot composé de plusieurs termes [techniques] plus anciens.",
|
|
||||||
"_about.nibblepoker.text.10": "● '<i>Nibble</i>' est un terme technique anglais historiquement utilisé pour décrire décrit un demi-octet, ou 4 bits d'information.",
|
|
||||||
"_about.nibblepoker.text.11": "● '<i>Poker</i>' viens du verbe anglais '<i>to poke</i>' qui, dans le domaine rétro-informatique, décrit le fait d'écrire des données dans la mémoire d'un ordinateur.",
|
|
||||||
"_about.nibblepoker.text.20": "Finalement, lors de la création de ce surnom, je travaillais depuis quelques temps sur d'anciennes machines telle la Commodore64, Acorn Electron et [???]ironique.",
|
|
||||||
|
|
||||||
|
|
||||||
"about.financing.title": "Financement",
|
|
||||||
|
|
||||||
"about.financing.text.01": "Ce site web, ainsi que son infrastructure environnante, ont été conçus pour coûter le moins possible tout en étant indépendants d'entreprises qui se prennent pour des censeurs.",
|
|
||||||
"about.financing.text.02": "Et en suivant mes principes fondamentaux, je souhaitais également conserver une \"souveraineté technologique\", et, par conséquent, refuse de soutenir ou d'utiliser des entreprises qui luttent activement contre la liberté d'expression.",
|
|
||||||
|
|
||||||
"about.financing.text.10": "Le détail des coûts opérationnels sont présents ci-dessous afin d'illustrer le faible prix d'une telle indépendance.",
|
|
||||||
|
|
||||||
"about.financing.text.20": "Et pour les plus motivés d'entre-vous, j'espère pouvoir vous motiver à au moins tester ce genre d'activités.",
|
|
||||||
"about.financing.text.21": "C'est un domaine qui peut paraître intimidant de prime abord, mais pour une fraction du coût présenté ici, <b>et avec un rien de motivation</b>, vous pouvez déjà accomplir énormément de choses et acquérir des connaissances essentielles dans un monde aussi connecté que le nôtre.",
|
|
||||||
|
|
||||||
"about.financing.text.isp": "Le coût de la connexion internet n'est pas compté car elle pourrait être remplacée par un Wi-Fi public lambda.",
|
|
||||||
|
|
||||||
"about.financing.part.service": "Service",
|
|
||||||
"about.financing.part.cost": "Coût",
|
|
||||||
"about.financing.part.cost.total": "Coût Total",
|
|
||||||
"about.financing.part.equipment": "Matériel",
|
|
||||||
"about.financing.part.cost.yearly": "Coût Annuel",
|
|
||||||
"about.financing.part.cost.yearly.total": "Coût Annuel",
|
|
||||||
|
|
||||||
"about.financing.part.domain.lu": "Domaine en <i>.lu</i>",
|
|
||||||
"about.financing.part.domain.com": "Domaine en <i>.com</i>",
|
|
||||||
"about.financing.part.proxy.europe": "Reverse-proxy en Europe",
|
|
||||||
"about.financing.part.proxy.america": "Reverse-proxy en Amérique",
|
|
||||||
"about.financing.part.proxy.asia": "Reverse-proxy en Asie",
|
|
||||||
"about.financing.part.emails": "Adresses email",
|
|
||||||
"about.financing.part.electricity": "Électricité",
|
|
||||||
"about.financing.part.nanopir4s": "NanoPi R4S",
|
|
||||||
"about.financing.part.nanopir4s.desc": "Gère tous les services et programmes internes.",
|
|
||||||
"about.financing.part.storage": "Stockage local",
|
|
||||||
|
|
||||||
|
|
||||||
"about.aziascreations.title": "Le nom 'AziasCreations'",
|
|
||||||
"about.aziascreations.text.01": "L'ancien surnom 'AziasCreations' était utilisé entre 2013 et 2020 et est à présent abandonné au profit de <i>NibblePoker</i>.",
|
|
||||||
"about.aziascreations.text.10": "Cependant, il reste utilisé sur GitHub et Gitea à cause de certaines limitations concernant les changements de pseudonyme qui m'ont empèché de faire un changement complet."
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"common.action.copy": "Copier",
|
|
||||||
"common.action.copied": "Copié",
|
|
||||||
|
|
||||||
"common.undefined": "Indéfini(e)",
|
|
||||||
"common.na": "Non-applicable",
|
|
||||||
|
|
||||||
"common.yes": "Oui",
|
|
||||||
"common.no": "Non",
|
|
||||||
|
|
||||||
"common.user-agent": "User-Agent"
|
|
||||||
}
|
|
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"debug.head.title": "Débogueur - NibblePoker",
|
|
||||||
"debug.head.description": "Page de débogage utilisée pour analyser le comportement des différents mécanismes utilisés par ce site web.",
|
|
||||||
"debug.og.title": "NibblePoker - Débogueur",
|
|
||||||
"debug.og.description": "Page de débogage utilisée pour analyser le comportement des différents mécanismes utilisés par ce site web.",
|
|
||||||
"debug.header.title": "Débogueur",
|
|
||||||
|
|
||||||
"debug.tables.field": "Champ",
|
|
||||||
"debug.tables.value": "Valeur",
|
|
||||||
|
|
||||||
"debug.host.title": "Configuration de l'hôte",
|
|
||||||
"debug.host.requested": "Demandé",
|
|
||||||
"debug.host.domain": "Domaine",
|
|
||||||
"debug.host.uri": "URI",
|
|
||||||
"debug.host.tld": "TLD",
|
|
||||||
"debug.host.waffle": "Mode gaufrier",
|
|
||||||
"debug.host.bouneschlupp": "Mode Bouneschlupp",
|
|
||||||
|
|
||||||
"debug.lang.title": "Système de localisation (L10N)",
|
|
||||||
"debug.lang.compile-date": "Date de compilation",
|
|
||||||
"debug.lang.default": "Langue par défaut",
|
|
||||||
"debug.lang.user": "Langue active",
|
|
||||||
"debug.lang.header.raw": "En-tête HTTP brut",
|
|
||||||
"debug.lang.header.processed": "En-tête HTTP traité",
|
|
||||||
|
|
||||||
"debug.client.title": "Informations du client"
|
|
||||||
}
|
|
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
}
|
|
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"footer.text.privacy": "Politique de confidentialité",
|
|
||||||
"footer.alt.sidebar.button": "Ouvrir et fermer le menu latéral de navigation.",
|
|
||||||
"footer.alt.logo": "Logo du site web"
|
|
||||||
}
|
|
@@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"home.head.title": "NibblePoker",
|
|
||||||
"home.head.description": "Collection d'utilitaires et de bibliothèques gratuits et open source, allant d'un simple énumérateur de ports COM à un suppresseur de mots de passe Excel ou même un système d'archivage de vidéos autonome.\n",
|
|
||||||
"home.og.title": "NibblePoker",
|
|
||||||
"home.og.description": "Collection d'utilitaires et de bibliothèques gratuits et open source, allant d'un simple énumérateur de ports COM à un suppresseur de mots de passe Excel ou même un système d'archivage de vidéos autonome.\n",
|
|
||||||
"home.header.title": "Page d'accueil",
|
|
||||||
|
|
||||||
|
|
||||||
"_home.intro.title": "Bienvenue sur '<i>%0</i>'",
|
|
||||||
"home.intro.title": "Bienvenue sur %0",
|
|
||||||
"home.intro.text.1": "Ce site web contient une collection de mes travaux personnels tels que des articles de blog, des logiciels utilitaires ou d'autres formes de médias.<br>Tout est accessible gratuitement et sous des licences à l'open source.",
|
|
||||||
"home.intro.text.2": "Si vous souhaitez me contacter, vous pouvez le faire via la page de contact lié dans la barre de navigation latérale.",
|
|
||||||
|
|
||||||
|
|
||||||
"home.showcase.title": "Vitrine",
|
|
||||||
|
|
||||||
|
|
||||||
"home.updates.title": "Updates",
|
|
||||||
|
|
||||||
"home.updates.text.privacy": "● Mise-à-jour de notre politique de confidentialité.",
|
|
||||||
|
|
||||||
"home.updates.4.date": "30 novembre 2023",
|
|
||||||
"home.updates.4.text.1": "● Centralisation des serveurs DNS & implémentation de GeoDNS.",
|
|
||||||
"home.updates.4.text.2": "● Ajout d'un CDN pour l'Amérique du Nord hébergé par <a href=\"https://www.chicagovps.net/\">ChicagoVPS</a>.",
|
|
||||||
"home.updates.4.text.3": "● Les autres régions utilisent le CDN Européen hébergé par <a href=\"https://www.ionos.fr/\">IONOS</a>.",
|
|
||||||
|
|
||||||
"home.updates.3.date": "12 novembre 2023",
|
|
||||||
"home.updates.3.text.1": "● Les services annexes sont disponibles.",
|
|
||||||
"home.updates.3.text.2": "● Changement d'hébergeur vers <a href=\"https://www.ionos.fr/\">IONOS</a>.",
|
|
||||||
"home.updates.3.text.3": "● Finition des pages annexes.",
|
|
||||||
|
|
||||||
"home.updates.2.date": "15 août 2023",
|
|
||||||
"home.updates.2.text.1": "● Le site internet est à nouveau disponible.",
|
|
||||||
"home.updates.2.text.2": "● Mise en place d'un nouveau design plus léger.",
|
|
||||||
"home.updates.2.text.3": "● Changement d'hébergeur vers <a href=\"https://hostbrr.com/\">HostBrr</a>.",
|
|
||||||
"home.updates.2.text.4": "● Ajout d'une nouvelle section pour les outils.",
|
|
||||||
|
|
||||||
"home.updates.1.date": " 9 septembre 2022",
|
|
||||||
"home.updates.1.text.1": "● Changement d'hébergeur vers v6Node."
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"lang.menu.title": "Langue",
|
|
||||||
"lang.current": "Français",
|
|
||||||
"lang.automatic": "Automatique",
|
|
||||||
"lang.english": "Anglais",
|
|
||||||
"lang.french": "Français",
|
|
||||||
"lang.german": "Allemand",
|
|
||||||
"lang.luxembourgish": "Luxembourgeois"
|
|
||||||
}
|
|
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"links.head.title": "Liens - NibblePoker",
|
|
||||||
"links.head.description": "TODO: description",
|
|
||||||
"links.og.title": "NibblePoker - Liens",
|
|
||||||
"links.og.description": "TODO: description",
|
|
||||||
"links.header.title": "Liens",
|
|
||||||
|
|
||||||
"links.social.title": "Réseaux Sociaux",
|
|
||||||
"links.work.title": "Travail & Freelancing",
|
|
||||||
"links.misc.title": "Autres liens",
|
|
||||||
|
|
||||||
"links.twitter.title": "Twitter <i>(@NibblePoker)</i>",
|
|
||||||
"links.twitter.text.1": "Des discussions et posts sur les projets sur lesquels je travaille.",
|
|
||||||
|
|
||||||
"links.github.title": "GitHub <i>(@aziascreations)</i>",
|
|
||||||
"links.github.text.1": "Compte privé contenant tous mes projets personnels.",
|
|
||||||
|
|
||||||
"links.github_pro.title": "GitHub <i>(@NibblePoker)</i>",
|
|
||||||
"links.github_pro.text.1": "Organisation contenant tout les dépôts en relation avec ce site web.",
|
|
||||||
|
|
||||||
"links.linkedin.title": "LinkedIn",
|
|
||||||
"links.linkedin.text.1": "???",
|
|
||||||
|
|
||||||
"links.malt.title": "Malt",
|
|
||||||
"links.malt.text.1": "???",
|
|
||||||
|
|
||||||
"links.gitea.title": "Gitea auto-hébergé",
|
|
||||||
"links.gitea.text.1": "Contient tous mes projets et des miroirs provenant de divers sites.",
|
|
||||||
|
|
||||||
"links.files.title": "Fichiers publiques",
|
|
||||||
"links.files.text.1": "Contient tout les fichiers pouvant être téléchargé sur ce site web et dans ma documentation.",
|
|
||||||
|
|
||||||
"links.archives.title": "Archives publiques",
|
|
||||||
"links.archives.text.1": "Contient une variété d'archives publiques."
|
|
||||||
}
|
|
@@ -1,75 +0,0 @@
|
|||||||
{
|
|
||||||
"privacy.head.title": "Politique de confidentialité - NibblePoker",
|
|
||||||
"privacy.head.description": "Notre politique de confidentialité dans un format clair et compréhensible.",
|
|
||||||
"privacy.og.title": "NibblePoker - Politique de confidentialité",
|
|
||||||
"privacy.og.description": "Notre politique de confidentialité dans un format clair et compréhensible.",
|
|
||||||
"privacy.header.title": "Politique de confidentialité",
|
|
||||||
|
|
||||||
"privacy.introduction.title": "Introduction",
|
|
||||||
"privacy.introduction.text.1": "La politique de confidentialité ci-présente a été écrite en accord avec les articles 12 et 13 de la RGPD.",
|
|
||||||
"privacy.introduction.text.2": "Si vous souhaitez consulter le texte officiel en question, vous pouvez le faire sur les sites internet suivants :",
|
|
||||||
|
|
||||||
"privacy.contact.title": "Comment nous contacter ?",
|
|
||||||
"privacy.contact.text.1": "Si vous souhaitez nous contacter afin d'obtenir plus d'informations concernant notre politique de confidentialité, nous vous recommandons d'utiliser le formulaire présent sur la page de contact, ou par courriel à l'adresse suivante:",
|
|
||||||
|
|
||||||
"privacy.complaint.title": "Comment contacter les autorités compétentes ?",
|
|
||||||
"privacy.complaint.text.1": "Dans l'éventualité où vous souhaiteriez déposer une plainte pour une quelconque raison en rapport avec notre politique de confidentialité, veuillez vous adresser à l'autorité nationale de protection des données (DPA).",
|
|
||||||
"privacy.complaint.text.2": "Les informations concernant cette procédure peuvent être trouvées sur les sites internet suivants:",
|
|
||||||
|
|
||||||
"privacy.v2.data.title": "Collecte de données (Web)",
|
|
||||||
"privacy.v2.data.intro.1": "Ce site web collecte des données au travers des journaux d'évènements afin de détecter et bloquer de potentiels acteurs malveillants.",
|
|
||||||
"privacy.v2.data.intro.2": "Les données collectées ne sont en aucun cas utilisées pour une quelconque autre raison.",
|
|
||||||
"privacy.v2.data.private.1": "Voici la liste des données personnelles collectées:",
|
|
||||||
"privacy.v2.data.private_list.1": "L'addresse IP source",
|
|
||||||
"privacy.v2.data.private_list.2": "Le \"User-Agent\" de votre navigateur internet",
|
|
||||||
"privacy.v2.data.non_private.1": "Et voici la liste des données non-personnelles collectées:",
|
|
||||||
"privacy.v2.data.non_private_list.1": "L'URI de la ressource demandée",
|
|
||||||
"privacy.v2.data.non_private_list.2": "La date et l'heure",
|
|
||||||
"privacy.v2.data.end.1": "Les données présentes dans les journaux d'évènements sont extraites et retirées pour être traitées par des applications qui tournent en local toute les 30 à 60 secondes.",
|
|
||||||
"privacy.v2.data.end.2": "L'application en question utilise et compare ces informations avec une liste d'acteurs malveillants et comportement suspects connus.<br>Si une correspondance est détectée, les informations privées sont stockées pendant 7 jours en attendant qu'un examen manuel soit effectué.",
|
|
||||||
"privacy.v2.data.end.3": "Après cette période de 7 jours, ou après qu'un examen ait été effectué, les données sont automatiquement supprimées.",
|
|
||||||
"privacy.v2.data.end.4": "Toute information concernant une requête non suspecte est automatiquement supprimée.",
|
|
||||||
"privacy.v2.data.end.5": "Ce processus n'est normalement jamais utilisé sur des requêtes provenant d'un trafic légitime dû au fait qu'il isole principalement les actions et requêtes qui ne devraient pas être possible sur ce site.",
|
|
||||||
"privacy.v2.data.end.6": "Cependant, ce processus n'est pas infaillible et il est toujours possible qu'une requête soit isolée par erreur.",
|
|
||||||
|
|
||||||
"privacy.v2.data_dns.title": "Collecte de données (DNS)",
|
|
||||||
"privacy.v2.data_dns.intro.1": "Nos serveurs <abbr title=\"Service de nom de domaine\">DNS</abbr> collectent des données au travers des journaux d'évènements afin de détecter et bloquer de potentiels acteurs malveillants.",
|
|
||||||
"privacy.v2.data_dns.intro.2": "Les données collectées ne sont en aucun cas utilisées pour une quelconque autre raison.",
|
|
||||||
"privacy.v2.data_dns.private.1": "Voici la liste des données personnelles collectées:",
|
|
||||||
"privacy.v2.data_dns.private_list.1": "L'addresse IP source",
|
|
||||||
"privacy.v2.data_dns.non_private.1": "Et voici la liste des données non-personnelles collectées:",
|
|
||||||
"privacy.v2.data_dns.non_private_list.1": "L'enregistrement DNS demandée",
|
|
||||||
"privacy.v2.data_dns.non_private_list.2": "La date et l'heure",
|
|
||||||
"privacy.v2.data_dns.end.1": "Toutes les données personnelles sont automatiquement supprimées après une période de 7 jours.",
|
|
||||||
|
|
||||||
"privacy.v2.update.title": "Changements à notre politique de confidentialité",
|
|
||||||
"privacy.v2.update.intro.1": "Le contenu de notre politique de confidentialité a été originalement écrit et le 4 décembre 2021 modifié pour la dernière fois le 18 mars 2022.",
|
|
||||||
"privacy.v2.update.history.1.date": "2021/12/04",
|
|
||||||
"privacy.v2.update.history.1.desc.1": "Version originale",
|
|
||||||
"privacy.v2.update.history.2.date": "2022/03/18",
|
|
||||||
"privacy.v2.update.history.2.desc.1": "Mise-à-jour de la section sur la collection des données.",
|
|
||||||
"privacy.v2.update.history.2.desc.2": "Ajout d'une mention de CloudFlare et ajout de liens vers leur politique de confidentialité.",
|
|
||||||
"privacy.v2.update.history.2.desc.3": "Amélioration de la section <i>\"Changements à notre politique de confidentialité\"</i>.",
|
|
||||||
"privacy.v2.update.history.3.date": "2022/09/09",
|
|
||||||
"privacy.v2.update.history.3.desc.1": "Changement des références aux services externes pour indiquer l'utilisation de v6Node.",
|
|
||||||
"privacy.v2.update.history.3.desc.1.1": "Ajout de mentions de v6Node et liens vers leur politique de vie confidentialité.",
|
|
||||||
"privacy.v2.update.history.3.desc.1.2": "Suppression de mentions de CloudFlare.",
|
|
||||||
"privacy.v2.update.history.3.desc.2": "Changement de la section \"Cookies\" afin d'indiquer qu'ils ne seront plus utilisés sur les domaines publics.",
|
|
||||||
"privacy.v2.update.history.4.date": "2023/11/11",
|
|
||||||
"privacy.v2.update.history.4.desc.1": "Changement des références aux services externes pour indiquer l'utilisation de IONOS.",
|
|
||||||
"privacy.v2.update.history.4.desc.1.1": "Suppression de mentions de v6Node.",
|
|
||||||
"privacy.v2.update.history.4.desc.2": "Changement des temps de traitement et mentions de l'infrastructure dans la section <i>\"Changements à notre politique de confidentialité\"</i>.",
|
|
||||||
"privacy.v2.update.history.5.date": "2023/11/30",
|
|
||||||
"privacy.v2.update.history.5.desc.1": "Ajout de la section sur la collection des données par le serveur DNS.",
|
|
||||||
"privacy.v2.update.history.5.desc.2": "Changement des références aux services externes pour indiquer l'utilisation de ChicagoVPS.",
|
|
||||||
"privacy.v2.update.end.2": "En cas de changement, vous serez clairement informé et une copie des anciennes versions de notre politique sera disponible au travers de cette page.",
|
|
||||||
|
|
||||||
"privacy.v2.third.title": "Organismes tiers",
|
|
||||||
"privacy.v2.third.intro.1": "Ce site web utilise des <abbr title=\"Serveur privé virtuel\">VPS</abbr> proposés par IONOS et ChicagoVPS dans le but de mettre en place un système de <abbr title=\"Réseau de diffusion de contenu (CDN)\">RDC</abbr>.",
|
|
||||||
"privacy.v2.third.intro.2": "Ceci a pour but d'améliorer l'expérience des personnes le visitant grâce à un système de filtrage et caching privé.",
|
|
||||||
"privacy.v2.third.intro.3": "Due à la nature des serveurs loués, aucune donnée ne devraient être collectées de leur côté.",
|
|
||||||
"privacy.v2.third.intro.4": "Si vous souhaitez consulter leur politique de confidentialité ainsi que celle de leur partenaires, vous pouvez le faire en suivant les liens ci-dessous:",
|
|
||||||
|
|
||||||
"privacy.v2.cookies.title": "Cookies de navigation",
|
|
||||||
"privacy.v2.cookies.intro.1": "Ce site web n'utilise pas, et ne stocke aucun cookies dans votre navigateur internet."
|
|
||||||
}
|
|
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"sidebar.alt.logo": "Logo du site web",
|
|
||||||
"sidebar.text.home": "Accueil",
|
|
||||||
"sidebar.text.shop": "Magasin",
|
|
||||||
"sidebar.text.school": "Formations",
|
|
||||||
"sidebar.text.projects": "Projets",
|
|
||||||
"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",
|
|
||||||
"sidebar.text.gitea": "Dépôts Git",
|
|
||||||
"sidebar.text.wiki": "Wiki",
|
|
||||||
"sidebar.text.about": "À-propos",
|
|
||||||
"sidebar.text.contributors": "Contributeurs",
|
|
||||||
"sidebar.text.contact": "Contact"
|
|
||||||
}
|
|
@@ -1,60 +0,0 @@
|
|||||||
<?php
|
|
||||||
$start_time = microtime(true);
|
|
||||||
set_include_path('../');
|
|
||||||
include_once 'commons/config.php';
|
|
||||||
include_once 'commons/langs.php';
|
|
||||||
?>
|
|
||||||
<!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 class="layout-generic">
|
|
||||||
<?php
|
|
||||||
include_once 'commons/DOM/utils.php';
|
|
||||||
$SIDEBAR_IDS = ['contact'];
|
|
||||||
include 'commons/DOM/sidebar.php';
|
|
||||||
?>
|
|
||||||
<header class="w-full p-m pl-s">
|
|
||||||
<h1 class="t-size-17 t-w-500">
|
|
||||||
<i class="fad fa-mailbox t-size-16 mr-s t-muted"></i><?php print(localize("contact.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("contact.email.title"), "fad fa-mail-bulk", "herwin.bozet@gmail.com"); ?>
|
|
||||||
<p class="m-s">
|
|
||||||
<a href="mailto:Herwin Bozet<herwin.bozet@gmail.com>?subject=Contact%20via%20NibblePoker.lu" class="a-hidden button-link">
|
|
||||||
<button class="p-xs r-s border b-light success"><i class="fad fa-external-link-alt mr-xs"></i><?php print(localize("contact.email.compose")); ?></button>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<?php printMainHeader(localize("contact.twitter.title"), "fab fa-twitter", "@NibblePoker"); ?>
|
|
||||||
<p class="m-s">
|
|
||||||
<a href="https://twitter.com/messages/compose?recipient_id=937370791334895616" class="a-hidden button-link">
|
|
||||||
<button class="p-xs r-s border b-light primary"><i class="fad fa-external-link-alt mr-xs"></i><?php print(localize("contact.twitter.compose")); ?></button>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</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 -->");
|
|
||||||
}
|
|
||||||
?>
|
|
@@ -1,6 +0,0 @@
|
|||||||
# Serving minified pages and/or pre-rendered ones first if available.
|
|
||||||
DirectoryIndex index.min.html index.min.php index.php index.html
|
|
||||||
|
|
||||||
# Redirecting any URL that starts with "/content" to the root of this folder.
|
|
||||||
RewriteEngine On
|
|
||||||
RewriteRule ^(.*) index.php [NC]
|
|
@@ -1,236 +0,0 @@
|
|||||||
<?php
|
|
||||||
$start_time = microtime(true);
|
|
||||||
|
|
||||||
// Importing required scripts.
|
|
||||||
set_include_path('../');
|
|
||||||
include_once 'commons/config.php';
|
|
||||||
include_once 'commons/langs.php';
|
|
||||||
|
|
||||||
// Preparing the content
|
|
||||||
include_once 'commons/content/manager.php';
|
|
||||||
include_once 'commons/content/composer.php';
|
|
||||||
$contentManager = ContentManager::createContentManager($config_dir_content);
|
|
||||||
$content = NULL;
|
|
||||||
if(!$contentManager->hasError && $contentManager->displayType == EContentDisplayType::DISPLAY) {
|
|
||||||
$content = load_content_by_file_path($contentManager->contentFilepath);
|
|
||||||
if(is_null($content)) {
|
|
||||||
$contentManager->hasError = true;
|
|
||||||
$contentManager->errorMessageKey = "content.error.message.cannot.load";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$content_error_message = localize($contentManager->errorMessageKey);
|
|
||||||
|
|
||||||
// Checking if an error occurred while loading data and parsing the URL.
|
|
||||||
// And if not, enabling special features.
|
|
||||||
$content_error_code = 200;
|
|
||||||
if($contentManager->hasError) {
|
|
||||||
// TODO: Add condition for the lack of data for an item.
|
|
||||||
if(is_null($contentManager->rootIndexEntries)) {
|
|
||||||
// Failed to get a display type or to extract types.
|
|
||||||
header("HTTP/1.1 400 Bad Request");
|
|
||||||
$content_error_code = 400;
|
|
||||||
} else {
|
|
||||||
//Other error. (No article, ...)
|
|
||||||
header("HTTP/1.1 500 Internal Server Error");
|
|
||||||
$content_error_code = 500;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$enable_code_highlight = true;
|
|
||||||
$enable_gallery = true;
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="<?php echo($user_language); ?>">
|
|
||||||
<head>
|
|
||||||
<?php
|
|
||||||
// Remark: The 'glider' and 'highlight.js' stylesheets are included here.
|
|
||||||
include 'commons/DOM/head.php';
|
|
||||||
|
|
||||||
$content_head_image = $host_uri . "/resources/NibblePoker/images/logos/v2_opengraph.png";
|
|
||||||
$content_head_image_type = "image/png";
|
|
||||||
|
|
||||||
// Preparing values for the head's tags.
|
|
||||||
if ($contentManager->hasError) {
|
|
||||||
$content_head_title = localize("content.error.head.title");
|
|
||||||
$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 == EContentDisplayType::DISPLAY) {
|
|
||||||
$content_head_title =
|
|
||||||
localize("content.item.head.title.prefix") .
|
|
||||||
$content->get_head_title() .
|
|
||||||
localize("content.item.head.title.suffix");
|
|
||||||
$content_head_description = $content->get_head_description();
|
|
||||||
$content_head_og_title =
|
|
||||||
localize("content.item.og.title.prefix") .
|
|
||||||
$content->get_head_title() .
|
|
||||||
localize("content.item.og.title.suffix");
|
|
||||||
$content_head_og_description = $content->get_head_description();
|
|
||||||
|
|
||||||
if(!is_null($content->metadata->opengraph->image)) {
|
|
||||||
$content_head_image = $host_uri . $content->metadata->opengraph->image;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_null($content->metadata->opengraph->image_type)) {
|
|
||||||
$content_head_image_type = $content->metadata->opengraph->image_type;
|
|
||||||
} else {
|
|
||||||
switch(pathinfo($content_head_image, PATHINFO_EXTENSION)) {
|
|
||||||
case "png":
|
|
||||||
$content_head_image_type = "image/png";
|
|
||||||
break;
|
|
||||||
case "jpg":
|
|
||||||
case "jpeg":
|
|
||||||
$content_head_image_type = "image/jpeg";
|
|
||||||
break;
|
|
||||||
case "gif":
|
|
||||||
$content_head_image_type = "image/gif";
|
|
||||||
break;
|
|
||||||
case "svg":
|
|
||||||
$content_head_image_type = "image/svg+xml";
|
|
||||||
break;
|
|
||||||
case "webp":
|
|
||||||
$content_head_image_type = "image/webp";
|
|
||||||
break;
|
|
||||||
case "apng":
|
|
||||||
$content_head_image_type = "image/apng";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} 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");
|
|
||||||
$content_head_og_description = localize("content.search.og.description");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Fix the OG URL tag to add the tags !
|
|
||||||
?>
|
|
||||||
<title><?php echo($content_head_title); ?></title>
|
|
||||||
<meta name="description" content="<?php echo($content_head_description); ?>">
|
|
||||||
<meta property="og:title" content="<?php echo($content_head_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($content_head_image); ?>"/>
|
|
||||||
<meta property="og:image:type" content="<?php echo($content_head_image_type); ?>"/>
|
|
||||||
<meta property="og:description" content="<?php echo($content_head_og_description); ?>"/>
|
|
||||||
</head>
|
|
||||||
<body class="layout-generic">
|
|
||||||
<?php
|
|
||||||
include_once 'commons/DOM/utils.php';
|
|
||||||
$SIDEBAR_IDS = array_merge(['content'], is_null($contentManager->requestedTags) ? [] : $contentManager->requestedTags);
|
|
||||||
include 'commons/DOM/sidebar.php';
|
|
||||||
?>
|
|
||||||
<header class="w-full p-m pl-s">
|
|
||||||
<h1 class="t-size-17 t-w-500">
|
|
||||||
<?php
|
|
||||||
if($contentManager->hasError) {
|
|
||||||
echo('<i class="fad fa-exclamation-triangle 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.error.header"));
|
|
||||||
echo('</span>');
|
|
||||||
} 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 == 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">');
|
|
||||||
echo('<span class="mx-s t-size-15">❱</span>');
|
|
||||||
echo('<span class="t-size-16">' . $content->get_head_title() . '</span>');
|
|
||||||
echo('</span>');
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</h1>
|
|
||||||
<?php include 'commons/DOM/header-lang.php'; ?>
|
|
||||||
</header>
|
|
||||||
<main id="main" class="rl-m border border-r-0 p-l">
|
|
||||||
<?php
|
|
||||||
// Checking if an error occurred.
|
|
||||||
if($content_error_code != 200) {
|
|
||||||
if($contentManager->displayType == EContentDisplayType::SEARCH) {
|
|
||||||
printMainHeader(localize("content.error.heading.main.search"), "fad fa-exclamation-triangle");
|
|
||||||
} 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
echo('<h3 class="mt-m t-size-18 t-center content-error-text mx-auto">' . $content_error_message . '</h3>');
|
|
||||||
|
|
||||||
goto content_printing_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($contentManager->displayType == EContentDisplayType::SEARCH) {
|
|
||||||
// We are handling a content search with at least one result.
|
|
||||||
|
|
||||||
// Making the header with the amount of results.
|
|
||||||
printMainHeader(
|
|
||||||
count($contentManager->rootIndexEntries) > 1 ?
|
|
||||||
localize("content.search.heading.main.multiple") :
|
|
||||||
localize("content.search.heading.main.single"),
|
|
||||||
"fad fa-file-search",
|
|
||||||
count($contentManager->rootIndexEntries) . " " . (
|
|
||||||
count($contentManager->rootIndexEntries) > 1 ?
|
|
||||||
localize("content.search.count.multiple") :
|
|
||||||
localize("content.search.count.single")));
|
|
||||||
|
|
||||||
// Printing the entry for each piece of relevant content.
|
|
||||||
$doPrintRuler = false;
|
|
||||||
foreach($contentManager->rootIndexEntries as $current_content) {
|
|
||||||
/** @var ContentIndexEntry $current_content */
|
|
||||||
|
|
||||||
if($doPrintRuler) {
|
|
||||||
echo('<hr class="subtle">');
|
|
||||||
} else {
|
|
||||||
$doPrintRuler = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo('<div class="p-s">');
|
|
||||||
echo('<a class="casper-link" href="'.l10n_url_abs("/content/".$current_content->id).'">');
|
|
||||||
echo('<div class="content-search-entry">');
|
|
||||||
|
|
||||||
echo('<img class="content-search-image mr-s r-l" src="' . $current_content->image . '">');
|
|
||||||
echo('<h3 class="mb-xs">' . $current_content->title[$user_language] . '</h3>');
|
|
||||||
echo('<p>' . $current_content->preamble[$user_language] . '</p>');
|
|
||||||
|
|
||||||
echo('</div>');
|
|
||||||
echo('</a>');
|
|
||||||
|
|
||||||
echo('<p class="mt-xs"><i class="fad fa-tags t-size-8"></i>');
|
|
||||||
foreach($current_content->tags as $current_content_tag) {
|
|
||||||
echo('<a href="' . l10n_url_abs("/content/?tags=".$current_content_tag) .
|
|
||||||
'" class="ml-xs">#' . $current_content_tag . '</a>');
|
|
||||||
}
|
|
||||||
echo('</p>');
|
|
||||||
|
|
||||||
echo('</div>');
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Print the tags used in the search and others that may be available.
|
|
||||||
} elseif($contentManager->displayType == EContentDisplayType::DISPLAY) {
|
|
||||||
// Printing the content
|
|
||||||
echo($content->get_html());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Label used when there is an error to skip the content printing parts.
|
|
||||||
content_printing_end:
|
|
||||||
?>
|
|
||||||
</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 -->");
|
|
||||||
}
|
|
||||||
?>
|
|
@@ -1,158 +0,0 @@
|
|||||||
{
|
|
||||||
"strings": {
|
|
||||||
"en": {
|
|
||||||
"meta.title": "CircuitPython - Custom File Systems",
|
|
||||||
"meta.description": "A set of examples of custom file systems and block-level devices for CircuitPython that can be used for educational purposes and expanded upon.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/CircuitPython-CustomFileSystems\"><i class=\"fab fa-github\"></i> View on GitHub</a>",
|
|
||||||
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "This project contains a set of examples of custom file systems and block-level devices for CircuitPython that can be used for educational purposes and expanded upon.",
|
|
||||||
"intro.p2": "All these examples are thoroughly documented in order to allow you to understand how each method of a virtual FS/BLD works, and also to show you some of the undocumented methods for these.",
|
|
||||||
|
|
||||||
"requirements.title": "Requirements",
|
|
||||||
"requirements.1": "A MCU with CircuitPython 8.0 or newer",
|
|
||||||
"requirements.1.1": "Access to the <a href=\"https://docs.circuitpython.org/en/latest/shared-bindings/zlib/index.html\">zlib</a> (Required for most block-level devices)",
|
|
||||||
"requirements.1.2": "Wi-Fi connectivity is required for some examples",
|
|
||||||
"requirements.1.3": "Around 1MiB of disk space and 48 KiB of RAM free on the MCU",
|
|
||||||
"requirements.2": "A way to mount disk images on you computer for block-level projects",
|
|
||||||
"requirements.2.1": "<a href=\"https://sourceforge.net/projects/imdisk-toolkit/\">ImDisk's Ram Disk tool</a> is recommended for Windows.",
|
|
||||||
"requirements.2.2": "I don't know about Linux, sorry.",
|
|
||||||
"requirements.3": "A lot of patience to deal with some of CircuitPython's quirks",
|
|
||||||
|
|
||||||
"fs.title": "File Systems",
|
|
||||||
|
|
||||||
"fs.blank.title": "Blank",
|
|
||||||
"fs.blank.p1": "Blank file system with a lot of comments on how each procedure works and what it should return.<br>When its content is listed, it is shown as being empty.",
|
|
||||||
"fs.blank.p2": "This file system has a LOT more comments than the others which explains in much more details how each important method works.",
|
|
||||||
|
|
||||||
"fs.rom.title": "Read-Only Memory",
|
|
||||||
|
|
||||||
"bld.title": "Block-level Devices",
|
|
||||||
|
|
||||||
"bld.stub.title": "Stub",
|
|
||||||
"bld.stub.p1": "Stub of a generic block-level class without any code, but detailed comments for each required methods and their warnings and notes.",
|
|
||||||
"bld.stub.p2": "The reasoning behind not making this one a working class is that block-level devices require quite a bit more code to make them work as you need to create a working MBR and FAT partition.",
|
|
||||||
|
|
||||||
"bld.remote.title": "Remote",
|
|
||||||
|
|
||||||
"warning.title": "Warning",
|
|
||||||
"warning.p1": "Due to the way some commands are executed, it is possible to have a <a href=\"https://owasp.org/www-community/attacks/Command_Injection\">command injection vulnerability</a> if you mess up or leave the config file editable by everyone.",
|
|
||||||
"warning.p2": "This might be fixed in the future, but don't count on it as this project is a personal one.",
|
|
||||||
|
|
||||||
"features.title": "Features",
|
|
||||||
"features.list.1.1": "● General",
|
|
||||||
|
|
||||||
"links.title": "Links",
|
|
||||||
"_123": "https://files.nibblepoker.lu/downloads/CircuitPython-CustomFileSystems/CircuitPython-CustomFileSystems-master.zip"
|
|
||||||
},
|
|
||||||
"fr": {
|
|
||||||
"meta.title": "CircuitPython - Systèmes de fichiers personalisés",
|
|
||||||
"meta.description": "Un set de systèmes de fichiers et stockage en blocs personnalisés pour CircuitPython qui peuvent être utilisés afin d'apprendre leur fonctionnement ou améliorés et implémentés dans d'autres solutions.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/CircuitPython-CustomFileSystems\"><i class=\"fab fa-github\"></i> Voir sur GitHub</a>",
|
|
||||||
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "Ce projet contient un set de systèmes de fichiers et stockage en blocs personnalisés pour CircuitPython qui peuvent être utilisés afin d'apprendre leur fonctionnement ou améliorés et implémentés dans d'autres solutions.",
|
|
||||||
"intro.p2": "Tous ces exemples sont soigneusement documentés afin de vous permettre de comprendre le fonctionnement de chaque méthode d'un système de fichiers virtuel ou d'un stockage en blocs<br>Et en plus de cela, ils vous montreront certaines des méthodes non documentées.",
|
|
||||||
|
|
||||||
"requirements.title": "Dépendances",
|
|
||||||
"requirements.1": "Un MCU avec CircuitPython 8.0 ou une version plus récente",
|
|
||||||
"requirements.1.1": "Access to the <a href=\"https://docs.circuitpython.org/en/latest/shared-bindings/zlib/index.html\">zlib</a> (Required for most block-level devices)",
|
|
||||||
"requirements.1.2": "Wi-Fi connectivity is required for some examples",
|
|
||||||
"requirements.1.3": "Around 1MiB of disk space and 48 KiB of RAM free on the MCU",
|
|
||||||
"requirements.2": "A way to mount disk images on you computer for block-level projects",
|
|
||||||
"requirements.2.1": "<a href=\"https://sourceforge.net/projects/imdisk-toolkit/\">ImDisk's Ram Disk tool</a> is recommended for Windows.",
|
|
||||||
"requirements.2.2": "I don't know about Linux, sorry.",
|
|
||||||
"requirements.3": "A lot of patience to deal with some of CircuitPython's quirks",
|
|
||||||
|
|
||||||
"warning.title": "Avertissements",
|
|
||||||
"warning.p1": "Due au fait que certaines commandes sont exécutées avec des paramètres arbitraires configurables cette application est vulnérable aux attaques par <a href=\"https://owasp.org/www-community/attacks/Command_Injection\">injection de commande</a> si le fichier de configuration est modifiable par des personnes non autorisées.",
|
|
||||||
"warning.p2": "Ce problème sera probablement réglé dans le futur, mais il n'y a pas de date fixe comme ce projet est plus personnel qu'autre-chose.",
|
|
||||||
|
|
||||||
"features.title": "Fonctionnalités",
|
|
||||||
|
|
||||||
"links.title": "Liens"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"template": "generic-project-readme",
|
|
||||||
"head": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description"
|
|
||||||
},
|
|
||||||
"opengraph": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description",
|
|
||||||
"type": null,
|
|
||||||
"url": null,
|
|
||||||
"image": null,
|
|
||||||
"image_type": null
|
|
||||||
},
|
|
||||||
"article": {
|
|
||||||
"icon": "fab fa-python",
|
|
||||||
"title": "meta.title",
|
|
||||||
"subtitle": "article.subtitle",
|
|
||||||
"tags": ["electronic", "python", "circuitpython"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{"type": "h1", "content": "intro.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p2"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "requirements.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph", "indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.1.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.1.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.1.3"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "paragraph", "indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.2.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.2.2"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "paragraph", "indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.3"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "fs.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "fs.p1"},
|
|
||||||
{"type": "image", "src": "fuck"},
|
|
||||||
{"type": "h1", "content": "fs.blank.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "fs.blank.p1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "fs.blank.p2"},
|
|
||||||
{"type": "h1", "content": "fs.rom.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p2"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "bld.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "bld.p1"},
|
|
||||||
{"type": "image", "src": "fuck"},
|
|
||||||
{"type": "h1", "content": "bld.stub.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "bld.stub.p1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "bld.stub.p2"},
|
|
||||||
{"type": "h1", "content": "bld.remote.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p2"}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,483 +0,0 @@
|
|||||||
{
|
|
||||||
"strings": {
|
|
||||||
"en": {
|
|
||||||
"meta.title": "CircuitPython - Ebyte E32 Driver",
|
|
||||||
"meta.description": "CircuitPython driver for Ebyte's E32 UART LoRa modules that use the SX1278/SX1276 chipsets.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/CircuitPython-Ebyte-E32\"><i class=\"fab fa-github\"></i> View on GitHub</a>",
|
|
||||||
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "This project is a simple driver for CircuitPython that allows you to easily interact with Ebyte's E32 series of LoRa modules.",
|
|
||||||
|
|
||||||
"features.title": "Features",
|
|
||||||
"features.1": "Supports all standard E32 UART modules.",
|
|
||||||
"features.2": "Extra support on a per-frequency and per-power basis:",
|
|
||||||
"features.2.1": "More descriptive constants for TX power.",
|
|
||||||
"features.2.2": "<s>Maximum packet size calculators.</s> (TODO)",
|
|
||||||
"features.2.3": "Entirely optional via separate modules.",
|
|
||||||
"features.3": "Minified versions for devices with tiny storage space:",
|
|
||||||
"features.3.1": "~75% smaller for <code class=\"code\">.py</code> files",
|
|
||||||
"features.3.2": "~5% smaller for <code class=\"code\">.mpy</code> files <i>(Due to shortened local variables, mostly)</i>",
|
|
||||||
|
|
||||||
"limitations.title": "Limitations",
|
|
||||||
"limitations.1": "No built-in packet size limit:",
|
|
||||||
"limitations.1.1": "Wildly different between frequencies & operating parameters.",
|
|
||||||
"limitations.1.2": "Not documented clearly enough in LoRA and LoRaWAN documentation.",
|
|
||||||
"limitations.2": "No built-in protocol:",
|
|
||||||
"limitations.2.1": "All LoRa packets are glued back-to-back when received.",
|
|
||||||
"limitations.2.2": "No LoraWAN support",
|
|
||||||
"limitations.3": "Missing support for some modules:",
|
|
||||||
"limitations.3.1": "Modules with <code class=\"code\">170</code>, <code class=\"code\">400</code> and <code class=\"code\">900</code> prefix. (Will improve overtime)",
|
|
||||||
|
|
||||||
"doc.title": "Documentation",
|
|
||||||
"doc.p1": "The entire documentation for this project can be found on Github.<br>The datasheets for all the E32 modules can also be found on \"<a href=\"https://files.nibblepoker.lu/datasheets/ebyte/e32/\">files.nibblepoker.lu</a>\".",
|
|
||||||
|
|
||||||
"usage.title": "Usage",
|
|
||||||
"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> 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",
|
|
||||||
"links.title": "Links"
|
|
||||||
},
|
|
||||||
"fr": {
|
|
||||||
"meta.title": "CircuitPython - Driver Ebyte E32",
|
|
||||||
"meta.description": "Driver CircuitPython pour les modules sérial LoRa E32 de Ebyte tournant sous les chipset SX1278/SX1276.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/CircuitPython-Ebyte-E32\"><i class=\"fab fa-github\"></i> Voir sur GitHub</a>",
|
|
||||||
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "Ce projet est un driver qui vous permet d'interagir avec la série de modules LoRa E32 d'Ebyte dans CircuitPython.",
|
|
||||||
|
|
||||||
"features.title": "Fonctionnalités",
|
|
||||||
"features.1": "Prend en charge tous les modules E32 UART standards.",
|
|
||||||
"features.2": "Support supplémentaire en fonction de la fréquence et de la puissance :",
|
|
||||||
"features.2.1": "Constantes pour la puissance d'émission.",
|
|
||||||
"features.2.2": "<s>Calculatrices de taille de paquet maximale.</s> (À FAIRE)",
|
|
||||||
"features.2.3": "Entièrement facultatif via des modules séparés.",
|
|
||||||
"features.3": "Versions minifiées pour les appareils avec un espace de stockage réduit :",
|
|
||||||
"features.3.1": "~75 % plus petites pour les fichiers <code class=\"code\">.py</code>",
|
|
||||||
"features.3.2": "~5 % plus petites pour les fichiers <code class=\"code\">.mpy</code>",
|
|
||||||
|
|
||||||
"limitations.title": "Limitations",
|
|
||||||
"limitations.1": "Aucune limitation de taille de paquet intégrée :",
|
|
||||||
"limitations.1.1": "Varie grandement entre les fréquences et les paramètres d'utilisation.",
|
|
||||||
"limitations.1.2": "Pas suffisamment documentée dans les spécifications techniques de LoRA et LoRaWAN.",
|
|
||||||
"limitations.2": "Aucun protocole intégré :",
|
|
||||||
"limitations.2.1": "Tous les paquets LoRa sont collés les uns aux autres dans un buffer lors de la réception.",
|
|
||||||
"limitations.2.2": "Aucun support pour LoRaWAN. (Limitation du module)",
|
|
||||||
"limitations.3": "Support avancé manquant pour certains modules :",
|
|
||||||
"limitations.3.1": "Modules avec les préfixes <code class=\"code\">170</code>, <code class=\"code\">400</code> ou <code class=\"code\">900</code>. (S'améliorera avec le temps)",
|
|
||||||
|
|
||||||
"doc.title": "Documentation",
|
|
||||||
"doc.p1": "Toute la documentation de ce projet est disponible sur Github.<br>Les fiches techniques de tous les modules E32 peuvent également être trouvées sur \"<a href=\"https://files.nibblepoker.lu/datasheets/ebyte/e32/\">files.nibblepoker.lu</a>\".",
|
|
||||||
|
|
||||||
"usage.title": "Utilisation",
|
|
||||||
"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 <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",
|
|
||||||
"links.title": "Liens"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"template": "generic-project-readme",
|
|
||||||
"head": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description"
|
|
||||||
},
|
|
||||||
"opengraph": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description",
|
|
||||||
"type": null,
|
|
||||||
"url": null,
|
|
||||||
"image": "/resources/NibblePoker/images/content/circuitpython-ebyte-e32/main.png",
|
|
||||||
"image_type": null
|
|
||||||
},
|
|
||||||
"article": {
|
|
||||||
"icon": "fab fa-python",
|
|
||||||
"title": "meta.title",
|
|
||||||
"subtitle": "article.subtitle",
|
|
||||||
"tags": ["electronic", "python" ,"circuitpython", "lora", "library"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{"type": "h1", "content": "intro.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p1"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "features.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph", "indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "features.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "features.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "features.2.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "features.2.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "features.2.3"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "features.3"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "features.3.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "features.3.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "limitations.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph", "indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "limitations.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "limitations.1.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "limitations.1.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "limitations.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "limitations.2.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "limitations.2.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "limitations.3"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "limitations.3.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "doc.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "doc.p1"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "usage.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "usage.p1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "usage.p2"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2, "modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "code", "indent": 2,
|
|
||||||
"modifiers": ["horizontal-scroll-auto", "code-block"],
|
|
||||||
"language": "python", "copyable": true,
|
|
||||||
"code": [
|
|
||||||
"import board",
|
|
||||||
"import time",
|
|
||||||
"",
|
|
||||||
"import ebyte_e32",
|
|
||||||
"",
|
|
||||||
"PIN_M0 = board.IO13",
|
|
||||||
"PIN_M1 = board.IO12",
|
|
||||||
"PIN_RXD = board.IO11 # Pin marked as RX on the module",
|
|
||||||
"PIN_TXD = board.IO10 # Pin marked as TX on the module",
|
|
||||||
"PIN_AUX = board.IO9",
|
|
||||||
"",
|
|
||||||
"e32 = ebyte_e32.E32Device(PIN_M0, PIN_M1, PIN_AUX, PIN_TXD, PIN_RXD, address=0xBEEF, channel=4)",
|
|
||||||
"",
|
|
||||||
"# Switching to fixed transmission mode.",
|
|
||||||
"e32.tx_mode = ebyte_e32.TransmissionMode.TRANSMISSION_FIXED",
|
|
||||||
"",
|
|
||||||
"# Switching to mode 0. (Normal mode)",
|
|
||||||
"e32.mode = ebyte_e32.Modes.MODE_NORMAL",
|
|
||||||
"",
|
|
||||||
"# Message content:",
|
|
||||||
"# * Receiver's address: 0x1337 (b'\\13\\x37')",
|
|
||||||
"# * Receiver's channel: 4 (b'\\x04')",
|
|
||||||
"# * Message: b'Hello World !'",
|
|
||||||
"message = b'\\x13\\x37\\x04Hello World !'",
|
|
||||||
"",
|
|
||||||
"# Sending message with helper method",
|
|
||||||
"e32.send(message)",
|
|
||||||
"",
|
|
||||||
"# The message may be truncated at specific lengths depending on the frequencies used.",
|
|
||||||
"# Please check the documentation for more information !"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"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"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "table", "modifiers": ["stylish", "auto-cell-padding", "v-center-cells"],
|
|
||||||
"head": [
|
|
||||||
{"type": "raw", "content": "content.commons.version"},
|
|
||||||
{"type": "raw", "content": "<code class=\"code\">.py</code>", "localize": false},
|
|
||||||
{"type": "raw", "content": "<code class=\"code\">.min.py</code>", "localize": false},
|
|
||||||
{"type": "raw", "content": "<code class=\"code\">.mpy</code>", "localize": false},
|
|
||||||
{"type": "raw", "content": "<code class=\"code\">.min.mpy</code>", "localize": false}
|
|
||||||
],
|
|
||||||
"body": [[
|
|
||||||
{"type": "raw", "content": "v0.8.0", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin", "download-primary"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.8.0/nibblepoker-circuitpython-e32-driver_v0.8.0_py.zip",
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 10.42 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.8.0/nibblepoker-circuitpython-e32-driver_v0.8.0_py-min.zip",
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 4.79 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin", "download-primary"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.8.0/nibblepoker-circuitpython-e32-driver_v0.8.0_mpy-8.zip",
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 6.25 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.8.0/nibblepoker-circuitpython-e32-driver_v0.8.0_mpy-8-min.zip",
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 5.99 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "v0.7.0", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.7.0/nibblepoker-circuitpython-e32-driver_v0.7.0_py.zip",
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 10.51 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.7.0/nibblepoker-circuitpython-e32-driver_v0.7.0_py-min.zip",
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 4.79 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.7.0/nibblepoker-circuitpython-e32-driver_v0.7.0_mpy-8.zip",
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 6.26 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/CircuitPython-Ebyte-E32/0.7.0/nibblepoker-circuitpython-e32-driver_v0.7.0_mpy-8-min.zip",
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 5.99 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "v0.6.0", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"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> 10.39 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"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> 4.62 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"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> 6.10 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"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> 5.83 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "v0.4.0", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"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> 19.96 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"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> 4.18 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"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> 5.27 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"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> 5.04 KiB</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "license.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph", "indent": 2, "content": "content.commons.license.mit.single",
|
|
||||||
"link": "https://github.com/aziascreations/CircuitPython-Ebyte-E32/blob/master/LICENSE"
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "links.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://github.com/aziascreations/CircuitPython-Ebyte-E32",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "content.commons.github"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://aziascreations.github.io/CircuitPython-Ebyte-E32/",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "content.commons.doc.online"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,152 +0,0 @@
|
|||||||
{
|
|
||||||
"strings": {
|
|
||||||
"en": {
|
|
||||||
"meta.title": "DotNet-Arguments",
|
|
||||||
"meta.description": "A simple and 'to-the-point' library to parse launch arguments in .NET and .NET Core applications.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/DotNet-Arguments\" class=\"font-size-16\"><i class=\"fab fa-github\"></i> View on GitHub</a>",
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "A simple and 'to-the-point' library to parse launch arguments in .NET and .NET Core applications.",
|
|
||||||
"intro.p2": "This library is an improved port of my <a href=\"https://github.com/aziascreations/PB-Arguments\">PB-Arguments</a> library that intended to achieve the same goals but was missing support for some features.",
|
|
||||||
"requirements.title": "Requirements",
|
|
||||||
"requirements.1": ".NET v6.0+",
|
|
||||||
"requirements.2": "C# 10.0",
|
|
||||||
"documentation.title": "Documentation",
|
|
||||||
"documentation.1": "Go to \"<a href=\"https://aziascreations.github.io/DotNet-Arguments/\">aziascreations.github.io/DotNet-Arguments/</a>\" for the HTML documentation.",
|
|
||||||
"example.title": "Basic Example",
|
|
||||||
"license.title": "License",
|
|
||||||
"links.title": "Links"
|
|
||||||
},
|
|
||||||
"fr": {
|
|
||||||
"meta.title": "DotNet-Arguments",
|
|
||||||
"meta.description": "Une petite librairie simple et efficace pour lire et interpréter les options de lancement d'un programme pour .NET et .NET Core.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/DotNet-Arguments\" class=\"font-size-16\"><i class=\"fab fa-github\"></i> Voir sur GitHub</a>",
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "Une petite librarie efficace qui permet de facilement et simplement interpréter et utiliser les options de lancement d'un programme en .NET et .NET Core.",
|
|
||||||
"intro.p2": "Cette librairie est une version améliorée de mon ancienne librairie <a href=\"https://github.com/aziascreations/PB-Arguments\">PB-Arguments</a> qui visait à accomplir les mêmes goals mais à laquelle il manquait quelques fonctionnalités.",
|
|
||||||
"requirements.title": "Besoins système",
|
|
||||||
"requirements.1": ".NET v6.0+",
|
|
||||||
"requirements.2": "C# 10.0",
|
|
||||||
"documentation.title": "Documentation",
|
|
||||||
"documentation.1": "Allez sur \"<a href=\"https://aziascreations.github.io/DotNet-Arguments/\">aziascreations.github.io/DotNet-Arguments/</a>\" pour consulter la documentation.",
|
|
||||||
"example.title": "Example basique",
|
|
||||||
"license.title": "Licence",
|
|
||||||
"links.title": "Liens"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"template": "generic-project-readme",
|
|
||||||
"head": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description"
|
|
||||||
},
|
|
||||||
"opengraph": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description",
|
|
||||||
"type": null,
|
|
||||||
"url": null,
|
|
||||||
"image": "/resources/NibblePoker/images/content/dotnet-arguments/main.png",
|
|
||||||
"image_type": null
|
|
||||||
},
|
|
||||||
"article": {
|
|
||||||
"icon": "fad fa-puzzle-piece",
|
|
||||||
"title": "meta.title",
|
|
||||||
"subtitle": "article.subtitle",
|
|
||||||
"tags": ["library", "dotnet"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{"type": "h1", "content": "intro.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p2"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "requirements.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "link": "https://dotnet.microsoft.com/en-us/download/dotnet/6.0", "content": "requirements.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.2"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "documentation.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "documentation.1"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "example.title"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2, "modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "code", "indent": 2,
|
|
||||||
"modifiers": ["horizontal-scroll-auto", "code-block"],
|
|
||||||
"language": "csharp", "copyable": true,
|
|
||||||
"code": [
|
|
||||||
"// Preparing options and root verb.",
|
|
||||||
"Option OptionHelp = new('h', \"help\", \"\", OptionFlags.StopsParsing);",
|
|
||||||
"Option OptionVerbose = new('v', \"verbose\", \"\", OptionFlags.Repeatable);",
|
|
||||||
"",
|
|
||||||
"Verb RootVerb = new Verb(\"\").RegisterOption(OptionHelp).RegisterOption(OptionVerbose);",
|
|
||||||
"",
|
|
||||||
"// Parsing lanch arguments",
|
|
||||||
"try {",
|
|
||||||
" ArgumentsParser.ParseArguments(RootVerb, args); // 'args' is gotten from Main().",
|
|
||||||
"} catch(ArgumentException) {",
|
|
||||||
" Console.Error.Write(\"Failed to parse the launch arguments !\");",
|
|
||||||
" RootVerb.Clear(); // Ignoring the error and simulating no launch parameters.",
|
|
||||||
"}",
|
|
||||||
"",
|
|
||||||
"// Using the results",
|
|
||||||
"if(OptionHelp.WasUsed()) {",
|
|
||||||
" Console.WriteLine(HelpText.GetFullHelpText(RootVerb, \"app.exe\"));",
|
|
||||||
"}",
|
|
||||||
"",
|
|
||||||
"if(OptionVerbose.WasUsed() && OptionVerbose.Occurrences >= 2) {",
|
|
||||||
" // We count the number of occurences to enable more logging.",
|
|
||||||
" Console.WriteLine(\"Activating super-verbose mode !\");",
|
|
||||||
"}"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "license.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph", "indent": 2, "content": "content.commons.license.mit.single",
|
|
||||||
"link": "https://github.com/aziascreations/DotNet-Arguments/blob/master/LICENSE"
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "links.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://github.com/aziascreations/DotNet-Arguments",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "content.commons.github"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://aziascreations.github.io/DotNet-Arguments/",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "content.commons.doc.online"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://www.nuget.org/packages/NibblePoker.Library.Arguments",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "content.commons.nuget"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,106 +0,0 @@
|
|||||||
{
|
|
||||||
"strings": {
|
|
||||||
"en": {
|
|
||||||
"meta.title": "Excel Worksheet Password Remover",
|
|
||||||
"meta.description": "Small web page from which you can easily remove a password from an Excel worksheet. It works by leaving the task of editing the XML files on an Excel document to your browser instead to keep everything local.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/Excel-Worksheet-Password-Remover\"><i class=\"fab fa-github\"></i> View on GitHub</a>",
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "This project aims to simplify the removal of passwords on Excel's Worksheet by leaving the task of editing the XML files on an Excel document to your browser.",
|
|
||||||
"working.title": "Security & Internal workings",
|
|
||||||
"working.p1": "In terms of security, your browser handles all the data without sending any of it to a central server like many web apps do.<br>This makes it, and your data, as safe as your browser can be since it is the only potential point of failure here.",
|
|
||||||
"working.p2": "As for the internal workings, the only thing this tool does is extract the content of the <code>.xlsx</code> file you gave it and removes the passwords on any worksheets and makes a new file with all the changes.<br>Once all of that is done, the file is downloaded via a <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs\">data URL</a>.",
|
|
||||||
"usage.title": "Usage",
|
|
||||||
"usage.p1": "To use this tool you can either visit \"<a href=\"https://aziascreations.github.io/Excel-Worksheet-Password-Remover\">aziascreations.github.io/Excel-Worksheet-Password-Remover</a>\" or download the repository and host the web page yourself.",
|
|
||||||
"demo.title": "Demonstration video",
|
|
||||||
"links.title": "Links",
|
|
||||||
"content.link.demo": "Demo hosted on GitHub"
|
|
||||||
},
|
|
||||||
"fr": {
|
|
||||||
"_meta.title": "",
|
|
||||||
"meta.description": "Petite application web qui permet de facilement retirer le mot de passe d'une feuille de calcul Excel depuis votre navigateur web sans avoir à uploader le fichier sur internet. Cette application laisse votre navigateur modifier les fichiers XML du fichier Excel afin de tout garder en local.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/Excel-Worksheet-Password-Remover\"><i class=\"fab fa-github\"></i> Voir sur GitHub</a>",
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "Ce projet vise à simplifier le processus de suppression des mots de passes sur les \"worksheet\" d'Excel en laissant votre navigateur web s'en charger.",
|
|
||||||
"working.title": "Sécurité & Fonctionnement",
|
|
||||||
"working.p1": "Cet outil charge le ficher que vous lui donnez en mémoire et travaille directement dessus dans le navigateur web sans utiliser un serveur central, vos données restent donc entièrement sur votre machine.",
|
|
||||||
"working.p2": "Par sécurité, nous vous demandons quand même de n'utiliser cet outil qu'avec des fichiers pour lesquels vous avez été explicitement autorisés à enlever le mot de passe.",
|
|
||||||
"usage.title": "Utilisation",
|
|
||||||
"usage.p1": "Vous pouvez utiliser cet outil en allant sur \"<a href=\"https://aziascreations.github.io/Excel-Worksheet-Password-Remover\">aziascreations.github.io/Excel-Worksheet-Password-Remover</a>\" ou en téléchargeant le dépôt et en hébergeant la page web vous-même.",
|
|
||||||
"demo.title": "Vidéo de démonstration",
|
|
||||||
"links.title": "Liens",
|
|
||||||
"content.link.demo": "Démo hébergée sur GitHub"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"template": "generic-project-readme",
|
|
||||||
"head": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description"
|
|
||||||
},
|
|
||||||
"opengraph": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description",
|
|
||||||
"type": null,
|
|
||||||
"url": null,
|
|
||||||
"image": "/resources/NibblePoker/images/content/excel-password-remover/excel-password-remover.png",
|
|
||||||
"image_type": null
|
|
||||||
},
|
|
||||||
"article": {
|
|
||||||
"icon": "fad fa-unlock",
|
|
||||||
"title": "meta.title",
|
|
||||||
"subtitle": "article.subtitle",
|
|
||||||
"tags": ["tool", "web"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{"type": "h1", "content": "intro.title", "modifiers": ["_no-top-margin"]},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p1"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "working.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "working.p1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "working.p2"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "usage.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "usage.p1"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "demo.title"},
|
|
||||||
{
|
|
||||||
"type": "container",
|
|
||||||
"modifiers": ["pb-0"],
|
|
||||||
"padding": 2,
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "video",
|
|
||||||
"source": "https://files.nibblepoker.lu/downloads/Excel-Worksheet-Password-Remover/demo_v1.mp4",
|
|
||||||
"thumbnail": "https://files.nibblepoker.lu/downloads/Excel-Worksheet-Password-Remover/demo_v1_thumb.webp"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "links.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://github.com/aziascreations/Excel-Worksheet-Password-Remover",
|
|
||||||
"sr_title": "Test 123",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "content.commons.github"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://aziascreations.github.io/Excel-Worksheet-Password-Remover",
|
|
||||||
"sr_title": "Test 123",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "content.link.demo"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,456 +0,0 @@
|
|||||||
{
|
|
||||||
"strings": {
|
|
||||||
"en": {
|
|
||||||
"meta.title": "DotNet-ListComPort",
|
|
||||||
"meta.description": "A simple CLI tool that can list COM ports with their name, friendly name and device name easily and cleanly.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/DotNet-ListComPort\" class=\"font-size-16\"><i class=\"fab fa-github\"></i> View on GitHub</a>",
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "A simple CLI tool that can list COM ports with their full name easily and cleanly.",
|
|
||||||
"intro.p2": "This tool is intended to replace the tedious task of having to use the <code class=\"code\">mode</code> command, and the <i>Device Manager</i> to find a newly plugged-in device that provides a COM port.",
|
|
||||||
"intro.p3": "This version of the program is a complete refactoring of my old <a href=\"https://github.com/aziascreations/PB-ListComPort\">PB-ListComPort</a> project that also changes from the proprietary and paid PureBasic language and compiler to .NET 6.0.",
|
|
||||||
"requirements.title": "Requirements",
|
|
||||||
"requirements.1": "Windows",
|
|
||||||
"requirements.2": "Any CPU architecture",
|
|
||||||
"requirements.3": ".NET 6.0",
|
|
||||||
"requirements.4": "Optional if using the larger \"self-contained\" builds.",
|
|
||||||
"improvements.title": "Improvements over PB-ListComPort",
|
|
||||||
"improvements.1": "Switched from PureBasic to .NET 6.0.",
|
|
||||||
"improvements.2": "Improved a lot of the program's logic.",
|
|
||||||
"improvements.3": "Added the <code>-H/--short-help</code>.",
|
|
||||||
"improvements.4": "Added support for Windows ARM & ARM64.",
|
|
||||||
"improvements.5": "Support for running without a console.",
|
|
||||||
"usage.title": "Usage",
|
|
||||||
"formatting.title": "Output formatting",
|
|
||||||
"requirements.table.title": "Requirements",
|
|
||||||
"requirements.text.dotnet": "<a href=\"https://dotnet.microsoft.com/en-us/download/dotnet/6.0\">.NET 6.0</a>",
|
|
||||||
"requirements.text.none.ms": "None",
|
|
||||||
"requirements.text.none.mp": "None",
|
|
||||||
"requirements.text.none.fs": "None",
|
|
||||||
"requirements.text.none.fp": "None",
|
|
||||||
"packages.title": "Packages",
|
|
||||||
"packages.single.title": "Single Builds",
|
|
||||||
"packages.single.1": "Lighter builds that only contain the exe and required licenses.<br>You will need to install the <a href=\"https://dotnet.microsoft.com/en-us/download\">.NET 6.0 Runtime</a>.",
|
|
||||||
"packages.self.title": "Self-Contained Builds",
|
|
||||||
"packages.self.1": "Larger builds that contain the exe and the <a href=\"https://dotnet.microsoft.com/en-us/download\">.NET 6.0 Runtime</a> as well as the required licenses.",
|
|
||||||
"packages.msi.title": "MSI Installers",
|
|
||||||
"packages.msi.1": "Windows installers that contain the relevant \"Self-Contained\" build with an option to automatically update existing installations and add the program to the <kbd>%PATH%</kbd>.<br>The install location is <kbd>%ProgramFiles%\\NibblePoker\\lscom\\</kbd> and cannot be changed. <i>(This will be possible in future releases)</i>",
|
|
||||||
"links.title": "Links",
|
|
||||||
"screenshots.title": "Screenshots"
|
|
||||||
},
|
|
||||||
"fr": {
|
|
||||||
"meta.title": "DotNet-ListComPort",
|
|
||||||
"meta.description": "Un petit utilitaire pour invité de commande qui permet de facilement lister les noms, noms formatés et chemin des ports COM.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/DotNet-ListComPort\" class=\"font-size-16\"><i class=\"fab fa-github\"></i> Voir sur GitHub</a>",
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "Un petit utilitaire pour invité de commande qui permet de facilement lister les noms, noms formatés et chemins des ports COM.",
|
|
||||||
"intro.p2": "Cet outil a pour bût de faciliter cette tâche sans avoir à utiliser la commande <code>mode</code> ou le <i>Gestionnaire de périphérique</i>.",
|
|
||||||
"intro.p3": "Cette version du programme a completement été réecrit depuis le projet original <a href=\"https://github.com/aziascreations/PB-ListComPort\">PB-ListComPort</a> en .NET 6.0 au lieu de PureBasic afin de ne plus utiliser de langage de programmation propriétaire.",
|
|
||||||
"requirements.title": "Dépendances",
|
|
||||||
"requirements.1": "Windows",
|
|
||||||
"requirements.2": "Toutes architectures de CPU",
|
|
||||||
"requirements.3": ".NET 6.0",
|
|
||||||
"requirements.4": "Optionnel si vous utilisez les paquets \"self-contained\".",
|
|
||||||
"improvements.title": "Améliorations",
|
|
||||||
"improvements.1": "Changement de PureBasic vers .NET 6.0.",
|
|
||||||
"improvements.2": "Amélioration de la logique interne du programme.",
|
|
||||||
"improvements.3": "Ajout de l'option <code>-H/--short-help</code>.",
|
|
||||||
"improvements.4": "Support pour Windows ARM et ARM64.",
|
|
||||||
"improvements.5": "Support pour le lancement sans invité de commande.",
|
|
||||||
"usage.title": "Utilisation",
|
|
||||||
"formatting.title": "Formatage de sortie",
|
|
||||||
"requirements.table.title": "Dépendances",
|
|
||||||
"requirements.text.none.ms": "Aucun",
|
|
||||||
"requirements.text.none.mp": "Aucuns",
|
|
||||||
"requirements.text.none.fs": "Aucune",
|
|
||||||
"requirements.text.none.fp": "Aucunes",
|
|
||||||
"packages.title": "Paquets",
|
|
||||||
"packages.single.title": "??? <i class=\"text-super-muted\">(Single)</i>",
|
|
||||||
"packages.single.1": "Lighter builds that only contain the exe and required licenses.<br>You will need to install the <a href=\"https://dotnet.microsoft.com/en-us/download\">.NET 6.0 Runtime</a>.",
|
|
||||||
"packages.self.title": "??? <i class=\"text-super-muted\">(Self-Contained)</i>",
|
|
||||||
"packages.self.1": "Larger builds that contain the exe and the <a href=\"https://dotnet.microsoft.com/en-us/download\">.NET 6.0 Runtime</a> as well as the required licenses.",
|
|
||||||
"packages.msi.title": "Installateurs MSI",
|
|
||||||
"packages.msi.1": "Windows installers that contain the relevant \"Self-Contained\" build with an option to automatically update existing installations and add the program to the <kbd>%PATH%</kbd>.<br>The install location is <kbd>%ProgramFiles%\\NibblePoker\\lscom\\</kbd> and cannot be changed. <i>(This will be possible in future releases)</i>",
|
|
||||||
"links.title": "Liens",
|
|
||||||
"screenshots.title": "Captures d'écran"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"template": "generic-project-readme",
|
|
||||||
"head": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description"
|
|
||||||
},
|
|
||||||
"opengraph": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description",
|
|
||||||
"type": null,
|
|
||||||
"url": null,
|
|
||||||
"image": "/resources/NibblePoker/images/content/lscom/lscom-v2-text-01-bkgd-cli.png",
|
|
||||||
"image_type": null
|
|
||||||
},
|
|
||||||
"article": {
|
|
||||||
"icon": "fad fa-terminal",
|
|
||||||
"title": "meta.title",
|
|
||||||
"subtitle": "article.subtitle",
|
|
||||||
"tags": ["application", "tool", "lscom", "dotnet", "windows"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{"type": "h1", "content": "intro.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p2"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p3"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "requirements.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.3"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ∘ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "requirements.4"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "improvements.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "improvements.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "improvements.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "improvements.3"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "improvements.4"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "improvements.5"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "screenshots.title"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2,
|
|
||||||
"modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "gallery",
|
|
||||||
"modifiers": [],
|
|
||||||
"images": [
|
|
||||||
"/resources/NibblePoker/images/content/lscom/screen-cli-stylish-2x-xBR.png",
|
|
||||||
"/resources/NibblePoker/images/content/lscom/screen-cli-csv-2x-xBR.png",
|
|
||||||
"/resources/NibblePoker/images/content/lscom/screen-cli-full-2x-xBR.png"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "usage.title"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2,
|
|
||||||
"modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "code", "indent": 2,
|
|
||||||
"modifiers": ["horizontal-scroll-auto", "code-block"],
|
|
||||||
"code": [
|
|
||||||
"lscom.exe [-a|--show-all] [-d|--show-device] [-D <str>|--divider <str>] [-f|--show-friendly]",
|
|
||||||
" [-h|--help] [-H|--short-help] [-n|--show-name-raw] [-P|--no-pretty] [-s|--sort]",
|
|
||||||
" [-S|--sort-reverse] [-t|--tab-padding] [-v|--version] [-V|--version-only]",
|
|
||||||
"",
|
|
||||||
"Launch arguments:",
|
|
||||||
" -a, --show-all Display the complete port's name (Equal to '-dfn')",
|
|
||||||
" -d, --show-device Displays the port's device name",
|
|
||||||
" -D <str>, --divider <str> Uses the given string or char as a separator (Can be empty string !)",
|
|
||||||
" -f, --show-friendly Displays the port's friendly name",
|
|
||||||
" -h, --help Display this help text",
|
|
||||||
" -H, --short-help Display the short help text",
|
|
||||||
" -n, --show-name-raw Displays the port's raw name (See remarks section)",
|
|
||||||
" -P, --no-pretty Disables the pretty printing format (Equal to -D \" \")",
|
|
||||||
" -s, --sort Sorts the port based on their raw names in an ascending order",
|
|
||||||
" -S, --sort-reverse Sorts the port based on their raw names in a descending order",
|
|
||||||
" -t, --tab-padding Use tabs for padding between the types of names (Overrides '-D')",
|
|
||||||
" -v, --version Shows the utility's version number and other info",
|
|
||||||
" -V, --version-only Shows the utility's version number only (Overrides '-v')"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "formatting.title"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2,
|
|
||||||
"modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "code", "indent": 2,
|
|
||||||
"modifiers": ["horizontal-scroll-auto", "code-block"],
|
|
||||||
"code": [
|
|
||||||
" *┬> No launch arguments:",
|
|
||||||
" └──> ${Raw name} => COM1",
|
|
||||||
" *┬> '-d' or '-f'",
|
|
||||||
" ├──> ${Device name} => \\Device\\Serial1",
|
|
||||||
" └──> ${Friendly name} => Communications Port",
|
|
||||||
" *┬> '-d' and '-f'",
|
|
||||||
" └──> ${Friendly name} [${Device name}] => Communications Port [\\Device\\Serial1]",
|
|
||||||
" *┬> '-n' and '-d'",
|
|
||||||
" └──> ${Raw name} [$DeviceName] => COM1 [\\Device\\Serial1]",
|
|
||||||
" *┬> '-n' and '-f'",
|
|
||||||
" └──> ${Raw name} - ${Friendly name} => COM1 - Communications Port",
|
|
||||||
" *┬> '-ndf' or '-a'",
|
|
||||||
" └──> ${Raw name} - ${Friendly name} [${Device name}] => COM1 - Communications Port [\\Device\\Serial1]",
|
|
||||||
" *┬> '-ndfp' or '-ap'",
|
|
||||||
" └──> ${Raw name} ${Friendly name} ${Device name} => COM1 Communications Port \\Device\\Serial1",
|
|
||||||
" *┬> '-ndfD \";\"' or '-aD \";\"'",
|
|
||||||
" └──> ${Raw name};${Friendly name};${Device name} => COM1;Communications Port;\\Device\\Serial1"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "packages.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "packages.single.title", "modifiers": ["bold"]},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "packages.single.1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "packages.self.title", "modifiers": ["bold"]},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "packages.self.1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "packages.msi.title", "modifiers": ["bold"]},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "packages.msi.1"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "content.commons.version.current"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2, "modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "table", "modifiers": ["stylish", "auto-cell-padding", "v-center-cells"],
|
|
||||||
"head": [
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.responsive"},
|
|
||||||
{"type": "raw", "content": "requirements.table.title"},
|
|
||||||
{"type": "raw", "content": "content.commons.download.single"}
|
|
||||||
],
|
|
||||||
"body": [
|
|
||||||
[
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.any"},
|
|
||||||
{"type": "raw", "content": "requirements.text.dotnet"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_AnyCPU.zip",
|
|
||||||
"modifiers": ["thin", "download-primary"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_AnyCPU.zip</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.x64", "rowspan": 3},
|
|
||||||
{"type": "raw", "content": "requirements.text.dotnet"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_x64_Single.zip",
|
|
||||||
"modifiers": ["thin"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_x64_Single.zip</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "requirements.text.none.fp", "rowspan": 2},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_x64_SelfContained.zip",
|
|
||||||
"modifiers": ["thin", "download-primary"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_x64_SelfContained.zip</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_x64.msi",
|
|
||||||
"modifiers": ["thin", "download-primary"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-archive\"></i> ListComPort_v3.0.0_x64.msi</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.x86", "rowspan": 3},
|
|
||||||
{"type": "raw", "content": "requirements.text.dotnet"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_x86_Single.zip",
|
|
||||||
"modifiers": ["thin"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_x86_Single.zip</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "requirements.text.none.fp", "rowspan": 2},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_x86_SelfContained.zip",
|
|
||||||
"modifiers": ["thin"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_x86_SelfContained.zip</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_x86.msi",
|
|
||||||
"modifiers": ["thin"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-archive\"></i> ListComPort_v3.0.0_x86.msi</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.arm64", "rowspan": 2},
|
|
||||||
{"type": "raw", "content": "requirements.text.dotnet"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_arm64_Single.zip",
|
|
||||||
"modifiers": ["thin"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_arm64_Single.zip</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "requirements.text.none.fp"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_arm64_SelfContained.zip",
|
|
||||||
"modifiers": ["thin"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_arm64_SelfContained.zip</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.arm32", "rowspan": 2},
|
|
||||||
{"type": "raw", "content": "requirements.text.dotnet"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_arm_Single.zip",
|
|
||||||
"modifiers": ["thin"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_arm_Single.zip</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "requirements.text.none.fp"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_arm_SelfContained.zip",
|
|
||||||
"modifiers": ["thin"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_arm_SelfContained.zip</span><i class=\"fas fa-download ml-s\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "content.commons.version.source"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2, "modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "table", "modifiers": ["stylish", "auto-cell-padding", "v-center-cells"],
|
|
||||||
"head": [
|
|
||||||
{"type": "raw", "content": "content.commons.version"},
|
|
||||||
{"type": "raw", "content": "content.commons.download.multiple"}
|
|
||||||
],
|
|
||||||
"body": [[
|
|
||||||
{"type": "raw", "content": "v3.0.0", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/DotNet-ListComPort-3.0.0.zip",
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 3.0.0.zip</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
},{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/DotNet-ListComPort-3.0.0.tar.gz",
|
|
||||||
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 3.0.0.tar.gz</span><i class=\"fas fa-download ml-s\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "links.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://github.com/aziascreations/DotNet-ListComPort",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "content.commons.github"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,395 +0,0 @@
|
|||||||
{
|
|
||||||
"strings": {
|
|
||||||
"en": {
|
|
||||||
"meta.title": "PB-ListComPort <i>(Legacy)</i>",
|
|
||||||
"meta.description": "A simple CLI tool that can list COM ports with their name, friendly name and device name easily and cleanly.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/PB-ListComPort\"><i class=\"fab fa-github\"></i> View on GitHub</a>",
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"intro.p1": "A simple CLI tool that can list COM ports with their full name easily and cleanly.",
|
|
||||||
"intro.p2": "This tool is intended to replace the tedious task of having to use the <code class=\"code\">mode</code> command, and the <i>Device Manager</i> to find a newly plugged-in device that provides a COM port.",
|
|
||||||
"intro.p3": "The earliest version of Windows that can be used is Windows XP x64 or Windows Vista due to the fact that RegGetValueW is not available on older versions of Windows.",
|
|
||||||
"usage.title": "Usage",
|
|
||||||
"formatting.title": "Output formatting",
|
|
||||||
"links.title": "Links"
|
|
||||||
},
|
|
||||||
"fr": {
|
|
||||||
"meta.title": "PB-ListComPort <i>(Legacy)</i>",
|
|
||||||
"meta.description": "Un petit utilitaire pour invité de commande qui permet de facilement lister les noms, noms formatés et chemin des ports COM.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/PB-ListComPort\"><i class=\"fab fa-github\"></i> Voir sur GitHub</a>",
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"_intro.p1": "",
|
|
||||||
"_intro.p2": "",
|
|
||||||
"_intro.p3": "",
|
|
||||||
"usage.title": "Utilisation",
|
|
||||||
"formatting.title": "Formatage de sortie",
|
|
||||||
"links.title": "Liens"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"template": "generic-project-readme",
|
|
||||||
"head": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description"
|
|
||||||
},
|
|
||||||
"opengraph": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description",
|
|
||||||
"type": null,
|
|
||||||
"url": null,
|
|
||||||
"image": "/resources/NibblePoker/images/content/lscom/lscom-legacy-simple.png",
|
|
||||||
"image_type": null
|
|
||||||
},
|
|
||||||
"article": {
|
|
||||||
"icon": "fad fa-terminal",
|
|
||||||
"title": "meta.title",
|
|
||||||
"subtitle": "article.subtitle",
|
|
||||||
"tags": ["application", "tool", "lscom", "purebasic", "windows"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{"type": "h1", "content": "intro.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p2"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "intro.p3"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "usage.title"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2,
|
|
||||||
"modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "code", "indent": 2,
|
|
||||||
"modifiers": ["horizontal-scroll-auto-auto-auto-auto", "code-block"],
|
|
||||||
"code": [
|
|
||||||
"lscom.exe [-a|--show-all] [-d|--show-device] [-D <str>|--divider <str>] [-f|--show-friendly]",
|
|
||||||
" [-h|--help] [-n|--show-name-raw] [-P|--no-pretty] [-s|--sort] [-S|--sort-reverse]",
|
|
||||||
" [-t|--tab-padding] [-v|--version] [-V|--version-only]",
|
|
||||||
"",
|
|
||||||
"Launch arguments:",
|
|
||||||
" -a, --show-all Display the complete port's name (Equal to '-dfn')",
|
|
||||||
" -d, --show-device Displays the port's device name",
|
|
||||||
" -D <str>, --divider <str> Uses the given string or char as a separator (Can be empty string !)",
|
|
||||||
" -f, --show-friendly Displays the port's friendly name",
|
|
||||||
" -h, --help Display this help text",
|
|
||||||
" -n, --show-name-raw Displays the port's raw name (See remarks section)",
|
|
||||||
" -P, --no-pretty Disables the pretty printing format (Equal to -D \" \")",
|
|
||||||
" -s, --sort Sorts the port based on their raw names in an ascending order",
|
|
||||||
" -S, --sort-reverse Sorts the port based on their raw names in a descending order",
|
|
||||||
" -t, --tab-padding Use tabs for padding between the types of names (Overrides '-D')",
|
|
||||||
" -v, --version Shows the utility's version number and other info",
|
|
||||||
" -V, --version-only Shows the utility's version number only (Overrides '-v')"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "formatting.title"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2,
|
|
||||||
"modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "code", "indent": 2,
|
|
||||||
"modifiers": ["horizontal-scroll-auto-auto-auto-auto", "code-block"],
|
|
||||||
"code": [
|
|
||||||
" *┬> No launch arguments:",
|
|
||||||
" └──> ${Raw name} => COM1",
|
|
||||||
" *┬> '-d' or '-f'",
|
|
||||||
" ├──> ${Device name} => \\Device\\Serial1",
|
|
||||||
" └──> ${Friendly name} => Communications Port",
|
|
||||||
" *┬> '-d' and '-f'",
|
|
||||||
" └──> ${Friendly name} [${Device name}] => Communications Port [\\Device\\Serial1]",
|
|
||||||
" *┬> '-n' and '-d'",
|
|
||||||
" └──> ${Raw name} [$DeviceName] => COM1 [\\Device\\Serial1]",
|
|
||||||
" *┬> '-n' and '-f'",
|
|
||||||
" └──> ${Raw name} - ${Friendly name} => COM1 - Communications Port",
|
|
||||||
" *┬> '-ndf' or '-a'",
|
|
||||||
" └──> ${Raw name} - ${Friendly name} [${Device name}] => COM1 - Communications Port [\\Device\\Serial1]",
|
|
||||||
" *┬> '-ndfp' or '-ap'",
|
|
||||||
" └──> ${Raw name} ${Friendly name} ${Device name} => COM1 Communications Port \\Device\\Serial1",
|
|
||||||
" *┬> '-ndfD \";\"' or '-aD \";\"'",
|
|
||||||
" └──> ${Raw name};${Friendly name};${Device name} => COM1;Communications Port;\\Device\\Serial1"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "content.commons.version.current"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2,
|
|
||||||
"modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "table", "modifiers": ["stylish", "auto-cell-padding", "v-center-cells"],
|
|
||||||
"head": [
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.responsive"},
|
|
||||||
{"type": "raw", "content": "content.commons.lang"},
|
|
||||||
{"type": "raw", "content": "content.commons.download.single"}
|
|
||||||
],
|
|
||||||
"body": [
|
|
||||||
[
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.x64", "rowspan": 2},
|
|
||||||
{"type": "raw", "content": "content.commons.lang.english"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.1.0/lscom_eng_x64.exe",
|
|
||||||
"modifiers": ["thin", "download-primary"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom_eng_x64.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.lang.french"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.1.0/lscom_fra_x64.exe",
|
|
||||||
"modifiers": ["thin", "download-primary"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom_fra_x64.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.x86", "rowspan": 2},
|
|
||||||
{"type": "raw", "content": "content.commons.lang.english"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.1.0/lscom_eng_x86.exe",
|
|
||||||
"modifiers": ["thin"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom_eng_x86.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.lang.french"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.1.0/lscom_fra_x86.exe",
|
|
||||||
"modifiers": ["thin"],
|
|
||||||
"parts": [{
|
|
||||||
"type": "raw",
|
|
||||||
"localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom_fra_x86.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "content.commons.version.previous.multiple"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2, "modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "table", "modifiers": ["stylish", "auto-cell-padding", "v-center-cells"],
|
|
||||||
"head": [
|
|
||||||
{"type": "raw", "content": "content.commons.version"},
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.responsive"},
|
|
||||||
{"type": "raw", "content": "content.commons.lang"},
|
|
||||||
{"type": "raw", "content": "content.commons.download.single"}
|
|
||||||
],
|
|
||||||
"body": [
|
|
||||||
[
|
|
||||||
{"type": "raw", "content": "v2.0.0", "localize": false, "rowspan": 4},
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.x64", "rowspan": 2},
|
|
||||||
{"type": "raw", "content": "content.commons.lang.english"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.0.0/lscom_eng_x64.exe",
|
|
||||||
"modifiers": ["thin"], "localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom_eng_x64.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.lang.french"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.0.0/lscom_fra_x64.exe",
|
|
||||||
"modifiers": ["thin"], "localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom_fra_x64.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.x86", "rowspan": 2},
|
|
||||||
{"type": "raw", "content": "content.commons.lang.english"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.0.0/lscom_eng_x86.exe",
|
|
||||||
"modifiers": ["thin"], "localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom_eng_x86.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.lang.french"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.0.0/lscom_fra_x86.exe",
|
|
||||||
"modifiers": ["thin"], "localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom_fra_x86.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "v1.1.0", "localize": false, "rowspan": 2},
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.x64"},
|
|
||||||
{"type": "raw", "content": "content.commons.lang.english", "rowspan": 2},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/1.1.0/lscom-x64.exe",
|
|
||||||
"modifiers": ["thin"], "localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom-x64.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.x86"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/1.1.0/lscom-x86.exe",
|
|
||||||
"modifiers": ["thin"], "localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom-x86.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "v1.0.0", "localize": false},
|
|
||||||
{"type": "raw", "content": "content.commons.cpu.x64"},
|
|
||||||
{"type": "raw", "content": "content.commons.lang.english"},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [{
|
|
||||||
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/1.0.0/lscom.exe",
|
|
||||||
"modifiers": ["thin"], "localize": false,
|
|
||||||
"content": "<span class=\"text-monospace\">lscom.exe</span><i class=\"fas fa-download ml-xs\"></i>"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "content.commons.version.source"},
|
|
||||||
{
|
|
||||||
"type": "container", "padding": 2, "modifiers": ["pb-0"],
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "table", "modifiers": ["stylish", "auto-cell-padding", "v-center-cells"],
|
|
||||||
"head": [
|
|
||||||
{"type": "raw", "content": "content.commons.version"},
|
|
||||||
{"type": "raw", "content": "content.commons.download.multiple"}
|
|
||||||
],
|
|
||||||
"body": [[
|
|
||||||
{"type": "raw", "content": "v2.1.0", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.1.0/2.1.0.zip",
|
|
||||||
"content": "<span class=\"text-monospace\">2.1.0.zip</span><i class=\"fas fa-download ml-xs\"></i>",
|
|
||||||
"localize": false
|
|
||||||
},{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.1.0/2.1.0.tar.gz",
|
|
||||||
"content": "<span class=\"text-monospace\">2.1.0.tar.gz</span><i class=\"fas fa-download ml-xs\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "v2.0.0", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.0.0/2.0.0.zip",
|
|
||||||
"content": "<span class=\"text-monospace\">2.0.0.zip</span><i class=\"fas fa-download ml-xs\"></i>",
|
|
||||||
"localize": false
|
|
||||||
},{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.0.0/2.0.0.tar.gz",
|
|
||||||
"content": "<span class=\"text-monospace\">2.0.0.tar.gz</span><i class=\"fas fa-download ml-xs\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "v1.1.0", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/1.1.0/1.1.0.zip",
|
|
||||||
"content": "<span class=\"text-monospace\">1.1.0.zip</span><i class=\"fas fa-download ml-xs\"></i>",
|
|
||||||
"localize": false
|
|
||||||
},{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/1.1.0/1.1.0.tar.gz",
|
|
||||||
"content": "<span class=\"text-monospace\">1.1.0.tar.gz</span><i class=\"fas fa-download ml-xs\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],[
|
|
||||||
{"type": "raw", "content": "v1.0.0", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/1.0.0/1.0.0.zip",
|
|
||||||
"content": "<span class=\"text-monospace\">1.0.0.zip</span><i class=\"fas fa-download ml-xs\"></i>",
|
|
||||||
"localize": false
|
|
||||||
},{
|
|
||||||
"type": "button", "modifiers": ["thin"],
|
|
||||||
"link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/1.0.0/1.0.0.tar.gz",
|
|
||||||
"content": "<span class=\"text-monospace\">1.0.0.tar.gz</span><i class=\"fas fa-download ml-xs\"></i>",
|
|
||||||
"localize": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]]
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "links.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://github.com/aziascreations/PB-ListComPort",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "content.commons.github"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,174 +0,0 @@
|
|||||||
{
|
|
||||||
"strings": {
|
|
||||||
"en": {
|
|
||||||
"meta.title": "Minecraft - Expanded Iron Bundles",
|
|
||||||
"meta.description": "A small Minecraft mod that provides bundles with more storage space, and new functionalities in the future.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/MC-Expanded-Iron-Bundles\" class=\"font-size-16\"><i class=\"fab fa-github\"></i> View on GitHub</a>",
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"feature.current.title": "Current features",
|
|
||||||
"feature.current.1": "Recipe for the vanilla bundle",
|
|
||||||
"feature.current.2": "Multiple variants with more storage space and special properties:",
|
|
||||||
"feature.current.3": "Copper Bundle (128 slots / 2 stacks)",
|
|
||||||
"feature.current.4": "Iron Bundle (256 slots / 4 stacks)",
|
|
||||||
"feature.current.5": "Gold Bundle (384 slots / 6 stacks)",
|
|
||||||
"feature.current.6": "Diamond Bundle (512 slots / 8 stacks)",
|
|
||||||
"feature.current.7": "Obsidian Bundle (768 slots / 12 stacks)",
|
|
||||||
"feature.current.8": "Ancient Scraps Bundle (896 slots / 14 stacks)",
|
|
||||||
"feature.current.9": "Netherite Bundle (1024 slots / 16 stacks & Immune to fire and lava)",
|
|
||||||
"feature.planned.title": "Planned features",
|
|
||||||
"feature.planned.1": "Versions for Forge and previous versions of Minecraft",
|
|
||||||
"feature.planned.2": "A config file to enable/disable specific bundles, change capacity",
|
|
||||||
"feature.planned.3": "Better visuals for the occupancy bar",
|
|
||||||
"feature.planned.4": "More bundles with special mechanics (i.e.: Ender Bundle, ...)",
|
|
||||||
"feature.planned.5": "More bundle upgrades",
|
|
||||||
"feature.planned.6": "Improved bundle mechanics (i.e.: Swapping last inserted item, ...)",
|
|
||||||
"feature.planned.7": "Support for modded ores and modded clones of existing ores",
|
|
||||||
"links.title": "Links"
|
|
||||||
},
|
|
||||||
"fr": {
|
|
||||||
"meta.title": "Minecraft - Expanded Iron Bundlest",
|
|
||||||
"meta.description": "Un petit mod pour Minecraft qui ajoute des sacs avec plus d'espace de stockage et de nouvelles fonctionalitées dans le futur.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/MC-Expanded-Iron-Bundles\" class=\"font-size-16\"><i class=\"fab fa-github\"></i> Voir sur GitHub</a>",
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"feature.current.title": "Fonctionnalités",
|
|
||||||
"feature.current.1": "Une recette pour le sac en cuir",
|
|
||||||
"feature.current.2": "Plusieurs variantes des sacs avec de nouvelles propriétés:",
|
|
||||||
"feature.current.3": "Sac en cuivre (128 slots / 2 stacks)",
|
|
||||||
"feature.current.4": "Sac en fer (256 slots / 4 stacks)",
|
|
||||||
"feature.current.5": "Sac en or (384 slots / 6 stacks)",
|
|
||||||
"feature.current.6": "Sac en diamant (512 slots / 8 stacks)",
|
|
||||||
"feature.current.7": "Sac en obsidienne (768 slots / 12 stacks)",
|
|
||||||
"feature.current.8": "Sac en fragments de Netherite (896 slots / 14 stacks)",
|
|
||||||
"feature.current.9": "Sac en Netherite (1024 slots / 16 stacks & Immune to fire and lava)",
|
|
||||||
"feature.planned.title": "Fonctionnalités planifiées",
|
|
||||||
"feature.planned.1": "Une version pour Forge et les anciennes versions du jeu",
|
|
||||||
"feature.planned.2": "Un fichier de configuration pour activer/désactiver des fonctionnalités et changer la taille des sacs",
|
|
||||||
"feature.planned.3": "Des meilleurs effets visuels pour la barre d'utilisation",
|
|
||||||
"feature.planned.4": "Des sacs avec des mécaniques spéciales (ex: Sac d'Ender, ...)",
|
|
||||||
"feature.planned.5": "Plus d'améliorations de sacs",
|
|
||||||
"feature.planned.6": "Mécaniques d'utilisations améliorées (ex: Changer l'objet qui sera sorti)",
|
|
||||||
"feature.planned.7": "Support pour les minerais issus d'autres mods",
|
|
||||||
"links.title": "Liens"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"template": "generic-project-readme",
|
|
||||||
"head": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description"
|
|
||||||
},
|
|
||||||
"opengraph": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description",
|
|
||||||
"type": null,
|
|
||||||
"url": null,
|
|
||||||
"image": "/resources/NibblePoker/images/content/mc-expanded-iron-bundles/item-icon.png",
|
|
||||||
"image_type": null
|
|
||||||
},
|
|
||||||
"article": {
|
|
||||||
"icon": "fad fa-cubes",
|
|
||||||
"title": "meta.title",
|
|
||||||
"subtitle": "article.subtitle",
|
|
||||||
"tags": ["game", "minecraft", "mod"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{"type": "h1", "content": "intro.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "meta.description"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "feature.current.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.current.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.current.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ⚬ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.current.3"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ⚬ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.current.4"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ⚬ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.current.5"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ⚬ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.current.6"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ⚬ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.current.7"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ⚬ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.current.8"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": " ⚬ ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.current.9"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "feature.planned.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.planned.1"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.planned.2"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.planned.3"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.planned.4"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.planned.5"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.planned.6"},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{"type": "raw", "content": "feature.planned.7"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "links.title"},
|
|
||||||
{
|
|
||||||
"type": "paragraph",
|
|
||||||
"indent": 2,
|
|
||||||
"modifiers": ["no-bottom-padding"],
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw",
|
|
||||||
"link": "https://github.com/aziascreations/MC-Expanded-Iron-Bundles",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "content.commons.github"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://modrinth.com/mod/expanded-iron-bundles",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "Modrinth [Fabric & Forge]", "localize": false}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{"type": "raw", "content": "<br>", "localize": false},
|
|
||||||
{"type": "raw", "content": "● ", "localize": false},
|
|
||||||
{
|
|
||||||
"type": "raw", "link": "https://www.curseforge.com/minecraft/mc-mods/expanded-iron-bundles-fabric",
|
|
||||||
"parts": [
|
|
||||||
{"type": "raw", "content": "CurseForge [Fabric]", "localize": false}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,106 +0,0 @@
|
|||||||
{
|
|
||||||
"strings": {
|
|
||||||
"en": {
|
|
||||||
"meta.title": "Youtube Auto Archiver",
|
|
||||||
"meta.description": "A simple and yet highly configurable Python application that automatically checks if a Youtuber is streaming, and downloads said streams while also archiving its latest uploads.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/Youtube-Auto-Archiver\"><i class=\"fab fa-github\"></i> View on GitHub</a>",
|
|
||||||
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"warning.title": "Warning",
|
|
||||||
"warning.p1": "Due to the way some commands are executed, it is possible to have a <a href=\"https://owasp.org/www-community/attacks/Command_Injection\">command injection vulnerability</a> if you mess up or leave the config file editable by everyone.",
|
|
||||||
"warning.p2": "This might be fixed in the future, but don't count on it as this project is a personal one.",
|
|
||||||
|
|
||||||
"features.title": "Features",
|
|
||||||
"features.list.1.1": "● General",
|
|
||||||
"features.list.1.2": "⚬ Can run on Windows and Linux (Tested on x64 and ARMv8)",
|
|
||||||
"features.list.1.3": "⚬ Relatively high level of configurability.",
|
|
||||||
"features.list.2.1": "● YouTube",
|
|
||||||
"features.list.2.2": "⚬ Automatic livestream download through https://youtube.com/c/.../live",
|
|
||||||
"features.list.2.3": "⚬ Automatic livestream thumbnail and description download.",
|
|
||||||
"features.list.2.4": "⚬ Automatic download of uploads and their metadata.",
|
|
||||||
"features.list.2.5": "⚬ Configurable delays, actions, locations per channel.",
|
|
||||||
"features.list.3.1": "● Planned for v1.0.0",
|
|
||||||
"features.list.3.2": "⚬ Native support for cookies for yt-dlp and maybe streamlink.",
|
|
||||||
"features.list.3.3": "⚬ Better support to prevent command injection. (Will block some features if used)",
|
|
||||||
"features.list.4.1": "● Planned for later",
|
|
||||||
"features.list.4.2": "⚬ Using TOML for the config file when Python 3.11 is released and stable.",
|
|
||||||
|
|
||||||
"links.title": "Links"
|
|
||||||
},
|
|
||||||
"fr": {
|
|
||||||
"_meta.title": "",
|
|
||||||
"meta.description": "Une simple petite application hautement configurable qui vérifie automatiquement si un Youtubeur stream et as uploadé des vidéos afin de les archiver.",
|
|
||||||
"article.subtitle": "<a href=\"https://github.com/aziascreations/Youtube-Auto-Archiver\"><i class=\"fab fa-github\"></i> Voir sur GitHub</a>",
|
|
||||||
|
|
||||||
"intro.title": "Introduction",
|
|
||||||
"warning.title": "Avertissements",
|
|
||||||
"warning.p1": "Due au fait que certaines commandes sont exécutées avec des paramètres arbitraires configurables cette application est vulnérable aux attaques par <a href=\"https://owasp.org/www-community/attacks/Command_Injection\">injection de commande</a> si le fichier de configuration est modifiable par des personnes non autorisées.",
|
|
||||||
"warning.p2": "Ce problème sera probablement réglé dans le futur, mais il n'y a pas de date fixe comme ce projet est plus personnel qu'autre-chose.",
|
|
||||||
|
|
||||||
"features.title": "Fonctionnalités",
|
|
||||||
"features.list.1.1": "● General",
|
|
||||||
"features.list.1.2": "⚬ Can run on Windows and Linux (Tested on x64 and ARMv8)",
|
|
||||||
"features.list.1.3": "⚬ Relatively high level of configurability.",
|
|
||||||
"features.list.2.1": "● YouTube",
|
|
||||||
"features.list.2.2": "⚬ Automatic livestream download through https://youtube.com/c/.../live",
|
|
||||||
"features.list.2.3": "⚬ Automatic livestream thumbnail and description download.",
|
|
||||||
"features.list.2.4": "⚬ Automatic download of uploads and their metadata.",
|
|
||||||
"features.list.2.5": "⚬ Configurable delays, actions, locations per channel.",
|
|
||||||
"features.list.3.1": "● Planned for v1.0.0",
|
|
||||||
"features.list.3.2": "⚬ Native support for cookies for yt-dlp and maybe streamlink.",
|
|
||||||
"features.list.3.3": "⚬ Better support to prevent command injection. (Will block some features if used)",
|
|
||||||
"features.list.4.1": "● Planned for later",
|
|
||||||
"features.list.4.2": "⚬ Using TOML for the config file when Python 3.11 is released and stable.",
|
|
||||||
|
|
||||||
"links.title": "Liens"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"template": "generic-project-readme",
|
|
||||||
"head": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description"
|
|
||||||
},
|
|
||||||
"opengraph": {
|
|
||||||
"title": "meta.title",
|
|
||||||
"description": "meta.description",
|
|
||||||
"type": null,
|
|
||||||
"url": null,
|
|
||||||
"image": "/resources/NibblePoker/images/content/yaa/icon-final.png",
|
|
||||||
"image_type": null
|
|
||||||
},
|
|
||||||
"article": {
|
|
||||||
"icon": "fab fa-youtube",
|
|
||||||
"title": "meta.title",
|
|
||||||
"subtitle": "article.subtitle",
|
|
||||||
"tags": ["docker", "application", "web", "python"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{"type": "h1", "content": "intro.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "meta.description"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "warning.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "warning.p1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "warning.p2"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "features.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "features.list.1.1"},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "features.list.1.2"},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "features.list.1.3"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "features.list.2.1"},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "features.list.2.2"},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "features.list.2.3"},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "features.list.2.4"},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "features.list.2.5"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "features.list.3.1"},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "features.list.3.2"},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "features.list.3.3"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "features.list.4.1"},
|
|
||||||
{"type": "paragraph", "indent": 4, "content": "features.list.4.2"},
|
|
||||||
|
|
||||||
{"type": "h1", "content": "warning.title"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "warning.p1"},
|
|
||||||
{"type": "paragraph", "indent": 2, "content": "warning.p2"}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,15 +0,0 @@
|
|||||||
circuitpython-ebyte-e32:
|
|
||||||
title:
|
|
||||||
en: "CircuitPython Ebyte E32"
|
|
||||||
fr: "CircuitPython Ebyte E32"
|
|
||||||
preamble:
|
|
||||||
en: "CircuitPython driver for Ebyte's E32 UART LoRa modules that use the SX1278/SX1276 chipsets."
|
|
||||||
fr: "Driver CircuitPython pour les modules sérial LoRa E32 de Ebyte tournant sous les chipset SX1278/SX1276."
|
|
||||||
image: "/resources/NibblePoker/images/content/circuitpython-ebyte-e32/main.png"
|
|
||||||
tags:
|
|
||||||
- "electronic"
|
|
||||||
- "python"
|
|
||||||
- "circuitpython"
|
|
||||||
- "lora"
|
|
||||||
- "library"
|
|
||||||
priority: 105
|
|
@@ -1,12 +0,0 @@
|
|||||||
dotnet-arguments:
|
|
||||||
title:
|
|
||||||
en: "DotNet-Arguments"
|
|
||||||
fr: "DotNet-Arguments"
|
|
||||||
preamble:
|
|
||||||
en: "A simple and 'to-the-point' library to parse launch arguments in .NET and .NET Core applications."
|
|
||||||
fr: "Une petite librairie simple et efficace pour lire et interpréter les options de lancement d'un programme pour .NET et .NET Core."
|
|
||||||
image: "/resources/NibblePoker/images/content/dotnet-arguments/main.png"
|
|
||||||
tags:
|
|
||||||
- "library"
|
|
||||||
- "dotnet"
|
|
||||||
priority: 40
|
|
@@ -1,16 +0,0 @@
|
|||||||
excel-worksheet-password-remover:
|
|
||||||
title:
|
|
||||||
en: "Excel-Worksheet-Password-Remover"
|
|
||||||
fr: "Excel-Worksheet-Password-Remover"
|
|
||||||
preamble:
|
|
||||||
en:
|
|
||||||
- "Small web page from which you can easily remove a password from an Excel worksheet."
|
|
||||||
- "It works by leaving the task of editing the XML files on an Excel document to your browser instead to keep everything local."
|
|
||||||
fr:
|
|
||||||
- "Petite application web qui permet de facilement retirer le mot de passe d'une feuille de calcul Excel depuis votre navigateur web sans avoir à uploader le fichier sur internet."
|
|
||||||
- "Cette application laisse votre navigateur modifier les fichiers XML du fichier Excel afin de tout garder en local."
|
|
||||||
image: "/resources/NibblePoker/images/content/excel-password-remover/excel-password-remover.png"
|
|
||||||
tags:
|
|
||||||
- "tool"
|
|
||||||
- "web"
|
|
||||||
priority: 50
|
|
@@ -1,19 +0,0 @@
|
|||||||
lscom-cli-dotnet:
|
|
||||||
title:
|
|
||||||
en: "DotNet-ListComPort"
|
|
||||||
fr: "DotNet-ListComPort"
|
|
||||||
preamble:
|
|
||||||
en:
|
|
||||||
- "A simple CLI tool that can list COM ports with their name, friendly name and device name easily and cleanly."
|
|
||||||
- "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."
|
|
||||||
fr:
|
|
||||||
- "Un petit utilitaire pour invité de commande qui permet de facilement lister les noms, noms formatés et chemins des ports COM."
|
|
||||||
- "Cet outil a pour bût de faciliter cette tâche sans avoir à utiliser la commande <code>mode</code> ou le <i>Gestionnaire de périphérique</i>."
|
|
||||||
image: "/resources/NibblePoker/images/content/lscom/lscom-v2-text-01-bkgd-cli.png"
|
|
||||||
tags:
|
|
||||||
- "application"
|
|
||||||
- "tool"
|
|
||||||
- "lscom"
|
|
||||||
- "dotnet"
|
|
||||||
- "windows"
|
|
||||||
priority: 100
|
|
@@ -1,19 +0,0 @@
|
|||||||
lscom-cli:
|
|
||||||
title:
|
|
||||||
en: "PB-ListComPort (Legacy)"
|
|
||||||
fr: "PB-ListComPort (Legacy)"
|
|
||||||
preamble:
|
|
||||||
en:
|
|
||||||
- "A simple CLI tool that can list COM ports with their name, friendly name and device name easily and cleanly."
|
|
||||||
- "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."
|
|
||||||
fr:
|
|
||||||
- "Un petit utilitaire pour invité de commande qui permet de facilement lister les noms, noms formatés et chemins des ports COM."
|
|
||||||
- "Cet outil a pour bût de faciliter cette tâche sans avoir à utiliser la commande <code>mode</code> ou le <i>Gestionnaire de périphérique</i>."
|
|
||||||
image: "/resources/NibblePoker/images/content/lscom/lscom-legacy-simple.png"
|
|
||||||
tags:
|
|
||||||
- "application"
|
|
||||||
- "tool"
|
|
||||||
- "lscom"
|
|
||||||
- "purebasic"
|
|
||||||
- "windows"
|
|
||||||
priority: 1
|
|
@@ -1,13 +0,0 @@
|
|||||||
mc-expanded-iron-bundles:
|
|
||||||
title:
|
|
||||||
en: "Expanded Iron Bundles"
|
|
||||||
fr: "Expanded Iron Bundles"
|
|
||||||
preamble:
|
|
||||||
en: "A small Minecraft mod that provides bundles with more storage space, and new functionalities in the future."
|
|
||||||
fr: "Un petit mod pour Minecraft qui ajoute des sacs avec plus d'espace de stockage et de nouvelles fonctionalitées dans le futur."
|
|
||||||
image: "/resources/NibblePoker/images/content/mc-expanded-iron-bundles/item-icon.png"
|
|
||||||
tags:
|
|
||||||
- "game"
|
|
||||||
- "minecraft"
|
|
||||||
- "mod"
|
|
||||||
priority: 20
|
|
@@ -1,14 +0,0 @@
|
|||||||
youtube-auto-archiver:
|
|
||||||
title:
|
|
||||||
en: "Youtube-Auto-Archiver"
|
|
||||||
fr: "Youtube-Auto-Archiver"
|
|
||||||
preamble:
|
|
||||||
en: "A simple and yet highly configurable Python application that automatically checks if a Youtuber is streaming, and downloads said streams while also archiving its latest uploads."
|
|
||||||
fr: "Conteneur et application Python hautement configurable qui permet d'automatiquement archiver et télécharger des livestreams et vidéos depuis YouTube."
|
|
||||||
image: "/resources/NibblePoker/images/content/yaa/icon-final.png"
|
|
||||||
tags:
|
|
||||||
- "docker"
|
|
||||||
- "application"
|
|
||||||
- "web"
|
|
||||||
- "python"
|
|
||||||
priority: 30
|
|
@@ -1,65 +0,0 @@
|
|||||||
<?php
|
|
||||||
$start_time = microtime(true);
|
|
||||||
set_include_path('../');
|
|
||||||
include_once 'commons/config.php';
|
|
||||||
include_once 'commons/langs.php';
|
|
||||||
$enable_kitty_and_doggo_sounds = true;
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="<?php echo($user_language); ?>">
|
|
||||||
<head>
|
|
||||||
<?php include 'commons/DOM/head.php'; ?>
|
|
||||||
<title><?php print(localize('contributors.head.title')); ?></title>
|
|
||||||
<meta name="description" content="<?php print(localize('contributors.head.description')); ?>">
|
|
||||||
<meta property="og:title" content="<?php print(localize('contributors.og.title')); ?>"/>
|
|
||||||
<meta property="og:type" content="website"/>
|
|
||||||
<meta property="og:url" content="<?php echo($host_uri . l10n_url_abs('/contributors/')); ?>"/>
|
|
||||||
<meta property="og:image" content="<?php echo($host_uri); ?>/resources/NibblePoker/images/logos/v2_opengraph_v2.png"/>
|
|
||||||
<meta property="og:image:type" content="image/png"/>
|
|
||||||
<meta property="og:description" content="<?php print(localize('contributors.og.description')); ?>"/>
|
|
||||||
<?php include 'commons/DOM/head-preloads.php'; ?>
|
|
||||||
</head>
|
|
||||||
<body class="layout-generic">
|
|
||||||
<?php
|
|
||||||
include_once 'commons/DOM/utils.php';
|
|
||||||
$SIDEBAR_IDS = ['contributors'];
|
|
||||||
include 'commons/DOM/sidebar.php';
|
|
||||||
?>
|
|
||||||
<header class="w-full p-m pl-s">
|
|
||||||
<h1 class="t-size-17 t-w-500">
|
|
||||||
<i class="fad fa-user t-size-16 mr-s t-muted"></i><?php print(localize("contributors.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("contributors.intro.title")); ?>
|
|
||||||
|
|
||||||
<?php //printSubHeader(localize("contributors.sponsors.title")); ?>
|
|
||||||
|
|
||||||
<?php printSubHeader(localize("contributors.code.title")); ?>
|
|
||||||
|
|
||||||
<?php printSubHeader(localize("contributors.spiritualis.title")); ?>
|
|
||||||
<div class="mx-xs mt-s">
|
|
||||||
<div id="kitty-kiki" class="img-contributor kitty">
|
|
||||||
<img src="/resources/NibblePoker/images/contributors/kiki-02.jpg" draggable="false">
|
|
||||||
<img src="/resources/NibblePoker/images/contributors/kiki-03.jpg" draggable="false">
|
|
||||||
</div>
|
|
||||||
<div id="kitty-maki" class="img-contributor kitty">
|
|
||||||
<img src="/resources/NibblePoker/images/contributors/maki-02.jpg" draggable="false">
|
|
||||||
<img src="/resources/NibblePoker/images/contributors/maki-03.jpg" draggable="false">
|
|
||||||
</div>
|
|
||||||
</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 -->");
|
|
||||||
}
|
|
||||||
?>
|
|
1
data/articles/.gitignore
vendored
Normal file
1
data/articles/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*/
|
20
data/contributors.yml
Normal file
20
data/contributors.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
config:
|
||||||
|
root_image_path: "/resources/NibblePoker/images/contributors/"
|
||||||
|
root_sound_path: "/resources/NibblePoker/sounds/contributors/"
|
||||||
|
|
||||||
|
regular:
|
||||||
|
|
||||||
|
spiritual:
|
||||||
|
- name: Kiki
|
||||||
|
image: "kiki-02.jpg"
|
||||||
|
image_hover: "kiki-04.jpg"
|
||||||
|
sound_entry: "meow-test-01.ogg"
|
||||||
|
sound_hover: "kiki-ronron-01.ogg"
|
||||||
|
sound_exit: "meow-test-02.ogg"
|
||||||
|
|
||||||
|
- name: Maki
|
||||||
|
image: "maki-02.jpg"
|
||||||
|
image_hover: "maki-03.jpg"
|
||||||
|
sound_entry: "meow-test-01.ogg"
|
||||||
|
#sound_hover: "meo-test-01.jpg"
|
||||||
|
sound_exit: "meow-test-02.ogg"
|
30
data/projects/circuitpython-ebyte-e32.yml
Normal file
30
data/projects/circuitpython-ebyte-e32.yml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
head:
|
||||||
|
title_key: "meta.title"
|
||||||
|
description_key: "meta.description"
|
||||||
|
opengraph:
|
||||||
|
title_key: "meta.title"
|
||||||
|
description_key: "meta.description"
|
||||||
|
type: null
|
||||||
|
url: null
|
||||||
|
image_url: "/resources/NibblePoker/images/content/circuitpython-ebyte-e32/main.png"
|
||||||
|
image_type: null
|
||||||
|
twitter:
|
||||||
|
title_key: "meta.title"
|
||||||
|
description_key: "meta.description"
|
||||||
|
index:
|
||||||
|
priority: 105
|
||||||
|
enable: true
|
||||||
|
title_key: "meta.title"
|
||||||
|
preamble_key: "meta.description"
|
||||||
|
image_url: "/resources/NibblePoker/images/content/circuitpython-ebyte-e32/main.png"
|
||||||
|
image_alt_key: ""
|
||||||
|
general:
|
||||||
|
icon: "fab fa-python"
|
||||||
|
title_key: "meta.title"
|
||||||
|
subtitle_key: "article.subtitle"
|
||||||
|
tags:
|
||||||
|
- "electronic"
|
||||||
|
- "python"
|
||||||
|
- "circuitpython"
|
||||||
|
- "lora"
|
||||||
|
- "library"
|
55
data/sidebar.yml
Normal file
55
data/sidebar.yml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
- title_key: text.home
|
||||||
|
abs_href: "/"
|
||||||
|
icon: fad fa-home
|
||||||
|
active_id: home
|
||||||
|
|
||||||
|
-
|
||||||
|
|
||||||
|
- title_key: text.articles
|
||||||
|
abs_href: "/articles/"
|
||||||
|
icon: fad fa-newspaper
|
||||||
|
active_id: articles
|
||||||
|
|
||||||
|
-
|
||||||
|
|
||||||
|
- title_key: text.applications
|
||||||
|
abs_href: "/content/?tags=application;web"
|
||||||
|
icon: fad fa-browser
|
||||||
|
active_id: application
|
||||||
|
|
||||||
|
- title_key: text.libraries
|
||||||
|
abs_href: "/content/?tags=library"
|
||||||
|
icon: fad fa-puzzle-piece
|
||||||
|
active_id: library
|
||||||
|
|
||||||
|
- title_key: text.electronics
|
||||||
|
abs_href: "/content/?tags=electronic"
|
||||||
|
icon: fad fa-microchip
|
||||||
|
active_id: electronic
|
||||||
|
|
||||||
|
- title_key: text.tools
|
||||||
|
abs_href: "/tools"
|
||||||
|
icon: fad fa-toolbox
|
||||||
|
active_id: tools
|
||||||
|
|
||||||
|
- title_key: text.downloads
|
||||||
|
raw_href: "https://files.nibblepoker.lu/"
|
||||||
|
icon: fad fa-download
|
||||||
|
active_id: ""
|
||||||
|
|
||||||
|
-
|
||||||
|
|
||||||
|
- title_key: text.about
|
||||||
|
abs_href: "/about"
|
||||||
|
icon: fad fa-user
|
||||||
|
active_id: about
|
||||||
|
|
||||||
|
- title_key: text.contact
|
||||||
|
abs_href: "/contact"
|
||||||
|
icon: fad fa-mailbox
|
||||||
|
active_id: ""
|
||||||
|
|
||||||
|
- title_key: text.links
|
||||||
|
abs_href: "/links"
|
||||||
|
icon: fad fa-link
|
||||||
|
active_id: links
|
10
data/sitemap.yml
Normal file
10
data/sitemap.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# ???
|
||||||
|
|
||||||
|
- "/"
|
||||||
|
- "/about/"
|
||||||
|
- "/articles/"
|
||||||
|
- "/contact/"
|
||||||
|
- "/content/"
|
||||||
|
- "/content/circuitpython-ebyte-e32/"
|
||||||
|
- "/links/"
|
||||||
|
- "/privacy/"
|
1
data/strings/_contributors.yml
Normal file
1
data/strings/_contributors.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# EN - Contributors
|
80
data/strings/en/about.yml
Normal file
80
data/strings/en/about.yml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# EN - About
|
||||||
|
|
||||||
|
head.title: About - NibblePoker
|
||||||
|
head.description: 'TODO: description'
|
||||||
|
og.title: NibblePoker - About
|
||||||
|
og.description: 'TODO: description'
|
||||||
|
header.title: About
|
||||||
|
intro.title: Introduction
|
||||||
|
intro.text.01: My name is Herwin Bozet, I'm an experienced developer with extensive
|
||||||
|
experience in PureBasic, Python, Java, VBA; and intermediate knowledge in C, Win32
|
||||||
|
APIs, embedded systems and general web development.
|
||||||
|
intro.text.02: I've been programming for about 10 years now, and for the last
|
||||||
|
5 years I've been actively working on applying that experience to a variety of projects
|
||||||
|
with the aim of helping programmers and people in their day-to-day life.
|
||||||
|
intro.text.10: NibblePoker is, in essence, a simple moniker and the front-end
|
||||||
|
for most of my public-focused work.
|
||||||
|
intro.text.11: It houses all my work made and tailored for usage by other people.
|
||||||
|
intro.text.20: This entire website, as well as all my work for it and other
|
||||||
|
personal projects, is completely open-source and available under permissive <abbr
|
||||||
|
title="Open Source Initiative">OSI</abbr> approved licenses.
|
||||||
|
intro.text.21: All of it is maintained, developed and expanded in my free time
|
||||||
|
with the occasional help from people in the open-source community.
|
||||||
|
tenets.title: Core tenets
|
||||||
|
tenets.text.01: ''
|
||||||
|
tenets.text.02: ''
|
||||||
|
future.title: Future plans
|
||||||
|
future.text.01: It is planned to turn NibblePoker into a <abbr title="Private
|
||||||
|
company with limited liability">SPRL</abbr> in a couple years if everything goes
|
||||||
|
as planned.
|
||||||
|
future.text.02: This would allow me to centralize many things and invest properly
|
||||||
|
in my targetted fields to achieve my goals.
|
||||||
|
future.text.10: The goal would be to create a small sustainable local business
|
||||||
|
that offers a wide range of products and solutions covering <abbr title="Internet
|
||||||
|
of things">IoT</abbr> devices, programming, and technological independence ; All
|
||||||
|
while including the required software and hardware components often lacking in such
|
||||||
|
products and solutions.
|
||||||
|
future.text.20: Ultimately, all this work and research would be made available
|
||||||
|
to the public under open-source licenses, enabling anyone who wishes to learn, reuse,
|
||||||
|
and resell open-source products, to do so in a similar way as companies like Adafruit
|
||||||
|
do.
|
||||||
|
_nibblepoker.title: The 'NibblePoker' name
|
||||||
|
_nibblepoker.text.01: TODO
|
||||||
|
_nibblepoker.text.10: TODO
|
||||||
|
_nibblepoker.text.11: TODO
|
||||||
|
_nibblepoker.text.20: TODO
|
||||||
|
financing.title: Financing
|
||||||
|
financing.text.01: This website, as well as the surrounding infrastructure,
|
||||||
|
was made to cost as little as possible while not being reliant on any censor-happy
|
||||||
|
companies.
|
||||||
|
financing.text.02: Following my core tenets, I also wanted to retain some sort
|
||||||
|
of "technological sovereignty", and therefore refuse to support or use companies
|
||||||
|
that actively fight against legal free speech.
|
||||||
|
financing.text.10: The details of the operating costs are provided below to
|
||||||
|
illustrate the low price of such independence.
|
||||||
|
financing.text.20: And for those of you who are more motivated, I hope to inspire
|
||||||
|
you to at least try this kind of activity.
|
||||||
|
financing.text.21: It may seem daunting at first, but for a fraction of the
|
||||||
|
cost presented here, <b>and with a bit of motivation</b>, you can already accomplish
|
||||||
|
a lot of things and gain valuable knowledge for a world as interconnected as ours.
|
||||||
|
financing.text.isp: The main ISP bill isn't accounted for since this could run
|
||||||
|
off some random public Wi-Fi.
|
||||||
|
financing.part.service: Service
|
||||||
|
financing.part.cost: Cost
|
||||||
|
financing.part.cost.total: Total Cost
|
||||||
|
financing.part.equipment: Equipment
|
||||||
|
financing.part.cost.yearly: Yearly Cost
|
||||||
|
financing.part.cost.yearly.total: Yearly Cost
|
||||||
|
financing.part.domain.lu: "<i>.lu</i> domain"
|
||||||
|
financing.part.domain.com: "<i>.com</i> domain"
|
||||||
|
financing.part.proxy.europe: European reverse-proxy
|
||||||
|
financing.part.proxy.america: American reverse-proxy
|
||||||
|
financing.part.proxy.asia: Asian reverse-proxy
|
||||||
|
financing.part.emails: Emails
|
||||||
|
financing.part.electricity: Electricity
|
||||||
|
financing.part.nanopir4s: NanoPi R4S
|
||||||
|
financing.part.nanopir4s.desc: Handles all non public-facing tasks and services.
|
||||||
|
financing.part.storage: Local storage
|
||||||
|
aziascreations.title: The 'AziasCreations' name
|
||||||
|
_aziascreations.text.01: TODO
|
||||||
|
_aziascreations.text.10: TODO
|
53
data/strings/en/circuitpython-ebyte-e32.yml
Normal file
53
data/strings/en/circuitpython-ebyte-e32.yml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# EN - Project - CircuitPython EByte E32
|
||||||
|
|
||||||
|
meta.title: CircuitPython - Ebyte E32 Driver
|
||||||
|
meta.description: CircuitPython driver for Ebyte's E32 UART LoRa modules that use
|
||||||
|
the SX1278/SX1276 chipsets.
|
||||||
|
article.subtitle: <a href="https://github.com/aziascreations/CircuitPython-Ebyte-E32"><i
|
||||||
|
class="fab fa-github"></i> View on GitHub</a>
|
||||||
|
intro.title: Introduction
|
||||||
|
intro.p1: This project is a simple driver for CircuitPython that allows you to easily
|
||||||
|
interact with Ebyte's E32 series of LoRa modules.
|
||||||
|
features.title: Features
|
||||||
|
features.1: Supports all standard E32 UART modules.
|
||||||
|
features.2: 'Extra support on a per-frequency and per-power basis:'
|
||||||
|
features.2.1: More descriptive constants for TX power.
|
||||||
|
features.2.2: "<s>Maximum packet size calculators.</s> (TODO)"
|
||||||
|
features.2.3: Entirely optional via separate modules.
|
||||||
|
features.3: 'Minified versions for devices with tiny storage space:'
|
||||||
|
features.3.1: ~75% smaller for <code class="code">.py</code> files
|
||||||
|
features.3.2: ~5% smaller for <code class="code">.mpy</code> files <i>(Due to shortened
|
||||||
|
local variables, mostly)</i>
|
||||||
|
limitations.title: Limitations
|
||||||
|
limitations.1: 'No built-in packet size limit:'
|
||||||
|
limitations.1.1: Wildly different between frequencies & operating parameters.
|
||||||
|
limitations.1.2: Not documented clearly enough in LoRA and LoRaWAN documentation.
|
||||||
|
limitations.2: 'No built-in protocol:'
|
||||||
|
limitations.2.1: All LoRa packets are glued back-to-back when received.
|
||||||
|
limitations.2.2: No LoraWAN support
|
||||||
|
limitations.3: 'Missing support for some modules:'
|
||||||
|
limitations.3.1: Modules with <code class="code">170</code>, <code class="code">400</code>
|
||||||
|
and <code class="code">900</code> prefix. (Will improve overtime)
|
||||||
|
doc.title: Documentation
|
||||||
|
doc.p1: The entire documentation for this project can be found on Github.<br>The datasheets
|
||||||
|
for all the E32 modules can also be found on "<a href="https://files.nibblepoker.lu/datasheets/ebyte/e32/">files.nibblepoker.lu</a>".
|
||||||
|
usage.title: Usage
|
||||||
|
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> 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
|
||||||
|
links.title: Links
|
23
data/strings/en/commons.yml
Normal file
23
data/strings/en/commons.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# EN - Commons
|
||||||
|
|
||||||
|
action.copy: Copy
|
||||||
|
action.copied: Copied
|
||||||
|
|
||||||
|
undefined: Undefined
|
||||||
|
na: N/A
|
||||||
|
|
||||||
|
yes: Yes
|
||||||
|
no: No
|
||||||
|
|
||||||
|
width: Width
|
||||||
|
height: Height
|
||||||
|
width.min: Minimum width
|
||||||
|
height.min: Minimum height
|
||||||
|
width.max: Maximum width
|
||||||
|
height.max: Maximum height
|
||||||
|
|
||||||
|
user-agent: User-Agent
|
||||||
|
|
||||||
|
server: Server
|
||||||
|
|
||||||
|
cpu.architecture: Architecture de CPU
|
15
data/strings/en/contact.yml
Normal file
15
data/strings/en/contact.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# FR - Contact
|
||||||
|
|
||||||
|
head.title: Contact - NibblePoker
|
||||||
|
head.description: 'TODO: description'
|
||||||
|
|
||||||
|
og.title: NibblePoker - Contact
|
||||||
|
og.description: 'TODO: description'
|
||||||
|
|
||||||
|
header.title: Contact
|
||||||
|
|
||||||
|
email.title: Email
|
||||||
|
email.compose: Send an email to <i>herwin.bozet@gmail.com</i>
|
||||||
|
|
||||||
|
twitter.title: Twitter
|
||||||
|
twitter.compose: Compose DM to @NibblePoker on Twitter
|
25
data/strings/en/debug.yml
Normal file
25
data/strings/en/debug.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# EN - Debug
|
||||||
|
|
||||||
|
head.title: Debugger - NibblePoker
|
||||||
|
head.description: Debugging page used to analyse the behaviour of various mechanisms
|
||||||
|
used by the website.
|
||||||
|
og.title: NibblePoker - Debugger
|
||||||
|
og.description: Debugging page used to analyse the behaviour of various mechanisms
|
||||||
|
used by the website.
|
||||||
|
header.title: Debugger
|
||||||
|
tables.field: Field
|
||||||
|
tables.value: Value
|
||||||
|
host.title: Host Configuration
|
||||||
|
host.requested: Requested
|
||||||
|
host.domain: Domain
|
||||||
|
host.uri: URI
|
||||||
|
host.tld: TLD
|
||||||
|
host.waffle: Waffle Mode
|
||||||
|
host.bouneschlupp: Bouneschlupp Mode
|
||||||
|
lang.title: Localization System (L10N)
|
||||||
|
lang.compile-date: Compilation date
|
||||||
|
lang.default: Default language
|
||||||
|
lang.user: Active language
|
||||||
|
lang.header.raw: Raw HTTP header
|
||||||
|
lang.header.processed: Processed HTTP header
|
||||||
|
client.title: Client Information
|
52
data/strings/en/errors.yml
Normal file
52
data/strings/en/errors.yml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# EN - Errors
|
||||||
|
|
||||||
|
403.head.title: 403 - NibblePoker
|
||||||
|
403.head.description: Access to the requested resource isn't unauthorized.
|
||||||
|
403.og.title: NibblePoker - 403 Error
|
||||||
|
403.og.description: Access to the requested resource isn't unauthorized.
|
||||||
|
403.header.title: Error<span class="mx-s t-size-15">❱</span>403 Error
|
||||||
|
|
||||||
|
404.head.title: 404 - NibblePoker
|
||||||
|
404.head.description: The server couldn't find the requested resource.
|
||||||
|
404.og.title: NibblePoker - 404 Error
|
||||||
|
404.og.description: The server couldn't find the requested resource.
|
||||||
|
404.header.title: Error<span class="mx-s t-size-15">❱</span>404 Error
|
||||||
|
|
||||||
|
500.head.title: 500 - NibblePoker
|
||||||
|
500.head.description: The server has encountered a situation it doesn't know how to handle.
|
||||||
|
500.og.title: NibblePoker - 500 Error
|
||||||
|
500.og.description: The server has encountered a situation it doesn't know how to handle.
|
||||||
|
500.header.title: Error<span class="mx-s t-size-15">❱</span>500 Error
|
||||||
|
|
||||||
|
content_tags_length.head.title: Content error - NibblePoker
|
||||||
|
content_tags_length.head.description: The "tags" URL parameter is too long.
|
||||||
|
content_tags_length.og.title: NibblePoker - Content error
|
||||||
|
content_tags_length.og.description: The "tags" URL parameter is too long.
|
||||||
|
content_tags_length.header.title: Content error
|
||||||
|
|
||||||
|
content_tags_alphanumeric.head.title: Content error - NibblePoker
|
||||||
|
content_tags_alphanumeric.head.description: One of the tags given in the "tags" URL parameter is not a valid alphanumeric string.
|
||||||
|
content_tags_alphanumeric.og.title: NibblePoker - Content error
|
||||||
|
content_tags_alphanumeric.og.description: One of the tags given in the "tags" URL parameter is not a valid alphanumeric string.
|
||||||
|
content_tags_alphanumeric.header.title: Content error
|
||||||
|
|
||||||
|
content_tags_empty.head.title: Content error - NibblePoker
|
||||||
|
content_tags_empty.head.description: No content could be found for the given tags.
|
||||||
|
content_tags_empty.og.title: NibblePoker - Content error
|
||||||
|
content_tags_empty.og.description: No content could be found for the given tags.
|
||||||
|
content_tags_empty.header.title: Content error
|
||||||
|
|
||||||
|
content_id_alphanumeric.head.title: Content error - NibblePoker
|
||||||
|
content_id_alphanumeric.head.description: The requested resource's ID isn't a valid alphanumeric string.
|
||||||
|
content_id_alphanumeric.og.title: NibblePoker - Content error
|
||||||
|
content_id_alphanumeric.og.description: The requested resource's ID isn't a valid alphanumeric string.
|
||||||
|
content_id_alphanumeric.header.title: Content error
|
||||||
|
|
||||||
|
content_id_not_exist.head.title: Content error - NibblePoker
|
||||||
|
content_id_not_exist.head.description: The requested content doesn't have an internal item file associated to it.
|
||||||
|
content_id_not_exist.og.title: NibblePoker - Content error
|
||||||
|
content_id_not_exist.og.description: The requested content doesn't have an internal item file associated to it.
|
||||||
|
content_id_not_exist.header.title: Content error
|
||||||
|
|
||||||
|
skit.pc.dead.alt: Drawing of an old PC with a face with crossed eyes.
|
||||||
|
skit.pc.warn.alt: Drawing of an old PC with a warning sign.
|
37
data/strings/en/excel-password-remover.yml
Normal file
37
data/strings/en/excel-password-remover.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# EN - Excel Password Remover
|
||||||
|
|
||||||
|
meta.title: Excel Worksheet Password Remover
|
||||||
|
meta.description: >-
|
||||||
|
Small web page from which you can easily remove a password from an Excel
|
||||||
|
worksheet. It works by leaving the task of editing the XML files on an Excel
|
||||||
|
document to your browser instead to keep everything local.
|
||||||
|
article.subtitle: >-
|
||||||
|
<a
|
||||||
|
href="https://github.com/aziascreations/Excel-Worksheet-Password-Remover"><i
|
||||||
|
class="fab fa-github"></i> View on GitHub</a>
|
||||||
|
intro.title: Introduction
|
||||||
|
intro.p1: >-
|
||||||
|
This project aims to simplify the removal of passwords on Excel's Worksheet by
|
||||||
|
leaving the task of editing the XML files on an Excel document to your
|
||||||
|
browser.
|
||||||
|
working.title: Security & Internal workings
|
||||||
|
working.p1: >-
|
||||||
|
In terms of security, your browser handles all the data without sending any of
|
||||||
|
it to a central server like many web apps do.<br>This makes it, and your data,
|
||||||
|
as safe as your browser can be since it is the only potential point of failure
|
||||||
|
here.
|
||||||
|
working.p2: >-
|
||||||
|
As for the internal workings, the only thing this tool does is extract the
|
||||||
|
content of the <code>.xlsx</code> file you gave it and removes the passwords
|
||||||
|
on any worksheets and makes a new file with all the changes.<br>Once all of
|
||||||
|
that is done, the file is downloaded via a <a
|
||||||
|
href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs">data
|
||||||
|
URL</a>.
|
||||||
|
usage.title: Usage
|
||||||
|
usage.p1: >-
|
||||||
|
To use this tool you can either visit "<a
|
||||||
|
href="https://aziascreations.github.io/Excel-Worksheet-Password-Remover">aziascreations.github.io/Excel-Worksheet-Password-Remover</a>"
|
||||||
|
or download the repository and host the web page yourself.
|
||||||
|
demo.title: Demonstration video
|
||||||
|
links.title: Links
|
||||||
|
content.link.demo: Demo hosted on GitHub
|
5
data/strings/en/footer.yml
Normal file
5
data/strings/en/footer.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# EN - Footer
|
||||||
|
|
||||||
|
text.privacy: Privacy policy
|
||||||
|
alt.sidebar.button: Open and close the navigation sidebar.
|
||||||
|
alt.logo: Website's logo
|
43
data/strings/en/home.yml
Normal file
43
data/strings/en/home.yml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# EN - Home
|
||||||
|
|
||||||
|
head.title: NibblePoker
|
||||||
|
head.description: Collection of free and open-source handmade utilities and libraries
|
||||||
|
ranging from a simple COM port lister to password remover and autonomous video archivers.
|
||||||
|
|
||||||
|
og.title: NibblePoker
|
||||||
|
og.description: Collection of free and open-source handmade utilities and libraries
|
||||||
|
ranging from a simple COM port lister to password remover and autonomous video archivers.
|
||||||
|
|
||||||
|
header.title: Homepage
|
||||||
|
|
||||||
|
intro.title: Welcome to %0
|
||||||
|
intro.text.1: This website contains a collection of my personal work through
|
||||||
|
blog posts, software releases and other forms of media, all of which is accessible
|
||||||
|
for free and under open-source friendly licenses.
|
||||||
|
intro.text.2: If you wish to contact me, you can do so through the contact form
|
||||||
|
linked in the sidebar or via the email address present on that page.
|
||||||
|
|
||||||
|
showcase.title: Showcase
|
||||||
|
|
||||||
|
updates.title: Updates
|
||||||
|
|
||||||
|
updates.text.privacy: Updated our privacy policy.
|
||||||
|
|
||||||
|
updates.4.date: November 30 2023
|
||||||
|
updates.4.text.1: Centralized DNS servers & implemented GeoDNS.
|
||||||
|
updates.4.text.2: Added US CDN hosted by <a href="https://www.chicagovps.net/">ChicagoVPS</a>.
|
||||||
|
updates.4.text.3: All other regions use the EU CDN hosted by <a href="https://www.ionos.fr/">IONOS</a>.
|
||||||
|
|
||||||
|
updates.3.date: November 12 2023
|
||||||
|
updates.3.text.1: Other services are back online.
|
||||||
|
updates.3.text.2: Changed our host to <a href="https://www.ionos.fr/">IONOS</a>.
|
||||||
|
updates.3.text.3: Finished all side pages.
|
||||||
|
|
||||||
|
updates.2.date: August 15 2023
|
||||||
|
updates.2.text.1: The website is back online.
|
||||||
|
updates.2.text.2: New and much lighter design.
|
||||||
|
updates.2.text.3: Changed our host to <a href="https://hostbrr.com/">HostBrr</a>.
|
||||||
|
updates.2.text.4: Added a section for web-based tools.
|
||||||
|
|
||||||
|
updates.1.date: September 9 2022
|
||||||
|
updates.1.text.1: Changed our host to v6Node.
|
15
data/strings/en/langs.yml
Normal file
15
data/strings/en/langs.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# EN - Langs
|
||||||
|
|
||||||
|
menu.title: Language
|
||||||
|
|
||||||
|
current: English
|
||||||
|
automatic: Automatic
|
||||||
|
|
||||||
|
english: English
|
||||||
|
french: French
|
||||||
|
german: German
|
||||||
|
luxembourgish: Luxembourgish
|
||||||
|
|
||||||
|
english.639-3: English (eng)
|
||||||
|
french.639-3: French (fra)
|
||||||
|
luxembourgish.639-3: Luxembourgish (ltz)
|
37
data/strings/en/links.yml
Normal file
37
data/strings/en/links.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# EN - Links
|
||||||
|
|
||||||
|
head.title: Links - NibblePoker
|
||||||
|
head.description: 'TODO: description'
|
||||||
|
|
||||||
|
og.title: NibblePoker - Links
|
||||||
|
og.description: 'TODO: description'
|
||||||
|
|
||||||
|
header.title: Links
|
||||||
|
|
||||||
|
social.title: Social Networks
|
||||||
|
work.title: Work
|
||||||
|
misc.title: Miscellaneous
|
||||||
|
|
||||||
|
twitter.title: Twitter <i>(@NibblePoker)</i>
|
||||||
|
twitter.text.1: Random rambles about projects I'm working on.
|
||||||
|
|
||||||
|
github.title: GitHub <i>(@aziascreations)</i>
|
||||||
|
github.text.1: Private account containing all my personal projects.
|
||||||
|
|
||||||
|
github_pro.title: GitHub <i>(@NibblePoker)</i>
|
||||||
|
github_pro.text.1: Organization containing all the repositories related to this website.
|
||||||
|
|
||||||
|
linkedin.title: LinkedIn
|
||||||
|
linkedin.text.1: Connect and chat with me in a more professional-oriented setting.
|
||||||
|
|
||||||
|
malt.title: Malt
|
||||||
|
malt.text.1: Any freelancing/consulting job can be conducted through their service.
|
||||||
|
|
||||||
|
gitea.title: Self-hosted Gitea
|
||||||
|
gitea.text.1: Contains all my projects and some mirrors from various sites.
|
||||||
|
|
||||||
|
files.title: Public files & downloads
|
||||||
|
files.text.1: Contains all files that can be downloaded on this website and other documentation.
|
||||||
|
|
||||||
|
archives.title: Public archives
|
||||||
|
archives.text.1: Contains various public archives.
|
130
data/strings/en/privacy.yml
Normal file
130
data/strings/en/privacy.yml
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
# EN - Privacy
|
||||||
|
|
||||||
|
head.title: Privacy policy - NibblePoker
|
||||||
|
head.description: Our privacy policy in a clear and easy to understand format.
|
||||||
|
og.title: NibblePoker - Privacy Policy
|
||||||
|
og.description: Our privacy policy in a clear and easy to understand format.
|
||||||
|
header.title: Privacy policy
|
||||||
|
introduction.title: Introduction
|
||||||
|
introduction.text.1: This privacy policy is written in accordance with the
|
||||||
|
12th and 13th articles of the GDPR.
|
||||||
|
introduction.text.2: 'If you wish to consult it, you can do so on the following
|
||||||
|
websites:'
|
||||||
|
contact.title: How to contact us ?
|
||||||
|
contact.text.1: 'If you wish to contact us for more information regarding
|
||||||
|
our privacy policy, please contact us via the form included on the contact page,
|
||||||
|
or at the following email address:'
|
||||||
|
complaint.title: How to contact the appropriate authorities ?
|
||||||
|
complaint.text.1: Should you wish to report a complaint or if you feel that
|
||||||
|
our privacy policy has not addressed your concern in a satisfactory manner, you
|
||||||
|
may contact your national Data Protection Authority (DPA).
|
||||||
|
complaint.text.2: 'More information on this procedure can be found on the
|
||||||
|
following websites:'
|
||||||
|
v2.data.title: Data collection (Web)
|
||||||
|
v2.data.intro.1: This websites only collects data through generic access logs
|
||||||
|
in order to detect and block bad actors from accessing this website.
|
||||||
|
v2.data.intro.2: None of the data collected is used for any other purpose,
|
||||||
|
it is never shared with any other third-party and is never use in any sort of analytics.
|
||||||
|
v2.data.private.1: 'Here is the list of private data being collected:'
|
||||||
|
v2.data.private_list.1: IP address
|
||||||
|
v2.data.private_list.2: Browser's User-Agent
|
||||||
|
v2.data.non_private.1: 'And here is the list of non-private data being collected:'
|
||||||
|
v2.data.non_private_list.1: Requested resource' URI
|
||||||
|
v2.data.non_private_list.2: Date and time
|
||||||
|
v2.data.end.1: Once the data has been logged in the access logs, it is automatically
|
||||||
|
retrieved and processed by a locally-hosted applications every 30-60 seconds and
|
||||||
|
then deleted from said logs.
|
||||||
|
v2.data.end.2: This application compares this information against a list of
|
||||||
|
known threat sources, targets and behaviours and if a match is found, the private
|
||||||
|
information is stored for 7 days pending a manual review.
|
||||||
|
v2.data.end.3: Once that 7 day period has elapsed, or once the report has
|
||||||
|
been reviewed, all the relevant data is automatically deleted.
|
||||||
|
v2.data.end.4: If your request wasn't flagged as potentially malicious, every
|
||||||
|
data collected from it is thrown out instantly.
|
||||||
|
v2.data.end.5: This process should normally never be triggered for regular
|
||||||
|
traffic since most of the triggering actions are ones that should not be possible
|
||||||
|
to accomplish through normal browsing.
|
||||||
|
v2.data.end.6: However, this process isn't infallible and there is always
|
||||||
|
an off chance that false positives may happen.
|
||||||
|
v2.data_dns.title: Data collection (DNS)
|
||||||
|
v2.data_dns.intro.1: Our <abbr title="Domain Name Service">DNS</abbr> servers
|
||||||
|
collects data through generic access logs in order to detect and block bad actors.
|
||||||
|
v2.data_dns.intro.2: None of the data collected is used for any other purpose,
|
||||||
|
it is never shared with any other third-party and is never use in any sort of analytics.
|
||||||
|
v2.data_dns.private.1: 'Here is the list of private data being collected:'
|
||||||
|
v2.data_dns.private_list.1: IP address
|
||||||
|
v2.data_dns.non_private.1: 'And here is the list of non-private data being
|
||||||
|
collected:'
|
||||||
|
v2.data_dns.non_private_list.1: Requested DNS record
|
||||||
|
v2.data_dns.non_private_list.2: Date and time
|
||||||
|
v2.data_dns.end.1: All private data is deleted after a period of 7 days.
|
||||||
|
v2.update.title: Changes to our privacy policy
|
||||||
|
v2.update.intro.1: The content of this privacy policy was originally written
|
||||||
|
on the 4th of December 2021 and was last updated on the 18th of March 2022.
|
||||||
|
v2.update.history.1.date: 2021/12/04
|
||||||
|
v2.update.history.1.desc.1: Original version
|
||||||
|
v2.update.history.2.date: 2022/03/18
|
||||||
|
v2.update.history.2.desc.1: Changed section on data collection to reflect
|
||||||
|
new policy.
|
||||||
|
v2.update.history.2.desc.2: Added mention about CloudFlare and linked to their
|
||||||
|
privacy policy.
|
||||||
|
v2.update.history.2.desc.3: Improved the <i>"Changes to our privacy policy"</i>
|
||||||
|
section.
|
||||||
|
v2.update.history.3.date: 2022/09/09
|
||||||
|
v2.update.history.3.desc.1: Changed references to external services to reflect
|
||||||
|
the migration to v6Node.
|
||||||
|
v2.update.history.3.desc.1.1: Added mention about v6Node and linked to their
|
||||||
|
privacy policy.
|
||||||
|
v2.update.history.3.desc.1.2: Removed mentions of CloudFlare.
|
||||||
|
v2.update.history.3.desc.2: Changed the "Cookies" section to indicate that
|
||||||
|
none should be used on public domains.
|
||||||
|
v2.update.history.4.date: 2023/11/11
|
||||||
|
v2.update.history.4.desc.1: Changed references to external services to reflect
|
||||||
|
the migration to IONOS.
|
||||||
|
v2.update.history.4.desc.1.1: Removed mentions of v6Node.
|
||||||
|
v2.update.history.4.desc.2: Changed section on data collection to reflect
|
||||||
|
new timings & infrastructure.
|
||||||
|
v2.update.history.5.date: 2023/11/30
|
||||||
|
v2.update.history.5.desc.1: Added a section regarding data collection through
|
||||||
|
DNS servers.
|
||||||
|
v2.update.history.5.desc.2: Changed references to external services to reflect
|
||||||
|
the usage of ChicagoVPS
|
||||||
|
v2.update.end.2: In the event of a change to our privacy policy, you will
|
||||||
|
be informed explicitly, and a copy of previous versions of the policy will be available
|
||||||
|
through this page.
|
||||||
|
v2.third.title: Third Parties
|
||||||
|
v2.third.intro.1: Our websites uses some <abbr title="Virtual private server">VPS</abbr>
|
||||||
|
provided by IONOS and ChicagoVPS in order to put in place a <abbr title="Content
|
||||||
|
delivery network">CDN</abbr> system.
|
||||||
|
v2.third.intro.2: The goal of this system is to improve your browsing experience
|
||||||
|
with the help of a private caching service and custom traffic filtering rules.
|
||||||
|
v2.third.intro.3: No data should be collected on their side due to the nature
|
||||||
|
of the server leased to us.
|
||||||
|
v2.third.intro.4: 'If you''d wish to consult their privacy policy and their
|
||||||
|
partners'', you can do so by using the following URLs:'
|
||||||
|
v2.cookies.title: Cookies
|
||||||
|
v2.cookies.intro.1: Our websites doesn't use nor store any cookies in your
|
||||||
|
browser.
|
||||||
|
v2.personal.title: Personal Measures & Convictions
|
||||||
|
v2.personal.disabled.intro: 'While not required by any laws, we decided to
|
||||||
|
improve your online privacy by disabling some features:'
|
||||||
|
v2.personal.disabled.list.1: Disabling hidden <a href="https://wikipedia.org/wiki/HTTP_referer">HTTP
|
||||||
|
Referer</a> system.
|
||||||
|
v2.personal.disabled.list.2: Disabling Google's predatory <i>Topics API</i>
|
||||||
|
and defunct <a href="https://www.eff.org/deeplinks/2021/03/googles-floc-terrible-idea"><i>Cohort</i></a>
|
||||||
|
ad-serving systems.
|
||||||
|
v2.personal.disabled.list.3: Preventing any external third-party code from
|
||||||
|
being injected into the page.
|
||||||
|
v2.personal.tracking.text.1: It is our belief that the web and modern technology
|
||||||
|
in general should never be used to track and spy on people in any way shape or form.
|
||||||
|
v2.personal.tracking.text.2: We believe that any service that is in any way
|
||||||
|
trying to force you to disable any ad-blocking or privacy-enhancing extensions should
|
||||||
|
be avoided at all cost and shunned for their practices.
|
||||||
|
v2.personal.tracking.text.3: Modern website should <b>never</b> break with
|
||||||
|
those type of extensions unless they are purposefully built to track you to near-illegal
|
||||||
|
extents, this excuse is only used to force you to accept these predatory practices.
|
||||||
|
_v2.personal.transparency.text.: Additionally, we believe in the principles
|
||||||
|
of transparency and openness [???]
|
||||||
|
v2.personal.recommendations: We also strongly recommend you to read the <acronym
|
||||||
|
title="European Union Agency for Cybersecurity">ENISA</acronym>'s <i>Privacy considerations
|
||||||
|
of online behavioural tracking report</i> in order to improve your online
|
12
data/strings/en/projects.yml
Normal file
12
data/strings/en/projects.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# EN - Projects
|
||||||
|
|
||||||
|
search.head.title: "Content search - NibblePoker"
|
||||||
|
search.head.description: "TODO: description"
|
||||||
|
|
||||||
|
search.og.title: "NibblePoker - Content search"
|
||||||
|
search.og.description: "TODO: description"
|
||||||
|
|
||||||
|
header.root: "Projects"
|
||||||
|
header.search: "Search"
|
||||||
|
header.error: "Error"
|
||||||
|
header.single: "Project"
|
21
data/strings/en/sidebar.yml
Normal file
21
data/strings/en/sidebar.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# FR - Sidebar
|
||||||
|
|
||||||
|
logo.alt: Website's logo
|
||||||
|
|
||||||
|
text.home: Home
|
||||||
|
text.shop: Shop
|
||||||
|
text.school: Training
|
||||||
|
text.articles: Articles
|
||||||
|
text.projects: Projects
|
||||||
|
text.applications: Applications
|
||||||
|
text.libraries: Libraries
|
||||||
|
text.electronics: Electronics
|
||||||
|
text.3d-print: 3D Printing
|
||||||
|
text.tools: Tools
|
||||||
|
text.links: Links
|
||||||
|
text.downloads: Downloads
|
||||||
|
text.gitea: Git Repos.
|
||||||
|
text.wiki: Wiki
|
||||||
|
text.about: About
|
||||||
|
text.contributors: Contributors
|
||||||
|
text.contact: Contact
|
20
data/strings/en/svg-to-png.yml
Normal file
20
data/strings/en/svg-to-png.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# EN - SVG to PNG
|
||||||
|
|
||||||
|
upload.add.button: "Add image(s)"
|
||||||
|
upload.clear.button: "Clear"
|
||||||
|
|
||||||
|
options.title: "Options"
|
||||||
|
|
||||||
|
fit.label: Fitting mode
|
||||||
|
|
||||||
|
fit.svg: SVG's resolution
|
||||||
|
fit.fixed: Fixed size
|
||||||
|
fit.bigger: Bigger or equal size
|
||||||
|
fit.smaller: Smaller or equal size
|
||||||
|
|
||||||
|
preview.title: "Preview"
|
||||||
|
|
||||||
|
download.main.button: "Convert & Download"
|
||||||
|
|
||||||
|
preview.generate.button: "Generate"
|
||||||
|
preview.clear.button: "Clear"
|
4
data/strings/en/uuid-generator.yml
Normal file
4
data/strings/en/uuid-generator.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# EN - UUID Generator
|
||||||
|
|
||||||
|
option.count: "UUID/GUID count"
|
||||||
|
option.hyphen: "Add hyphens"
|
94
data/strings/fr/about.yml
Normal file
94
data/strings/fr/about.yml
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
# FR - About
|
||||||
|
|
||||||
|
head.title: À-propos - NibblePoker
|
||||||
|
head.description: 'TODO: description'
|
||||||
|
og.title: NibblePoker - À-propos
|
||||||
|
og.description: 'TODO: description'
|
||||||
|
header.title: À-propos
|
||||||
|
intro.title: Introduction
|
||||||
|
intro.text.01: Je m'appelle Herwin Bozet, et je suis un développeur expérimenté
|
||||||
|
en PureBasic, Python, Java, VBA ; et de manière plus modérée en C, API Win32, systèmes
|
||||||
|
embarqués et le développement web général.
|
||||||
|
intro.text.02: Je programme depuis environ 10 ans, et au cours des 5 dernières
|
||||||
|
années, j'ai activement travaillé à l'application de cette expérience à divers projets
|
||||||
|
dans le but d'aider les programmeurs et les gens dans leur vie quotidienne.
|
||||||
|
intro.text.10: NibblePoker est, en essence, un simple pseudonyme et une ombrelle
|
||||||
|
sous laquelle la majeure partie de mon travail axé sur le public sera présente.
|
||||||
|
intro.text.11: Il abrite l'ensemble de mon travail créé et adapté pour être
|
||||||
|
utilisé par d'autres personnes.
|
||||||
|
intro.text.20: L'ensemble de ce site web, ainsi que l'ensemble de mon travail
|
||||||
|
et autres projets personnels réalisés pour lui, sont entièrement open-source et
|
||||||
|
disponibles sous des licences permissives approuvées par l'<abbr title="Open Source
|
||||||
|
Initiative">OSI</abbr>.
|
||||||
|
intro.text.21: Tout cela est maintenu, développé et étendu pendant mon temps
|
||||||
|
libre, avec l'aide occasionnelle de personnes de la communauté open source.
|
||||||
|
tenets.title: Principes fondamentaux
|
||||||
|
tenets.text.01: ''
|
||||||
|
tenets.text.02: ''
|
||||||
|
future.title: Projet d'avenir
|
||||||
|
future.text.01: 'Il est prévu que je décline NibblePoker en une petite <abbr
|
||||||
|
title="Societé privée à responsibilité limitée">SPRL</abbr> d''ici quelques années
|
||||||
|
si tout se déroule comme prévu.
|
||||||
|
|
||||||
|
'
|
||||||
|
future.text.02: Cela aura pour but de me permettre de centraliser plein de choses
|
||||||
|
et d'investir correctement dans mes domaines de prédilection.
|
||||||
|
future.text.10: La finalité serait de pouvoir créer un petit projet local d'entreprise
|
||||||
|
durable, ainsi que de proposer une large gamme de produits et solutions couvrant
|
||||||
|
les domaines de l'électronique connectée et intelligente, la programmation et l’indépendance
|
||||||
|
technologique tout en incluant les composantes logicielles et physiques souvent
|
||||||
|
manquantes dans de tels produits et solutions.
|
||||||
|
future.text.20: Finalement tout ce travail et recherches seraient mis à disposition
|
||||||
|
du public sous des licences open-source afin de permettre permettant à quiconque
|
||||||
|
le souhaite d’apprendre, réutiliser et revendre des produits ouverts tels que le
|
||||||
|
font des compagnies comme Adafruit.
|
||||||
|
_nibblepoker.title: Le nom 'NibblePoker'
|
||||||
|
_nibblepoker.text.01: Le surnom '<i>NibblePoker</i>' est un mot composé de plusieurs
|
||||||
|
termes [techniques] plus anciens.
|
||||||
|
_nibblepoker.text.10: "● '<i>Nibble</i>' est un terme technique anglais
|
||||||
|
historiquement utilisé pour décrire décrit un demi-octet, ou 4 bits d'information."
|
||||||
|
_nibblepoker.text.11: "● '<i>Poker</i>' viens du verbe anglais '<i>to
|
||||||
|
poke</i>' qui, dans le domaine rétro-informatique, décrit le fait d'écrire des données
|
||||||
|
dans la mémoire d'un ordinateur."
|
||||||
|
_nibblepoker.text.20: Finalement, lors de la création de ce surnom, je travaillais
|
||||||
|
depuis quelques temps sur d'anciennes machines telle la Commodore64, Acorn Electron
|
||||||
|
et [???]ironique.
|
||||||
|
financing.title: Financement
|
||||||
|
financing.text.01: Ce site web, ainsi que son infrastructure environnante, ont
|
||||||
|
été conçus pour coûter le moins possible tout en étant indépendants d'entreprises
|
||||||
|
qui se prennent pour des censeurs.
|
||||||
|
financing.text.02: Et en suivant mes principes fondamentaux, je souhaitais également
|
||||||
|
conserver une "souveraineté technologique", et, par conséquent, refuse de soutenir
|
||||||
|
ou d'utiliser des entreprises qui luttent activement contre la liberté d'expression.
|
||||||
|
financing.text.10: Le détail des coûts opérationnels sont présents ci-dessous
|
||||||
|
afin d'illustrer le faible prix d'une telle indépendance.
|
||||||
|
financing.text.20: Et pour les plus motivés d'entre-vous, j'espère pouvoir vous
|
||||||
|
motiver à au moins tester ce genre d'activités.
|
||||||
|
financing.text.21: C'est un domaine qui peut paraître intimidant de prime abord,
|
||||||
|
mais pour une fraction du coût présenté ici, <b>et avec un rien de motivation</b>,
|
||||||
|
vous pouvez déjà accomplir énormément de choses et acquérir des connaissances essentielles
|
||||||
|
dans un monde aussi connecté que le nôtre.
|
||||||
|
financing.text.isp: Le coût de la connexion internet n'est pas compté car elle
|
||||||
|
pourrait être remplacée par un Wi-Fi public lambda.
|
||||||
|
financing.part.service: Service
|
||||||
|
financing.part.cost: Coût
|
||||||
|
financing.part.cost.total: Coût Total
|
||||||
|
financing.part.equipment: Matériel
|
||||||
|
financing.part.cost.yearly: Coût Annuel
|
||||||
|
financing.part.cost.yearly.total: Coût Annuel
|
||||||
|
financing.part.domain.lu: Domaine en <i>.lu</i>
|
||||||
|
financing.part.domain.com: Domaine en <i>.com</i>
|
||||||
|
financing.part.proxy.europe: Reverse-proxy en Europe
|
||||||
|
financing.part.proxy.america: Reverse-proxy en Amérique
|
||||||
|
financing.part.proxy.asia: Reverse-proxy en Asie
|
||||||
|
financing.part.emails: Adresses email
|
||||||
|
financing.part.electricity: Électricité
|
||||||
|
financing.part.nanopir4s: NanoPi R4S
|
||||||
|
financing.part.nanopir4s.desc: Gère tous les services et programmes internes.
|
||||||
|
financing.part.storage: Stockage local
|
||||||
|
aziascreations.title: Le nom 'AziasCreations'
|
||||||
|
aziascreations.text.01: L'ancien surnom 'AziasCreations' était utilisé entre
|
||||||
|
2013 et 2020 et est à présent abandonné au profit de <i>NibblePoker</i>.
|
||||||
|
aziascreations.text.10: Cependant, il reste utilisé sur GitHub et Gitea à cause
|
||||||
|
de certaines limitations concernant les changements de pseudonyme qui m'ont empèché
|
||||||
|
de faire un changement complet.
|
55
data/strings/fr/circuitpython-ebyte-e32.yml
Normal file
55
data/strings/fr/circuitpython-ebyte-e32.yml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# FR - Project - CircuitPython EByte E32
|
||||||
|
|
||||||
|
meta.title: CircuitPython - Driver Ebyte E32
|
||||||
|
meta.description: Driver CircuitPython pour les modules sérial LoRa E32 de Ebyte tournant
|
||||||
|
sous les chipset SX1278/SX1276.
|
||||||
|
article.subtitle: <a href="https://github.com/aziascreations/CircuitPython-Ebyte-E32"><i
|
||||||
|
class="fab fa-github"></i> Voir sur GitHub</a>
|
||||||
|
intro.title: Introduction
|
||||||
|
intro.p1: Ce projet est un driver qui vous permet d'interagir avec la série de modules
|
||||||
|
LoRa E32 d'Ebyte dans CircuitPython.
|
||||||
|
features.title: Fonctionnalités
|
||||||
|
features.1: Prend en charge tous les modules E32 UART standards.
|
||||||
|
features.2: 'Support supplémentaire en fonction de la fréquence et de la puissance
|
||||||
|
:'
|
||||||
|
features.2.1: Constantes pour la puissance d'émission.
|
||||||
|
features.2.2: "<s>Calculatrices de taille de paquet maximale.</s> (À FAIRE)"
|
||||||
|
features.2.3: Entièrement facultatif via des modules séparés.
|
||||||
|
features.3: 'Versions minifiées pour les appareils avec un espace de stockage réduit
|
||||||
|
:'
|
||||||
|
features.3.1: ~75 % plus petites pour les fichiers <code class="code">.py</code>
|
||||||
|
features.3.2: ~5 % plus petites pour les fichiers <code class="code">.mpy</code>
|
||||||
|
limitations.title: Limitations
|
||||||
|
limitations.1: 'Aucune limitation de taille de paquet intégrée :'
|
||||||
|
limitations.1.1: Varie grandement entre les fréquences et les paramètres d'utilisation.
|
||||||
|
limitations.1.2: Pas suffisamment documentée dans les spécifications techniques de
|
||||||
|
LoRA et LoRaWAN.
|
||||||
|
limitations.2: 'Aucun protocole intégré :'
|
||||||
|
limitations.2.1: Tous les paquets LoRa sont collés les uns aux autres dans un buffer
|
||||||
|
lors de la réception.
|
||||||
|
limitations.2.2: Aucun support pour LoRaWAN. (Limitation du module)
|
||||||
|
limitations.3: 'Support avancé manquant pour certains modules :'
|
||||||
|
limitations.3.1: Modules avec les préfixes <code class="code">170</code>, <code class="code">400</code>
|
||||||
|
ou <code class="code">900</code>. (S'améliorera avec le temps)
|
||||||
|
doc.title: Documentation
|
||||||
|
doc.p1: Toute la documentation de ce projet est disponible sur Github.<br>Les fiches
|
||||||
|
techniques de tous les modules E32 peuvent également être trouvées sur "<a href="https://files.nibblepoker.lu/datasheets/ebyte/e32/">files.nibblepoker.lu</a>".
|
||||||
|
usage.title: Utilisation
|
||||||
|
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 <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é.
|
||||||
|
downloads.title: Télechargements
|
||||||
|
license.title: Licence
|
||||||
|
links.title: Liens
|
23
data/strings/fr/commons.yml
Normal file
23
data/strings/fr/commons.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# FR - Commons
|
||||||
|
|
||||||
|
action.copy: Copier
|
||||||
|
action.copied: Copié
|
||||||
|
|
||||||
|
undefined: Indéfini(e)
|
||||||
|
na: Non-applicable
|
||||||
|
|
||||||
|
yes: Oui
|
||||||
|
no: Non
|
||||||
|
|
||||||
|
width: Largeur
|
||||||
|
height: Hauteur
|
||||||
|
width.min: Largeur minimale
|
||||||
|
height.min: Hauteur minimale
|
||||||
|
width.max: Largeur maximale
|
||||||
|
height.max: Hauteur maximale
|
||||||
|
|
||||||
|
user-agent: User-Agent
|
||||||
|
|
||||||
|
server: Serveur
|
||||||
|
|
||||||
|
cpu.architecture: CPU Architecture
|
15
data/strings/fr/contact.yml
Normal file
15
data/strings/fr/contact.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# FR - Contact
|
||||||
|
|
||||||
|
head.title: Contact - NibblePoker
|
||||||
|
head.description: 'TODO: description'
|
||||||
|
|
||||||
|
og.title: NibblePoker - Contact
|
||||||
|
og.description: 'TODO: description'
|
||||||
|
|
||||||
|
header.title: Contact
|
||||||
|
|
||||||
|
email.title: Courriel
|
||||||
|
email.compose: Envoyer un courriel à <i>herwin.bozet@gmail.com</i>
|
||||||
|
|
||||||
|
twitter.title: Twitter
|
||||||
|
twitter.compose: Composer un message privé pour @NibblePoker sur Twitter
|
25
data/strings/fr/debug.yml
Normal file
25
data/strings/fr/debug.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# FR - Debug
|
||||||
|
|
||||||
|
head.title: Débogueur - NibblePoker
|
||||||
|
head.description: Page de débogage utilisée pour analyser le comportement des
|
||||||
|
différents mécanismes utilisés par ce site web.
|
||||||
|
og.title: NibblePoker - Débogueur
|
||||||
|
og.description: Page de débogage utilisée pour analyser le comportement des
|
||||||
|
différents mécanismes utilisés par ce site web.
|
||||||
|
header.title: Débogueur
|
||||||
|
tables.field: Champ
|
||||||
|
tables.value: Valeur
|
||||||
|
host.title: Configuration de l'hôte
|
||||||
|
host.requested: Demandé
|
||||||
|
host.domain: Domaine
|
||||||
|
host.uri: URI
|
||||||
|
host.tld: TLD
|
||||||
|
host.waffle: Mode gaufrier
|
||||||
|
host.bouneschlupp: Mode Bouneschlupp
|
||||||
|
lang.title: Système de localisation (L10N)
|
||||||
|
lang.compile-date: Date de compilation
|
||||||
|
lang.default: Langue par défaut
|
||||||
|
lang.user: Langue active
|
||||||
|
lang.header.raw: En-tête HTTP brut
|
||||||
|
lang.header.processed: En-tête HTTP traité
|
||||||
|
client.title: Informations du client
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user