@@ -17,6 +17,7 @@ module Text.Pandoc.Writers.OpenDocument ( writeOpenDocument ) where
1717import Control.Arrow ((***), (>>>))
1818import Control.Monad.State.Strict hiding (when)
1919import Data.Char (chr)
20+import Data.Foldable (find)
2021import Data.List (sortOn, sortBy, foldl')
2122import qualified Data.Map as Map
2223import Data.Maybe (fromMaybe, isNothing)
@@ -35,6 +36,7 @@ import Text.DocLayout
3536import Text.Pandoc.Shared (linesToPara, tshow, blocksToInlines)
3637import Text.Pandoc.Templates (renderTemplate)
3738import qualified Text.Pandoc.Translations as Term (Term(Figure, Table))
39+import Text.Pandoc.Walk
3840import Text.Pandoc.Writers.Math
3941import Text.Pandoc.Writers.Shared
4042import qualified Text.Pandoc.Writers.AnnotatedTable as Ann
@@ -54,6 +56,11 @@ plainToPara x = x
5456
5557type OD m = StateT WriterState m
5658
59+data ReferenceType
60+ = HeaderRef
61+ | TableRef
62+ | ImageRef
63+
5764data WriterState =
5865 WriterState { stNotes :: [Doc Text]
5966 , stTableStyles :: [Doc Text]
@@ -69,6 +76,7 @@ data WriterState =
6976 , stImageId :: Int
7077 , stTableCaptionId :: Int
7178 , stImageCaptionId :: Int
79+ , stIdentTypes :: [(Text,ReferenceType)]
7280 }
7381
7482defaultWriterState :: WriterState
@@ -86,6 +94,7 @@ defaultWriterState =
8694 , stImageId = 1
8795 , stTableCaptionId = 1
8896 , stImageCaptionId = 1
97+ , stIdentTypes = []
8998 }
9099
91100when :: Bool -> Doc Text -> Doc Text
@@ -243,6 +252,12 @@ writeOpenDocument opts (Pandoc meta blocks) = do
243252 meta
244253 ((body, metadata),s) <- flip runStateT
245254 defaultWriterState $ do
255+ let collectInlineIdent (Image (ident,_,_) _ _) = [(ident,ImageRef)]
256+ collectInlineIdent _ = []
257+ let collectBlockIdent (Header _ (ident,_,_) _) = [(ident,HeaderRef)]
258+ collectBlockIdent (Table (ident,_,_) _ _ _ _ _) = [(ident,TableRef)]
259+ collectBlockIdent _ = []
260+ modify $ \s -> s{ stIdentTypes = query collectBlockIdent blocks ++ query collectInlineIdent blocks }
246261 m <- metaToContext opts
247262 (blocksToOpenDocument opts)
248263 (fmap chomp . inlinesToOpenDocument opts)
@@ -411,7 +426,7 @@ blockToOpenDocument o bs
411426 inTags True "text:list" [ ("text:style-name", "L" <> tshow ln)]
412427 <$> orderedListToOpenDocument o pn b
413428 table :: PandocMonad m => Ann.Table -> OD m (Doc Text)
414− table (Ann.Table _ (Caption _ c) colspecs thead tbodies _) = do
429+ table (Ann.Table (ident, _, _) (Caption _ c) colspecs thead tbodies _) = do
415430 tn <- length <$> gets stTableStyles
416431 pn <- length <$> gets stParaStyles
417432 let genIds = map chr [65..]
@@ -433,7 +448,7 @@ blockToOpenDocument o bs
433448 then return empty
434449 else inlinesToOpenDocument o (blocksToInlines c) >>=
435450 if isEnabled Ext_native_numbering o
436− then numberedTableCaption
451+ then numberedTableCaption ident
437452 else unNumberedCaption "TableCaption"
438453 th <- colHeadsToOpenDocument o (map fst paraHStyles) thead
439454 tr <- mapM (tableBodyToOpenDocument o (map fst paraStyles)) tbodies
@@ -442,36 +457,39 @@ blockToOpenDocument o bs
442457 , ("table:style-name", name)
443458 ] (vcat columns $$ th $$ vcat tr)
444459 return $ captionDoc $$ tableDoc
445− figure attr caption source title | null caption =
460+ figure attr@(ident, _, _) caption source title | null caption =
446461 withParagraphStyle o "Figure" [Para [Image attr caption (source,title)]]
447462 | otherwise = do
448463 imageDoc <- withParagraphStyle o "FigureWithCaption" [Para [Image attr caption (source,title)]]
449464 captionDoc <- inlinesToOpenDocument o caption >>=
450465 if isEnabled Ext_native_numbering o
451− then numberedFigureCaption
466+ then numberedFigureCaption ident
452467 else unNumberedCaption "FigureCaption"
453468 return $ imageDoc $$ captionDoc
454469
455470
456−numberedTableCaption :: PandocMonad m => Doc Text -> OD m (Doc Text)
457−numberedTableCaption caption = do
471+numberedTableCaption :: PandocMonad m => Text -> Doc Text -> OD m (Doc Text)
472+numberedTableCaption ident caption = do
458473 id' <- gets stTableCaptionId
459474 modify (\st -> st{ stTableCaptionId = id' + 1 })
460475 capterm <- translateTerm Term.Table
461− return $ numberedCaption "TableCaption" capterm "Table" id' caption
476+ return $ numberedCaption "TableCaption" capterm "Table" id' ident caption
462477
463−numberedFigureCaption :: PandocMonad m => Doc Text -> OD m (Doc Text)
464−numberedFigureCaption caption = do
478+numberedFigureCaption :: PandocMonad m => Text -> Doc Text -> OD m (Doc Text)
479+numberedFigureCaption ident caption = do
465480 id' <- gets stImageCaptionId
466481 modify (\st -> st{ stImageCaptionId = id' + 1 })
467482 capterm <- translateTerm Term.Figure
468− return $ numberedCaption "FigureCaption" capterm "Illustration" id' caption
483+ return $ numberedCaption "FigureCaption" capterm "Illustration" id' ident caption
469484
470−numberedCaption :: Text -> Text -> Text -> Int -> Doc Text -> Doc Text
471−numberedCaption style term name num caption =
485+numberedCaption :: Text -> Text -> Text -> Int -> Text -> Doc Text -> Doc Text
486+numberedCaption style term name num ident caption =
472487 let t = text $ T.unpack term
473488 r = num - 1
474− s = inTags False "text:sequence" [ ("text:ref-name", "ref" <> name <> tshow r),
489+ ident' = case ident of
490+ "" -> "ref" <> name <> tshow r
491+ _ -> ident
492+ s = inTags False "text:sequence" [ ("text:ref-name", ident'),
475493 ("text:name", name),
476494 ("text:formula", "ooow:" <> name <> "+1"),
477495 ("style:num-format", "1") ] $ text $ show num
@@ -607,7 +625,9 @@ inlineToOpenDocument o ils
607625 else do
608626 report $ InlineNotRendered ils
609627 return empty
610− Link _ l (s,t) -> mkLink s t <$> inlinesToOpenDocument o l
628+ Link _ l (s,t) -> do
629+ identTypes <- gets stIdentTypes
630+ mkLink o identTypes s t <$> inlinesToOpenDocument o l
611631 Image attr _ (s,t) -> mkImg attr s t
612632 Note l -> mkNote l
613633 where
@@ -619,10 +639,6 @@ inlineToOpenDocument o ils
619639 unhighlighted s = inlinedCode $ preformatted s
620640 preformatted s = handleSpaces $ escapeStringForXML s
621641 inlinedCode s = return $ inTags False "text:span" [("text:style-name", "Source_Text")] s
622− mkLink s t = inTags False "text:a" [ ("xlink:type" , "simple")
623− , ("xlink:href" , s )
624− , ("office:name", t )
625− ] . inSpanTags "Definition"
626642 mkImg (_, _, kvs) s _ = do
627643 id' <- gets stImageId
628644 modify (\st -> st{ stImageId = id' + 1 })
@@ -659,6 +675,45 @@ inlineToOpenDocument o ils
659675 addNote nn
660676 return nn
661677
678+mkLink :: WriterOptions -> [(Text,ReferenceType)] -> Text -> Text -> Doc Text -> Doc Text
679+mkLink o identTypes s t d =
680+ let maybeIdentAndType = case T.uncons s of
681+ Just ('#', ident) -> find ((ident ==) . fst) identTypes
682+ _ -> Nothing
683+ d' = inSpanTags "Definition" d
684+ ref refType format ident = inTags False refType
685+ [ ("text:reference-format", format ),
686+ ("text:ref-name", ident) ]
687+ inlineSpace = selfClosingTag "text:s" []
688+ bookmarkRef = ref "text:bookmark-ref"
689+ bookmarkRefNumber ident = bookmarkRef "number" ident mempty
690+ bookmarkRefName ident = bookmarkRef "text" ident d
691+ bookmarkRefNameNumber ident = bookmarkRefNumber ident <> inlineSpace <> bookmarkRefName ident
692+ bookmarkRef'
693+ | isEnabled Ext_xrefs_number o && isEnabled Ext_xrefs_name o = bookmarkRefNameNumber
694+ | isEnabled Ext_xrefs_name o = bookmarkRefName
695+ | otherwise = bookmarkRefNumber
696+ sequenceRef = ref "text:sequence-ref"
697+ sequenceRefNumber ident = sequenceRef "value" ident mempty
698+ sequenceRefName ident = sequenceRef "caption" ident d
699+ sequenceRefNameNumber ident = sequenceRefNumber ident <> inlineSpace <> sequenceRefName ident
700+ sequenceRef'
701+ | isEnabled Ext_xrefs_number o && isEnabled Ext_xrefs_name o = sequenceRefNameNumber
702+ | isEnabled Ext_xrefs_name o = sequenceRefName
703+ | otherwise = sequenceRefNumber
704+ link = inTags False "text:a" [ ("xlink:type" , "simple")
705+ , ("xlink:href" , s )
706+ , ("office:name", t )
707+ ] d'
708+ linkOrReference = case maybeIdentAndType of
709+ Just (ident, HeaderRef) -> bookmarkRef' ident
710+ Just (ident, TableRef) -> sequenceRef' ident
711+ Just (ident, ImageRef) -> sequenceRef' ident
712+ _ -> link
713+ in if isEnabled Ext_xrefs_name o || isEnabled Ext_xrefs_number o
714+ then linkOrReference
715+ else link
716+
662717bulletListStyle :: PandocMonad m => Int -> OD m (Int,(Int,[Doc Text]))
663718bulletListStyle l = do
664719 let doStyles i = inTags True "text:list-level-style-bullet"