Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
permissions:
checks: write
pull-requests: write
contents: read
issues: write
jobs:
ci:
name: Continuous Integration
uses: PSInclusive/.github/.github/workflows/ModuleCI.yml@main
105 changes: 105 additions & 0 deletions Accessibility/Private/Get-ColorBlindPaletteData.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Okabe-Ito palette: peer-reviewed, safe across all common colorblindness types.

Check warning on line 1 in Accessibility/Private/Get-ColorBlindPaletteData.ps1

View workflow job for this annotation

GitHub Actions / Continuous Integration / Run Linters

Unknown word (Okabe) Suggestions: (kobe, okas, okay, okie, Okie)
# Source: https://jfly.uni-koeln.de/color/
$script:OKABE_ITO = @{

Check warning on line 3 in Accessibility/Private/Get-ColorBlindPaletteData.ps1

View workflow job for this annotation

GitHub Actions / Continuous Integration / Run Linters

Unknown word (OKABE) Suggestions: (kobe, okas, okay, okie, oobe)
Black = @{ R = 0; G = 0; B = 0 }
Orange = @{ R = 230; G = 159; B = 0 }
SkyBlue = @{ R = 86; G = 180; B = 233 }
BluishGreen = @{ R = 0; G = 158; B = 115 }
Yellow = @{ R = 240; G = 228; B = 66 }
Blue = @{ R = 0; G = 114; B = 178 }
Vermillion = @{ R = 213; G = 94; B = 0 }

Check warning on line 10 in Accessibility/Private/Get-ColorBlindPaletteData.ps1

View workflow job for this annotation

GitHub Actions / Continuous Integration / Run Linters

Misspelled word (Vermillion) Suggestions: (vermilion*, vermilion's, vermination)
ReddishPurple = @{ R = 204; G = 121; B = 167 }
}

function Get-ColorBlindPaletteData {
<#
.SYNOPSIS
Returns the RGB color table for a named color blind profile.

.DESCRIPTION
Returns a hashtable of named color entries (each with R, G, B keys) for the specified
color blindness profile. All profiles are derived from the Okabe-Ito palette, adjusted

Check warning on line 21 in Accessibility/Private/Get-ColorBlindPaletteData.ps1

View workflow job for this annotation

GitHub Actions / Continuous Integration / Run Linters

Unknown word (Okabe) Suggestions: (kobe, okas, okay, okie, Okie)
per the specific perceptual needs of each condition.

.PARAMETER ProfileType
The color blindness profile to retrieve. Valid values: Deuteranopia, Protanopia,
Tritanopia, Achromatopsia, AccessibleDefault.

Check warning on line 26 in Accessibility/Private/Get-ColorBlindPaletteData.ps1

View workflow job for this annotation

GitHub Actions / Continuous Integration / Run Linters

Unknown word (Achromatopsia) Suggestions: (achromatous)

.EXAMPLE
Get-ColorBlindPaletteData -ProfileType Deuteranopia
#>
param (
[Parameter(Mandatory = $true)]
[ValidateSet('Deuteranopia', 'Protanopia', 'Tritanopia', 'Achromatopsia', 'AccessibleDefault')]

Check warning on line 33 in Accessibility/Private/Get-ColorBlindPaletteData.ps1

View workflow job for this annotation

GitHub Actions / Continuous Integration / Run Linters

Unknown word (Achromatopsia) Suggestions: (achromatous)
[string]$ProfileType
)

switch ($ProfileType) {
'Deuteranopia' {
# Red-green deficiency (most common). Maximize blue/orange/yellow contrast.
# Red and green are shifted to orange and blue respectively.
@{
Error = $script:OKABE_ITO.Vermillion # Vermillion (not red)

Check warning on line 42 in Accessibility/Private/Get-ColorBlindPaletteData.ps1

View workflow job for this annotation

GitHub Actions / Continuous Integration / Run Linters

Misspelled word (Vermillion) Suggestions: (vermilion*, vermilion's, vermination)

Check warning on line 42 in Accessibility/Private/Get-ColorBlindPaletteData.ps1

View workflow job for this annotation

GitHub Actions / Continuous Integration / Run Linters

Misspelled word (Vermillion) Suggestions: (vermilion*, vermilion's, vermination)

Check warning on line 42 in Accessibility/Private/Get-ColorBlindPaletteData.ps1

View workflow job for this annotation

GitHub Actions / Continuous Integration / Run Linters

Unknown word (OKABE) Suggestions: (kobe, okas, okay, okie, oobe)
Warning = $script:OKABE_ITO.Orange # Orange

Check warning on line 43 in Accessibility/Private/Get-ColorBlindPaletteData.ps1

View workflow job for this annotation

GitHub Actions / Continuous Integration / Run Linters

Unknown word (OKABE) Suggestions: (kobe, okas, okay, okie, oobe)
Success = $script:OKABE_ITO.Blue # Blue (not green)
Info = $script:OKABE_ITO.SkyBlue # Sky Blue
Highlight = $script:OKABE_ITO.Yellow # Yellow
Accent = $script:OKABE_ITO.ReddishPurple # Reddish Purple
Text = $script:OKABE_ITO.Black # Black
Muted = @{ R = 120; G = 120; B = 120 } # Mid-gray (not part of Okabe-Ito)
}
}
'Protanopia' {
# Red-weak (cannot perceive red). Red-range hues shifted further toward orange/yellow.
@{
Error = @{ R = 230; G = 159; B = 0 } # Orange (red is invisible)
Warning = @{ R = 240; G = 228; B = 66 } # Yellow
Success = @{ R = 0; G = 114; B = 178 } # Blue
Info = @{ R = 86; G = 180; B = 233 } # Sky Blue
Highlight = @{ R = 204; G = 121; B = 167 } # Reddish Purple
Accent = @{ R = 0; G = 158; B = 115 } # Bluish Green
Text = @{ R = 0; G = 0; B = 0 } # Black
Muted = @{ R = 120; G = 120; B = 120 } # Mid-gray
}
}
'Tritanopia' {
# Blue-yellow deficiency. Shift to red/green contrast; replace blue with high-contrast cyan.
@{
Error = @{ R = 213; G = 94; B = 0 } # Vermillion
Warning = @{ R = 204; G = 121; B = 167 } # Reddish Purple (not yellow)
Success = @{ R = 0; G = 158; B = 115 } # Bluish Green
Info = @{ R = 0; G = 200; B = 200 } # Cyan (high contrast, not pure blue)
Highlight = @{ R = 255; G = 100; B = 100 } # Light Red (visible to tritanopes)
Accent = @{ R = 180; G = 60; B = 60 } # Dark Red
Text = @{ R = 0; G = 0; B = 0 } # Black
Muted = @{ R = 120; G = 120; B = 120 } # Mid-gray
}
}
'Achromatopsia' {
# Full colorblindness. High-contrast grayscale ladder designed for strong separation between steps.
@{
Error = @{ R = 30; G = 30; B = 30 } # Near-black (on white bg)
Warning = @{ R = 80; G = 80; B = 80 } # Dark gray
Success = @{ R = 50; G = 50; B = 50 } # Dark gray variant
Info = @{ R = 110; G = 110; B = 110 } # Medium gray
Highlight = @{ R = 230; G = 230; B = 230 } # Near-white
Accent = @{ R = 0; G = 0; B = 0 } # Black
Text = @{ R = 0; G = 0; B = 0 } # Black
Muted = @{ R = 160; G = 160; B = 160 } # Light gray
}
}
'AccessibleDefault' {
# Okabe-Ito as-is: a safe general baseline for users unsure of their type.
@{
Error = @{ R = 213; G = 94; B = 0 } # Vermillion
Warning = @{ R = 230; G = 159; B = 0 } # Orange
Success = @{ R = 0; G = 158; B = 115 } # Bluish Green
Info = @{ R = 86; G = 180; B = 233 } # Sky Blue
Highlight = @{ R = 240; G = 228; B = 66 } # Yellow
Accent = @{ R = 0; G = 114; B = 178 } # Blue
Text = @{ R = 0; G = 0; B = 0 } # Black
Muted = @{ R = 120; G = 120; B = 120 } # Mid-gray
}
}
}
}
34 changes: 34 additions & 0 deletions Accessibility/Private/Get-ContrastRatio.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
function Get-ContrastRatio {
<#
.SYNOPSIS
Calculates the WCAG contrast ratio between two relative luminance values.

.DESCRIPTION
Implements the W3C WCAG 2.1 contrast ratio formula. Returns a ratio between 1:1
(no contrast) and 21:1 (maximum contrast, black on white).

.PARAMETER Luminance1
Relative luminance of the first color (0.0 to 1.0).

.PARAMETER Luminance2
Relative luminance of the second color (0.0 to 1.0).

.EXAMPLE
Get-ContrastRatio -Luminance1 1.0 -Luminance2 0.0
# Returns 21.0 (white on black)

.NOTES
https://www.w3.org/TR/WCAG21/#dfn-contrast-ratio
#>
param (
[Parameter(Mandatory = $true)]
[double]$Luminance1,
[Parameter(Mandatory = $true)]
[double]$Luminance2
)

$lighter = [Math]::Max($Luminance1, $Luminance2)
$darker = [Math]::Min($Luminance1, $Luminance2)

return ($lighter + 0.05) / ($darker + 0.05)
}
52 changes: 52 additions & 0 deletions Accessibility/Private/Get-RelativeLuminance.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
function Get-RelativeLuminance {
<#
.SYNOPSIS
Calculates the relative luminance of an RGB color per the W3C WCAG 2.1 formula.

.DESCRIPTION
Implements the W3C relative luminance formula required for WCAG contrast ratio
calculations. Returns a value between 0 (black) and 1 (white).

.PARAMETER R
Red channel value (0-255).

.PARAMETER G
Green channel value (0-255).

.PARAMETER B
Blue channel value (0-255).

.EXAMPLE
Get-RelativeLuminance -R 0 -G 0 -B 0
# Returns 0 (black)

.EXAMPLE
Get-RelativeLuminance -R 255 -G 255 -B 255
# Returns 1 (white)

.NOTES
https://www.w3.org/TR/WCAG21/#dfn-relative-luminance
#>
param (
[Parameter(Mandatory = $true)]
[ValidateRange(0, 255)]
[int]$R,
[Parameter(Mandatory = $true)]
[ValidateRange(0, 255)]
[int]$G,
[Parameter(Mandatory = $true)]
[ValidateRange(0, 255)]
[int]$B
)

$channels = @($R / 255.0, $G / 255.0, $B / 255.0)
$linearized = $channels | ForEach-Object {
if ($_ -le 0.04045) {
$_ / 12.92
} else {
[Math]::Pow(($_ + 0.055) / 1.055, 2.4)
}
}

return (0.2126 * $linearized[0]) + (0.7152 * $linearized[1]) + (0.0722 * $linearized[2])
}
51 changes: 51 additions & 0 deletions Accessibility/Public/ConvertTo-PlainText.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
function ConvertTo-PlainText {
<#
.SYNOPSIS
Strips common ANSI color/style escape codes and PSStyle formatting from a string.

.DESCRIPTION
Removes common ANSI/VT100 SGR-style escape sequences (colors, bold, italic, etc.)
from text, returning clean plain text without those decorations. Useful for
preparing terminal output for screen readers, plain-text logging, or piping to
tools that do not handle such escape codes.

Supports pipeline input.

.PARAMETER InputText
The text string to strip of ANSI color/style escape codes.

.EXAMPLE
ConvertTo-PlainText -InputText "$($PSStyle.Bold)Hello$($PSStyle.BoldOff) World"

Returns 'Hello World' with no formatting.

.EXAMPLE
ConvertTo-Bionic "The quick brown fox" | ConvertTo-PlainText

Converts text to bionic format then strips common ANSI color/style escape sequences
for screen reader use.

.EXAMPLE
Get-Content .\log.txt -Raw | ConvertTo-PlainText

Strips common ANSI color/style escape codes from a log file that may contain
colored output.

.NOTES
https://www.w3.org/WAI/WCAG21/Techniques/general/G166
#>
[CmdletBinding()]
param (
[Parameter(
Mandatory = $true,
ValueFromPipeline = $true,
Position = 0
)]
[string]$InputText
)

process {
# Matches ESC (0x1B) followed by [ and any sequence of parameter/intermediate bytes and a final byte
$InputText -replace '\x1B\[[0-9;]*[mABCDEFGHJKSTfhilmnprsu]', ''
}
}
40 changes: 40 additions & 0 deletions Accessibility/Public/Disable-ScreenReaderMode.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
function Disable-ScreenReaderMode {
<#
.SYNOPSIS
Restores normal ANSI-formatted terminal output after screen reader mode.

.DESCRIPTION
Clears the screen reader mode flag set by Enable-ScreenReaderMode, allowing
Accessibility module commands to resume producing colored and styled terminal
output using ANSI escape sequences.

.EXAMPLE
Disable-ScreenReaderMode

Deactivates screen reader mode and restores ANSI-formatted output.

.EXAMPLE
Enable-ScreenReaderMode
ConvertTo-Bionic "Example text"
Disable-ScreenReaderMode

Temporarily uses screen reader mode for one operation, then restores normal output.

.NOTES
https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast
#>
[CmdletBinding()]
param ()

$script:ScreenReaderMode = $false

if ($script:PreviousOutputRendering) {
$PSStyle.OutputRendering = $script:PreviousOutputRendering
Write-Verbose "Screen reader mode disabled. Previous output rendering restored."
}
else {
# Fallback if no previous output rendering mode was saved.
$PSStyle.OutputRendering = [System.Management.Automation.OutputRendering]::Host
Write-Verbose "Screen reader mode disabled. Output rendering set to Host."
}
}
40 changes: 40 additions & 0 deletions Accessibility/Public/Enable-ScreenReaderMode.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
function Enable-ScreenReaderMode {
<#
.SYNOPSIS
Optimizes terminal output for screen reader assistive technology.

.DESCRIPTION
Sets a module-wide flag that signals all Accessibility module commands to produce
output that is compatible with screen readers: no ANSI color codes, no box-drawing
characters, simplified structure, and plain descriptive text only.

Use Disable-ScreenReaderMode to return to normal output mode.

.EXAMPLE
Enable-ScreenReaderMode

Activates screen reader-friendly output mode for all Accessibility module commands.

.EXAMPLE
Enable-ScreenReaderMode
ConvertTo-Bionic "The quick brown fox jumped over the lazy dog."

Enables screen reader mode then runs a bionic conversion. Output will contain no
ANSI bold codes, just the plain text result.

.NOTES
https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast
#>
[CmdletBinding()]
param ()

$script:ScreenReaderMode = $true

if (-not (Get-Variable -Name PreviousOutputRendering -Scope Script -ErrorAction SilentlyContinue)) {
$script:PreviousOutputRendering = $PSStyle.OutputRendering
}

$PSStyle.OutputRendering = [System.Management.Automation.OutputRendering]::PlainText

Write-Verbose "Screen reader mode enabled. ANSI output suppressed."
}
41 changes: 41 additions & 0 deletions Accessibility/Public/Export-AccessibilityProfile.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
function Export-AccessibilityProfile {
<#
.SYNOPSIS
Exports the current accessibility settings to a JSON file.

.DESCRIPTION
Serializes all active accessibility settings (color blind profile, screen reader mode,
output rendering) to a JSON file at the specified path. The file can later be restored
using Import-AccessibilityProfile, making it easy to share configurations or persist
them outside of $PROFILE.

.PARAMETER Path
The file path where the JSON settings file should be written.

.EXAMPLE
Export-AccessibilityProfile -Path "$HOME\accessibility-settings.json"

Exports the current settings to a JSON file in the user's home directory.

.EXAMPLE
Set-ColorBlindProfile -ProfileType Deuteranopia
Export-AccessibilityProfile -Path ".\my-profile.json"

Applies a color profile then exports it to a local file.

.NOTES
https://www.w3.org/WAI/WCAG21/Understanding/
#>
[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$Path
)

$profile = Get-AccessibilityProfile

if ($PSCmdlet.ShouldProcess($Path, "Export accessibility settings")) {
$profile | ConvertTo-Json -Depth 5 | Set-Content -Path $Path -Encoding UTF8
Write-Verbose "Accessibility settings exported to: $Path"
}
}
Loading
Loading