diff --git a/ConvertOneNote2MarkDown-v2.Tests.ps1 b/ConvertOneNote2MarkDown-v2.Tests.ps1 index 72d1ae7..ca31fef 100644 --- a/ConvertOneNote2MarkDown-v2.Tests.ps1 +++ b/ConvertOneNote2MarkDown-v2.Tests.ps1 @@ -262,6 +262,24 @@ Describe "Remove-InvalidFileNameChars" -Tag 'Unit' { $result | Should -Be $expectedFileName } + It "Should remove trailing periods" { + $fileName = 'foo. bar.' + $expectedFileName = 'foo.-bar' + + $result = Remove-InvalidFileNameChars -Name $fileName + + $result | Should -Be $expectedFileName + } + + It "Should remove trailing periods and spaces if -KeepPathSpaces" { + $fileName = 'foo. bar. .' + $expectedFileName = 'foo. bar' + + $result = Remove-InvalidFileNameChars -Name $fileName -KeepPathSpaces + + $result | Should -Be $expectedFileName + } + } } @@ -313,6 +331,15 @@ Describe "Truncate-PathFileName" -Tag 'Unit' { $path | Truncate-PathFileName -Length $length | Should -Be $expectedPath } + It "Should remove trailing periods and spaces from a truncated filename" { + $drive = "C:$( [io.path]::DirectorySeparatorChar )" # E.g. C:\ + $path = $drive + ("a" * 100) + '. .' + ("b" * 100) + $length = 103 + $expectedPath = $drive + ("a" * 100) + + $path | Truncate-PathFileName -Length $length | Should -Be $expectedPath + } + } } @@ -618,6 +645,22 @@ function Get-FakeOneNoteHierarchyWithDuplicatePageNames { $hierarchy } +function Get-FakeOneNoteHierarchyWithPageNamesEndingWithAPeriod { + # Sample outerXML of a hierarchy object. Here we have one notebook 'test' with a page and its subpage, both with names ending with a period + $hierarchy = @' + + + + + + + + + +'@ -as [xml] + $hierarchy +} + function Get-FakeOneNotePageContent { # Sample outerXML of a page object $page = @' @@ -817,6 +860,24 @@ Describe 'New-SectionGroupConversionConfig' -Tag 'Unit' { } } + It "Should determine file and folder paths without trailing periods for pages with names ending with a period" { + $fakeHierarchy = Get-FakeOneNoteHierarchyWithPageNamesEndingWithAPeriod + $params['SectionGroups'] = $fakeHierarchy.Notebooks.Notebook + $result = @( New-SectionGroupConversionConfig @params 6>$null ) + + $result.Count | Should -Be 2 + + $pageCfg1 = $result[0] # First level page + $pageCfg2 = $result[1] # Second level page preceded by a first level page + + $pageCfg1['filePathRel'] | Should -Be 'p0.0-test' + $pageCfg1['fileName'] | Should -Be 'p0.0-test.md' + $pageCfg2['pagePrefix'] | Should -Be "p0.0-test$( [io.path]::DirectorySeparatorChar )" + $pageCfg2['filePathRel'] | Should -Be "p0.0-test$( [io.path]::DirectorySeparatorChar )p0.1-test" + $pageCfg2['fileName'] | Should -Be 'p0.1-test.md' + $pageCfg2['fileDirectory'] | Should -Match "$( [regex]::Escape("$( [io.path]::DirectorySeparatorChar )p0.0-test") )$" + } + It "Should determine attachment references correctly" { $result = @( New-SectionGroupConversionConfig @params 6>$null ) @@ -1792,6 +1853,14 @@ Describe 'Convert-OneNotePage' -Tag 'Unit' { Assert-MockCalled -CommandName Set-ContentNoBom -ParameterFilter { $LiteralPath } -Times 1 -Scope It } + It "Does not halt conversion if mutating markdown content fails, and reports the markdown file path" { + Mock Get-Content -ParameterFilter { $LiteralPath -and ! $Raw } { throw } + + $err = Convert-OneNotePage @params 6>$null 2>&1 + + $err.Exception.Message | Select-Object -First 1 | Should -match "Failed to mutate markdown content of $( [regex]::Escape($params['ConversionConfig']['filePathNormal']) )" + } + It "Does a dry run" { Mock New-Item { 'foo' } Mock Remove-Item { 'foo' } diff --git a/ConvertOneNote2MarkDown-v2.ps1 b/ConvertOneNote2MarkDown-v2.ps1 index 3668cba..a429c33 100644 --- a/ConvertOneNote2MarkDown-v2.ps1 +++ b/ConvertOneNote2MarkDown-v2.ps1 @@ -404,7 +404,7 @@ Function Truncate-PathFileName { $name = Split-Path $Path -Leaf if ($name.Length -gt $maxLength) { $parent = Split-Path $Path -Parent - $truncatedName = $name.Substring(0, $maxLength) + $truncatedName = $name.Substring(0, $maxLength).TrimEnd('.', ' ') # Windows does not support file or folder names ending with periods or spaces [io.path]::combine( $parent, $truncatedName ) }else { $Path @@ -433,6 +433,8 @@ Function Remove-InvalidFileNameChars { } else { $newName -replace "\s", "-" } + # Remove trailing periods and spaces. Windows strips them from file and folder names, so a folder 'foo.' would be created as 'foo', and long paths like '\\?\C:\notes\foo.\bar.md' would not be found + $newName = $newName.TrimEnd('.', ' ') return $newName } @@ -1301,7 +1303,7 @@ Function Convert-OneNotePage { Set-ContentNoBom -LiteralPath $pageCfg['filePath'] -Value $content -ErrorAction Stop # Use -LiteralPath so that characters like '(', ')', '[', ']', '`', "'", '"' are supported. Or else we will get an error "Cannot find path 'xxx' because it does not exist" } }catch { - Write-Error "Failed to mutate markdown content: $( $_.Exception.Message )" + Write-Error "Failed to mutate markdown content of $( $pageCfg['filePathNormal'] ). Exception: $( $_.Exception.Message )" } "Markdown file ready: $( $pageCfg['filePathNormal'] )" | Write-Host -ForegroundColor Green