Powerpoint writer: Implement syntax highlighting
This also necessitated implementing colors and underlining, though there is currently no way to produce these from markdown. Note that background colors can't be implemented in PowerPoint, so highlighting styles that require these will be incomplete.
This commit is contained in:
parent
63b10cf157
commit
d0a895acee
3 changed files with 87 additions and 29 deletions
10
MANUAL.txt
10
MANUAL.txt
|
@ -2265,11 +2265,11 @@ this syntax:
|
|||
Here `mycode` is an identifier, `haskell` and `numberLines` are classes, and
|
||||
`startFrom` is an attribute with value `100`. Some output formats can use this
|
||||
information to do syntax highlighting. Currently, the only output formats
|
||||
that uses this information are HTML, LaTeX, Docx, and Ms. If highlighting
|
||||
is supported for your output format and language, then the code block above
|
||||
will appear highlighted, with numbered lines. (To see which languages are
|
||||
supported, type `pandoc --list-highlight-languages`.) Otherwise, the code
|
||||
block above will appear as follows:
|
||||
that uses this information are HTML, LaTeX, Docx, Ms, and PowerPoint. If
|
||||
highlighting is supported for your output format and language, then the code
|
||||
block above will appear highlighted, with numbered lines. (To see which
|
||||
languages are supported, type `pandoc --list-highlight-languages`.) Otherwise,
|
||||
the code block above will appear as follows:
|
||||
|
||||
<pre id="mycode" class="haskell numberLines" startFrom="100">
|
||||
<code>
|
||||
|
|
|
@ -38,6 +38,7 @@ import Control.Monad.Except (throwError, catchError)
|
|||
import Control.Monad.Reader
|
||||
import Control.Monad.State
|
||||
import Codec.Archive.Zip
|
||||
import Data.Char (toUpper)
|
||||
import Data.List (intercalate, stripPrefix, nub, union, isPrefixOf)
|
||||
import Data.Default
|
||||
import Text.Pandoc.Compat.Time (formatTime, defaultTimeLocale)
|
||||
|
@ -62,6 +63,7 @@ import System.FilePath.Glob
|
|||
import Text.TeXMath
|
||||
import Text.Pandoc.Writers.Math (convertMath)
|
||||
import Text.Pandoc.Writers.Powerpoint.Presentation
|
||||
import Skylighting (fromColor)
|
||||
|
||||
-- This populates the global ids map with images already in the
|
||||
-- template, so the ids won't be used by images introduced by the
|
||||
|
@ -703,12 +705,14 @@ paraElemToElement Break = return $ mknode "a:br" [] ()
|
|||
paraElemToElement (Run rpr s) = do
|
||||
let sizeAttrs = case rPropForceSize rpr of
|
||||
Just n -> [("sz", (show $ n * 100))]
|
||||
Nothing -> []
|
||||
Nothing -> if rPropCode rpr
|
||||
-- hardcoded size for code for now
|
||||
then [("sz", "1800")]
|
||||
else []
|
||||
attrs = sizeAttrs ++
|
||||
if rPropCode rpr
|
||||
then []
|
||||
else (if rPropBold rpr then [("b", "1")] else []) ++
|
||||
(if rPropBold rpr then [("b", "1")] else []) ++
|
||||
(if rPropItalics rpr then [("i", "1")] else []) ++
|
||||
(if rPropUnderline rpr then [("u", "sng")] else []) ++
|
||||
(case rStrikethrough rpr of
|
||||
Just NoStrike -> [("strike", "noStrike")]
|
||||
Just SingleStrike -> [("strike", "sngStrike")]
|
||||
|
@ -743,10 +747,19 @@ paraElemToElement (Run rpr s) = do
|
|||
]
|
||||
in [mknode "a:hlinkClick" linkAttrs ()]
|
||||
Nothing -> return []
|
||||
let propContents = if rPropCode rpr
|
||||
let colorContents = case rSolidFill rpr of
|
||||
Just color ->
|
||||
case fromColor color of
|
||||
'#':hx -> [mknode "a:solidFill" []
|
||||
[mknode "a:srgbClr" [("val", map toUpper hx)] ()]
|
||||
]
|
||||
_ -> []
|
||||
Nothing -> []
|
||||
let codeContents = if rPropCode rpr
|
||||
then [mknode "a:latin" [("typeface", "Courier")] ()]
|
||||
else linkProps
|
||||
return $ mknode "a:r" [] [ mknode "a:rPr" attrs propContents
|
||||
else []
|
||||
let propContents = linkProps ++ colorContents ++ codeContents
|
||||
return $ mknode "a:r" [] [ mknode "a:rPr" attrs $ propContents
|
||||
, mknode "a:t" [] s
|
||||
]
|
||||
paraElemToElement (MathElem mathType texStr) = do
|
||||
|
|
|
@ -73,6 +73,10 @@ import Text.Pandoc.Writers.Shared (metaValueToInlines)
|
|||
import qualified Data.Map as M
|
||||
import qualified Data.Set as S
|
||||
import Data.Maybe (maybeToList)
|
||||
import Text.Pandoc.Highlighting
|
||||
import qualified Data.Text as T
|
||||
import Control.Applicative ((<|>))
|
||||
import Skylighting
|
||||
|
||||
data WriterEnv = WriterEnv { envMetadata :: Meta
|
||||
, envRunProps :: RunProps
|
||||
|
@ -280,6 +284,10 @@ data RunProps = RunProps { rPropBold :: Bool
|
|||
, rPropCode :: Bool
|
||||
, rPropBlockQuote :: Bool
|
||||
, rPropForceSize :: Maybe Pixels
|
||||
, rSolidFill :: Maybe Color
|
||||
-- TODO: Make a full underline data type with
|
||||
-- the different options.
|
||||
, rPropUnderline :: Bool
|
||||
} deriving (Show, Eq)
|
||||
|
||||
instance Default RunProps where
|
||||
|
@ -292,6 +300,8 @@ instance Default RunProps where
|
|||
, rPropCode = False
|
||||
, rPropBlockQuote = False
|
||||
, rPropForceSize = Nothing
|
||||
, rSolidFill = Nothing
|
||||
, rPropUnderline = False
|
||||
}
|
||||
|
||||
data PicProps = PicProps { picPropLink :: Maybe LinkTarget
|
||||
|
@ -391,8 +401,17 @@ blockToParagraphs (LineBlock ilsList) = do
|
|||
return [Paragraph pProps parElems]
|
||||
-- TODO: work out the attributes
|
||||
blockToParagraphs (CodeBlock attr str) =
|
||||
local (\r -> r{envParaProps = def{pPropMarginLeft = Just 100}}) $
|
||||
blockToParagraphs $ Para [Code attr str]
|
||||
local (\r -> r{ envParaProps = def{pPropMarginLeft = Just 100}
|
||||
, envRunProps = (envRunProps r){rPropCode = True}}) $ do
|
||||
mbSty <- writerHighlightStyle <$> asks envOpts
|
||||
synMap <- writerSyntaxMap <$> asks envOpts
|
||||
case mbSty of
|
||||
Just sty ->
|
||||
case highlight synMap (formatSourceLines sty) attr str of
|
||||
Right pElems -> do pProps <- asks envParaProps
|
||||
return $ [Paragraph pProps pElems]
|
||||
Left _ -> blockToParagraphs $ Para [Str str]
|
||||
Nothing -> blockToParagraphs $ Para [Str str]
|
||||
-- We can't yet do incremental lists, but we should render a
|
||||
-- (BlockQuote List) as a list to maintain compatibility with other
|
||||
-- formats.
|
||||
|
@ -878,3 +897,29 @@ documentToPresentation opts (Pandoc meta blks) =
|
|||
docProps = metaToDocProps meta
|
||||
in
|
||||
(Presentation docProps presSlides, msgs)
|
||||
|
||||
-- --------------------------------------------------------------
|
||||
|
||||
applyTokStyToRunProps :: TokenStyle -> RunProps -> RunProps
|
||||
applyTokStyToRunProps tokSty rProps =
|
||||
rProps{ rSolidFill = tokenColor tokSty <|> rSolidFill rProps
|
||||
, rPropBold = tokenBold tokSty || rPropBold rProps
|
||||
, rPropItalics = tokenItalic tokSty || rPropItalics rProps
|
||||
, rPropUnderline = tokenUnderline tokSty || rPropUnderline rProps
|
||||
}
|
||||
|
||||
formatToken :: Style -> Token -> ParaElem
|
||||
formatToken sty (tokType, txt) =
|
||||
let rProps = def{rPropCode = True, rSolidFill = defaultColor sty}
|
||||
rProps' = case M.lookup tokType (tokenStyles sty) of
|
||||
Just tokSty -> applyTokStyToRunProps tokSty rProps
|
||||
Nothing -> rProps
|
||||
in
|
||||
Run rProps' $ T.unpack txt
|
||||
|
||||
formatSourceLine :: Style -> FormatOptions -> SourceLine -> [ParaElem]
|
||||
formatSourceLine sty _ srcLn = map (formatToken sty) srcLn
|
||||
|
||||
formatSourceLines :: Style -> FormatOptions -> [SourceLine] -> [ParaElem]
|
||||
formatSourceLines sty opts srcLns = intercalate [Break] $
|
||||
map (formatSourceLine sty opts) srcLns
|
||||
|
|
Loading…
Reference in a new issue