Types/OpenPackage.View/Markdown.html.ps1
|
<# .SYNOPSIS Views Markdown as HTML .DESCRIPTION Views Markdown as HTML .EXAMPLE #> [OutputType('text/html')] [PSTypeName('string')] [PSTypeName('IO.Packaging.Package')] [PSTypeName('IO.Packaging.PackagePart')] param() # Quickly enumerate all input and arguments. $allInput = @($input) + @($args) # If there is no pipeline builder if (-not ('Markdig.MarkdownPipelineBuilder' -as [type])) { # warn and return Write-Warning "Markdig not loaded (ConvertFrom-Markdown is not installed)" return } # Create the pipeline builder $mdPipelineBuilder = [Markdig.MarkdownPipelineBuilder]::new() $mdPipeline = [Markdig.MarkdownExtensions]::UsePipeTables($mdPipelineBuilder).Build() # Make one quick pass over all input $allInput = @( foreach ($in in $allInput) { # and expand any packages we find into their parts. if ($in -is [IO.Packaging.Package]) { $in.GetParts() } else { $in } } ) # Next make a neat little filter to decorate our output # We can give PowerShell objects N arbitrary types # including actual content types filter text/html { # Just check if our typenames do not contain our invocation name if ($_.pstypenames -and $_.pstypenames -notcontains $myInvocation.InvocationName) { # and add that typename. $_.pstypenames.add($myInvocation.InvocationName) } $_ # and pass thru the input. } # Now, let's go over all input :nextInput foreach ($in in $allInput) { # If the input is a string if ($in -is [string]) { # Just make the markdown html # and stick it in an <article> tag "<article>$( [Markdig.Markdown]::ToHtml($in, $mdPipeline) )</article>" | text/html # and continue to the next input. continue nextInput } # If the input is a package part, we can do more if ( $in -is [IO.Packaging.PackagePart] -and # (if it is not a markdown file, we should ignore it). $in.Uri -match '(?>\.md|\.markdown)$' ) { # Let's read our input real quick: $partStream = $in.GetStream('Open', 'Read') $reader = [IO.StreamReader]::new($partStream) # Just store the markdown. $markdown = $reader.ReadToEnd() # and clean up. $reader.Close(), $reader.Dispose() $partStream.Close(), $partStream.Dispose() # We stick the markdown into an article tag $markdownHtml = "<article>$( $( [Markdig.Markdown]::ToHtml($markdown, $mdPipeline) ) )</article>" $markdownxhtml = $markdownHtml -as [xml] foreach ($link in $markdownxhtml | Select-Xml //a) { if ($link.Node.href -match '\.(?>md|markdown)$') { $link.Node.href = $link.Node.href -replace '^(?<Name>.+?)\.(?>md|markdown)$', '../${Name}/' } } # And we can use relationships to determine more. $part = $in # If the part had a 'palette' relationship $paletteUrl = # If the part had a 'palette' relationship if ($part.RelationshipExists('palette')) { # use that target uri $part.GetRelationship('palette').TargetUri } elseif ($part.Package.RelationshipExists('palette')) { # alternatively, if the package had a palette, use that. $part.Package.GetRelationship('palette').TargetUri } # Now, we can put the markdown into HTML. $html = @( "<html><head>" # The title is easy. "<title>" $([Web.HttpUtility]::HtmlEncode($part.Name)) "</title>" # If there's a palette url if ($paletteUrl) { # link the stylesheet with that id. "<link rel='stylesheet' id='palette' href='$($paletteUrl)' />" } "</head>" "<body>" $markdownxhtml.OuterXml "</body>" "</html>" ) -join [Environment]::NewLine $html | Add-Member NoteProperty Package $in.Package -Force -PassThru | Add-Member NoteProperty PartUri $in.Uri -Force -PassThru | Add-Member NoteProperty Part $in -Force -PassThru | text/html # continue to the next input. continue nextInput } } |