Private/ReportGlossary.ps1
|
# The chapter "Begriffe": first what Gutcheck is - the principles it keeps and the concepts a # Report is built from, in every Report alike - then the words of the trade a Report uses, # each said once in plain words. # # A Report names a DFS-Namespace or a Primary Refresh Token by the name a Technician finds it # under in Windows and in a search, and not by a German word made up for it; what the name # means stands here, at the end of the Report, for whoever has not met it. Each entry has its # name in the other language beside it where that is another word: a Technician searches in # both. # # Only the terms a Report uses: a list of every word Gutcheck knows is a dictionary nobody # reads. The principles and the concepts are the exception, because every Report rests on # them. function Get-ReportGlossary { <# .SYNOPSIS Every term the glossary knows: its name, its name in the other language, what it is, and the other ways a text writes it. Pure. .DESCRIPTION The name itself is always found, and so is its name in the other language; Also names what else counts as the same term, as a regular expression: "W32Time" is the Windows-Zeitgeber as well. Lang is the language of the other name: English beside a German name, German beside an English one. #> [CmdletBinding()] [OutputType([psobject])] param() $entry = { param($Term, $Other, $Text, $Also, $Lang = 'en') [pscustomobject]@{ Term = $Term; Other = $Other; Lang = $Lang; Text = $Text; Also = $Also } } # The domain & $entry (Get-Text 'Glossary.Term.DfsNamespace') '' (Get-Text 'Glossary.Text.DfsNamespace') '' & $entry (Get-Text 'Glossary.Term.Site') (Get-Text 'Glossary.Other.Site') (Get-Text 'Glossary.Text.Site') 'Standorte' & $entry (Get-Text 'Glossary.Term.Sysvol') '' (Get-Text 'Glossary.Text.Sysvol') '' & $entry (Get-Text 'Glossary.Term.Kerberos') '' (Get-Text 'Glossary.Text.Kerberos') '' & $entry (Get-Text 'Glossary.Term.Ldap') '' (Get-Text 'Glossary.Text.Ldap') 'LDAPS' & $entry (Get-Text 'Glossary.Term.Ntlm') '' (Get-Text 'Glossary.Text.Ntlm') 'NTLMv[12]' & $entry (Get-Text 'Glossary.Term.LmLevel') (Get-Text 'Glossary.Other.LmLevel') (Get-Text 'Glossary.Text.LmLevel') 'LmCompatibilityLevel|NTLM-Stufe|NTLM-Anmeldestufe' & $entry (Get-Text 'Glossary.Term.SecureChannel') (Get-Text 'Glossary.Other.SecureChannel') (Get-Text 'Glossary.Text.SecureChannel') '' & $entry (Get-Text 'Glossary.Term.Forest') (Get-Text 'Glossary.Other.Forest') (Get-Text 'Glossary.Text.Forest') '' & $entry (Get-Text 'Glossary.Term.Gpo') (Get-Text 'Glossary.Other.Gpo') (Get-Text 'Glossary.Text.Gpo') 'Gruppenrichtlinienobjekte?|GPOs?' & $entry (Get-Text 'Glossary.Term.ClientSideExtension') (Get-Text 'Glossary.Other.ClientSideExtension') (Get-Text 'Glossary.Text.ClientSideExtension') 'Client-Side Extensions' 'de' & $entry (Get-Text 'Glossary.Term.DriveMaps') (Get-Text 'Glossary.Other.DriveMaps') (Get-Text 'Glossary.Text.DriveMaps') '' 'de' & $entry (Get-Text 'Glossary.Term.WmiFilter') '' (Get-Text 'Glossary.Text.WmiFilter') '' & $entry (Get-Text 'Glossary.Term.W32Time') (Get-Text 'Glossary.Other.W32Time') (Get-Text 'Glossary.Text.W32Time') 'W32Time|Windows-Zeitgeber|w32tm' & $entry (Get-Text 'Glossary.Term.Ntp') '' (Get-Text 'Glossary.Text.Ntp') '\(S\)NTP' & $entry (Get-Text 'Glossary.Term.Stratum') '' (Get-Text 'Glossary.Text.Stratum') '' & $entry (Get-Text 'Glossary.Term.LeapIndicator') (Get-Text 'Glossary.Other.LeapIndicator') (Get-Text 'Glossary.Text.LeapIndicator') '' # Signing in to Microsoft 365, and Outlook & $entry (Get-Text 'Glossary.Term.EntraId') '' (Get-Text 'Glossary.Text.EntraId') 'Azure AD|Entra' & $entry (Get-Text 'Glossary.Term.Prt') '' (Get-Text 'Glossary.Text.Prt') 'Primary Refresh Token|AzureAdPrt|PRT' & $entry (Get-Text 'Glossary.Term.Wam') '' (Get-Text 'Glossary.Text.Wam') 'WAM' & $entry (Get-Text 'Glossary.Term.AadBroker') '' (Get-Text 'Glossary.Text.AadBroker') 'AAD Broker|BrokerPlugin' & $entry (Get-Text 'Glossary.Term.Drs') (Get-Text 'Glossary.Other.Drs') (Get-Text 'Glossary.Text.Drs') 'Device Registration Service' 'de' & $entry (Get-Text 'Glossary.Term.Adfs') '' (Get-Text 'Glossary.Text.Adfs') 'AD ?FS' & $entry (Get-Text 'Glossary.Term.Mfa') (Get-Text 'Glossary.Other.Mfa') (Get-Text 'Glossary.Text.Mfa') '' & $entry (Get-Text 'Glossary.Term.Autodiscover') (Get-Text 'Glossary.Other.Autodiscover') (Get-Text 'Glossary.Text.Autodiscover') '' 'de' & $entry (Get-Text 'Glossary.Term.Scp') (Get-Text 'Glossary.Other.Scp') (Get-Text 'Glossary.Text.Scp') 'SCPs|Dienstverbindungspunkte' 'de' & $entry (Get-Text 'Glossary.Term.MapiHttp') (Get-Text 'Glossary.Other.MapiHttp') (Get-Text 'Glossary.Text.MapiHttp') 'MAPI' 'de' & $entry (Get-Text 'Glossary.Term.CacheMode') (Get-Text 'Glossary.Other.CacheMode') (Get-Text 'Glossary.Text.CacheMode') 'Cache-Modus' & $entry (Get-Text 'Glossary.Term.Oab') (Get-Text 'Glossary.Other.Oab') (Get-Text 'Glossary.Text.Oab') 'OAB' & $entry (Get-Text 'Glossary.Term.Ost') '' (Get-Text 'Glossary.Text.Ost') 'OST' & $entry (Get-Text 'Glossary.Term.Pst') '' (Get-Text 'Glossary.Text.Pst') 'PST' & $entry (Get-Text 'Glossary.Term.ClickToRun') (Get-Text 'Glossary.Other.ClickToRun') (Get-Text 'Glossary.Text.ClickToRun') '' 'de' # Encryption and certificates & $entry (Get-Text 'Glossary.Term.Tls') '' (Get-Text 'Glossary.Text.Tls') '' & $entry (Get-Text 'Glossary.Term.TlsHandshake') '' (Get-Text 'Glossary.Text.TlsHandshake') 'Handshakes?' & $entry (Get-Text 'Glossary.Term.Schannel') '' (Get-Text 'Glossary.Text.Schannel') 'SChannel' & $entry (Get-Text 'Glossary.Term.CertificateChain') (Get-Text 'Glossary.Other.CertificateChain') (Get-Text 'Glossary.Text.CertificateChain') '' & $entry (Get-Text 'Glossary.Term.Crl') (Get-Text 'Glossary.Other.Crl') (Get-Text 'Glossary.Text.Crl') 'CRL' & $entry (Get-Text 'Glossary.Term.Ctl') (Get-Text 'Glossary.Other.Ctl') (Get-Text 'Glossary.Text.Ctl') 'CTL' 'de' # The network & $entry (Get-Text 'Glossary.Term.Dns') '' (Get-Text 'Glossary.Text.Dns') '' & $entry (Get-Text 'Glossary.Term.Tcp') '' (Get-Text 'Glossary.Text.Tcp') '' & $entry (Get-Text 'Glossary.Term.Udp') '' (Get-Text 'Glossary.Text.Udp') '' & $entry (Get-Text 'Glossary.Term.Quic') '' (Get-Text 'Glossary.Text.Quic') '' & $entry (Get-Text 'Glossary.Term.Port') '' (Get-Text 'Glossary.Text.Port') 'Ports' & $entry (Get-Text 'Glossary.Term.Ping') '' (Get-Text 'Glossary.Text.Ping') '' & $entry (Get-Text 'Glossary.Term.Loss') (Get-Text 'Glossary.Other.Loss') (Get-Text 'Glossary.Text.Loss') 'Paketverluste?' & $entry (Get-Text 'Glossary.Term.Gateway') '' (Get-Text 'Glossary.Text.Gateway') 'Gateways' & $entry (Get-Text 'Glossary.Term.Wlan') (Get-Text 'Glossary.Other.Wlan') (Get-Text 'Glossary.Text.Wlan') 'WiFi' & $entry (Get-Text 'Glossary.Term.Vpn') '' (Get-Text 'Glossary.Text.Vpn') '' & $entry (Get-Text 'Glossary.Term.Proxy') '' (Get-Text 'Glossary.Text.Proxy') 'Proxys|Proxies' & $entry (Get-Text 'Glossary.Term.HttpStatus') (Get-Text 'Glossary.Other.HttpStatus') (Get-Text 'Glossary.Text.HttpStatus') '' & $entry (Get-Text 'Glossary.Term.Smb') '' (Get-Text 'Glossary.Text.Smb') '' & $entry (Get-Text 'Glossary.Term.Share') (Get-Text 'Glossary.Other.Share') (Get-Text 'Glossary.Text.Share') 'Freigaben' & $entry (Get-Text 'Glossary.Term.Multichannel') '' (Get-Text 'Glossary.Text.Multichannel') 'Multichannel' & $entry (Get-Text 'Glossary.Term.Oplocks') (Get-Text 'Glossary.Other.Oplocks') (Get-Text 'Glossary.Text.Oplocks') 'Oplocks' 'de' & $entry (Get-Text 'Glossary.Term.WebDav') '' (Get-Text 'Glossary.Text.WebDav') 'WebClient' & $entry (Get-Text 'Glossary.Term.OfflineFiles') (Get-Text 'Glossary.Other.OfflineFiles') (Get-Text 'Glossary.Text.OfflineFiles') '' & $entry (Get-Text 'Glossary.Term.FolderRedirection') (Get-Text 'Glossary.Other.FolderRedirection') (Get-Text 'Glossary.Text.FolderRedirection') '' & $entry (Get-Text 'Glossary.Term.Dhcp') '' (Get-Text 'Glossary.Text.Dhcp') '' & $entry (Get-Text 'Glossary.Term.Subnet') (Get-Text 'Glossary.Other.Subnet') (Get-Text 'Glossary.Text.Subnet') 'Subnetze' & $entry (Get-Text 'Glossary.Term.Apipa') '' (Get-Text 'Glossary.Text.Apipa') '169\.254' & $entry (Get-Text 'Glossary.Term.DnsSuffix') '' (Get-Text 'Glossary.Text.DnsSuffix') 'Suffix-Suchliste' & $entry (Get-Text 'Glossary.Term.SrvRecord') (Get-Text 'Glossary.Other.SrvRecord') (Get-Text 'Glossary.Text.SrvRecord') '' & $entry (Get-Text 'Glossary.Term.Ncsi') '' (Get-Text 'Glossary.Text.Ncsi') '' & $entry (Get-Text 'Glossary.Term.WinHttpProxy') '' (Get-Text 'Glossary.Text.WinHttpProxy') '' & $entry (Get-Text 'Glossary.Term.Pac') '' (Get-Text 'Glossary.Text.Pac') '' & $entry (Get-Text 'Glossary.Term.InterruptModeration') (Get-Text 'Glossary.Other.InterruptModeration') (Get-Text 'Glossary.Text.InterruptModeration') '' & $entry (Get-Text 'Glossary.Term.Bits') '' (Get-Text 'Glossary.Text.Bits') '' & $entry (Get-Text 'Glossary.Term.Rpc') '' (Get-Text 'Glossary.Text.Rpc') '' & $entry (Get-Text 'Glossary.Term.Rdp') (Get-Text 'Glossary.Other.Rdp') (Get-Text 'Glossary.Text.Rdp') 'Remotedesktops?|RDP' & $entry (Get-Text 'Glossary.Term.Sip') '' (Get-Text 'Glossary.Text.Sip') '' # Windows itself & $entry (Get-Text 'Glossary.Term.Registry') (Get-Text 'Glossary.Other.Registry') (Get-Text 'Glossary.Text.Registry') 'HKLM|HKCU|HKU' & $entry (Get-Text 'Glossary.Term.ServiceControlManager') (Get-Text 'Glossary.Other.ServiceControlManager') (Get-Text 'Glossary.Text.ServiceControlManager') '' 'de' & $entry (Get-Text 'Glossary.Term.Spooler') (Get-Text 'Glossary.Other.Spooler') (Get-Text 'Glossary.Text.Spooler') 'Spooler' & $entry (Get-Text 'Glossary.Term.FastStartup') (Get-Text 'Glossary.Other.FastStartup') (Get-Text 'Glossary.Text.FastStartup') '' & $entry (Get-Text 'Glossary.Term.ComponentStore') (Get-Text 'Glossary.Other.ComponentStore') (Get-Text 'Glossary.Text.ComponentStore') 'WinSxS' & $entry (Get-Text 'Glossary.Term.Odbc') (Get-Text 'Glossary.Other.Odbc') (Get-Text 'Glossary.Text.Odbc') 'ODBC|DSN' # Crashes and the memory & $entry (Get-Text 'Glossary.Term.Bluescreen') '' (Get-Text 'Glossary.Text.Bluescreen') 'Bluescreens|Stop-Codes?|Minidumps?' & $entry (Get-Text 'Glossary.Term.LiveKernel') '' (Get-Text 'Glossary.Text.LiveKernel') 'Live-Kernel|LiveKernel\w*' & $entry (Get-Text 'Glossary.Term.Whea') '' (Get-Text 'Glossary.Text.Whea') '' & $entry (Get-Text 'Glossary.Term.Win32k') '' (Get-Text 'Glossary.Text.Win32k') '' & $entry (Get-Text 'Glossary.Term.AccessViolation') (Get-Text 'Glossary.Other.AccessViolation') (Get-Text 'Glossary.Text.AccessViolation') '' & $entry (Get-Text 'Glossary.Term.StackOverflow') (Get-Text 'Glossary.Other.StackOverflow') (Get-Text 'Glossary.Text.StackOverflow') '' 'de' & $entry (Get-Text 'Glossary.Term.StackBufferOverrun') '' (Get-Text 'Glossary.Text.StackBufferOverrun') 'Stack Buffer Overrun|Fail-Fast' & $entry (Get-Text 'Glossary.Term.UserGdi') (Get-Text 'Glossary.Other.UserGdi') (Get-Text 'Glossary.Text.UserGdi') 'USER-Objekte\w*|GDI-Objekte\w*' & $entry (Get-Text 'Glossary.Term.WorkingSet') (Get-Text 'Glossary.Other.WorkingSet') (Get-Text 'Glossary.Text.WorkingSet') '' & $entry (Get-Text 'Glossary.Term.Commit') (Get-Text 'Glossary.Other.Commit') (Get-Text 'Glossary.Text.Commit') 'Zugesichert\w*' & $entry (Get-Text 'Glossary.Term.PageFile') (Get-Text 'Glossary.Other.PageFile') (Get-Text 'Glossary.Text.PageFile') '' & $entry (Get-Text 'Glossary.Term.Smart') '' (Get-Text 'Glossary.Text.Smart') 'SMART' & $entry (Get-Text 'Glossary.Term.AcpiThermalZone') '' (Get-Text 'Glossary.Text.AcpiThermalZone') 'ACPI Thermal Zones' } function Get-ReportPrinciple { <# .SYNOPSIS What Gutcheck holds to, each in one sentence a Technician can check the Report against. Pure. #> [CmdletBinding()] [OutputType([string])] param() Get-Text 'Glossary.Principle.AsksOnly' Get-Text 'Glossary.Principle.StateNotActivity' Get-Text 'Glossary.Principle.Confidential' Get-Text 'Glossary.Principle.NotMeasured' Get-Text 'Glossary.Principle.LogReach' Get-Text 'Glossary.Principle.CodeMeaning' Get-Text 'Glossary.Principle.Lead' Get-Text 'Glossary.Principle.OneServer' Get-Text 'Glossary.Principle.Service' Get-Text 'Glossary.Principle.Definitions' } function Get-ReportConcept { <# .SYNOPSIS The concepts a Report is built from, by the word the Report uses for each, with the English word of Gutcheck's own language beside it. Pure. .DESCRIPTION In every Report, and never looked for in its text: "Befund" and "Server" stand everywhere, and a page of dotted words is a page nobody reads. What a reader never sees - how a Check is built inside - has no entry. #> [CmdletBinding()] [OutputType([psobject])] param() $entry = { param($Term, $Other, $Text) [pscustomobject]@{ Term = $Term; Other = $Other; Lang = 'en'; Text = $Text; Also = '' } } # The Run, and what it looks at & $entry (Get-Text 'Glossary.Concept.Term.Run') (Get-Text 'Glossary.Concept.Other.Run') (Get-Text 'Glossary.Concept.Text.Run') & $entry (Get-Text 'Glossary.Concept.Term.Machine') (Get-Text 'Glossary.Concept.Other.Machine') (Get-Text 'Glossary.Concept.Text.Machine') & $entry (Get-Text 'Glossary.Concept.Term.User') (Get-Text 'Glossary.Concept.Other.User') (Get-Text 'Glossary.Concept.Text.User') & $entry (Get-Text 'Glossary.Concept.Term.Session') (Get-Text 'Glossary.Concept.Other.Session') (Get-Text 'Glossary.Concept.Text.Session') & $entry (Get-Text 'Glossary.Concept.Term.UserProfile') (Get-Text 'Glossary.Concept.Other.UserProfile') (Get-Text 'Glossary.Concept.Text.UserProfile') & $entry (Get-Text 'Glossary.Concept.Term.Situation') (Get-Text 'Glossary.Concept.Other.Situation') (Get-Text 'Glossary.Concept.Text.Situation') & $entry (Get-Text 'Glossary.Concept.Term.Privilege') (Get-Text 'Glossary.Concept.Other.Privilege') (Get-Text 'Glossary.Concept.Text.Privilege') & $entry (Get-Text 'Glossary.Concept.Term.Check') (Get-Text 'Glossary.Concept.Other.Check') (Get-Text 'Glossary.Concept.Text.Check') & $entry (Get-Text 'Glossary.Concept.Term.Definition') (Get-Text 'Glossary.Concept.Other.Definition') (Get-Text 'Glossary.Concept.Text.Definition') & $entry (Get-Text 'Glossary.Concept.Term.Scope') (Get-Text 'Glossary.Concept.Other.Scope') (Get-Text 'Glossary.Concept.Text.Scope') # What a Run produces & $entry (Get-Text 'Glossary.Concept.Term.Finding') (Get-Text 'Glossary.Concept.Other.Finding') (Get-Text 'Glossary.Concept.Text.Finding') & $entry (Get-Text 'Glossary.Concept.Term.Severity') (Get-Text 'Glossary.Concept.Other.Severity') (Get-Text 'Glossary.Concept.Text.Severity') & $entry (Get-Text 'Glossary.Concept.Term.Category') (Get-Text 'Glossary.Concept.Other.Category') (Get-Text 'Glossary.Concept.Text.Category') & $entry (Get-Text 'Glossary.Concept.Term.App') (Get-Text 'Glossary.Concept.Other.App') (Get-Text 'Glossary.Concept.Text.App') & $entry (Get-Text 'Glossary.Concept.Term.Meaning') (Get-Text 'Glossary.Concept.Other.Meaning') (Get-Text 'Glossary.Concept.Text.Meaning') & $entry (Get-Text 'Glossary.Concept.Term.Hint') (Get-Text 'Glossary.Concept.Other.Hint') (Get-Text 'Glossary.Concept.Text.Hint') & $entry (Get-Text 'Glossary.Concept.Term.Lead') (Get-Text 'Glossary.Concept.Other.Lead') (Get-Text 'Glossary.Concept.Text.Lead') & $entry (Get-Text 'Glossary.Concept.Term.Reference') (Get-Text 'Glossary.Concept.Other.Reference') (Get-Text 'Glossary.Concept.Text.Reference') & $entry (Get-Text 'Glossary.Concept.Term.Evidence') (Get-Text 'Glossary.Concept.Other.Evidence') (Get-Text 'Glossary.Concept.Text.Evidence') & $entry (Get-Text 'Glossary.Concept.Term.Section') (Get-Text 'Glossary.Concept.Other.Section') (Get-Text 'Glossary.Concept.Text.Section') & $entry (Get-Text 'Glossary.Concept.Term.Change') (Get-Text 'Glossary.Concept.Other.Change') (Get-Text 'Glossary.Concept.Text.Change') # The network & $entry (Get-Text 'Glossary.Concept.Term.Server') '' (Get-Text 'Glossary.Concept.Text.Server') & $entry (Get-Text 'Glossary.Concept.Term.Service') (Get-Text 'Glossary.Concept.Other.Service') (Get-Text 'Glossary.Concept.Text.Service') & $entry (Get-Text 'Glossary.Concept.Term.WindowsService') (Get-Text 'Glossary.Concept.Other.WindowsService') (Get-Text 'Glossary.Concept.Text.WindowsService') & $entry (Get-Text 'Glossary.Concept.Term.Printer') (Get-Text 'Glossary.Concept.Other.Printer') (Get-Text 'Glossary.Concept.Text.Printer') & $entry (Get-Text 'Glossary.Concept.Term.Link') (Get-Text 'Glossary.Concept.Other.Link') (Get-Text 'Glossary.Concept.Text.Link') & $entry (Get-Text 'Glossary.Concept.Term.Measurement') (Get-Text 'Glossary.Concept.Other.Measurement') (Get-Text 'Glossary.Concept.Text.Measurement') & $entry (Get-Text 'Glossary.Concept.Term.TimedEvent') (Get-Text 'Glossary.Concept.Other.TimedEvent') (Get-Text 'Glossary.Concept.Text.TimedEvent') & $entry (Get-Text 'Glossary.Concept.Term.LogReach') '' (Get-Text 'Glossary.Concept.Text.LogReach') & $entry (Get-Text 'Glossary.Concept.Term.BigPicture') '' (Get-Text 'Glossary.Concept.Text.BigPicture') } function Select-ReportGlossary { <# .SYNOPSIS The terms a text uses, in alphabetical order. Pure. .DESCRIPTION A term counts where it stands as a word of its own: "OST" in "Outlook-OST", and not in "HOST". By its name, by its name in the other language, or as Also writes it. Read in one pass, however long the text: a Report with its evidence is megabytes. #> [CmdletBinding()] [OutputType([psobject])] param([AllowNull()][AllowEmptyString()][string]$Text, [AllowNull()][AllowEmptyCollection()]$Entry) $entries = @($Entry | Where-Object { $_ }) if (-not $Text -or -not $entries.Count) { return } # The longest name first: of two that begin alike at one place the first is taken, and # "DNS-Suffix" is no "DNS" with something behind it. $alternatives = foreach ($i in (Get-ReportGlossaryOrder -Entry $entries)) { $ways = @([regex]::Escape("$($entries[$i].Term)")) if ("$($entries[$i].Other)") { $ways += [regex]::Escape("$($entries[$i].Other)") } if ("$($entries[$i].Also)") { $ways += "$($entries[$i].Also)" } '(?<t{0}>{1})' -f $i, ($ways -join '|') } $pattern = [regex]('(?<![\w])(?:' + ($alternatives -join '|') + ')(?![\w])') $found = New-Object 'System.Collections.Generic.HashSet[int]' foreach ($match in $pattern.Matches($Text)) { for ($i = 0; $i -lt $entries.Count; $i++) { if ($match.Groups["t$i"].Success) { $null = $found.Add($i); break } } if ($found.Count -eq $entries.Count) { break } } $picked = @($found | ForEach-Object { $entries[$_] }) # Ordinal, so that the order is the same on every machine whatever its language. [array]::Sort([object[]]$picked, [Comparison[object]] { param($a, $b) [StringComparer]::OrdinalIgnoreCase.Compare("$($a.Term)", "$($b.Term)") }) $picked } function Get-ReportGlossaryOrder { <# .SYNOPSIS The indexes of the entries, the one with the longest name first, and of two as long the earlier first. Pure. #> [CmdletBinding()] [OutputType([int])] param([AllowNull()][AllowEmptyCollection()]$Entry) $entries = @($Entry) $order = [int[]]@(0..($entries.Count - 1) | Where-Object { $entries.Count }) [array]::Sort($order, [Comparison[int]] { param($a, $b) $byLength = "$($entries[$b].Term)".Length.CompareTo("$($entries[$a].Term)".Length) if ($byLength) { $byLength } else { $a.CompareTo($b) } }) $order } function ConvertTo-ReportGlossaryText { <# .SYNOPSIS What a reader reads of a piece of the Report, without its markup. Pure. #> [CmdletBinding()] [OutputType([string])] param([AllowNull()][AllowEmptyString()][string]$Html) if (-not $Html) { return '' } [System.Net.WebUtility]::HtmlDecode(($Html -replace '<[^>]*>', ' ')) } function ConvertTo-ReportGlossaryHtml { <# .SYNOPSIS The terms as a list, each with its name in the other language and what it is. Nothing where there is none. Pure. #> [CmdletBinding()] [OutputType([string])] param([AllowNull()][AllowEmptyCollection()]$Entry, [string]$Id = '') $entries = @($Entry | Where-Object { $_ }) if (-not $entries.Count) { return '' } $idAttribute = if ($Id) { ' id="{0}"' -f $Id } else { '' } '<dl class="glossary"{0}>{1}</dl>' -f $idAttribute, (($entries | ForEach-Object { $other = '' if ("$($_.Other)") { $lang = if ("$($_.Lang)" -eq 'de') { 'de' } else { 'en' } $other = ' <span class="other" lang="{0}">{1}</span>' -f $lang, (ConvertTo-HtmlText "$($_.Other)") } '<div><dt>{0}{1}</dt><dd>{2}</dd></div>' -f (ConvertTo-HtmlText "$($_.Term)"), $other, (ConvertTo-HtmlText "$($_.Text)") }) -join '') } function ConvertTo-ReportGlossaryChapterHtml { <# .SYNOPSIS The chapter "Begriffe": what Gutcheck holds to and the concepts of a Report, then the terms this Report uses. In every Report. Pure. .DESCRIPTION Counted by the entries it explains, the concepts and the terms together, as the search counts what it finds among them. A Report that uses no term says so where the terms would stand. #> [CmdletBinding()] [OutputType([string])] param([AllowNull()][AllowEmptyCollection()]$Term) $terms = @($Term | Where-Object { $_ }) $concepts = @(Get-ReportConcept) $principles = (@(Get-ReportPrinciple) | ForEach-Object { '<li>{0}</li>' -f (ConvertTo-HtmlText $_) }) -join '' $termList = if ($terms.Count) { ConvertTo-ReportGlossaryHtml -Entry $terms -Id 'glossary-terms' } else { '<p class="none">{0}</p>' -f (ConvertTo-HtmlText (Get-Text 'Report.Glossary.NoTerms')) } ("<section data-chapter=`"glossary`" id=`"ch-glossary`">`n<h2>{0} · {1}</h2>`n" + "<div class=`"glossblock`" id=`"glossary-gutcheck`"><h3 class=`"glosshead`">{2}</h3>`n<p class=`"glossnote`">{3}</p>`n" + "<h4 class=`"glosssub`">{4}</h4>`n<ol class=`"principles`">{5}</ol>`n<h4 class=`"glosssub`">{6}</h4>`n{7}</div>`n" + "<div class=`"glossblock`"><h3 class=`"glosshead`">{8}</h3>`n<p class=`"glossnote`">{9}</p>`n{10}</div>`n</section>") -f ` (ConvertTo-HtmlText (Get-Text 'Report.Heading.Glossary')), ($concepts.Count + $terms.Count), (ConvertTo-HtmlText (Get-Text 'Report.Glossary.Gutcheck')), (ConvertTo-HtmlText (Get-Text 'Report.Glossary.GutcheckIntro')), (ConvertTo-HtmlText (Get-Text 'Report.Glossary.Principles')), $principles, (ConvertTo-HtmlText (Get-Text 'Report.Glossary.Concepts')), (ConvertTo-ReportGlossaryHtml -Entry $concepts -Id 'glossary-concepts'), (ConvertTo-HtmlText (Get-Text 'Report.Glossary.Terms')), (ConvertTo-HtmlText (Get-Text 'Report.Glossary.Intro')), $termList } function ConvertTo-ReportGlossaryData { <# .SYNOPSIS The terms a Report uses, as data for its script: each with its name, its name in the other language, what it is, and what it looks like in a text as a JavaScript pattern. Nothing where there is none. Pure. .DESCRIPTION So that a term is explained where it stands, and not only at the end. A pattern of the glossary is written for .NET and for JavaScript alike; only the names themselves are escaped here, for JavaScript, whose escapes are fewer. #> [CmdletBinding()] [OutputType([string])] param([AllowNull()][AllowEmptyCollection()]$Entry) $entries = @($Entry | Where-Object { $_ }) if (-not $entries.Count) { return '' } $escape = { param([string]$Name) [regex]::Replace($Name, '[\\^$.*+?()\[\]{}|/]', '\$0') } # The longest name first, as Select-ReportGlossary reads them: the script takes the first # that fits. $data = @(Get-ReportGlossaryOrder -Entry $entries | ForEach-Object { $entries[$_] } | ForEach-Object { $pattern = & $escape "$($_.Term)" if ("$($_.Other)") { $pattern = '{0}|{1}' -f $pattern, (& $escape "$($_.Other)") } if ("$($_.Also)") { $pattern = '{0}|{1}' -f $pattern, "$($_.Also)" } [ordered]@{ t = "$($_.Term)"; o = "$($_.Other)"; x = "$($_.Text)"; p = $pattern } }) # Inside a script element nothing may close it. $json = (ConvertTo-Json -InputObject $data -Compress -Depth 3) -replace '<', '\u003c' '<script type="application/json" id="terms">{0}</script>' -f $json } |