From 005612406c8a23f9103d05d50c45a9ccc3bb3164 Mon Sep 17 00:00:00 2001 From: flick9000 <137506210+flick9000@users.noreply.github.com> Date: Tue, 6 Oct 2026 22:11:09 +0200 Subject: [PATCH 1/6] feat: migrate scripts.js to ts --- app/src/assets/js/global.d.ts | 7 ++++ app/src/assets/js/{scripts.js => scripts.ts} | 44 +++++++++++--------- app/src/layouts/Layout.astro | 2 +- 3 files changed, 33 insertions(+), 20 deletions(-) create mode 100644 app/src/assets/js/global.d.ts rename app/src/assets/js/{scripts.js => scripts.ts} (98%) diff --git a/app/src/assets/js/global.d.ts b/app/src/assets/js/global.d.ts new file mode 100644 index 00000000..78a054a6 --- /dev/null +++ b/app/src/assets/js/global.d.ts @@ -0,0 +1,7 @@ +declare global { + interface Window { + manualURLs?: string[]; + } +} + +export {}; diff --git a/app/src/assets/js/scripts.js b/app/src/assets/js/scripts.ts similarity index 98% rename from app/src/assets/js/scripts.js rename to app/src/assets/js/scripts.ts index a5307f9c..6e78ae17 100644 --- a/app/src/assets/js/scripts.js +++ b/app/src/assets/js/scripts.ts @@ -1,7 +1,7 @@ document.addEventListener("DOMContentLoaded", function () { const parentDiv = document.querySelector(".allScripts"); - function addScript(className, scriptContent) { + function addScript(className: string, scriptContent: string) { const newDiv = document.createElement("div"); const codeElement = document.createElement("code"); @@ -10,15 +10,15 @@ document.addEventListener("DOMContentLoaded", function () { codeElement.textContent = scriptContent; newDiv.appendChild(codeElement); - parentDiv.appendChild(newDiv); - hljs.highlightElement(codeElement); + parentDiv?.appendChild(newDiv); + (window as any).hljs.highlightElement(codeElement); } - function removeScripts(className) { - parentDiv.querySelectorAll(`.${className}`).forEach((el) => el.remove()); + function removeScripts(className: string) { + parentDiv?.querySelectorAll(`.${className}`).forEach((el) => el.remove()); } - const scripts = { + const scripts: Record = { microsoftstore: [ "Write-Host '-- Uninstalling Microsoft Store' -ForegroundColor Green", 'Get-AppxPackage "*Microsoft.WindowsStore*" | Remove-AppxPackage', @@ -1037,7 +1037,7 @@ document.addEventListener("DOMContentLoaded", function () { checkbox.addEventListener("change", () => { removeScripts(id); - if (checkbox.checked) { + if (checkbox instanceof HTMLInputElement && checkbox.checked) { scripts[id]?.forEach((script) => addScript(id, script)); } }); @@ -1046,7 +1046,7 @@ document.addEventListener("DOMContentLoaded", function () { const radios = document.querySelectorAll('input[type="radio"]'); radios.forEach((radio) => { radio.addEventListener("change", () => { - if (radio.checked) { + if (radio instanceof HTMLInputElement && radio.checked) { const groupName = radio.name; document @@ -1066,17 +1066,19 @@ function uncheckAll() { const indicator = document.querySelectorAll(".indicator"); window.manualURLs = []; - document.getElementById("manualList").innerHTML = ""; + + const manualList = document.getElementById("manualList"); + if (manualList) manualList.innerHTML = ""; checkboxes.forEach((checkbox) => { - if (checkbox.checked) { + if (checkbox instanceof HTMLInputElement && checkbox.checked) { checkbox.checked = false; checkbox.dispatchEvent(new Event("change")); } }); radios.forEach((radio) => { - if (radio.checked) { + if (radio instanceof HTMLInputElement && radio.checked) { radio.checked = false; radio.dispatchEvent(new Event("change")); } @@ -1086,15 +1088,19 @@ function uncheckAll() { indicator.textContent = indicator.getAttribute("data-off") || "Off"; }); - document.querySelector(".chocolatey-container").style.display = "none"; - document.querySelector(".winget-container").style.display = "none"; - document.querySelector(".div-install").style.display = "none"; + const chocolateyContainer = document.querySelector(".chocolatey-container"); + const wingetContainer = document.querySelector(".winget-container"); + const installDiv = document.querySelector(".div-install"); + + if (chocolateyContainer instanceof HTMLDivElement) chocolateyContainer.style.display = "none"; + if (wingetContainer instanceof HTMLDivElement) wingetContainer.style.display = "none"; + if (installDiv instanceof HTMLDivElement) installDiv.style.display = "none"; } -document.getElementById("uncheckAll").addEventListener("click", uncheckAll); +document.getElementById("uncheckAll")?.addEventListener("click", uncheckAll); // Presets -const presets = { +const presets: Record = { basic: [ "cleanmgr", "cleantemp", @@ -1246,11 +1252,11 @@ const presets = { ], }; -const applyPreset = (ids) => { +const applyPreset = (ids: string[]) => { uncheckAll(); ids.forEach((id) => { const checkbox = document.getElementById(id); - if (checkbox) { + if (checkbox instanceof HTMLInputElement) { checkbox.checked = true; checkbox.dispatchEvent(new Event("change")); } @@ -1260,5 +1266,5 @@ const applyPreset = (ids) => { ["basic", "strict", "extreme"].forEach((preset) => document .getElementById(`${preset}Preset`) - .addEventListener("click", () => applyPreset(presets[preset])), + ?.addEventListener("click", () => applyPreset(presets[preset])), ); diff --git a/app/src/layouts/Layout.astro b/app/src/layouts/Layout.astro index e2276321..29e190e8 100644 --- a/app/src/layouts/Layout.astro +++ b/app/src/layouts/Layout.astro @@ -22,7 +22,7 @@ const { locale = "en" } = Astro.props; - + From a72501b1808f72ec1a8624ad835203ce784ac731 Mon Sep 17 00:00:00 2001 From: flick9000 <137506210+flick9000@users.noreply.github.com> Date: Tue, 6 Oct 2026 22:26:01 +0200 Subject: [PATCH 2/6] feat: migrate appinstall to ts --- .../js/{appinstall.js => appinstall.ts} | 86 +++++++++++-------- app/src/layouts/Layout.astro | 2 +- .../js/{appinstall.js => appinstall.ts} | 86 +++++++++++-------- website/src/assets/js/global.d.ts | 7 ++ .../src/assets/js/{scripts.js => scripts.ts} | 44 ++++++---- website/src/layouts/Layout.astro | 4 +- 6 files changed, 131 insertions(+), 98 deletions(-) rename app/src/assets/js/{appinstall.js => appinstall.ts} (92%) rename website/src/assets/js/{appinstall.js => appinstall.ts} (92%) create mode 100644 website/src/assets/js/global.d.ts rename website/src/assets/js/{scripts.js => scripts.ts} (98%) diff --git a/app/src/assets/js/appinstall.js b/app/src/assets/js/appinstall.ts similarity index 92% rename from app/src/assets/js/appinstall.js rename to app/src/assets/js/appinstall.ts index 45523852..49bc4df2 100644 --- a/app/src/assets/js/appinstall.js +++ b/app/src/assets/js/appinstall.ts @@ -388,7 +388,7 @@ function appsInstallChocolatey() { return appListChocolatey .filter((app) => { const element = document.getElementById(app.id); - return element && element.checked; + return element instanceof HTMLInputElement && element.checked; }) .map((app) => app.url); } @@ -396,7 +396,7 @@ function appsInstallChocolatey() { // Function to update the command display function updateCommandDisplay() { const checkedUrls = getCheckedUrls(); - const allUrls = [...checkedUrls, ...window.manualURLs]; + const allUrls = [...checkedUrls, ...(window.manualURLs ?? [])]; const finalURL = allUrls .filter((url) => url && url.trim() !== "") .map((url) => `\\"${url}\\"`) @@ -413,19 +413,22 @@ function appsInstallChocolatey() { : ""; // Display the final URL in the div - document.querySelector(".div-install").style.display = allUrls.length > 0 ? "block" : "none"; - document.querySelector(".winget-container").style.display = "none"; - document.querySelector(".chocolatey-container").style.display = - allUrls.length > 0 ? "block" : "none"; + const divInstall = document.querySelector(".div-install") as HTMLDivElement; + const wingetContainer = document.querySelector(".winget-container") as HTMLDivElement; + const chocolateyContainer = document.querySelector(".chocolatey-container") as HTMLDivElement; + + divInstall.style.display = allUrls.length > 0 ? "block" : "none"; + wingetContainer.style.display = "none"; + chocolateyContainer.style.display = allUrls.length > 0 ? "block" : "none"; const commandDisplay = document.querySelector(".commandDisplay"); - commandDisplay.textContent = command; + if (commandDisplay) commandDisplay.textContent = command; const installingApps = document.querySelector(".installingApps"); - installingApps.textContent = allUrls.join(", "); + if (installingApps) installingApps.textContent = allUrls.join(", "); const manualList = document.getElementById("manualList"); - if (window.manualURLs.length > 0) { + if (window.manualURLs && window.manualURLs.length > 0 && manualList) { manualList.innerHTML = "Manual packages added: " + window.manualURLs.join(" | "); } } @@ -823,7 +826,7 @@ function appsInstallWinget() { return appListWinget .filter((app) => { const element = document.getElementById(app.id); - return element && element.checked; + return element instanceof HTMLInputElement && element.checked; }) .map((app) => app.url); } @@ -831,7 +834,7 @@ function appsInstallWinget() { // Function to update the command display function updateCommandDisplay() { const checkedUrls = getCheckedUrls(); - const allUrls = [...checkedUrls, ...window.manualURLs]; + const allUrls = [...checkedUrls, ...(window.manualURLs ?? [])]; const finalURL = allUrls .filter((url) => url && url.trim() !== "") .map((url) => `\\"${url}\\"`) @@ -845,22 +848,26 @@ function appsInstallWinget() { : ""; // Display the final URL in the div - document.querySelector(".div-install").style.display = allUrls.length > 0 ? "block" : "none"; - document.querySelector(".chocolatey-container").style.display = "none"; - document.querySelector(".winget-container").style.display = - allUrls.length > 0 ? "block" : "none"; + const divInstall = document.querySelector(".div-install") as HTMLDivElement; + const chocolateyContainer = document.querySelector(".chocolatey-container") as HTMLDivElement; + const wingetContainer = document.querySelector(".winget-container") as HTMLDivElement; + + divInstall.style.display = allUrls.length > 0 ? "block" : "none"; + chocolateyContainer.style.display = "none"; + wingetContainer.style.display = allUrls.length > 0 ? "block" : "none"; const commandDisplay = document.querySelector(".commandDisplay"); - commandDisplay.textContent = command; + if (commandDisplay) commandDisplay.textContent = command; const installingApps = document.querySelector(".installingApps"); - installingApps.textContent = allUrls.join(", "); + if (installingApps) installingApps.textContent = allUrls.join(", "); const wingetUpgrade = document.getElementById("wingetUpgrade"); - wingetUpgrade.textContent = `$v = winget -v; if ([version]($v.TrimStart('v')) -lt [version]'1.7.0') { Write-Output '-- Old Winget version detected, upgrading.'; Set-Location $env:USERPROFILE; Invoke-WebRequest -Uri 'https://aka.ms/getwinget' -OutFile 'winget.msixbundle'; Add-AppPackage -ForceApplicationShutdown .\\winget.msixbundle; Remove-Item .\\winget.msixbundle } else { Write-Output 'Winget is already up to date, skipping upgrade.' }`; + if (wingetUpgrade) + wingetUpgrade.textContent = `$v = winget -v; if ([version]($v.TrimStart('v')) -lt [version]'1.7.0') { Write-Output '-- Old Winget version detected, upgrading.'; Set-Location $env:USERPROFILE; Invoke-WebRequest -Uri 'https://aka.ms/getwinget' -OutFile 'winget.msixbundle'; Add-AppPackage -ForceApplicationShutdown .\\winget.msixbundle; Remove-Item .\\winget.msixbundle } else { Write-Output 'Winget is already up to date, skipping upgrade.' }`; const manualList = document.getElementById("manualList"); - if (window.manualURLs.length > 0) { + if (window.manualURLs && window.manualURLs.length > 0 && manualList) { manualList.innerHTML = "Manual packages added: " + window.manualURLs.join(" | "); } } @@ -871,8 +878,8 @@ function appsInstallWinget() { appsInstallWinget(); appsInstallChocolatey(); -const selectedPackageManager = document.getElementById("packageManager"); -selectedPackageManager.addEventListener("change", () => { +const selectedPackageManager = document.getElementById("packageManager") as HTMLInputElement; +selectedPackageManager?.addEventListener("change", () => { if (selectedPackageManager.value === "chocolatey") { appsInstallChocolatey(); } else if (selectedPackageManager.value === "winget") { @@ -881,27 +888,30 @@ selectedPackageManager.addEventListener("change", () => { }); // Check manual IDs -function isValidManualId(manualId) { +function isValidManualId(manualId: string) { return /^[A-Za-z0-9._+\-]+$/.test(manualId); } // Manual IDs button listener const addButton = document.getElementById("addApp"); -addButton.addEventListener("click", () => { - const manualInput = document.getElementById("manualInput").value.trim(); - if (manualInput) { - if (!isValidManualId(manualInput)) { - const manualList = document.getElementById("manualList"); - manualList.innerHTML = "Please enter a valid package ID."; - return; - } - window.manualURLs.push(manualInput); - document.getElementById("manualInput").value = ""; // Clear input - if (selectedPackageManager.value === "chocolatey") { - appsInstallChocolatey(); - } else if (selectedPackageManager.value === "winget") { - appsInstallWinget(); - } +addButton?.addEventListener("click", () => { + const manualInput = document.getElementById("manualInput") as HTMLInputElement; + const manualList = document.getElementById("manualList"); + const inputValue = manualInput.value.trim(); + + if (!manualInput || !manualList) return; + + if (!isValidManualId(inputValue)) { + manualList.innerHTML = "Please enter a valid package ID."; + return; + } + if (window.manualURLs) window.manualURLs.push(inputValue); + manualInput.value = ""; + + if (selectedPackageManager.value === "chocolatey") { + appsInstallChocolatey(); + } else if (selectedPackageManager.value === "winget") { + appsInstallWinget(); } }); @@ -909,7 +919,7 @@ addButton.addEventListener("click", () => { const apps = document.querySelectorAll('[js-target="install"]'); document.addEventListener("DOMContentLoaded", () => { document.body.addEventListener("change", (event) => { - if (event.target.matches("[js-target=install]")) { + if (event.target instanceof Element && event.target.matches("[js-target=install]")) { if (selectedPackageManager.value === "chocolatey") { appsInstallChocolatey(); } else if (selectedPackageManager.value === "winget") { diff --git a/app/src/layouts/Layout.astro b/app/src/layouts/Layout.astro index 29e190e8..3c09a9ec 100644 --- a/app/src/layouts/Layout.astro +++ b/app/src/layouts/Layout.astro @@ -23,7 +23,7 @@ const { locale = "en" } = Astro.props; - + - - + + From 770f31a127e081c57375021d68c29e349e9d6f2d Mon Sep 17 00:00:00 2001 From: flick9000 <137506210+flick9000@users.noreply.github.com> Date: Tue, 6 Oct 2026 22:28:07 +0200 Subject: [PATCH 3/6] feat: migrate unattend to ts --- app/src/assets/js/{unattend.js => unattend.ts} | 8 ++++++-- app/src/layouts/Layout.astro | 2 +- website/src/assets/js/{unattend.js => unattend.ts} | 7 +++++-- website/src/layouts/Layout.astro | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) rename app/src/assets/js/{unattend.js => unattend.ts} (97%) rename website/src/assets/js/{unattend.js => unattend.ts} (97%) diff --git a/app/src/assets/js/unattend.js b/app/src/assets/js/unattend.ts similarity index 97% rename from app/src/assets/js/unattend.js rename to app/src/assets/js/unattend.ts index 80b57651..328f5952 100644 --- a/app/src/assets/js/unattend.js +++ b/app/src/assets/js/unattend.ts @@ -2,8 +2,12 @@ import { save } from "@tauri-apps/plugin-dialog"; import { writeTextFile } from "@tauri-apps/plugin-fs"; const autoattendBtn = document.getElementById("autounattendBtn"); -autoattendBtn.addEventListener("click", async () => { - let script = document.getElementById("code").innerText; +autoattendBtn?.addEventListener("click", async () => { + const code = document.getElementById("code"); + if (!code) return; + + let script = code.innerText; + script = script.replace(/\n/g, "\r\n"); script = script.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">"); diff --git a/app/src/layouts/Layout.astro b/app/src/layouts/Layout.astro index 3c09a9ec..1388a901 100644 --- a/app/src/layouts/Layout.astro +++ b/app/src/layouts/Layout.astro @@ -24,7 +24,7 @@ const { locale = "en" } = Astro.props; - + - + From 28fcda81de387023a226ffe459ead94081ab9eab Mon Sep 17 00:00:00 2001 From: flick9000 <137506210+flick9000@users.noreply.github.com> Date: Wed, 7 Oct 2026 00:01:35 +0200 Subject: [PATCH 4/6] feat: migrate main to ts --- app/src/assets/js/{main.js => main.ts} | 226 +++++++++++---------- app/src/layouts/Layout.astro | 2 +- website/src/assets/js/{main.js => main.ts} | 124 ++++++----- website/src/layouts/Layout.astro | 2 +- 4 files changed, 189 insertions(+), 165 deletions(-) rename app/src/assets/js/{main.js => main.ts} (69%) rename website/src/assets/js/{main.js => main.ts} (68%) diff --git a/app/src/assets/js/main.js b/app/src/assets/js/main.ts similarity index 69% rename from app/src/assets/js/main.js rename to app/src/assets/js/main.ts index 52085e7e..6c961983 100644 --- a/app/src/assets/js/main.js +++ b/app/src/assets/js/main.ts @@ -1,9 +1,9 @@ -import { writeTextFile, readTextFile, mkdir, remove, exists } from "@tauri-apps/plugin-fs"; -import { tempDir, join, dirname } from "@tauri-apps/api/path"; +import { writeTextFile, readTextFile, mkdir } from "@tauri-apps/plugin-fs"; +import { tempDir, join } from "@tauri-apps/api/path"; import { Command } from "@tauri-apps/plugin-shell"; import { app } from "@tauri-apps/api"; import { version, locale as getOsLocale } from "@tauri-apps/plugin-os"; -import { getCurrentWindow } from "@tauri-apps/api/window"; +import { Effect, getCurrentWindow } from "@tauri-apps/api/window"; import { ask, save, open } from "@tauri-apps/plugin-dialog"; import { check } from "@tauri-apps/plugin-updater"; import { relaunch } from "@tauri-apps/plugin-process"; @@ -13,15 +13,15 @@ import { getMatches } from "@tauri-apps/plugin-cli"; async function loadConfig() { const matches = await getMatches(); if (matches.args.import) { - const path = matches.args.import.value; + const path = matches.args.import.value?.toString(); if (!path) { return; } try { - const checkboxes = document.querySelectorAll('input[type="checkbox"]'); - const radios = document.querySelectorAll('input[type="radio"]'); + const checkboxes = document.querySelectorAll('input[type="checkbox"]'); + const radios = document.querySelectorAll('input[type="radio"]'); const contents = await readTextFile(path); const settings = JSON.parse(contents); @@ -104,9 +104,10 @@ async function alertForUpdates() { } // Checks if an update is available and performs it -async function checkForUpdates() { +async function checkAndUpdate() { try { const update = await check(); + if (!update) return; let updateAsk = await ask("An update is available. Do you want to update?", { title: "Update Available", @@ -129,9 +130,9 @@ async function checkForUpdates() { async function isInstalled() { const update = await check(); + if (!update) return; - if (update) { - const script = ` + const script = ` $processExists = [bool](Get-Process winscript-portable -ErrorAction SilentlyContinue) $parentPath = (Get-Process -Id (Get-CimInstance Win32_Process -Filter "ProcessId=$PID").ParentProcessId).Path $uninstallPath = Join-Path (Split-Path $parentPath) "uninstall.exe" @@ -139,29 +140,26 @@ async function isInstalled() { @{ isPortable = $processExists; uninstallExists = $uninstallExists } | ConvertTo-Json -Compress `; - const shell = new Command("powershell", [ - "-NoProfile", - "-WindowStyle", - "Hidden", - "-Command", - script, - ]); + const shell = Command.create("powershell", [ + "-NoProfile", + "-WindowStyle", + "Hidden", + "-Command", + script, + ]); - const result = await shell.execute(); - const { isPortable, uninstallExists } = JSON.parse(result.stdout); + const result = await shell.execute(); + const { isPortable, uninstallExists } = JSON.parse(result.stdout); - if (isPortable) { - alertForUpdates(); - return; - } + if (isPortable) { + alertForUpdates(); + return; + } - if (uninstallExists) { - checkForUpdates(); - } else { - alertForUpdates(); - } + if (uninstallExists) { + checkAndUpdate(); } else { - return; + alertForUpdates(); } } @@ -177,7 +175,7 @@ function isWindows11() { function applyMica() { try { if (isWindows11()) { - getCurrentWindow().setEffects({ effects: ["mica"] }); + getCurrentWindow().setEffects({ effects: [Effect.Mica] }); } else { document.body.style.backgroundColor = "var(--background)"; } @@ -189,7 +187,7 @@ function applyMica() { async function hasWindowsTerminal() { try { - const check = new Command("where", ["wt"]); + const check = Command.create("where", ["wt"]); const output = await check.execute(); return output.code === 0; } catch (error) { @@ -213,21 +211,28 @@ document.addEventListener("DOMContentLoaded", () => { }); async function displayVersion() { + const versionElement = document.getElementById("version"); + if (!versionElement) return; + try { const version = await app.getVersion(); - document.getElementById("version").textContent = `${version}`; + versionElement.textContent = `${version}`; } catch (error) { - document.getElementById("version").textContent = ``; + versionElement.textContent = ``; console.error("Failed to get app version:", error); } } displayVersion(); -document.querySelector(".nav-icon").addEventListener("click", () => { +document.querySelector(".nav-icon")?.addEventListener("click", () => { const navbar = document.getElementById("sidebar"); const content = document.querySelector(".content"); - const paragraphs = document.querySelectorAll(".content-entry:not(.about) p"); + const paragraphs = document.querySelectorAll( + ".content-entry:not(.about) p", + ); + + if (!navbar || !content) return; if (!navbar.classList.contains("responsive")) { navbar.classList.add("responsive"); @@ -249,19 +254,19 @@ document.querySelector(".nav-icon").addEventListener("click", () => { } }); -const tabs = document.querySelectorAll(".sidebar-entry"); +const tabs = document.querySelectorAll(".sidebar-entry"); const contents = document.querySelectorAll(".tab-content"); -const title = document.getElementById("content-header"); // Select the header element for updating +const title = document.getElementById("content-header"); -// Set only the first tab and its corresponding content as active if (tabs.length > 0 && contents.length > 0) { tabs[0].classList.add("active"); contents[0].classList.add("active"); - title.textContent = tabs[0].textContent || "WinScript"; // Update header with the first tab's text + + if (title) title.textContent = tabs[0].textContent || "WinScript"; } // Titlebar button goes to languages tab -document.querySelector('button[data-tab="localizations-tab"]').addEventListener("click", () => { +document.querySelector('button[data-tab="localizations-tab"]')?.addEventListener("click", () => { tabs[9].click(); }); @@ -281,18 +286,18 @@ tabs.forEach((tab, index) => { tab.classList.add("active"); contents[index].classList.add("active"); - title.textContent = tab.textContent; + if (title) title.textContent = tab.textContent; }); }); // Import & Export const importBtn = document.getElementById("importBtn"); const exportBtn = document.getElementById("exportBtn"); -const checkboxes = document.querySelectorAll('input[type="checkbox"]'); -const radios = document.querySelectorAll('input[type="radio"]'); +const checkboxes = document.querySelectorAll('input[type="checkbox"]'); +const radios = document.querySelectorAll('input[type="radio"]'); -exportBtn.addEventListener("click", async () => { - let settings = {}; +exportBtn?.addEventListener("click", async () => { + let settings: Record = {}; checkboxes.forEach((checkbox) => { settings[checkbox.id] = checkbox.checked; }); @@ -319,7 +324,7 @@ exportBtn.addEventListener("click", async () => { } }); -importBtn.addEventListener("click", async () => { +importBtn?.addEventListener("click", async () => { try { const filePath = await open({ filters: [ @@ -357,41 +362,43 @@ const visualEffects = document.getElementById("openVisualEffects"); const pageFile = document.getElementById("openPageFile"); const msConfig = document.getElementById("openMSConfig"); -windowsSettings.addEventListener("click", () => { - new Command("cmd", ["/c", "start", "ms-settings:"]).execute(); +windowsSettings?.addEventListener("click", () => { + Command.create("cmd", ["/c", "start", "ms-settings:"]).execute(); }); -deviceManager.addEventListener("click", () => { - new Command("cmd", ["/c", "start", "devmgmt.msc"]).execute(); +deviceManager?.addEventListener("click", () => { + Command.create("cmd", ["/c", "start", "devmgmt.msc"]).execute(); }); -controlPanel.addEventListener("click", () => { - new Command("cmd", ["/c", "start", "control"]).execute(); +controlPanel?.addEventListener("click", () => { + Command.create("cmd", ["/c", "start", "control"]).execute(); }); -visualEffects.addEventListener("click", () => { - new Command("cmd", ["/c", "start", "SystemPropertiesPerformance"]).execute(); +visualEffects?.addEventListener("click", () => { + Command.create("cmd", ["/c", "start", "SystemPropertiesPerformance"]).execute(); }); -pageFile.addEventListener("click", () => { - new Command("cmd", ["/c", "SystemPropertiesPerformance /pagefile"]).execute(); +pageFile?.addEventListener("click", () => { + Command.create("cmd", ["/c", "SystemPropertiesPerformance /pagefile"]).execute(); }); -msConfig.addEventListener("click", () => { - new Command("cmd", ["/c", "start", "msconfig"]).execute(); +msConfig?.addEventListener("click", () => { + Command.create("cmd", ["/c", "start", "msconfig"]).execute(); }); // MAS Checkbox const masCheckbox = document.getElementById("installmas"); -masCheckbox.addEventListener("change", () => { - if (masCheckbox.checked) { - document.querySelector(".mas-container").style.display = "block"; - } else { - document.querySelector(".mas-container").style.display = "none"; - } -}); +const masContainer = document.querySelector(".mas-container"); + +if (masCheckbox instanceof HTMLInputElement && masContainer instanceof HTMLDivElement) { + masCheckbox.addEventListener("change", () => { + masContainer.style.display = masCheckbox.checked ? "block" : "none"; + }); +} // OneDrive Checkbox const onedriveCheckbox = document.getElementById("onedrive"); let onedriveChanging = false; -onedriveCheckbox.addEventListener("click", async (e) => { +onedriveCheckbox?.addEventListener("click", async (e) => { + if (!(onedriveCheckbox instanceof HTMLInputElement)) return; + if (onedriveChanging) { onedriveChanging = false; return; @@ -404,7 +411,6 @@ onedriveCheckbox.addEventListener("click", async (e) => { "Uninstalling OneDrive will delete all of your OneDrive files, make sure to backup if you wish to proceed. Do you want to continue?", { title: "Uninstall OneDrive", - type: "question", }, ); @@ -417,22 +423,20 @@ onedriveCheckbox.addEventListener("click", async (e) => { }); // Restore Point Checkbox -const restoreCheckbox = document.getElementById("restorepoint"); -restoreCheckbox.addEventListener("change", () => { - if (restoreCheckbox.checked) { - document.querySelector(".restore-container").style.display = "block"; - } else { - document.querySelector(".restore-container").style.display = "none"; - } +const restoreCheckbox = document.getElementById("restorepoint") as HTMLInputElement; +const restoreContainer = document.querySelector(".restore-container") as HTMLDivElement; +restoreCheckbox?.addEventListener("change", () => { + restoreContainer.style.display = restoreCheckbox.checked ? "block" : "none"; }); // App Search Bar -document.getElementById("searchBar").addEventListener("input", () => { - const searchValue = document.getElementById("searchBar").value.toLowerCase(); - const detailsElements = document.querySelectorAll("#install-tab details"); +const searchBar = document.getElementById("searchBar") as HTMLInputElement; +searchBar?.addEventListener("input", () => { + const searchValue = searchBar.value.toLowerCase(); + const detailsElements = document.querySelectorAll("#install-tab details"); detailsElements.forEach((details) => { - const entries = [...details.querySelectorAll(".content-entry")]; + const entries = [...details.querySelectorAll(".content-entry")]; const summary = details.querySelector("summary"); let hasMatch = false; @@ -463,7 +467,7 @@ const chocoUpdateCommand = "choco upgrade all -y"; const wingetUpdateCommand = "winget upgrade --all --include-unknown --silent --accept-source-agreements --accept-package-agreements"; -async function updateApps(packageUpdateCommand) { +async function updateApps(packageUpdateCommand: string) { const hasWt = await hasWindowsTerminal(); const args = ["/c", "start"]; if (hasWt) args.push("wt"); @@ -477,20 +481,25 @@ async function updateApps(packageUpdateCommand) { packageUpdateCommand, ); - new Command("cmd", args).execute(); + Command.create("cmd", args).execute(); } -updateBtn.addEventListener("click", () => { - if (packageManager.value === "chocolatey") { - updateApps(chocoUpdateCommand); - } else if (packageManager.value === "winget") { - updateApps(wingetUpdateCommand); +updateBtn?.addEventListener("click", () => { + if (!packageManager) return; + if (packageManager instanceof HTMLInputElement) { + if (packageManager.value === "chocolatey") { + updateApps(chocoUpdateCommand); + } else if (packageManager.value === "winget") { + updateApps(wingetUpdateCommand); + } } }); // Copy to clipboard button -document.getElementById("copyBtn").addEventListener("click", function () { - var textContent = document.getElementById("code").innerText; +document.getElementById("copyBtn")?.addEventListener("click", function () { + var textContent = document.getElementById("code")?.innerText; + if (!textContent) return; + try { navigator.clipboard.writeText(textContent); } catch (error) { @@ -504,7 +513,7 @@ document.querySelectorAll(".checkbox-wrapper").forEach((wrapper) => { const radio = wrapper.querySelector('input[type="radio"]'); const indicator = wrapper.querySelector(".indicator"); - if (checkbox) { + if (checkbox instanceof HTMLInputElement) { checkbox.addEventListener("change", () => { if (indicator) { indicator.textContent = checkbox.checked @@ -517,36 +526,35 @@ document.querySelectorAll(".checkbox-wrapper").forEach((wrapper) => { if (radio) { radio.addEventListener("change", () => { const radioName = radio.getAttribute("name"); - document.querySelectorAll(`input[type="radio"][name="${radioName}"]`).forEach((r) => { - const parentWrapper = r.closest(".checkbox-wrapper"); - if (parentWrapper) { - const ind = parentWrapper.querySelector(".indicator"); - if (ind) { - ind.textContent = r.checked - ? ind.getAttribute("data-on") || "On" - : ind.getAttribute("data-off") || "Off"; + document + .querySelectorAll(`input[type="radio"][name="${radioName}"]`) + .forEach((r) => { + const parentWrapper = r.closest(".checkbox-wrapper"); + if (parentWrapper) { + const indicator = parentWrapper.querySelector(".indicator"); + if (!indicator) return; + indicator.textContent = r.checked + ? indicator.getAttribute("data-on") || "On" + : indicator.getAttribute("data-off") || "Off"; } - } - }); + }); }); } }); // Run Button -document.getElementById("runBtn").addEventListener("click", async function () { +document.getElementById("runBtn")?.addEventListener("click", async function () { if (!restoreCheckbox.checked) { let restoreAsk = await ask("Do you want to create a restore point?", { title: "Restore Point", }); - if (restoreAsk === true) { - document.querySelector(".restore-container").style.display = "block"; - } else { - document.querySelector(".restore-container").style.display = "none"; - } + if (!restoreContainer) return; + restoreContainer.style.display = restoreAsk ? "block" : "none"; } - let textContent = document.getElementById("code").innerText; + let textContent = document.getElementById("code")?.innerText; + if (!textContent) return; // Convert LF to CRLF textContent = textContent.replace(/\n/g, "\r\n"); @@ -587,7 +595,7 @@ document.getElementById("runBtn").addEventListener("click", async function () { filePath, ]; - const command = new Command("cmd", args); + const command = Command.create("cmd", args); command .spawn() @@ -601,12 +609,12 @@ document.getElementById("runBtn").addEventListener("click", async function () { // Language switching document.querySelectorAll(".localization-entry").forEach((entry) => { const useBtn = entry.querySelector(".use-lang-btn"); - const locale = useBtn.getAttribute("data-locale"); + const locale = useBtn?.getAttribute("data-locale"); - useBtn.addEventListener("click", (e) => { + useBtn?.addEventListener("click", (e) => { + if (!locale) return; e.stopPropagation(); - // Redirect to /[locale] - // If locale is en, we could go to / but /en is safer/more consistent + window.location.href = `/${locale}`; localStorage.setItem("locale", locale); }); diff --git a/app/src/layouts/Layout.astro b/app/src/layouts/Layout.astro index 1388a901..04972c7c 100644 --- a/app/src/layouts/Layout.astro +++ b/app/src/layouts/Layout.astro @@ -21,7 +21,7 @@ const { locale = "en" } = Astro.props; - + diff --git a/website/src/assets/js/main.js b/website/src/assets/js/main.ts similarity index 68% rename from website/src/assets/js/main.js rename to website/src/assets/js/main.ts index 06b3f45d..e1d12205 100644 --- a/website/src/assets/js/main.js +++ b/website/src/assets/js/main.ts @@ -45,8 +45,10 @@ function loadLocale() { document.querySelectorAll(".fa-solid").forEach((icon) => { icon.addEventListener("click", () => { const navbar = document.getElementById("sidebar"); - const menuIcon = document.querySelector(".fa-solid.fa-bars-staggered"); - const markIcon = document.querySelector(".fa-solid.fa-xmark"); + const menuIcon = document.querySelector(".fa-solid.fa-bars-staggered") as HTMLElement; + const markIcon = document.querySelector(".fa-solid.fa-xmark") as HTMLElement; + + if (!navbar || !menuIcon || !markIcon) return; if (!navbar.classList.contains("responsive")) { navbar.classList.add("responsive"); @@ -72,7 +74,10 @@ const title = document.getElementById("content-header"); if (tabs.length > 0 && contents.length > 0) { tabs[0].classList.add("active"); contents[0].classList.add("active"); - title.textContent = tabs[0].textContent || "WinScript"; // Update header with the first tab's text + + if (title) { + title.textContent = tabs[0].textContent || "WinScript"; + } } // Remove 'active' from all other content divs @@ -91,37 +96,36 @@ tabs.forEach((tab, index) => { tab.classList.add("active"); contents[index].classList.add("active"); - title.textContent = tab.textContent; + if (title) { + title.textContent = tab.textContent; + } }); }); // MAS Checkbox const masCheckbox = document.getElementById("installmas"); -masCheckbox.addEventListener("change", () => { - if (masCheckbox.checked) { - document.querySelector(".mas-container").style.display = "block"; - } else { - document.querySelector(".mas-container").style.display = "none"; - } -}); +const masContainer = document.querySelector(".mas-container"); -// Restore Point Checkbox -const restoreCheckbox = document.getElementById("restorepoint"); -restoreCheckbox.addEventListener("change", () => { - if (restoreCheckbox.checked) { - document.querySelector(".restore-container").style.display = "block"; - } else { - document.querySelector(".restore-container").style.display = "none"; - } +if (masCheckbox instanceof HTMLInputElement && masContainer instanceof HTMLDivElement) { + masCheckbox.addEventListener("change", () => { + masContainer.style.display = masCheckbox.checked ? "block" : "none"; + }); +} + +const restoreCheckbox = document.getElementById("restorepoint") as HTMLInputElement; +const restoreContainer = document.querySelector(".restore-container") as HTMLDivElement; +restoreCheckbox?.addEventListener("change", () => { + restoreContainer.style.display = restoreCheckbox.checked ? "block" : "none"; }); // App Search Bar -document.getElementById("searchBar").addEventListener("input", () => { - const searchValue = document.getElementById("searchBar").value.toLowerCase(); - const detailsElements = document.querySelectorAll("#install-tab details"); +const searchBar = document.getElementById("searchBar") as HTMLInputElement; +searchBar?.addEventListener("input", () => { + const searchValue = searchBar.value.toLowerCase(); + const detailsElements = document.querySelectorAll("#install-tab details"); detailsElements.forEach((details) => { - const entries = [...details.querySelectorAll(".content-entry")]; + const entries = [...details.querySelectorAll(".content-entry")]; const summary = details.querySelector("summary"); let hasMatch = false; @@ -147,11 +151,11 @@ document.getElementById("searchBar").addEventListener("input", () => { const importBtn = document.getElementById("importBtn"); const exportBtn = document.getElementById("exportBtn"); -const checkboxes = document.querySelectorAll('input[type="checkbox"]'); -const radios = document.querySelectorAll('input[type="radio"]'); +const checkboxes = document.querySelectorAll('input[type="checkbox"]'); +const radios = document.querySelectorAll('input[type="radio"]'); -exportBtn.addEventListener("click", () => { - let settings = {}; +exportBtn?.addEventListener("click", () => { + let settings: Record = {}; checkboxes.forEach((checkbox) => { settings[checkbox.id] = checkbox.checked; }); @@ -176,19 +180,22 @@ exportBtn.addEventListener("click", () => { console.log("File saved successfully"); }); -importBtn.addEventListener("click", () => { +importBtn?.addEventListener("click", () => { const fileInput = document.createElement("input"); fileInput.type = "file"; fileInput.accept = ".json"; fileInput.addEventListener("change", (event) => { - const file = event.target.files[0]; + const file = (event.target as HTMLInputElement)?.files?.[0]; if (!file) return; const reader = new FileReader(); reader.onload = (e) => { try { - const settings = JSON.parse(e.target.result); + const result = (e.target as FileReader)?.result; + if (typeof result !== "string") return; + const settings = JSON.parse(result); + checkboxes.forEach((checkbox) => { checkbox.checked = settings[checkbox.id]; checkbox.dispatchEvent(new Event("change")); @@ -209,9 +216,14 @@ importBtn.addEventListener("click", () => { }); // Copy to clipboard button -document.getElementById("copyBtn").addEventListener("click", function () { - var textContent = document.getElementById("code").innerText; - navigator.clipboard.writeText(textContent); +document.getElementById("copyBtn")?.addEventListener("click", async function () { + var textContent = document.getElementById("code")?.innerText; + if (!textContent) return; + try { + await navigator.clipboard.writeText(textContent); + } catch (error) { + console.error("Error copying to clipboard:", error); + } }); // Update the indicator text @@ -220,7 +232,7 @@ document.querySelectorAll(".checkbox-wrapper").forEach((wrapper) => { const radio = wrapper.querySelector('input[type="radio"]'); const indicator = wrapper.querySelector(".indicator"); - if (checkbox) { + if (checkbox instanceof HTMLInputElement) { checkbox.addEventListener("change", () => { if (indicator) { indicator.textContent = checkbox.checked @@ -233,26 +245,28 @@ document.querySelectorAll(".checkbox-wrapper").forEach((wrapper) => { if (radio) { radio.addEventListener("change", () => { const radioName = radio.getAttribute("name"); - document.querySelectorAll(`input[type="radio"][name="${radioName}"]`).forEach((r) => { - const parentWrapper = r.closest(".checkbox-wrapper"); - if (parentWrapper) { - const ind = parentWrapper.querySelector(".indicator"); - if (ind) { - ind.textContent = r.checked - ? ind.getAttribute("data-on") || "On" - : ind.getAttribute("data-off") || "Off"; + document + .querySelectorAll(`input[type="radio"][name="${radioName}"]`) + .forEach((r) => { + const parentWrapper = r.closest(".checkbox-wrapper"); + if (parentWrapper) { + const indicator = parentWrapper.querySelector(".indicator"); + if (!indicator) return; + indicator.textContent = r.checked + ? indicator.getAttribute("data-on") || "On" + : indicator.getAttribute("data-off") || "Off"; } - } - }); + }); }); } }); -document.getElementById("downloadBtn").addEventListener("click", function () { +document.getElementById("downloadBtn")?.addEventListener("click", function () { const supportDialog = document.getElementById("supportDialog"); const closeSupportDialog = document.getElementById("closeSupportDialog"); - var textContent = document.getElementById("code").innerText; + var textContent = document.getElementById("code")?.innerText; + if (!textContent) return; // Convert LF to CRLF textContent = textContent.replace(/\n/g, "\r\n"); @@ -266,23 +280,25 @@ document.getElementById("downloadBtn").addEventListener("click", function () { link.click(); document.body.removeChild(link); - supportDialog.showModal(); + if (supportDialog instanceof HTMLDialogElement) { + supportDialog?.showModal(); - closeSupportDialog.addEventListener("click", () => { - supportDialog.close(); - }); + closeSupportDialog?.addEventListener("click", () => { + supportDialog?.close(); + }); + } }); // Language switching document.querySelectorAll(".localization-entry").forEach((entry) => { const useBtn = entry.querySelector(".use-lang-btn"); - const locale = useBtn.getAttribute("data-locale"); + const locale = useBtn?.getAttribute("data-locale"); - useBtn.addEventListener("click", (e) => { + useBtn?.addEventListener("click", (e) => { + if (!locale) return; e.stopPropagation(); + localStorage.setItem("locale", locale); - // Redirect to /[locale] - // If locale is en, we could go to / but /en is safer/more consistent window.location.href = `/${locale}`; }); }); diff --git a/website/src/layouts/Layout.astro b/website/src/layouts/Layout.astro index 6d1e5ca4..d16a56d6 100644 --- a/website/src/layouts/Layout.astro +++ b/website/src/layouts/Layout.astro @@ -39,7 +39,7 @@ const { locale = "en" } = Astro.props; hljs.highlightAll(); - + From 5dac7751a06a135189be3cc0a69e89d9d369ab71 Mon Sep 17 00:00:00 2001 From: flick9000 <137506210+flick9000@users.noreply.github.com> Date: Wed, 7 Oct 2026 00:02:51 +0200 Subject: [PATCH 5/6] feat(ci): update compare for ts files --- .github/workflows/compare.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compare.yml b/.github/workflows/compare.yml index e6d3be32..8912ad4c 100644 --- a/.github/workflows/compare.yml +++ b/.github/workflows/compare.yml @@ -71,8 +71,8 @@ jobs: } } - $appInstallApp = "app/src/assets/js/appinstall.js" - $appInstallWeb = "website/src/assets/js/appinstall.js" + $appInstallApp = "app/src/assets/js/appinstall.ts" + $appInstallWeb = "website/src/assets/js/appinstall.ts" if ((Test-Path $appInstallApp) -and (Test-Path $appInstallWeb)) { if ((Get-FileHash $appInstallApp).Hash -ne (Get-FileHash $appInstallWeb).Hash) { @@ -81,8 +81,8 @@ jobs: } } - $scriptsApp = "app/src/assets/js/scripts.js" - $scriptsWeb = "website/src/assets/js/scripts.js" + $scriptsApp = "app/src/assets/js/scripts.ts" + $scriptsWeb = "website/src/assets/js/scripts.ts" if ((Test-Path $scriptsApp) -and (Test-Path $scriptsWeb)) { if ((Get-FileHash $scriptsApp).Hash -ne (Get-FileHash $scriptsWeb).Hash) { From 94c8c7c4599489d8dd49a9fe307813fcf1dd4164 Mon Sep 17 00:00:00 2001 From: flick9000 <137506210+flick9000@users.noreply.github.com> Date: Wed, 7 Oct 2026 17:50:30 +0200 Subject: [PATCH 6/6] chore: remove comments --- app/vite.config.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/vite.config.js b/app/vite.config.js index 9bd2f853..cf474b01 100644 --- a/app/vite.config.js +++ b/app/vite.config.js @@ -4,11 +4,9 @@ const host = process.env.TAURI_DEV_HOST; export default defineConfig(async () => ({ root: "src", - resolve: { alias: { "~": "" } }, // Remove /src from resolved paths + resolve: { alias: { "~": "" } }, server: { - // Tauri expects a fixed port, fail if that port is not available strictPort: true, - // if the host Tauri is expecting is set, use it host: host || false, port: 4321, },