From 0a02a1e56d74de1fd756990d25bfed6e1ccc9780 Mon Sep 17 00:00:00 2001 From: Herwin Bozet Date: Sat, 1 Mar 2025 07:40:47 +0100 Subject: [PATCH] Revamped site's common scripts, Many pages slightly broken Update commons.yml, excel-password-remover.yml, and 31 more files... --- data/strings/en/commons.yml | 5 +- data/strings/en/excel-password-remover.yml | 14 ++-- data/strings/fr/commons.yml | 5 +- data/strings/fr/excel-password-remover.yml | 8 ++ data/tools/.excel-password-remover.yml | 30 ------- data/tools/excel-password-remover.yml | 2 +- scripts/compile-js-site.cmd | 30 ++++--- .../excel-password-remover.mjs | 37 +++++++-- .../NibblePoker/js/nibblepoker-code.mjs | 68 ++++++++++++++++ .../js/nibblepoker-contributors.mjs | 64 +++++++++++++++ .../{nibblepoker.mjs => nibblepoker-core.mjs} | 79 +++++-------------- .../NibblePoker/js/nibblepoker-debug.mjs | 27 +++++++ .../NibblePoker/js/nibblepoker-default.mjs | 11 +++ .../NibblePoker/js/nibblepoker-leftovers.mjs | 48 +++++++++++ .../NibblePoker/js/nibblepoker-splide.mjs | 18 +++++ .../NibblePoker/js/nibblepoker-template.mjs | 48 +++++++++++ .../NibblePoker/js/nibblepoker-ui.mjs | 46 +++++++++++ .../applets/excel-password-remover.jinja | 29 +++++-- templates/base_www.jinja | 4 +- templates/elements/file-input.jinja | 6 +- templates/pages/about.jinja | 4 + templates/pages/contact.jinja | 4 + templates/pages/debug.jinja | 4 + templates/pages/error.jinja | 4 + templates/pages/links.jinja | 4 + templates/pages/privacy.jinja | 4 + templates/pages/project_index.jinja | 4 + templates/pages/root.jinja | 4 + templates/pages/tools_index.jinja | 4 + templates/pages/tools_page.jinja | 2 + website/content/dataclasses.py | 5 ++ website/renderers/applet.py | 5 +- 32 files changed, 499 insertions(+), 128 deletions(-) delete mode 100644 data/tools/.excel-password-remover.yml create mode 100644 static/resources/NibblePoker/js/nibblepoker-code.mjs create mode 100644 static/resources/NibblePoker/js/nibblepoker-contributors.mjs rename static/resources/NibblePoker/js/{nibblepoker.mjs => nibblepoker-core.mjs} (65%) create mode 100644 static/resources/NibblePoker/js/nibblepoker-debug.mjs create mode 100644 static/resources/NibblePoker/js/nibblepoker-default.mjs create mode 100644 static/resources/NibblePoker/js/nibblepoker-leftovers.mjs create mode 100644 static/resources/NibblePoker/js/nibblepoker-splide.mjs create mode 100644 static/resources/NibblePoker/js/nibblepoker-template.mjs create mode 100644 static/resources/NibblePoker/js/nibblepoker-ui.mjs diff --git a/data/strings/en/commons.yml b/data/strings/en/commons.yml index 6904fdf..4de43f1 100644 --- a/data/strings/en/commons.yml +++ b/data/strings/en/commons.yml @@ -64,10 +64,13 @@ none.fp: None eula.short: EULA eula.long: End-user license agreement (EULA) +disclaimer.responsability: Disclaimer +disclaimer.warning: Disclaimer dont.ask.again: "Don't ask again" -file.drop.upload: "Choose file(s)" +file.drop.upload.single: "Choose file" +file.drop.upload.multiple: "Choose file(s)" file.drop.clear: "Clear selection" file.drop.label.single: "Choose or drop a file:" file.drop.label.multiple: "Choose or drop files:" diff --git a/data/strings/en/excel-password-remover.yml b/data/strings/en/excel-password-remover.yml index 1543671..eb2ebc6 100644 --- a/data/strings/en/excel-password-remover.yml +++ b/data/strings/en/excel-password-remover.yml @@ -37,10 +37,10 @@ links.title: Links content.link.demo: Demo hosted on GitHub -eula.1: "This tool is for use only with files you have permission to unlock.
-If you don’t have authorization, contact the appropriate authority.
-You are responsible for how you use this tool." -eula.2: "No data is sent online, as everything happens in your browser with JavaScript.
-However, do not use this tool for sensitive files unless you have permission from the relevant authorities to avoid legal issues." -eula.3: "The tool doesn't reveal the original password, as it’s secure and not stored in plain text; it simply removes it." -eula.4: "By using this tool, you accept full responsibility, and it is provided “as is”, without any warranty." +eula.1: "This tool should only be used with files you have the express permission to unlock." +eula.2: "All password removal is done locally in your browser, and no data is sent online.
+The original password cannot be revealed as it’s secure by design and not stored in plain text; it simply gets removed." +eula.3: "By using this tool, you accept full responsibility, and that it is provided “as is” without any warranty." + +file.selection.title: "File Selection" +file.selection.1: "Drop your excel file(s) here or click on the buttons." diff --git a/data/strings/fr/commons.yml b/data/strings/fr/commons.yml index 3a5b085..1c4c8ff 100644 --- a/data/strings/fr/commons.yml +++ b/data/strings/fr/commons.yml @@ -64,10 +64,13 @@ none.fp: Aucunes eula.short: CLUF eula.long: Contrat de licence utilisateur final (CLUF) +disclaimer.responsability: Clause de non-responsabilité +disclaimer.warning: Avertissement dont.ask.again: "Ne plus demander" -file.drop.upload: "Ajouter fichier(s)" +file.drop.upload.single: "Ajouter fichier" +file.drop.upload.multiple: "Ajouter fichier(s)" file.drop.clear: "Vider la séléction" file.drop.label.single: "Choisissez ou déposez un fichier:" file.drop.label.multiple: "Choisissez ou déposez des fichiers:" diff --git a/data/strings/fr/excel-password-remover.yml b/data/strings/fr/excel-password-remover.yml index 1673b73..bd0db2f 100644 --- a/data/strings/fr/excel-password-remover.yml +++ b/data/strings/fr/excel-password-remover.yml @@ -31,3 +31,11 @@ usage.p1: >- demo.title: Vidéo de démonstration links.title: Liens content.link.demo: Démo hébergée sur GitHub + +eula.1 : "Cet outil ne doit être utilisé qu'avec des fichiers pour lesquels vous avez l'autorisation de les déverrouiller." +eula.2 : "Toute suppression de mot de passe se fait localement dans votre navigateur, et aucune donnée n'est envoyée via Internet.
+Le mot de passe original ne peut pas être révélé car il est sécurisé par Excel et n'est pas stocké en texte clair ; il est simplement supprimé." +eula.3 : "En utilisant cet outil, vous acceptez l'entière responsabilité de vos action, et le fait qu'il est fourni “tel quel” sans aucune garantie." + +file.selection.title : "Sélection de fichier(s)" +file.selection.1 : "Déposez vos fichiers Excel ici ou cliquez sur les boutons." diff --git a/data/tools/.excel-password-remover.yml b/data/tools/.excel-password-remover.yml deleted file mode 100644 index 9f4d2e5..0000000 --- a/data/tools/.excel-password-remover.yml +++ /dev/null @@ -1,30 +0,0 @@ -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/excel-password-remover/excel-password-remover.png" - image_type: null - twitter: - title_key: "meta.title" - description_key: "meta.description" - index: - priority: 100 - enable: true - title_key: "meta.title" - preamble_key: "meta.description" - image_url: "/resources/NibblePoker/images/tools/excel-password-remover/excel-password-remover.png" - image_alt_key: "" - general: - icon: "fab fa-python" - title_key: "meta.title" - subtitle_key: "article.subtitle" - tags: - - "undefined" -resources: - scripts: - - "epr_main.js" diff --git a/data/tools/excel-password-remover.yml b/data/tools/excel-password-remover.yml index 829619d..412e44f 100644 --- a/data/tools/excel-password-remover.yml +++ b/data/tools/excel-password-remover.yml @@ -24,7 +24,7 @@ tools: image_url: "/resources/NibblePoker/images/tools/excel-password-remover/excel-password-remover.png" image_alt_key: "" general: - icon: "fab fa-python" + icon: "fad fa-table-cells-column-unlock" title_key: "meta.title" subtitle_key: "article.subtitle" tags: diff --git a/scripts/compile-js-site.cmd b/scripts/compile-js-site.cmd index 89446a6..3634b9b 100644 --- a/scripts/compile-js-site.cmd +++ b/scripts/compile-js-site.cmd @@ -15,27 +15,37 @@ echo Minifying nibblepoker.js pushd %CD% cd %~dp0\..\static\resources\NibblePoker\js\ echo ^> static\resources\NibblePoker\js\nibblepoker.js -call "%~dp0node_modules\.bin\rollup" nibblepoker.mjs --file nibblepoker.js -call "%~dp0node_modules\.bin\terser" nibblepoker.js -c -m -o nibblepoker.min.js -echo ^> static\resources\NibblePoker\js\nibblepoker-code.js +call "%~dp0node_modules\.bin\rollup" nibblepoker-default.mjs --file nibblepoker-default.js +call "%~dp0node_modules\.bin\terser" nibblepoker-default.js -c -m -o nibblepoker-default.min.js + +echo ^> static\resources\NibblePoker\js\nibblepoker-code.mjs +call "%~dp0node_modules\.bin\rollup" nibblepoker-code.mjs --file nibblepoker-code.js call "%~dp0node_modules\.bin\terser" nibblepoker-code.js -c -m -o nibblepoker-code.min.js -echo ^> static\resources\NibblePoker\js\nibblepoker-contributors.js + +echo ^> static\resources\NibblePoker\js\nibblepoker-contributors.mjs +call "%~dp0node_modules\.bin\rollup" nibblepoker-contributors.mjs --file nibblepoker-contributors.js call "%~dp0node_modules\.bin\terser" nibblepoker-contributors.js -c -m -o nibblepoker-contributors.min.js + echo ^> static\resources\NibblePoker\js\nibblepoker-debug.js +call "%~dp0node_modules\.bin\rollup" nibblepoker-debug.mjs --file nibblepoker-debug.js call "%~dp0node_modules\.bin\terser" nibblepoker-debug.js -c -m -o nibblepoker-debug.min.js + echo ^> static\resources\NibblePoker\js\nibblepoker-splide.js +call "%~dp0node_modules\.bin\rollup" nibblepoker-splide.mjs --file nibblepoker-splide.js call "%~dp0node_modules\.bin\terser" nibblepoker-splide.js -c -m -o nibblepoker-splide.min.js popd -:js-svgtopng-minify -echo Minifying SVG-to-PNG + +:js-applet-excel-password-remover +echo Minifying Excel Password Remover pushd %CD% -cd %~dp0\..\static\resources\NibblePoker\tools\svg-to-png\ -echo ^> static\resources\NibblePoker\tools\svg-to-png\svg-to-png.mjs -call "%~dp0node_modules\.bin\rollup" svg-to-png.mjs --file svg-to-png.js -call "%~dp0node_modules\.bin\terser" svg-to-png.js -c -m -o svg-to-png.min.js +cd %~dp0\..\static\resources\NibblePoker\applets\excel-password-remover\ +echo ^> static\resources\NibblePoker\applets\excel-password-remover\excel-password-remover.mjs +call "%~dp0node_modules\.bin\rollup" excel-password-remover.mjs --file excel-password-remover.js +call "%~dp0node_modules\.bin\terser" excel-password-remover.js -c -m -o excel-password-remover.min.js popd + :js-uuidgenerator-minify echo Minifying UUID Generator pushd %CD% diff --git a/static/resources/NibblePoker/applets/excel-password-remover/excel-password-remover.mjs b/static/resources/NibblePoker/applets/excel-password-remover/excel-password-remover.mjs index 2bc5832..fe61752 100644 --- a/static/resources/NibblePoker/applets/excel-password-remover/excel-password-remover.mjs +++ b/static/resources/NibblePoker/applets/excel-password-remover/excel-password-remover.mjs @@ -1,30 +1,53 @@ +import {initCore} from "../../js/nibblepoker-core.mjs" + const excelFileRegex = /^.*\.xls[xm]$/gi; const excelWorksheetRegex = /^xl\/worksheets\/.*.xml$/gi; -var outputZip; -var outputZipFilename = "default-filename.error.zip"; -var filesTotalCount = 0; -var filesProcessedCount = 0; -var passwordsRemoved = 0; +/** + * Checks if the given filename appears to be for an Excel file. + * @param fileName {string} Filename to be checked + * @returns {boolean} `true` if it appears to be an Excel file, `false` otherwise. + */ +function isExcelExtension(fileName) { + return fileName.match(excelFileRegex) !== null; +} // Tool-centric stuff { + initCore(); + + var outputZip; + var outputZipFilename = "default-filename.error.zip"; + var filesTotalCount = 0; + var filesProcessedCount = 0; + var passwordsRemoved = 0; + /** @type {string} */ const appletId = "excel-password-remover"; - ///** @type {HTMLElement} */ - //const eEulaContainer = document.querySelector(`#${appletId}-eula`); + /** @type {HTMLElement} */ + const eEulaContainer = document.querySelector(`#${appletId}-eula`); ///** @type {HTMLInputElement} */ //const eEulaDontAskAgainOption = document.querySelector(`input#${appletId}-eula-remember`); ///** @type {HTMLButtonElement} */ //const eEulaAcceptButton = document.querySelector(`button#${appletId}-eula-accept`); + /** @type {HTMLInputElement} */ + const eFileInput = document.querySelector(`input[type=file]#${appletId}-input-file`); + /*function acceptTerms() { document.getElementById("warning").hidden = true; document.getElementById("file-select").hidden = false; }*/ window.onload = function () { + + eFileInput.addEventListener('change', function(e) { + let fileCount = e.target.files.length; + + console.log(fileCount); + }); + /*console.log(eEulaContainer); console.log(eEulaDontAskAgainOption); console.log(eEulaAcceptButton); diff --git a/static/resources/NibblePoker/js/nibblepoker-code.mjs b/static/resources/NibblePoker/js/nibblepoker-code.mjs new file mode 100644 index 0000000..2b2bbfe --- /dev/null +++ b/static/resources/NibblePoker/js/nibblepoker-code.mjs @@ -0,0 +1,68 @@ +document.addEventListener("DOMContentLoaded", () => { + // Highlights the code blocks when included on a page. + // This command is separated in its own file since highlight.js isn't on every page and because I can't use JS + // in a script element without using an external .js file. + Array.from(document.getElementsByClassName("code")).forEach(eCodeContainer => { + let language = null; + + eCodeContainer.classList.forEach(cCodeContainer => { + if(cCodeContainer.startsWith("language-")) { + language = cCodeContainer; + } + }); + + if(language !== null) { + Array.from(eCodeContainer.children).forEach(eCodeLine => { + if(eCodeLine.classList.contains("code-line")) { + eCodeLine.classList.add(language); + hljs.highlightElement(eCodeLine); + } + }); + } + }); + + // Adding the action to copy the code to elements with the "js-code-copy" class. + // The search works by searching the closest parent with the "code" class or that is a "code" element, and then + // reading each of its children with the "code-line" class. + Array.from(document.getElementsByClassName("js-code-copy")).forEach(eCodeCopyButton => { + let eParentCodeBlock = eCodeCopyButton; + + while(eParentCodeBlock != null &&!eParentCodeBlock.classList.contains("code") && + eParentCodeBlock.nodeName.toLowerCase() !== "code") { + eParentCodeBlock = eParentCodeBlock.parentElement; + } + + if(eParentCodeBlock != null) { + let code = ""; + + Array.from(eParentCodeBlock.children).forEach(eCodeLine => { + if(eCodeLine.classList.contains("code-line")) { + code += eCodeLine.textContent + "\n" + } + }); + + eCodeCopyButton.onclick = function() { + const eCodeCopySpans = eCodeCopyButton.querySelectorAll("span"); + + navigator.clipboard.writeText(code); + + if(eCodeCopySpans.length < 2) { + return; + } + + const eSpanCopy = eCodeCopySpans[0]; + const eSpanCopied = eCodeCopySpans[1]; + + eSpanCopy.hidden = true; + eSpanCopied.hidden = false; + + fadeOut(eSpanCopied, 600).then(r => { + eSpanCopy.hidden = false; + eSpanCopied.hidden = true; + }); + }; + + eCodeCopyButton.hidden = false; + } + }); +}); \ No newline at end of file diff --git a/static/resources/NibblePoker/js/nibblepoker-contributors.mjs b/static/resources/NibblePoker/js/nibblepoker-contributors.mjs new file mode 100644 index 0000000..baa5df0 --- /dev/null +++ b/static/resources/NibblePoker/js/nibblepoker-contributors.mjs @@ -0,0 +1,64 @@ +{ + const rootSoundDirectory = "/resources/NibblePoker/sounds/" + + class CatData { + constructor(meows, purrs) { + this.meowSounds = meows; + this.purrSounds = purrs; + } + } + + const kittyData = { + "kitty-kiki": new CatData( + ["meow-test-01.ogg"], + ["kiki-ronron-01.ogg"] + ), + "kitty-maki": new CatData( + ["meow-test-02.ogg"], + [] + ), + } + + document.addEventListener("DOMContentLoaded", () => { + for(const [eId, catData] of Object.entries(kittyData)) { + const eHovered = document.getElementById(eId); + + const audioPurr = (catData.purrSounds.length > 0) ? new Audio() : null; + + if(eHovered !== null) { + eHovered.addEventListener('mouseover', function() { + // Playing the meow sound + if(catData.meowSounds.length > 0) { + const meowIndex = Math.floor(Math.random() * catData.meowSounds.length); + const audioMeow = new Audio(rootSoundDirectory + catData.meowSounds[meowIndex]); + audioMeow.volume = 0.1; + try { + audioMeow.play(); + } catch(DOMException) { + } + } + + // Playing the purr sound + if(audioPurr !== null) { + const purrIndex = Math.floor(Math.random() * catData.purrSounds.length); + audioPurr.src = rootSoundDirectory + catData.purrSounds[purrIndex]; + audioPurr.volume = 0.075; + try { + audioPurr.load(); + audioPurr.loop = true; + audioPurr.play(); + } catch(DOMException) { + } + } + }); + + eHovered.addEventListener('mouseout', function() { + // Stopping the purring sound + if(audioPurr !== null) { + audioPurr.pause(); + } + }); + } + } + }); +} diff --git a/static/resources/NibblePoker/js/nibblepoker.mjs b/static/resources/NibblePoker/js/nibblepoker-core.mjs similarity index 65% rename from static/resources/NibblePoker/js/nibblepoker.mjs rename to static/resources/NibblePoker/js/nibblepoker-core.mjs index 13ebe2b..55d784b 100644 --- a/static/resources/NibblePoker/js/nibblepoker.mjs +++ b/static/resources/NibblePoker/js/nibblepoker-core.mjs @@ -1,67 +1,30 @@ -// NibblePoker - Mandatory Scripts +// NibblePoker - Core Scripts // Author: Herwin Bozet (@NibblePoker) // License: Public Domain (This code) -// Remark: This modules contains all the scripts that are globally required on this website +// Remark: +// * This module contains all the scripts that are globally required on this website -import {fadeIn} from "./nibblepoker-ui" +export let isSidebarVisible = true; -/*class CpuArchitecture { - constructor(id, name) { - this.id = id; - this.name = name; - } -} - -const CpuArchitectures = { - Unknown: new CpuArchitecture(0, "?"), - x86: new CpuArchitecture(1, "x86"), - x64: new CpuArchitecture(2, "x64"), - ArmGeneric: new CpuArchitecture(3, "ARM"), - Arm64: new CpuArchitecture(4, "ARM64"), - RiscV: new CpuArchitecture(5, "RISC-V"), -} - -function getCpuArchitecture(userAgent = navigator.userAgent) { - if(userAgent.includes("x64")) { - return CpuArchitectures.x64; - } else if(userAgent.includes("x86")) { - return CpuArchitectures.x86; - } else if(userAgent.includes("ARM")) { - return CpuArchitectures.ArmGeneric; - } else if(userAgent.includes("ARM64")) { - return CpuArchitectures.Arm64; - } else if(userAgent.includes("RISC-V")) { - return CpuArchitectures.RiscV; - } - return CpuArchitectures.Unknown; -}*/ - -let isSidebarVisible = true; -let eContentModal = document.getElementById("modal-content"); -let eContentModalInner = document.getElementById("modal-content-inner"); - -function showContentModal(eContent) { - eContentModalInner.appendChild(eContent); - fadeIn(eContentModal, 175).then(r => { - // We don't care about what happens afterward... - }); -} - -document.addEventListener("DOMContentLoaded", () => { - const eSidebar = document.getElementById("sidebar"); +export function initCore() { + const eSidebarToggleButton = document.getElementById("sidebar-toggle-footer"); + const eSidebar = document.getElementById("sidebar"); const eMain = document.getElementById("main"); // TODO: Emit an event to help Splide re-align after the sidebar has changed state. - document.getElementById("sidebar-toggle-footer").onclick = function() { - if(isSidebarVisible) { - eSidebar.classList.add("retracted"); - eMain.classList.add("expanded"); - } else { - eSidebar.classList.remove("retracted"); - eMain.classList.remove("expanded"); - } - isSidebarVisible = !isSidebarVisible; - }; + + if(eSidebarToggleButton !== null && eSidebar !== null && eMain !== null) { + eSidebarToggleButton.onclick = function() { + if(isSidebarVisible) { + eSidebar.classList.add("retracted"); + eMain.classList.add("expanded"); + } else { + eSidebar.classList.remove("retracted"); + eMain.classList.remove("expanded"); + } + isSidebarVisible = !isSidebarVisible; + }; + } //showContentModal(eContentModal); @@ -165,4 +128,4 @@ document.addEventListener("DOMContentLoaded", () => { } }); }); -}); +} diff --git a/static/resources/NibblePoker/js/nibblepoker-debug.mjs b/static/resources/NibblePoker/js/nibblepoker-debug.mjs new file mode 100644 index 0000000..bca5d9e --- /dev/null +++ b/static/resources/NibblePoker/js/nibblepoker-debug.mjs @@ -0,0 +1,27 @@ +const idButtonBorder = "test-toggle-borders"; + +const classBorderActive = "debug"; +const classBorderInactive = "_debug"; + +function swapDebugClasses() { + const activeElements = document.querySelectorAll('.' + classBorderActive); + const inactiveElements = document.querySelectorAll('.' + classBorderInactive); + + activeElements.forEach(element => { + element.classList.remove(classBorderActive); + element.classList.add(classBorderInactive); + }); + + inactiveElements.forEach(element => { + element.classList.remove(classBorderInactive); + element.classList.add(classBorderActive); + }); +} + +document.addEventListener("DOMContentLoaded", function() { + // Adding the action to the border button + const eBorderButton = document.getElementById(idButtonBorder); + if(eBorderButton !== null) { + eBorderButton.addEventListener("click", swapDebugClasses); + } +}); diff --git a/static/resources/NibblePoker/js/nibblepoker-default.mjs b/static/resources/NibblePoker/js/nibblepoker-default.mjs new file mode 100644 index 0000000..ed4be10 --- /dev/null +++ b/static/resources/NibblePoker/js/nibblepoker-default.mjs @@ -0,0 +1,11 @@ +// NibblePoker - Default Main Script +// Author: Herwin Bozet (@NibblePoker) +// License: Public Domain (This code) +// Remark: +// * This module is used on all static pages that aren't dynamically generated + +import {initCore} from "./nibblepoker-core.mjs" + +document.addEventListener("DOMContentLoaded", () => { + initCore(); +}); diff --git a/static/resources/NibblePoker/js/nibblepoker-leftovers.mjs b/static/resources/NibblePoker/js/nibblepoker-leftovers.mjs new file mode 100644 index 0000000..226caf4 --- /dev/null +++ b/static/resources/NibblePoker/js/nibblepoker-leftovers.mjs @@ -0,0 +1,48 @@ +// NibblePoker - Leftovers +// Author: Herwin Bozet (@NibblePoker) +// License: Public Domain (This code) + +import {fadeIn} from "./nibblepoker-ui" + +//export cloneTemplate; + +/*class CpuArchitecture { + constructor(id, name) { + this.id = id; + this.name = name; + } +} + +const CpuArchitectures = { + Unknown: new CpuArchitecture(0, "?"), + x86: new CpuArchitecture(1, "x86"), + x64: new CpuArchitecture(2, "x64"), + ArmGeneric: new CpuArchitecture(3, "ARM"), + Arm64: new CpuArchitecture(4, "ARM64"), + RiscV: new CpuArchitecture(5, "RISC-V"), +} + +function getCpuArchitecture(userAgent = navigator.userAgent) { + if(userAgent.includes("x64")) { + return CpuArchitectures.x64; + } else if(userAgent.includes("x86")) { + return CpuArchitectures.x86; + } else if(userAgent.includes("ARM")) { + return CpuArchitectures.ArmGeneric; + } else if(userAgent.includes("ARM64")) { + return CpuArchitectures.Arm64; + } else if(userAgent.includes("RISC-V")) { + return CpuArchitectures.RiscV; + } + return CpuArchitectures.Unknown; +}*/ + +let eContentModal = document.getElementById("modal-content"); +let eContentModalInner = document.getElementById("modal-content-inner"); + +function showContentModal(eContent) { + eContentModalInner.appendChild(eContent); + fadeIn(eContentModal, 175).then(r => { + // We don't care about what happens afterward... + }); +} diff --git a/static/resources/NibblePoker/js/nibblepoker-splide.mjs b/static/resources/NibblePoker/js/nibblepoker-splide.mjs new file mode 100644 index 0000000..d0710a7 --- /dev/null +++ b/static/resources/NibblePoker/js/nibblepoker-splide.mjs @@ -0,0 +1,18 @@ +// Creating the galleries with SplideJs + +window.addEventListener('load', function() { + try { + new Splide( '.splide', { + perPage: 2, + cover: true, + heightRatio: 0.4, + breakpoints: { + 768: { + perPage: 1, + }, + }, + }).mount(); + } catch(err) { + console.log("Unable to setup Splide !"); + } +}); diff --git a/static/resources/NibblePoker/js/nibblepoker-template.mjs b/static/resources/NibblePoker/js/nibblepoker-template.mjs new file mode 100644 index 0000000..8b72547 --- /dev/null +++ b/static/resources/NibblePoker/js/nibblepoker-template.mjs @@ -0,0 +1,48 @@ +// NibblePoker - Template Utilities +// Author: Herwin Bozet (@NibblePoker) +// License: Public Domain (This code) + +/** + * @param eTemplate {HTMLTemplateElement | string} The template to be cloned, or its ID. + * @param subParts {Object.} + * @param ignoreMissingParts {bool} + * @returns {Promise} + */ +export function cloneTemplate(eTemplate, + subParts, + ignoreMissingParts) { + if (typeof eTemplate === 'string' || eTemplate instanceof String) { + eTemplate = document.getElementById(eTemplate); + } + return new Promise((resolve, reject) => { + if(eTemplate == null) { + reject("The given template couldn't be found !"); + } else { + /** @type {DocumentFragment} */ + let eClone = document.importNode(eTemplate.content, true); + + for (const key in subParts) { + if (subParts.hasOwnProperty(key)) { + const value = subParts[key]; + + let ePart = eClone.getElementById(key); + + if(ePart == null) { + if(ignoreMissingParts) { + continue; + } + reject(`Unable to find sub-element with id '${key}' !`); + } + + if(value instanceof Node) { + ePart.appendChild(value); + } else { + ePart.innerHTML += value; + } + } + } + + resolve(eClone); + } + }); +} diff --git a/static/resources/NibblePoker/js/nibblepoker-ui.mjs b/static/resources/NibblePoker/js/nibblepoker-ui.mjs new file mode 100644 index 0000000..ced77d1 --- /dev/null +++ b/static/resources/NibblePoker/js/nibblepoker-ui.mjs @@ -0,0 +1,46 @@ +// NibblePoker - UI Scripts +// Author: Herwin Bozet (@NibblePoker) +// License: Public Domain (This code) + +export const animationStepCount = 10; + +export function getBezierBlend(progress) { + return (3 * progress ** 2) - (2 * progress ** 3); +} + +export function fadeOut(element, time = 200) { + element.style.opacity = "1.0"; + element.hidden = false; + return new Promise((resolve) => { + const delay = time / animationStepCount; + let i = 0; + const intervalId = setInterval(() => { + element.style.opacity = String(1 - getBezierBlend(i / animationStepCount)); + i++; + if(i === animationStepCount) { + element.style.opacity = "0.0"; + element.hidden = true; + clearInterval(intervalId); + resolve(); + } + }, delay); + }); +} + +export function fadeIn(element, time = 200) { + element.style.opacity = "0.0"; + element.hidden = false; + return new Promise((resolve) => { + const delay = time / animationStepCount; + let i = 0; + const intervalId = setInterval(() => { + element.style.opacity = String(getBezierBlend(i / animationStepCount)); + i++; + if(i === animationStepCount) { + element.style.opacity = "1.0"; + clearInterval(intervalId); + resolve(); + } + }, delay); + }); +} diff --git a/templates/applets/excel-password-remover.jinja b/templates/applets/excel-password-remover.jinja index 5b7beaf..cb9daae 100644 --- a/templates/applets/excel-password-remover.jinja +++ b/templates/applets/excel-password-remover.jinja @@ -1,22 +1,35 @@
- {{ render_h2(l10n("eula.long", "commons", user_lang)) }} + {{ render_h2(l10n("disclaimer.warning", "commons", user_lang)) }} {{ render_paragraph(l10n("eula.1", applet_data.id, user_lang)) }} {{ render_paragraph(l10n("eula.2", applet_data.id, user_lang)) }} {{ render_paragraph(l10n("eula.3", applet_data.id, user_lang)) }} - {{ render_paragraph(l10n("eula.4", applet_data.id, user_lang)) }}
{{ render_h2(l10n("file.selection.title", applet_data.id, user_lang)) }} -

123

+ + {{ render_paragraph(l10n("file.selection.1", applet_data.id, user_lang)) }} + + {{ render_file_input(applet_data.id + "-input-file", true, ".xlsx, .xlsm", true, true) }} + +
+
+ ⚠️ These styles require a special workaround to work properly ⚠️ +
+
{{ render_h2(l10n("details.title", applet_data.id, user_lang)) }} -

123

+ +
+ {{ render_paragraph(l10n("details.empty.1", applet_data.id, user_lang)) }} +
-
- {{ render_h2(l10n("licenses.title", applet_data.id, user_lang)) }} -

123

-
+{% if is_standalone %} +
+ {{ render_h2(l10n("licenses.title", applet_data.id, user_lang)) }} +

123

+
+{% endif %} diff --git a/templates/base_www.jinja b/templates/base_www.jinja index aab9e6c..44e0ea1 100644 --- a/templates/base_www.jinja +++ b/templates/base_www.jinja @@ -18,7 +18,7 @@ {% block extra_preloads %}{% endblock %} - + @@ -112,7 +112,7 @@ - + {% block extra_scripts %}{% endblock %} diff --git a/templates/elements/file-input.jinja b/templates/elements/file-input.jinja index 081241a..0b5b318 100644 --- a/templates/elements/file-input.jinja +++ b/templates/elements/file-input.jinja @@ -2,7 +2,11 @@ {% if file_upload_button %} {% endif %} diff --git a/templates/pages/about.jinja b/templates/pages/about.jinja index f1cfaa7..a971a5b 100644 --- a/templates/pages/about.jinja +++ b/templates/pages/about.jinja @@ -97,3 +97,7 @@ {{ l10n("financing.text.isp", "about", user_lang) }}

{% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/templates/pages/contact.jinja b/templates/pages/contact.jinja index a909439..e0e893f 100644 --- a/templates/pages/contact.jinja +++ b/templates/pages/contact.jinja @@ -28,3 +28,7 @@

{% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/templates/pages/debug.jinja b/templates/pages/debug.jinja index 95bde70..99712c7 100644 --- a/templates/pages/debug.jinja +++ b/templates/pages/debug.jinja @@ -119,3 +119,7 @@ {% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/templates/pages/error.jinja b/templates/pages/error.jinja index a222b11..3dacff8 100644 --- a/templates/pages/error.jinja +++ b/templates/pages/error.jinja @@ -27,3 +27,7 @@ draggable="false"> {% endif %} {% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/templates/pages/links.jinja b/templates/pages/links.jinja index a2c62f1..c6f3184 100644 --- a/templates/pages/links.jinja +++ b/templates/pages/links.jinja @@ -62,3 +62,7 @@

{{ l10n("gitea.text.1", "links", user_lang ) }}

{% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/templates/pages/privacy.jinja b/templates/pages/privacy.jinja index 6c4fe5c..1b38f97 100644 --- a/templates/pages/privacy.jinja +++ b/templates/pages/privacy.jinja @@ -179,3 +179,7 @@ '(' + l10n('french', "langs", user_lang) + ')' ) }} {% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/templates/pages/project_index.jinja b/templates/pages/project_index.jinja index 085909c..23113a4 100644 --- a/templates/pages/project_index.jinja +++ b/templates/pages/project_index.jinja @@ -38,3 +38,7 @@ {% endfor %} {% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/templates/pages/root.jinja b/templates/pages/root.jinja index e52f5a2..fc95777 100644 --- a/templates/pages/root.jinja +++ b/templates/pages/root.jinja @@ -52,3 +52,7 @@ ]) }} {% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/templates/pages/tools_index.jinja b/templates/pages/tools_index.jinja index 33c3edb..39db6ee 100644 --- a/templates/pages/tools_index.jinja +++ b/templates/pages/tools_index.jinja @@ -38,3 +38,7 @@ {% endfor %} {% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/templates/pages/tools_page.jinja b/templates/pages/tools_page.jinja index 22a26f7..7a60dfd 100644 --- a/templates/pages/tools_page.jinja +++ b/templates/pages/tools_page.jinja @@ -28,5 +28,7 @@ {% endblock %} {% block extra_scripts %} + + {{ render_applet_scripts(applet_data, is_standalone) }} {% endblock %} diff --git a/website/content/dataclasses.py b/website/content/dataclasses.py index fe53b17..7d85fd7 100644 --- a/website/content/dataclasses.py +++ b/website/content/dataclasses.py @@ -126,6 +126,9 @@ class ContentResource: self.scripts = [ContentResourceDefinition(x) for x in self.scripts] self.stylesheets = [ContentResourceDefinition(x) for x in self.stylesheets] + self.scripts: list[ContentResourceDefinition] + self.stylesheets: list[ContentResourceDefinition] + @dataclass class ContentApplet: @@ -135,6 +138,7 @@ class ContentApplet: def __post_init__(self): self.resources: dict self.resources = ContentResource(**self.resources) + self.resources: ContentResource # print(self.resources) @@ -148,6 +152,7 @@ class ContentTool: def __post_init__(self): self.metadata: dict self.metadata = ContentMetadata(**self.metadata) + self.metadata: ContentMetadata @dataclass diff --git a/website/renderers/applet.py b/website/renderers/applet.py index 18bc190..679f454 100644 --- a/website/renderers/applet.py +++ b/website/renderers/applet.py @@ -20,7 +20,7 @@ def render_applet_head(applet_data: ContentApplet, is_standalone: bool = False) "./static/resources/NibblePoker/applets/", applet_data.id, applet_style.get_clean_path()) - print(applet_style) + # print(applet_style) elif applet_style.is_standalone(): rsc_path = os.path.join( "./static/resources/Standalone/", @@ -61,6 +61,7 @@ def render_applet_scripts(applet_data: ContentApplet, is_standalone: bool = Fals "./static/resources/NibblePoker/applets/", applet_data.id, applet_script.get_clean_path()) + rsc_path = rsc_path.replace(".mjs", ".min.js") elif applet_script.is_standalone(): rsc_path = os.path.join( "./static/resources/Standalone/", @@ -68,7 +69,7 @@ def render_applet_scripts(applet_data: ContentApplet, is_standalone: bool = Fals if rsc_path is not None: with open(rsc_path) as applet_script_file: - applet_script_html += "" if applet_script.raw_uri.endswith(".mjs") else ">") + applet_script_html += "" if applet_script.raw_uri.endswith(".mjs") else ">") applet_script_html += applet_script_file.read() applet_script_html += ""