XurrentHelpers.psm1
|
#Region './Private/Get-Section.ps1' -1 function Get-Section { <# .SYNOPSIS Extracts the body of a named Markdown H2 section. .DESCRIPTION Returns the trimmed text body of a ## Heading section from a Markdown string. Matches content from the heading line to the next same-level ## heading or end of string. Returns an empty string when the requested section is not found. .PARAMETER Content The full Markdown document content as a string. .PARAMETER Heading The section heading to search for, without the leading ## prefix. .EXAMPLE Get-Section -Content $markdown -Heading 'Description' #> [CmdletBinding()] [OutputType([string])] param ( [Parameter(Mandatory = $true)] [string] $Content, [Parameter(Mandatory = $true)] [string] $Heading ) process { $pattern = "(?ms)^##\s+$([regex]::Escape($Heading))\s*$\r?\n(.*?)(?=\r?\n^##\s+|\z)" if ($Content -match $pattern) { return $Matches[1].Trim() } return '' } } #EndRegion './Private/Get-Section.ps1' 44 #Region './Public/ConvertTo-XurrentKnowledgeArticle.ps1' -1 function ConvertTo-XurrentKnowledgeArticle { <# .SYNOPSIS Converts a Markdown knowledge article file to a Xurrent import object. .DESCRIPTION Reads a *KnowledgeArticle.md file and extracts the Subject (first H1 heading), Description (## Description section), Instructions (## Instructions section), and Keywords (**Keywords:** line) into a PSCustomObject formatted for the Xurrent / 4me bulk-import CSV schema. .PARAMETER File The input file to convert. Supports FileInfo, path strings, and objects that expose a FullName or Path property. Accepts pipeline input. .PARAMETER Service The Xurrent service name to write to the Service column of the import row. .PARAMETER ServiceInstances The Xurrent service instance name(s) for the Service Instances column. .EXAMPLE Get-Item .\MyAppKnowledgeArticle.md | ConvertTo-XurrentKnowledgeArticle -Service 'techwork automator' -ServiceInstances 'techwork automator for ACS' .EXAMPLE Get-ChildItem -Recurse -Filter '*KnowledgeArticle.md' | ConvertTo-XurrentKnowledgeArticle -Service 'my svc' -ServiceInstances 'my inst' #> [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias('FullName', 'Path', 'PSPath')] [object] $File, [Parameter(Mandatory = $true)] [string] $Service, [Parameter(Mandatory = $true)] [string] $ServiceInstances ) process { $filePath = $null if ($File -is [System.IO.FileInfo]) { $filePath = $File.FullName } elseif ($File -is [string]) { $filePath = $File } elseif ($null -ne $File.PSObject.Properties['FullName']) { $filePath = [string]$File.FullName } elseif ($null -ne $File.PSObject.Properties['Path']) { $filePath = [string]$File.Path } if (-not $filePath) { throw 'File must be a path string, FileInfo, or an object with FullName/Path.' } $resolvedFile = Get-Item -LiteralPath $filePath -ErrorAction Stop if ($resolvedFile -isnot [System.IO.FileInfo]) { throw "Input path '$filePath' is not a file." } $raw = Get-Content -Path $resolvedFile.FullName -Raw -Encoding UTF8 $subject = '' if ($raw -match '(?m)^#\s+(.+)$') { $subject = $Matches[1].Trim() } $keywords = '' if ($raw -match '\*\*Keywords:\*\*\s*(.+)') { $keywords = $Matches[1].Trim() } [PSCustomObject]@{ ID = '' Source = '4me' 'Source ID' = '' Status = 'work_in_progress' Service = $Service 'Service Instances' = $ServiceInstances Subject = $subject Description = Get-Section -Content $raw -Heading 'Description' Instructions = Get-Section -Content $raw -Heading 'Instructions' Keywords = $keywords Template = '' } } } #EndRegion './Public/ConvertTo-XurrentKnowledgeArticle.ps1' 101 #Region './Public/Export-XurrentKnowledgeArticle.ps1' -1 function Export-XurrentKnowledgeArticle { <# .SYNOPSIS Exports Xurrent knowledge articles from Markdown files to a CSV import file. .DESCRIPTION Scans a folder recursively for *KnowledgeArticle.md files and writes a CSV in the Xurrent / 4me bulk-import format. Subject is read from the first H1 heading, Description and Instructions from same-named ## sections, Keywords from a **Keywords:** line. Service and ServiceInstances can be set via parameters or loaded from a .env file (SERVICE and SERVICE_INSTANCES keys). .PARAMETER Folder Path to the folder to scan recursively for *KnowledgeArticle.md files. .PARAMETER Service Xurrent service name written to the Service column of every export row. Defaults to 'techwork automator'. Can also be supplied via SERVICE= in a .env file. .PARAMETER ServiceInstances Xurrent service instance name(s) for the Service Instances column. Can be supplied via SERVICE_INSTANCES= in a .env file; prompts interactively if still empty. .PARAMETER OutputPath Full path of the CSV file to write. Defaults to import-knowledge_articles.csv in the current working directory. .PARAMETER EnvFile Path to a .env file supplying SERVICE and SERVICE_INSTANCES defaults. Defaults to .env in the current working directory when that file exists. .EXAMPLE Export-KnowledgeArticle -Folder .\ACS -Service 'techwork automator' -ServiceInstances 'techwork automator for ACS' .EXAMPLE Export-KnowledgeArticle -Folder .\TTTech Loads SERVICE and SERVICE_INSTANCES from .env in the current directory. #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true)] [ValidateScript({ Test-Path $_ -PathType Container })] [string] $Folder, [Parameter()] [string] $Service = 'techwork automator', [Parameter()] [string] $ServiceInstances = '', [Parameter()] [string] $OutputPath = (Join-Path (Get-Location).Path 'import-knowledge_articles.csv'), [Parameter()] [string] $EnvFile = (Join-Path (Get-Location).Path '.env') ) process { if (Test-Path $EnvFile) { foreach ($line in (Get-Content $EnvFile)) { if ($line -match "^([A-Z_]+)\s*=\s*'?([^']*?)'?\s*$") { $key = $Matches[1] $val = $Matches[2] if ($key -eq 'SERVICE' -and -not $PSBoundParameters.ContainsKey('Service')) { $Service = $val } if ($key -eq 'SERVICE_INSTANCES' -and -not $PSBoundParameters.ContainsKey('ServiceInstances')) { $ServiceInstances = $val } } } } if (-not $Service) { $Service = Read-Host -Prompt "Enter SERVICE name (e.g. 'techwork automator')" } if (-not $ServiceInstances) { $ServiceInstances = Read-Host -Prompt 'Enter SERVICE_INSTANCES' } $files = Get-ChildItem -Path $Folder -Recurse -Filter '*KnowledgeArticle.md' if ($files.Count -eq 0) { Write-Warning "No *KnowledgeArticle.md files found in $Folder" return } Write-Verbose "Found $($files.Count) knowledge article(s) in $Folder" $rows = foreach ($file in $files) { Write-Verbose " Processing $($file.FullName)" ConvertTo-XurrentKnowledgeArticle -File $file -Service $Service -ServiceInstances $ServiceInstances } if ($PSCmdlet.ShouldProcess($OutputPath, 'Export CSV')) { # PS 7+ needs utf8BOM for a BOM-prefixed file; PS 5.1 UTF8 already includes one. $encoding = if ($PSVersionTable.PSVersion.Major -ge 7) { 'utf8BOM' } else { 'UTF8' } $rows | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding $encoding Write-Verbose "Exported $($rows.Count) article(s) to $OutputPath" } } } #EndRegion './Public/Export-XurrentKnowledgeArticle.ps1' 115 #Region './Public/New-XurrentKnowledgeArticleCsvExample.ps1' -1 function New-XurrentKnowledgeArticleCsvExample { <# .SYNOPSIS Creates an example CSV file in the Xurrent knowledge article import format. .DESCRIPTION Writes a CSV file with all columns required by the Xurrent / 4me bulk-import schema for knowledge articles, pre-filled with one illustrative example row. Use it as a reference or starting point before populating real data via Export-KnowledgeArticle. .PARAMETER OutputPath Full path of the CSV file to write. Defaults to example-knowledge_articles.csv in the current working directory. .EXAMPLE New-KnowledgeArticleCsvExample Creates example-knowledge_articles.csv in the current directory. .EXAMPLE New-KnowledgeArticleCsvExample -OutputPath C:\Temp\example.csv Creates the example CSV at the specified path. #> [CmdletBinding(SupportsShouldProcess = $true)] [OutputType([System.IO.FileInfo])] param ( [Parameter()] [string] $OutputPath = (Join-Path (Get-Location).Path 'example-knowledge_articles.csv') ) process { $example = [PSCustomObject]@{ ID = '' Source = '4me' 'Source ID' = '' Status = 'work_in_progress' Service = 'my service' 'Service Instances' = 'my service instance' Subject = 'Example knowledge article subject' Description = 'A brief description of the knowledge article.' Instructions = 'Step 1: Do this. Step 2: Do that.' Keywords = 'example, keyword1, keyword2' Template = '' } if ($PSCmdlet.ShouldProcess($OutputPath, 'Create example knowledge article CSV')) { $encoding = if ($PSVersionTable.PSVersion.Major -ge 7) { 'utf8BOM' } else { 'UTF8' } $example | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding $encoding Get-Item -Path $OutputPath } } } #EndRegion './Public/New-XurrentKnowledgeArticleCsvExample.ps1' 57 #Region './Public/New-XurrentKnowledgeArticleTemplate.ps1' -1 function New-XurrentKnowledgeArticleTemplate { <# .SYNOPSIS Creates a Markdown template file for a Xurrent knowledge article. .DESCRIPTION Writes a *KnowledgeArticle.md template to the specified folder with the correct structure expected by ConvertTo-KnowledgeArticle: an H1 heading for the Subject, a **Keywords:** line, and ## Description and ## Instructions sections. .PARAMETER Name The name of the knowledge article, used as the H1 heading and filename prefix. The file is written as <Name>KnowledgeArticle.md. .PARAMETER Path The folder in which to create the template file. Defaults to the current working directory. .EXAMPLE New-KnowledgeArticleTemplate -Name 'HowToResetPassword' Creates HowToResetPasswordKnowledgeArticle.md in the current directory. .EXAMPLE New-KnowledgeArticleTemplate -Name 'VPN Setup' -Path C:\Articles Creates 'VPN SetupKnowledgeArticle.md' in C:\Articles. #> [CmdletBinding(SupportsShouldProcess = $true)] [OutputType([System.IO.FileInfo])] param ( [Parameter(Mandatory = $true)] [string] $Name, [Parameter()] [ValidateScript({ Test-Path $_ -PathType Container })] [string] $Path = (Get-Location).Path ) process { $fileName = '{0}KnowledgeArticle.md' -f $Name $filePath = Join-Path -Path $Path -ChildPath $fileName $template = @" # $Name **Keywords:** keyword1, keyword2 ## Description Describe the knowledge article here. ## Instructions Provide step-by-step instructions here. "@ if ($PSCmdlet.ShouldProcess($filePath, 'Create knowledge article template')) { Set-Content -Path $filePath -Value $template -Encoding UTF8 Get-Item -Path $filePath } } } #EndRegion './Public/New-XurrentKnowledgeArticleTemplate.ps1' 68 |