Added more content, Minor incremental improvements

Update app.py, uuid-generator.yml, and 23 more files...
This commit is contained in:
2025-02-24 21:17:56 +01:00
parent 0e91b5ed96
commit ec905b4735
23 changed files with 608 additions and 69 deletions

69
app.py
View File

@@ -3,18 +3,15 @@ import os
from html import escape from html import escape
from typing import Optional from typing import Optional
from bs4 import BeautifulSoup
from flask import Flask, request, send_from_directory, url_for, Response from flask import Flask, request, send_from_directory, url_for, Response
from flask import render_template from flask import render_template
from minify_html import minify
from werkzeug.exceptions import HTTPException from werkzeug.exceptions import HTTPException
from website.content import get_articles, get_projects, get_tools, sanitize_input_tags, load_content_items, get_content, \ from website.content import get_projects, get_tools, sanitize_input_tags, load_content_items, get_content, \
get_applets get_applets, get_projects_languages, get_projects_by_languages
from website.contributors import reload_contributors_data, get_contributors_data from website.contributors import reload_contributors_data
from website.domains import ALLOWED_DOMAINS from website.domains import ALLOWED_DOMAINS
from website.l10n.utils import get_user_lang, localize, reload_strings, l10n_url_abs, l10n_url_switch, L10N, \ from website.l10n.utils import get_user_lang, localize, reload_strings, l10n_url_abs, l10n_url_switch, DEFAULT_LANG
DEFAULT_LANG
from website.renderers.applet import render_applet_scripts, render_applet_head from website.renderers.applet import render_applet_scripts, render_applet_head
from website.renderers.button import render_button from website.renderers.button import render_button
from website.renderers.code import render_code_block from website.renderers.code import render_code_block
@@ -22,6 +19,7 @@ from website.renderers.headings import render_heading, render_h2, render_h1, ren
from website.renderers.paragraph import render_paragraph from website.renderers.paragraph import render_paragraph
from website.renderers.lists import render_list_ul from website.renderers.lists import render_list_ul
from website.renderers.splide import render_splide from website.renderers.splide import render_splide
from website.renderers.standalone import get_standalone_common_headers
from website.sidebar import reload_sidebar_entries, get_sidebar_entries from website.sidebar import reload_sidebar_entries, get_sidebar_entries
from website.sitemap import reload_sitemap_entries, get_sitemap_entries from website.sitemap import reload_sitemap_entries, get_sitemap_entries
@@ -34,11 +32,15 @@ except ImportError:
if os.environ.get('NP_HTML_POST_PROCESS', "NONE") == "MINIFY": if os.environ.get('NP_HTML_POST_PROCESS', "NONE") == "MINIFY":
print("Using 'minify' as HTML post-processor") print("Using 'minify' as HTML post-processor")
from minify_html import minify
def post_process_html(html: str) -> str: def post_process_html(html: str) -> str:
return minify(html).replace("> <", "><") return minify(html).replace("> <", "><")
elif os.environ.get('NP_HTML_POST_PROCESS', "NONE") == "BS4": elif os.environ.get('NP_HTML_POST_PROCESS', "NONE") == "BS4":
print("Using 'BeautifulSoup4' as HTML post-processor") print("Using 'BeautifulSoup4' as HTML post-processor")
from bs4 import BeautifulSoup
def post_process_html(html: str) -> str: def post_process_html(html: str) -> str:
return BeautifulSoup(html, features="html.parser").prettify() return BeautifulSoup(html, features="html.parser").prettify()
else: else:
@@ -104,8 +106,11 @@ def inject_processors():
# Content # Content
get_content=get_content, get_content=get_content,
get_articles=get_articles, get_applets=get_applets,
# get_articles=get_articles,
get_projects=get_projects, get_projects=get_projects,
get_projects_by_languages=get_projects_by_languages,
get_projects_languages=get_projects_languages,
get_tools=get_tools, get_tools=get_tools,
# Renderers # Renderers
@@ -125,6 +130,9 @@ def inject_processors():
# Commons # Commons
url_for=url_for, url_for=url_for,
escape=escape, escape=escape,
# Standalone
get_standalone_common_headers=get_standalone_common_headers
) )
@@ -150,12 +158,13 @@ def route_sitemap():
@app.route('/fr/', defaults={'lang': "fr"}) @app.route('/fr/', defaults={'lang': "fr"})
def route_root(lang: Optional[str]): def route_root(lang: Optional[str]):
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE")) user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
return post_process_html(render_template( return post_process_html(render_template(
"pages/root.jinja", "pages/root.jinja",
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
)).replace("> <", "><") )).replace("> <", "><")
@@ -164,12 +173,13 @@ def route_root(lang: Optional[str]):
@app.route('/fr/contact/', defaults={'lang': "fr"}) @app.route('/fr/contact/', defaults={'lang': "fr"})
def route_contact(lang: Optional[str]): def route_contact(lang: Optional[str]):
user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE")) user_lang = get_user_lang(lang, request.headers.get("HTTP_ACCEPT_LANGUAGE"))
return post_process_html(render_template( return post_process_html(render_template(
"pages/contact.jinja", "pages/contact.jinja",
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
)).replace("> <", "><") )).replace("> <", "><")
@@ -189,7 +199,7 @@ def route_content(lang: Optional[str]):
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
requested_tags=requested_tags, requested_tags=requested_tags,
)).replace("> <", "><") )).replace("> <", "><")
@@ -215,7 +225,7 @@ def route_content_project(lang: Optional[str], project_id: str):
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
error_key=error_key, error_key=error_key,
error_code=error_code, error_code=error_code,
)).replace("> <", "><"), error_code )).replace("> <", "><"), error_code
@@ -225,7 +235,7 @@ def route_content_project(lang: Optional[str], project_id: str):
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
project_data=get_projects().get(project_id), project_data=get_projects().get(project_id),
project_id=project_id, project_id=project_id,
)).replace("> <", "><") )).replace("> <", "><")
@@ -247,7 +257,7 @@ def route_tools_index(lang: Optional[str]):
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
requested_tags=requested_tags, requested_tags=requested_tags,
)).replace("> <", "><") )).replace("> <", "><")
@@ -273,7 +283,7 @@ def route_tools_page(lang: Optional[str], tool_id: str):
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
error_key=error_key, error_key=error_key,
error_code=error_code, error_code=error_code,
)).replace("> <", "><"), error_code )).replace("> <", "><"), error_code
@@ -283,7 +293,7 @@ def route_tools_page(lang: Optional[str], tool_id: str):
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
tool_data=get_tools().get(tool_id), tool_data=get_tools().get(tool_id),
tool_id=tool_id, tool_id=tool_id,
applet_data=get_applets().get(get_tools().get(tool_id).applet_id), applet_data=get_applets().get(get_tools().get(tool_id).applet_id),
@@ -300,7 +310,7 @@ def route_about(lang: Optional[str]):
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
)).replace("> <", "><") )).replace("> <", "><")
@@ -314,7 +324,7 @@ def route_privacy(lang: Optional[str]):
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
)).replace("> <", "><") )).replace("> <", "><")
@@ -328,7 +338,7 @@ def route_links(lang: Optional[str]):
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
)).replace("> <", "><") )).replace("> <", "><")
@@ -342,7 +352,7 @@ def route_debug(lang: Optional[str]):
user_lang=user_lang, user_lang=user_lang,
raw_lang=lang, raw_lang=lang,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
)).replace("> <", "><") )).replace("> <", "><")
@@ -361,7 +371,7 @@ def handle_exception(e: Exception):
user_lang=DEFAULT_LANG, user_lang=DEFAULT_LANG,
raw_lang=DEFAULT_LANG, raw_lang=DEFAULT_LANG,
request_path=request.path, request_path=request.path,
standalone="standalone" in request.args, is_standalone="standalone" in request.args,
error_key=str(e.code), error_key=str(e.code),
error_code=e.code, error_code=e.code,
)).replace("> <", "><"), error_code )).replace("> <", "><"), error_code
@@ -374,24 +384,13 @@ if __name__ == '__main__':
reload_contributors_data(os.path.join(os.getcwd(), "data/contributors.yml")) reload_contributors_data(os.path.join(os.getcwd(), "data/contributors.yml"))
reload_sitemap_entries(os.path.join(os.getcwd(), "data/sitemap.yml")) reload_sitemap_entries(os.path.join(os.getcwd(), "data/sitemap.yml"))
# try: #from waitress import serve
# os.remove("data/strings/dumps.json") #serve(app, host='0.0.0.0', port=5000, threads=64)
# 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( app.run(
host="0.0.0.0", host="0.0.0.0",
port=5000, port=5000,
debug=True, debug=True,
#debug=False, # debug=False,
load_dotenv=False load_dotenv=False
) )

View File

@@ -1,8 +1,8 @@
applets: applets:
- id: "uuid-generator" - id: "web-usb-test"
resources: resources:
scripts: scripts:
- "uuid-generator.mjs" - "web-usb-test.mjs"
stylesheets: stylesheets:
- "uuid-generator.css" - "web-usb-test.css"

View File

@@ -0,0 +1,8 @@
applets:
- id: "uuid-generator"
resources:
scripts:
- "uuid-generator.mjs"
stylesheets:
- "uuid-generator.css"

View File

@@ -0,0 +1,34 @@
projects:
- id: "lscom-cli-dotnet"
metadata:
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/lscom/lscom-v2-text-01-bkgd-cli.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/lscom/lscom-v2-text-01-bkgd-cli.png"
image_alt_key: ""
general:
icon: "fad fa-terminal"
title_key: "meta.title"
subtitle_key: "article.subtitle"
tags:
- "application"
- "tool"
- "windows"
languages:
- "dotnet"

View File

@@ -0,0 +1,32 @@
projects:
- id: "web-usb-test"
metadata:
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/web-usb-test/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/web-usb-test/main.png"
image_alt_key: ""
general:
icon: "fab fa-docker"
title_key: "meta.title"
subtitle_key: "article.subtitle"
tags:
- "experiments"
languages:
- "javascript"

View File

@@ -20,6 +20,42 @@ user-agent: User-Agent
server: Server server: Server
cpu.architecture: Architecture de CPU cpu.architecture: CPU Architecture
cpu.responsive: "CPU<span class=\"mobile-hide\"> Architecture</span>"
cpu.any: "Any architecture"
cpu.x64: "x64"
#cpu.x64: "<p>x64<br>AMD64</p>"
cpu.x86: "x86"
cpu.arm32: "ARM32"
#cpu.arm32: "<p>ARM32<br>ARMv7<br>AArch32</p>"
cpu.arm64: "ARM64"
#cpu.arm64: "<p>ARM64<br>ARMv8<br>AArch64</p>"
cpu.risc-v: "RISC-V"
requirements: Requirements
python: Python python: Python
java: Java
c99: C99
dotnet: .NET
purebasic: PureBasic
version: "Version"
version.current: "Current version"
version.previous.single: "Previous version"
version.previous.multiple: "Previous versions"
version.old.single: "Old version"
version.old.multiple: "Old versions"
source.code: "Source code"
download.single: "Download"
download.multiple: "Downloads"
github: "GitHub Repository"
gitea: "Self-hosted Gitea Repository"
nuget: "Nuget Package"
none.ms: None
none.mp: None
none.fs: None
none.fp: None

View File

@@ -0,0 +1,47 @@
# EN - DotNet-ListComPort
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>
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

View File

@@ -20,6 +20,42 @@ user-agent: User-Agent
server: Serveur server: Serveur
cpu.architecture: CPU Architecture cpu.architecture: Architecture de CPU
cpu.responsive: "<span class=\"mobile-hide\">Architecture de </span>CPU"
cpu.any: "Indépendante"
cpu.x64: "x64"
#cpu.x64: "<p>x64<br>AMD64</p>"
cpu.x86: "x86"
cpu.arm32: "ARM32"
#cpu.arm32: "<p>ARM32<br>ARMv7<br>AArch32</p>"
cpu.arm64: "ARM64"
#cpu.arm64: "<p>ARM64<br>ARMv8<br>AArch64</p>"
cpu.risc-v: "RISC-V"
requirements: "Dépendances"
python: Python python: Python
java: Java
c99: C99
dotnet: .NET
purebasic: PureBasic
version: "Version"
version.current: "Version actuelle"
version.previous.single: "Version précédente"
version.previous.multiple: "Versions précédentes"
version.old.single: "Ancienne version"
version.old.multiple: "Anciennes versions"
source.code: "Code source"
download.single: "Téléchargement"
download.multiple: "Téléchargements"
github: "Dépôt GitHub"
gitea: "Dépôt Gitea auto-hébergé"
nuget: "Packet Nuget"
none.ms: Aucun
none.mp: Aucuns
none.fs: Aucune
none.fp: Aucunes

View File

@@ -0,0 +1,46 @@
# FR - DotNet-ListComPort
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.dotnet: <a href="https://dotnet.microsoft.com/en-us/download/dotnet/6.0">.NET 6.0</a>
packages.title: Paquets
packages.single.title: ???&nbsp;&nbsp;<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: ???&nbsp;&nbsp;<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

View File

@@ -0,0 +1,60 @@
/**
* Checks if the required JS API for WebUSB is available.
* @returns {boolean}
*/
function isWebUsbAvailable() {
return navigator.usb !== null;
}
// Tool-centric stuff
{
/** @type {HTMLElement} */
const eApiSupportedText = document.querySelector("#web-usb-test-api-supported");
/** @type {HTMLElement} */
const eApiNonSupportedText = document.querySelector("#web-usb-test-api-not-supported");
/** @type {HTMLElement} */
const eApiSupportUnknownText = document.querySelector("#web-usb-test-api-support-unknown");
/** @type {HTMLButtonElement} */
const eListAllButton = document.querySelector("button#web-usb-test-list-all");
/** @type {HTMLButtonElement} */
const eBa63GetterButton = document.querySelector("button#web-usb-test-ba63-getter");
window.onload = function () {
if (!isWebUsbAvailable()) {
eApiSupportUnknownText.hidden = true;
eApiNonSupportedText.hidden = false;
return;
}
eApiSupportUnknownText.hidden = true;
eApiSupportedText.hidden = false;
eListAllButton.addEventListener("click", function () {
navigator.usb.getDevices().then((devices) => {
console.log(`Total devices: ${devices.length}`);
devices.forEach((device) => {
console.log(
`Product name: ${device.productName}, serial number ${device.serialNumber}`,
);
console.log(device);
});
});
});
eBa63GetterButton.addEventListener("click", function () {
const filters = [
{vendorId: 0x0AA7, productId: 0x0200},
];
navigator.usb
.requestDevice({filters})
.then((usbDevice) => {
console.log(`Product name: ${usbDevice.productName}`);
})
.catch((e) => {
console.error(`There is no device. ${e}`);
});
});
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
<h2>Test 123</h2>
<p id="web-usb-test-api-supported" hidden>Supported</p>
<p id="web-usb-test-api-not-supported" hidden>Not Available</p>
<p id="web-usb-test-api-support-unknown">Unknown / Blocked</p>
<button id="web-usb-test-list-all" class="p-xxs r-s border">List all</button>
<button id="web-usb-test-ba63-getter" class="p-xxs r-s border">Ba63</button>

View File

@@ -7,12 +7,17 @@
<meta name="viewport" content="width=device-width"/> <meta name="viewport" content="width=device-width"/>
<meta name="author" content="Herwin Bozet"> <meta name="author" content="Herwin Bozet">
<meta name="robots" content="index, follow"> <meta name="robots" content="index, follow">
<!-- Check: https://css-tricks.com/probably-dont-base64-svg/ -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg"> <link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="alternate icon" href="/favicon.ico"> <link rel="alternate icon" href="/favicon.ico">
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/FontAwesomePro/6.5.1/css/all.min.css">
<!--<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/NibblePoker/StandardCSS/nibblepoker.min.css">--> <!--<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/FontAwesomePro/6.5.1/css/all.min.css">-->
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/NibblePoker/IndevCSS/nibblepoker.min.css"> <!--<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/NibblePoker/IndevCSS/nibblepoker.min.css">-->
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/Quantum/Quantum.min.css"> <!--<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/Quantum/Quantum.min.css">-->
{{ get_standalone_common_headers() }}
<!-- No '<link>' should be present in here -->
{% block extra_stylesheets %}{% endblock %}
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" <meta name="viewport"
@@ -40,5 +45,7 @@
</a> </a>
</footer> </footer>
{% block extra_scripts %}{% endblock %}
</body> </body>
</html> </html>

View File

@@ -1,10 +1,14 @@
{% extends "base_www.jinja" %} {% if is_standalone %}
{% extends "base_standalone.jinja" %}
{% else %}
{% extends "base_www.jinja" %}
{% endif %}
{% block head_title %}{{ l10n(tool_data.metadata.head.title_key, tool_id, user_lang) }}{% endblock %} {% block head_title %}{{ l10n(tool_data.metadata.head.title_key, tool_id, user_lang) }}{% endblock %}
{% block head_description %}{{ l10n(tool_data.metadata.head.description_key, tool_id, user_lang) }}{% endblock %} {% block head_description %}{{ l10n(tool_data.metadata.head.description_key, tool_id, user_lang) }}{% endblock %}
{% block extra_stylesheets %} {% block extra_stylesheets %}
{{ render_applet_head(applet_data) }} {{ render_applet_head(applet_data, is_standalone) }}
{% endblock %} {% endblock %}
{% block header_title %} {% block header_title %}
@@ -24,5 +28,5 @@
{% endblock %} {% endblock %}
{% block extra_scripts %} {% block extra_scripts %}
{{ render_applet_scripts(applet_data) }} {{ render_applet_scripts(applet_data, is_standalone) }}
{% endblock %} {% endblock %}

View File

@@ -0,0 +1,169 @@
{% extends "projects/_project.jinja" %}
{% block project_content %}
{{ render_h2(l10n("intro.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("intro.p1", project_id, user_lang)) }}
{{ render_paragraph(l10n("intro.p2", project_id, user_lang)) }}
{{ render_paragraph(l10n("intro.p3", project_id, user_lang)) }}
{{ render_h2(l10n("requirements.title", project_id, user_lang)) }}
{{ render_list_ul([
l10n("requirements.1", project_id, user_lang),
[
l10n("requirements.2", project_id, user_lang),
],
l10n("requirements.3", project_id, user_lang),
[
l10n("requirements.4", project_id, user_lang),
],
]) }}
{{ render_h2(l10n("improvements.title", project_id, user_lang)) }}
{{ render_list_ul([
l10n("improvements.1", project_id, user_lang),
l10n("improvements.2", project_id, user_lang),
l10n("improvements.3", project_id, user_lang),
l10n("improvements.4", project_id, user_lang),
l10n("improvements.5", project_id, user_lang),
]) }}
{{ render_h2(l10n("screenshots.title", project_id, user_lang)) }}
{{ render_splide([
'<img src="' + url_for("static", filename="/resources/NibblePoker/images/content/lscom/screen-cli-stylish-2x-xBR.png") + '">',
'<img src="' + url_for("static", filename="/resources/NibblePoker/images/content/lscom/screen-cli-csv-2x-xBR.png") + '">',
'<img src="' + url_for("static", filename="/resources/NibblePoker/images/content/lscom/screen-cli-full-2x-xBR.png") + '">',
]) }}
{{ render_h2(l10n("usage.title", project_id, user_lang)) }}
{{
render_code_block([
"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')"
], None)
}}
{{ render_h2(l10n("formatting.title", project_id, user_lang)) }}
{{
render_code_block([
" *┬> 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"
], None)
}}
{{ render_h2(l10n("packages.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("packages.single.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("packages.single.1", project_id, user_lang)) }}
{{ render_paragraph(l10n("packages.self.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("packages.self.1", project_id, user_lang)) }}
{{ render_paragraph(l10n("packages.msi.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("packages.msi.1", project_id, user_lang)) }}
{{ render_h2(l10n("version.current", "commons", user_lang)) }}
<table class="table-stylish table-p-s border r-l">
<thead>
<tr>
<th>{{ l10n("cpu.architecture", "commons", user_lang) }}</th>
<th>{{ l10n("requirements", "commons", user_lang) }}</th>
<th>{{ l10n("download.multiple", "commons", user_lang) }}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ l10n("cpu.any", "commons", user_lang) }}</td>
<td>{{ l10n("requirements.text.dotnet", project_id, user_lang) }}</td>
<td>...</td>
</tr>
<tr>
<td rowspan="2">{{ l10n("cpu.x64", "commons", user_lang) }}</td>
<td>{{ l10n("requirements.text.dotnet", project_id, user_lang) }}</td>
<td>...</td>
</tr>
<tr>
<td>{{ l10n("none.fs", "commons", user_lang) }}</td>
<td>...</td>
</tr>
<tr>
<td rowspan="2">{{ l10n("cpu.x86", "commons", user_lang) }}</td>
<td>{{ l10n("requirements.text.dotnet", project_id, user_lang) }}</td>
<td>...</td>
</tr>
<tr>
<td>{{ l10n("none.fs", "commons", user_lang) }}</td>
<td>...</td>
</tr>
<tr>
<td rowspan="2">{{ l10n("cpu.arm64", "commons", user_lang) }}</td>
<td>{{ l10n("requirements.text.dotnet", project_id, user_lang) }}</td>
<td>...</td>
</tr>
<tr>
<td>{{ l10n("none.fs", "commons", user_lang) }}</td>
<td>...</td>
</tr>
<tr>
<td rowspan="2">{{ l10n("cpu.arm32", "commons", user_lang) }}</td>
<td>{{ l10n("requirements.text.dotnet", project_id, user_lang) }}</td>
<td>...</td>
</tr>
<tr>
<td>{{ l10n("none.fs", "commons", user_lang) }}</td>
<td>...</td>
</tr>
</tbody>
</table>
{{ render_h2(l10n("source.code", "commons", user_lang)) }}
<table class="table-stylish table-p-s border r-l">
<thead>
<tr>
<th>{{ l10n("version", "commons", user_lang) }}</th>
<th>{{ l10n("download.multiple", "commons", user_lang) }}</th>
</tr>
</thead>
<tbody>
<tr>
<td>v3.0.0</td>
<td>...</td>
</tr>
</tbody>
</table>
{{ render_h2(l10n("links.title", project_id, user_lang)) }}
{{ render_list_ul([
"<a href='https://github.com/aziascreations/DotNet-ListComPort'>" +
l10n("github", "commons", user_lang) +
"</a>",
]) }}
{% endblock %}

View File

@@ -0,0 +1,18 @@
{% extends "projects/_project.jinja" %}
{% block extra_stylesheets %}
{{ render_applet_head(get_applets()["web-usb-test"], is_standalone) }}
{% endblock %}
{% block project_content %}
{{ render_h2(l10n("intro.title", project_id, user_lang)) }}
{{ render_paragraph(l10n("intro.1", project_id, user_lang)) }}
{{ render_paragraph(l10n("intro.2", project_id, user_lang)) }}
{% include 'applets/web-usb-test.jinja' %}
{% endblock %}
{% block extra_scripts %}
{{ render_applet_scripts(get_applets()["web-usb-test"], is_standalone) }}
{% endblock %}

View File

@@ -1,5 +1,4 @@
import os import os
from pathlib import Path
from typing import Any from typing import Any
from locked_dict.locked_dict import LockedDict from locked_dict.locked_dict import LockedDict
@@ -9,11 +8,6 @@ from .dataclasses import *
__CONTENT: ContentRoot = ContentRoot() __CONTENT: ContentRoot = ContentRoot()
__CONTENT_APPLETS: LockedDict[str, ContentApplet] = LockedDict()
__CONTENT_ARTICLES: LockedDict = LockedDict()
__CONTENT_PROJECTS: LockedDict[str, ContentProject] = LockedDict()
__CONTENT_TOOLS: LockedDict[str, ContentTool] = LockedDict()
def get_content() -> ContentRoot: def get_content() -> ContentRoot:
return __CONTENT return __CONTENT
@@ -23,8 +17,8 @@ def get_applets() -> LockedDict[str, ContentApplet]:
return __CONTENT.applets return __CONTENT.applets
def get_articles() -> LockedDict: #def get_articles() -> LockedDict:
return __CONTENT_ARTICLES # return __CONTENT.a
def get_projects() -> LockedDict[str, ContentProject]: def get_projects() -> LockedDict[str, ContentProject]:
@@ -39,12 +33,24 @@ def get_projects_by_tags(tags: list[str]) -> dict[Any, ContentProject]:
} }
def get_projects_by_languages(languages: list[str]) -> dict[Any, ContentProject]:
project_obj: ContentProject
return {
project_key: project_value for project_key, project_value in __CONTENT.projects.items()
if any(language in project_value.metadata.general.languages for language in languages)
}
def get_projects_languages() -> list[str]:
return __CONTENT.projects_languages
def get_tools() -> LockedDict[str, ContentTool]: def get_tools() -> LockedDict[str, ContentTool]:
return __CONTENT.tools return __CONTENT.tools
def get_tools_by_tags(tags: list[str]) -> dict[Any, ContentProject]: def get_tools_by_tags(tags: list[str]) -> dict[Any, ContentProject]:
tool_obj: ContentProject tool_obj: ContentTool
return { return {
tool_key: tool_value for tool_key, tool_value in __CONTENT.tools.items() tool_key: tool_value for tool_key, tool_value in __CONTENT.tools.items()
if any(tag in tool_value.metadata.general.tags for tag in tags) if any(tag in tool_value.metadata.general.tags for tag in tags)
@@ -100,7 +106,7 @@ def load_content_items() -> None:
for project_data in projects_data["projects"]: for project_data in projects_data["projects"]:
_project = ContentProject(**project_data) _project = ContentProject(**project_data)
__CONTENT.projects[_project.id] = _project __CONTENT.projects[_project.id] = _project
print(_project) #print(_project)
"""for project_item in os.listdir(os.path.join(os.getcwd(), "data/projects")): """for project_item in os.listdir(os.path.join(os.getcwd(), "data/projects")):
project_item_path = os.path.join(os.getcwd(), "data/projects/", project_item) project_item_path = os.path.join(os.getcwd(), "data/projects/", project_item)
@@ -143,6 +149,13 @@ def load_content_items() -> None:
# FIXME: Check if the required files exist too !""" # FIXME: Check if the required files exist too !"""
# Preparing some more stuff
for project in __CONTENT.projects.values():
__CONTENT.projects_languages.extend(project.metadata.general.languages)
__CONTENT.projects_languages = list(set(__CONTENT.projects_languages))
__CONTENT.projects_languages.sort()
#print(__CONTENT.projects_languages)
def validate_content_items() -> bool: def validate_content_items() -> bool:
pass pass

View File

@@ -114,3 +114,4 @@ class ContentRoot:
# articles: list[Con] = field(default_factory=list) # articles: list[Con] = field(default_factory=list)
projects: LockedDict[str, ContentProject] = field(default_factory=LockedDict) projects: LockedDict[str, ContentProject] = field(default_factory=LockedDict)
tools: LockedDict[str, ContentTool] = field(default_factory=LockedDict) tools: LockedDict[str, ContentTool] = field(default_factory=LockedDict)
projects_languages: list[str] = field(default_factory=list)

View File

@@ -1,12 +1,18 @@
import os
from flask import url_for from flask import url_for
from website.content import ContentApplet from website.content import ContentApplet
def render_applet_head(applet_data: ContentApplet) -> str: def render_applet_head(applet_data: ContentApplet, is_standalone: bool = False) -> str:
applet_style_html = "" applet_style_html = ""
for applet_style in applet_data.resources.stylesheets: for applet_style in applet_data.resources.stylesheets:
if is_standalone:
with open(os.path.join("./static/resources/NibblePoker/applets/", applet_data.id, applet_style)) as applet_style_file:
applet_style_html += "<style>" + applet_style_file.read() + "</style>"
else:
applet_style_html += ("<link rel='stylesheet' href='" + applet_style_html += ("<link rel='stylesheet' href='" +
url_for( url_for(
"static", "static",
@@ -16,10 +22,16 @@ def render_applet_head(applet_data: ContentApplet) -> str:
return applet_style_html return applet_style_html
def render_applet_scripts(applet_data: ContentApplet): def render_applet_scripts(applet_data: ContentApplet, is_standalone: bool = False):
applet_script_html = "" applet_script_html = ""
for applet_script in applet_data.resources.scripts: for applet_script in applet_data.resources.scripts:
if is_standalone:
with open(os.path.join("./static/resources/NibblePoker/applets/", applet_data.id, applet_script)) as applet_script_file:
applet_script_html += "<script" + (" type='module'>" if applet_script.endswith(".mjs") else ">")
applet_script_html += applet_script_file.read()
applet_script_html += "</script>"
else:
applet_script_html += ("<script src='" + applet_script_html += ("<script src='" +
url_for( url_for(
"static", "static",

View File

@@ -0,0 +1,6 @@
def get_standalone_common_headers() -> str:
_html = ""
with open("./static/resources/Standalone/nibblepoker.min.css", encoding='utf-8') as f:
_html += "<style>" + f.read() + "</style>"
return _html