pandoc-crossref 0.1.2.4 → 0.1.3.0
raw patch · 11 files changed
+101/−33 lines, 11 filesdep ~pandoc
Dependency ranges changed: pandoc
Files
- README.md +14/−1
- pandoc-crossref.cabal +3/−3
- src/References/Accessors.hs +3/−0
- src/References/Blocks.hs +26/−9
- src/References/List.hs +2/−6
- src/References/Refs.hs +7/−8
- src/References/Types.hs +4/−3
- src/Util/Options.hs +8/−2
- src/Util/Settings.hs +2/−0
- src/Util/Util.hs +4/−0
- test-pandoc-crossref.hs +28/−1
README.md view
@@ -77,6 +77,16 @@ There are a couple options to add code block labels. Those work only if code block id starts with `lst:`, e.g. `{#lst:label}` +### Section labels++You can also reference sections of any level. Section labels use native pandoc syntax, but must start with "sec:", e.g.++```markdown+# Section {#sec:section}+```++You can also use `autoSectionLabels` variable to automatically prepend all section labels (automatically generated with pandoc included) with "sec:". Bear in mind that references can't contain periods, commas etc, so some auto-generated labels will still be unusable.+ #### `caption` attribute `caption` attribute will be treated as code block caption. If code block has both id and `caption` attributes, it will be treated as numbered code block.@@ -168,7 +178,8 @@ Following variables are supported: * `cref`: if True, latex export will use `\cref` from cleveref package. Only relevant for LaTeX output. `\usepackage{cleveref}` will be automatically added to `header-includes`.-* `chapter`: if True, number elements as `chapter.item`, and restart `item` on each first-level heading (as `--chapters` for latex/pdf output)+* `chapters`: if True, number elements as `chapter.item`, and restart `item` on each first-level heading (as `--chapters` for latex/pdf output)+* `chaptersDepth`, default `1`: header level to treat as "chapter". If `chaptersDepth>1`, then items will be prefixed with several numbers, corresponding to header numbers, e.g. `fig. 1.4.3`. * `listings`: if True, generate code blocks for `listings` package. Only relevant for LaTeX output. `\usepackage{listings}` will be automatically added to `header-includes`. You need to specify `--listings` option as well. * `codeBlockCaptions`: if True, parse table-style code block captions. * `figureTitle`, default `Figure`: Word(s) to prepend to figure titles, e.g. `Figure 1: Description`@@ -179,6 +190,8 @@ * `eqnPrefix`, default `eq.`, `eqns.`: Prefix for references to equations, e.g. `eqns. 3,4` * `tblPrefix`, default `tbl.`, `tbls.`: Prefix for references to tables, e.g. `tbl. 2` * `lstPrefix`, default `lst.`, `lsts.`: Prefix for references to lists, e.g. `lsts. 2,5`+* `secPrefix`, default `sec.`, `secs.`: Prefix for references to sections, e.g. `secs. 2,5`+* `autoSectionLabels`, default `false`: Automatically prefix all section labels with `sec:`. Note that this messes with pandoc's automatic header references. * `chapDelim`, default `.`: Delimiter between chapter number and item number. * `rangeDelim`, default `-`: Delimiter between reference ranges, e.g. `eq. 2-5` * `lofTitle`, default `# List of Figures`: Title for list of figures (lof)
pandoc-crossref.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: pandoc-crossref-version: 0.1.2.4+version: 0.1.3.0 synopsis: Pandoc filter for cross-references description: pandoc-crossref is a pandoc filter for numbering figures, equations, tables and cross-references to them. license: GPL-2@@ -23,7 +23,7 @@ source-repository this type: git location: https://github.com/lierdakil/pandoc-crossref- tag: v0.1.2.4+ tag: v0.1.3.0 executable pandoc-crossref main-is: pandoc-crossref.hs@@ -73,7 +73,7 @@ other-extensions: CPP hs-source-dirs: ., src Build-Depends: base >=4.2 && <5- , pandoc >= 1.13 && <1.15+ , pandoc >= 1.13 && <1.16 , mtl >= 1.1 && <2.3 , containers >= 0.1 && <0.6 , pandoc-types >= 1.12.4.1 && < 1.13
src/References/Accessors.hs view
@@ -14,3 +14,6 @@ lstRefs' :: Accessor References RefMap lstRefs' new r@References{lstRefs=old} = (old, r{lstRefs=new})++secRefs' :: Accessor References RefMap+secRefs' new r@References{secRefs=old} = (old, r{secRefs=new})
src/References/Blocks.hs view
@@ -15,12 +15,21 @@ import Util.Template replaceBlocks :: Options -> Block -> WS Block-replaceBlocks opts x@(Header 1 (_, cls, _) _)- | sepChapters opts+replaceBlocks opts (Header n (label, cls, attrs) text') = do- unless ("unnumbered" `elem` cls) $- modify (\r@References{curChap=cc} -> r{curChap=cc+1})- return x+ let label' = if autoSecLab opts && not ("sec:" `isPrefixOf` label)+ then "sec:"++label+ else label+ unless ("unnumbered" `elem` cls) $ do+ modify $ \r@References{curChap=cc} ->+ let ln = length cc+ inc l = init l ++ [last l + 1]+ cc' | ln > n = inc $ take n cc+ | ln == n = inc cc+ | otherwise = cc ++ take (n-ln) [1,1..]+ in r{curChap=cc'}+ when ("sec:" `isPrefixOf` label') $ replaceAttrSec label' text' secRefs'+ return $ Header n (label', cls, attrs) text' replaceBlocks opts (Para (Image alt img:c)) | Just label <- getRefLabel "fig" c = do@@ -115,12 +124,20 @@ replaceAttr :: Options -> String -> [Inline] -> Accessor References RefMap -> WS [Inline] replaceAttr o label title prop = do- chap <- gets curChap+ chap <- take (chapDepth o) `fmap` gets curChap index <- (1+) `fmap` gets (M.size . M.filter ((==chap) . fst . refIndex) . getProp prop) modify $ modifyProp prop $ M.insert label RefRec { refIndex=(chap,index) , refTitle=normalizeSpaces title }- if sepChapters o && chap>0- then return $ Str (show chap) : chapDelim o ++ [Str (show index)]- else return [Str (show index)]+ return $ chapPrefix (chapDelim o) chap index++replaceAttrSec :: String -> [Inline] -> Accessor References RefMap -> WS ()+replaceAttrSec label title prop+ = do+ chap <- gets curChap+ modify $ modifyProp prop $ M.insert label RefRec {+ refIndex=(init chap,last chap)+ , refTitle=normalizeSpaces title+ }+ return ()
src/References/List.hs view
@@ -24,7 +24,7 @@ makeList opts titlef xs refs = return $ titlef opts ++- (if sepChapters opts+ (if chapDepth opts > 0 then Div ("", ["list"], []) (itemChap `map` refsSorted) else OrderedList style (item `map` refsSorted)) : xs@@ -33,9 +33,5 @@ compare' (_,RefRec{refIndex=i}) (_,RefRec{refIndex=j}) = compare i j item = (:[]) . Plain . refTitle . snd itemChap = Para . uncurry ((. (Space :)) . (++)) . (numWithChap . refIndex &&& refTitle) . snd- numWithChap (c,i)- | c > 0 = s c : chapDelim opts ++ [s i]- | otherwise = [s i]- where- s = Str . show+ numWithChap = uncurry $ chapPrefix (chapDelim opts) style = (1,DefaultStyle,DefaultDelim)
src/References/Refs.hs view
@@ -45,6 +45,7 @@ ,("eq:" ,eqnRefs') ,("tbl:",tblRefs') ,("lst:",lstRefs')+ ,("sec:",secRefs') ] -- accessors to options@@ -53,6 +54,7 @@ ,("eq:" ,eqnPrefix) ,("tbl:",tblPrefix) ,("lst:",lstPrefix)+ ,("sec:",secPrefix) ] prefixes :: [String]@@ -108,16 +110,16 @@ let indices' = groupBy ((==) `on` (fmap fst . fst)) (sort indices) cap = maybe False isFirstUpper $ getLabelPrefix . citationId . head $ cits- return $ normalizeInlines $ getRefPrefix opts prefix cap (length cits - 1) ++ concatMap (makeIndices opts) indices'+ return $ normalizeInlines $ getRefPrefix opts prefix cap (length cits - 1) ++ intercalate [Str ",", Space] (makeIndices opts `map` indices') -getRefIndex :: String -> Citation -> WS (Maybe (Int, Int), [Inline])+getRefIndex :: String -> Citation -> WS (Maybe ([Int], Int), [Inline]) getRefIndex prefix Citation{citationId=cid,citationSuffix=suf} = (\x -> (x,suf)) `fmap` gets (fmap refIndex . M.lookup lab . getProp prop) where prop = lookupUnsafe prefix accMap lab = prefix ++ getLabelWithoutPrefix cid -makeIndices :: Options -> [(Maybe (Int, Int), [Inline])] -> [Inline]+makeIndices :: Options -> [(Maybe ([Int], Int), [Inline])] -> [Inline] makeIndices _ s | any (isNothing . fst) s = [Strong [Str "??"]] makeIndices o s = intercalate sep $ reverse $ map f $ foldl' f2 [] $ map (A.first fromJust) $ filter (isJust . fst) s where@@ -132,8 +134,5 @@ f [w] = show' w -- single value f [w1,w2] = show' w2 ++ sep ++ show' w1 -- two values f (x:xs) = show' (last xs) ++ rangeDelim o ++ show' x -- shorten more than two values- sep = [Str ", "]- show' ((c,n),suf) = (if sepChapters o && c>0- then [Str $ show c] ++ chapDelim o ++ [Str $ show n]- else [Str $ show n])- ++ suf+ sep = [Str ",", Space]+ show' ((c,n),suf) = chapPrefix (chapDelim o) c n ++ suf
src/References/Types.hs view
@@ -10,7 +10,7 @@ import Control.Monad.State import Data.Default -data RefRec = RefRec { refIndex :: (Int, Int)+data RefRec = RefRec { refIndex :: ([Int], Int) , refTitle :: [Inline] } deriving (Show, Eq) @@ -21,12 +21,13 @@ , eqnRefs :: RefMap , tblRefs :: RefMap , lstRefs :: RefMap- , curChap :: Int+ , secRefs :: RefMap+ , curChap :: [Int] } deriving (Show, Eq) --state monad type WS a = State References a instance Default References where- def = References n n n n 0+ def = References n n n n n [] where n = M.empty
src/Util/Options.hs view
@@ -10,13 +10,15 @@ -- import Control.Monad.Identity data Options = Options { useCleveref :: Bool- , sepChapters :: Bool+ , chapDepth :: Int , useListings :: Bool , cbCaptions :: Bool+ , autoSecLab :: Bool , figPrefix :: Bool -> Int -> [Inline] , eqnPrefix :: Bool -> Int -> [Inline] , tblPrefix :: Bool -> Int -> [Inline] , lstPrefix :: Bool -> Int -> [Inline]+ , secPrefix :: Bool -> Int -> [Inline] , chapDelim :: [Inline] , rangeDelim :: [Inline] , lofTitle :: [Block]@@ -32,13 +34,17 @@ getOptions dtv fmt = Options { useCleveref = getMetaBool "cref" dtv- , sepChapters = getMetaBool "chapters" dtv+ , chapDepth = if getMetaBool "chapters" dtv+ then read $ getMetaString "chaptersDepth" dtv+ else 0 , useListings = getMetaBool "listings" dtv , cbCaptions = getMetaBool "codeBlockCaptions" dtv+ , autoSecLab = getMetaBool "autoSectionLabels" dtv , figPrefix = tryCapitalizeM (flip (getMetaList toInlines) dtv) "figPrefix" , eqnPrefix = tryCapitalizeM (flip (getMetaList toInlines) dtv) "eqnPrefix" , tblPrefix = tryCapitalizeM (flip (getMetaList toInlines) dtv) "tblPrefix" , lstPrefix = tryCapitalizeM (flip (getMetaList toInlines) dtv) "lstPrefix"+ , secPrefix = tryCapitalizeM (flip (getMetaList toInlines) dtv) "secPrefix" , chapDelim = getMetaInlines "chapDelim" dtv , rangeDelim = getMetaInlines "rangeDelim" dtv , lofTitle = getMetaBlock "lofTitle" dtv
src/Util/Settings.hs view
@@ -32,6 +32,7 @@ , ("eqnPrefix" , MetaList [MetaInlines [Str "eq."], MetaInlines [Str "eqns."]]) , ("tblPrefix" , MetaList [MetaInlines [Str "tbl."], MetaInlines [Str "tbls."]]) , ("lstPrefix" , MetaList [MetaInlines [Str "lst."], MetaInlines [Str "lsts."]])+ , ("secPrefix" , MetaList [MetaInlines [Str "sec."], MetaInlines [Str "secs."]]) , ("lofTitle" , MetaBlocks [Header 1 nullAttr [Str "List",Space,Str "of",Space,Str "Figures"]]) , ("lotTitle" , MetaBlocks [Header 1 nullAttr [Str "List",Space,Str "of",Space,Str "Tables"]]) , ("lolTitle" , MetaBlocks [Header 1 nullAttr [Str "List",Space,Str "of",Space,Str "Listings"]])@@ -39,5 +40,6 @@ , ("tableTemplate" , MetaInlines [var "tableTitle",Space,var "i",var "titleDelim",Space,var "t"]) , ("listingTemplate", MetaInlines [var "listingTitle",Space,var "i",var "titleDelim",Space,var "t"]) , ("crossrefYaml" , MetaString "pandoc-crossref.yaml")+ , ("chaptersDepth" , MetaString "1") ] where var = Math DisplayMath
src/Util/Util.hs view
@@ -2,6 +2,7 @@ import Text.Pandoc.Definition import Data.Char (toUpper, toLower, isUpper)+import Data.List (intercalate) isFormat :: String -> Maybe Format -> Bool isFormat fmt (Just (Format f)) = takeWhile (`notElem` "+-") f == fmt@@ -18,3 +19,6 @@ isFirstUpper :: String -> Bool isFirstUpper (x:_) = isUpper x isFirstUpper [] = False++chapPrefix :: [Inline] -> [Int] -> Int -> [Inline]+chapPrefix delim chap index = intercalate delim (map (return . Str . show) (chap++[index]))
test-pandoc-crossref.hs view
@@ -43,6 +43,11 @@ testBlocks (codeBlockDiv "Test code block" "codeblock") (codeBlockDiv "Listing 1: Test code block" "codeblock", def{lstRefs=M.fromList $ refRec' "lst:codeblock" 1 "Test code block"})+ it "Labels sections divs" $+ testBlocks (section "Section Header" 1 "section")+ (section "Section Header" 1 "section",+ def{secRefs=M.fromList $ refRec' "sec:section" 1 "Section Header",+ curChap=[1]}) describe "References.Refs.replaceRefs" $ do it "References one image" $@@ -61,6 +66,12 @@ testRefs' "lst:" [1] [4] lstRefs' "lst.\160\&4" it "References multiple listings" $ testRefs' "lst:" [1..3] [4..6] lstRefs' "lsts.\160\&4-6"+ it "References one section" $+ testRefs' "sec:" [1] [4] secRefs' "sec.\160\&4"+ it "References multiple sections" $+ testRefs' "sec:" [1..3] [4..6] secRefs' "secs.\160\&4-6"+ it "Separates references to different chapter items by a comma" $+ testRefs'' "lst:" [1..6] (zip [1,1..] [4..6] ++ zip [2,2..] [7..9]) lstRefs' "lsts.\160\&1.4-1.6, 2.7-2.9" describe "References.Refs.replaceRefs capitalization" $ do it "References one image" $@@ -79,6 +90,10 @@ testRefs' "Lst:" [1] [4] lstRefs' "Lst.\160\&4" it "References multiple listings" $ testRefs' "Lst:" [1..3] [4..6] lstRefs' "Lsts.\160\&4-6"+ it "References one listing" $+ testRefs' "Sec:" [1] [4] secRefs' "Sec.\160\&4"+ it "References multiple listings" $+ testRefs' "Sec:" [1..3] [4..6] secRefs' "Secs.\160\&4-6" describe "References.List.listOf" $ do it "Generates list of tables" $@@ -127,15 +142,24 @@ refGen :: String -> [Int] -> [Int] -> M.Map String RefRec refGen p l1 l2 = M.fromList $ mconcat $ zipWith refRec'' (((uncapitalizeFirst p++) . show) `map` l1) l2 +refGen' :: String -> [Int] -> [(Int, Int)] -> M.Map String RefRec+refGen' p l1 l2 = M.fromList $ mconcat $ zipWith refRec''' (((uncapitalizeFirst p++) . show) `map` l1) l2+ refRec' :: String -> Int -> String -> [(String, RefRec)]-refRec' ref i tit = [(ref, RefRec{refIndex=(0,i),refTitle=toList $ text tit})]+refRec' ref i tit = [(ref, RefRec{refIndex=([],i),refTitle=toList $ text tit})] refRec'' :: String -> Int -> [(String, RefRec)] refRec'' ref i = refRec' ref i [] +refRec''' :: String -> (Int, Int) -> [(String, RefRec)]+refRec''' ref (c,i) = [(ref, RefRec{refIndex=([c],i),refTitle=toList $ text []})]+ testRefs' :: String -> [Int] -> [Int] -> Accessor References (M.Map String RefRec) -> String -> Expectation testRefs' p l1 l2 prop res = testRefs (para $ citeGen p l1) (setProp prop (refGen p l1 l2) def) (para $ text res) +testRefs'' :: String -> [Int] -> [(Int, Int)] -> Accessor References (M.Map String RefRec) -> String -> Expectation+testRefs'' p l1 l2 prop res = testRefs (para $ citeGen p l1) (setProp prop (refGen' p l1 l2) def) (para $ text res)+ testBlocks :: Blocks -> (Blocks, References) -> Expectation testBlocks arg res = runState (walkM (f defaultOptions) arg) def `shouldBe` res where f = References.Blocks.replaceBlocks@@ -151,6 +175,9 @@ figure :: String -> String -> String -> String -> Blocks figure src title alt ref = para (image src title (text alt) <> ref' "fig" ref)++section :: String -> Int -> String -> Blocks+section text' level label = headerWith ("sec:" ++ label,[],[]) level (text text') equation :: String -> String -> Blocks equation eq ref = para (displayMath eq <> ref' "eq" ref)