├── ConvertFromMarkdown.psd1 ├── ConvertFromMarkdown.psm1 ├── DoTests.ps1 ├── Example ├── README.md ├── lintThis.ps1 └── manuscript │ ├── Book.txt │ ├── chapter00.md │ └── chapter01.md ├── InstallModule.ps1 ├── LICENSE ├── PublishToGallery.ps1 ├── README.md ├── TestPSCodeBlock.ps1 ├── TestREADME.md ├── __tests__ ├── ConvertFromReadmeMD.tests.ps1 ├── README.md ├── READMECodeThatErrors.md ├── READMEExcludeCode.md ├── READMEGoodCode.md ├── READMEOneChapterNoCode.md └── changelog.md ├── appveyor.yml ├── exportManuscript.ps1 └── images ├── Convert.png ├── ConvertExampleReadme.png └── manuscript.png /ConvertFromMarkdown.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | 3 | # Script module or binary module file associated with this manifest. 4 | RootModule = 'ConvertFromMarkdown.psm1' 5 | 6 | # Version number of this module. 7 | ModuleVersion = '1.2.0' 8 | 9 | # ID used to uniquely identify this module 10 | GUID = '83c87d12-6c30-424f-ab67-9016daada1d4' 11 | 12 | # Author of this module 13 | Author = 'Douglas Finke' 14 | 15 | # Company or vendor of this module 16 | CompanyName = 'Doug Finke' 17 | 18 | # Copyright statement for this module 19 | Copyright = 'c 2018 All rights reserved.' 20 | 21 | # Description of the functionality provided by this module 22 | Description = @' 23 | From your Markdown to generated chapters, run ScriptAnalyzer on your examples and generate HTML, a Word Doc or PDF. Table of Contents included 24 | '@ 25 | 26 | # Minimum version of the Windows PowerShell engine required by this module 27 | # PowerShellVersion = '' 28 | 29 | # Name of the Windows PowerShell host required by this module 30 | # PowerShellHostName = '' 31 | 32 | # Minimum version of the Windows PowerShell host required by this module 33 | # PowerShellHostVersion = '' 34 | 35 | # Minimum version of Microsoft .NET Framework required by this module 36 | # DotNetFrameworkVersion = '' 37 | 38 | # Minimum version of the common language runtime (CLR) required by this module 39 | # CLRVersion = '' 40 | 41 | # Processor architecture (None, X86, Amd64) required by this module 42 | # ProcessorArchitecture = '' 43 | 44 | # Modules that must be imported into the global environment prior to importing this module 45 | # RequiredModules = @() 46 | 47 | # Assemblies that must be loaded prior to importing this module 48 | # RequiredAssemblies = @() 49 | 50 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 51 | # ScriptsToProcess = @() 52 | 53 | # Type files (.ps1xml) to be loaded when importing this module 54 | # TypesToProcess = @() 55 | 56 | # Format files (.ps1xml) to be loaded when importing this module 57 | # FormatsToProcess = @() 58 | 59 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 60 | # NestedModules = @() 61 | 62 | # Functions to export from this module 63 | FunctionsToExport = '*' 64 | 65 | # Cmdlets to export from this module 66 | CmdletsToExport = '*' 67 | 68 | # Variables to export from this module 69 | VariablesToExport = '*' 70 | 71 | # Aliases to export from this module 72 | AliasesToExport = '*' 73 | 74 | # List of all modules packaged with this module 75 | # ModuleList = @() 76 | 77 | # List of all files packaged with this module 78 | # FileList = @() 79 | 80 | # Private data to pass to the module specified in RootModule/ModuleToProcess 81 | PrivateData = @{ 82 | # PSData is module packaging and gallery metadata embedded in PrivateData 83 | # It's for rebuilding PowerShellGet (and PoshCode) NuGet-style packages 84 | # We had to do this because it's the only place we're allowed to extend the manifest 85 | # https://connect.microsoft.com/PowerShell/feedback/details/421837 86 | PSData = @{ 87 | # The primary categorization of this module (from the TechNet Gallery tech tree). 88 | Category = "PowerShell Documentation Markdown" 89 | 90 | # Keyword tags to help users find this module via navigations and search. 91 | Tags = @("PowerShell", "Markdown") 92 | 93 | # The web address of an icon which can be used in galleries to represent this module 94 | # IconUri = "" 95 | 96 | # The web address of this module's project or support homepage. 97 | ProjectUri = "https://github.com/dfinke/ConvertFromMarkdown" 98 | 99 | # The web address of this module's license. Points to a page that's embeddable and linkable. 100 | LicenseUri = "https://github.com/dfinke/ConvertFromMarkdown/blob/master/LICENSE" 101 | 102 | # Release notes for this particular version of the module 103 | #ReleaseNotes = $True 104 | 105 | # If true, the LicenseUrl points to an end-user license (not just a source license) which requires the user agreement before use. 106 | # RequireLicenseAcceptance = "" 107 | 108 | # Indicates this is a pre-release/testing version of the module. 109 | IsPrerelease = 'False' 110 | } 111 | } 112 | 113 | # HelpInfo URI of this module 114 | # HelpInfoURI = '' 115 | 116 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 117 | # DefaultCommandPrefix = '' 118 | 119 | } -------------------------------------------------------------------------------- /ConvertFromMarkdown.psm1: -------------------------------------------------------------------------------- 1 | . $PSScriptRoot\exportManuscript.ps1 2 | . $PSScriptRoot\TestPSCodeBlock.ps1 3 | 4 | function Test-Chapter { 5 | param ( 6 | $outputPath = $pwd 7 | ) 8 | 9 | (Get-ChildItem $outputPath).Count -gt 0 10 | } 11 | 12 | function ConvertFrom-Markdown { 13 | param ( 14 | $markdownFile = "$pwd\README.md", 15 | $outputPath = $pwd, 16 | [ValidateSet("Html", "Docx", "PDF")] 17 | $OutputType, 18 | [Switch]$Show 19 | ) 20 | 21 | Write-Progress -Activity "Generating manuscript" -Status "[$(Get-Date)] Creating chapters" 22 | Export-Manuscript -markdownFile $markdownFile -outputPath $outputPath 23 | 24 | $targetPath = "$($outputPath)\manuscript" 25 | 26 | Write-Progress -Activity "Generating manuscript" -Status "[$(Get-Date)] Analyzing PowerShell" 27 | Test-PSCodeBlock -markdownFile $markdownFile -outputPath $outputPath 28 | 29 | 30 | if (!(Test-Chapter $targetPath)) { 31 | "No chapters found" 32 | return 33 | } 34 | 35 | #if ((Get-Command pandoc.exe -ErrorAction SilentlyContinue) -and $AsPDF) { 36 | if ($OutputType) { 37 | 38 | if (!(Get-Command pandoc.exe -ErrorAction SilentlyContinue)) { 39 | Write-Warning @" 40 | To generate that output type, you need to install Pandoc, https://pandoc.org/installing.html 41 | If you want a PDF, you need to also install LaTeX, https://miktex.org/ 42 | "@ 43 | return 44 | } 45 | 46 | # $chapters = (Get-Content "$targetPath\book.txt") -join ' ' 47 | $chapters = (Get-ChildItem $targetPath chap* | ForEach-Object FullName ) -join ' ' 48 | 49 | # if ($chapters.trim().length -gt 0) { 50 | $outFile = "$($targetPath)\book.$($OutputType)" 51 | Write-Progress -Activity "Generating manuscript" -Status "[$(Get-Date)] Creating $($OutputType)" 52 | "pandoc $chapters -S --toc --standalone -o $outFile" | Invoke-Expression 53 | 54 | Write-Progress -Activity "Generating manuscript" -Status "[$(Get-Date)] Launching $($OutputType)" 55 | if ($Show) { 56 | Invoke-Item $outFile 57 | } 58 | # } 59 | # else { 60 | # "No chapters found" 61 | # } 62 | } 63 | } 64 | 65 | function Test-IsUri { 66 | param($targetUri) 67 | 68 | [System.Uri]::IsWellFormedUriString($targetUri, 'Absolute') 69 | } -------------------------------------------------------------------------------- /DoTests.ps1: -------------------------------------------------------------------------------- 1 | $PSVersionTable.PSVersion 2 | 3 | $ErrorActionPreference = "Continue" 4 | 5 | if ((Get-Module -ListAvailable pester) -eq $null) { 6 | Install-Module -Name Pester -Repository PSGallery -Force -Scope CurrentUser 7 | } 8 | 9 | if ((Get-Module -ListAvailable PSScriptAnalyzer) -eq $null) { 10 | Install-Module -Name PSScriptAnalyzer -Repository PSGallery -Force -Scope CurrentUser 11 | } 12 | 13 | $result = Invoke-Pester -Script $PSScriptRoot\__tests__ -Verbose -PassThru 14 | 15 | if ($result.FailedCount -gt 0) { 16 | throw "$($result.FailedCount) tests failed." 17 | } -------------------------------------------------------------------------------- /Example/README.md: -------------------------------------------------------------------------------- 1 | 2 | # STRINGS 3 | 4 | ## Trim leading and trailing white-space from string 5 | 6 | This is an alternative to using the `Trim()` method. The 7 | function below works by finding all leading and trailing white-space and 8 | removing it from the start and end of the string. 9 | 10 | **Example Function:** 11 | 12 | ```ps 13 | function Invoke-TrimString { 14 | param($targetText) 15 | 16 | $targetText -replace '^[ \t]+|[ \t]+$', '' 17 | } 18 | ``` 19 | 20 | **Example Usage:** 21 | 22 | ```powershell 23 | PS C:\> Invoke-TrimString " Hello, World " 24 | Hello, World 25 | 26 | PS C:\> $name = " John Black " 27 | PS C:\> Invoke-TrimString $name 28 | John Black 29 | ``` 30 | 31 | ## Strip all instances of pattern from string 32 | 33 | **Example Function:** 34 | 35 | ```ps 36 | function Invoke-StripAll { 37 | param($targetText, $pattern) 38 | 39 | $count = 0 40 | $targetText -replace $pattern, '' 41 | } 42 | ``` 43 | 44 | **Example Usage:** 45 | 46 | ```powershell 47 | PS C:\> Invoke-StripAll "The Quick Brown Fox" "[aeiou]" 48 | Th Qck Brwn Fx 49 | 50 | PS C:\> Invoke-StripAll "The Quick Brown Fox" " " 51 | TheQuickBrownFox 52 | 53 | PS C:\> Invoke-StripAll "The Quick Brown Fox" "Quick " 54 | The Brown Fox 55 | ``` 56 | 57 | 58 | 59 | 60 | # ARRAYS 61 | 62 | -------------------------------------------------------------------------------- /Example/lintThis.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-TrimString { 2 | param($targetText) 3 | 4 | $targetText -replace '^[ \t]+|[ \t]+$', '' 5 | } 6 | 7 | function Invoke-StripAll { 8 | param($targetText, $pattern) 9 | 10 | $count = 0 11 | $targetText -replace $pattern, '' 12 | } 13 | 14 | -------------------------------------------------------------------------------- /Example/manuscript/Book.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfinke/ConvertFromMarkdown/c6a04ae1991baba336fc001a8b434e6e15c2b55c/Example/manuscript/Book.txt -------------------------------------------------------------------------------- /Example/manuscript/chapter00.md: -------------------------------------------------------------------------------- 1 | # STRINGS 2 | 3 | ## Trim leading and trailing white-space from string 4 | 5 | This is an alternative to using the `Trim()` method. The 6 | function below works by finding all leading and trailing white-space and 7 | removing it from the start and end of the string. 8 | 9 | **Example Function:** 10 | 11 | ```ps 12 | function Invoke-TrimString { 13 | param($targetText) 14 | 15 | $targetText -replace '^[ \t]+|[ \t]+$', '' 16 | } 17 | ``` 18 | 19 | **Example Usage:** 20 | 21 | ```powershell 22 | PS C:\> Invoke-TrimString " Hello, World " 23 | Hello, World 24 | 25 | PS C:\> $name = " John Black " 26 | PS C:\> Invoke-TrimString $name 27 | John Black 28 | ``` 29 | 30 | ## Strip all instances of pattern from string 31 | 32 | **Example Function:** 33 | 34 | ```ps 35 | function Invoke-StripAll { 36 | param($targetText, $pattern) 37 | 38 | $count = 0 39 | $targetText -replace $pattern, '' 40 | } 41 | ``` 42 | 43 | **Example Usage:** 44 | 45 | ```powershell 46 | PS C:\> Invoke-StripAll "The Quick Brown Fox" "[aeiou]" 47 | Th Qck Brwn Fx 48 | 49 | PS C:\> Invoke-StripAll "The Quick Brown Fox" " " 50 | TheQuickBrownFox 51 | 52 | PS C:\> Invoke-StripAll "The Quick Brown Fox" "Quick " 53 | The Brown Fox 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /Example/manuscript/chapter01.md: -------------------------------------------------------------------------------- 1 | # ARRAYS 2 | -------------------------------------------------------------------------------- /InstallModule.ps1: -------------------------------------------------------------------------------- 1 | $fullPath = 'C:\Program Files\WindowsPowerShell\Modules\ConvertFromMarkdown' 2 | 3 | Robocopy . $fullPath /mir /XD .vscode .git /XF appveyor.yml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Doug Finke 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PublishToGallery.ps1: -------------------------------------------------------------------------------- 1 | $p = @{ 2 | Name = "ConvertFromMarkdown" 3 | NuGetApiKey = $NuGetApiKey 4 | #ReleaseNote = "Add NumberFormat parameter" 5 | } 6 | 7 | Publish-Module @p -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | ## Convert From Markdown: In Action Video 6 | 7 | Check it out, How to ConvertFrom-Markdown with all the bells and whistles. 8 | 9 | 10 | IMAGE ALT TEXT HERE 11 | 12 | 13 | 14 | 15 | 16 | ## Updates 17 | 18 | - Added `KeepLintFile` switch 19 | - Added try/catch around `Invoke-ScriptAnalyzer` 20 | - Added `` and ``. For example, if have code blocks that define the same class, you can exclude 21 | it so PSScriptAnalyzer doesn't fail 22 | 23 | # Convert From Markdown 24 | Quickly re-purpose your markdown as input to a service like LeanPub (for self publishing), and run the PowerShell ScriptAnalyzer against your PowerShell samples in the markdown. 25 | 26 | This PowerShell module significantly improves your workflow for authoring your PowerShell `README.md` 27 | 28 | Leveraging markdown, a typical workflow is creating a README.md for your PowerShell module/scripts. Describing your functions, parameters and how they operate. Next, supplying examples of these functions in action, and followed by sample output. 29 | 30 | While this is a great way to communicate with your audience, it causes a few problems for you, the author. First it locks your documentation into your README, making it difficult to re-purpose, for example as input to a service like LeanPub, a platform which is the combination of two things: a publishing workflow and a storefront. 31 | 32 | The second challenge is, how can you make sure that your PowerShell examples are correct? One way to solve this is you do the double work of "testing" the code you add to the markdown. 33 | 34 | This module improves that with two simple additions to your markdown authoring. 35 | 36 | ## Fenced code blocks and Chapters 37 | 38 | ### Fenced code blocks 39 | Fenced code blocks let you create highlighted coding in your `README`. You can create fenced code blocks by placing triple backticks ```. 40 | 41 | Syntax highlighting can be done with ```ps. For example: 42 | 43 | ``` 44 | ```ps 45 | function test { 46 | param( 47 | $name 48 | ) 49 | } 50 | ``` 51 | ``` 52 | 53 | Becomes this: 54 | ```ps 55 | function test { 56 | param( 57 | $name 58 | ) 59 | } 60 | ``` 61 | 62 | ### Chapters 63 | 64 | In markdown you can have comments, they take the form of ``. 65 | Let's leverage that with `` an `` 66 | 67 | Wrapping sections of your markdown with these enable cool automation opportunities by becoming "`fenced chapter blocks`". 68 | 69 | ## Where are we? 70 | 71 | By continuing to use `fenced code blocks`, and adopting `fenced chapter blocks`, next level automation can be achieved. 72 | 73 | This module reads your markdown and when it finds these blocks it extracts two things. First it creates a manuscript (ready for LeanPub), by creating a `manuscript` directory and placing "`fenced chapter blocks`" in numbered `chapterNNN.txt` files, including a `book.txt` 74 | 75 | Then, it pulls out the PowerShell code and runs the PowerShell ScriptAnalyzer on it, reporting any issues. 76 | 77 | 78 | ## In Action 79 | 80 | Running the `ConverFrom-ReadmeMD` on a markdown file does a few things. It extracts the code in the fenced code blocks and runs the PowerShell ScriptAnalyzer against it 81 | 82 | ### The Analyzer 83 | ![](./images/Convert.png) 84 | 85 | And, it extracts all the `fenced chapter blocks` into the `manuscript` director, ready for shipping to LeanPub for publishing. 86 | 87 | ### The Manuscript 88 | 89 | Here is the extraction of the `fenced chapter blocks` ready for your book publishing. 90 | 91 | ![](./images/manuscript.png) 92 | 93 | ## Summary 94 | 95 | Re-purposing effort makes us more agile, improves cycle time (from idea to customers using it). This module bumps you up to the next level. 96 | 97 | Enjoy -------------------------------------------------------------------------------- /TestPSCodeBlock.ps1: -------------------------------------------------------------------------------- 1 | #Requires -modules PSScriptAnalyzer 2 | 3 | function Test-PSCodeBlock { 4 | param ( 5 | $markdownFile = "$pwd\README.md", 6 | $outputPath = $pwd, 7 | [Switch]$KeepLintFile 8 | ) 9 | 10 | $codeBlocks = [ordered]@{} 11 | $inCodeBlock = $false 12 | $codeBlockIndex = 0 13 | $excludeCode = $false 14 | 15 | if (!(Test-IsUri $markdownFile)) { 16 | $markdownContent = Get-Content $markdownFile 17 | } 18 | else { 19 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 20 | $markdownContent = Invoke-RestMethod $markdownFile 21 | $markdownContent = $markdownContent -split "`n" 22 | } 23 | 24 | # switch -File ($markdownFile) { 25 | switch ($markdownContent) { 26 | 27 | '' {$excludeCode = $true} 28 | '' {$excludeCode = $false} 29 | 30 | '```' { 31 | $inCodeBlock = $false 32 | $codeBlockIndex += 1 33 | } 34 | 35 | {$inCodeBlock} { 36 | if (!$excludeCode) { 37 | $currentBlock = "block{0:0#}" -f $codeBlockIndex 38 | $codeBlocks.$currentBlock += $_ + "`r`n" 39 | } 40 | } 41 | 42 | '```ps' {$inCodeBlock = $true} 43 | 44 | default {} 45 | } 46 | 47 | if ($codeBlocks.Values.count -gt 0) { 48 | #$targetFile = "$pwd\lintThis.ps1" 49 | $targetFile = "$outputPath\lintThis.ps1" 50 | $codeBlocks.Values | Set-Content -Encoding Ascii $targetFile 51 | 52 | try { 53 | $analysis = Invoke-ScriptAnalyzer $targetFile -ErrorAction Stop 54 | 55 | if ($analysis.count -gt 0) { 56 | $analysis 57 | } 58 | else { 59 | "all analyzed - no issues" 60 | if (!$KeepLintFile) { 61 | Remove-Item $targetFile 62 | } 63 | } 64 | } 65 | catch { 66 | $_.Exception 67 | #throw 'caught' 68 | } 69 | } 70 | else { 71 | "no code found" 72 | } 73 | } -------------------------------------------------------------------------------- /TestREADME.md: -------------------------------------------------------------------------------- 1 | 2 | # Let's Talk about Strings 3 | Lets convert lowercase strings to uppercase 4 | 5 | ```ps 6 | 'this Is MixEd CaSe'.ToUpper() 7 | ``` 8 | 9 | ## Prints 10 | 11 | ``` 12 | THIS IS MIXED CASE 13 | ``` 14 | 15 | 16 | 17 | 18 | # Let's Talk about Functions 19 | Here is a simple function. 20 | 21 | ```ps 22 | function test { 23 | "Hello World" 24 | } 25 | ``` 26 | 27 | ### Example Usage 28 | 29 | ```powershell 30 | PS C:\> test 31 | 32 | Hello World 33 | ``` 34 | 35 | 36 | 37 | 38 | # Let's Talk about ScriptAnalyzer Errors 39 | 40 | Spot the issue 41 | 42 | 43 | ```ps 44 | function test { 45 | param($p) 46 | 47 | $result = "Hello $p" 48 | } 49 | ``` 50 | 51 | ### Example Usage 52 | 53 | ```powershell 54 | PS C:\> test 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /__tests__/ConvertFromReadmeMD.tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Convertfrom ReadmdMD" { 2 | 3 | BeforeAll { 4 | Import-Module $PSScriptRoot\..\ConvertFromMarkdown.psm1 -Force 5 | } 6 | 7 | AfterEach { 8 | Remove-Item $env:TEMP\manuscript -Recurse -Force -ErrorAction Ignore 9 | Remove-Item $env:TEMP\lintThis.ps1 -Force -ErrorAction Ignore 10 | } 11 | 12 | It "Should create a manuscript folder" { 13 | ConvertFrom-Markdown $PSScriptRoot\README.md $env:TEMP 14 | 15 | Test-Path $env:TEMP\manuscript | Should Be $true 16 | Test-Path $env:TEMP\lintThis.ps1 | Should Be $true 17 | } 18 | 19 | It "Should have six files in the manuscript directory" { 20 | ConvertFrom-Markdown $PSScriptRoot\README.md $env:TEMP 21 | 22 | (Get-ChildItem $env:TEMP\manuscript | Measure-Object ).Count | Should Be 6 23 | } 24 | 25 | It "Read from the web, should have six files in the manuscript directory" { 26 | ConvertFrom-Markdown https://raw.githubusercontent.com/dfinke/ConvertFromMarkdown/master/__tests__/README.md $env:TEMP 27 | (Get-ChildItem $env:TEMP\manuscript | Measure-Object ).Count | Should Be 6 28 | } 29 | 30 | It "Should have book.md in the manuscript directory" { 31 | ConvertFrom-Markdown $PSScriptRoot\README.md $env:TEMP 32 | 33 | Test-Path $env:TEMP\manuscript\book.txt | Should Be $true 34 | } 35 | 36 | It "Should have five chapter files in the manuscript directory" { 37 | ConvertFrom-Markdown $PSScriptRoot\README.md $env:TEMP 38 | 39 | (Get-ChildItem $env:TEMP\manuscript chapter*.txt | Measure-Object ).Count | Should Be 5 40 | } 41 | 42 | It "Should create a manuscript folder no code blocks" { 43 | ConvertFrom-Markdown $PSScriptRoot\READMEOneChapterNoCode.md $env:TEMP 44 | 45 | Test-Path $env:TEMP\manuscript | Should Be $true 46 | Test-Path $env:TEMP\lintThis.ps1 | Should Be $false 47 | } 48 | 49 | It "Should create a test code blocks and delete lint file" { 50 | $actual = Test-PSCodeBlock $PSScriptRoot\READMEGoodCode.md $env:TEMP 51 | $actual | Should Be "all analyzed - no issues" 52 | Test-Path $env:TEMP\lintThis.ps1 | Should Be $false 53 | } 54 | 55 | It "Reads from the web, should create a test code blocks and delete lint file" { 56 | $actual = Test-PSCodeBlock https://raw.githubusercontent.com/dfinke/ConvertFromMarkdown/master/__tests__/READMEGoodCode.md $env:TEMP 57 | $actual | Should Be "all analyzed - no issues" 58 | Test-Path $env:TEMP\lintThis.ps1 | Should Be $false 59 | } 60 | 61 | It "Should keep lint file" { 62 | $actual = Test-PSCodeBlock $PSScriptRoot\READMEGoodCode.md $env:TEMP -KeepLintFile 63 | $actual | Should Be "all analyzed - no issues" 64 | 65 | Test-Path $env:TEMP\lintThis.ps1 | Should Be $true 66 | } 67 | 68 | It "Should handle errors in the fenced blocks" { 69 | $actual = Test-PSCodeBlock $PSScriptRoot\READMECodeThatErrors.md $env:TEMP 70 | $actual | Should Not Be "all analyzed - no issues" 71 | 72 | Test-Path $env:TEMP\lintThis.ps1 | Should Be $true 73 | } 74 | 75 | It "Should respect excluded blocks" { 76 | $actual = Test-PSCodeBlock $PSScriptRoot\READMEExcludeCode.md $env:TEMP 77 | $actual | Should Be "all analyzed - no issues" 78 | 79 | Test-Path $env:TEMP\lintThis.ps1 | Should Be $false 80 | } 81 | 82 | It "Should fail as a Uri" { 83 | Test-IsUri .\README.md | Should Be $false 84 | } 85 | 86 | It "Should be a Uri" { 87 | Test-IsUri https://raw.githubusercontent.com/dfinke/ConvertFromMarkdown/master/README.md | Should Be $true 88 | } 89 | 90 | AfterAll { 91 | Remove-Item $env:TEMP\manuscript -Recurse -Force -ErrorAction Ignore 92 | Remove-Item $env:TEMP\lintThis.ps1 -Force -ErrorAction Ignore 93 | } 94 | } 95 | 96 | Describe "Test markdown file with no chapters and no code" { 97 | BeforeAll { 98 | Import-Module $PSScriptRoot\..\ConvertFromMarkdown.psm1 -Force 99 | } 100 | 101 | It "Should report no code" { 102 | $actual = ConvertFrom-Markdown $PSScriptRoot\changelog.md -OutputType PDF 103 | 104 | $actual.Count | Should Be 2 105 | 106 | $actual[0] | Should Be 'no code found' 107 | $actual[1] | Should Be 'No chapters found' 108 | } 109 | 110 | AfterAll { 111 | Remove-Item $env:TEMP\manuscript -Recurse -Force -ErrorAction Ignore 112 | Remove-Item $env:TEMP\lintThis.ps1 -Force -ErrorAction Ignore 113 | } 114 | 115 | } -------------------------------------------------------------------------------- /__tests__/README.md: -------------------------------------------------------------------------------- 1 | # ConvertFromReadmeMD 2 | Transform a README.md 3 | 4 | 5 | 6 | ## Let's talk about strings 7 | 8 | PowerShell strings are textual 9 | 10 | 11 | 12 | 13 | ## Let's talk about variables 14 | 15 | All variables start with a `$`. 16 | 17 | ```ps 18 | $a=1 19 | $a++ 20 | $a 21 | ``` 22 | 23 | Prints 24 | 25 | ```powershell 26 | 2 27 | ``` 28 | 29 | 30 | 31 | 32 | ## Let's talk about Cmdlets 33 | 34 | verb-noun 35 | 36 | 37 | 38 | 39 | 40 | ## Let's talk about Functions 41 | 42 | ```ps 43 | function test { 44 | $n = "World" 45 | "Hello " 46 | } 47 | ``` 48 | 49 | ### Example Usage: 50 | 51 | ```powershell 52 | PS C:\> test "World" 53 | 54 | ``` 55 | 56 | 57 | 58 | 59 | ## Let's talk about REST 60 | 61 | `Invoke-RestMethod` 62 | 63 | 64 | -------------------------------------------------------------------------------- /__tests__/READMECodeThatErrors.md: -------------------------------------------------------------------------------- 1 | 2 | ## Let's talk about strings 3 | 4 | PowerShell strings are textual 5 | 6 | ```ps 7 | class Test {} 8 | ``` 9 | 10 | ```ps 11 | class Test {} 12 | ``` 13 | -------------------------------------------------------------------------------- /__tests__/READMEExcludeCode.md: -------------------------------------------------------------------------------- 1 | 2 | ## Let's talk about strings 3 | 4 | PowerShell strings are textual 5 | 6 | 7 | ```ps 8 | class Test {} 9 | ``` 10 | 11 | 12 | ```ps 13 | class Test {} 14 | ``` 15 | -------------------------------------------------------------------------------- /__tests__/READMEGoodCode.md: -------------------------------------------------------------------------------- 1 | 2 | ## Let's talk about strings 3 | 4 | PowerShell strings are textual 5 | 6 | ```ps 7 | function Test { 8 | "Hello World" 9 | } 10 | ``` 11 | 12 | -------------------------------------------------------------------------------- /__tests__/READMEOneChapterNoCode.md: -------------------------------------------------------------------------------- 1 | 2 | ## Let's talk about strings 3 | 4 | PowerShell strings are textual 5 | 6 | -------------------------------------------------------------------------------- /__tests__/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## unreleased 4 | 5 | - Test3 6 | - Test4 7 | 8 | ## 4.0.30 9 | 10 | - Test1 11 | - Test2 -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfinke/ConvertFromMarkdown/c6a04ae1991baba336fc001a8b434e6e15c2b55c/appveyor.yml -------------------------------------------------------------------------------- /exportManuscript.ps1: -------------------------------------------------------------------------------- 1 | function Export-Manuscript { 2 | param( 3 | $markdownFile = "$pwd\README.md", 4 | $outputPath = $pwd, 5 | [ValidateSet('txt', 'md')] 6 | $chapterExtension = "txt" 7 | ) 8 | 9 | $manuscriptPath = "$outputPath\manuscript" 10 | 11 | Remove-Item -Recurse -Force $manuscriptPath -ErrorAction Ignore 12 | 13 | $null = mkdir $manuscriptPath 14 | 15 | $chapters = [ordered]@{} 16 | $chapterIndex = 0 17 | 18 | if (!(Test-IsUri $markdownFile)) { 19 | $markdownContent = Get-Content $markdownFile 20 | } 21 | else { 22 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 23 | $markdownContent = Invoke-RestMethod $markdownFile 24 | $markdownContent = $markdownContent -split "`n" 25 | } 26 | 27 | # switch -File ($markdownFile) { 28 | switch ($markdownContent) { 29 | 30 | "" { 31 | $inChapter = $false 32 | $chapterIndex += 1 33 | } 34 | 35 | {$inChapter} { 36 | $currentChapter = "chapter{0:0#}" -f $chapterIndex 37 | if (!$chapters.$currentChapter) { 38 | $chapters.$currentChapter = @() 39 | } 40 | 41 | $chapters.$currentChapter += $_ 42 | } 43 | 44 | "" {$inChapter = $true} 45 | } 46 | 47 | foreach ($chapter in $chapters.Keys) { 48 | 49 | #$chapter 50 | $chapterName = "$($chapter).$($chapterExtension)" 51 | $chapterFile = "$($manuscriptPath)\$($chapterName)" 52 | 53 | $chapters.$chapter | Set-Content -Encoding Ascii $chapterFile 54 | $chapterName >> "$manuscriptPath\Book.txt" 55 | } 56 | } -------------------------------------------------------------------------------- /images/Convert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfinke/ConvertFromMarkdown/c6a04ae1991baba336fc001a8b434e6e15c2b55c/images/Convert.png -------------------------------------------------------------------------------- /images/ConvertExampleReadme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfinke/ConvertFromMarkdown/c6a04ae1991baba336fc001a8b434e6e15c2b55c/images/ConvertExampleReadme.png -------------------------------------------------------------------------------- /images/manuscript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfinke/ConvertFromMarkdown/c6a04ae1991baba336fc001a8b434e6e15c2b55c/images/manuscript.png --------------------------------------------------------------------------------