{-
Copyright (C) 2007-8 John MacFarlane <jgm@berkeley.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}{- |
Module : Text.Pandoc.Writers.ConTeXt
Copyright : Copyright (C) 2007-8 John MacFarlane
License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
Stability : alpha
Portability : portable
Conversion of 'Pandoc' format into ConTeXt.
-}moduleText.Pandoc.Writers.ConTeXt(writeConTeXt)whereimportText.Pandoc.DefinitionimportText.Pandoc.SharedimportText.Printf(printf)importData.List(isSuffixOf,intercalate,intersperse)importControl.Monad.StateimportText.PrettyPrint.HughesPJhiding(Str)importText.Pandoc.Templates(renderTemplate)dataWriterState=WriterState{stNextRef::Int-- number of next URL reference,stOrderedListLevel::Int-- level of ordered list,stOptions::WriterOptions-- writer options}orderedListStyles::[[Char]]orderedListStyles=cycle["[n]","[a]","[r]","[g]"]-- | Convert Pandoc to ConTeXt.writeConTeXt::WriterOptions->Pandoc->StringwriteConTeXtoptionsdocument=letdefaultWriterState=WriterState{stNextRef=1,stOrderedListLevel=0,stOptions=options}inevalState(pandocToConTeXtoptionsdocument)defaultWriterStatepandocToConTeXt::WriterOptions->Pandoc->StateWriterStateStringpandocToConTeXtoptions(Pandoc(Metatitleauthorsdate)blocks)=dotitletext<-ifnulltitlethenreturn""elseliftMrender$inlineListToConTeXttitleauthorstext<-mapM(liftMrender.inlineListToConTeXt)authorsdatetext<-ifnulldatethenreturn""elseliftMrender$inlineListToConTeXtdatebody<-blockListToConTeXtblocksletmain=renderbodyletcontext=writerVariablesoptions++[("toc",ifwriterTableOfContentsoptionsthen"yes"else""),("body",main),("title",titletext),("date",datetext)]++[("author",a)|a<-authorstext]return$ifwriterStandaloneoptionsthenrenderTemplatecontext$writerTemplateoptionselsemain-- escape things as needed for ConTeXtescapeCharForConTeXt::Char->StringescapeCharForConTeXtch=casechof'{'->"\\letteropenbrace{}"'}'->"\\letterclosebrace{}"'\\'->"\\letterbackslash{}"'$'->"\\$"'|'->"\\letterbar{}"'^'->"\\letterhat{}"'%'->"\\%"'~'->"\\lettertilde{}"'&'->"\\&"'#'->"\\#"'<'->"\\letterless{}"'>'->"\\lettermore{}"'_'->"\\letterunderscore{}"'\160'->"~"x->[x]-- | Escape string for ConTeXtstringToConTeXt::String->StringstringToConTeXt=concatMapescapeCharForConTeXt-- | Convert Pandoc block element to ConTeXt.blockToConTeXt::Block->StateWriterStateBlockWrapperblockToConTeXtNull=return$RegemptyblockToConTeXt(Plainlst)=dost<-getletoptions=stOptionsstcontents<-wrapTeXIfNeededoptionsFalseinlineListToConTeXtlstreturn$RegcontentsblockToConTeXt(Para[Imagetxt(src,_)])=docapt<-inlineListToConTeXttxtreturn$Pad$text"\\placefigure[here,nonumber]{"<>capt<>text"}{\\externalfigure["<>textsrc<>text"]}"blockToConTeXt(Paralst)=dost<-getletoptions=stOptionsstcontents<-wrapTeXIfNeededoptionsFalseinlineListToConTeXtlstreturn$PadcontentsblockToConTeXt(BlockQuotelst)=docontents<-blockListToConTeXtlstreturn$Pad$text"\\startblockquote"$$contents$$text"\\stopblockquote"blockToConTeXt(CodeBlock_str)=return$Reg$text$"\\starttyping\n"++str++"\n\\stoptyping\n"-- \n because \stoptyping can't have anything after it, inc. }blockToConTeXt(RawHtml_)=return$RegemptyblockToConTeXt(BulletListlst)=docontents<-mapMlistItemToConTeXtlstreturn$Pad$text"\\startitemize"$$vcatcontents$$text"\\stopitemize"blockToConTeXt(OrderedList(start,style',delim)lst)=dost<-getletlevel=stOrderedListLevelstput$st{stOrderedListLevel=level+1}contents<-mapMlistItemToConTeXtlstput$st{stOrderedListLevel=level}letstart'=ifstart==1then""else"start="++showstartletdelim'=casedelimofDefaultDelim->""Period->"stopper=."OneParen->"stopper=)"TwoParens->"left=(,stopper=)"letwidth=maximum$maplength$take(lengthcontents)(orderedListMarkers(start,style',delim))letwidth'=(toEnumwidth+1)/2letwidth''=ifwidth'>(1.5::Double)then"width="++showwidth'++"em"else""letspecs2Items=filter(not.null)[start',delim',width'']letspecs2=ifnullspecs2Itemsthen""else"["++intercalate","specs2Items++"]"letstyle''=casestyle'ofDefaultStyle->orderedListStyles!!levelDecimal->"[n]"LowerRoman->"[r]"UpperRoman->"[R]"LowerAlpha->"[a]"UpperAlpha->"[A]"letspecs=style''++specs2return$Pad$text("\\startitemize"++specs)$$vcatcontents$$text"\\stopitemize"blockToConTeXt(DefinitionListlst)=mapMdefListItemToConTeXtlst>>=return.Pad.wrappedBlocksToDocblockToConTeXtHorizontalRule=return$Pad$text"\\thinrule"blockToConTeXt(Headerlevellst)=docontents<-inlineListToConTeXtlstst<-getletopts=stOptionsstletbase=ifwriterNumberSectionsoptsthen"section"else"subject"return$Pad$iflevel>=1&&level<=5thenchar'\\'<>text(concat(replicate(level-1)"sub"))<>textbase<>char'{'<>contents<>char'}'elsecontentsblockToConTeXt(Tablecaptionalignswidthsheadsrows)=doletcolDescriptorcolWidthalignment=(casealignmentofAlignLeft->'l'AlignRight->'r'AlignCenter->'c'AlignDefault->'l'):ifcolWidth==0then"|"else("p("++printf"%.2f"colWidth++"\\textwidth)|")letcolDescriptors="|"++(concat$zipWithcolDescriptorwidthsaligns)headers<-ifallnullheadsthenreturnemptyelseliftM($$text"\\HL")$tableRowToConTeXtheadscaptionText<-inlineListToConTeXtcaptionletcaptionText'=ifnullcaptionthentext"none"elsecaptionTextrows'<-mapMtableRowToConTeXtrowsreturn$Pad$text"\\placetable[here]{"<>captionText'<>char'}'$$text"\\starttable["<>textcolDescriptors<>char']'$$text"\\HL"$$headers$$vcatrows'$$text"\\HL\n\\stoptable"tableRowToConTeXt::[[Block]]->StateWriterStateDoctableRowToConTeXtcols=docols'<-mapMblockListToConTeXtcolsreturn$(vcat(map(text"\\NC "<>)cols'))$$text"\\NC\\AR"listItemToConTeXt::[Block]->StateWriterStateDoclistItemToConTeXtlist=blockListToConTeXtlist>>=return.(text"\\item"$$).(nest2)defListItemToConTeXt::([Inline],[[Block]])->StateWriterStateBlockWrapperdefListItemToConTeXt(term,defs)=doterm'<-inlineListToConTeXttermdef'<-liftM(vcat.intersperse(text""))$mapMblockListToConTeXtdefsreturn$Pad$text"\\startdescr{"<>term'<>char'}'$$def'$$text"\\stopdescr"-- | Convert list of block elements to ConTeXt.blockListToConTeXt::[Block]->StateWriterStateDocblockListToConTeXtlst=mapMblockToConTeXtlst>>=return.wrappedBlocksToDoc-- | Convert list of inline elements to ConTeXt.inlineListToConTeXt::[Inline]-- ^ Inlines to convert->StateWriterStateDocinlineListToConTeXtlst=mapMinlineToConTeXtlst>>=return.hcat-- | Convert inline element to ConTeXtinlineToConTeXt::Inline-- ^ Inline to convert->StateWriterStateDocinlineToConTeXt(Emphlst)=docontents<-inlineListToConTeXtlstreturn$text"{\\em "<>contents<>char'}'inlineToConTeXt(Stronglst)=docontents<-inlineListToConTeXtlstreturn$text"{\\bf "<>contents<>char'}'inlineToConTeXt(Strikeoutlst)=docontents<-inlineListToConTeXtlstreturn$text"\\overstrikes{"<>contents<>char'}'inlineToConTeXt(Superscriptlst)=docontents<-inlineListToConTeXtlstreturn$text"\\high{"<>contents<>char'}'inlineToConTeXt(Subscriptlst)=docontents<-inlineListToConTeXtlstreturn$text"\\low{"<>contents<>char'}'inlineToConTeXt(SmallCapslst)=docontents<-inlineListToConTeXtlstreturn$text"{\\sc "<>contents<>char'}'inlineToConTeXt(Codestr)=return$text$"\\type{"++str++"}"inlineToConTeXt(QuotedSingleQuotelst)=docontents<-inlineListToConTeXtlstreturn$text"\\quote{"<>contents<>char'}'inlineToConTeXt(QuotedDoubleQuotelst)=docontents<-inlineListToConTeXtlstreturn$text"\\quotation{"<>contents<>char'}'inlineToConTeXt(Cite_lst)=inlineListToConTeXtlstinlineToConTeXtApostrophe=return$char'\''inlineToConTeXtEmDash=return$text"---"inlineToConTeXtEnDash=return$text"--"inlineToConTeXtEllipses=return$text"\\ldots{}"inlineToConTeXt(Strstr)=return$text$stringToConTeXtstrinlineToConTeXt(MathInlineMathstr)=return$char'$'<>textstr<>char'$'inlineToConTeXt(MathDisplayMathstr)=return$text"\\startformula "<>textstr<>text" \\stopformula"inlineToConTeXt(TeXstr)=return$textstrinlineToConTeXt(HtmlInline_)=returnemptyinlineToConTeXt(LineBreak)=return$text"\\crlf\n"inlineToConTeXtSpace=return$char' 'inlineToConTeXt(Link[Codestr](src,tit))=-- since ConTeXt has its own inlineToConTeXt(Link[Strstr](src,tit))-- way of printing links... inlineToConTeXt(Linktxt(src,_))=dost<-getletnext=stNextRefstput$st{stNextRef=next+1}letref=shownextlabel<-inlineListToConTeXttxtreturn$text"\\useURL["<>textref<>text"]["<>textsrc<>text"][]["<>label<>text"]\\from["<>textref<>char']'inlineToConTeXt(Image_(src,_))=doreturn$text"{\\externalfigure["<>textsrc<>text"]}"inlineToConTeXt(Notecontents)=docontents'<-blockListToConTeXtcontentsletrawnote=stripTrailingNewlines$rendercontents'-- note: a \n before } is needed when note ends with a \stoptypingletoptNewline="\\stoptyping"`isSuffixOf`rawnotereturn$text"\\footnote{"<>textrawnote<>(ifoptNewlinethenchar'\n'elseempty)<>char'}'