diff --git a/ConvertOneNote2MarkDown-v2.Tests.ps1 b/ConvertOneNote2MarkDown-v2.Tests.ps1 index 72d1ae7..8645573 100644 --- a/ConvertOneNote2MarkDown-v2.Tests.ps1 +++ b/ConvertOneNote2MarkDown-v2.Tests.ps1 @@ -313,6 +313,24 @@ Describe "Truncate-PathFileName" -Tag 'Unit' { $path | Truncate-PathFileName -Length $length | Should -Be $expectedPath } + It "Should keep a given -KeepSuffix when truncating" { + $drive = "C:$( [io.path]::DirectorySeparatorChar )" # E.g. C:\ + $path = $drive + ("a" * 1000) + '-1' + $length = 123 + $expectedPath = $drive + ("a" * 121) + '-1' + + $path | Truncate-PathFileName -Length $length -KeepSuffix '-1' | Should -Be $expectedPath + } + + It "Should ignore -KeepSuffix if the filename does not end with it" { + $drive = "C:$( [io.path]::DirectorySeparatorChar )" # E.g. C:\ + $path = $drive + ("a" * 1000) + $length = 123 + $expectedPath = $drive + ("a" * 123) + + $path | Truncate-PathFileName -Length $length -KeepSuffix '-1' | Should -Be $expectedPath + } + } } @@ -833,6 +851,32 @@ Describe 'New-SectionGroupConversionConfig' -Tag 'Unit' { } } + It "Should not match an attachment's name inside a longer attachment name" { + Mock Get-OneNotePageContent { + @' + + + + + + + + + +'@ -as [xml] + } + + $pageCfg = @( New-SectionGroupConversionConfig @params 6>$null ) | Select-Object -First 1 + $content = '\<\\> and \<\<11-36-00002.pdf\>\>' + foreach ($m in ($pageCfg['mutations'] | Where-Object { $_['description'] -eq 'Change inserted attachment(s) filename references' })) { + foreach ($r in $m['replacements']) { + $content = $content -replace $r['searchRegex'], $r['replacement'] + } + } + + $content | Should -Be "\<\<[Datenblatt_11-36-00002.pdf]($( $pageCfg['mediaPathPandoc'] )/Datenblatt_11-36-00002.pdf)\>\> and \<\<[11-36-00002.pdf]($( $pageCfg['mediaPathPandoc'] )/11-36-00002.pdf)\>\>" + } + It "Should generate fully unique docx file for each page, even for identically-named pages in a section" { $result = @( New-SectionGroupConversionConfig @params 6>$null ) @@ -885,6 +929,34 @@ Describe 'New-SectionGroupConversionConfig' -Tag 'Unit' { } } + It "Should keep the unique postfix of identically named pages when truncating long names" { + $longName = 'Some long name ' * 20 + $fakeHierarchy = @" + + + + + + + + + + +"@ -as [xml] + $params['SectionGroups'] = $fakeHierarchy.Notebooks.Notebook + $params['Config']['mdFileNameAndFolderNameMaxLength']['value'] = 100 + + $result = @( New-SectionGroupConversionConfig @params 6>$null ) + + $result.Count | Should -Be 3 + $result[1]['fileName'] | Should -Match '-1\.md$' + $result[2]['fileName'] | Should -Match '-2\.md$' + @( $result | ForEach-Object { $_['filePathNormal'] } | Select-Object -Unique ).Count | Should -Be 3 + foreach ($pageCfg in $result) { + $pageCfg['fileName'].Length | Should -BeLessOrEqual 100 + } + } + It "Should honor config notesdestpath" { if ($env:OS -match 'windows') { $params['Config']['notesdestpath']['value'] = 'D:\foo\bar' diff --git a/ConvertOneNote2MarkDown-v2.ps1 b/ConvertOneNote2MarkDown-v2.ps1 index 3668cba..bb5a62e 100644 --- a/ConvertOneNote2MarkDown-v2.ps1 +++ b/ConvertOneNote2MarkDown-v2.ps1 @@ -386,6 +386,11 @@ Function Truncate-PathFileName { [ValidateRange(0,255)] [int] $Length + , + # A suffix (e.g. the '-1' postfix of a duplicate page name) that must survive truncation + [Parameter()] + [string] + $KeepSuffix = '' ) process { @@ -404,7 +409,11 @@ Function Truncate-PathFileName { $name = Split-Path $Path -Leaf if ($name.Length -gt $maxLength) { $parent = Split-Path $Path -Parent - $truncatedName = $name.Substring(0, $maxLength) + $truncatedName = if ($KeepSuffix -and $name.EndsWith($KeepSuffix) -and $maxLength -gt $KeepSuffix.Length) { + $name.Substring(0, $maxLength - $KeepSuffix.Length) + $KeepSuffix + }else { + $name.Substring(0, $maxLength) + } [io.path]::combine( $parent, $truncatedName ) }else { $Path @@ -800,17 +809,18 @@ Function New-SectionGroupConversionConfig { $pageCfg['filePathRel'] = & { $filePathRel = "$( $pageCfg['pagePrefix'] )$( $pageCfg['nameCompat'] )" - # in case multiple pages with the same name exist in a section, postfix the filename + # In case multiple pages with the same name exist in a section, postfix the filename. + # Compare the names as they will be written (truncated to fit '.md'), so two long names that only differ + # after the cut-off are also recognized as duplicates. The postfix is kept when truncating below, so it can't be cut off again. + $pageCfg['filePathRelKey'] = $filePathRel | Truncate-PathFileName -Length ($config['mdFileNameAndFolderNameMaxLength']['value'] - 3) $recurrence = 0 foreach ($p in $sectionCfg['pages']) { - if ($p['pagePrefix'] -eq $pageCfg['pagePrefix'] -and $p['pathFromRoot'] -eq $pageCfg['pathFromRoot']) { + if ($p['filePathRelKey'] -eq $pageCfg['filePathRelKey']) { $recurrence++ } } - if ($recurrence -gt 0) { - $filePathRel = "$filePathRel-$recurrence" - } - $filePathRel | Truncate-PathFileName -Length $config['mdFileNameAndFolderNameMaxLength']['value'] # Truncate to no more than 255 characters so we don't hit the folder name limit on most file systems on Windows / Linux + $pageCfg['filePathRelPostfix'] = if ($recurrence -gt 0) { "-$recurrence" } else { '' } + "$filePathRel$( $pageCfg['filePathRelPostfix'] )" | Truncate-PathFileName -Length $config['mdFileNameAndFolderNameMaxLength']['value'] -KeepSuffix $pageCfg['filePathRelPostfix'] # Truncate to no more than 255 characters so we don't hit the folder name limit on most file systems on Windows / Linux } $pageCfg['filePathRelUnderscore'] = $pageCfg['filePathRel'].Replace( [io.path]::DirectorySeparatorChar, '_' ) $pageCfg['filePathNormal'] = & { @@ -819,7 +829,7 @@ Function New-SectionGroupConversionConfig { }else { [io.path]::combine( $cfg['notesDirectory'], $sectionCfg['nameCompat'], "$( $pageCfg['filePathRel'] )" ) } - "$( $pathWithoutExtension | Truncate-PathFileName -Length ($config['mdFileNameAndFolderNameMaxLength']['value'] - 3) ).md" # Truncate to no more than 255 characters so we don't hit the file name limit on Windows / Linux + "$( $pathWithoutExtension | Truncate-PathFileName -Length ($config['mdFileNameAndFolderNameMaxLength']['value'] - 3) -KeepSuffix $pageCfg['filePathRelPostfix'] ).md" # Truncate to no more than 255 characters so we don't hit the file name limit on Windows / Linux } $pageCfg['filePathLong'] = "\\?\$( $pageCfg['filePathNormal'] )" # A non-Win32 path. Prefixing with '\\?\' allows Windows Powershell <= 5 (based on Win32) to support long absolute paths. $pageCfg['filePath'] = if ($PSVersionTable.PSVersion.Major -le 5) { @@ -896,7 +906,9 @@ Function New-SectionGroupConversionConfig { description = 'Change inserted attachment(s) filename references' replacements = @( @{ - searchRegex = [regex]::Escape( $attachmentCfg['object'].preferredName ) + # Only where the name is not part of a longer file name: with attachments '11-36-00002.pdf' and 'Datenblatt_11-36-00002.pdf' + # on one page, a plain search for the first one also matched inside the second, nesting one link inside the other + searchRegex = '(?