Types/MarkX/FindReference.ps1
|
<# .SYNOPSIS Find Markdown References .DESCRIPTION Finds References to a dictionary of words within markdown. This allows us to find keyword mentions within a file, and can be used to cross-reference content. #> param( # A dictionary of topics to reference. # The keys are the strings we will search for. # The values may be anything, but should probably be titles or changelogs [Alias('ReferenceTopics')] [Collections.IDictionary] $TopicReference ) $skipReference = @() $header = $this.Header # Front matter may indicate we want to skip specific cross references $skipReference += @( if ($header.SkipReference) { $header.SkipReference} elseif ($header.SkipReferences) { $header.SkipReferences } elseif ($header.NoReference) { $header.NoReference } elseif ($header.NoReferences) { $header.NoReferences} ) # Sort all potential reference by length and then alphabetically # (this lets us match the longest potential reference first) $sortedKeys = $topicReference.Keys | Sort-Object Length, { $_ } -Descending # We only want to match references that follow # the start anchor or any whitespace, end tag, quote, underscore, or open parenthesis $LookBehind = "(?<=(?>^|[\s\>'`"_\(]))" # We only want to match references that preceed # the end anchor or any whitespace, end tag, quote, underscore, or close parenthesis $LookAhead = "(?=(?>$|[\s\>'`"_\.,\)]))" $NotAfter = '(?<!\#{1,6}[\s\S-[\r\n]])' $referencePattern = [Regex]::new("${LookBehind}${NotAfter}(?>$( @(foreach ($k in $sortedKeys) { [Regex]::Escape($k) -replace '\\\s', '[\s\-_]' }) -join '|' ))$LookAhead", 'Multiline,IgnoreCase') # We will match any references within the markdown foreach ($match in $referencePattern.Matches("$($this.markdown)")) { $topicAlias = $match -replace '[\s\-_]',' ' if ($skipReference -and ( $skipReference -contains $topicAlias -or $skipReference -contains $topicReference["$topicAlias"].TopicName) ) { continue } $match } |