git.iko.soy/typeable/pandoc
on master help sign in
Docx writer: make more deterministic to facilitate testing

This will allow us to compare files directly in a golden test. Times are still based on IO, but we will be able to safely skip those. Changes: - `getUniqueId` now calls to the state to get an incremented digit, instead of calling to P.uniqueHash. - we always start the PRNG in mkNumbering/mkAbstractNum with the same seed (1848), so our randoms should be the same each time.

commit9cf9f1f89d31e8a4a65cbdd419a50b6e4e62c9ab authorJesse Rosenthal <jrosenthal@jhu.edu> dateThu 25 Jan 2018, 16:59 (9 years ago) parentae2157f
1 file changed+16−10
src/Text/Pandoc/Writers/Docx.hs+16−10
src/Text/Pandoc/Writers/Docx.hs+16−10
@@ -47,7 +47,7 @@ import qualified Data.Set as Set
4747import qualified Data.Text as T
4848import Data.Time.Clock.POSIX
4949import Skylighting
50−import System.Random (randomR)
50+import System.Random (randomR, StdGen, mkStdGen)
5151import Text.Pandoc.BCP47 (getLang, renderLang)
5252import Text.Pandoc.Class (PandocMonad, report, toLang)
5353import qualified Text.Pandoc.Class as P
@@ -132,6 +132,7 @@ data WriterState = WriterState{
132132 , stTocTitle :: [Inline]
133133 , stDynamicParaProps :: Set.Set String
134134 , stDynamicTextProps :: Set.Set String
135+ , stCurId :: Int
135136 }
136137
137138defaultWriterState :: WriterState
@@ -149,6 +150,7 @@ defaultWriterState = WriterState{
149150 , stTocTitle = [Str "Table of Contents"]
150151 , stDynamicParaProps = Set.empty
151152 , stDynamicTextProps = Set.empty
153+ , stCurId = 20
152154 }
153155
154156type WS m = ReaderT WriterEnv (StateT WriterState m)
@@ -642,7 +644,7 @@ baseListId = 1000
642644
643645mkNumbering :: (PandocMonad m) => [ListMarker] -> m [Element]
644646mkNumbering lists = do
645− elts <- mapM mkAbstractNum (ordNub lists)
647+ elts <- evalStateT (mapM mkAbstractNum (ordNub lists)) (mkStdGen 1848)
646648 return $ elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)]
647649
648650maxListLevel :: Int
@@ -660,10 +662,11 @@ mkNum marker numid =
660662 $ mknode "w:startOverride" [("w:val",show start)] ())
661663 [0..maxListLevel]
662664
663−mkAbstractNum :: (PandocMonad m) => ListMarker -> m Element
665+mkAbstractNum :: (PandocMonad m) => ListMarker -> StateT StdGen m Element
664666mkAbstractNum marker = do
665− gen <- P.newStdGen
666− let (nsid, _) = randomR (0x10000000 :: Integer, 0xFFFFFFFF :: Integer) gen
667+ gen <- get
668+ let (nsid, gen') = randomR (0x10000000 :: Integer, 0xFFFFFFFF :: Integer) gen
669+ put gen'
667670 return $ mknode "w:abstractNum" [("w:abstractNumId",listMarkerToId marker)]
668671 $ mknode "w:nsid" [("w:val", printf "%8x" nsid)] ()
669672 : mknode "w:multiLevelType" [("w:val","multilevel")] ()
@@ -822,10 +825,13 @@ rStyleM styleName = do
822825 let sty' = getStyleId styleName $ sCharStyleMap styleMaps
823826 return $ mknode "w:rStyle" [("w:val",sty')] ()
824827
825−getUniqueId :: (PandocMonad m) => m String
828+getUniqueId :: (PandocMonad m) => WS m String
826829-- the + 20 is to ensure that there are no clashes with the rIds
827830-- already in word/document.xml.rel
828−getUniqueId = (show . (+ 20)) <$> P.newUniqueHash
831+getUniqueId = do
832+ n <- gets stCurId
833+ modify $ \st -> st{stCurId = n + 1}
834+ return $ show n
829835
830836-- | Key for specifying user-defined docx styles.
831837dynamicStyleKey :: String
@@ -1232,7 +1238,7 @@ inlineToOpenXML' opts (Code attrs str) = do
12321238 unhighlighted
12331239inlineToOpenXML' opts (Note bs) = do
12341240 notes <- gets stFootnotes
1235− notenum <- (lift . lift) getUniqueId
1241+ notenum <- getUniqueId
12361242 footnoteStyle <- rStyleM "Footnote Reference"
12371243 let notemarker = mknode "w:r" []
12381244 [ mknode "w:rPr" [] footnoteStyle
@@ -1263,7 +1269,7 @@ inlineToOpenXML' opts (Link _ txt (src,_)) = do
12631269 id' <- case M.lookup src extlinks of
12641270 Just i -> return i
12651271 Nothing -> do
1266− i <- ("rId"++) `fmap` (lift . lift) getUniqueId
1272+ i <- ("rId"++) `fmap` getUniqueId
12671273 modify $ \st -> st{ stExternalLinks =
12681274 M.insert src i extlinks }
12691275 return i
@@ -1277,7 +1283,7 @@ inlineToOpenXML' opts (Image attr alt (src, title)) = do
12771283 Nothing ->
12781284 catchError
12791285 (do (img, mt) <- P.fetchItem src
1280− ident <- ("rId"++) `fmap` (lift . lift) getUniqueId
1286+ ident <- ("rId"++) `fmap` getUniqueId
12811287 let (xpt,ypt) = desiredSizeInPoints opts attr
12821288 (either (const def) id (imageSize opts img))
12831289 -- 12700 emu = 1 pt