Compare commits

...

11 Commits

Author SHA1 Message Date
Gabi
e909d1a847 Delete WPFTweaksLaptopHibernation (#4066) 2026-02-17 14:24:29 -06:00
Gabi
dcfa68476a Add-WPFTweaksRevertStartMenu (#4023)
* Add WPFTweaksRevertStartMenu

* Create revertstartmenu.md

* Update tweaks.json

* Update tweaks.json

* Update tweaks.json

* Update revertstartmenu.md

* Update tweaks.json

* Update tweaks.json

* Update revertstartmenu.md

* Update tweaks.json
2026-02-17 13:49:54 -06:00
Eren
60d31a1fe0 Hightlight FOSS Apps (#4065)
* add foss tag functionality

* update applications

* update

* update

* fix

* update

* update

* fix formatting
2026-02-17 13:35:26 -06:00
Gabi
5476cd928f Fix WPFTweaksEdgeDebloat block copilot not working (#4063)
* Fix WPFTweaksEdgeDebloat block copilot not working

* Update tweaks.json

* Update tweaks.json

* Update tweaks.json
2026-02-17 13:31:44 -06:00
Gabi
84f2046912 Update-WPFTweaksWidget (#4058)
* Update WPFTweaksWidget how did you miss this chris?

* Fix WPFTweaksWidget not working
2026-02-17 13:30:37 -06:00
Gabi
586fd56603 Update-Invoke-WPFSystemRepair.ps1 (#4043)
* Update Invoke-WPFSystemRepair.ps1

* Update Invoke-WPFSystemRepair.ps1

* add chkdsk back in to tell users if there disk is broken

* Merge branch 'Update-Invoke-WPFSystemRepair' of https://github.com/gabinun/winutil into pr/GabiNun/4043

* add doc
2026-02-17 12:55:51 -06:00
KamaleiZestri
70a94abe02 Decoupled UI and data (#4051)
* Decoupled UI and data

* Fix bad variable naming

* Fix mistype

* Fix mistype v2

Editing from mobile is hard
2026-02-17 12:39:44 -06:00
KamaleiZestri
0e41122d89 More microwin files to delete (#4050) 2026-02-17 12:31:23 -06:00
Gabi
4e7416a2dc Remove Adobe Creative Cloud (#4048)
* Delete functions/public/Invoke-WPFRunAdobeCCCleanerTool.ps1

* Update feature.json
2026-02-17 12:30:38 -06:00
Gabi
61a6265cf9 Fix WPFTweaksBlockAdobeNet (#4042)
* Fix WPFTweaksBlockAdobeNet

* Update tweaks.json
2026-02-17 12:29:41 -06:00
Sean (ANGRYxScotsman)
5582c3cb44 More winutil docs update (#4038)
* updated the gen to add a blackline under the frontmatter and added .md file in the same location with breakdown on what the script does

* copyright fix.

found out the reason why it rendered correctly on my pc and not with site builder. it was because we use --minify for the site builder and i have not been using that on the local instance

* Update pre-release.yaml

* Update en.yaml
2026-02-17 12:28:36 -06:00
28 changed files with 1038 additions and 690 deletions

View File

@@ -16,6 +16,25 @@ jobs:
- name: Checkout Repository
uses: actions/checkout@v6
- name: Generate Dev Docs and Update JSON Links
shell: pwsh
run: |
Set-Location tools
./devdocs-generator.ps1
- name: Commit Updated JSON Links
shell: pwsh
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add config/tweaks.json config/feature.json
$changes = git diff --cached --quiet; if ($LASTEXITCODE -ne 0) {
git commit -m "Update documentation links in JSON configs"
git push
} else {
Write-Host "No JSON link changes to commit"
}
- name: Compile project
shell: pwsh
run: |

File diff suppressed because it is too large Load Diff

View File

@@ -72,5 +72,13 @@
"Type": "Button",
"Order": "5",
"Description": "Show the selected applications"
},
"WPFToggleFOSSHighlight": {
"Content": "Highlight FOSS",
"Category": "__Selection",
"Type": "Toggle",
"Checked": true,
"Order": "6",
"Description": "Toggle the green highlight for FOSS applications"
}
}
}

View File

@@ -181,15 +181,6 @@
"ButtonWidth": "300",
"link": "https://winutil.christitus.com/dev/features/fixes/winget"
},
"WPFRunAdobeCCCleanerTool": {
"Content": "Remove Adobe Creative Cloud",
"category": "Fixes",
"panel": "1",
"Order": "a045_",
"Type": "Button",
"ButtonWidth": "300",
"link": "https://winutil.christitus.com/dev/features/fixes/runadobecccleanertool"
},
"WPFPanelControl": {
"Content": "Control Panel",
"category": "Legacy Windows Panels",

View File

@@ -65,9 +65,11 @@
"panel": "1",
"InvokeScript": [
"
# Sometimes if you dont stop Widgets Process for removal to work
# Sometimes if you dont stop the Widgets process the removal may fail
Stop-Process -Name Widgets
Get-AppxPackage Microsoft.WidgetsPlatformRuntime -AllUsers | Remove-AppxPackage -AllUsers
Get-AppxPackage MicrosoftWindows.Client.WebExperience -AllUsers | Remove-AppxPackage -AllUsers
Invoke-WinUtilExplorerUpdate -action \"restart\"
Write-Host \"Removed widgets\"
@@ -76,59 +78,49 @@
"UndoScript": [
"
Write-Host \"Restoring widgets AppxPackages\"
Add-AppxPackage -DisableDevelopmentMode -Register \"C:\\Program Files\\WindowsApps\\Microsoft.WidgetsPlatformRuntime*\\AppxManifest.xml\"
Add-AppxPackage -Register \"C:\\Program Files\\WindowsApps\\Microsoft.WidgetsPlatformRuntime*\\AppxManifest.xml\" -DisableDevelopmentMode
Add-AppxPackage -Register \"C:\\Program Files\\WindowsApps\\MicrosoftWindows.Client.WebExperience*\\AppxManifest.xml\" -DisableDevelopmentMode
Invoke-WinUtilExplorerUpdate -action \"restart\"
"
],
"link": "https://winutil.christitus.com/dev/tweaks/essential-tweaks/widget"
},
"WPFTweaksLaptopHibernation": {
"Content": "Set Hibernation as default (good for laptops)",
"Description": "Most modern laptops have connected standby enabled which drains the battery, this sets hibernation as default which will not drain the battery. See issue https://github.com/ChrisTitusTech/winutil/issues/1399",
"WPFTweaksRevertStartMenu": {
"Content": "Revert the new start menu",
"Description": "Uses vivetool to revert the the original start menu from 24h2",
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"Order": "a030_",
"registry": [
{
"Path": "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Power\\PowerSettings\\238C9FA8-0AAD-41ED-83F4-97BE242C8F20\\7bc4a2f9-d8fc-4469-b07b-33eb785aaca0",
"OriginalValue": "1",
"Name": "Attributes",
"Value": "2",
"Type": "DWord"
},
{
"Path": "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Power\\PowerSettings\\abfc2519-3608-4c2a-94ea-171b0ed546ab\\94ac6d29-73ce-41a6-809f-6363ba21b47e",
"OriginalValue": "0",
"Name": "Attributes ",
"Value": "2",
"Type": "DWord"
}
],
"InvokeScript": [
"
Write-Host \"Turn on Hibernation\"
powercfg.exe /hibernate on
Invoke-WebRequest https://github.com/thebookisclosed/ViVe/releases/download/v0.3.4/ViVeTool-v0.3.4-IntelAmd.zip -OutFile ViVeTool.zip
Expand-Archive ViVeTool.zip
Remove-Item ViVeTool.zip
Start-Process 'ViVeTool\\ViVeTool.exe' -ArgumentList '/disable /id:47205210' -Wait -NoNewWindow
Remove-Item ViVeTool -Recurse
# Set hibernation as the default action
powercfg.exe change standby-timeout-ac 60
powercfg.exe change standby-timeout-dc 60
powercfg.exe change monitor-timeout-ac 10
powercfg.exe change monitor-timeout-dc 1
Write-Host 'Old start menu reverted please restart your computer to take effect'
"
],
"UndoScript": [
"
Write-Host \"Turn off Hibernation\"
powercfg.exe /hibernate off
Invoke-WebRequest https://github.com/thebookisclosed/ViVe/releases/download/v0.3.4/ViVeTool-v0.3.4-IntelAmd.zip -OutFile ViVeTool.zip
Expand-Archive ViVeTool.zip
Remove-Item ViVeTool.zip
Start-Process 'ViVeTool\\ViVeTool.exe' -ArgumentList '/enable /id:47205210' -Wait -NoNewWindow
Remove-Item ViVeTool -Recurse
# Set standby to default values
powercfg.exe change standby-timeout-ac 15
powercfg.exe change standby-timeout-dc 15
powercfg.exe change monitor-timeout-ac 15
powercfg.exe change monitor-timeout-dc 15
Write-Host 'New start menu reverted please restart your computer to take effect'
"
],
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/laptophibernation"
"link": "https://winutil.christitus.com/dev/tweaks/z--Advanced-Tweaks---CAUTION/revertstartmenu"
},
"WPFTweaksLocation": {
"Content": "Disable Location Tracking",
@@ -1196,10 +1188,10 @@
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Edge",
"Name": "ofefcgjbeghpigppfmkologfjadafddi",
"Path": "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Edge\\ExtensionInstallBlocklist",
"Name": "1",
"Type": "String",
"Value": "1",
"Value": "ofefcgjbeghpigppfmkologfjadafddi",
"OriginalValue": "<RemoveEntry>"
},
{
@@ -1987,9 +1979,9 @@
"InvokeScript": [
"
$hostsUrl = \"https://github.com/Ruddernation-Designs/Adobe-URL-Block-List/raw/refs/heads/master/hosts\"
$hosts = \"$env:SystemRoot\\System32\\drivers\\etc\\hosts\"
$hosts = \"$Env:SystemRoot\\System32\\drivers\\etc\\hosts\"
Copy-Item $hosts \"$env:SystemRoot\\System32\\drivers\\etc\\hosts\\$hosts.bak\"
Move-Item $hosts \"$hosts.bak\"
Invoke-WebRequest $hostsUrl -OutFile $hosts
ipconfig /flushdns
@@ -1998,10 +1990,10 @@
],
"UndoScript": [
"
$hosts = \"$env:SystemRoot\\System32\\drivers\\etc\\hosts\"
$backup = \"$env:SystemRoot\\System32\\drivers\\etc\\hosts\\$hosts.bak\"
$hosts = \"$Env:SystemRoot\\System32\\drivers\\etc\\hosts\"
Remove-Item $hosts
Move-Item \"$hosts.bak\" $hosts
ipconfig /flushdns
Write-Host \"Removed Adobe url block list from host file\"

View File

@@ -0,0 +1,40 @@
---
title: "Revert the new start menu"
description: ""
---
```json
"WPFTweaksRevertStartMenu": {
"Content": "Revert the new start menu",
"Description": "Uses vivetool to revert the the original start menu from 24h2",
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"InvokeScript": [
"
Invoke-WebRequest https://github.com/thebookisclosed/ViVe/releases/download/v0.3.4/ViVeTool-v0.3.4-IntelAmd.zip -OutFile ViVeTool.zip
Expand-Archive ViVeTool.zip
Remove-Item ViVeTool.zip
ViVeTool\\ViVeTool.exe /disable /id:47205210
Remove-Item ViVeTool -Recurse
Write-Host 'Old start menu reverted please restart your computer to take effect'
"
],
"UndoScript": [
"
Invoke-WebRequest https://github.com/thebookisclosed/ViVe/releases/download/v0.3.4/ViVeTool-v0.3.4-IntelAmd.zip -OutFile ViVeTool.zip
Expand-Archive ViVeTool.zip
Remove-Item ViVeTool.zip
ViVeTool\\ViVeTool.exe /enable /id:47205210
Remove-Item ViVeTool -Recurse
Write-Host 'New start menu reverted please restart your computer to take effect'
"
],
```

View File

@@ -1,4 +1,4 @@
copyright: "&copy; <script>document.write(new Date().getFullYear())</script> <a href='https://christitus.com'> Chris Titus Tech</a>. All rights reserved."
copyright: "&copy; <script>document.write(new Date().getFullYear())</script>&nbsp; <a href='https://christitus.com'>Chris Titus Tech</a>. All rights reserved."
backToTop: "Scroll to top"
changeLanguage: "Change language"

View File

@@ -1,92 +0,0 @@
Function Get-WinUtilCheckBoxes {
<#
.SYNOPSIS
Finds all checkboxes that are checked on the specific tab and inputs them into a script.
.PARAMETER unCheck
Whether to uncheck the checkboxes that are checked. Defaults to true
.OUTPUTS
A List containing the name of each checked checkbox
.EXAMPLE
Get-WinUtilCheckBoxes "WPFInstall"
#>
Param(
[boolean]$unCheck = $false
)
$Output = @{
Install = @()
WPFTweaks = @()
WPFFeature = @()
WPFInstall = @()
WPFToggle = @()
}
$CheckBoxes = $sync.GetEnumerator() | Where-Object { $_.Value -is [System.Windows.Controls.CheckBox] }
# Collect toggle switch states
foreach ($CheckBox in $CheckBoxes) {
if ($CheckBox.Key -like "WPFToggle*" -and $CheckBox.Value.IsChecked -eq $true) {
$Output["WPFToggle"] += $CheckBox.Key
Write-Debug "Adding toggle: $($CheckBox.Key)"
}
}
# First check and add WPFTweaksRestorePoint if checked
$RestorePoint = $CheckBoxes | Where-Object { $_.Key -eq 'WPFTweaksRestorePoint' -and $_.Value.IsChecked -eq $true }
if ($RestorePoint) {
$Output["WPFTweaks"] = @('WPFTweaksRestorePoint')
Write-Debug "Adding WPFTweaksRestorePoint as first in WPFTweaks"
if ($unCheck) {
$RestorePoint.Value.IsChecked = $false
}
}
foreach ($CheckBox in $CheckBoxes) {
if ($CheckBox.Key -eq 'WPFTweaksRestorePoint') { continue } # Skip since it's already handled
$group = if ($CheckBox.Key.StartsWith("WPFInstall")) { "Install" }
elseif ($CheckBox.Key.StartsWith("WPFTweaks")) { "WPFTweaks" }
elseif ($CheckBox.Key.StartsWith("WPFFeature")) { "WPFFeature" }
if ($group) {
if ($CheckBox.Value.IsChecked -eq $true) {
$feature = switch ($group) {
"Install" {
# Get the winget value
[PsCustomObject]@{
winget="$($sync.configs.applications.$($CheckBox.Name).winget)";
choco="$($sync.configs.applications.$($CheckBox.Name).choco)";
}
}
default {
$CheckBox.Name
}
}
if (-not $Output.ContainsKey($group)) {
$Output[$group] = @()
}
if ($group -eq "Install") {
$Output["WPFInstall"] += $CheckBox.Name
Write-Debug "Adding: $($CheckBox.Name) under: WPFInstall"
}
Write-Debug "Adding: $($feature) under: $($group)"
$Output[$group] += $feature
if ($unCheck) {
$CheckBox.Value.IsChecked = $false
}
}
}
}
return $Output
}

View File

@@ -41,16 +41,19 @@ function Initialize-InstallAppEntry {
})
$checkBox = New-Object Windows.Controls.CheckBox
$checkBox.Name = $appKey
# Sanitize the name for WPF
$checkBox.Name = $appKey -replace '-', '_'
# Store the original appKey in Tag
$checkBox.Tag = $appKey
$checkbox.Style = $sync.Form.Resources.AppEntryCheckboxStyle
$checkbox.Add_Checked({
Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $this
Invoke-WPFSelectedCheckboxesUpdate -type "Add" -checkboxName $this.Parent.Tag
$borderElement = $this.Parent
$borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallSelectedColor")
})
$checkbox.Add_Unchecked({
Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this
Invoke-WPFSelectedCheckboxesUpdate -type "Remove" -checkboxName $this.Parent.Tag
$borderElement = $this.Parent
$borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor")
})
@@ -60,6 +63,12 @@ function Initialize-InstallAppEntry {
$appName.Style = $sync.Form.Resources.AppEntryNameStyle
$appName.Text = $Apps.$appKey.content
# Change color to Green if FOSS
if ($Apps.$appKey.foss -eq $true) {
$appName.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "FOSSColor")
$appName.FontWeight = "Bold"
}
# Add the name to the Checkbox
$checkBox.Content = $appName

View File

@@ -6,7 +6,7 @@ Function Invoke-WinUtilCurrentSystem {
Checks to see what tweaks have already been applied and what programs are installed, and checks the according boxes
.EXAMPLE
Get-WinUtilCheckBoxes "WPFInstall"
InvokeWinUtilCurrentSystem -Checkbox "winget"
#>

View File

@@ -174,6 +174,18 @@ function Invoke-WinutilThemeChange {
}
}
# Set FOSS Highlight Color
$fossEnabled = $true
if ($sync.WPFToggleFOSSHighlight) {
$fossEnabled = $sync.WPFToggleFOSSHighlight.IsChecked
}
if ($fossEnabled) {
$sync.Form.Resources["FOSSColor"] = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(76, 175, 80)) # #4CAF50
} else {
$sync.Form.Resources["FOSSColor"] = $sync.Form.Resources["MainForegroundColor"]
}
# Update the theme selector button with the appropriate icon
$ThemeButton = $sync.Form.FindName("ThemeButton")
$ThemeButton.Content = [string]$themeButtonIcon

View File

@@ -0,0 +1,75 @@
function Reset-WPFCheckBoxes {
<#
.SYNOPSIS
Set winutil checkboxs to match $sync.selected values.
Should only need to be run if $sync.selected updated outside of UI (i.e. presets or import)
.PARAMETER doToggles
Whether or not to set UI toggles. WARNING: they will trigger if altered
.PARAMETER checkboxfilterpattern
The Pattern to use when filtering through CheckBoxes, defaults to "**"
Used to make reset blazingly fast.
#>
param (
[Parameter(position=0)]
[bool]$doToggles = $false,
[Parameter(position=1)]
[string]$checkboxfilterpattern = "**"
)
$CheckBoxesToCheck = $sync.selectedApps + $sync.selectedTweaks + $sync.selectedFeatures
$CheckBoxes = ($sync.GetEnumerator()).where{ $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" -and $_.Name -like "$checkboxfilterpattern"}
Write-Debug "Getting checkboxes to set, number of checkboxes: $($CheckBoxes.Count)"
if ($CheckBoxesToCheck -ne "") {
$debugMsg = "CheckBoxes to Check are: "
$CheckBoxesToCheck | ForEach-Object { $debugMsg += "$_, " }
$debugMsg = $debugMsg -replace (',\s*$', '')
Write-Debug "$debugMsg"
}
foreach ($CheckBox in $CheckBoxes) {
$checkboxName = $CheckBox.Key
if (-not $CheckBoxesToCheck) {
$sync.$checkBoxName.IsChecked = $false
continue
}
# Check if the checkbox name exists in the flattened JSON hashtable
if ($CheckBoxesToCheck -contains $checkboxName) {
# If it exists, set IsChecked to true
$sync.$checkboxName.IsChecked = $true
Write-Debug "$checkboxName is checked"
} else {
# If it doesn't exist, set IsChecked to false
$sync.$checkboxName.IsChecked = $false
Write-Debug "$checkboxName is not checked"
}
}
# Update Installs tab UI values
$count = $sync.SelectedApps.Count
$sync.WPFselectedAppsButton.Content = "Selected Apps: $count"
# On every change, remove all entries inside the Popup Menu. This is done, so we can keep the alphabetical order even if elements are selected in a random way
$sync.selectedAppsstackPanel.Children.Clear()
$sync.selectedApps | Foreach-Object { Add-SelectedAppsMenuItem -name $($sync.configs.applicationsHashtable.$_.Content) -key $_ }
if($doToggles) {
# Restore toggle switch states
$importedToggles = $sync.selectedToggles
$allToggles = $sync.GetEnumerator() | Where-Object { $_.Key -like "WPFToggle*" -and $_.Value -is [System.Windows.Controls.CheckBox] }
foreach ($toggle in $allToggles) {
if ($importedToggles -contains $toggle.Key) {
$sync[$toggle.Key].IsChecked = $true
Write-Debug "Restoring toggle: $($toggle.Key) = checked"
} else {
$sync[$toggle.Key].IsChecked = $false
Write-Debug "Restoring toggle: $($toggle.Key) = unchecked"
}
}
}
}

View File

@@ -0,0 +1,59 @@
function Update-WinUtilSelections {
<#
.SYNOPSIS
Updates the $sync.selected variables with a given preset.
.PARAMETER flatJson
The flattened json list of $sync values to select.
#>
param (
$flatJson
)
Write-Debug "JSON to import: $($flatJson)"
foreach ($cbkey in $flatJson) {
$group = if ($cbkey.StartsWith("WPFInstall")) { "Install" }
elseif ($cbkey.StartsWith("WPFTweaks")) { "Tweaks" }
elseif ($cbkey.StartsWith("WPFToggle")) { "Toggle" }
elseif ($cbkey.StartsWith("WPFFeature")) { "Feature" }
else { "na" }
switch ($group) {
"Install" {
if (!$sync.selectedApps.Contains($cbkey)) {
$sync.selectedApps.Add($cbkey)
# The List type needs to be specified again, because otherwise Sort-Object will convert the list to a string if there is only a single entry
[System.Collections.Generic.List[pscustomobject]]$sync.selectedApps = $sync.SelectedApps | Sort-Object
}
}
"Tweaks" {
if (!$sync.selectedTweaks.Contains($cbkey)) {
$sync.selectedTweaks.Add($cbkey)
}
}
"Toggle" {
if (!$sync.selectedToggles.Contains($cbkey)) {
$sync.selectedToggles.Add($cbkey)
}
}
"Feature" {
if (!$sync.selectedFeatures.Contains($cbkey)) {
$sync.selectedFeatures.Add($cbkey)
}
}
default {
Write-Host "Unknown group for checkbox: $($cbkey)"
}
}
}
Write-Debug "-------------------------------------"
Write-Debug "Selected Apps: $($sync.selectedApps)"
Write-Debug "Selected Tweaks: $($sync.selectedTweaks)"
Write-Debug "Selected Toggles: $($sync.selectedToggles)"
Write-Debug "Selected Features: $($sync.selectedFeatures)"
Write-Debug "--------------------------------------"
}

View File

@@ -1,20 +0,0 @@
function Invoke-AutoConfigDialog {
<#
.SYNOPSIS
Sets the automatic configuration file based on a specified JSON file
#>
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
$OFD = New-Object System.Windows.Forms.OpenFileDialog
$OFD.Filter = "JSON Files (*.json)|*.json"
$OFD.ShowDialog()
if ($OFD.FileName -eq "")
{
Write-Host "No automatic config file has been selected. Continuing without one..."
return
}
return $OFD.FileName
}

View File

@@ -63,5 +63,12 @@ function Invoke-WPFButton {
"WPFWinUtilUninstallPSProfile" {Invoke-WinUtilUninstallPSProfile}
"WPFWinUtilSSHServer" {Invoke-WPFSSHServer}
"WPFselectedAppsButton" {$sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen}
"WPFToggleFOSSHighlight" {
if ($sync.WPFToggleFOSSHighlight.IsChecked) {
$sync.Form.Resources["FOSSColor"] = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(76, 175, 80)) # #4CAF50
} else {
$sync.Form.Resources["FOSSColor"] = $sync.Form.Resources["MainForegroundColor"]
}
}
}
}

View File

@@ -12,7 +12,7 @@ function Invoke-WPFFeatureInstall {
return
}
$Features = (Get-WinUtilCheckBoxes)["WPFFeature"]
$Features = $sync.selectedFeatures
Invoke-WPFRunspace -ArgumentList $Features -DebugPreference $DebugPreference -ScriptBlock {
param($Features, $DebugPreference)

View File

@@ -44,7 +44,8 @@ function Invoke-WPFImpex {
try {
$Config = ConfigDialog
if ($Config) {
$jsonFile = Get-WinUtilCheckBoxes -unCheck $false | ConvertTo-Json
$allConfs = $sync.selectedApps + $sync.selectedTweaks + $sync.selectedToggles + $sync.selectedFeatures
$jsonFile = $allConfs | ConvertTo-Json
$jsonFile | Out-File $Config -Force
"iex ""& { `$(irm https://christitus.com/win) } -Config '$Config'""" | Set-Clipboard
}
@@ -66,21 +67,12 @@ function Invoke-WPFImpex {
Write-Error "Failed to load the JSON file from the specified path or URL: $_"
return
}
$flattenedJson = $jsonFile.PSObject.Properties.Where({ $_.Name -ne "Install" -and $_.Name -ne "WPFToggle" }).ForEach({ $_.Value })
Invoke-WPFPresets -preset $flattenedJson -imported $true
# Restore toggle switch states
$importedToggles = if ($jsonFile.WPFToggle) { $jsonFile.WPFToggle } else { @() }
$allToggles = $sync.GetEnumerator() | Where-Object { $_.Key -like "WPFToggle*" -and $_.Value -is [System.Windows.Controls.CheckBox] }
foreach ($toggle in $allToggles) {
if ($importedToggles -contains $toggle.Key) {
$sync[$toggle.Key].IsChecked = $true
Write-Debug "Restoring toggle: $($toggle.Key) = checked"
} else {
$sync[$toggle.Key].IsChecked = $false
Write-Debug "Restoring toggle: $($toggle.Key) = unchecked"
}
}
# TODO how to handle old style? detected json type then flatten it in a func?
# $flattenedJson = $jsonFile.PSObject.Properties.Where({ $_.Name -ne "Install" }).ForEach({ $_.Value })
$flattenedJson = $jsonFile
Update-WinUtilSelections -flatJson $flattenedJson
# TODO test with toggles
Reset-WPFCheckBoxes -doToggles $true
}
} catch {
Write-Error "An error occurred while importing: $_"

View File

@@ -2,10 +2,10 @@ function Invoke-WPFPresets {
<#
.SYNOPSIS
Sets the options in the tweaks panel to the given preset
Sets the checkboxes in winutil to the given preset
.PARAMETER preset
The preset to set the options to
The preset to set the checkboxes to
.PARAMETER imported
If the preset is imported from a file, defaults to false
@@ -17,7 +17,7 @@ function Invoke-WPFPresets {
param (
[Parameter(position=0)]
[Array]$preset = "",
[Array]$preset = $null,
[Parameter(position=1)]
[bool]$imported = $false,
@@ -32,33 +32,19 @@ function Invoke-WPFPresets {
$CheckBoxesToCheck = $sync.configs.preset.$preset
}
$CheckBoxes = ($sync.GetEnumerator()).where{ $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" -and $_.Name -like "$checkboxfilterpattern"}
Write-Debug "Getting checkboxes to set, number of checkboxes: $($CheckBoxes.Count)"
if ($CheckBoxesToCheck -ne "") {
$debugMsg = "CheckBoxes to Check are: "
$CheckBoxesToCheck | ForEach-Object { $debugMsg += "$_, " }
$debugMsg = $debugMsg -replace (',\s*$', '')
Write-Debug "$debugMsg"
}
foreach ($CheckBox in $CheckBoxes) {
$checkboxName = $CheckBox.Key
if (-not $CheckBoxesToCheck) {
$sync.$checkboxName.IsChecked = $false
continue
}
# Check if the checkbox name exists in the flattened JSON hashtable
if ($CheckBoxesToCheck -contains $checkboxName) {
# If it exists, set IsChecked to true
$sync.$checkboxName.IsChecked = $true
Write-Debug "$checkboxName is checked"
} else {
# If it doesn't exist, set IsChecked to false
$sync.$checkboxName.IsChecked = $false
Write-Debug "$checkboxName is not checked"
# clear out the filtered pattern
if (!$preset) {
switch ($checkboxfilterpattern) {
"WPFTweak*" { $sync.selectedTweaks = [System.Collections.Generic.List[string]]::new() }
"WPFInstall*" { $sync.selectedApps = [System.Collections.Generic.List[string]]::new() }
"WPFeatures" { $sync.selectedFeatures = [System.Collections.Generic.List[string]]::new() }
"WPFToggle" { $sync.selectedToggles = [System.Collections.Generic.List[string]]::new() }
default {}
}
}
else {
Update-WinUtilSelections -flatJson $CheckBoxesToCheck
}
Reset-WPFCheckBoxes -doToggles $false -checkboxfilterpattern $checkboxfilterpattern
}

View File

@@ -1,32 +0,0 @@
function Invoke-WPFRunAdobeCCCleanerTool {
<#
.SYNOPSIS
It removes or fixes problem files and resolves permission issues in registry keys.
.DESCRIPTION
The Creative Cloud Cleaner tool is a utility for experienced users to clean up corrupted installations.
#>
[string]$url="https://swupmf.adobe.com/webfeed/CleanerTool/win/AdobeCreativeCloudCleanerTool.exe"
Write-Host "The Adobe Creative Cloud Cleaner tool is hosted at"
Write-Host "$url"
try {
# Don't show the progress because it will slow down the download speed
$ProgressPreference='SilentlyContinue'
Invoke-WebRequest -Uri $url -OutFile "$env:TEMP\AdobeCreativeCloudCleanerTool.exe" -UseBasicParsing -ErrorAction SilentlyContinue -Verbose
# Revert back the ProgressPreference variable to the default value since we got the file desired
$ProgressPreference='Continue'
Start-Process -FilePath "$env:TEMP\AdobeCreativeCloudCleanerTool.exe" -Wait -ErrorAction SilentlyContinue -Verbose
} catch {
Write-Error $_.Exception.Message
} finally {
if (Test-Path -Path "$env:TEMP\AdobeCreativeCloudCleanerTool.exe") {
Write-Host "Cleaning up..."
Remove-Item -Path "$env:TEMP\AdobeCreativeCloudCleanerTool.exe" -Verbose
}
}
}

View File

@@ -1,43 +0,0 @@
function Invoke-WPFSelectedAppsUpdate {
<#
.SYNOPSIS
This is a helper function that is called by the Checked and Unchecked events of the Checkboxes on the install tab.
It Updates the "Selected Apps" selectedAppLabel on the Install Tab to represent the current collection
.PARAMETER type
Eigther: Add | Remove
.PARAMETER checkbox
should contain the current instance of the checkbox that triggered the Event.
Most of the time will be the automatic variable $this
.EXAMPLE
$checkbox.Add_Unchecked({Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this})
OR
Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $specificCheckbox
#>
param (
$type,
$checkbox
)
$selectedAppsButton = $sync.WPFselectedAppsButton
# Get the actual Name from the selectedAppLabel inside the Checkbox
$appKey = $checkbox.Parent.Tag
if ($type -eq "Add") {
$sync.selectedApps.Add($appKey)
# The List type needs to be specified again, because otherwise Sort-Object will convert the list to a string if there is only a single entry
[System.Collections.Generic.List[pscustomobject]]$sync.selectedApps = $sync.SelectedApps | Sort-Object
}
elseif ($type -eq "Remove") {
$sync.SelectedApps.Remove($appKey)
}
else{
Write-Error "Type: $type not implemented"
}
$count = $sync.SelectedApps.Count
$selectedAppsButton.Content = "Selected Apps: $count"
# On every change, remove all entries inside the Popup Menu. This is done, so we can keep the alphabetical order even if elements are selected in a random way
$sync.selectedAppsstackPanel.Children.Clear()
$sync.SelectedApps | Foreach-Object { Add-SelectedAppsMenuItem -name $($sync.configs.applicationsHashtable.$_.Content) -key $_ }
}

View File

@@ -0,0 +1,95 @@
function Invoke-WPFSelectedCheckboxesUpdate{
<#
.SYNOPSIS
This is a helper function that is called by the Checked and Unchecked events of the Checkboxes.
It also Updates the "Selected Apps" selectedAppLabel on the Install Tab to represent the current collection
.PARAMETER type
Either: Add | Remove
.PARAMETER checkboxName
should contain the name of the current instance of the checkbox that triggered the Event.
Most of the time will be the automatic variable $this.Parent.Tag
.EXAMPLE
$checkbox.Add_Unchecked({Invoke-WPFSelectedCheckboxesUpdate -type "Remove" -checkboxName $this.Parent.Tag})
OR
Invoke-WPFSelectedCheckboxesUpdate -type "Add" -checkboxName $specificCheckbox.Parent.Tag
#>
param (
$type,
$checkboxName
)
if (($type -ne "Add") -and ($type -ne "Remove"))
{
Write-Error "Type: $type not implemented"
return
}
# Get the actual Name from the selectedAppLabel inside the Checkbox
$appKey = $checkboxName
$group = if ($appKey.StartsWith("WPFInstall")) { "Install" }
elseif ($appKey.StartsWith("WPFTweaks")) { "Tweaks" }
elseif ($appKey.StartsWith("WPFToggle")) { "Toggle" }
elseif ($appKey.StartsWith("WPFFeature")) { "Feature" }
else { "na" }
switch ($group) {
"Install" {
if ($type -eq "Add") {
if (!$sync.selectedApps.Contains($appKey)) {
$sync.selectedApps.Add($appKey)
# The List type needs to be specified again, because otherwise Sort-Object will convert the list to a string if there is only a single entry
[System.Collections.Generic.List[pscustomobject]]$sync.selectedApps = $sync.SelectedApps | Sort-Object
}
}
else{
$sync.selectedApps.Remove($appKey)
}
$count = $sync.SelectedApps.Count
$sync.WPFselectedAppsButton.Content = "Selected Apps: $count"
# On every change, remove all entries inside the Popup Menu. This is done, so we can keep the alphabetical order even if elements are selected in a random way
$sync.selectedAppsstackPanel.Children.Clear()
$sync.selectedApps | Foreach-Object { Add-SelectedAppsMenuItem -name $($sync.configs.applicationsHashtable.$_.Content) -key $_ }
}
"Tweaks" {
if ($type -eq "Add") {
if (!$sync.selectedTweaks.Contains($appKey)) {
$sync.selectedTweaks.Add($appKey)
}
}
else{
$sync.selectedTweaks.Remove($appKey)
}
}
"Toggle" {
if ($type -eq "Add") {
if (!$sync.selectedToggles.Contains($appKey)) {
$sync.selectedToggles.Add($appKey)
}
}
else{
$sync.selectedToggles.Remove($appKey)
}
}
"Feature" {
if ($type -eq "Add") {
if (!$sync.selectedFeatures.Contains($appKey)) {
$sync.selectedFeatures.Add($appKey)
}
}
else{
$sync.selectedFeatures.Remove($appKey)
}
}
default {
Write-Host "Unknown group for checkbox: $($appKey)"
}
}
Write-Debug "-------------------------------------"
Write-Debug "Selected Apps: $($sync.selectedApps)"
Write-Debug "Selected Tweaks: $($sync.selectedTweaks)"
Write-Debug "Selected Toggles: $($sync.selectedToggles)"
Write-Debug "Selected Features: $($sync.selectedFeatures)"
Write-Debug "--------------------------------------"
}

View File

@@ -1,137 +1,17 @@
function Invoke-WPFSystemRepair {
<#
.SYNOPSIS
Checks for system corruption using Chkdsk, SFC, and DISM
Checks for system corruption using SFC, and DISM
.DESCRIPTION
1. Chkdsk - Fixes disk and filesystem corruption
2. SFC Run 1 - Fixes system file corruption, and fixes DISM if it was corrupted
3. DISM - Fixes system image corruption, and fixes SFC's system image if it was corrupted
4. SFC Run 2 - Fixes system file corruption, this time with an almost guaranteed uncorrupted system image
1. SFC - Fixes system file corruption, and fixes DISM if it was corrupted
2. DISM - Fixes system image corruption, and fixes SFC's system image if it was corrupted
3. Chkdsk - Checks for disk errors, which can cause system file corruption and notifies of early disk failure
#>
Start-Process cmd.exe -ArgumentList "/c chkdsk.exe /scan /perf" -NoNewWindow -Wait
Start-Process cmd.exe -ArgumentList "/c sfc /scannow" -NoNewWindow -Wait
Start-Process cmd.exe -ArgumentList "/c dism /online /cleanup-image /restorehealth" -NoNewWindow -Wait
function Invoke-Chkdsk {
<#
.SYNOPSIS
Runs chkdsk on the system drive
.DESCRIPTION
Chkdsk /Scan - Runs an online scan on the system drive, attempts to fix any corruption, and queues other corruption for fixing on reboot
#>
param(
[int]$parentProgressId = 0
)
Write-Progress -Id 1 -ParentId $parentProgressId -Activity $childProgressBarActivity -Status "Running chkdsk..." -PercentComplete 0
$oldpercent = 0
# 2>&1 redirects stdout, allowing iteration over the output
chkdsk.exe /scan /perf 2>&1 | ForEach-Object {
Write-Debug $_
# Regex to match the total percentage regardless of windows locale (it's always the second percentage in the status output)
if ($_ -match "%.*?(\d+)%") {
[int]$percent = $matches[1]
if ($percent -gt $oldpercent) {
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "Running chkdsk... ($percent%)" -PercentComplete $percent
$oldpercent = $percent
}
}
}
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "chkdsk Completed" -PercentComplete 100 -Completed
}
function Invoke-SFC {
<#
.SYNOPSIS
Runs sfc on the system drive
.DESCRIPTION
SFC /ScanNow - Performs a scan of the system files and fixes any corruption
.NOTES
ErrorActionPreference is set locally within a script block & {...} to isolate their effects.
ErrorActionPreference suppresses false errors caused by sfc.exe output redirection.
A bug in SFC output buffering causes progress updates to appear in chunks when redirecting output
#>
param(
[int]$parentProgressId = 0
)
& {
$ErrorActionPreference = "SilentlyContinue"
Write-Progress -Id 1 -ParentId $parentProgressId -Activity $childProgressBarActivity -Status "Running SFC..." -PercentComplete 0
$oldpercent = 0
sfc.exe /scannow 2>&1 | ForEach-Object {
Write-Debug $_
if ($_ -ne "") {
# sfc.exe /scannow outputs unicode characters, so we directly remove null characters for optimization
$utf8line = $_ -replace "`0", ""
if ($utf8line -match "(\d+)\s*%") {
[int]$percent = $matches[1]
if ($percent -gt $oldpercent) {
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "Running SFC... ($percent%)" -PercentComplete $percent
$oldpercent = $percent
}
}
}
}
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "SFC Completed" -PercentComplete 100 -Completed
}
}
function Invoke-DISM {
<#
.SYNOPSIS
Runs DISM on the system drive
.DESCRIPTION
DISM - Fixes system image corruption, and fixes SFC's system image if it was corrupted
/Online - Fixes the currently running system image
/Cleanup-Image - Performs cleanup operations on the image, could remove some unneeded temporary files
/Restorehealth - Performs a scan of the image and fixes any corruption
#>
param(
[int]$parentProgressId = 0
)
Write-Progress -Id 1 -ParentId $parentProgressId -Activity $childProgressBarActivity -Status "Running DISM..." -PercentComplete 0
$oldpercent = 0
DISM /Online /Cleanup-Image /RestoreHealth | ForEach-Object {
Write-Debug $_
# Filter for lines that contain a percentage that is greater than the previous one
if ($_ -match "(\d+)[.,]\d+%") {
[int]$percent = $matches[1]
if ($percent -gt $oldpercent) {
# Update the progress bar
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "Running DISM... ($percent%)" -PercentComplete $percent
$oldpercent = $percent
}
}
}
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "DISM Completed" -PercentComplete 100 -Completed
}
try {
Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
$childProgressBarActivity = "Scanning for corruption"
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 0
# Step 1: Run chkdsk to fix disk and filesystem corruption before proceeding with system file repairs
Invoke-Chkdsk
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 25
# Step 2: Run SFC to fix system file corruption and ensure DISM can operate correctly
Invoke-SFC
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 50
# Step 3: Run DISM to repair the system image, which SFC relies on for accurate repairs
Invoke-DISM
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 75
# Step 4: Run SFC again to ensure system files are repaired using the now-fixed system image
Invoke-SFC
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 100 -Completed
Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
} catch {
Write-Error "An error occurred while repairing the system: $_"
Set-WinUtilTaskbaritem -state "Error" -overlay "warning"
} finally {
Write-Host "==> Finished System Repair"
Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
}
Write-Host "==> Finished System Repair"
Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
}

View File

@@ -176,18 +176,32 @@ function Invoke-WPFUIElements {
$itemsControl.Items.Add($dockPanel) | Out-Null
$sync[$entryInfo.Name] = $checkBox
$sync[$entryInfo.Name].IsChecked = (Get-WinUtilToggleStatus $entryInfo.Name)
$sync[$entryInfo.Name].Add_Checked({
[System.Object]$Sender = $args[0]
Invoke-WinUtilTweaks $sender.name
})
$sync[$entryInfo.Name].Add_Unchecked({
[System.Object]$Sender = $args[0]
Invoke-WinUtiltweaks $sender.name -undo $true
})
if ($entryInfo.Name -eq "WPFToggleFOSSHighlight") {
if ($entryInfo.Checked -eq $true) {
$sync[$entryInfo.Name].IsChecked = $true
}
$sync[$entryInfo.Name].Add_Checked({
Invoke-WPFButton -Button "WPFToggleFOSSHighlight"
})
$sync[$entryInfo.Name].Add_Unchecked({
Invoke-WPFButton -Button "WPFToggleFOSSHighlight"
})
} else {
$sync[$entryInfo.Name].IsChecked = (Get-WinUtilToggleStatus $entryInfo.Name)
$sync[$entryInfo.Name].Add_Checked({
[System.Object]$Sender = $args[0]
Invoke-WPFSelectedCheckboxesUpdate -type "Add" -checkboxName $Sender.name
Invoke-WinUtilTweaks $Sender.name
})
$sync[$entryInfo.Name].Add_Unchecked({
[System.Object]$Sender = $args[0]
Invoke-WPFSelectedCheckboxesUpdate -type "Remove" -checkboxName $Sender.name
Invoke-WinUtiltweaks $Sender.name -undo $true
})
}
}
"ToggleButton" {
@@ -355,6 +369,16 @@ function Invoke-WPFUIElements {
$itemsControl.Items.Add($horizontalStackPanel) | Out-Null
$sync[$entryInfo.Name] = $checkBox
$sync[$entryInfo.Name].Add_Checked({
[System.Object]$Sender = $args[0]
Invoke-WPFSelectedCheckboxesUpdate -type "Add" -checkboxName $Sender.name
})
$sync[$entryInfo.Name].Add_Unchecked({
[System.Object]$Sender = $args[0]
Invoke-WPFSelectedCheckboxesUpdate -type "Remove" -checkbox $Sender.name
})
}
}
}

View File

@@ -12,7 +12,7 @@ function Invoke-WPFtweaksbutton {
return
}
$Tweaks = (Get-WinUtilCheckBoxes)["WPFTweaks"]
$Tweaks = $sync.selectedTweaks
Set-WinUtilDNS -DNSProvider $sync["WPFchangedns"].text

View File

@@ -12,7 +12,7 @@ function Invoke-WPFundoall {
return
}
$tweaks = (Get-WinUtilCheckBoxes)["WPFtweaks"]
$tweaks = $sync.selectedTweaks
if ($tweaks.count -eq 0) {
$msg = "Please check the tweaks you wish to undo."

View File

@@ -40,6 +40,9 @@ $sync.configs = @{}
$sync.Buttons = [System.Collections.Generic.List[PSObject]]::new()
$sync.ProcessRunning = $false
$sync.selectedApps = [System.Collections.Generic.List[string]]::new()
$sync.selectedTweaks = [System.Collections.Generic.List[string]]::new()
$sync.selectedToggles = [System.Collections.Generic.List[string]]::new()
$sync.selectedFeatures = [System.Collections.Generic.List[string]]::new()
$sync.currentTab = "Install"
$sync.selectedAppsStackPanel
$sync.selectedAppsPopup

100
tools/devdocs-generator.md Normal file
View File

@@ -0,0 +1,100 @@
---
title: "Dev Docs Generator"
description: "How the devdocs-generator.ps1 script works"
---
# Dev Docs Generator
The `devdocs-generator.ps1` script automatically generates Hugo-compatible markdown files for the development documentation. It pulls content directly from the JSON config files and PowerShell function files so the docs never go out of sync.
## When Does It Run?
- Automatically in CI via the GitHub Actions `docs.yaml` workflow before Hugo builds the site
- Triggered when any of these change: `docs/**`, `config/tweaks.json`, `config/feature.json`, `functions/**`
- Can also be run manually with `workflow_dispatch`
## What Does It Do?
### 1. Loads the Data
- Reads `config/tweaks.json` and `config/feature.json`
- Reads all `.ps1` function files from `functions/public/` and `functions/private/`
- Parses `Invoke-WPFButton.ps1` to build a mapping of button names to their function names
### 2. Updates Links in JSON
- Adds or updates a `"link"` property on every entry in both JSON config files
- Each link points to that entry's documentation page on the Hugo site
### 3. Cleans Up Old Docs
- Deletes all `.md` files (except `_index.md`) from `docs/content/dev/tweaks/` and `docs/content/dev/features/`
- This prevents duplicate or orphaned files from previous runs
### 4. Generates Tweak Documentation
For each entry in `tweaks.json` that belongs to a documented category:
- **Button type** entries get the mapped PowerShell function file embedded
- **All other types** get the raw JSON snippet embedded with correct line numbers from the source file
- Entries with **registry changes** get a Registry Changes section added
- Entries with **services** get the `Set-WinUtilService.ps1` function appended
### 5. Generates Feature Documentation
For each entry in `feature.json` that belongs to a documented category:
- **Fixes and Legacy Windows Panels** get the mapped PowerShell function file embedded
- **Features** get the raw JSON snippet embedded with correct line numbers
### 6. Output Format
- Every `.md` file gets Hugo frontmatter with `title` and `description`
- Code blocks use Hugo syntax with filename labels and line numbers
- Files are organized into category subdirectories matching the JSON `category` field
## Documented Categories
The script generates docs for entries in these categories:
- Essential Tweaks
- z__Advanced Tweaks - CAUTION
- Customize Preferences
- Performance Plans
- Features
- Fixes
- Legacy Windows Panels
## File Structure
```
docs/content/dev/
tweaks/
Essential-Tweaks/
z--Advanced-Tweaks---CAUTION/
Customize-Preferences/
Performance-Plans/
features/
Features/
Fixes/
Legacy-Windows-Panels/
```
## How File Names Are Derived
The script strips common prefixes from the JSON key names using the pattern `WPF(WinUtil|Toggle|Features?|Tweaks?|Panel|Fix(es)?)?`. For example:
| JSON Key | Generated File |
|---|---|
| `WPFTweaksHiber` | `Hiber.md` |
| `WPFTweaksDeBloat` | `DeBloat.md` |
| `WPFFeatureshyperv` | `hyperv.md` |
| `WPFPanelDISM` | `DISM.md` |
## Key Points
- The JSON config files are the single source of truth
- Manual edits to generated `.md` files will be overwritten on the next run
- The script does not touch `_index.md` files or `architecture.md`
- Category directories are created automatically if they don't exist
- The `"link"` property added to JSON entries is excluded from the displayed code blocks

View File

@@ -242,7 +242,7 @@ foreach ($itemName in $tweakNames) {
# Hugo frontmatter
$title = $item.Content -replace '"', '\"'
$content = "---`r`ntitle: `"$title`"`r`ndescription: `"`"`r`n---`r`n"
$content = "---`r`ntitle: `"$title`"`r`ndescription: `"`"`r`n---`r`n`r`n"
if ($item.Type -eq "Button") {
# Button-type tweak: embed the mapped PowerShell function
@@ -315,7 +315,7 @@ foreach ($itemName in $featureNames) {
}
$title = $item.Content -replace '"', '\"'
$content = "---`r`ntitle: `"$title`"`r`ndescription: `"`"`r`n---`r`n"
$content = "---`r`ntitle: `"$title`"`r`ndescription: `"`"`r`n---`r`n`r`n"
if ($item.category -eq "Fixes" -or $item.category -eq "Legacy Windows Panels") {
# Embed the PowerShell function file