Compare commits

..

7 Commits

Author SHA1 Message Date
3e29592b48 Updated build packages, Updated png analyser page
Update package-lock.json and png-analyser.jinja
2025-09-08 00:38:18 +02:00
30da615199 Updated VAT calculator, fixed minor TLD issues, Added strings, Optimized assets
Update sidebar.yml, commons.yml, and 10 more files...
2025-09-08 00:15:59 +02:00
615affcc2d Added VAT calculator tool and applet, Cleaned up launch logs and DOM trash
Update .gitignore, vat-calculator.yml, and 17 more files...
2025-09-07 20:52:02 +02:00
eb2ffa296b Added uppercase option to UUID generator
Update uuid-generator.yml, uuid-generator.yml, and 2 more files...
2025-08-25 21:23:24 +02:00
41286a8253 Updated png and bmp related-libs, Updated home page and sidebar
Update sidebar.yml, home.yml, and 7 more files...
2025-08-25 00:03:01 +02:00
a20b45d86e Update IbanGenerator and UUIDGenerator styles, Updated standalone style
Update extra.css, nibblepoker.min.css, and 2 more files...
2025-08-25 00:00:15 +02:00
690b3179ed Updated and fixed IbanGenerator tool
Update purebasic-structure-on-stack.md, iban-generator.yml, and 4 more files...
2025-08-24 18:55:54 +02:00
41 changed files with 1192 additions and 151 deletions

1
.gitignore vendored
View File

@@ -14,5 +14,6 @@ node_modules/
*.ai *.ai
# Temp # Temp
static/resources/DecimalJs*
static/resources/SortableJS static/resources/SortableJS
static/resources/Standalone static/resources/Standalone

View File

@@ -0,0 +1,7 @@
applets:
- id: "vat-calculator"
resources:
scripts:
- "applet://vat-calculator.mjs"
stylesheets:
- "applet://vat-calculator.css"

View File

@@ -48,7 +48,7 @@
abs_href: "/tools" abs_href: "/tools"
icon: fad fa-toolbox icon: fad fa-toolbox
active_id: tools active_id: tools
has_new_until_utc: 1760986472 has_new_until_utc: 1759856025
- title_key: text.downloads - title_key: text.downloads
raw_href: "https://files.nibblepoker.lu/" raw_href: "https://files.nibblepoker.lu/"
@@ -58,11 +58,11 @@
- -
- title_key: text.about #- title_key: text.about
abs_href: "/about" # abs_href: "/about"
icon: fad fa-user # icon: fad fa-user
active_id: about # active_id: about
has_new_until_utc: 0 # has_new_until_utc: 0
- title_key: text.contact - title_key: text.contact
abs_href: "/contact" abs_href: "/contact"

View File

@@ -14,3 +14,4 @@
- "/tools/iban-generator/" - "/tools/iban-generator/"
- "/tools/excel-password-remover/" - "/tools/excel-password-remover/"
- "/tools/uuid-generator/" - "/tools/uuid-generator/"
- "/tools/vat-calculator/"

View File

@@ -91,3 +91,48 @@ format.json: "JSON"
format.yaml: "YAML" format.yaml: "YAML"
action.generate: "Generate" action.generate: "Generate"
country.afghanistan: "Afghanistan"
country.albania: "Albania"
country.algeria: "Algeria"
country.andorra: "Andorra"
country.angola: "Angola"
country.anguilla: "Anguilla"
country.argentina: "Argentina"
country.australia: "Australia"
country.austria: "Austria"
country.azerbaijan: "Azerbaijan"
country.azores: "Azores"
country.bahamas: "Bahamas"
country.belgium: "Belgium"
country.bulgaria: "Bulgaria"
country.corsica: "Corsica"
country.croatia: "Croatia"
country.cyprus: "Cyprus"
country.czechia: "Czechia"
country.denmark: "Denmark"
country.estonia: "Estonia"
country.finland: "Finland"
country.france: "France"
country.france.corsica: "France - Corsica"
country.germany: "Germany"
country.greece: "Greece"
country.hungary: "Hungary"
country.ireland: "Ireland"
country.italy: "Italy"
country.latvia: "Latvia"
country.lithuania: "lithuania"
country.luxembourg: "Luxembourg"
country.madeira: "Madeira"
country.malta: "Malta"
country.monaco: "Monaco"
country.netherlands: "Netherlands"
country.poland: "Poland"
country.portugal: "Portugal"
country.portugal.azores: "Portugal - Azores"
country.portugal.madeira: "Portugal - Madeira"
country.romania: "Romania"
country.slovenia: "Slovenia"
country.slovakia: "Slovakia"
country.spain: "Spain"
country.sweden: "Sweden"

View File

@@ -9,12 +9,18 @@ meta.description.light: "Web application that allows you to generate IBANs in bu
country.label: "Country" country.label: "Country"
option.count: "IBAN Count" option.count: "IBAN Count"
option.human.readable: "Format for readability"
option.prefer.numbers: "Prefer numbers over letters"
option.for.each: "Generate <i>X</i> for each country" option.for.each: "Generate <i>X</i> for each country"
option.sepa.enable: "Enable SEPA countries" option.sepa.enable: "Enable SEPA countries"
option.non-sepa.enable: "Enable non-SEPA countries" option.non-sepa.enable: "Enable non-SEPA countries"
option.prefer.random: "Do not prefer letters nor numbers"
option.prefer.numbers: "Prefer numbers over letters"
option.prefer.letters: "Prefer letters over numbers"
option.human.format.none: "No formatting"
option.human.format.standard: "Use recommended spacing"
option.human.format.4by4: "Use 4 character-wide spacing"
license.1: "The code for this project is released in the public domain." license.1: "The code for this project is released in the public domain."
license.2: "The original source code can be found on <a href=\"https://github.com/aziascreations/Web-NibblePoker\">GitHub</a>." license.2: "The original source code can be found on <a href=\"https://github.com/aziascreations/Web-NibblePoker\">GitHub</a>."
license.3: "Data from Swift's license.3: "Data from Swift's

View File

@@ -10,6 +10,7 @@ type.uuid4: "UUID4 / GUID4"
option.count: "UUID Count" option.count: "UUID Count"
option.hyphen: "Add hyphens" option.hyphen: "Add hyphens"
option.guid_brackets: "Add GUID brackets" option.guid_brackets: "Add GUID brackets"
option.uppercase: "Generate in uppercase"
generate: "Generate" generate: "Generate"

View File

@@ -0,0 +1,52 @@
# EN - VAT Calculator
meta.title: "VAT Calculator"
meta.description: "Simple VAT calculator with a selection of common rates for 32 countries/regions."
preset.label: "Official rates"
option.detailed: "Show VAT rate types"
radio.rate: "VAT rate: "
radio.untaxed: "Excl. VAT: "
radio.taxed: "Incl. VAT: "
text.radio.explanation: "The selected radio input indicates the automatically calculated field."
rate.option.custom: "Custom rate"
rate.type.standard: "Standard"
rate.type.intermediate: "Intermediate"
rate.type.preferential: "Preferential"
rate.type.reduced: "Reduced"
rate.type.reduced.super: "Super reduced"
rate.type.special: "Special"
option.decimal-places: "Decimal places count"
option.trim-zeroes: "Trim trailing zeroes"
rounding.mode.label: "Rounding mode"
rounding.mode.group.regular: "Regular rounding"
rounding.mode.group.half: "Half rounding&emsp;(Towards nearest neighbour)"
rounding.mode.up: "Away from zero&emsp;(Up)"
rounding.mode.down: "Towards zero&emsp;(Down)"
rounding.mode.ceil: "Towards infinity&emsp;(Ceil)"
rounding.mode.floor: "Towards negative infinity&emsp;(Floor)"
rounding.mode.up.half: "Away from zero if equidistant&emsp;(Half up)"
rounding.mode.down.half: "Towards zero if equidistant&emsp;(Half down)"
rounding.mode.even.half: "Towards even neighbour if equidistant&emsp;(Half even)"
rounding.mode.ceil.half: "Towards infinity if equidistant&emsp;(Half ceil)"
rounding.mode.floor.half: "Towards negative infinity if equidistant&emsp;(Half floor)"
#rounding.mode.up.half: "Towards nearest neighbour, away from zero if equidistant&emsp;(Half up)"
#rounding.mode.down.half: "Towards nearest neighbour, towards zero if equidistant&emsp;(Half down)"
#rounding.mode.even.half: "Towards nearest neighbour, towards even neighbour if equidistant&emsp;(Half even)"
#rounding.mode.ceil.half: "Towards nearest neighbour, towards infinity if equidistant&emsp;(Half ceil)"
#rounding.mode.floor.half: "Towards nearest neighbour, towards negative infinity if equidistant&emsp;(Half floor)"
license.text.1: "This tool uses the <a href=\"https://github.com/MikeMcl/decimal.js-light\">decimal.js-light</a>
library, which is licensed under the <a href=\"https://github.com/MikeMcl/decimal.js-light/blob/master/LICENCE.md\">MIT license</a>."
license.text.2: "The rest of this tool's code is released in the <a href=\"https://github.com/aziascreations/Web-NibblePoker\">public domain</a>."

View File

@@ -91,3 +91,48 @@ format.json: "JSON"
format.yaml: "YAML" format.yaml: "YAML"
action.generate: "Générer" action.generate: "Générer"
country.afghanistan: "Afghanistan"
country.albania: "Albanie"
country.algeria: "Algérie"
country.andorra: "Andorre"
country.angola: "Angola"
country.anguilla: "Anguilla"
country.argentina: "Argentine"
country.australia: "Australie"
country.austria: "Autriche"
country.azerbaijan: "Azerbaïdjan"
country.azores: "Açores"
country.bahamas: "Bahamas"
country.belgium: "Belgique"
country.bulgaria: "Bulgarie"
country.corsica: "Corse"
country.croatia: "Croatie"
country.cyprus: "Chypre"
country.czechia: "Tchéquie"
country.denmark: "Danemark"
country.estonia: "Estonie"
country.finland: "Finlande"
country.france: "France"
country.france.corsica: "France - Corse"
country.germany: "Allemagne"
country.greece: "Grèce"
country.hungary: "Hongrie"
country.ireland: "Irlande"
country.italy: "Italie"
country.latvia: "Lettonie"
country.lithuania: "Lituanie"
country.luxembourg: "Luxembourg"
country.madeira: "Madère"
country.malta: "Malte"
country.monaco: "Monaco"
country.netherlands: "Pays-Bas"
country.poland: "Pologne"
country.portugal: "Portugal"
country.portugal.azores: "Portugal - Açores"
country.portugal.madeira: "Portugal - Madère"
country.romania: "Roumanie"
country.slovenia: "Slovénie"
country.slovakia: "Slovaquie"
country.spain: "Espagne"
country.sweden: "Suède"

View File

@@ -15,7 +15,7 @@ header.title: Page d'accueil
intro.title: Bienvenue sur %0 intro.title: Bienvenue sur %0
intro.text.1: Ce site web contient une collection de mes travaux personnels tels 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 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. est accessible gratuitement et sous des licences open source.
intro.text.2: Si vous souhaitez me contacter, vous pouvez le faire via la page 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. de contact lié dans la barre de navigation latérale.

View File

@@ -9,12 +9,18 @@ meta.description.light: "Application web qui vous permet de générer des IBANs
country.label: "Pays" country.label: "Pays"
option.count: "Nombre d'IBAN" option.count: "Nombre d'IBAN"
option.human.readable: "Formatter pour lecture"
option.prefer.numbers: "Favoriser les nombres aux lettres"
option.for.each: "Générer <i>X</i> pour chaque pays" option.for.each: "Générer <i>X</i> pour chaque pays"
option.sepa.enable: "Activer les pays SEPA" option.sepa.enable: "Activer les pays SEPA"
option.non-sepa.enable: "Activer les pays non-SEPA" option.non-sepa.enable: "Activer les pays non-SEPA"
option.prefer.random: "Pas de favorisation des lettres ou nombres"
option.prefer.numbers: "Favoriser les nombres aux lettres"
option.prefer.letters: "Favoriser les lettres aux nombres"
option.human.format.none: "Aucun formatage"
option.human.format.standard: "Utiliser le format standard des pays"
option.human.format.4by4: "Formater en segments de 4 caractères"
license.1: "Le code de ce projet est publié dans le domaine public." license.1: "Le code de ce projet est publié dans le domaine public."
license.2: "Le code source original peut être trouvé sur <a href=\"https://github.com/aziascreations/Web-NibblePoker\">GitHub</a>." license.2: "Le code source original peut être trouvé sur <a href=\"https://github.com/aziascreations/Web-NibblePoker\">GitHub</a>."
license.3: "Les données du license.3: "Les données du

View File

@@ -10,6 +10,7 @@ type.uuid4: "UUID4 / GUID4"
option.count: "Nombre d'UUID/GUID" option.count: "Nombre d'UUID/GUID"
option.hyphen: "Ajouter trait d'union" option.hyphen: "Ajouter trait d'union"
option.guid_brackets: "Ajouter accolades pour GUID" option.guid_brackets: "Ajouter accolades pour GUID"
option.uppercase: "Générer en majuscules"
generate: "Générer" generate: "Générer"

View File

@@ -0,0 +1,52 @@
# FR - VAT Calculator
meta.title: "Calculateur de TVA"
meta.description: "Simple calculateur de TVA avec une selection de taux communs pour 32 pays/régions."
preset.label: "Taux officiel"
option.detailed: "Afficher le type de TVA"
radio.rate: "Taux: "
radio.untaxed: "<abbr title=\"Hors Taxe sur la Valeur Ajoutée\">HTVA</abbr>: "
radio.taxed: "<abbr title=\"Toutes Taxes Comprises\">TTC</abbr>: "
text.radio.explanation: "Le cercle en vert indique la valeur automatiquement calculée."
rate.option.custom: "Taux personalisé"
rate.type.standard: "Standard"
rate.type.intermediate: "Intermédiaire"
rate.type.preferential: "Préférentiel"
rate.type.reduced: "Réduit"
rate.type.reduced.super: "Super réduit"
rate.type.special: "Spécial"
option.decimal-places: "Nombre de décimales"
option.trim-zeroes: "Supprimer les zéros de fin"
rounding.mode.label: "Type d'arrondi"
rounding.mode.group.regular: "Arrondis classiques"
rounding.mode.group.half: "Demi-arrondis&emsp;(Vers le plus proche)"
rounding.mode.up: "Loin de zéro&emsp;(Arrondi au supérieur)"
rounding.mode.down: "Vers zéro&emsp;(Arrondi à l'inférieur)"
rounding.mode.ceil: "Vers l'infini&emsp;(Par plafond)"
rounding.mode.floor: "Vers moins l'infini&emsp;(Par plancher)"
rounding.mode.up.half: "Loin de zéro si équidistant&emsp;(Demi supérieur)"
rounding.mode.down.half: "Vers zéro si équidistant&emsp;(Demi inférieur)"
rounding.mode.even.half: "Vers le pair si équidistant&emsp;(Demi pair)"
rounding.mode.ceil.half: "Vers l'infini&emsp;(Demi plafond)"
rounding.mode.floor.half: "Vers moins l'infini&emsp;(Demi plancher)"
#rounding.mode.up.half: "Vers le plus proche, loin de zéro si équidistant&emsp;(Demi supérieur)"
#rounding.mode.down.half: "Vers le plus proche, vers zéro si équidistant&emsp;(Demi inférieur)"
#rounding.mode.even.half: "Vers le plus proche, vers le pair si équidistant&emsp;(Demi pair)"
#rounding.mode.ceil.half: "Vers le plus proche, vers l'infini&emsp;(Demi plafond)"
#rounding.mode.floor.half: "Vers le plus proche, vers moins l'infini&emsp;(Demi plancher)"
license.text.1: "Cet outil utilise la bibliothèque <a href=\"https://github.com/MikeMcl/decimal.js-light\">decimal.js-light</a>,
qui est distribuée sous licence <a href=\"https://github.com/MikeMcl/decimal.js-light/blob/master/LICENCE.md\">MIT</a>."
license.text.2: "Le reste du code de cet outil est placé dans le <a href=\"https://github.com/aziascreations/Web-NibblePoker\">domaine public</a>."

View File

@@ -24,7 +24,7 @@ tools:
image_url: "/resources/NibblePoker/images/tools/iban-generator/main.png" image_url: "/resources/NibblePoker/images/tools/iban-generator/main.png"
image_alt_key: "" image_alt_key: ""
general: general:
icon: "fa-duotone fa-solid fa-credit-card-front" icon: "fa-duotone fa-credit-card-front"
title_key: "meta.title" title_key: "meta.title"
subtitle_key: "article.subtitle" subtitle_key: "article.subtitle"
tags: tags:

View File

@@ -24,7 +24,7 @@ tools:
image_url: "/resources/NibblePoker/images/tools/uuid-generator/main.png" image_url: "/resources/NibblePoker/images/tools/uuid-generator/main.png"
image_alt_key: "" image_alt_key: ""
general: general:
icon: "fab fa-python" icon: "fa-duotone fa-memo-pad"
title_key: "meta.title" title_key: "meta.title"
subtitle_key: "article.subtitle" subtitle_key: "article.subtitle"
tags: tags:

View File

@@ -0,0 +1,32 @@
tools:
- id: "vat-calculator"
applet_id: "vat-calculator"
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/tools/vat-calculator/main-quiet.png"
image_type: null
twitter:
title_key: "meta.title"
description_key: "meta.description"
index:
priority: 500
enable: true
title_key: "meta.title"
preamble_key: "meta.description"
image_url: "/resources/NibblePoker/images/tools/vat-calculator/main-quiet.png"
image_alt_key: ""
general:
icon: "fa-solid fa-memo-pad"
title_key: "meta.title"
subtitle_key: "article.subtitle"
tags:
- "calculator"
- "finance"

View File

@@ -93,6 +93,16 @@ call "%~dp0node_modules\.bin\rollup" png-analyser.mjs --file png-analyser.js
call "%~dp0node_modules\.bin\terser" png-analyser.js -c -m -o png-analyser.min.js call "%~dp0node_modules\.bin\terser" png-analyser.js -c -m -o png-analyser.min.js
popd popd
:js-vatcalculator-minify
echo Minifying VAT Calculator
pushd %CD%
cd %~dp0\..\static\resources\NibblePoker\applets\vat-calculator\
echo ^> static\resources\NibblePoker\applets\vat-calculator\vat-calculator.mjs
call "%~dp0node_modules\.bin\rollup" vat-calculator.mjs --file vat-calculator.js
call "%~dp0node_modules\.bin\terser" vat-calculator.js -c -m -o vat-calculator.min.js
popd
:js-nibblepoker-end :js-nibblepoker-end
:end :end

View File

@@ -5,9 +5,10 @@
"packages": { "packages": {
"": { "": {
"devDependencies": { "devDependencies": {
"browserify": "^17.0.1",
"html-minifier-terser": "^7.2.0", "html-minifier-terser": "^7.2.0",
"minify": "^10.2.0", "minify": "^10.2.0",
"rollup": "^3.27.2", "rollup": "^4.48.1",
"sass": "^1.63.6", "sass": "^1.63.6",
"terser": "^5.19.0", "terser": "^5.19.0",
"typescript": "^5.1.6" "typescript": "^5.1.6"

View File

@@ -1,10 +1,11 @@
{ {
"devDependencies": { "devDependencies": {
"minify": "^10.2.0", "minify": "^10.2.0",
"rollup": "^3.27.2", "rollup": "^4.48.1",
"sass": "^1.63.6", "sass": "^1.63.6",
"terser": "^5.19.0", "terser": "^5.19.0",
"typescript": "^5.1.6", "typescript": "^5.1.6",
"html-minifier-terser": "^7.2.0" "html-minifier-terser": "^7.2.0",
"browserify": "^17.0.1"
} }
} }

1
static/resources/Externals/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.svg

View File

@@ -30,10 +30,20 @@ import {initCore} from "../../js/nibblepoker-core.mjs";
/** @type {HTMLInputElement} */ /** @type {HTMLInputElement} */
const eOptionCount = document.querySelector("input#iban-generator-option-count"); const eOptionCount = document.querySelector("input#iban-generator-option-count");
/** @type {HTMLInputElement} */
const eOptionPrettyPrint = document.querySelector("input#iban-generator-option-pretty"); ///** @type {HTMLInputElement} */
//const eOptionPreferRandom = document.querySelector("input#iban-generator-option-prefer-random");
/** @type {HTMLInputElement} */ /** @type {HTMLInputElement} */
const eOptionPreferNumbers = document.querySelector("input#iban-generator-option-prefer-numbers"); const eOptionPreferNumbers = document.querySelector("input#iban-generator-option-prefer-numbers");
/** @type {HTMLInputElement} */
const eOptionPreferLetters = document.querySelector("input#iban-generator-option-prefer-letters");
/** @type {HTMLInputElement} */
const eOptionFormatNone = document.querySelector("input#iban-generator-option-format-none");
/** @type {HTMLInputElement} */
const eOptionFormatStandard = document.querySelector("input#iban-generator-option-format-standard");
/** @type {HTMLInputElement} */
const eOptionFormat4By4 = document.querySelector("input#iban-generator-option-format-4by4");
/** @type {HTMLElement} */ /** @type {HTMLElement} */
const eGenerateButton = document.querySelector("#iban-generator-generate"); const eGenerateButton = document.querySelector("#iban-generator-generate");
@@ -75,14 +85,14 @@ import {initCore} from "../../js/nibblepoker-core.mjs";
/** @returns {number} */ /** @returns {number} */
function getDesiredCount() { function getDesiredCount() {
return getInputCount(eOptionCount, 1, 1000); return getInputCount(eOptionCount, 1, 10000);
} }
function changeDesiredCount(difference = 0) { function changeDesiredCount(difference = 0) {
if(difference !== 0) { if(difference !== 0) {
eOptionCount.value = getDesiredCount(eOptionCount, 1, 1000) + difference; eOptionCount.value = getDesiredCount(eOptionCount, 1, 10000) + difference;
} }
eOptionCount.value = getDesiredCount(eOptionCount, 1, 1000); eOptionCount.value = getDesiredCount(eOptionCount, 1, 10000);
} }
window.onload = function () { window.onload = function () {
@@ -108,12 +118,28 @@ import {initCore} from "../../js/nibblepoker-core.mjs";
let desiredCount = getDesiredCount(); let desiredCount = getDesiredCount();
let preferNumbers = eOptionPreferNumbers.checked; let preferNumbers = eOptionPreferNumbers.checked;
let prettyIban = eOptionPrettyPrint.checked; let preferLetters = eOptionPreferLetters.checked;
let ibanFormat = (
eOptionFormatNone.checked ? 0 : (
eOptionFormatStandard.checked ? 1 : (
eOptionFormat4By4.checked ? 2 : 0
)
)
);
/** @type {IbanSpecification[]} */ /** @type {IbanSpecification[]} */
let targetSpecs; let targetSpecs;
if(eOptionForEach.checked) { if(eOptionForEach.checked) {
targetSpecs = Object.values(countriesSpecs); targetSpecs = Object.values(countriesSpecs);
// BUGFIX: Removing unwanted specs.
if(!eOptionEnableSepa.checked) {
targetSpecs = targetSpecs.filter(ibanSpec => !ibanSpec.isSepa);
}
if(!eOptionEnableNonSepa.checked) {
targetSpecs = targetSpecs.filter(ibanSpec => ibanSpec.isSepa);
}
} else { } else {
targetSpecs = [countriesSpecs[eOptionCountry.value]]; targetSpecs = [countriesSpecs[eOptionCountry.value]];
} }
@@ -123,15 +149,27 @@ import {initCore} from "../../js/nibblepoker-core.mjs";
return; return;
} }
for(let i = 0; i < desiredCount; i++) { for(let i = 0; i < desiredCount; i++) {
if(prettyIban) { if(ibanFormat === 1) {
// standard
lastIBANs.push( lastIBANs.push(
spec.getFormattedIban( spec.getFormattedIban(
new StandardIban(spec.countryCode, spec.generateRandomBban(preferNumbers), spec).toString() new StandardIban(spec.countryCode, spec.generateRandomBban(preferNumbers, preferLetters), spec)
.toString()
) )
); );
} else { } else if(ibanFormat === 2) {
// 4-by-4
lastIBANs.push( lastIBANs.push(
new StandardIban(spec.countryCode, spec.generateRandomBban(preferNumbers), spec).toString() new StandardIban(spec.countryCode, spec.generateRandomBban(preferNumbers, preferLetters), spec)
.toString()
.match(/.{1,4}/g)
.join(' ')
);
} else {
// none
lastIBANs.push(
new StandardIban(spec.countryCode, spec.generateRandomBban(preferNumbers, preferLetters), spec)
.toString()
); );
} }
} }

View File

@@ -1,6 +1,7 @@
import {initCore} from "../../js/nibblepoker-core.mjs" import {initCore} from "../../js/nibblepoker-core.mjs"
import {parsePngFile} from "../../libs/png-utils.mjs"; import {parsePngFile} from "../../libs/png-utils.mjs";
import {parseBmpFile} from "../../libs/bmp-utils.mjs";
{ {
initCore(); initCore();
@@ -16,12 +17,18 @@ import {parsePngFile} from "../../libs/png-utils.mjs";
console.log(files); console.log(files);
if(files[0].name.endsWith(".png")) {
parsePngFile(files[0]).then(pngFile => { parsePngFile(files[0]).then(pngFile => {
console.log(pngFile); console.log(pngFile);
console.log(pngFile.getImageHeaderChunk().getWidth()); console.log(pngFile.getImageHeaderChunk().getWidth());
console.log(pngFile.getImageHeaderChunk().getHeight()); console.log(pngFile.getImageHeaderChunk().getHeight());
}); });
} else if(files[0].name.endsWith(".bmp")) {
parseBmpFile(files[0]).then(bmpFile => {
console.log(bmpFile);
});
}
}); });
}; };
} }

View File

@@ -19,6 +19,8 @@ import {initCore} from "../../js/nibblepoker-core.mjs";
const eOptionHyphenInput = document.querySelector("input#uuid-generator-option-hyphens"); const eOptionHyphenInput = document.querySelector("input#uuid-generator-option-hyphens");
/** @type {HTMLInputElement} */ /** @type {HTMLInputElement} */
const eOptionGuidBracketsInput = document.querySelector("input#uuid-generator-option-guid-brackets"); const eOptionGuidBracketsInput = document.querySelector("input#uuid-generator-option-guid-brackets");
/** @type {HTMLInputElement} */
const eOptionUppercaseInput = document.querySelector("input#uuid-generator-option-uppercase");
/** @type {HTMLElement} */ /** @type {HTMLElement} */
const eGenerateButton = document.querySelector("#uuid-generator-generate"); const eGenerateButton = document.querySelector("#uuid-generator-generate");
@@ -57,10 +59,16 @@ import {initCore} from "../../js/nibblepoker-core.mjs";
let addGuidBrackets = eOptionGuidBracketsInput.checked; let addGuidBrackets = eOptionGuidBracketsInput.checked;
lastUUIDs = []; lastUUIDs = [];
if (eOptionUppercaseInput.checked) {
for (let i = 0; i < desiredCount; i++) {
lastUUIDs.push(uuidGenerator(addHyphens, addGuidBrackets).toUpperCase());
}
} else {
for (let i = 0; i < desiredCount; i++) { for (let i = 0; i < desiredCount; i++) {
lastUUIDs.push(uuidGenerator(addHyphens, addGuidBrackets)); lastUUIDs.push(uuidGenerator(addHyphens, addGuidBrackets));
ePreviewTextArea.value += uuidGenerator(addHyphens, addGuidBrackets) + "\n";
} }
}
ePreviewTextArea.value = lastUUIDs.join("\n"); ePreviewTextArea.value = lastUUIDs.join("\n");
}); });

View File

@@ -0,0 +1,248 @@
import {initCore} from "../../js/nibblepoker-core.mjs";
//import {Decimal} from "../../../DecimalJs/10.6.0/decimal.mjs";
import {Decimal} from "../../../DecimalJs-Light/2.5.1/decimal.mjs";
import {getInputCount, getInputNumber} from "../../libs/input-utils.mjs";
// Tool-centric stuff
{
initCore();
const classesReadonly = ["bkgd-gray"];
const calcRadioGroupName = "vat_calc_target";
/** @type {HTMLLabelElement} */
const ePresetShortLabel = document.querySelector("label[for=vat-calculator-preset-short]");
/** @type {HTMLSelectElement} */
const ePresetShortSelect = document.getElementById("vat-calculator-preset-short");
/** @type {HTMLLabelElement} */
const ePresetDetailedLabel = document.querySelector("label[for=vat-calculator-preset-detailed]");
/** @type {HTMLSelectElement} */
const ePresetDetailedSelect = document.getElementById("vat-calculator-preset-detailed");
/** @type {HTMLInputElement} */
const eCheckboxDetailedPreset = document.getElementById("vat-calculator-detailed-presets");
/** @type {HTMLSpanElement} */
const ePresetEchoedCountry = document.getElementById("vat-calculator-preset-country-echo");
/** @type {HTMLButtonElement} */
const eButtonDecimalPlacesMinus = document.getElementById("vat-calculator-decimal-places-minus");
/** @type {HTMLInputElement} */
const eInputDecimalPlaces = document.getElementById("vat-calculator-option-decimal-places");
/** @type {HTMLButtonElement} */
const eButtonDecimalPlacesPlus = document.getElementById("vat-calculator-decimal-places-plus");
/* #vat-calculator-detailed-trim-zeroes */
/** @type {HTMLInputElement} */
const eCalcRateRadio = document.getElementById("vat-calculator-radio-rate");
/** @type {HTMLInputElement} */
const eCalcRateInput = document.getElementById("vat-calculator-input-rate");
/** @type {HTMLInputElement} */
const eCalcUntaxedRadio = document.getElementById("vat-calculator-radio-untaxed");
/** @type {HTMLInputElement} */
const eCalcUntaxedInput = document.getElementById("vat-calculator-input-untaxed");
/** @type {HTMLInputElement} */
const eCalcTaxedRadio = document.getElementById("vat-calculator-radio-taxed");
/** @type {HTMLInputElement} */
const eCalcTaxedInput = document.getElementById("vat-calculator-input-taxed");
/** @type {HTMLSelectElement} */
const eRoundingModeSelect = document.getElementById("vat-calculator-rounding-mode");
/**
* Handles the switch between the short and detailed standard rates selects
*/
function handlePresetDetailLevelChange() {
ePresetShortLabel.hidden = eCheckboxDetailedPreset.checked;
ePresetShortSelect.hidden = eCheckboxDetailedPreset.checked;
ePresetDetailedLabel.hidden = !eCheckboxDetailedPreset.checked;
ePresetDetailedSelect.hidden = !eCheckboxDetailedPreset.checked;
}
/** @returns {number} */
function getDecimalPlaces() {
return getInputCount(eInputDecimalPlaces, 0, 99);
}
function changeDecimalPlacesDesiredCount(difference = 0) {
if (difference !== 0) {
eInputDecimalPlaces.value = getInputCount(eInputDecimalPlaces, 0, 99) + difference;
}
eInputDecimalPlaces.value = getInputCount(eInputDecimalPlaces, 0, 99);
}
/**
* Handles the locking and unlocking of the calculator input fields.
* @param eInput {HTMLInputElement}
* @param isLocked {boolean}
*/
function setCalcFieldLockStatus(eInput, isLocked) {
eInput.readOnly = isLocked;
classesReadonly.forEach((roClass) => {
eInput.classList.remove(roClass);
if(isLocked) {
eInput.classList.add(roClass);
}
});
}
function handleCalcValueChange() {
let vatRate = getInputNumber(eCalcRateInput);
let untaxedValue = getInputNumber(eCalcUntaxedInput);
let taxedValue = getInputNumber(eCalcTaxedInput);
if(eCalcRateRadio.checked) {
if(untaxedValue === null || taxedValue === null || isNaN(untaxedValue) || isNaN(taxedValue)) {
return;
}
untaxedValue = new Decimal(eCalcUntaxedInput.value);
taxedValue = new Decimal(eCalcTaxedInput.value);
eCalcRateInput.value = taxedValue
.minus(untaxedValue)
.div(untaxedValue)
.times(100)
.toDecimalPlaces(getDecimalPlaces());
} else if(eCalcUntaxedRadio.checked) {
if(vatRate === null || taxedValue === null || isNaN(vatRate) || isNaN(taxedValue)) {
return;
}
vatRate = new Decimal(eCalcRateInput.value).dividedBy(100).plus(1);
taxedValue = new Decimal(eCalcTaxedInput.value);
eCalcUntaxedInput.value = taxedValue
.dividedBy(vatRate)
.toDecimalPlaces(getDecimalPlaces());
} else if(eCalcTaxedRadio.checked) {
if(vatRate === null || untaxedValue === null || isNaN(vatRate) || isNaN(untaxedValue)) {
return;
}
vatRate = new Decimal(eCalcRateInput.value).dividedBy(100).plus(1);
untaxedValue = new Decimal(eCalcUntaxedInput.value);
eCalcTaxedInput.value = untaxedValue
.times(vatRate)
.toDecimalPlaces(getDecimalPlaces());
}
}
function handleDecimalConfigChange() {
Decimal.set({
rounding: getInputCount(eRoundingModeSelect, 0, 8),
precision: 99,
defaults: true,
});
}
function handlePresetChange() {
if(ePresetShortSelect.value.length > 0) {
let eSelectedOption = ePresetShortSelect.querySelector('option:checked');
if(eSelectedOption === null) {
return;
}
let eSelectedOptionGroup = eSelectedOption.closest('optgroup');
if(eSelectedOptionGroup === null) {
return;
}
ePresetEchoedCountry.innerHTML = eSelectedOptionGroup.label;
} else {
ePresetEchoedCountry.innerHTML = "";
}
}
window.onload = function () {
// Handling the detailed rate toggle
eCheckboxDetailedPreset.addEventListener("click", function () {
handlePresetDetailLevelChange();
});
// Handling the rate select input
ePresetShortSelect.addEventListener("change", function () {
ePresetDetailedSelect.selectedIndex = ePresetShortSelect.selectedIndex;
eCalcRateInput.value = ePresetShortSelect.value;
handlePresetChange();
handleCalcValueChange();
});
ePresetDetailedSelect.addEventListener("change", function () {
ePresetShortSelect.selectedIndex = ePresetDetailedSelect.selectedIndex;
eCalcRateInput.value = ePresetDetailedSelect.value;
handlePresetChange();
handleCalcValueChange();
});
// Handling calc radio input change
document.addEventListener("change", (e) => {
if (e.target.type === "radio" && e.target.name === calcRadioGroupName) {
setCalcFieldLockStatus(eCalcRateInput, e.target.value === "0");
setCalcFieldLockStatus(eCalcUntaxedInput, e.target.value === "1");
setCalcFieldLockStatus(eCalcTaxedInput, e.target.value === "2");
ePresetDetailedSelect.disabled = e.target === eCalcRateRadio;
ePresetShortSelect.disabled = e.target === eCalcRateRadio;
}
});
eCalcRateRadio.addEventListener("change", function () {
ePresetShortSelect.selectedIndex = 0;
ePresetDetailedSelect.selectedIndex = 0;
handlePresetChange();
});
// Handling decimal places options
eButtonDecimalPlacesMinus.addEventListener("click", function () {
changeDecimalPlacesDesiredCount(-1);
handleDecimalConfigChange();
handleCalcValueChange();
});
eButtonDecimalPlacesPlus.addEventListener("click", function () {
changeDecimalPlacesDesiredCount(1);
handleDecimalConfigChange();
handleCalcValueChange();
});
eInputDecimalPlaces.addEventListener("change", function() {
changeDecimalPlacesDesiredCount(0);
handleDecimalConfigChange();
handleCalcValueChange();
});
eInputDecimalPlaces.addEventListener("mousewheel", function(e) {
// Handling wheel scroll on count field.
if(e.wheelDelta < 0) {
changeDecimalPlacesDesiredCount(-1);
} else {
changeDecimalPlacesDesiredCount(1);
}
handleDecimalConfigChange();
handleCalcValueChange();
});
// Handling other DecimalJs config fields
eRoundingModeSelect.addEventListener("change", function() {
handleDecimalConfigChange();
handleCalcValueChange();
});
// Handling the calculator field changes
eCalcRateInput.addEventListener("change", function() {
ePresetShortSelect.selectedIndex = 0;
ePresetDetailedSelect.selectedIndex = 0;
handleCalcValueChange();
handlePresetChange();
});
eCalcUntaxedInput.addEventListener("change", function() {
handleCalcValueChange();
});
eCalcTaxedInput.addEventListener("change", function() {
handleCalcValueChange();
});
handlePresetDetailLevelChange();
handleDecimalConfigChange();
handlePresetChange();
}
}

View File

@@ -15,22 +15,6 @@ input[type=file].np-file-input-drop {
cursor: pointer; cursor: pointer;
} }
/* Nicer checkboxes, move to CSS 8 */
input[type=checkbox] {
text-align: center;
padding: 0;
&:before {
content: "✘";
}
&:checked {
&:before {
content: "✔";
}
}
}
/* Top margin trimmer for heading renderer */ /* Top margin trimmer for heading renderer */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,57 @@
import {loadFileAsUint8Array} from "./file-utils.mjs";
import {peekUInt32BE, peekUInt16BE} from "./data-utils.mjs";
/*export const test = {
WINDOWS: "BM",
OS2_STRUCT_BITMAP_ARRAY: "BA",
OS2_STRUCT_COLOR_ICON: "CI",
OS2_CONST_COLOR_POINTER: "CP",
OS2_STRUCT_ICON: "IC",
OS2_POINTER: "PT",
}*/
export class BmpHeader {
/** @type {Uint8Array} */
data;
/**
* @param byteArray {Uint8Array|null}
*/
constructor(byteArray) {
if(byteArray === null || byteArray === undefined) {
this.data = new Uint8Array(14);
} else {
this.data = byteArray;
}
}
getSignature() {
return peekUInt16BE(this.data, 0);
}
getFileSize() {
return peekUInt32BE(this.data, 2);
}
getReserved() {
return peekUInt32BE(this.data, 6);
}
getDataOffset() {
return peekUInt32BE(this.data, 10);
}
}
export class CrudeBmpFile {
constructor(file = null, fileData = null) {
this.originalFile = file;
}
}
export function parseBmpFile(file) {
return loadFileAsUint8Array(file).then(byteBuffer => {
return new CrudeBmpFile(file, byteBuffer);
});
}

View File

@@ -23,6 +23,34 @@ export function areUintArraysEqual(array1, array2) {
return true; return true;
} }
/**
* Peeks a UInt16 from the given data at the given offset in Big-Endian.
* @param data {Uint8Array} - Data to read from.
* @param offset {number} - Offset to read from in the given `data`.
* @return {number} The peeked number.
* @throws RangeError If the given offset is too close or over the end of the data.
*/
export function peekUInt16BE(data, offset = 0) {
if(offset + 2 > data.length) {
throw new RangeError(`Offset is too far into the given data ! (${offset} & ${data.length})`);
}
return new DataView(data.buffer, offset, 2).getUint16(0, false);
}
/**
* Peeks a UInt16 from the given data at the given offset in Little-Endian.
* @param data {Uint8Array} - Data to read from.
* @param offset {number} - Offset to read from in the given `data`.
* @return {number} The peeked number.
* @throws RangeError If the given offset is too close or over the end of the data.
*/
export function peekUInt16LE(data, offset = 0) {
if(offset + 2 > data.length) {
throw new RangeError(`Offset is too far into the given data ! (${offset} & ${data.length})`);
}
return new DataView(data.buffer, offset, 2).getUint16(0, true);
}
/** /**
* Peeks a UInt32 from the given data at the given offset in Big-Endian. * Peeks a UInt32 from the given data at the given offset in Big-Endian.
* @param data {Uint8Array} - Data to read from. * @param data {Uint8Array} - Data to read from.

View File

@@ -269,7 +269,7 @@ export class IbanSpecification {
return iban.match(/.{1,4}/g).join(' '); return iban.match(/.{1,4}/g).join(' ');
} }
generateRandomBban(preferNumbers = false) { generateRandomBban(preferNumbers = false, preferLetters = false) {
let returnedBban = ""; let returnedBban = "";
let patternParts = ("_" + this.bbanFormat + "0").split("!"); let patternParts = ("_" + this.bbanFormat + "0").split("!");
@@ -290,9 +290,13 @@ export class IbanSpecification {
case 'C': case 'C':
if(preferNumbers) { if(preferNumbers) {
elementChoices = charsN; elementChoices = charsN;
} else {
if(preferLetters) {
elementChoices = charsA;
} else { } else {
elementChoices = charsC; elementChoices = charsC;
} }
}
break; break;
case 'a': case 'a':
case 'A': case 'A':

View File

@@ -2,21 +2,7 @@
// Author: Herwin Bozet (@NibblePoker) // Author: Herwin Bozet (@NibblePoker)
// License: Public Domain (This code) // License: Public Domain (This code)
/** function postProcessNumber(desiredCount, min = null, max = null) {
* Retrieves the number from an `HTMLInputElement`
* @param eInput {HTMLInputElement} The `HTMLInputElement` from which the value will be retrieved.
* @param min {number|null} If given, sets a minimum the value can have when returned.
* @param max {number|null} If given, sets a maximum the value can have when returned.
* @returns {number} The value from the given `HTMLInputElement`, or `1` if no valid one was given.
*/
export function getInputCount(eInput, min = null, max = null) {
let desiredCount = null;
try {
desiredCount = parseInt(eInput.value);
} catch (e) {
console.error(e);
}
if (desiredCount === null) { if (desiredCount === null) {
desiredCount = 1; desiredCount = 1;
} }
@@ -34,3 +20,37 @@ export function getInputCount(eInput, min = null, max = null) {
return desiredCount; return desiredCount;
} }
/**
* Retrieves the integer number from an `HTMLInputElement`
* @param eInput {HTMLInputElement|HTMLSelectElement} The `HTMLInputElement` from which the value will be retrieved.
* @param min {number|null} If given, sets a minimum the value can have when returned.
* @param max {number|null} If given, sets a maximum the value can have when returned.
* @returns {number|NaN} The value from the given `HTMLInputElement`, or `1` if no valid one was given.
*/
export function getInputCount(eInput, min = null, max = null) {
let desiredCount = null;
try {
desiredCount = parseInt(eInput.value);
} catch (e) {
console.error(e);
}
return postProcessNumber(desiredCount, min, max);
}
/**
* Retrieves the float number from an `HTMLInputElement`
* @param eInput {HTMLInputElement|HTMLSelectElement} The `HTMLInputElement` from which the value will be retrieved.
* @param min {number|null} If given, sets a minimum the value can have when returned.
* @param max {number|null} If given, sets a maximum the value can have when returned.
* @returns {number|NaN} The value from the given `HTMLInputElement`, or `1` if no valid one was given.
*/
export function getInputNumber(eInput, min = null, max = null) {
let desiredCount = null;
try {
desiredCount = parseFloat(eInput.value);
} catch (e) {
console.error(e);
}
return postProcessNumber(desiredCount, min, max);
}

File diff suppressed because one or more lines are too long

View File

@@ -2,17 +2,12 @@
<!-- {{ render_h2(l10n("disclaimer.title", applet_data.id, user_lang)) }} --> <!-- {{ render_h2(l10n("disclaimer.title", applet_data.id, user_lang)) }} -->
<label for="iban-generator-option-enable-sepa" class="mr-xxs">{{ l10n("option.sepa.enable", "iban-generator", user_lang) }}:</label> <label for="iban-generator-option-enable-sepa" class="mr-xxs">{{ l10n("option.sepa.enable", "iban-generator", user_lang) }}:</label>
<input id="iban-generator-option-enable-sepa" class="r-m border" type="checkbox" checked> <input id="iban-generator-option-enable-sepa" class="r-m border cb-pretty" type="checkbox" checked>
<br> <br>
<label for="iban-generator-option-enable-non-sepa" class="mr-xxs">{{ l10n("option.non-sepa.enable", "iban-generator", user_lang) }}:</label> <label for="iban-generator-option-enable-non-sepa" class="mr-xxs">{{ l10n("option.non-sepa.enable", "iban-generator", user_lang) }}:</label>
<input id="iban-generator-option-enable-non-sepa" class="r-m border" type="checkbox" checked> <input id="iban-generator-option-enable-non-sepa" class="r-m border cb-pretty" type="checkbox" checked>
<br>
<label for="iban-generator-option-foreach" class="mr-xxs">{{ l10n("option.for.each", "iban-generator", user_lang) }}:</label>
<input id="iban-generator-option-foreach" class="r-m border" type="checkbox">
<hr class="subtle"> <hr class="subtle">
@@ -113,17 +108,45 @@
<br> <br>
<label for="iban-generator-option-count" class="mr-xs">{{ l10n("option.count", "iban-generator", user_lang) }}:</label> <label for="iban-generator-option-count" class="mr-xs">{{ l10n("option.count", "iban-generator", user_lang) }}:</label>
<input id="iban-generator-option-count" class="p-xxs border r-s" type="number" value="4" min="1" max="1000"> <input id="iban-generator-option-count" class="p-xxs border r-s" type="number" value="4" min="1" max="10000">
<br> <br>
<label for="iban-generator-option-pretty" class="mr-xxs">{{ l10n("option.human.readable", "iban-generator", user_lang) }}:</label> <label for="iban-generator-option-foreach" class="mr-xxs">{{ l10n("option.for.each", "iban-generator", user_lang) }}:</label>
<input id="iban-generator-option-pretty" class="r-m border" type="checkbox" checked> <input id="iban-generator-option-foreach" class="r-m border cb-pretty" type="checkbox">
<hr class="subtle">
<input type="radio" id="iban-generator-option-prefer-random" name="iban_charset" value="0" class="radio-solid border mr-xxs radio-unchecked-subtle" checked>
<label for="iban-generator-option-prefer-random">{{ l10n("option.prefer.random", "iban-generator", user_lang) }}</label>
<br> <br>
<label for="iban-generator-option-prefer-numbers" class="mr-xxs">{{ l10n("option.prefer.numbers", "iban-generator", user_lang) }}:</label> <input type="radio" id="iban-generator-option-prefer-numbers" name="iban_charset" value="0" class="radio-solid border mr-xxs radio-unchecked-subtle">
<input id="iban-generator-option-prefer-numbers" class="r-m border" type="checkbox"> <label for="iban-generator-option-prefer-numbers">{{ l10n("option.prefer.numbers", "iban-generator", user_lang) }}</label>
<br>
<input type="radio" id="iban-generator-option-prefer-letters" name="iban_charset" value="0" class="radio-solid border mr-xxs radio-unchecked-subtle">
<label for="iban-generator-option-prefer-letters">{{ l10n("option.prefer.letters", "iban-generator", user_lang) }}</label>
<hr class="subtle">
<input type="radio" id="iban-generator-option-format-none" name="iban_format" value="none" class="radio-solid border mr-xxs radio-unchecked-subtle" checked>
<label for="iban-generator-option-format-none">{{ l10n("option.human.format.none", "iban-generator", user_lang) }}</label>
<br>
<input type="radio" id="iban-generator-option-format-standard" name="iban_format" value="standard" class="radio-solid border mr-xxs radio-unchecked-subtle">
<label for="iban-generator-option-format-standard">{{ l10n("option.human.format.standard", "iban-generator", user_lang) }}</label>
<br>
<input type="radio" id="iban-generator-option-format-4by4" name="iban_format" value="4by4" class="radio-solid border mr-xxs radio-unchecked-subtle">
<label for="iban-generator-option-format-4by4">{{ l10n("option.human.format.4by4", "iban-generator", user_lang) }}</label>
<hr class="subtle"> <hr class="subtle">

View File

@@ -1,3 +1,38 @@
{{ render_file_input(tool_id + "-test-input", true, ".png", true, true) }} {{ render_file_input(tool_id + "-test-input", true, ".png, .bmp", true, true) }}
<div class="w-full ox-auto">
<table class="table-stylish table-p-s border r-m w-full table-no-wrap">
<thead>
<tr>
<th class="bkgd-grid30">Offset</th>
<th class="bkgd-grid30">Chunk Header</th>
<th class="bkgd-grid30">Chunk Data</th>
<th class="bkgd-grid30">Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td class="t-monospace">0x0000</td>
<td>2</td>
<td>2</td>
<td>
<button class="p-xs r-s border btn-primary">
<i class="fa-duotone fa-solid fa-binary"></i><span class="ml-xxs mobile-hide">Hex dump</span>
</button>
<button class="p-xs r-s border btn-primary">
<i class="fa-duotone fa-solid fa-download"></i><span class="ml-xxs mobile-hide">Export</span>
</button>
</td>
</tr>
<tr>
<td class="t-monospace">0x0010</td>
<td>4</td>
<td>4</td>
<td>4</td>
</tr>
</tbody>
</table>
</div>

View File

@@ -9,15 +9,20 @@
<label for="uuid-generator-option-count" class="mr-xs">{{ l10n("option.count", "uuid-generator", user_lang) }}:</label> <label for="uuid-generator-option-count" class="mr-xs">{{ l10n("option.count", "uuid-generator", user_lang) }}:</label>
<input id="uuid-generator-option-count" class="p-xxs border r-s" type="number" value="4" min="1" max="1000"> <input id="uuid-generator-option-count" class="p-xxs border r-s" type="number" value="4" min="1" max="1000">
<br> <hr class="subtle">
<label for="uuid-generator-option-hyphens" class="mr-xxs">{{ l10n("option.hyphen", "uuid-generator", user_lang) }}:</label> <label for="uuid-generator-option-hyphens" class="mr-xxs">{{ l10n("option.hyphen", "uuid-generator", user_lang) }}:</label>
<input id="uuid-generator-option-hyphens" class="r-m border" type="checkbox" checked> <input id="uuid-generator-option-hyphens" class="r-m border cb-pretty" type="checkbox" checked>
<br> <br>
<label for="uuid-generator-option-guid-brackets" class="mr-xxs">{{ l10n("option.guid_brackets", "uuid-generator", user_lang) }}:</label> <label for="uuid-generator-option-guid-brackets" class="mr-xxs">{{ l10n("option.guid_brackets", "uuid-generator", user_lang) }}:</label>
<input id="uuid-generator-option-guid-brackets" class="r-m border" type="checkbox"> <input id="uuid-generator-option-guid-brackets" class="r-m border cb-pretty" type="checkbox">
<br>
<label for="uuid-generator-option-uppercase" class="mr-xxs">{{ l10n("option.uppercase", "uuid-generator", user_lang) }}:</label>
<input id="uuid-generator-option-uppercase" class="r-m border cb-pretty" type="checkbox">
<hr class="subtle"> <hr class="subtle">

View File

@@ -0,0 +1,295 @@
{%
set all_vat_data = [
["afghanistan",
[[10, "standard"]], [
"https://ard.gov.af/file_download/432/FAQs+of+VAT+English.pdf",
]],
["austria",
[[10, "reduced"],[13, "reduced"],[20, "standard"]], [
"https://www.usp.gv.at/en/themen/steuern-finanzen/umsatzsteuer-ueberblick/steuersaetze-und-steuerbefreiungen-der-umsatzsteuer.html",
]],
["belgium",
[[6, "reduced"],[12, "intermediate"],[21, "standard"]], [
"https://finance.belgium.be/en/enterprises/vat/vat-obligation/rates-and-calculation/vat-rates",
]],
["bulgaria",
[[9, "reduced"],[20, "standard"]], [
"https://www.bulgaria-tax-law.bg/vat-rates-eu-member-states.html"]],
["croatia",
[[5, "reduced"],[13, "reduced"],[25, "standard"]], [
"https://porezna-uprava.gov.hr/en/value-added-tax-h-e-reinafter-vat-information-on-the-general-rules-rates-and-exemptions-registering-for-and-paying-vat-obtaining-a-refund/7313",
]],
["cyprus",
[[3, "reduced"],[5, "reduced"],[9, "reduced"],[19, "standard"]], [
"https://www.mof.gov.cy/mof/tax/taxdep.nsf/All/6F2D9F654287FF02C2258251002C8130",
]],
["czechia",
[[12, "reduced"],[21, "standard"]], [
"https://portal.gov.cz/en/informace/general-rules-and-vat-rates-INF-205",
]],
["denmark",
[[25, "standard"]], [
"https://skat.dk/erhverv/moms/fradrag-for-moms",
]],
["estonia",
[[9, "reduced"],[13, "reduced"],[24, "standard"]], [
"https://www.emta.ee/en/business-client/taxes-and-payment/value-added-tax",
"https://www.e-resident.gov.ee/blog/posts/a-guide-to-vat-for-e-residents/",
]],
["finland",
[[10, "reduced"],[14, "reduced"],[25.5, "standard"]], [
"https://www.vero.fi/en/businesses-and-corporations/taxes-and-charges/vat/rates-of-vat/",
]],
["france",
[[2.1, "reduced"],[5.5, "reduced"],[10, "intermediate"],[20, "standard"]], [
"https://www.economie.gouv.fr/cedef/les-fiches-pratiques/quels-sont-les-taux-de-tva-en-vigueur-en-france-et-dans-lunion",
]],
["france.corsica",
[[0.9, "special"],[2.1, "reduced"],[5.5, "reduced"],[10, "intermediate"],[13, "special"],[20, "standard"]], [
"https://www.economie.gouv.fr/particuliers/impots-et-fiscalite/gerer-mes-autres-impots-et-taxes/tva-quels-sont-les-taux-de-votre",
]],
["germany",
[[7, "reduced"],[19, "standard"]], [
"https://www.bundesfinanzministerium.de/Content/DE/Downloads/BMF_Schreiben/Steuerarten/Umsatzsteuer/Merkblaetter/2024-03-05-Umsatzsteuer-Merkblatt-Personenbefoerderung-Kraftomnibusse-englisch.pdf",
]],
["greece",
[[6, "reduced.super"],[13, "reduced"],[24, "standard"]], [
"https://www.gov.gr/en/sdg/taxes/vat/general/basic-vat-rates",
]],
["hungary",
[[5, "preferential"],[18, "preferential"],[27, "standard"]], [
"https://nav.gov.hu/pfile/file?path=/en/taxation/taxinfo/vat-liabilities-of-foreign-marketers-in-hungary",
]],
["ireland",
[[4.8, "reduced"],[9, "reduced"],[13.5, "reduced"],[23, "standard"]], [
"https://www.revenue.ie/en/vat/vat-rates/search-vat-rates/current-vat-rates.aspx",
]],
["italy",
[[4, "reduced"],[5, "reduced"],[10, "reduced"],[22, "standard"]], [
"https://www.agenziaentrate.gov.it/portale/web/english/nse/services/vat-mini-one-stop-shop/faq/vat-rates",
"https://www.agenziaentrate.gov.it/portale/web/english/general-vat-rules-and-rates"
]],
["latvia",
[[5, "reduced"],[12, "reduced"],[21, "standard"]], [
"https://www.fm.gov.lv/lv/tax-rates",
]],
["lithuania",
[[5, "reduced"],[9, "reduced"],[21, "standard"]], [
"https://finmin.lrv.lt/en/competence-areas/taxation/main-taxes/value-added-tax/",
]],
["luxembourg",
[[3, "reduced.super"],[8, "reduced"],[14, "intermediate"],[17, "standard"]], [
"https://logistics.public.lu/en/formalities-procedures/taxes/value-added-tax/national-operations.html",
]],
["malta",
[[5, "reduced"],[7, "reduced"],[12, "reduced"],[18, "standard"]], [
"https://mtca.gov.mt/business-tax/vat1/vat-compliance/vat-rates/vat-rates",
]],
["monaco",
[[2.1, "reduced"],[5.5, "reduced"],[10, "intermediate"],[20, "standard"]], [
"https://monentreprise.gouv.mc/en/themes/accounting-obligations-and-tax/tax/vat",
"https://www.economie.gouv.fr/particuliers/impots-et-fiscalite/gerer-mes-autres-impots-et-taxes/tva-quels-sont-les-taux-de-votre"
]],
["netherlands",
[[9, "reduced"],[21, "standard"]], [
"https://business.gov.nl/regulation/vat-rates-exemptions/",
]],
["poland",
[[5, "reduced"],[8, "reduced"],[23, "standard"]], [
"https://www.podatki.gov.pl/en/value-added-tax/general-vat-rules-and-rates/list-of-vat-rates/",
]],
["portugal",
[[6, "reduced"],[13, "intermediate"],[23, "standard"]], [
"https://www2.gov.pt/en/cidadaos-europeus-viajar-viver-e-fazer-negocios-em-portugal/impostos-para-atividades-economicas-em-portugal/imposto-sobre-valor-acrescentado-iva-em-portugal",
]],
["portugal.azores",
[[4, "reduced"],[9, "intermediate"],[16, "standard"]], [
"https://www2.gov.pt/en/cidadaos-europeus-viajar-viver-e-fazer-negocios-em-portugal/impostos-para-atividades-economicas-em-portugal/imposto-sobre-valor-acrescentado-iva-em-portugal",
]],
["portugal.madeira",
[[5, "reduced"],[12, "intermediate"],[22, "standard"]], [
"https://www2.gov.pt/en/cidadaos-europeus-viajar-viver-e-fazer-negocios-em-portugal/impostos-para-atividades-economicas-em-portugal/imposto-sobre-valor-acrescentado-iva-em-portugal",
]],
["romania",
[[5, "reduced"],[9, "reduced"],[19, "standard"]], [
"https://mfinante.gov.ro/referinte-tva",
"https://www.mfinante.gov.ro/static/10/Mfp/legislatie/Ghid_TVA_parteaI.htm"
]],
["slovakia",
[[5, "reduced"],[19, "reduced"],[23, "standard"]], [
"https://www.slovensko.sk/en/life-situation/life-situation/_value-added-tax/",
]],
["slovenia",
[[9.5, "reduced"],[22, "standard"]], [
"https://www.fu.gov.si/en/taxes_and_other_duties/areas_of_work/value_added_tax_vat",
]],
["spain",
[[4, "reduced"],[10, "reduced"],[21, "standard"]], [
"https://sede.agenciatributaria.gob.es/Sede/en_gb/iva/calculo-iva-repercutido-clientes/tipos-impositivos-iva.html"
"https://sede.agenciatributaria.gob.es/Sede/iva.html",
]],
["sweden",
[[6, "reduced"],[12, "reduced"],[25, "standard"]], [
"https://www.skatteverket.se/servicelankar/otherlanguages/englishengelska/businessesandemployers/startingandrunningaswedishbusiness/declaringtaxesbusinesses/vat/vatratesandvatexemption.4.676f4884175c97df419255d.html",
]],
]
%}
<label for="vat-calculator-preset-short" class="mr-xxs">
{{ l10n("preset.label", "vat-calculator", user_lang) }}:
</label>
<select name="vat-calculator-preset-short" id="vat-calculator-preset-short" class="p-xxs border r-s">
<option value="" selected>{{ l10n("rate.option.custom", "vat-calculator", user_lang) }}</option>
<hr>
{% for country_vat_data in all_vat_data %}
<optgroup label="{{ l10n("country." + country_vat_data[0], "commons", user_lang) }}">
{% for country_vat_rate in country_vat_data[1] %}
<option value="{{ country_vat_rate[0] }}">
{{ country_vat_rate[0] }} %
</option>
{% endfor %}
</optgroup>
{% endfor %}
</select>
<label for="vat-calculator-preset-detailed" class="mr-xxs" hidden>
{{ l10n("preset.label", "vat-calculator", user_lang) }}:
</label>
<select name="vat-calculator-preset-detailed" id="vat-calculator-preset-detailed" class="p-xxs border r-s" hidden>
<option value="" selected>{{ l10n("rate.option.custom", "vat-calculator", user_lang) }}</option>
<hr>
{% for country_vat_data in all_vat_data %}
<optgroup label="{{ l10n("country." + country_vat_data[0], "commons", user_lang) }}">
{% for country_vat_rate in country_vat_data[1] %}
<option value="{{ country_vat_rate[0] }}">
{{ country_vat_rate[0] }} %&emsp;({{ l10n("rate.type." + country_vat_rate[1], "vat-calculator", user_lang) }})
</option>
{% endfor %}
</optgroup>
{% endfor %}
</select>
<span id="vat-calculator-preset-country-echo" class="t-muted ml-xs t-italic mobile-hide"></span>
<br>
<label for="vat-calculator-detailed-presets" class="mr-xxs">{{ l10n("option.detailed", "vat-calculator", user_lang) }}:</label>
<input id="vat-calculator-detailed-presets" class="r-m border cb-pretty" type="checkbox">
<hr class="subtle">
<!-- TODO: Implement iframe-able template for multi-instance applets on the same page -->
<table class="">
<tr>
<td>
<input type="radio" id="vat-calculator-radio-rate" name="vat_calc_target" value="0"
class="radio-solid border mr-xxs radio-unchecked-subtle">
<label for="vat-calculator-radio-rate">
{{ l10n("radio.rate", "vat-calculator", user_lang) }}
</label>
</td>
<td>
<label for="vat-calculator-input-rate" class="mr-xs"></label>
<input id="vat-calculator-input-rate" class="p-xxs border r-s" type="number" min="0">
{% if not is_standalone %}<i class="fa-duotone fa-solid fa-percent ml-xxs t-muted"></i>{% else %}%{% endif %}
</td>
</tr>
<tr>
<td class="pt-xxs">
<input type="radio" id="vat-calculator-radio-untaxed" name="vat_calc_target" value="1"
class="radio-solid border mr-xxs radio-unchecked-subtle" checked>
<label for="vat-calculator-radio-untaxed">
{{ l10n("radio.untaxed", "vat-calculator", user_lang) }}
</label>
</td>
<td class="pt-xxs">
<label for="vat-calculator-input-untaxed" class="mr-xs"></label>
<input id="vat-calculator-input-untaxed" class="p-xxs border r-s bkgd-gray" type="number" min="0" readonly>
{% if not is_standalone %}<i class="fa-duotone fa-solid fa-money-bill ml-xxs t-muted"></i>{% endif %}
</td>
</tr>
<tr>
<td class="pt-xxs">
<input type="radio" id="vat-calculator-radio-taxed" name="vat_calc_target" value="2"
class="radio-solid border mr-xxs radio-unchecked-subtle">
<label for="vat-calculator-radio-taxed">
{{ l10n("radio.taxed", "vat-calculator", user_lang) }}
</label>
</td>
<td class="pt-xxs">
<label for="vat-calculator-input-taxed" class="mr-xs"></label>
<input id="vat-calculator-input-taxed" class="p-xxs border r-s" type="number" min="0">
{% if not is_standalone %}<i class="fa-duotone fa-solid fa-money-bill ml-xxs t-muted"></i>{% endif %}
</td>
</tr>
</table>
<p class="t-muted ml-xs mt-xs t-italic">{{ l10n("text.radio.explanation", "vat-calculator", user_lang) }}</p>
<hr class="subtle">
<label for="vat-calculator-rounding-mode" class="mr-xxs">
{{ l10n("rounding.mode.label", "vat-calculator", user_lang) }}:
</label>
<select name="vat-calculator-rounding-mode" id="vat-calculator-rounding-mode" class="p-xxs border r-s">
<optgroup label="{{ l10n("rounding.mode.group.regular", "vat-calculator", user_lang) }}">
<option value="0" selected>{{ l10n("rounding.mode.up", "vat-calculator", user_lang) }}</option>
<option value="1">{{ l10n("rounding.mode.down", "vat-calculator", user_lang) }}</option>
<option value="2">{{ l10n("rounding.mode.ceil", "vat-calculator", user_lang) }}</option>
<option value="3">{{ l10n("rounding.mode.floor", "vat-calculator", user_lang) }}</option>
</optgroup>
<optgroup label="{{ l10n("rounding.mode.group.half", "vat-calculator", user_lang) }}">
<option value="4">{{ l10n("rounding.mode.up.half", "vat-calculator", user_lang) }}</option>
<option value="5">{{ l10n("rounding.mode.down.half", "vat-calculator", user_lang) }}</option>
<option value="6">{{ l10n("rounding.mode.even.half", "vat-calculator", user_lang) }}</option>
<option value="7">{{ l10n("rounding.mode.ceil.half", "vat-calculator", user_lang) }}</option>
<option value="8">{{ l10n("rounding.mode.floor.half", "vat-calculator", user_lang) }}</option>
</optgroup>
</select>
<br>
<label for="vat-calculator-option-decimal-places" class="mr-xs">{{ l10n("option.decimal-places", "vat-calculator", user_lang) }}:</label>
<button id="vat-calculator-decimal-places-minus" class="p-xxs border br-0 rl-s {% if is_standalone %}px-xs{% endif %}">
{% if not is_standalone %}<i class="fa-duotone fa-solid fa-minus"></i>{% else %}-{% endif %}
</button>
<input id="vat-calculator-option-decimal-places" class="p-xxs border" type="number" value="2" min="0" max="99">
<button id="vat-calculator-decimal-places-plus" class="p-xxs border bl-0 rr-s {% if is_standalone %}px-xs{% endif %}">
{% if not is_standalone %}<i class="fa-duotone fa-solid fa-plus"></i>{% else %}+{% endif %}
</button>
<br hidden>
<label for="vat-calculator-detailed-trim-zeroes" class="mr-xxs" hidden>{{ l10n("option.trim-zeroes", "vat-calculator", user_lang) }}:</label>
<input id="vat-calculator-detailed-trim-zeroes" class="r-m border cb-pretty" type="checkbox" hidden>
<!--<hr class="subtle">
<details class="border bkgd-dark r-m mt-s">
<summary class="p-xs">Click to show/hide all classes</summary>
<div class="p-xs bt bkgd-grey">
<p>
<span class="code mr-xs">p-0</span>
</p>
</div>
</details>-->
{% if is_standalone %}
<hr class="subtle">
<p class="t-half-muted">
{{ l10n("license.text.1", "vat-calculator", user_lang) }}<br>
{{ l10n("license.text.2", "vat-calculator", user_lang) }}
</p>
{% endif %}

View File

@@ -12,18 +12,17 @@
<meta name="theme-color" content="#6F2F65"> <meta name="theme-color" content="#6F2F65">
<!--<link rel="dns-prefetch" href="https://cdn.nibblepoker.lu/"/>--> <!--<link rel="dns-prefetch" href="https://cdn.nibblepoker.lu/"/>-->
<link rel="preconnect" href="https://cdn.nibblepoker.lu/"/> <link rel="preconnect" href="https://cdn.nibblepoker.{{ domain_tld }}/"/>
<link rel="prefetch" href="https://cdn.nibblepoker.lu/FontAwesomePro/6.7.2/webfonts/fa-brands-400.woff2" as="font" /> <link rel="prefetch" href="https://cdn.nibblepoker.{{ domain_tld }}/FontAwesomePro/6.7.2/webfonts/fa-brands-400.woff2" as="font" />
<link rel="prefetch" href="https://cdn.nibblepoker.lu/FontAwesomePro/6.7.2/webfonts/fa-duotone-900.woff2" as="font" /> <link rel="prefetch" href="https://cdn.nibblepoker.{{ domain_tld }}/FontAwesomePro/6.7.2/webfonts/fa-duotone-900.woff2" as="font" />
<link rel="prefetch" href="https://cdn.nibblepoker.lu/FontAwesomePro/6.7.2/webfonts/fa-solid-900.woff2" as="font" /> <link rel="prefetch" href="https://cdn.nibblepoker.{{ domain_tld }}/FontAwesomePro/6.7.2/webfonts/fa-solid-900.woff2" as="font" />
<link rel="prefetch" href="https://cdn.nibblepoker.lu/NibblePoker/StandardCSS/3px-tile-0.1.png" as="image" />
<link rel="prefetch" href="https://cdn.nibblepoker.lu/NibblePoker/StandardCSS/3px-tile-0.4.png" as="image" />
{% block extra_preloads %}{% endblock %} {% block extra_preloads %}{% endblock %}
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/FontAwesomePro/6.7.2/css/all.min.css"> <link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/FontAwesomePro/6.7.2/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/StandardCSS/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">-->
<link rel="stylesheet" href="https://cdn.nibblepoker.{{ domain_tld }}/FamFamFam/FlagsExtended/famfamfam-flags.min.css">
<link rel="stylesheet" href="{{ url_for("static", filename="resources/NibblePoker/css/extra.css") }}"> <link rel="stylesheet" href="{{ url_for("static", filename="resources/NibblePoker/css/extra.css") }}">
@@ -53,16 +52,37 @@
</summary> </summary>
<div class="p-xs border bkgd-surround r-m t-w-500"> <div class="p-xs border bkgd-surround r-m t-w-500">
<a href="{{ l10n_url_switch(request_path, "en") }}" class="a-hidden"> <table class="w-full table-p-xxs">
<p class="mb-s px-xxs">{{ l10n("english", "langs", user_lang) }}</p> <tr>
<td>
<a href="{{ l10n_url_switch(request_path, "en") }}" class="w-full d-inline-block a-hidden">
{{ l10n("english", "langs", user_lang) }}
</a> </a>
<a href="{{ l10n_url_switch(request_path, "fr") }}" class="a-hidden"> </td>
<p class="my-s px-xxs">{{ l10n("french", "langs", user_lang) }}</p> <td class="t-center"><i class="famfamfam-flag-us"></i></td>
</tr>
<tr>
<td>
<a href="{{ l10n_url_switch(request_path, "fr") }}" class="w-full d-inline-block a-hidden">
{{ l10n("french", "langs", user_lang) }}
</a> </a>
</td>
<td class="t-center"><i class="famfamfam-flag-be"></i></td>
</tr>
<tr>
<td colspan="2">
<hr class="subtle m-0"> <hr class="subtle m-0">
<a href="{{ l10n_url_switch(request_path) }}" class="a-hidden"> </td>
<p class="mt-xs px-xxs">{{ l10n("automatic", "langs", user_lang) }}</p> </tr>
<tr>
<td>
<a href="{{ l10n_url_switch(request_path) }}" class="w-full d-inline-block a-hidden">
{{ l10n("automatic", "langs", user_lang) }}
</a> </a>
</td>
<td class="t-center"><i class="famfamfam-flag-unknown"></i></td>
</tr>
</table>
</div> </div>
</details> </details>
</header> </header>

View File

@@ -12,15 +12,20 @@
{% endblock %} {% endblock %}
{% block main_content %} {% block main_content %}
<section>
{{ render_h1(l10n("intro.title", "home", user_lang, ["NibblePoker." + domain_tld] )) }} {{ render_h1(l10n("intro.title", "home", user_lang, ["NibblePoker." + domain_tld] )) }}
<div class="content-spacer">
{{ render_paragraph(l10n("intro.text.1", "home", user_lang)) }} {{ render_paragraph(l10n("intro.text.1", "home", user_lang)) }}
{{ render_paragraph(l10n("intro.text.2", "home", user_lang)) }} {{ render_paragraph(l10n("intro.text.2", "home", user_lang)) }}
</div>
</section>
<section>
{{ render_h2(l10n("updates.title", "home", user_lang)) }} {{ render_h2(l10n("updates.title", "home", user_lang)) }}
<p><i class="fad fa-calendar-alt mr-xs mt-s"></i>{{ l10n("updates.5.date", "home", user_lang) }}</p> <div class="content-spacer">
<p><i class="fad fa-calendar-alt mr-xs"></i>{{ l10n("updates.5.date", "home", user_lang) }}</p>
{{ render_list_ul([ {{ render_list_ul([
l10n("updates.5.text.1", "home", user_lang), l10n("updates.5.text.1", "home", user_lang),
l10n("updates.5.text.2", "home", user_lang), l10n("updates.5.text.2", "home", user_lang),
@@ -57,6 +62,8 @@
l10n("updates.1.text.1", "home", user_lang), l10n("updates.1.text.1", "home", user_lang),
l10n("updates.text.privacy", "home", user_lang) l10n("updates.text.privacy", "home", user_lang)
]) }} ]) }}
</div>
</section>
{% endblock %} {% endblock %}

View File

@@ -43,7 +43,7 @@ def reload_strings(strings_root: str) -> None:
domain_key = str(Path(lang_domain).with_suffix('')) domain_key = str(Path(lang_domain).with_suffix(''))
if lang_domain.endswith(".json"): if lang_domain.endswith(".json"):
print(f"Loading JSON lang data from '{lang_domain_path}'...") #print(f"Loading JSON lang data from '{lang_domain_path}'...")
L10N.add_domain( L10N.add_domain(
lang_dir, lang_dir,
domain_key, domain_key,
@@ -51,7 +51,7 @@ def reload_strings(strings_root: str) -> None:
) )
if lang_domain.endswith(".yml"): if lang_domain.endswith(".yml"):
print(f"Loading YAML lang data from '{lang_domain_path}'...") #print(f"Loading YAML lang data from '{lang_domain_path}'...")
L10N.add_domain( L10N.add_domain(
lang_dir, lang_dir,
domain_key, domain_key,