hpdft 0.4.6.3 → 0.4.6.4
raw patch · 5 files changed
+56/−3 lines, 5 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ PDF.ContentStream: normalizePdfNumber :: String -> String
+ PDF.ContentStream: parsePdfNumber :: String -> Double
+ PDF.Interpret: normalizePdfNumber :: String -> String
+ PDF.Interpret: parsePdfNumber :: String -> Double
Files
- CHANGELOG.md +7/−0
- hpdft.cabal +1/−1
- src/PDF/ContentStream.hs +3/−1
- src/PDF/Interpret.hs +3/−1
- test/Unit.hs +42/−0
CHANGELOG.md view
@@ -1,5 +1,12 @@ # Changelog +## 0.4.6.4 (2026-07-06)++### Fixed++- Content-stream number parsing no longer corrupts negative fractions with an omitted integer part (e.g. `-.24` in a `cm` matrix); the previous bug turned them into large integers, broke the CTM, and left geometry/tagged text extraction empty while legacy/TUI output still looked fine.+- Golden fixture `data/fixtures/negative-fraction-ctm.pdf` and unit tests for `normalizePdfNumber` / `parsePdfNumber` in both the geometry and legacy lexers.+ ## 0.4.6.3 (2026-07-06) ### Added
hpdft.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.8 name: hpdft-version: 0.4.6.3+version: 0.4.6.4 synopsis: PDF parsing library and CLI for text, layout, diff, images, and forms description: hpdft is a Haskell library and command-line tool for parsing PDF files.
src/PDF/ContentStream.hs view
@@ -3,6 +3,8 @@ module PDF.ContentStream ( parseStream , parseColorSpace+ , normalizePdfNumber+ , parsePdfNumber ) where import Data.Char (chr, ord)@@ -871,7 +873,7 @@ normalizePdfNumber s | null s = s | head s == '.' = '0' : s- | length s >= 2 && head s == '-' && s !! 1 == '.' = '-' : '0' : drop 2 s+ | length s >= 2 && head s == '-' && s !! 1 == '.' = '-' : '0' : drop 1 s | otherwise = s parsePdfNumber :: String -> Double
src/PDF/Interpret.hs view
@@ -17,6 +17,8 @@ , bytesToCodes , encodingUnicode , unicodeBytesToCodes+ , normalizePdfNumber+ , parsePdfNumber ) where import PDF.Definition@@ -1023,7 +1025,7 @@ normalizePdfNumber s | null s = s | head s == '.' = '0' : s- | length s >= 2 && head s == '-' && s !! 1 == '.' = '-' : '0' : drop 2 s+ | length s >= 2 && head s == '-' && s !! 1 == '.' = '-' : '0' : drop 1 s | otherwise = s parsePdfNumber :: String -> Double
test/Unit.hs view
@@ -12,6 +12,8 @@ , encodingUnicode , unicodeBytesToCodes )+import qualified PDF.Interpret as Interpret+import qualified PDF.ContentStream as ContentStream import PDF.Layout (LayoutOptions(..), defaultLayoutOptions, needsAozoraBar, aozoraRuby, layoutParagraphs, layoutParagraphsWith, layoutPageText, layoutDocument, sortLinesByReadingOrder, linesFromGlyphs, Line(..)) import PDF.Structure (StructElem(..), StructKid(..), structTree, logicalOrder) import PDF.Document (Document(..), openDocument)@@ -187,6 +189,7 @@ ++ taggedEndToEndResults ++ textStreamResults ++ cmapEncodingResults+ ++ normalizePdfNumberResults ++ tuiScrollResults let failures = [msg | Fail msg <- results] passed = length results - length failures@@ -1376,4 +1379,43 @@ , assertBool "bytesToCodes JISmap 2-byte fixed" (bytesToCodes jfi [0x46, 0x7C, 0x4B, 0x5C] == [0x467C, 0x4B5C]) ]++normalizePdfNumberResults :: [Result]+normalizePdfNumberResults =+ let cases =+ [ (".5", 0.5)+ , ("-.5", -0.5)+ , ("-.23999999", -0.23999999)+ , ("1.5", 1.5)+ , ("-1.5", -1.5)+ , ("5.", 5.0)+ ]+ abnormal =+ [ ""+ , "-"+ , "+"+ , "-.5."+ , "."+ , "-."+ ]+ in [ assertDoubleEq ("Interpret.parsePdfNumber " ++ s) n (Interpret.parsePdfNumber s)+ | (s, n) <- cases+ ]+ ++ [ assertDoubleEq ("ContentStream.parsePdfNumber " ++ s) n (ContentStream.parsePdfNumber s)+ | (s, n) <- cases+ ]+ ++ [ assertBool ("Interpret.parsePdfNumber abnormal " ++ show s)+ (Interpret.parsePdfNumber s `seq` True)+ | s <- abnormal+ ]+ ++ [ assertBool ("ContentStream.parsePdfNumber abnormal " ++ show s)+ (ContentStream.parsePdfNumber s `seq` True)+ | s <- abnormal+ ]+ ++ [ assertTextEq ("Interpret.normalizePdfNumber " ++ s) (T.pack expected) (T.pack (Interpret.normalizePdfNumber s))+ | (s, expected) <- [(".5", "0.5"), ("-.5", "-0.5"), ("-.23999999", "-0.23999999")]+ ]+ ++ [ assertTextEq ("ContentStream.normalizePdfNumber " ++ s) (T.pack expected) (T.pack (ContentStream.normalizePdfNumber s))+ | (s, expected) <- [(".5", "0.5"), ("-.5", "-0.5"), ("-.23999999", "-0.23999999")]+ ]