pandoc 0.44 → 0.45
raw patch · 143 files changed
+17457/−11773 lines, 143 filesdep +containersdep +prettydep ~basedep ~networkbinary-added
Dependencies added: containers, pretty
Dependency ranges changed: base, network
Files
- INSTALL +6/−0
- Main.hs +519/−0
- Makefile +87/−92
- PROFILING +1/−3
- README +81/−31
- Text/Pandoc.hs +110/−0
- Text/Pandoc/ASCIIMathML.hs +14/−0
- Text/Pandoc/Blocks.hs +145/−0
- Text/Pandoc/CharacterReferences.hs +327/−0
- Text/Pandoc/Definition.hs +117/−0
- Text/Pandoc/Readers/HTML.hs +496/−0
- Text/Pandoc/Readers/LaTeX.hs +652/−0
- Text/Pandoc/Readers/Markdown.hs +906/−0
- Text/Pandoc/Readers/RST.hs +640/−0
- Text/Pandoc/Readers/TeXMath.hs +222/−0
- Text/Pandoc/Shared.hs +843/−0
- Text/Pandoc/UTF8.hs +45/−0
- Text/Pandoc/Writers/ConTeXt.hs +300/−0
- Text/Pandoc/Writers/DefaultHeaders.hs +59/−0
- Text/Pandoc/Writers/Docbook.hs +301/−0
- Text/Pandoc/Writers/HTML.hs +473/−0
- Text/Pandoc/Writers/LaTeX.hs +319/−0
- Text/Pandoc/Writers/Man.hs +295/−0
- Text/Pandoc/Writers/Markdown.hs +374/−0
- Text/Pandoc/Writers/RST.hs +324/−0
- Text/Pandoc/Writers/RTF.hs +288/−0
- Text/Pandoc/Writers/S5.hs +140/−0
- debian/changelog +267/−0
- debian/control +5/−4
- debian/copyright +1/−1
- debian/rules +3/−1
- freebsd/pkg-descr +1/−1
- html2markdown +32/−27
- macports/Portfile.in +35/−2
- man/man1/hsmarkdown.1.md +1/−1
- man/man1/html2markdown.1.md +3/−0
- man/man1/pandoc.1.md +15/−3
- pandoc.cabal +43/−30
- pandoc.cabal.ghc66 +63/−0
- src/ASCIIMathML.js +0/−945
- src/Main.hs +0/−505
- src/Text/Pandoc.hs +0/−105
- src/Text/Pandoc/ASCIIMathML.hs +0/−14
- src/Text/Pandoc/Blocks.hs +0/−145
- src/Text/Pandoc/CharacterReferences.hs +0/−327
- src/Text/Pandoc/Definition.hs +0/−116
- src/Text/Pandoc/Readers/HTML.hs +0/−499
- src/Text/Pandoc/Readers/LaTeX.hs +0/−649
- src/Text/Pandoc/Readers/Markdown.hs +0/−898
- src/Text/Pandoc/Readers/RST.hs +0/−629
- src/Text/Pandoc/Shared.hs +0/−806
- src/Text/Pandoc/UTF8.hs +0/−44
- src/Text/Pandoc/Writers/ConTeXt.hs +0/−248
- src/Text/Pandoc/Writers/DefaultHeaders.hs +0/−59
- src/Text/Pandoc/Writers/Docbook.hs +0/−297
- src/Text/Pandoc/Writers/HTML.hs +0/−448
- src/Text/Pandoc/Writers/LaTeX.hs +0/−309
- src/Text/Pandoc/Writers/Man.hs +0/−292
- src/Text/Pandoc/Writers/Markdown.hs +0/−360
- src/Text/Pandoc/Writers/RST.hs +0/−323
- src/Text/Pandoc/Writers/RTF.hs +0/−286
- src/Text/Pandoc/Writers/S5.hs +0/−140
- src/headers/ConTeXtHeader +0/−61
- src/headers/DocbookHeader +0/−3
- src/headers/LaTeXHeader +0/−5
- src/headers/RTFHeader +0/−4
- src/headers/S5Header +0/−3
- src/templates/ASCIIMathML.hs +0/−7
- src/templates/DefaultHeaders.hs +0/−52
- src/templates/Makefile +0/−20
- src/templates/S5.hs +0/−133
- src/templates/fillTemplates.pl +0/−131
- src/ui/default/blank.gif binary
- src/ui/default/bodybg.gif binary
- src/ui/default/framing.css +0/−23
- src/ui/default/iepngfix.htc +0/−42
- src/ui/default/opera.css +0/−7
- src/ui/default/outline.css +0/−15
- src/ui/default/pretty.css +0/−86
- src/ui/default/print.css +0/−24
- src/ui/default/s5-core.css +0/−9
- src/ui/default/slides.css +0/−3
- src/ui/default/slides.js +0/−553
- src/wrappers/common.sh +0/−43
- src/wrappers/hsmarkdown.in +0/−5
- src/wrappers/html2markdown.in +0/−157
- src/wrappers/markdown2pdf.in +0/−81
- src/wrappers/tempdir.sh +0/−18
- templates/ASCIIMathML.hs +7/−0
- templates/ASCIIMathML.js +3363/−0
- templates/DefaultHeaders.hs +52/−0
- templates/Makefile +20/−0
- templates/S5.hs +133/−0
- templates/fillTemplates.pl +131/−0
- templates/headers/ConTeXtHeader +67/−0
- templates/headers/DocbookHeader +3/−0
- templates/headers/LaTeXHeader +5/−0
- templates/headers/RTFHeader +4/−0
- templates/headers/S5Header +3/−0
- templates/ui/default/blank.gif binary
- templates/ui/default/bodybg.gif binary
- templates/ui/default/framing.css +23/−0
- templates/ui/default/iepngfix.htc +42/−0
- templates/ui/default/opera.css +7/−0
- templates/ui/default/outline.css +15/−0
- templates/ui/default/pretty.css +86/−0
- templates/ui/default/print.css +24/−0
- templates/ui/default/s5-core.css +9/−0
- templates/ui/default/slides.css +3/−0
- templates/ui/default/slides.js +553/−0
- tests/latex-reader.native +7/−7
- tests/rst-reader.native +27/−4
- tests/rst-reader.rst +17/−0
- tests/s5.basic.html +27/−1
- tests/s5.fancy.html +3185/−866
- tests/s5.fragment.html +27/−1
- tests/s5.inserts.html +27/−1
- tests/s5.native +1/−1
- tests/tables.context +0/−1
- tests/testsuite.native +7/−21
- tests/testsuite.txt +0/−25
- tests/writer.context +388/−283
- tests/writer.docbook +7/−54
- tests/writer.html +59/−46
- tests/writer.latex +13/−45
- tests/writer.man +7/−42
- tests/writer.markdown +0/−17
- tests/writer.native +7/−21
- tests/writer.rst +73/−104
- tests/writer.rtf +10/−24
- web/Makefile +9/−9
- web/css +8/−0
- web/demos +27/−16
- web/footer.html +1/−1
- web/html2x.txt +55/−0
- web/index.txt.in +31/−53
- web/math.txt +17/−0
- web/mkdemos.pl +8/−5
- wrappers/common.sh +43/−0
- wrappers/hsmarkdown.in +5/−0
- wrappers/html2markdown.in +162/−0
- wrappers/markdown2pdf.in +81/−0
- wrappers/tempdir.sh +18/−0
INSTALL view
@@ -161,6 +161,12 @@ This will install the pandoc executable and the Haskell libraries, but not the shell scripts, man pages, or other documentation. +Note: If you are using GHC 6.6.*, you will need to start by+replacing `pandoc.cabal` with a version suitable for GHC 6.6:++ cp pandoc.cabal pandoc.cabal.orig+ cp pandoc.cabal.ghc66 pandoc.cabal + Installing pandoc using MacPorts ================================
+ Main.hs view
@@ -0,0 +1,519 @@+{-+Copyright (C) 2006-7 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 : Main+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley@edu>+ Stability : alpha + Portability : portable++Parses command-line options and calls the appropriate readers and+writers.+-}+module Main where+import Text.Pandoc+import Text.Pandoc.UTF8+import Text.Pandoc.Shared ( joinWithSep, HTMLMathMethod (..) )+import Text.Regex ( mkRegex, matchRegex )+import System.Environment ( getArgs, getProgName, getEnvironment )+import System.Exit ( exitWith, ExitCode (..) )+import System.Console.GetOpt+import System.IO+import Data.Maybe ( fromMaybe )+import Data.List ( isPrefixOf )+import Data.Char ( toLower )+import Control.Monad ( (>>=) )++copyrightMessage :: String+copyrightMessage = "\nCopyright (C) 2006-7 John MacFarlane\n\+ \Web: http://johnmacfarlane.net/pandoc\n\+ \This is free software; see the source for copying conditions. There is no\n\+ \warranty, not even for merchantability or fitness for a particular purpose."++-- | Association list of formats and readers.+readers :: [(String, ParserState -> String -> Pandoc)]+readers = [("native" , readPandoc)+ ,("markdown" , readMarkdown)+ ,("rst" , readRST)+ ,("html" , readHtml)+ ,("latex" , readLaTeX)+ ]++-- | Reader for native Pandoc format.+readPandoc :: ParserState -> String -> Pandoc+readPandoc state input = read input+ +-- | Association list of formats and pairs of writers and default headers.+writers :: [ ( String, ( WriterOptions -> Pandoc -> String, String ) ) ]+writers = [("native" , (writeDoc, ""))+ ,("html" , (writeHtmlString, ""))+ ,("s5" , (writeS5String, defaultS5Header))+ ,("docbook" , (writeDocbook, defaultDocbookHeader))+ ,("latex" , (writeLaTeX, defaultLaTeXHeader))+ ,("context" , (writeConTeXt, defaultConTeXtHeader))+ ,("man" , (writeMan, ""))+ ,("markdown" , (writeMarkdown, ""))+ ,("rst" , (writeRST, ""))+ ,("rtf" , (writeRTF, defaultRTFHeader))+ ]++-- | Writer for Pandoc native format.+writeDoc :: WriterOptions -> Pandoc -> String+writeDoc options = prettyPandoc ++-- | Data structure for command line options.+data Opt = Opt+ { optPreserveTabs :: Bool -- ^ Convert tabs to spaces+ , optTabStop :: Int -- ^ Number of spaces per tab+ , optStandalone :: Bool -- ^ Include header, footer+ , optReader :: String -- ^ Reader format+ , optWriter :: String -- ^ Writer format+ , optParseRaw :: Bool -- ^ Parse unconvertable HTML and TeX+ , optCSS :: String -- ^ CSS file to link to+ , optTableOfContents :: Bool -- ^ Include table of contents+ , optIncludeInHeader :: String -- ^ File to include in header+ , optIncludeBeforeBody :: String -- ^ File to include at top of body+ , optIncludeAfterBody :: String -- ^ File to include at end of body+ , optCustomHeader :: String -- ^ Custom header to use, or "DEFAULT"+ , optTitlePrefix :: String -- ^ Optional prefix for HTML title+ , optOutputFile :: String -- ^ Name of output file+ , optNumberSections :: Bool -- ^ Number sections in LaTeX+ , optIncremental :: Bool -- ^ Use incremental lists in S5+ , optSmart :: Bool -- ^ Use smart typography+ , optHTMLMathMethod :: HTMLMathMethod -- ^ Method to print HTML math+ , optDumpArgs :: Bool -- ^ Output command-line arguments+ , optIgnoreArgs :: Bool -- ^ Ignore command-line arguments+ , optStrict :: Bool -- ^ Use strict markdown syntax+ , optReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst+ , optWrapText :: Bool -- ^ Wrap text+ }++-- | Defaults for command-line options.+defaultOpts :: Opt+defaultOpts = Opt+ { optPreserveTabs = False+ , optTabStop = 4+ , optStandalone = False+ , optReader = "" -- null for default reader+ , optWriter = "" -- null for default writer+ , optParseRaw = False+ , optCSS = ""+ , optTableOfContents = False+ , optIncludeInHeader = ""+ , optIncludeBeforeBody = ""+ , optIncludeAfterBody = ""+ , optCustomHeader = "DEFAULT"+ , optTitlePrefix = ""+ , optOutputFile = "-" -- "-" means stdout+ , optNumberSections = False+ , optIncremental = False+ , optSmart = False+ , optHTMLMathMethod = PlainMath+ , optDumpArgs = False+ , optIgnoreArgs = False+ , optStrict = False+ , optReferenceLinks = False+ , optWrapText = True+ }++-- | A list of functions, each transforming the options data structure+-- in response to a command-line option.+options :: [OptDescr (Opt -> IO Opt)]+options =+ [ Option "fr" ["from","read"]+ (ReqArg+ (\arg opt -> return opt { optReader = map toLower arg })+ "FORMAT")+ "" -- ("(" ++ (joinWithSep ", " $ map fst readers) ++ ")")++ , Option "tw" ["to","write"]+ (ReqArg+ (\arg opt -> return opt { optWriter = map toLower arg })+ "FORMAT")+ "" -- ("(" ++ (joinWithSep ", " $ map fst writers) ++ ")")+ + , Option "s" ["standalone"]+ (NoArg+ (\opt -> return opt { optStandalone = True }))+ "" -- "Include needed header and footer on output"++ , Option "o" ["output"]+ (ReqArg+ (\arg opt -> return opt { optOutputFile = arg })+ "FILENAME")+ "" -- "Name of output file"++ , Option "p" ["preserve-tabs"]+ (NoArg+ (\opt -> return opt { optPreserveTabs = True }))+ "" -- "Preserve tabs instead of converting to spaces"++ , Option "" ["tab-stop"]+ (ReqArg+ (\arg opt -> return opt { optTabStop = (read arg) } )+ "TABSTOP")+ "" -- "Tab stop (default 4)"++ , Option "" ["strict"]+ (NoArg+ (\opt -> return opt { optStrict = True } ))+ "" -- "Disable markdown syntax extensions"++ , Option "" ["reference-links"]+ (NoArg+ (\opt -> return opt { optReferenceLinks = True } ))+ "" -- "Use reference links in parsing HTML"++ , Option "R" ["parse-raw"]+ (NoArg+ (\opt -> return opt { optParseRaw = True }))+ "" -- "Parse untranslatable HTML codes and LaTeX environments as raw"++ , Option "S" ["smart"]+ (NoArg+ (\opt -> return opt { optSmart = True }))+ "" -- "Use smart quotes, dashes, and ellipses"++ , Option "m" ["asciimathml"]+ (OptArg+ (\arg opt -> return opt { optHTMLMathMethod = + ASCIIMathML arg })+ "URL")+ "" -- "Use ASCIIMathML script in html output"++ , Option "" ["mimetex"]+ (OptArg+ (\arg opt -> return opt { optHTMLMathMethod = MimeTeX+ (fromMaybe "/cgi-bin/mimetex.cgi" arg)})+ "URL")+ "" -- "Use mimetex for HTML math"++ , Option "" ["gladtex"]+ (NoArg+ (\opt -> return opt { optHTMLMathMethod = GladTeX }))+ "" -- "Use gladtex for HTML math"++ , Option "i" ["incremental"]+ (NoArg+ (\opt -> return opt { optIncremental = True }))+ "" -- "Make list items display incrementally in S5"++ , Option "N" ["number-sections"]+ (NoArg+ (\opt -> return opt { optNumberSections = True }))+ "" -- "Number sections in LaTeX"++ , Option "" ["no-wrap"]+ (NoArg+ (\opt -> return opt { optWrapText = False }))+ "" -- "Do not wrap text in output"++ , Option "" ["toc", "table-of-contents"]+ (NoArg+ (\opt -> return opt { optTableOfContents = True }))+ "" -- "Include table of contents" ++ , Option "c" ["css"]+ (ReqArg+ (\arg opt -> return opt { optCSS = arg, + optStandalone = True })+ "CSS")+ "" -- "Link to CSS style sheet"++ , Option "H" ["include-in-header"]+ (ReqArg+ (\arg opt -> do+ text <- readFile arg+ return opt { optIncludeInHeader = fromUTF8 text, + optStandalone = True })+ "FILENAME")+ "" -- "File to include at end of header (implies -s)"++ , Option "B" ["include-before-body"]+ (ReqArg+ (\arg opt -> do+ text <- readFile arg+ return opt { optIncludeBeforeBody = fromUTF8 text })+ "FILENAME")+ "" -- "File to include before document body"++ , Option "A" ["include-after-body"]+ (ReqArg+ (\arg opt -> do+ text <- readFile arg+ return opt { optIncludeAfterBody = fromUTF8 text })+ "FILENAME")+ "" -- "File to include after document body"++ , Option "C" ["custom-header"]+ (ReqArg+ (\arg opt -> do+ text <- readFile arg+ return opt { optCustomHeader = fromUTF8 text, + optStandalone = True })+ "FILENAME")+ "" -- "File to use for custom header (implies -s)"++ , Option "T" ["title-prefix"]+ (ReqArg+ (\arg opt -> return opt { optTitlePrefix = arg, + optStandalone = True })+ "STRING")+ "" -- "String to prefix to HTML window title"+ + , Option "D" ["print-default-header"]+ (ReqArg+ (\arg opt -> do+ let header = case (lookup arg writers) of+ Just (writer, head) -> head+ Nothing -> error ("Unknown reader: " ++ arg) + hPutStr stdout header+ exitWith ExitSuccess)+ "FORMAT")+ "" -- "Print default header for FORMAT"++ , Option "" ["dump-args"]+ (NoArg+ (\opt -> return opt { optDumpArgs = True }))+ "" -- "Print output filename and arguments to stdout."++ , Option "" ["ignore-args"]+ (NoArg+ (\opt -> return opt { optIgnoreArgs = True }))+ "" -- "Ignore command-line arguments."+ + , Option "v" ["version"]+ (NoArg+ (\_ -> do+ prg <- getProgName+ hPutStrLn stderr (prg ++ " " ++ pandocVersion ++ + copyrightMessage)+ exitWith $ ExitFailure 4))+ "" -- "Print version"++ , Option "h" ["help"]+ (NoArg+ (\_ -> do+ prg <- getProgName+ hPutStr stderr (usageMessage prg options)+ exitWith $ ExitFailure 2))+ "" -- "Show help"+ ]++-- Returns usage message+usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String+usageMessage programName options = usageInfo + (programName ++ " [OPTIONS] [FILES]" ++ "\nInput formats: " ++ + (joinWithSep ", " $ map fst readers) ++ "\nOutput formats: " ++ + (joinWithSep ", " $ map fst writers) ++ "\nOptions:")+ options+ +-- Determine default reader based on source file extensions+defaultReaderName :: [String] -> String+defaultReaderName [] = "markdown"+defaultReaderName (x:xs) = + let x' = map toLower x in+ case (matchRegex (mkRegex ".*\\.(.*)") x') of+ Nothing -> defaultReaderName xs -- no extension+ Just ["xhtml"] -> "html"+ Just ["html"] -> "html"+ Just ["htm"] -> "html"+ Just ["tex"] -> "latex"+ Just ["latex"] -> "latex"+ Just ["ltx"] -> "latex"+ Just ["rst"] -> "rst"+ Just ["native"] -> "native"+ Just _ -> "markdown"++-- Determine default writer based on output file extension+defaultWriterName :: String -> String+defaultWriterName "-" = "html" -- no output file+defaultWriterName x =+ let x' = map toLower x in+ case (matchRegex (mkRegex ".*\\.(.*)") x') of+ Nothing -> "markdown" -- no extension+ Just [""] -> "markdown" -- empty extension + Just ["tex"] -> "latex"+ Just ["latex"] -> "latex"+ Just ["ltx"] -> "latex"+ Just ["context"] -> "context"+ Just ["ctx"] -> "context"+ Just ["rtf"] -> "rtf"+ Just ["rst"] -> "rst"+ Just ["s5"] -> "s5"+ Just ["native"] -> "native"+ Just ["txt"] -> "markdown"+ Just ["text"] -> "markdown"+ Just ["md"] -> "markdown"+ Just ["markdown"] -> "markdown"+ Just ["db"] -> "docbook"+ Just ["xml"] -> "docbook"+ Just ["sgml"] -> "docbook"+ Just [[x]] | x `elem` ['1'..'9'] -> "man"+ Just _ -> "html"++main = do++ rawArgs <- getArgs+ prg <- getProgName+ let compatMode = (prg == "hsmarkdown")++ let (actions, args, errors) = if compatMode+ then ([], rawArgs, [])+ else getOpt Permute options rawArgs++ if (not (null errors))+ then do+ name <- getProgName+ mapM (\e -> hPutStrLn stderr e) errors+ hPutStr stderr (usageMessage name options)+ exitWith $ ExitFailure 2+ else+ return ()++ let defaultOpts' = if compatMode + then defaultOpts { optReader = "markdown"+ , optWriter = "html"+ , optStrict = True }+ else defaultOpts++ -- thread option data structure through all supplied option actions+ opts <- foldl (>>=) (return defaultOpts') actions++ let Opt { optPreserveTabs = preserveTabs+ , optTabStop = tabStop+ , optStandalone = standalone+ , optReader = readerName+ , optWriter = writerName+ , optParseRaw = parseRaw+ , optCSS = css+ , optTableOfContents = toc+ , optIncludeInHeader = includeHeader+ , optIncludeBeforeBody = includeBefore+ , optIncludeAfterBody = includeAfter+ , optCustomHeader = customHeader+ , optTitlePrefix = titlePrefix+ , optOutputFile = outputFile+ , optNumberSections = numberSections+ , optIncremental = incremental+ , optSmart = smart+ , optHTMLMathMethod = mathMethod+ , optDumpArgs = dumpArgs+ , optIgnoreArgs = ignoreArgs+ , optStrict = strict+ , optReferenceLinks = referenceLinks+ , optWrapText = wrap+ } = opts++ if dumpArgs+ then do+ hPutStrLn stdout outputFile+ mapM (\arg -> hPutStrLn stdout arg) args+ exitWith $ ExitSuccess+ else return ()++ let sources = if ignoreArgs then [] else args++ -- assign reader and writer based on options and filenames+ let readerName' = if null readerName + then defaultReaderName sources+ else readerName++ let writerName' = if null writerName + then defaultWriterName outputFile+ else writerName++ reader <- case (lookup readerName' readers) of+ Just r -> return r+ Nothing -> error ("Unknown reader: " ++ readerName')++ (writer, defaultHeader) <- case (lookup writerName' writers) of+ Just (w,h) -> return (w, h)+ Nothing -> error ("Unknown writer: " ++ writerName')++ output <- if (outputFile == "-")+ then return stdout + else openFile outputFile WriteMode++ environment <- getEnvironment+ let columns = case lookup "COLUMNS" environment of+ Just cols -> read cols+ Nothing -> stateColumns defaultParserState++ let tabFilter _ [] = ""+ tabFilter _ ('\n':xs) = '\n':(tabFilter tabStop xs)+ -- remove DOS line endings+ tabFilter _ ('\r':'\n':xs) = '\n':(tabFilter tabStop xs)+ tabFilter _ ('\r':xs) = '\n':(tabFilter tabStop xs)+ tabFilter spsToNextStop ('\t':xs) = + if preserveTabs+ then '\t':(tabFilter tabStop xs) + else replicate spsToNextStop ' ' ++ tabFilter tabStop xs + tabFilter 1 (x:xs) = + x:(tabFilter tabStop xs)+ tabFilter spsToNextStop (x:xs) = + x:(tabFilter (spsToNextStop - 1) xs)++ let startParserState = + defaultParserState { stateParseRaw = parseRaw,+ stateTabStop = tabStop, + stateStandalone = standalone && (not strict),+ stateSmart = smart || writerName' `elem` + ["latex", "context"],+ stateColumns = columns,+ stateStrict = strict }+ let csslink = if (css == "")+ then "" + else "<link rel=\"stylesheet\" href=\"" ++ css ++ + "\" type=\"text/css\" media=\"all\" />\n"+ let header = (if (customHeader == "DEFAULT") + then defaultHeader+ else customHeader) ++ csslink ++ includeHeader+ let writerOptions = WriterOptions { writerStandalone = standalone &&+ (not strict), + writerHeader = header, + writerTitlePrefix = titlePrefix,+ writerTabStop = tabStop, + writerTableOfContents = toc &&+ (not strict) &&+ writerName/="s5",+ writerHTMLMathMethod = mathMethod,+ writerS5 = (writerName=="s5"),+ writerIgnoreNotes = False,+ writerIncremental = incremental, + writerNumberSections = numberSections,+ writerIncludeBefore = includeBefore, + writerIncludeAfter = includeAfter,+ writerStrictMarkdown = strict,+ writerReferenceLinks = referenceLinks,+ writerWrapText = wrap }++ (readSources sources) >>= (hPutStrLn output . toUTF8 . + (writer writerOptions) . + (reader startParserState) . tabFilter tabStop .+ fromUTF8 . (joinWithSep "\n")) >> + hClose output++ where + readSources [] = mapM readSource ["-"]+ readSources sources = mapM readSource sources+ readSource "-" = getContents+ readSource source = readFile source
Makefile view
@@ -4,23 +4,21 @@ # Constant names and commands in source tree #------------------------------------------------------------------------------- CABAL := pandoc.cabal-SRCDIR := src+SRCDIR := . MANDIR := man TESTDIR := tests BUILDDIR := dist-BUILDCONF := .setup-config-BUILDCMD := ./setup+BUILDCONF := $(BUILDDIR)/setup-config BUILDVARS := vars CONFIGURE := configure #------------------------------------------------------------------------------- # Cabal constants #--------------------------------------------------------------------------------NAME := $(shell sed -ne 's/^[Nn]ame:[[:space:]]*//p' $(CABAL))-THIS := $(shell echo $(NAME) | tr A-Z a-z)+PKG := $(shell sed -ne 's/^[Nn]ame:[[:space:]]*//p' $(CABAL) | tr A-Z a-z) VERSION := $(shell sed -ne 's/^[Vv]ersion:[[:space:]]*//p' $(CABAL))-RELNAME := $(THIS)-$(VERSION)-EXECSBASE := $(shell sed -ne 's/^[Ee]xecutable:[[:space:]]*//p' $(CABAL))+PKGID := $(PKG)-$(VERSION)+EXECSBASE := $(shell sed -ne 's/^[Ee]xecutable:\{0,1\}[[:space:]]*//p' $(CABAL)) #------------------------------------------------------------------------------- # Install targets@@ -29,10 +27,11 @@ # Add .exe extensions if we're running Windows/Cygwin. EXTENSION := $(shell uname | tr '[:upper:]' '[:lower:]' | \ sed -ne 's/^cygwin.*$$/\.exe/p')+BUILDCMD := $(addsuffix $(EXTENSION), ./setup) EXECS := $(addsuffix $(EXTENSION),$(EXECSBASE))-PROGS := $(EXECS) $(WRAPPERS) +PROGS := $(EXECS) $(WRAPPERS) MAIN := $(firstword $(EXECS))-DOCS := README.html README BUGS +DOCS := README.html README BUGS MANPAGES := $(patsubst %.md,%,$(wildcard $(MANDIR)/man?/*.?.md)) #-------------------------------------------------------------------------------@@ -41,12 +40,14 @@ # Specify default values. prefix := /usr/local-destdir := +destdir := # Attempt to set variables from a previous make session. -include $(BUILDVARS) # Fallback to defaults but allow to get the values from environment. PREFIX ?= $(prefix) DESTDIR ?= $(destdir)+DATADIR ?= $(PKGID)+DOCDIR ?= $(PKGID)/doc #------------------------------------------------------------------------------- # Installation paths@@ -54,11 +55,9 @@ DESTPATH := $(DESTDIR)$(PREFIX) BINPATH := $(DESTPATH)/bin DATAPATH := $(DESTPATH)/share-LIBPATH := $(DESTPATH)/$(NAME)-$(VERSION)-DOCPATH := $(DATAPATH)/doc/$(THIS)-LIBDOCPATH := $(DATAPATH)/doc/$(THIS)-doc MANPATH := $(DATAPATH)/man-PKGPATH := $(DATAPATH)/$(THIS)+PKGDATAPATH := $(DATAPATH)/$(DATADIR)+PKGDOCPATH := $(DATAPATH)/$(DOCDIR) #------------------------------------------------------------------------------- # Generic Makefile variables@@ -67,8 +66,9 @@ INSTALL_PROGRAM := $(INSTALL) -m 755 INSTALL_DATA := $(INSTALL) -m 644 STRIP := strip-GHC := ghc-GHC_PKG := ghc-pkg+GHC ?= ghc+GHC_PKG ?= ghc-pkg+GHC_VERSION := $(shell $(GHC) --version | sed -e 's/[^0-9]*//') #------------------------------------------------------------------------------- # Recipes@@ -93,11 +93,11 @@ ./$(MAIN) -s -S -w man $< >$@ || rm -f $@ .PHONY: templates-templates: $(SRCDIR)/templates+templates: $(MAKE) -C $(SRCDIR)/templates define generate-shell-script-echo "Generating $@..."; \+echo >&2 "Generating $@..."; \ awk ' \ /^[ \t]*###+ / { \ lead = $$0; sub(/[^ \t].*$$/, "", lead); \@@ -117,13 +117,21 @@ $(WRAPPERS): %: $(SRCDIR)/wrappers/%.in $(SRCDIR)/wrappers/*.sh @$(generate-shell-script) +CABAL_BACKUP=$(CABAL).orig+$(CABAL_BACKUP):+ cp $(CABAL) $(CABAL_BACKUP) ; \+ if echo $(GHC_VERSION) | grep -q '^6.6'; then \+ cp $(CABAL).ghc66 $(CABAL); \+ fi+ .PHONY: configure cleanup_files+=Setup.hi Setup.o $(BUILDCMD) $(BUILDVARS) configure: $(BUILDCONF) templates-$(BUILDCONF): $(CABAL)- ghc -package Cabal Setup.hs -o $(BUILDCMD)- $(BUILDCMD) configure --prefix=$(PREFIX)- # Make configuration time settings persistent (definitely a hack).+$(BUILDCMD): Setup.hs+ $(GHC) -package Cabal Setup.hs -o $(BUILDCMD)+$(BUILDCONF): $(CABAL) $(CABAL_BACKUP) $(BUILDCMD)+ $(BUILDCMD) configure --prefix=$(PREFIX) --with-compiler=$(GHC) --with-hc-pkg=$(GHC_PKG)+ @# Make configuration time settings persistent (definitely a hack). @echo "PREFIX?=$(PREFIX)" >$(BUILDVARS) @echo "DESTDIR?=$(DESTDIR)" >>$(BUILDVARS) @@ -136,8 +144,8 @@ cleanup_files+=$(EXECS) $(EXECS): build for f in $@; do \- find $(BUILDDIR) -type f -name "$$f" \- -perm +a=x -exec ln -s -f {} . \; ; \+ find $(BUILDDIR) -type f -name "$$f" -perm +a=x \+ -exec ln -s -f {} . \; ; \ done .PHONY: build-doc@@ -162,42 +170,29 @@ .PHONY: install-doc uninstall-doc man_all:=$(patsubst $(MANDIR)/%,%,$(MANPAGES)) install-doc: build-doc- $(INSTALL) -d $(DOCPATH) && $(INSTALL_DATA) $(DOCS) $(DOCPATH)/+ $(INSTALL) -d $(PKGDOCPATH) && $(INSTALL_DATA) $(DOCS) $(PKGDOCPATH)/ for f in $(man_all); do \ $(INSTALL) -d $(MANPATH)/$$(dirname $$f); \ $(INSTALL_DATA) $(MANDIR)/$$f $(MANPATH)/$$f; \ done uninstall-doc:- -for f in $(DOCS); do rm -f $(DOCPATH)/$$f; done+ -for f in $(DOCS); do rm -f $(PKGDOCPATH)/$$f; done -for f in $(man_all); do rm -f $(MANPATH)/$$f; done- -rmdir $(DOCPATH)--# Library documents installation.-.PHONY: install-lib-doc uninstall-lib-doc-install-lib-doc: build-lib-doc- $(INSTALL) -d $(LIBDOCPATH) && cp -R html $(LIBDOCPATH)/-uninstall-lib-doc:- -rm -rf $(LIBDOCPATH)/html- -rmdir $(LIBDOCPATH)--# Helper to install the given files $(1) into the path $(2).-# It also has the ability to follow symlinks.-install-executable-files = \- $(INSTALL) -d $(2); \- for f in $(1); do \- if [ -L $$f ]; then \- f=$$(readlink $$f); \- fi; \- $(INSTALL_PROGRAM) $$f $(2)/; \- done+ rmdir $(PKGDOCPATH) $(PKGDATAPATH) 2>/dev/null ||: # Program only installation. .PHONY: install-exec uninstall-exec install-exec: build-exec $(STRIP) $(EXECS)- $(call install-executable-files,$(PROGS),$(BINPATH))+ $(INSTALL) -d $(BINPATH); \+ for f in $(PROGS); do \+ if [ -L $$f ]; then \+ f=$$(readlink $$f); \+ fi; \+ $(INSTALL_PROGRAM) $$f $(BINPATH)/; \+ done uninstall-exec:- -for f in $(notdir $(PROGS)); do rm -f $(BINPATH)/$$f; done ;+ -for f in $(notdir $(PROGS)); do rm -f $(BINPATH)/$$f; done # Program + user documents installation. .PHONY: install-program uninstall-program@@ -205,9 +200,8 @@ uninstall-program: uninstall-exec uninstall-doc .PHONY: install-all uninstall-all-# Install libraries-install-all: build-all install-doc install-lib-doc- # Install the library (+ main executable) and register it.+# Full installation through Cabal: main + wrappers + user docs + lib + lib docs+install-all: build-all install-program destdir=$(DESTDIR); \ # Older Cabal versions have no '--destdir' option. if $(BUILDCMD) copy --help | grep -q '\-\-destdir'; then \@@ -215,22 +209,24 @@ else \ opt="--copy-prefix=$${destdir}$(PREFIX)"; \ fi; \- $(BUILDCMD) copy $$opt; \- $(BUILDCMD) register- # Note that, we are in the position of having to install the wrappers- # separately, as Cabal installs the main exec along with the library.- $(call install-executable-files,$(WRAPPERS),$(BINPATH))-uninstall-all: uninstall-program uninstall-lib-doc- -pkg_id="$(NAME)-$(VERSION)"; \- libdir=$$($(GHC_PKG) field $$pkg_id library-dirs 2>/dev/null | \+ $(BUILDCMD) copy $$opt; $(BUILDCMD) register+# Cabal lacks an 'uninstall' command. We have to remove some cruft manually.+uninstall-all: uninstall-program+ @libdir=$$($(GHC_PKG) field $(PKGID) library-dirs 2>/dev/null | \ sed 's/^library-dirs: *//'); \- if [ -d "$$libdir" ]; then \- $(BUILDCMD) unregister; \- rm -rf $$libdir; \- rmdir $$(dirname $$libdir); \+ htmldir=$$($(GHC_PKG) field $(PKGID) haddock-html 2>/dev/null | \+ sed 's/^haddock-html: *//'); \+ if [ -d $$libdir ]; then \+ $(BUILDCMD) unregister ||:; \ else \- echo "*** Couldn't locate library files for pkgid: $$pkg_id. ***"; \- fi+ echo >&2 "*** Couldn't locate library for pkgid: $(PKGID). ***"; \+ fi; \+ for d in $$libdir $$htmldir; do \+ [ -d $$d ] && { \+ rm -rf $$d; rmdir $$(dirname $$d) 2>/dev/null ||:; \+ } \+ done; \+ rmdir $(PKGDOCPATH) $(PKGDATAPATH) 2>/dev/null ||: # Default installation recipe for a common deployment scenario. .PHONY: install uninstall@@ -242,8 +238,8 @@ freebsd_dest:=freebsd freebsd_makefile:=$(freebsd_dest)/Makefile freebsd_template:=$(freebsd_makefile).in-cleanup_files+=$(freebsd_makefile) -freebsd : $(freebsd_makefile) +cleanup_files+=$(freebsd_makefile)+freebsd : $(freebsd_makefile) $(freebsd_makefile) : $(freebsd_template) sed -e 's/@VERSION@/$(VERSION)/' $< > $@ @@ -257,15 +253,15 @@ $(portfile) : $(portfile_template) tarball sed -e 's/@VERSION@/$(VERSION)/' $(portfile_template) | \ sed -e 's/@TARBALLMD5SUM@/$(word 2, $(shell openssl md5 $(tarball)))/' > \- $(portfile) + $(portfile) .PHONY: win-pkg-win_pkg_name:=$(RELNAME).zip+win_pkg_name:=$(PKGID).zip win_docs:=COPYING.txt COPYRIGHT.txt BUGS.txt README.txt README.html cleanup_files+=$(win_pkg_name) $(win_docs) win-pkg: $(win_pkg_name)-$(win_pkg_name): $(THIS).exe $(win_docs)- zip -r $(win_pkg_name) $(THIS).exe $(win_docs)+$(win_pkg_name): $(PKG).exe $(win_docs)+ zip -r $(win_pkg_name) $(PKG).exe $(win_docs) .PHONY: test test-markdown test: $(MAIN)@@ -276,8 +272,8 @@ @for suite in $(markdown_test_dirs); do \ ( \ suite_version=$$(echo $$suite | sed -e 's/.*_//');\- echo "-----------------------------------------";\- echo "Running Markdown test suite version $${suite_version}.";\+ echo >&2 "-----------------------------------------";\+ echo >&2 "Running Markdown test suite version $${suite_version}.";\ PATH=$(PWD):$$PATH; export PATH; cd $$suite && \ perl MarkdownTest.pl -s $(compat) -tidy ; \ ) \@@ -291,15 +287,15 @@ LC_ALL=C sort tags >tags.sorted; mv tags.sorted tags .PHONY: tarball-tarball:=$(RELNAME).tar.gz+tarball:=$(PKGID).tar.gz cleanup_files+=$(tarball) tarball: $(tarball) $(tarball):- svn export . $(RELNAME)- $(MAKE) -C $(RELNAME) templates- $(MAKE) -C $(RELNAME) wrappers- tar cvzf $(tarball) $(RELNAME)- -rm -rf $(RELNAME)+ svn export . $(PKGID)+ $(MAKE) -C $(PKGID) templates+ $(MAKE) -C $(PKGID) wrappers+ tar cvzf $(tarball) $(PKGID)+ -rm -rf $(PKGID) .PHONY: deb deb_name:=$(shell grep ^Package debian/control | cut -d' ' -f2 | head -n 1)@@ -308,47 +304,46 @@ deb_main:=$(deb_name)_$(deb_version)_$(deb_arch).deb deb: debian @[ -x /usr/bin/fakeroot ] || { \- echo "*** Please install fakeroot package. ***"; \+ echo >&2 "*** Please install fakeroot package. ***"; \ exit 1; \ } @[ -x /usr/bin/dpkg-buildpackage ] || { \- echo "*** Please install dpkg-dev package. ***"; \+ echo >&2 "*** Please install dpkg-dev package. ***"; \ exit 1; \ }- -mv $(BUILDVARS) $(BUILDVARS).old # backup settings + mv $(BUILDVARS) $(BUILDVARS).old 2>/dev/null ||: # backup settings if [ -x /usr/bin/debuild ]; then \ debuild -uc -us -i.svn -I.svn -i_darcs -I_darcs --lintian-opts -i; \ else \- echo "*** Please install devscripts package. ***"; \- echo "*** Using dpkg-buildpackage for package building. ***"; \+ echo >&2 "*** Please install devscripts package. ***"; \+ echo >&2 "*** Using dpkg-buildpackage for package building. ***"; \ dpkg-buildpackage -rfakeroot -uc -us -i.svn -I.svn -i_darcs -I_darcs; \ fi- -mv $(BUILDVARS).old $(BUILDVARS) # restore + mv $(BUILDVARS).old $(BUILDVARS) 2>/dev/null ||: # restore .PHONY: website web_src:=web web_dest:=pandoc-website make_page:=./$(MAIN) -s -S -B $(web_src)/header.html \ -A $(web_src)/footer.html \- -H $(web_src)/css + -H $(web_src)/css cleanup_files+=$(web_dest)-$(web_dest) : html $(wildcard $(web_src)/*) changelog \+$(web_dest) : html $(wildcard $(web_src)/*) debian/changelog \ INSTALL $(MANPAGES) $(MANDIR)/man1/pandoc.1.md README- -rm -rf $(web_dest)- ( \+ rm -rf $(web_dest) && { \ mkdir $(web_dest); \ cp -r html $(web_dest)/doc; \ cp $(web_src)/* $(web_dest)/; \ sed -e 's#@VERSION@#$(VERSION)#g' $(web_src)/index.txt.in > \ $(web_dest)/index.txt; \- cp changelog $(web_dest)/ ; \+ cp debian/changelog $(web_dest)/changelog.txt ; \ cp README $(web_dest)/ ; \ cp INSTALL $(web_dest)/ ; \ cp $(MANDIR)/man1/pandoc.1.md $(web_dest)/ ; \ cp $(MANDIR)/man1/*.1 $(web_dest)/ ; \- ) || { rm -rf $(web_dest); exit 1; }+ } || { rm -rf $(web_dest); exit 1; } website: $(MAIN) $(web_dest)- PANDOC_PATH=$(shell pwd) make -C $(web_dest) + PANDOC_PATH=$(shell pwd) make -C $(web_dest) .PHONY: distclean clean distclean: clean
PROFILING view
@@ -1,8 +1,6 @@ To use the GHC profiler: -first, add -auto-all to ghc-options in pandoc.cabal. then--make clean+make distclean make templates runhaskell Setup.hs configure --enable-library-profiling --enable-executable-profiling runhaskell Setup.hs build
README view
@@ -310,17 +310,28 @@ `context`.) `-m`*[url]* or `--asciimathml`*[=url]*-: will cause LaTeX formulas (between $ signs) in HTML or S5 to display- as formulas rather than as code. The trick will not work in all- browsers, but it works in Firefox. Peter Jipsen's [ASCIIMathML]- script is used to do the magic. If a local copy of `ASCIIMathML.js`- is available on the webserver where the page will be viewed,- provide a *url* and a link will be inserted in the generated- HTML or S5. If no *url* is provided, the contents of the script- will be inserted directly; this provides portability at the price of- efficiency. If you plan to use math on several pages, it is much- better to link to a copy of `ASCIIMathML.js`, which can be cached.+: causes `pandoc` to use Peter Jipsen's [ASCIIMathML] script to display+ TeX math in HTML or S5. If a local copy of `ASCIIMathML.js` is+ available on the webserver where the page will be viewed, provide a+ *url* and a link will be inserted in the generated HTML or S5. If+ no *url* is provided, the contents of the script will be inserted+ directly; this provides portability at the price of efficiency. If+ you plan to use math on several pages, it is much better to link to+ a copy of `ASCIIMathML.js`, which can be cached. (See `--gladtex`+ and `--mimetex` for alternative ways of dealing with math in HTML.) +`--gladtex`*[=url]*+: causes TeX formulas to be enclosed in `<eq>` tags in HTML or S5 output.+ This output can then be processed by [gladTeX] to produce links to+ images with the typeset formulas. (See `--asciimathml` and+ `--mimetex` for alternative ways of dealing with math in HTML.)++`--mimetex`*[=url]*+: causes TeX formulas to be replaced by `<img>` tags linking to the+ [mimeTeX] CGI script, which will produce images with the typeset+ formulas. (See `--asciimathml` and `--mimetex` for alternative+ ways of dealing with math in HTML.)+ `-i` or `--incremental` : causes all lists in S5 output to be displayed incrementally by default (one item at a time). The normal default is for lists to be@@ -330,6 +341,10 @@ : causes sections to be numbered in LaTeX or ConTeXt output. By default, sections are not numbered. +`--no-wrap`+: disables text-wrapping in output. By default, text is wrapped+ appropriately for the output format.+ `--dump-args` : is intended to make it easier to create wrapper scripts that use Pandoc. It causes Pandoc to dump information about the arguments@@ -365,6 +380,8 @@ [Smartypants]: http://daringfireball.net/projects/smartypants/ [ASCIIMathML]: http://www1.chapman.edu/~jipsen/mathml/asciimath.html+[gladTeX]: http://www.math.uio.no/~martingu/gladtex/index.html+[mimeTeX]: http://www.forkosh.com/mimetex.html Pandoc's markdown vs. standard markdown =======================================@@ -796,16 +813,6 @@ Note, however, that this method of providing links to sections works only in HTML. -Box-style blockquotes------------------------Pandoc supports emacs-style boxquote block quotes, in addition to-standard markdown (email-style) block quotes:-- ,----- | They look like this.- `----- Blank lines before headers and blockquotes ------------------------------------------ @@ -819,23 +826,63 @@ I like several of their flavors of ice cream: #22, for example, and #5. -Inline LaTeX-------------+Math+---- -Anything between two $ characters will be parsed as LaTeX math. The+Anything between two $ characters will be treated as TeX math. The opening $ must have a character immediately to its right, while the closing $ must have a character immediately to its left. Thus,-`$20,000 and $30,000` won't parse as math. The $ character can be-escaped with a backslash if needed.+`$20,000 and $30,000` won't parse as math. If for some reason+you need to enclose text in literal $ characters, backslash-escape+them and they won't be treated as math delimiters. -Pandoc can use the [ASCIIMathML] script to display LaTeX formulas-in HTML (at least on better browsers). See above on the-`-m|--asciimathml` command-line option.+TeX math will be printed in all output formats. In Markdown,+reStructuredText, LaTeX, and ConTeXt output, it will appear verbatim+between $ characters. -[ASCIIMathML]: http://www1.chapman.edu/~jipsen/asciimath.html +In groff man output, it will be rendered verbatim without $'s. -Inline LaTeX commands will also be preserved and passed unchanged-to the LaTeX writer. Thus, for example, you can use LaTeX to+In RTF and Docbook output, it will be rendered, as far as possible,+using unicode characters, and will otherwise appear verbatim. Unknown+commands and symbols, and commands that cannot be dealt with this way+(like `\frac`), will be rendered verbatim. So the results may be a mix+of raw TeX code and properly rendered unicode math.++In HTML and S5 output, the way math is rendered will depend on the+command-line options selected:++1. The default is to render TeX math as far as possible using unicode+ characters, as with RTF and Docbook output. Formulas are put inside+ a `span` with `class="math"`, so that they may be styled differently+ from the surrounding text if needed.++2. If the `--asciimathml` option is used, TeX math will be displayed+ between $ characters, as in LaTeX, and the [ASCIIMathML] script will+ be used to render it as formulas. (This trick does not work in all+ browsers, but it works in Firefox. In browsers that do not support+ ASCIIMathML, TeX math will appear verbatim between $ characters.)++3. If the `--mimetex` option is used, the [mimeTeX] CGI script will+ be called to generate images for each TeX formula. This should+ work in all browsers. The `--mimetex` option takes an optional URL+ as argument. If no URL is specified, it will be assumed that the+ mimeTeX CGI script is at `/cgi-bin/mimetex.cgi`.++4. If the `--gladtex` option is used, TeX formulas will be enclosed+ in `<eq>` tags in the HTML output. The resulting `htex` file may then+ be processed by [gladTeX], which will produce image files for each+ formula and an `html` file with links to these images. So, the+ procedure is:++ pandoc -s --gladtex myfile.txt -o myfile.htex+ gladtex -d myfile-images myfile.htex # produces myfile.html+ # and images in myfile-images++Inline TeX+----------++Inline TeX commands will be preserved and passed unchanged to the+LaTeX and ConTeXt writers. Thus, for example, you can use LaTeX to include BibTeX citations: This result was proved in \cite{jones.1967}.@@ -851,6 +898,9 @@ the material between the begin and end tags will be interpreted as raw LaTeX, not as markdown.++Inline LaTeX is ignored in output formats other than Markdown, LaTeX,+and ConTeXt. Custom headers ==============
+ Text/Pandoc.hs view
@@ -0,0 +1,110 @@+{-+Copyright (C) 2006-7 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+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha + Portability : portable++This helper module exports the main writers, readers, and data+structure definitions from the Pandoc libraries.++A typical application will chain together a reader and a writer+to convert strings from one format to another. For example, the+following simple program will act as a filter converting markdown+fragments to reStructuredText, using reference-style links instead of+inline links:++> module Main where+> import Text.Pandoc+> +> markdownToRST :: String -> String+> markdownToRST = toUTF8 .+> (writeRST defaultWriterOptions {writerReferenceLinks = True}) .+> (readMarkdown defaultParserState) . fromUTF8+> +> main = interact markdownToRST++-}++module Text.Pandoc+ ( + -- * Definitions+ module Text.Pandoc.Definition+ -- * Readers: converting /to/ Pandoc format+ , readMarkdown+ , readRST+ , readLaTeX+ , readHtml+ -- * Parser state used in readers+ , ParserState (..)+ , defaultParserState+ , ParserContext (..)+ , QuoteContext (..)+ , KeyTable+ , NoteTable+ , HeaderType (..)+ -- * Writers: converting /from/ Pandoc format+ , writeMarkdown+ , writeRST+ , writeLaTeX+ , writeConTeXt+ , writeHtml+ , writeHtmlString+ , writeS5+ , writeS5String+ , writeDocbook+ , writeMan+ , writeRTF+ , prettyPandoc+ -- * Writer options used in writers + , WriterOptions (..)+ , defaultWriterOptions+ -- * Default headers for various output formats+ , module Text.Pandoc.Writers.DefaultHeaders+ -- * Functions for converting to and from UTF-8+ , module Text.Pandoc.UTF8+ -- * Version+ , pandocVersion+ ) where++import Text.Pandoc.Definition+import Text.Pandoc.Readers.Markdown+import Text.Pandoc.Readers.RST+import Text.Pandoc.Readers.LaTeX+import Text.Pandoc.Readers.HTML+import Text.Pandoc.Writers.Markdown+import Text.Pandoc.Writers.RST +import Text.Pandoc.Writers.LaTeX+import Text.Pandoc.Writers.ConTeXt+import Text.Pandoc.Writers.HTML+import Text.Pandoc.Writers.S5+import Text.Pandoc.Writers.Docbook+import Text.Pandoc.Writers.Man+import Text.Pandoc.Writers.RTF +import Text.Pandoc.Writers.DefaultHeaders+import Text.Pandoc.UTF8+import Text.Pandoc.Shared++-- | Version number of pandoc library.+pandocVersion :: String+pandocVersion = "0.45"
+ Text/Pandoc/ASCIIMathML.hs view
@@ -0,0 +1,14 @@+----------------------------------------------------+-- Do not edit this file by hand. Edit +-- 'templates/ASCIIMathML.hs'+-- and run ./fillTemplates.pl Text/Pandoc/ASCIIMathML.hs+----------------------------------------------------++-- | Definitions for use of ASCIIMathML in HTML. +-- (See <http://www1.chapman.edu/~jipsen/mathml/asciimath.html>.)+module Text.Pandoc.ASCIIMathML ( asciiMathMLScript ) where++-- | String containing ASCIIMathML javascript.+asciiMathMLScript :: String+asciiMathMLScript = "<script type=\"text/javascript\">\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n\nvar mathcolor = \"\"; // change it to \"\" (to inherit) or another color\nvar mathfontsize = \"1em\"; // change to e.g. 1.2em for larger math\nvar mathfontfamily = \"serif\"; // change to \"\" to inherit (works in IE) \n // or another family (e.g. \"arial\")\nvar automathrecognize = false; // writing \"amath\" on page makes this true\nvar checkForMathML = true; // check if browser can display MathML\nvar notifyIfNoMathML = true; // display note at top if no MathML capability\nvar alertIfNoMathML = false; // show alert box if no MathML capability\nvar translateOnLoad = true; // set to false to do call translators from js \nvar translateLaTeX = true; // false to preserve $..$, $$..$$\nvar translateLaTeXformatting = true; // false to preserve \\emph,\\begin{},\\end{}\nvar translateASCIIMath = true; // false to preserve `..`\nvar translateASCIIsvg = true; // false to preserve agraph.., \\begin{graph}..\nvar avoidinnerHTML = false; // set true if assigning to innerHTML gives error\nvar displaystyle = true; // puts limits above and below large operators\nvar showasciiformulaonhover = true; // helps students learn ASCIIMath\nvar decimalsign = \".\"; // change to \",\" if you like, beware of `(1,2)`!\nvar AMdelimiter1 = \"`\", AMescape1 = \"\\\\\\\\`\"; // can use other characters\nvar AMdocumentId = \"wikitext\" // PmWiki element containing math (default=body)\nvar checkforprocessasciimathinmoodle = false; // true for systems like Moodle\nvar dsvglocation = \"\"; // path to d.svg (blank if same as ASCIIMathML.js loc)\n\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n\nvar isIE = document.createElementNS==null;\nvar noMathML = false, translated = false;\n\nif (isIE) { // avoid adding MathPlayer info explicitly to each webpage\n document.write(\"<object id=\\\"mathplayer\\\"\\\n classid=\\\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\\\"></object>\");\n document.write(\"<?import namespace=\\\"m\\\" implementation=\\\"#mathplayer\\\"?>\");\n}\n\n// Add a stylesheet, replacing any previous custom stylesheet (adapted from TW)\nfunction setStylesheet(s) {\n\tvar id = \"AMMLcustomStyleSheet\";\n\tvar n = document.getElementById(id);\n\tif(document.createStyleSheet) {\n\t\t// Test for IE's non-standard createStyleSheet method\n\t\tif(n)\n\t\t\tn.parentNode.removeChild(n);\n\t\t// This failed without the \n\t\tdocument.getElementsByTagName(\"head\")[0].insertAdjacentHTML(\"beforeEnd\",\" <style id='\" + id + \"'>\" + s + \"</style>\");\n\t} else {\n\t\tif(n) {\n\t\t\tn.replaceChild(document.createTextNode(s),n.firstChild);\n\t\t} else {\n\t\t\tn = document.createElement(\"style\");\n\t\t\tn.type = \"text/css\";\n\t\t\tn.id = id;\n\t\t\tn.appendChild(document.createTextNode(s));\n\t\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(n);\n\t\t}\n\t}\n}\n\nsetStylesheet(\"#AMMLcloseDiv \\{font-size:0.8em; padding-top:1em; color:#014\\}\\n#AMMLwarningBox \\{position:absolute; width:100%; top:0; left:0; z-index:200; text-align:center; font-size:1em; font-weight:bold; padding:0.5em 0 0.5em 0; color:#ffc; background:#c30\\}\");\n\nfunction init(){\n\tvar msg, warnings = new Array();\n\tif (document.getElementById==null){\n\t\talert(\"This webpage requires a recent browser such as Mozilla Firefox/Netscape 7+ or Internet Explorer 6+ with MathPlayer and Adobe SVGviewer\");\n\t\treturn null;\n\t}\n\tif (checkForMathML && (msg = checkMathML())) warnings.push(msg);\n\tif (checkIfSVGavailable && (msg = checkSVG())) warnings.push(msg);\n\tif (warnings.length>0) displayWarnings(warnings);\n\tif (!noMathML) initSymbols();\n\treturn true;\n}\n\nfunction checkMathML(){\n if (navigator.appName.slice(0,8)==\"Netscape\") \n if (navigator.appVersion.slice(0,1)>=\"5\") noMathML = null;\n else noMathML = true;\n else if (navigator.appName.slice(0,9)==\"Microsoft\")\n try {\n var ActiveX = new ActiveXObject(\"MathPlayer.Factory.1\");\n noMathML = null;\n } catch (e) {\n noMathML = true;\n }\n else noMathML = true;\n//noMathML = true; //uncomment to check\n if (noMathML && notifyIfNoMathML) {\n var msg = \"To view the ASCIIMathML notation use Internet Explorer + MathPlayer or Mozilla Firefox 2.0 or later.\";\n if (alertIfNoMathML)\n alert(msg);\n else return msg;\n }\n}\n\nfunction hideWarning(){\n\tvar body = document.getElementsByTagName(\"body\")[0];\n\tbody.removeChild(document.getElementById('AMMLwarningBox'));\n\tbody.onclick = null;\n}\n\nfunction displayWarnings(warnings) {\n var i, frag, nd = createElementXHTML(\"div\");\n var body = document.getElementsByTagName(\"body\")[0];\n body.onclick=hideWarning;\n nd.id = 'AMMLwarningBox';\n for (i=0; i<warnings.length; i++) {\n\tfrag = createElementXHTML(\"div\");\n\tfrag.appendChild(document.createTextNode(warnings[i]));\n\tfrag.style.paddingBottom = \"1.0em\";\n\tnd.appendChild(frag);\n }\n nd.appendChild(createElementXHTML(\"p\"));\n nd.appendChild(document.createTextNode(\"For instructions see the \"));\n var an = createElementXHTML(\"a\");\n an.appendChild(document.createTextNode(\"ASCIIMathML\"));\n an.setAttribute(\"href\",\"http://www.chapman.edu/~jipsen/asciimath.html\");\n nd.appendChild(an);\n nd.appendChild(document.createTextNode(\" homepage\"));\n an = createElementXHTML(\"div\");\n an.id = 'AMMLcloseDiv';\n an.appendChild(document.createTextNode('(click anywhere to close this warning)'));\n nd.appendChild(an);\n var body = document.getElementsByTagName(\"body\")[0];\n body.insertBefore(nd,body.childNodes[0]);\n}\n\nfunction translate(spanclassAM) {\n if (!translated) { // run this only once\n translated = true;\n var body = document.getElementsByTagName(\"body\")[0];\n var processN = document.getElementById(AMdocumentId);\n if (translateLaTeX) LMprocessNode((processN!=null?processN:body));\n if (translateASCIIMath) AMprocessNode((processN!=null?processN:body), false, spanclassAM);\n }\n}\n\nfunction createElementXHTML(t) {\n if (isIE) return document.createElement(t);\n else return document.createElementNS(\"http://www.w3.org/1999/xhtml\",t);\n}\n\nfunction createMmlNode(t,frag) {\n if (isIE) var node = document.createElement(\"m:\"+t);\n else var node = document.createElementNS(\"http://www.w3.org/1998/Math/MathML\",t);\n if (frag) node.appendChild(frag);\n return node;\n}\n\n// character lists for Mozilla/Netscape fonts\nvar AMcal = [0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];\nvar AMfrk = [0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];\nvar AMbbb = [0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];\n\nvar CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,\n RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,\n LEFTRIGHT = 9, TEXT = 10, BIG = 11, LONG = 12, STRETCHY = 13,\n MATRIX = 14;; // token types\n\nvar AMquote = {input:\"\\\"\", tag:\"mtext\", output:\"mbox\", tex:null, ttype:TEXT};\n\nvar AMsymbols = [\n//some greek symbols\n{input:\"alpha\", tag:\"mi\", output:\"\\u03B1\", tex:null, ttype:CONST},\n{input:\"beta\", tag:\"mi\", output:\"\\u03B2\", tex:null, ttype:CONST},\n{input:\"chi\", tag:\"mi\", output:\"\\u03C7\", tex:null, ttype:CONST},\n{input:\"delta\", tag:\"mi\", output:\"\\u03B4\", tex:null, ttype:CONST},\n{input:\"Delta\", tag:\"mo\", output:\"\\u0394\", tex:null, ttype:CONST},\n{input:\"epsi\", tag:\"mi\", output:\"\\u03B5\", tex:\"epsilon\", ttype:CONST},\n{input:\"varepsilon\", tag:\"mi\", output:\"\\u025B\", tex:null, ttype:CONST},\n{input:\"eta\", tag:\"mi\", output:\"\\u03B7\", tex:null, ttype:CONST},\n{input:\"gamma\", tag:\"mi\", output:\"\\u03B3\", tex:null, ttype:CONST},\n{input:\"Gamma\", tag:\"mo\", output:\"\\u0393\", tex:null, ttype:CONST},\n{input:\"iota\", tag:\"mi\", output:\"\\u03B9\", tex:null, ttype:CONST},\n{input:\"kappa\", tag:\"mi\", output:\"\\u03BA\", tex:null, ttype:CONST},\n{input:\"lambda\", tag:\"mi\", output:\"\\u03BB\", tex:null, ttype:CONST},\n{input:\"Lambda\", tag:\"mo\", output:\"\\u039B\", tex:null, ttype:CONST},\n{input:\"mu\", tag:\"mi\", output:\"\\u03BC\", tex:null, ttype:CONST},\n{input:\"nu\", tag:\"mi\", output:\"\\u03BD\", tex:null, ttype:CONST},\n{input:\"omega\", tag:\"mi\", output:\"\\u03C9\", tex:null, ttype:CONST},\n{input:\"Omega\", tag:\"mo\", output:\"\\u03A9\", tex:null, ttype:CONST},\n{input:\"phi\", tag:\"mi\", output:\"\\u03C6\", tex:null, ttype:CONST},\n{input:\"varphi\", tag:\"mi\", output:\"\\u03D5\", tex:null, ttype:CONST},\n{input:\"Phi\", tag:\"mo\", output:\"\\u03A6\", tex:null, ttype:CONST},\n{input:\"pi\", tag:\"mi\", output:\"\\u03C0\", tex:null, ttype:CONST},\n{input:\"Pi\", tag:\"mo\", output:\"\\u03A0\", tex:null, ttype:CONST},\n{input:\"psi\", tag:\"mi\", output:\"\\u03C8\", tex:null, ttype:CONST},\n{input:\"Psi\", tag:\"mi\", output:\"\\u03A8\", tex:null, ttype:CONST},\n{input:\"rho\", tag:\"mi\", output:\"\\u03C1\", tex:null, ttype:CONST},\n{input:\"sigma\", tag:\"mi\", output:\"\\u03C3\", tex:null, ttype:CONST},\n{input:\"Sigma\", tag:\"mo\", output:\"\\u03A3\", tex:null, ttype:CONST},\n{input:\"tau\", tag:\"mi\", output:\"\\u03C4\", tex:null, ttype:CONST},\n{input:\"theta\", tag:\"mi\", output:\"\\u03B8\", tex:null, ttype:CONST},\n{input:\"vartheta\", tag:\"mi\", output:\"\\u03D1\", tex:null, ttype:CONST},\n{input:\"Theta\", tag:\"mo\", output:\"\\u0398\", tex:null, ttype:CONST},\n{input:\"upsilon\", tag:\"mi\", output:\"\\u03C5\", tex:null, ttype:CONST},\n{input:\"xi\", tag:\"mi\", output:\"\\u03BE\", tex:null, ttype:CONST},\n{input:\"Xi\", tag:\"mo\", output:\"\\u039E\", tex:null, ttype:CONST},\n{input:\"zeta\", tag:\"mi\", output:\"\\u03B6\", tex:null, ttype:CONST},\n\n//binary operation symbols\n//{input:\"-\", tag:\"mo\", output:\"\\u0096\", tex:null, ttype:CONST},\n{input:\"*\", tag:\"mo\", output:\"\\u22C5\", tex:\"cdot\", ttype:CONST},\n{input:\"**\", tag:\"mo\", output:\"\\u22C6\", tex:\"star\", ttype:CONST},\n{input:\"//\", tag:\"mo\", output:\"/\", tex:null, ttype:CONST},\n{input:\"\\\\\\\\\", tag:\"mo\", output:\"\\\\\", tex:\"backslash\", ttype:CONST},\n{input:\"setminus\", tag:\"mo\", output:\"\\\\\", tex:null, ttype:CONST},\n{input:\"xx\", tag:\"mo\", output:\"\\u00D7\", tex:\"times\", ttype:CONST},\n{input:\"-:\", tag:\"mo\", output:\"\\u00F7\", tex:\"divide\", ttype:CONST},\n{input:\"@\", tag:\"mo\", output:\"\\u2218\", tex:\"circ\", ttype:CONST},\n{input:\"o+\", tag:\"mo\", output:\"\\u2295\", tex:\"oplus\", ttype:CONST},\n{input:\"ox\", tag:\"mo\", output:\"\\u2297\", tex:\"otimes\", ttype:CONST},\n{input:\"o.\", tag:\"mo\", output:\"\\u2299\", tex:\"odot\", ttype:CONST},\n{input:\"sum\", tag:\"mo\", output:\"\\u2211\", tex:null, ttype:UNDEROVER},\n{input:\"prod\", tag:\"mo\", output:\"\\u220F\", tex:null, ttype:UNDEROVER},\n{input:\"^^\", tag:\"mo\", output:\"\\u2227\", tex:\"wedge\", ttype:CONST},\n{input:\"^^^\", tag:\"mo\", output:\"\\u22C0\", tex:\"bigwedge\", ttype:UNDEROVER},\n{input:\"vv\", tag:\"mo\", output:\"\\u2228\", tex:\"vee\", ttype:CONST},\n{input:\"vvv\", tag:\"mo\", output:\"\\u22C1\", tex:\"bigvee\", ttype:UNDEROVER},\n{input:\"nn\", tag:\"mo\", output:\"\\u2229\", tex:\"cap\", ttype:CONST},\n{input:\"nnn\", tag:\"mo\", output:\"\\u22C2\", tex:\"bigcap\", ttype:UNDEROVER},\n{input:\"uu\", tag:\"mo\", output:\"\\u222A\", tex:\"cup\", ttype:CONST},\n{input:\"uuu\", tag:\"mo\", output:\"\\u22C3\", tex:\"bigcup\", ttype:UNDEROVER},\n\n//binary relation symbols\n{input:\"!=\", tag:\"mo\", output:\"\\u2260\", tex:\"ne\", ttype:CONST},\n{input:\":=\", tag:\"mo\", output:\":=\", tex:null, ttype:CONST},\n{input:\"lt\", tag:\"mo\", output:\"<\", tex:null, ttype:CONST},\n{input:\"<=\", tag:\"mo\", output:\"\\u2264\", tex:\"le\", ttype:CONST},\n{input:\"lt=\", tag:\"mo\", output:\"\\u2264\", tex:\"leq\", ttype:CONST},\n{input:\">=\", tag:\"mo\", output:\"\\u2265\", tex:\"ge\", ttype:CONST},\n{input:\"geq\", tag:\"mo\", output:\"\\u2265\", tex:null, ttype:CONST},\n{input:\"-<\", tag:\"mo\", output:\"\\u227A\", tex:\"prec\", ttype:CONST},\n{input:\"-lt\", tag:\"mo\", output:\"\\u227A\", tex:null, ttype:CONST},\n{input:\">-\", tag:\"mo\", output:\"\\u227B\", tex:\"succ\", ttype:CONST},\n{input:\"-<=\", tag:\"mo\", output:\"\\u2AAF\", tex:\"preceq\", ttype:CONST},\n{input:\">-=\", tag:\"mo\", output:\"\\u2AB0\", tex:\"succeq\", ttype:CONST},\n{input:\"in\", tag:\"mo\", output:\"\\u2208\", tex:null, ttype:CONST},\n{input:\"!in\", tag:\"mo\", output:\"\\u2209\", tex:\"notin\", ttype:CONST},\n{input:\"sub\", tag:\"mo\", output:\"\\u2282\", tex:\"subset\", ttype:CONST},\n{input:\"sup\", tag:\"mo\", output:\"\\u2283\", tex:\"supset\", ttype:CONST},\n{input:\"sube\", tag:\"mo\", output:\"\\u2286\", tex:\"subseteq\", ttype:CONST},\n{input:\"supe\", tag:\"mo\", output:\"\\u2287\", tex:\"supseteq\", ttype:CONST},\n{input:\"-=\", tag:\"mo\", output:\"\\u2261\", tex:\"equiv\", ttype:CONST},\n{input:\"~=\", tag:\"mo\", output:\"\\u2245\", tex:\"cong\", ttype:CONST},\n{input:\"~~\", tag:\"mo\", output:\"\\u2248\", tex:\"approx\", ttype:CONST},\n{input:\"prop\", tag:\"mo\", output:\"\\u221D\", tex:\"propto\", ttype:CONST},\n\n//logical symbols\n{input:\"and\", tag:\"mtext\", output:\"and\", tex:null, ttype:SPACE},\n{input:\"or\", tag:\"mtext\", output:\"or\", tex:null, ttype:SPACE},\n{input:\"not\", tag:\"mo\", output:\"\\u00AC\", tex:\"neg\", ttype:CONST},\n{input:\"=>\", tag:\"mo\", output:\"\\u21D2\", tex:\"implies\", ttype:CONST},\n{input:\"if\", tag:\"mo\", output:\"if\", tex:null, ttype:SPACE},\n{input:\"<=>\", tag:\"mo\", output:\"\\u21D4\", tex:\"iff\", ttype:CONST},\n{input:\"AA\", tag:\"mo\", output:\"\\u2200\", tex:\"forall\", ttype:CONST},\n{input:\"EE\", tag:\"mo\", output:\"\\u2203\", tex:\"exists\", ttype:CONST},\n{input:\"_|_\", tag:\"mo\", output:\"\\u22A5\", tex:\"bot\", ttype:CONST},\n{input:\"TT\", tag:\"mo\", output:\"\\u22A4\", tex:\"top\", ttype:CONST},\n{input:\"|--\", tag:\"mo\", output:\"\\u22A2\", tex:\"vdash\", ttype:CONST},\n{input:\"|==\", tag:\"mo\", output:\"\\u22A8\", tex:\"models\", ttype:CONST},\n\n//grouping brackets\n{input:\"(\", tag:\"mo\", output:\"(\", tex:null, ttype:LEFTBRACKET},\n{input:\")\", tag:\"mo\", output:\")\", tex:null, ttype:RIGHTBRACKET},\n{input:\"[\", tag:\"mo\", output:\"[\", tex:null, ttype:LEFTBRACKET},\n{input:\"]\", tag:\"mo\", output:\"]\", tex:null, ttype:RIGHTBRACKET},\n{input:\"{\", tag:\"mo\", output:\"{\", tex:null, ttype:LEFTBRACKET},\n{input:\"}\", tag:\"mo\", output:\"}\", tex:null, ttype:RIGHTBRACKET},\n{input:\"|\", tag:\"mo\", output:\"|\", tex:null, ttype:LEFTRIGHT},\n//{input:\"||\", tag:\"mo\", output:\"||\", tex:null, ttype:LEFTRIGHT},\n{input:\"(:\", tag:\"mo\", output:\"\\u2329\", tex:\"langle\", ttype:LEFTBRACKET},\n{input:\":)\", tag:\"mo\", output:\"\\u232A\", tex:\"rangle\", ttype:RIGHTBRACKET},\n{input:\"<<\", tag:\"mo\", output:\"\\u2329\", tex:null, ttype:LEFTBRACKET},\n{input:\">>\", tag:\"mo\", output:\"\\u232A\", tex:null, ttype:RIGHTBRACKET},\n{input:\"{:\", tag:\"mo\", output:\"{:\", tex:null, ttype:LEFTBRACKET, invisible:true},\n{input:\":}\", tag:\"mo\", output:\":}\", tex:null, ttype:RIGHTBRACKET, invisible:true},\n\n//miscellaneous symbols\n{input:\"int\", tag:\"mo\", output:\"\\u222B\", tex:null, ttype:CONST},\n{input:\"dx\", tag:\"mi\", output:\"{:d x:}\", tex:null, ttype:DEFINITION},\n{input:\"dy\", tag:\"mi\", output:\"{:d y:}\", tex:null, ttype:DEFINITION},\n{input:\"dz\", tag:\"mi\", output:\"{:d z:}\", tex:null, ttype:DEFINITION},\n{input:\"dt\", tag:\"mi\", output:\"{:d t:}\", tex:null, ttype:DEFINITION},\n{input:\"oint\", tag:\"mo\", output:\"\\u222E\", tex:null, ttype:CONST},\n{input:\"del\", tag:\"mo\", output:\"\\u2202\", tex:\"partial\", ttype:CONST},\n{input:\"grad\", tag:\"mo\", output:\"\\u2207\", tex:\"nabla\", ttype:CONST},\n{input:\"+-\", tag:\"mo\", output:\"\\u00B1\", tex:\"pm\", ttype:CONST},\n{input:\"O/\", tag:\"mo\", output:\"\\u2205\", tex:\"emptyset\", ttype:CONST},\n{input:\"oo\", tag:\"mo\", output:\"\\u221E\", tex:\"infty\", ttype:CONST},\n{input:\"aleph\", tag:\"mo\", output:\"\\u2135\", tex:null, ttype:CONST},\n{input:\"...\", tag:\"mo\", output:\"...\", tex:\"ldots\", ttype:CONST},\n{input:\":.\", tag:\"mo\", output:\"\\u2234\", tex:\"therefore\", ttype:CONST},\n{input:\"/_\", tag:\"mo\", output:\"\\u2220\", tex:\"angle\", ttype:CONST},\n{input:\"\\\\ \", tag:\"mo\", output:\"\\u00A0\", tex:null, ttype:CONST},\n{input:\"quad\", tag:\"mo\", output:\"\\u00A0\\u00A0\", tex:null, ttype:CONST},\n{input:\"qquad\", tag:\"mo\", output:\"\\u00A0\\u00A0\\u00A0\\u00A0\", tex:null, ttype:CONST},\n{input:\"cdots\", tag:\"mo\", output:\"\\u22EF\", tex:null, ttype:CONST},\n{input:\"vdots\", tag:\"mo\", output:\"\\u22EE\", tex:null, ttype:CONST},\n{input:\"ddots\", tag:\"mo\", output:\"\\u22F1\", tex:null, ttype:CONST},\n{input:\"diamond\", tag:\"mo\", output:\"\\u22C4\", tex:null, ttype:CONST},\n{input:\"square\", tag:\"mo\", output:\"\\u25A1\", tex:null, ttype:CONST},\n{input:\"|__\", tag:\"mo\", output:\"\\u230A\", tex:\"lfloor\", ttype:CONST},\n{input:\"__|\", tag:\"mo\", output:\"\\u230B\", tex:\"rfloor\", ttype:CONST},\n{input:\"|~\", tag:\"mo\", output:\"\\u2308\", tex:\"lceiling\", ttype:CONST},\n{input:\"~|\", tag:\"mo\", output:\"\\u2309\", tex:\"rceiling\", ttype:CONST},\n{input:\"CC\", tag:\"mo\", output:\"\\u2102\", tex:null, ttype:CONST},\n{input:\"NN\", tag:\"mo\", output:\"\\u2115\", tex:null, ttype:CONST},\n{input:\"QQ\", tag:\"mo\", output:\"\\u211A\", tex:null, ttype:CONST},\n{input:\"RR\", tag:\"mo\", output:\"\\u211D\", tex:null, ttype:CONST},\n{input:\"ZZ\", tag:\"mo\", output:\"\\u2124\", tex:null, ttype:CONST},\n{input:\"f\", tag:\"mi\", output:\"f\", tex:null, ttype:UNARY, func:true},\n{input:\"g\", tag:\"mi\", output:\"g\", tex:null, ttype:UNARY, func:true},\n\n//standard functions\n{input:\"lim\", tag:\"mo\", output:\"lim\", tex:null, ttype:UNDEROVER},\n{input:\"Lim\", tag:\"mo\", output:\"Lim\", tex:null, ttype:UNDEROVER},\n{input:\"sin\", tag:\"mo\", output:\"sin\", tex:null, ttype:UNARY, func:true},\n{input:\"cos\", tag:\"mo\", output:\"cos\", tex:null, ttype:UNARY, func:true},\n{input:\"tan\", tag:\"mo\", output:\"tan\", tex:null, ttype:UNARY, func:true},\n{input:\"sinh\", tag:\"mo\", output:\"sinh\", tex:null, ttype:UNARY, func:true},\n{input:\"cosh\", tag:\"mo\", output:\"cosh\", tex:null, ttype:UNARY, func:true},\n{input:\"tanh\", tag:\"mo\", output:\"tanh\", tex:null, ttype:UNARY, func:true},\n{input:\"cot\", tag:\"mo\", output:\"cot\", tex:null, ttype:UNARY, func:true},\n{input:\"sec\", tag:\"mo\", output:\"sec\", tex:null, ttype:UNARY, func:true},\n{input:\"csc\", tag:\"mo\", output:\"csc\", tex:null, ttype:UNARY, func:true},\n{input:\"log\", tag:\"mo\", output:\"log\", tex:null, ttype:UNARY, func:true},\n{input:\"ln\", tag:\"mo\", output:\"ln\", tex:null, ttype:UNARY, func:true},\n{input:\"det\", tag:\"mo\", output:\"det\", tex:null, ttype:UNARY, func:true},\n{input:\"dim\", tag:\"mo\", output:\"dim\", tex:null, ttype:CONST},\n{input:\"mod\", tag:\"mo\", output:\"mod\", tex:null, ttype:CONST},\n{input:\"gcd\", tag:\"mo\", output:\"gcd\", tex:null, ttype:UNARY, func:true},\n{input:\"lcm\", tag:\"mo\", output:\"lcm\", tex:null, ttype:UNARY, func:true},\n{input:\"lub\", tag:\"mo\", output:\"lub\", tex:null, ttype:CONST},\n{input:\"glb\", tag:\"mo\", output:\"glb\", tex:null, ttype:CONST},\n{input:\"min\", tag:\"mo\", output:\"min\", tex:null, ttype:UNDEROVER},\n{input:\"max\", tag:\"mo\", output:\"max\", tex:null, ttype:UNDEROVER},\n\n//arrows\n{input:\"uarr\", tag:\"mo\", output:\"\\u2191\", tex:\"uparrow\", ttype:CONST},\n{input:\"darr\", tag:\"mo\", output:\"\\u2193\", tex:\"downarrow\", ttype:CONST},\n{input:\"rarr\", tag:\"mo\", output:\"\\u2192\", tex:\"rightarrow\", ttype:CONST},\n{input:\"->\", tag:\"mo\", output:\"\\u2192\", tex:\"to\", ttype:CONST},\n{input:\">->\", tag:\"mo\", output:\"\\u21A3\", tex:\"rightarrowtail\", ttype:CONST},\n{input:\"->>\", tag:\"mo\", output:\"\\u21A0\", tex:\"twoheadrightarrow\", ttype:CONST},\n{input:\">->>\", tag:\"mo\", output:\"\\u2916\", tex:\"twoheadrightarrowtail\", ttype:CONST},\n{input:\"|->\", tag:\"mo\", output:\"\\u21A6\", tex:\"mapsto\", ttype:CONST},\n{input:\"larr\", tag:\"mo\", output:\"\\u2190\", tex:\"leftarrow\", ttype:CONST},\n{input:\"harr\", tag:\"mo\", output:\"\\u2194\", tex:\"leftrightarrow\", ttype:CONST},\n{input:\"rArr\", tag:\"mo\", output:\"\\u21D2\", tex:\"Rightarrow\", ttype:CONST},\n{input:\"lArr\", tag:\"mo\", output:\"\\u21D0\", tex:\"Leftarrow\", ttype:CONST},\n{input:\"hArr\", tag:\"mo\", output:\"\\u21D4\", tex:\"Leftrightarrow\", ttype:CONST},\n//commands with argument\n{input:\"sqrt\", tag:\"msqrt\", output:\"sqrt\", tex:null, ttype:UNARY},\n{input:\"root\", tag:\"mroot\", output:\"root\", tex:null, ttype:BINARY},\n{input:\"frac\", tag:\"mfrac\", output:\"/\", tex:null, ttype:BINARY},\n{input:\"/\", tag:\"mfrac\", output:\"/\", tex:null, ttype:INFIX},\n{input:\"stackrel\", tag:\"mover\", output:\"stackrel\", tex:null, ttype:BINARY},\n{input:\"_\", tag:\"msub\", output:\"_\", tex:null, ttype:INFIX},\n{input:\"^\", tag:\"msup\", output:\"^\", tex:null, ttype:INFIX},\n{input:\"hat\", tag:\"mover\", output:\"\\u005E\", tex:null, ttype:UNARY, acc:true},\n{input:\"bar\", tag:\"mover\", output:\"\\u00AF\", tex:\"overline\", ttype:UNARY, acc:true},\n{input:\"vec\", tag:\"mover\", output:\"\\u2192\", tex:null, ttype:UNARY, acc:true},\n{input:\"dot\", tag:\"mover\", output:\".\", tex:null, ttype:UNARY, acc:true},\n{input:\"ddot\", tag:\"mover\", output:\"..\", tex:null, ttype:UNARY, acc:true},\n{input:\"ul\", tag:\"munder\", output:\"\\u0332\", tex:\"underline\", ttype:UNARY, acc:true},\n{input:\"text\", tag:\"mtext\", output:\"text\", tex:null, ttype:TEXT},\n{input:\"mbox\", tag:\"mtext\", output:\"mbox\", tex:null, ttype:TEXT},\nAMquote,\n{input:\"bb\", tag:\"mstyle\", atname:\"fontweight\", atval:\"bold\", output:\"bb\", tex:null, ttype:UNARY},\n{input:\"mathbf\", tag:\"mstyle\", atname:\"fontweight\", atval:\"bold\", output:\"mathbf\", tex:null, ttype:UNARY},\n{input:\"sf\", tag:\"mstyle\", atname:\"fontfamily\", atval:\"sans-serif\", output:\"sf\", tex:null, ttype:UNARY},\n{input:\"mathsf\", tag:\"mstyle\", atname:\"fontfamily\", atval:\"sans-serif\", output:\"mathsf\", tex:null, ttype:UNARY},\n{input:\"bbb\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"double-struck\", output:\"bbb\", tex:null, ttype:UNARY, codes:AMbbb},\n{input:\"mathbb\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"double-struck\", output:\"mathbb\", tex:null, ttype:UNARY, codes:AMbbb},\n{input:\"cc\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"script\", output:\"cc\", tex:null, ttype:UNARY, codes:AMcal},\n{input:\"mathcal\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"script\", output:\"mathcal\", tex:null, ttype:UNARY, codes:AMcal},\n{input:\"tt\", tag:\"mstyle\", atname:\"fontfamily\", atval:\"monospace\", output:\"tt\", tex:null, ttype:UNARY},\n{input:\"mathtt\", tag:\"mstyle\", atname:\"fontfamily\", atval:\"monospace\", output:\"mathtt\", tex:null, ttype:UNARY},\n{input:\"fr\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"fraktur\", output:\"fr\", tex:null, ttype:UNARY, codes:AMfrk},\n{input:\"mathfrak\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"fraktur\", output:\"mathfrak\", tex:null, ttype:UNARY, codes:AMfrk}\n];\n\nfunction compareNames(s1,s2) {\n if (s1.input > s2.input) return 1\n else return -1;\n}\n\nvar AMnames = []; //list of input symbols\n\nfunction initSymbols() {\n var texsymbols = [], i;\n for (i=0; i<AMsymbols.length; i++)\n if (AMsymbols[i].tex) \n texsymbols[texsymbols.length] = {input:AMsymbols[i].tex, \n tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype};\n AMsymbols = AMsymbols.concat(texsymbols);\n refreshSymbols();\n}\n\nfunction refreshSymbols(){\n var i;\n AMsymbols.sort(compareNames);\n for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;\n LMsymbols.sort(compareNames);\n for (i=0; i<LMsymbols.length; i++) LMnames[i] = LMsymbols[i].input;\n}\n\nfunction define(oldstr,newstr) {\n if(oldstr.substr(0,1)==\"\\\\\")\n LMsymbols = LMsymbols.concat([{input:oldstr, tag:\"mo\", output:newstr,\n ttype:DEFINITION}]);\n else\n AMsymbols = AMsymbols.concat([{input:oldstr, tag:\"mo\", output:newstr, \n tex:null, ttype:DEFINITION}]);\n refreshSymbols(); // this may be a problem if many symbols are defined!\n}\n\nfunction AMremoveCharsAndBlanks(str,n) {\n//remove n characters and any following blanks\n var st;\n if (str.charAt(n)==\"\\\\\" && str.charAt(n+1)!=\"\\\\\" && str.charAt(n+1)!=\" \") \n st = str.slice(n+1);\n else st = str.slice(n);\n for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);\n return st.slice(i);\n}\n\nfunction position(arr, str, n) { \n// return position >=n where str appears or would be inserted\n// assumes arr is sorted\n if (n==0) {\n var h,m;\n n = -1;\n h = arr.length;\n while (n+1<h) {\n m = (n+h) >> 1;\n if (arr[m]<str) n = m; else h = m;\n }\n return h;\n } else\n for (var i=n; i<arr.length && arr[i]<str; i++);\n return i; // i=arr.length || arr[i]>=str\n}\n\nfunction AMgetSymbol(str) {\n//return maximal initial substring of str that appears in names\n//return null if there is none\n var k = 0; //new pos\n var j = 0; //old pos\n var mk; //match pos\n var st;\n var tagst;\n var match = \"\";\n var more = true;\n for (var i=1; i<=str.length && more; i++) {\n st = str.slice(0,i); //initial substring of length i\n j = k;\n k = position(AMnames, st, j);\n if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){\n match = AMnames[k];\n mk = k;\n i = match.length;\n }\n more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];\n }\n AMpreviousSymbol=AMcurrentSymbol;\n if (match!=\"\"){\n AMcurrentSymbol=AMsymbols[mk].ttype;\n return AMsymbols[mk]; \n }\n// if str[0] is a digit or - return maxsubstring of digits.digits\n AMcurrentSymbol=CONST;\n k = 1;\n st = str.slice(0,1);\n var integ = true;\n while (\"0\"<=st && st<=\"9\" && k<=str.length) {\n st = str.slice(k,k+1);\n k++;\n }\n if (st == decimalsign) {\n st = str.slice(k,k+1);\n if (\"0\"<=st && st<=\"9\") {\n integ = false;\n k++;\n while (\"0\"<=st && st<=\"9\" && k<=str.length) {\n st = str.slice(k,k+1);\n k++;\n }\n }\n }\n if ((integ && k>1) || k>2) {\n st = str.slice(0,k-1);\n tagst = \"mn\";\n } else {\n k = 2;\n st = str.slice(0,1); //take 1 character\n tagst = ((\"A\">st || st>\"Z\") && (\"a\">st || st>\"z\")?\"mo\":\"mi\");\n }\n if (st==\"-\" && AMpreviousSymbol==INFIX) {\n AMcurrentSymbol = INFIX; //trick \"/\" into recognizing \"-\" on second parse\n return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};\n }\n return {input:st, tag:tagst, output:st, ttype:CONST};\n}\n\nfunction AMremoveBrackets(node) {\n var st;\n if (node.nodeName==\"mrow\") {\n st = node.firstChild.firstChild.nodeValue;\n if (st==\"(\" || st==\"[\" || st==\"{\") node.removeChild(node.firstChild);\n }\n if (node.nodeName==\"mrow\") {\n st = node.lastChild.firstChild.nodeValue;\n if (st==\")\" || st==\"]\" || st==\"}\") node.removeChild(node.lastChild);\n }\n}\n\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n\nvar AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;\n\nfunction AMparseSexpr(str) { //parses str and returns [node,tailstr]\n var symbol, node, result, i, st,// rightvert = false,\n newFrag = document.createDocumentFragment();\n str = AMremoveCharsAndBlanks(str,0);\n symbol = AMgetSymbol(str); //either a token or a bracket or empty\n if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {\n return [null,str];\n }\n if (symbol.ttype == DEFINITION) {\n str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length); \n symbol = AMgetSymbol(str);\n }\n switch (symbol.ttype) { case UNDEROVER:\n case CONST:\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n return [createMmlNode(symbol.tag, //its a constant\n document.createTextNode(symbol.output)),str];\n case LEFTBRACKET: //read (expr+)\n AMnestingDepth++;\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n result = AMparseExpr(str,true);\n AMnestingDepth--;\n if (typeof symbol.invisible == \"boolean\" && symbol.invisible) \n node = createMmlNode(\"mrow\",result[0]);\n else {\n node = createMmlNode(\"mo\",document.createTextNode(symbol.output));\n node = createMmlNode(\"mrow\",node);\n node.appendChild(result[0]);\n }\n return [node,result[1]];\n case TEXT:\n if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);\n if (str.charAt(0)==\"{\") i=str.indexOf(\"}\");\n else if (str.charAt(0)==\"(\") i=str.indexOf(\")\");\n else if (str.charAt(0)==\"[\") i=str.indexOf(\"]\");\n else if (symbol==AMquote) i=str.slice(1).indexOf(\"\\\"\")+1;\n else i = 0;\n if (i==-1) i = str.length;\n st = str.slice(1,i);\n if (st.charAt(0) == \" \") {\n node = createMmlNode(\"mspace\");\n node.setAttribute(\"width\",\"1ex\");\n newFrag.appendChild(node);\n }\n newFrag.appendChild(\n createMmlNode(symbol.tag,document.createTextNode(st)));\n if (st.charAt(st.length-1) == \" \") {\n node = createMmlNode(\"mspace\");\n node.setAttribute(\"width\",\"1ex\");\n newFrag.appendChild(node);\n }\n str = AMremoveCharsAndBlanks(str,i+1);\n return [createMmlNode(\"mrow\",newFrag),str];\n case UNARY:\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n result = AMparseSexpr(str);\n if (result[0]==null) return [createMmlNode(symbol.tag,\n document.createTextNode(symbol.output)),str];\n if (typeof symbol.func == \"boolean\" && symbol.func) { // functions hack\n st = str.charAt(0);\n if (st==\"^\" || st==\"_\" || st==\"/\" || st==\"|\" || st==\",\") {\n return [createMmlNode(symbol.tag,\n document.createTextNode(symbol.output)),str];\n } else {\n node = createMmlNode(\"mrow\",\n createMmlNode(symbol.tag,document.createTextNode(symbol.output)));\n node.appendChild(result[0]);\n return [node,result[1]];\n }\n }\n AMremoveBrackets(result[0]);\n if (symbol.input == \"sqrt\") { // sqrt\n return [createMmlNode(symbol.tag,result[0]),result[1]];\n } else if (typeof symbol.acc == \"boolean\" && symbol.acc) { // accent\n node = createMmlNode(symbol.tag,result[0]);\n node.appendChild(createMmlNode(\"mo\",document.createTextNode(symbol.output)));\n return [node,result[1]];\n } else { // font change command\n if (!isIE && typeof symbol.codes != \"undefined\") {\n for (i=0; i<result[0].childNodes.length; i++)\n if (result[0].childNodes[i].nodeName==\"mi\" || result[0].nodeName==\"mi\") {\n st = (result[0].nodeName==\"mi\"?result[0].firstChild.nodeValue:\n result[0].childNodes[i].firstChild.nodeValue);\n var newst = [];\n for (var j=0; j<st.length; j++)\n if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst +\n String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);\n else newst = newst + st.charAt(j);\n if (result[0].nodeName==\"mi\")\n result[0]=createMmlNode(\"mo\").\n appendChild(document.createTextNode(newst));\n else result[0].replaceChild(createMmlNode(\"mo\").\n appendChild(document.createTextNode(newst)),\n result[0].childNodes[i]);\n }\n }\n node = createMmlNode(symbol.tag,result[0]);\n node.setAttribute(symbol.atname,symbol.atval);\n return [node,result[1]];\n }\n case BINARY:\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n result = AMparseSexpr(str);\n if (result[0]==null) return [createMmlNode(\"mo\",\n document.createTextNode(symbol.input)),str];\n AMremoveBrackets(result[0]);\n var result2 = AMparseSexpr(result[1]);\n if (result2[0]==null) return [createMmlNode(\"mo\",\n document.createTextNode(symbol.input)),str];\n AMremoveBrackets(result2[0]);\n if (symbol.input==\"root\" || symbol.input==\"stackrel\") \n newFrag.appendChild(result2[0]);\n newFrag.appendChild(result[0]);\n if (symbol.input==\"frac\") newFrag.appendChild(result2[0]);\n return [createMmlNode(symbol.tag,newFrag),result2[1]];\n case INFIX:\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n return [createMmlNode(\"mo\",document.createTextNode(symbol.output)),str];\n case SPACE:\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n node = createMmlNode(\"mspace\");\n node.setAttribute(\"width\",\"1ex\");\n newFrag.appendChild(node);\n newFrag.appendChild(\n createMmlNode(symbol.tag,document.createTextNode(symbol.output)));\n node = createMmlNode(\"mspace\");\n node.setAttribute(\"width\",\"1ex\");\n newFrag.appendChild(node);\n return [createMmlNode(\"mrow\",newFrag),str];\n case LEFTRIGHT:\n// if (rightvert) return [null,str]; else rightvert = true;\n AMnestingDepth++;\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n result = AMparseExpr(str,false);\n AMnestingDepth--;\n var st = \"\";\n if (result[0].lastChild!=null)\n st = result[0].lastChild.firstChild.nodeValue;\n if (st == \"|\") { // its an absolute value subterm\n node = createMmlNode(\"mo\",document.createTextNode(symbol.output));\n node = createMmlNode(\"mrow\",node);\n node.appendChild(result[0]);\n return [node,result[1]];\n } else { // the \"|\" is a \\mid so use unicode 2223 (divides) for spacing\n node = createMmlNode(\"mo\",document.createTextNode(\"\\u2223\"));\n node = createMmlNode(\"mrow\",node);\n return [node,str];\n }\n default:\n//alert(\"default\");\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n return [createMmlNode(symbol.tag, //its a constant\n document.createTextNode(symbol.output)),str];\n }\n}\n\nfunction AMparseIexpr(str) {\n var symbol, sym1, sym2, node, result, underover;\n str = AMremoveCharsAndBlanks(str,0);\n sym1 = AMgetSymbol(str);\n result = AMparseSexpr(str);\n node = result[0];\n str = result[1];\n symbol = AMgetSymbol(str);\n if (symbol.ttype == INFIX && symbol.input != \"/\") {\n str = AMremoveCharsAndBlanks(str,symbol.input.length);\n// if (symbol.input == \"/\") result = AMparseIexpr(str); else ...\n result = AMparseSexpr(str);\n if (result[0] == null) // show box in place of missing argument\n result[0] = createMmlNode(\"mo\",document.createTextNode(\"\\u25A1\"));\n else AMremoveBrackets(result[0]);\n str = result[1];\n// if (symbol.input == \"/\") AMremoveBrackets(node);\n if (symbol.input == \"_\") {\n sym2 = AMgetSymbol(str);\n underover = (sym1.ttype == UNDEROVER);\n if (sym2.input == \"^\") {\n str = AMremoveCharsAndBlanks(str,sym2.input.length);\n var res2 = AMparseSexpr(str);\n AMremoveBrackets(res2[0]);\n str = res2[1];\n node = createMmlNode((underover?\"munderover\":\"msubsup\"),node);\n node.appendChild(result[0]);\n node.appendChild(res2[0]);\n node = createMmlNode(\"mrow\",node); // so sum does not stretch\n } else {\n node = createMmlNode((underover?\"munder\":\"msub\"),node);\n node.appendChild(result[0]);\n }\n } else {\n node = createMmlNode(symbol.tag,node);\n node.appendChild(result[0]);\n }\n }\n return [node,str];\n}\n\nfunction AMparseExpr(str,rightbracket) {\n var symbol, node, result, i, nodeList = [],\n newFrag = document.createDocumentFragment();\n do {\n str = AMremoveCharsAndBlanks(str,0);\n result = AMparseIexpr(str);\n node = result[0];\n str = result[1];\n symbol = AMgetSymbol(str);\n if (symbol.ttype == INFIX && symbol.input == \"/\") {\n str = AMremoveCharsAndBlanks(str,symbol.input.length);\n result = AMparseIexpr(str);\n if (result[0] == null) // show box in place of missing argument\n result[0] = createMmlNode(\"mo\",document.createTextNode(\"\\u25A1\"));\n else AMremoveBrackets(result[0]);\n str = result[1];\n AMremoveBrackets(node);\n node = createMmlNode(symbol.tag,node);\n node.appendChild(result[0]);\n newFrag.appendChild(node);\n symbol = AMgetSymbol(str);\n } \n else if (node!=undefined) newFrag.appendChild(node);\n } while ((symbol.ttype != RIGHTBRACKET && \n (symbol.ttype != LEFTRIGHT || rightbracket)\n || AMnestingDepth == 0) && symbol!=null && symbol.output!=\"\");\n if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {\n// if (AMnestingDepth > 0) AMnestingDepth--;\n var len = newFrag.childNodes.length;\n if (len>0 && newFrag.childNodes[len-1].nodeName == \"mrow\" && len>1 &&\n newFrag.childNodes[len-2].nodeName == \"mo\" &&\n newFrag.childNodes[len-2].firstChild.nodeValue == \",\") { //matrix\n var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;\n if (right==\")\" || right==\"]\") {\n var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;\n if (left==\"(\" && right==\")\" && symbol.output != \"}\" || \n left==\"[\" && right==\"]\") {\n var pos = []; // positions of commas\n var matrix = true;\n var m = newFrag.childNodes.length;\n for (i=0; matrix && i<m; i=i+2) {\n pos[i] = [];\n node = newFrag.childNodes[i];\n if (matrix) matrix = node.nodeName==\"mrow\" && \n (i==m-1 || node.nextSibling.nodeName==\"mo\" && \n node.nextSibling.firstChild.nodeValue==\",\")&&\n node.firstChild.firstChild.nodeValue==left &&\n node.lastChild.firstChild.nodeValue==right;\n if (matrix) \n for (var j=0; j<node.childNodes.length; j++)\n if (node.childNodes[j].firstChild.nodeValue==\",\")\n pos[i][pos[i].length]=j;\n if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;\n }\n if (matrix) {\n var row, frag, n, k, table = document.createDocumentFragment();\n for (i=0; i<m; i=i+2) {\n row = document.createDocumentFragment();\n frag = document.createDocumentFragment();\n node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>\n n = node.childNodes.length;\n k = 0;\n node.removeChild(node.firstChild); //remove (\n for (j=1; j<n-1; j++) {\n if (typeof pos[i][k] != \"undefined\" && j==pos[i][k]){\n node.removeChild(node.firstChild); //remove ,\n row.appendChild(createMmlNode(\"mtd\",frag));\n k++;\n } else frag.appendChild(node.firstChild);\n }\n row.appendChild(createMmlNode(\"mtd\",frag));\n if (newFrag.childNodes.length>2) {\n newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>\n newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>\n }\n table.appendChild(createMmlNode(\"mtr\",row));\n }\n node = createMmlNode(\"mtable\",table);\n if (typeof symbol.invisible == \"boolean\" && symbol.invisible) node.setAttribute(\"columnalign\",\"left\");\n newFrag.replaceChild(node,newFrag.firstChild);\n }\n }\n }\n }\n str = AMremoveCharsAndBlanks(str,symbol.input.length);\n if (typeof symbol.invisible != \"boolean\" || !symbol.invisible) {\n node = createMmlNode(\"mo\",document.createTextNode(symbol.output));\n newFrag.appendChild(node);\n }\n }\n return [newFrag,str];\n}\n\nfunction parseMath(str,latex) {\n var frag, node;\n AMnestingDepth = 0;\n frag = latex ? LMparseExpr(str.replace(/^\\s+/g,\"\"),false,false)[0] : AMparseExpr(str.replace(/^\\s+/g,\"\"),false)[0];\n node = createMmlNode(\"mstyle\",frag);\n node.setAttribute(\"mathcolor\",mathcolor);\n node.setAttribute(\"fontfamily\",mathfontfamily);\n node.setAttribute(\"mathsize\",mathfontsize);\n if (displaystyle) node.setAttribute(\"displaystyle\",\"true\");\n node = createMmlNode(\"math\",node);\n if (showasciiformulaonhover) //fixed by djhsu so newline\n node.setAttribute(\"title\",str.replace(/\\s+/g,\" \"));//does not show in Gecko\n return node;\n}\n\nfunction strarr2docFrag(arr, linebreaks, latex) {\n var newFrag=document.createDocumentFragment();\n var expr = false;\n for (var i=0; i<arr.length; i++) {\n if (expr) newFrag.appendChild(parseMath(arr[i],latex));\n else {\n var arri = (linebreaks ? arr[i].split(\"\\n\\n\") : [arr[i]]);\n newFrag.appendChild(createElementXHTML(\"span\").\n appendChild(document.createTextNode(arri[0])));\n for (var j=1; j<arri.length; j++) {\n newFrag.appendChild(createElementXHTML(\"p\"));\n newFrag.appendChild(createElementXHTML(\"span\").\n appendChild(document.createTextNode(arri[j])));\n }\n }\n expr = !expr;\n }\n return newFrag;\n}\n\nfunction AMautomathrec(str) {\n//formula is a space (or start of str) followed by a maximal sequence of *two* or more tokens, possibly separated by runs of digits and/or space.\n//tokens are single letters (except a, A, I) and ASCIIMathML tokens\n var texcommand = \"\\\\\\\\[a-zA-Z]+|\\\\\\\\\\\\s|\";\n var ambigAMtoken = \"\\\\b(?:oo|lim|ln|int|oint|del|grad|aleph|prod|prop|sinh|cosh|tanh|cos|sec|pi|tt|fr|sf|sube|supe|sub|sup|det|mod|gcd|lcm|min|max|vec|ddot|ul|chi|eta|nu|mu)(?![a-z])|\";\n var englishAMtoken = \"\\\\b(?:sum|ox|log|sin|tan|dim|hat|bar|dot)(?![a-z])|\";\n var secondenglishAMtoken = \"|\\\\bI\\\\b|\\\\bin\\\\b|\\\\btext\\\\b\"; // took if and or not out\n var simpleAMtoken = \"NN|ZZ|QQ|RR|CC|TT|AA|EE|sqrt|dx|dy|dz|dt|xx|vv|uu|nn|bb|cc|csc|cot|alpha|beta|delta|Delta|epsilon|gamma|Gamma|kappa|lambda|Lambda|omega|phi|Phi|Pi|psi|Psi|rho|sigma|Sigma|tau|theta|Theta|xi|Xi|zeta\"; // uuu nnn?\n var letter = \"[a-zA-HJ-Z](?=(?:[^a-zA-Z]|$|\"+ambigAMtoken+englishAMtoken+simpleAMtoken+\"))|\";\n var token = letter+texcommand+\"\\\\d+|[-()[\\\\]{}+=*&^_%\\\\\\@/<>,\\\\|!:;'~]|\\\\.(?!(?:\\x20|$))|\"+ambigAMtoken+englishAMtoken+simpleAMtoken;\n var re = new RegExp(\"(^|\\\\s)(((\"+token+\")\\\\s?)((\"+token+secondenglishAMtoken+\")\\\\s?)+)([,.?]?(?=\\\\s|$))\",\"g\");\n str = str.replace(re,\" `$2`$7\");\n var arr = str.split(AMdelimiter1);\n var re1 = new RegExp(\"(^|\\\\s)([b-zB-HJ-Z+*<>]|\"+texcommand+ambigAMtoken+simpleAMtoken+\")(\\\\s|\\\\n|$)\",\"g\");\n var re2 = new RegExp(\"(^|\\\\s)([a-z]|\"+texcommand+ambigAMtoken+simpleAMtoken+\")([,.])\",\"g\"); // removed |\\d+ for now\n for (i=0; i<arr.length; i++) //single nonenglish tokens\n if (i%2==0) {\n arr[i] = arr[i].replace(re1,\" `$2`$3\");\n arr[i] = arr[i].replace(re2,\" `$2`$3\");\n arr[i] = arr[i].replace(/([{}[\\]])/,\"`$1`\");\n }\n str = arr.join(AMdelimiter1);\n str = str.replace(/((^|\\s)\\([a-zA-Z]{2,}.*?)\\)`/g,\"$1`)\"); //fix parentheses\n str = str.replace(/`(\\((a\\s|in\\s))(.*?[a-zA-Z]{2,}\\))/g,\"$1`$3\"); //fix parentheses\n str = str.replace(/\\sin`/g,\"` in\");\n str = str.replace(/`(\\(\\w\\)[,.]?(\\s|\\n|$))/g,\"$1`\");\n str = str.replace(/`([0-9.]+|e.g|i.e)`(\\.?)/gi,\"$1$2\");\n str = str.replace(/`([0-9.]+:)`/g,\"$1\");\n return str;\n}\n\nfunction processNodeR(n, linebreaks,latex) {\n var mtch, str, arr, frg, i;\n if (n.childNodes.length == 0) {\n if ((n.nodeType!=8 || linebreaks) &&\n n.parentNode.nodeName!=\"form\" && n.parentNode.nodeName!=\"FORM\" &&\n n.parentNode.nodeName!=\"textarea\" && n.parentNode.nodeName!=\"TEXTAREA\" /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */) {\n str = n.nodeValue;\n if (!(str == null)) {\n str = str.replace(/\\r\\n\\r\\n/g,\"\\n\\n\");\n str = str.replace(/\\x20+/g,\" \");\n str = str.replace(/\\s*\\r\\n/g,\" \");\n if(latex) {\n// DELIMITERS:\n mtch = (str.indexOf(\"\\$\")==-1 ? false : true);\n str = str.replace(/([^\\\\])\\$/g,\"$1 \\$\");\n str = str.replace(/^\\$/,\" \\$\");\t// in case \\$ at start of string\n arr = str.split(\" \\$\");\n for (i=0; i<arr.length; i++)\n\t arr[i]=arr[i].replace(/\\\\\\$/g,\"\\$\");\n } else {\n mtch = false;\n str = str.replace(new RegExp(AMescape1, \"g\"),\n function(){mtch = true; return \"AMescape1\"});\n str = str.replace(/\\\\?end{?a?math}?/i,\n function(){automathrecognize = false; mtch = true; return \"\"});\n str = str.replace(/amath\\b|\\\\begin{a?math}/i,\n function(){automathrecognize = true; mtch = true; return \"\"});\n arr = str.split(AMdelimiter1);\n if (automathrecognize)\n for (i=0; i<arr.length; i++)\n if (i%2==0) arr[i] = AMautomathrec(arr[i]);\n str = arr.join(AMdelimiter1);\n arr = str.split(AMdelimiter1);\n for (i=0; i<arr.length; i++) // this is a problem ************\n arr[i]=arr[i].replace(/AMescape1/g,AMdelimiter1);\n }\n if (arr.length>1 || mtch) {\n if (!noMathML) {\n frg = strarr2docFrag(arr,n.nodeType==8,latex);\n var len = frg.childNodes.length;\n n.parentNode.replaceChild(frg,n);\n return len-1;\n } else return 0;\n }\n }\n } else return 0;\n } else if (n.nodeName!=\"math\") {\n for (i=0; i<n.childNodes.length; i++)\n i += processNodeR(n.childNodes[i], linebreaks,latex);\n }\n return 0;\n}\n\nfunction AMprocessNode(n, linebreaks, spanclassAM) {\n var frag,st;\n if (spanclassAM!=null) {\n frag = document.getElementsByTagName(\"span\")\n for (var i=0;i<frag.length;i++)\n if (frag[i].className == \"AM\") \n processNodeR(frag[i],linebreaks,false);\n } else {\n try {\n st = n.innerHTML; // look for AMdelimiter on page\n } catch(err) {}\n//alert(st)\n if (st==null || /amath\\b|\\\\begin{a?math}/i.test(st) ||\n st.indexOf(AMdelimiter1+\" \")!=-1 || st.slice(-1)==AMdelimiter1 ||\n st.indexOf(AMdelimiter1+\"<\")!=-1 || st.indexOf(AMdelimiter1+\"\\n\")!=-1) {\n processNodeR(n,linebreaks,false);\n }\n }\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n}\n\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n\n// all further global variables start with \"LM\"\n\n// Commented out by DRW to prevent 1/2 turning into a 2-line fraction\n// LMdiv = {input:\"/\",\t tag:\"mfrac\", output:\"/\", ttype:INFIX},\n// Commented out by DRW so that \" prints literally in equations\n// LMquote = {input:\"\\\"\",\t tag:\"mtext\", output:\"mbox\", ttype:TEXT};\n\nvar LMsymbols = [\n//Greek letters\n{input:\"\\\\alpha\",\ttag:\"mi\", output:\"\\u03B1\", ttype:CONST},\n{input:\"\\\\beta\",\ttag:\"mi\", output:\"\\u03B2\", ttype:CONST},\n{input:\"\\\\gamma\",\ttag:\"mi\", output:\"\\u03B3\", ttype:CONST},\n{input:\"\\\\delta\",\ttag:\"mi\", output:\"\\u03B4\", ttype:CONST},\n{input:\"\\\\epsilon\",\ttag:\"mi\", output:\"\\u03B5\", ttype:CONST},\n{input:\"\\\\varepsilon\", tag:\"mi\", output:\"\\u025B\", ttype:CONST},\n{input:\"\\\\zeta\",\ttag:\"mi\", output:\"\\u03B6\", ttype:CONST},\n{input:\"\\\\eta\",\t\ttag:\"mi\", output:\"\\u03B7\", ttype:CONST},\n{input:\"\\\\theta\",\ttag:\"mi\", output:\"\\u03B8\", ttype:CONST},\n{input:\"\\\\vartheta\",\ttag:\"mi\", output:\"\\u03D1\", ttype:CONST},\n{input:\"\\\\iota\",\ttag:\"mi\", output:\"\\u03B9\", ttype:CONST},\n{input:\"\\\\kappa\",\ttag:\"mi\", output:\"\\u03BA\", ttype:CONST},\n{input:\"\\\\lambda\",\ttag:\"mi\", output:\"\\u03BB\", ttype:CONST},\n{input:\"\\\\mu\",\t\ttag:\"mi\", output:\"\\u03BC\", ttype:CONST},\n{input:\"\\\\nu\",\t\ttag:\"mi\", output:\"\\u03BD\", ttype:CONST},\n{input:\"\\\\xi\",\t\ttag:\"mi\", output:\"\\u03BE\", ttype:CONST},\n{input:\"\\\\pi\",\t\ttag:\"mi\", output:\"\\u03C0\", ttype:CONST},\n{input:\"\\\\varpi\",\ttag:\"mi\", output:\"\\u03D6\", ttype:CONST},\n{input:\"\\\\rho\",\t\ttag:\"mi\", output:\"\\u03C1\", ttype:CONST},\n{input:\"\\\\varrho\",\ttag:\"mi\", output:\"\\u03F1\", ttype:CONST},\n{input:\"\\\\varsigma\",\ttag:\"mi\", output:\"\\u03C2\", ttype:CONST},\n{input:\"\\\\sigma\",\ttag:\"mi\", output:\"\\u03C3\", ttype:CONST},\n{input:\"\\\\tau\",\t\ttag:\"mi\", output:\"\\u03C4\", ttype:CONST},\n{input:\"\\\\upsilon\",\ttag:\"mi\", output:\"\\u03C5\", ttype:CONST},\n{input:\"\\\\phi\",\t\ttag:\"mi\", output:\"\\u03C6\", ttype:CONST},\n{input:\"\\\\varphi\",\ttag:\"mi\", output:\"\\u03D5\", ttype:CONST},\n{input:\"\\\\chi\",\t\ttag:\"mi\", output:\"\\u03C7\", ttype:CONST},\n{input:\"\\\\psi\",\t\ttag:\"mi\", output:\"\\u03C8\", ttype:CONST},\n{input:\"\\\\omega\",\ttag:\"mi\", output:\"\\u03C9\", ttype:CONST},\n{input:\"\\\\Gamma\",\ttag:\"mo\", output:\"\\u0393\", ttype:CONST},\n{input:\"\\\\Delta\",\ttag:\"mo\", output:\"\\u0394\", ttype:CONST},\n{input:\"\\\\Theta\",\ttag:\"mo\", output:\"\\u0398\", ttype:CONST},\n{input:\"\\\\Lambda\",\ttag:\"mo\", output:\"\\u039B\", ttype:CONST},\n{input:\"\\\\Xi\",\t\ttag:\"mo\", output:\"\\u039E\", ttype:CONST},\n{input:\"\\\\Pi\",\t\ttag:\"mo\", output:\"\\u03A0\", ttype:CONST},\n{input:\"\\\\Sigma\",\ttag:\"mo\", output:\"\\u03A3\", ttype:CONST},\n{input:\"\\\\Upsilon\",\ttag:\"mo\", output:\"\\u03A5\", ttype:CONST},\n{input:\"\\\\Phi\",\t\ttag:\"mo\", output:\"\\u03A6\", ttype:CONST},\n{input:\"\\\\Psi\",\t\ttag:\"mo\", output:\"\\u03A8\", ttype:CONST},\n{input:\"\\\\Omega\",\ttag:\"mo\", output:\"\\u03A9\", ttype:CONST},\n\n//fractions\n{input:\"\\\\frac12\",\ttag:\"mo\", output:\"\\u00BD\", ttype:CONST},\n{input:\"\\\\frac14\",\ttag:\"mo\", output:\"\\u00BC\", ttype:CONST},\n{input:\"\\\\frac34\",\ttag:\"mo\", output:\"\\u00BE\", ttype:CONST},\n{input:\"\\\\frac13\",\ttag:\"mo\", output:\"\\u2153\", ttype:CONST},\n{input:\"\\\\frac23\",\ttag:\"mo\", output:\"\\u2154\", ttype:CONST},\n{input:\"\\\\frac15\",\ttag:\"mo\", output:\"\\u2155\", ttype:CONST},\n{input:\"\\\\frac25\",\ttag:\"mo\", output:\"\\u2156\", ttype:CONST},\n{input:\"\\\\frac35\",\ttag:\"mo\", output:\"\\u2157\", ttype:CONST},\n{input:\"\\\\frac45\",\ttag:\"mo\", output:\"\\u2158\", ttype:CONST},\n{input:\"\\\\frac16\",\ttag:\"mo\", output:\"\\u2159\", ttype:CONST},\n{input:\"\\\\frac56\",\ttag:\"mo\", output:\"\\u215A\", ttype:CONST},\n{input:\"\\\\frac18\",\ttag:\"mo\", output:\"\\u215B\", ttype:CONST},\n{input:\"\\\\frac38\",\ttag:\"mo\", output:\"\\u215C\", ttype:CONST},\n{input:\"\\\\frac58\",\ttag:\"mo\", output:\"\\u215D\", ttype:CONST},\n{input:\"\\\\frac78\",\ttag:\"mo\", output:\"\\u215E\", ttype:CONST},\n\n//binary operation symbols\n{input:\"\\\\pm\",\t\ttag:\"mo\", output:\"\\u00B1\", ttype:CONST},\n{input:\"\\\\mp\",\t\ttag:\"mo\", output:\"\\u2213\", ttype:CONST},\n{input:\"\\\\triangleleft\",tag:\"mo\", output:\"\\u22B2\", ttype:CONST},\n{input:\"\\\\triangleright\",tag:\"mo\",output:\"\\u22B3\", ttype:CONST},\n{input:\"\\\\cdot\",\ttag:\"mo\", output:\"\\u22C5\", ttype:CONST},\n{input:\"\\\\star\",\ttag:\"mo\", output:\"\\u22C6\", ttype:CONST},\n{input:\"\\\\ast\",\t\ttag:\"mo\", output:\"\\u002A\", ttype:CONST},\n{input:\"\\\\times\",\ttag:\"mo\", output:\"\\u00D7\", ttype:CONST},\n{input:\"\\\\div\",\t\ttag:\"mo\", output:\"\\u00F7\", ttype:CONST},\n{input:\"\\\\circ\",\ttag:\"mo\", output:\"\\u2218\", ttype:CONST},\n//{input:\"\\\\bullet\",\t tag:\"mo\", output:\"\\u2219\", ttype:CONST},\n{input:\"\\\\bullet\",\ttag:\"mo\", output:\"\\u2022\", ttype:CONST},\n{input:\"\\\\oplus\",\ttag:\"mo\", output:\"\\u2295\", ttype:CONST},\n{input:\"\\\\ominus\",\ttag:\"mo\", output:\"\\u2296\", ttype:CONST},\n{input:\"\\\\otimes\",\ttag:\"mo\", output:\"\\u2297\", ttype:CONST},\n{input:\"\\\\bigcirc\",\ttag:\"mo\", output:\"\\u25CB\", ttype:CONST},\n{input:\"\\\\oslash\",\ttag:\"mo\", output:\"\\u2298\", ttype:CONST},\n{input:\"\\\\odot\",\ttag:\"mo\", output:\"\\u2299\", ttype:CONST},\n{input:\"\\\\land\",\ttag:\"mo\", output:\"\\u2227\", ttype:CONST},\n{input:\"\\\\wedge\",\ttag:\"mo\", output:\"\\u2227\", ttype:CONST},\n{input:\"\\\\lor\",\t\ttag:\"mo\", output:\"\\u2228\", ttype:CONST},\n{input:\"\\\\vee\",\t\ttag:\"mo\", output:\"\\u2228\", ttype:CONST},\n{input:\"\\\\cap\",\t\ttag:\"mo\", output:\"\\u2229\", ttype:CONST},\n{input:\"\\\\cup\",\t\ttag:\"mo\", output:\"\\u222A\", ttype:CONST},\n{input:\"\\\\sqcap\",\ttag:\"mo\", output:\"\\u2293\", ttype:CONST},\n{input:\"\\\\sqcup\",\ttag:\"mo\", output:\"\\u2294\", ttype:CONST},\n{input:\"\\\\uplus\",\ttag:\"mo\", output:\"\\u228E\", ttype:CONST},\n{input:\"\\\\amalg\",\ttag:\"mo\", output:\"\\u2210\", ttype:CONST},\n{input:\"\\\\bigtriangleup\",tag:\"mo\",output:\"\\u25B3\", ttype:CONST},\n{input:\"\\\\bigtriangledown\",tag:\"mo\",output:\"\\u25BD\", ttype:CONST},\n{input:\"\\\\dag\",\t\ttag:\"mo\", output:\"\\u2020\", ttype:CONST},\n{input:\"\\\\dagger\",\ttag:\"mo\", output:\"\\u2020\", ttype:CONST},\n{input:\"\\\\ddag\",\ttag:\"mo\", output:\"\\u2021\", ttype:CONST},\n{input:\"\\\\ddagger\",\ttag:\"mo\", output:\"\\u2021\", ttype:CONST},\n{input:\"\\\\lhd\",\t\ttag:\"mo\", output:\"\\u22B2\", ttype:CONST},\n{input:\"\\\\rhd\",\t\ttag:\"mo\", output:\"\\u22B3\", ttype:CONST},\n{input:\"\\\\unlhd\",\ttag:\"mo\", output:\"\\u22B4\", ttype:CONST},\n{input:\"\\\\unrhd\",\ttag:\"mo\", output:\"\\u22B5\", ttype:CONST},\n\n\n//BIG Operators\n{input:\"\\\\sum\",\t\ttag:\"mo\", output:\"\\u2211\", ttype:UNDEROVER},\n{input:\"\\\\prod\",\ttag:\"mo\", output:\"\\u220F\", ttype:UNDEROVER},\n{input:\"\\\\bigcap\",\ttag:\"mo\", output:\"\\u22C2\", ttype:UNDEROVER},\n{input:\"\\\\bigcup\",\ttag:\"mo\", output:\"\\u22C3\", ttype:UNDEROVER},\n{input:\"\\\\bigwedge\",\ttag:\"mo\", output:\"\\u22C0\", ttype:UNDEROVER},\n{input:\"\\\\bigvee\",\ttag:\"mo\", output:\"\\u22C1\", ttype:UNDEROVER},\n{input:\"\\\\bigsqcap\",\ttag:\"mo\", output:\"\\u2A05\", ttype:UNDEROVER},\n{input:\"\\\\bigsqcup\",\ttag:\"mo\", output:\"\\u2A06\", ttype:UNDEROVER},\n{input:\"\\\\coprod\",\ttag:\"mo\", output:\"\\u2210\", ttype:UNDEROVER},\n{input:\"\\\\bigoplus\",\ttag:\"mo\", output:\"\\u2A01\", ttype:UNDEROVER},\n{input:\"\\\\bigotimes\",\ttag:\"mo\", output:\"\\u2A02\", ttype:UNDEROVER},\n{input:\"\\\\bigodot\",\ttag:\"mo\", output:\"\\u2A00\", ttype:UNDEROVER},\n{input:\"\\\\biguplus\",\ttag:\"mo\", output:\"\\u2A04\", ttype:UNDEROVER},\n{input:\"\\\\int\",\t\ttag:\"mo\", output:\"\\u222B\", ttype:CONST},\n{input:\"\\\\oint\",\ttag:\"mo\", output:\"\\u222E\", ttype:CONST},\n\n//binary relation symbols\n{input:\":=\",\t\ttag:\"mo\", output:\":=\",\t ttype:CONST},\n{input:\"\\\\lt\",\t\ttag:\"mo\", output:\"<\",\t ttype:CONST},\n{input:\"\\\\gt\",\t\ttag:\"mo\", output:\">\",\t ttype:CONST},\n{input:\"\\\\ne\",\t\ttag:\"mo\", output:\"\\u2260\", ttype:CONST},\n{input:\"\\\\neq\",\t\ttag:\"mo\", output:\"\\u2260\", ttype:CONST},\n{input:\"\\\\le\",\t\ttag:\"mo\", output:\"\\u2264\", ttype:CONST},\n{input:\"\\\\leq\",\t\ttag:\"mo\", output:\"\\u2264\", ttype:CONST},\n{input:\"\\\\leqslant\",\ttag:\"mo\", output:\"\\u2264\", ttype:CONST},\n{input:\"\\\\ge\",\t\ttag:\"mo\", output:\"\\u2265\", ttype:CONST},\n{input:\"\\\\geq\",\t\ttag:\"mo\", output:\"\\u2265\", ttype:CONST},\n{input:\"\\\\geqslant\",\ttag:\"mo\", output:\"\\u2265\", ttype:CONST},\n{input:\"\\\\equiv\",\ttag:\"mo\", output:\"\\u2261\", ttype:CONST},\n{input:\"\\\\ll\",\t\ttag:\"mo\", output:\"\\u226A\", ttype:CONST},\n{input:\"\\\\gg\",\t\ttag:\"mo\", output:\"\\u226B\", ttype:CONST},\n{input:\"\\\\doteq\",\ttag:\"mo\", output:\"\\u2250\", ttype:CONST},\n{input:\"\\\\prec\",\ttag:\"mo\", output:\"\\u227A\", ttype:CONST},\n{input:\"\\\\succ\",\ttag:\"mo\", output:\"\\u227B\", ttype:CONST},\n{input:\"\\\\preceq\",\ttag:\"mo\", output:\"\\u227C\", ttype:CONST},\n{input:\"\\\\succeq\",\ttag:\"mo\", output:\"\\u227D\", ttype:CONST},\n{input:\"\\\\subset\",\ttag:\"mo\", output:\"\\u2282\", ttype:CONST},\n{input:\"\\\\supset\",\ttag:\"mo\", output:\"\\u2283\", ttype:CONST},\n{input:\"\\\\subseteq\",\ttag:\"mo\", output:\"\\u2286\", ttype:CONST},\n{input:\"\\\\supseteq\",\ttag:\"mo\", output:\"\\u2287\", ttype:CONST},\n{input:\"\\\\sqsubset\",\ttag:\"mo\", output:\"\\u228F\", ttype:CONST},\n{input:\"\\\\sqsupset\",\ttag:\"mo\", output:\"\\u2290\", ttype:CONST},\n{input:\"\\\\sqsubseteq\", tag:\"mo\", output:\"\\u2291\", ttype:CONST},\n{input:\"\\\\sqsupseteq\", tag:\"mo\", output:\"\\u2292\", ttype:CONST},\n{input:\"\\\\sim\",\t\ttag:\"mo\", output:\"\\u223C\", ttype:CONST},\n{input:\"\\\\simeq\",\ttag:\"mo\", output:\"\\u2243\", ttype:CONST},\n{input:\"\\\\approx\",\ttag:\"mo\", output:\"\\u2248\", ttype:CONST},\n{input:\"\\\\cong\",\ttag:\"mo\", output:\"\\u2245\", ttype:CONST},\n{input:\"\\\\Join\",\ttag:\"mo\", output:\"\\u22C8\", ttype:CONST},\n{input:\"\\\\bowtie\",\ttag:\"mo\", output:\"\\u22C8\", ttype:CONST},\n{input:\"\\\\in\",\t\ttag:\"mo\", output:\"\\u2208\", ttype:CONST},\n{input:\"\\\\ni\",\t\ttag:\"mo\", output:\"\\u220B\", ttype:CONST},\n{input:\"\\\\owns\",\ttag:\"mo\", output:\"\\u220B\", ttype:CONST},\n{input:\"\\\\propto\",\ttag:\"mo\", output:\"\\u221D\", ttype:CONST},\n{input:\"\\\\vdash\",\ttag:\"mo\", output:\"\\u22A2\", ttype:CONST},\n{input:\"\\\\dashv\",\ttag:\"mo\", output:\"\\u22A3\", ttype:CONST},\n{input:\"\\\\models\",\ttag:\"mo\", output:\"\\u22A8\", ttype:CONST},\n{input:\"\\\\perp\",\ttag:\"mo\", output:\"\\u22A5\", ttype:CONST},\n{input:\"\\\\smile\",\ttag:\"mo\", output:\"\\u2323\", ttype:CONST},\n{input:\"\\\\frown\",\ttag:\"mo\", output:\"\\u2322\", ttype:CONST},\n{input:\"\\\\asymp\",\ttag:\"mo\", output:\"\\u224D\", ttype:CONST},\n{input:\"\\\\notin\",\ttag:\"mo\", output:\"\\u2209\", ttype:CONST},\n\n//matrices\n{input:\"\\\\begin{eqnarray}\",\toutput:\"X\",\tttype:MATRIX, invisible:true},\n{input:\"\\\\begin{array}\",\toutput:\"X\",\tttype:MATRIX, invisible:true},\n{input:\"\\\\\\\\\",\t\t\toutput:\"}&{\",\tttype:DEFINITION},\n{input:\"\\\\end{eqnarray}\",\toutput:\"}}\",\tttype:DEFINITION},\n{input:\"\\\\end{array}\",\t\toutput:\"}}\",\tttype:DEFINITION},\n\n//grouping and literal brackets -- ieval is for IE\n{input:\"\\\\big\",\t tag:\"mo\", output:\"X\", atval:\"1.2\", ieval:\"2.2\", ttype:BIG},\n{input:\"\\\\Big\",\t tag:\"mo\", output:\"X\", atval:\"1.6\", ieval:\"2.6\", ttype:BIG},\n{input:\"\\\\bigg\", tag:\"mo\", output:\"X\", atval:\"2.2\", ieval:\"3.2\", ttype:BIG},\n{input:\"\\\\Bigg\", tag:\"mo\", output:\"X\", atval:\"2.9\", ieval:\"3.9\", ttype:BIG},\n{input:\"\\\\left\", tag:\"mo\", output:\"X\", ttype:LEFTBRACKET},\n{input:\"\\\\right\", tag:\"mo\", output:\"X\", ttype:RIGHTBRACKET},\n{input:\"{\",\t output:\"{\", ttype:LEFTBRACKET, invisible:true},\n{input:\"}\",\t output:\"}\", ttype:RIGHTBRACKET, invisible:true},\n\n{input:\"(\",\t tag:\"mo\", output:\"(\", atval:\"1\", ttype:STRETCHY},\n{input:\"[\",\t tag:\"mo\", output:\"[\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\lbrack\", tag:\"mo\", output:\"[\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\{\",\t tag:\"mo\", output:\"{\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\lbrace\", tag:\"mo\", output:\"{\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\langle\", tag:\"mo\", output:\"\\u2329\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\lfloor\", tag:\"mo\", output:\"\\u230A\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\lceil\", tag:\"mo\", output:\"\\u2308\", atval:\"1\", ttype:STRETCHY},\n\n// rtag:\"mi\" causes space to be inserted before a following sin, cos, etc.\n// (see function LMparseExpr() )\n{input:\")\",\t tag:\"mo\",output:\")\",\t rtag:\"mi\",atval:\"1\",ttype:STRETCHY},\n{input:\"]\",\t tag:\"mo\",output:\"]\",\t rtag:\"mi\",atval:\"1\",ttype:STRETCHY},\n{input:\"\\\\rbrack\",tag:\"mo\",output:\"]\",\t rtag:\"mi\",atval:\"1\",ttype:STRETCHY},\n{input:\"\\\\}\",\t tag:\"mo\",output:\"}\",\t rtag:\"mi\",atval:\"1\",ttype:STRETCHY},\n{input:\"\\\\rbrace\",tag:\"mo\",output:\"}\",\t rtag:\"mi\",atval:\"1\",ttype:STRETCHY},\n{input:\"\\\\rangle\",tag:\"mo\",output:\"\\u232A\", rtag:\"mi\",atval:\"1\",ttype:STRETCHY},\n{input:\"\\\\rfloor\",tag:\"mo\",output:\"\\u230B\", rtag:\"mi\",atval:\"1\",ttype:STRETCHY},\n{input:\"\\\\rceil\", tag:\"mo\",output:\"\\u2309\", rtag:\"mi\",atval:\"1\",ttype:STRETCHY},\n\n// \"|\", \"\\\\|\", \"\\\\vert\" and \"\\\\Vert\" modified later: lspace = rspace = 0em\n{input:\"|\",\t\ttag:\"mo\", output:\"\\u2223\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\|\",\t\ttag:\"mo\", output:\"\\u2225\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\vert\",\ttag:\"mo\", output:\"\\u2223\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\Vert\",\ttag:\"mo\", output:\"\\u2225\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\mid\",\t\ttag:\"mo\", output:\"\\u2223\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\parallel\",\ttag:\"mo\", output:\"\\u2225\", atval:\"1\", ttype:STRETCHY},\n{input:\"/\",\t\ttag:\"mo\", output:\"/\",\tatval:\"1.01\", ttype:STRETCHY},\n{input:\"\\\\backslash\",\ttag:\"mo\", output:\"\\u2216\", atval:\"1\", ttype:STRETCHY},\n{input:\"\\\\setminus\",\ttag:\"mo\", output:\"\\\\\",\t ttype:CONST},\n\n//miscellaneous symbols\n{input:\"\\\\!\",\t tag:\"mspace\", atname:\"width\", atval:\"-0.167em\", ttype:SPACE},\n{input:\"\\\\,\",\t tag:\"mspace\", atname:\"width\", atval:\"0.167em\", ttype:SPACE},\n{input:\"\\\\>\",\t tag:\"mspace\", atname:\"width\", atval:\"0.222em\", ttype:SPACE},\n{input:\"\\\\:\",\t tag:\"mspace\", atname:\"width\", atval:\"0.222em\", ttype:SPACE},\n{input:\"\\\\;\",\t tag:\"mspace\", atname:\"width\", atval:\"0.278em\", ttype:SPACE},\n{input:\"~\",\t tag:\"mspace\", atname:\"width\", atval:\"0.333em\", ttype:SPACE},\n{input:\"\\\\quad\", tag:\"mspace\", atname:\"width\", atval:\"1em\", ttype:SPACE},\n{input:\"\\\\qquad\", tag:\"mspace\", atname:\"width\", atval:\"2em\", ttype:SPACE},\n//{input:\"{}\",\t\t tag:\"mo\", output:\"\\u200B\", ttype:CONST}, // zero-width\n{input:\"\\\\prime\",\ttag:\"mo\", output:\"\\u2032\", ttype:CONST},\n{input:\"'\",\t\ttag:\"mo\", output:\"\\u02B9\", ttype:CONST},\n{input:\"''\",\t\ttag:\"mo\", output:\"\\u02BA\", ttype:CONST},\n{input:\"'''\",\t\ttag:\"mo\", output:\"\\u2034\", ttype:CONST},\n{input:\"''''\",\t\ttag:\"mo\", output:\"\\u2057\", ttype:CONST},\n{input:\"\\\\ldots\",\ttag:\"mo\", output:\"\\u2026\", ttype:CONST},\n{input:\"\\\\cdots\",\ttag:\"mo\", output:\"\\u22EF\", ttype:CONST},\n{input:\"\\\\vdots\",\ttag:\"mo\", output:\"\\u22EE\", ttype:CONST},\n{input:\"\\\\ddots\",\ttag:\"mo\", output:\"\\u22F1\", ttype:CONST},\n{input:\"\\\\forall\",\ttag:\"mo\", output:\"\\u2200\", ttype:CONST},\n{input:\"\\\\exists\",\ttag:\"mo\", output:\"\\u2203\", ttype:CONST},\n{input:\"\\\\Re\",\t\ttag:\"mo\", output:\"\\u211C\", ttype:CONST},\n{input:\"\\\\Im\",\t\ttag:\"mo\", output:\"\\u2111\", ttype:CONST},\n{input:\"\\\\aleph\",\ttag:\"mo\", output:\"\\u2135\", ttype:CONST},\n{input:\"\\\\hbar\",\ttag:\"mo\", output:\"\\u210F\", ttype:CONST},\n{input:\"\\\\ell\",\t\ttag:\"mo\", output:\"\\u2113\", ttype:CONST},\n{input:\"\\\\wp\",\t\ttag:\"mo\", output:\"\\u2118\", ttype:CONST},\n{input:\"\\\\emptyset\",\ttag:\"mo\", output:\"\\u2205\", ttype:CONST},\n{input:\"\\\\infty\",\ttag:\"mo\", output:\"\\u221E\", ttype:CONST},\n{input:\"\\\\surd\",\ttag:\"mo\", output:\"\\\\sqrt{}\", ttype:DEFINITION},\n{input:\"\\\\partial\",\ttag:\"mo\", output:\"\\u2202\", ttype:CONST},\n{input:\"\\\\nabla\",\ttag:\"mo\", output:\"\\u2207\", ttype:CONST},\n{input:\"\\\\triangle\",\ttag:\"mo\", output:\"\\u25B3\", ttype:CONST},\n{input:\"\\\\therefore\",\ttag:\"mo\", output:\"\\u2234\", ttype:CONST},\n{input:\"\\\\angle\",\ttag:\"mo\", output:\"\\u2220\", ttype:CONST},\n//{input:\"\\\\\\\\ \",\t tag:\"mo\", output:\"\\u00A0\", ttype:CONST},\n{input:\"\\\\diamond\",\ttag:\"mo\", output:\"\\u22C4\", ttype:CONST},\n//{input:\"\\\\Diamond\",\t tag:\"mo\", output:\"\\u25CA\", ttype:CONST},\n{input:\"\\\\Diamond\",\ttag:\"mo\", output:\"\\u25C7\", ttype:CONST},\n{input:\"\\\\neg\",\t\ttag:\"mo\", output:\"\\u00AC\", ttype:CONST},\n{input:\"\\\\lnot\",\ttag:\"mo\", output:\"\\u00AC\", ttype:CONST},\n{input:\"\\\\bot\",\t\ttag:\"mo\", output:\"\\u22A5\", ttype:CONST},\n{input:\"\\\\top\",\t\ttag:\"mo\", output:\"\\u22A4\", ttype:CONST},\n{input:\"\\\\square\",\ttag:\"mo\", output:\"\\u25AB\", ttype:CONST},\n{input:\"\\\\Box\",\t\ttag:\"mo\", output:\"\\u25A1\", ttype:CONST},\n{input:\"\\\\wr\",\t\ttag:\"mo\", output:\"\\u2240\", ttype:CONST},\n\n//standard functions\n//Note UNDEROVER *must* have tag:\"mo\" to work properly\n{input:\"\\\\arccos\", tag:\"mi\", output:\"arccos\", ttype:UNARY, func:true},\n{input:\"\\\\arcsin\", tag:\"mi\", output:\"arcsin\", ttype:UNARY, func:true},\n{input:\"\\\\arctan\", tag:\"mi\", output:\"arctan\", ttype:UNARY, func:true},\n{input:\"\\\\arg\",\t tag:\"mi\", output:\"arg\", ttype:UNARY, func:true},\n{input:\"\\\\cos\",\t tag:\"mi\", output:\"cos\", ttype:UNARY, func:true},\n{input:\"\\\\cosh\", tag:\"mi\", output:\"cosh\", ttype:UNARY, func:true},\n{input:\"\\\\cot\",\t tag:\"mi\", output:\"cot\", ttype:UNARY, func:true},\n{input:\"\\\\coth\", tag:\"mi\", output:\"coth\", ttype:UNARY, func:true},\n{input:\"\\\\csc\",\t tag:\"mi\", output:\"csc\", ttype:UNARY, func:true},\n{input:\"\\\\deg\",\t tag:\"mi\", output:\"deg\", ttype:UNARY, func:true},\n{input:\"\\\\det\",\t tag:\"mi\", output:\"det\", ttype:UNARY, func:true},\n{input:\"\\\\dim\",\t tag:\"mi\", output:\"dim\", ttype:UNARY, func:true}, //CONST?\n{input:\"\\\\exp\",\t tag:\"mi\", output:\"exp\", ttype:UNARY, func:true},\n{input:\"\\\\gcd\",\t tag:\"mi\", output:\"gcd\", ttype:UNARY, func:true}, //CONST?\n{input:\"\\\\hom\",\t tag:\"mi\", output:\"hom\", ttype:UNARY, func:true},\n{input:\"\\\\inf\",\t tag:\"mo\", output:\"inf\",\t ttype:UNDEROVER},\n{input:\"\\\\ker\",\t tag:\"mi\", output:\"ker\", ttype:UNARY, func:true},\n{input:\"\\\\lg\",\t tag:\"mi\", output:\"lg\", ttype:UNARY, func:true},\n{input:\"\\\\lim\",\t tag:\"mo\", output:\"lim\",\t ttype:UNDEROVER},\n{input:\"\\\\liminf\", tag:\"mo\", output:\"liminf\", ttype:UNDEROVER},\n{input:\"\\\\limsup\", tag:\"mo\", output:\"limsup\", ttype:UNDEROVER},\n{input:\"\\\\ln\",\t tag:\"mi\", output:\"ln\", ttype:UNARY, func:true},\n{input:\"\\\\log\",\t tag:\"mi\", output:\"log\", ttype:UNARY, func:true},\n{input:\"\\\\max\",\t tag:\"mo\", output:\"max\",\t ttype:UNDEROVER},\n{input:\"\\\\min\",\t tag:\"mo\", output:\"min\",\t ttype:UNDEROVER},\n{input:\"\\\\Pr\",\t tag:\"mi\", output:\"Pr\", ttype:UNARY, func:true},\n{input:\"\\\\sec\",\t tag:\"mi\", output:\"sec\", ttype:UNARY, func:true},\n{input:\"\\\\sin\",\t tag:\"mi\", output:\"sin\", ttype:UNARY, func:true},\n{input:\"\\\\sinh\", tag:\"mi\", output:\"sinh\", ttype:UNARY, func:true},\n{input:\"\\\\sup\",\t tag:\"mo\", output:\"sup\",\t ttype:UNDEROVER},\n{input:\"\\\\tan\",\t tag:\"mi\", output:\"tan\", ttype:UNARY, func:true},\n{input:\"\\\\tanh\", tag:\"mi\", output:\"tanh\", ttype:UNARY, func:true},\n\n//arrows\n{input:\"\\\\gets\",\t\ttag:\"mo\", output:\"\\u2190\", ttype:CONST},\n{input:\"\\\\leftarrow\",\t\ttag:\"mo\", output:\"\\u2190\", ttype:CONST},\n{input:\"\\\\to\",\t\t\ttag:\"mo\", output:\"\\u2192\", ttype:CONST},\n{input:\"\\\\rightarrow\",\t\ttag:\"mo\", output:\"\\u2192\", ttype:CONST},\n{input:\"\\\\leftrightarrow\",\ttag:\"mo\", output:\"\\u2194\", ttype:CONST},\n{input:\"\\\\uparrow\",\t\ttag:\"mo\", output:\"\\u2191\", ttype:CONST},\n{input:\"\\\\downarrow\",\t\ttag:\"mo\", output:\"\\u2193\", ttype:CONST},\n{input:\"\\\\updownarrow\",\t\ttag:\"mo\", output:\"\\u2195\", ttype:CONST},\n{input:\"\\\\Leftarrow\",\t\ttag:\"mo\", output:\"\\u21D0\", ttype:CONST},\n{input:\"\\\\Rightarrow\",\t\ttag:\"mo\", output:\"\\u21D2\", ttype:CONST},\n{input:\"\\\\Leftrightarrow\",\ttag:\"mo\", output:\"\\u21D4\", ttype:CONST},\n{input:\"\\\\iff\", tag:\"mo\", output:\"~\\\\Longleftrightarrow~\", ttype:DEFINITION},\n{input:\"\\\\Uparrow\",\t\ttag:\"mo\", output:\"\\u21D1\", ttype:CONST},\n{input:\"\\\\Downarrow\",\t\ttag:\"mo\", output:\"\\u21D3\", ttype:CONST},\n{input:\"\\\\Updownarrow\",\t\ttag:\"mo\", output:\"\\u21D5\", ttype:CONST},\n{input:\"\\\\mapsto\",\t\ttag:\"mo\", output:\"\\u21A6\", ttype:CONST},\n{input:\"\\\\longleftarrow\",\ttag:\"mo\", output:\"\\u2190\", ttype:LONG},\n{input:\"\\\\longrightarrow\",\ttag:\"mo\", output:\"\\u2192\", ttype:LONG},\n{input:\"\\\\longleftrightarrow\",\ttag:\"mo\", output:\"\\u2194\", ttype:LONG},\n{input:\"\\\\Longleftarrow\",\ttag:\"mo\", output:\"\\u21D0\", ttype:LONG},\n{input:\"\\\\Longrightarrow\",\ttag:\"mo\", output:\"\\u21D2\", ttype:LONG},\n{input:\"\\\\implies\",\t\ttag:\"mo\", output:\"\\u21D2\", ttype:LONG},\n{input:\"\\\\Longleftrightarrow\", tag:\"mo\", output:\"\\u21D4\", ttype:LONG},\n{input:\"\\\\longmapsto\",\t\ttag:\"mo\", output:\"\\u21A6\", ttype:CONST},\n\t\t\t\t\t\t\t// disaster if LONG\n\n//commands with argument\n\n{input:\"\\\\sqrt\",\ttag:\"msqrt\", output:\"sqrt\",\tttype:UNARY},\n{input:\"\\\\root\",\ttag:\"mroot\", output:\"root\",\tttype:BINARY},\n{input:\"\\\\frac\",\ttag:\"mfrac\", output:\"/\",\tttype:BINARY},\n{input:\"\\\\stackrel\", tag:\"mover\", output:\"stackrel\", ttype:BINARY},\n{input:\"\\\\atop\",\ttag:\"mfrac\", output:\"\",\t\tttype:INFIX},\n{input:\"\\\\choose\", tag:\"mfrac\", output:\"\",\t\tttype:INFIX},\n{input:\"_\",\t\ttag:\"msub\", output:\"_\",\tttype:INFIX},\n{input:\"^\",\t\ttag:\"msup\", output:\"^\",\tttype:INFIX},\n{input:\"\\\\mathrm\",\ttag:\"mtext\", output:\"text\",\tttype:TEXT},\n{input:\"\\\\mbox\",\ttag:\"mtext\", output:\"mbox\",\tttype:TEXT},\n\n//diacritical marks\n{input:\"\\\\acute\",\ttag:\"mover\", output:\"\\u00B4\", ttype:UNARY, acc:true},\n//{input:\"\\\\acute\",\t tag:\"mover\", output:\"\\u0317\", ttype:UNARY, acc:true},\n//{input:\"\\\\acute\",\t tag:\"mover\", output:\"\\u0301\", ttype:UNARY, acc:true},\n//{input:\"\\\\grave\",\t tag:\"mover\", output:\"\\u0300\", ttype:UNARY, acc:true},\n//{input:\"\\\\grave\",\t tag:\"mover\", output:\"\\u0316\", ttype:UNARY, acc:true},\n{input:\"\\\\grave\",\ttag:\"mover\", output:\"\\u0060\", ttype:UNARY, acc:true},\n{input:\"\\\\breve\",\ttag:\"mover\", output:\"\\u02D8\", ttype:UNARY, acc:true},\n{input:\"\\\\check\",\ttag:\"mover\", output:\"\\u02C7\", ttype:UNARY, acc:true},\n{input:\"\\\\dot\",\t\ttag:\"mover\", output:\".\", ttype:UNARY, acc:true},\n{input:\"\\\\ddot\",\ttag:\"mover\", output:\"..\", ttype:UNARY, acc:true},\n//{input:\"\\\\ddot\",\t tag:\"mover\", output:\"\\u00A8\", ttype:UNARY, acc:true},\n{input:\"\\\\mathring\",\ttag:\"mover\", output:\"\\u00B0\", ttype:UNARY, acc:true},\n{input:\"\\\\vec\",\t\ttag:\"mover\", output:\"\\u20D7\", ttype:UNARY, acc:true},\n{input:\"\\\\overrightarrow\",tag:\"mover\",output:\"\\u20D7\", ttype:UNARY, acc:true},\n{input:\"\\\\overleftarrow\",tag:\"mover\", output:\"\\u20D6\", ttype:UNARY, acc:true},\n{input:\"\\\\hat\",\t\ttag:\"mover\", output:\"\\u005E\", ttype:UNARY, acc:true},\n{input:\"\\\\widehat\",\ttag:\"mover\", output:\"\\u0302\", ttype:UNARY, acc:true},\n{input:\"\\\\tilde\",\ttag:\"mover\", output:\"~\", ttype:UNARY, acc:true},\n//{input:\"\\\\tilde\",\t tag:\"mover\", output:\"\\u0303\", ttype:UNARY, acc:true},\n{input:\"\\\\widetilde\",\ttag:\"mover\", output:\"\\u02DC\", ttype:UNARY, acc:true},\n{input:\"\\\\bar\",\t\ttag:\"mover\", output:\"\\u203E\", ttype:UNARY, acc:true},\n{input:\"\\\\overbrace\",\ttag:\"mover\", output:\"\\u23B4\", ttype:UNARY, acc:true},\n{input:\"\\\\overline\",\ttag:\"mover\", output:\"\\u00AF\", ttype:UNARY, acc:true},\n{input:\"\\\\underbrace\", tag:\"munder\", output:\"\\u23B5\", ttype:UNARY, acc:true},\n{input:\"\\\\underline\",\ttag:\"munder\", output:\"\\u00AF\", ttype:UNARY, acc:true},\n//{input:\"underline\",\ttag:\"munder\", output:\"\\u0332\", ttype:UNARY, acc:true},\n\n//typestyles and fonts\n{input:\"\\\\displaystyle\",tag:\"mstyle\",atname:\"displaystyle\",atval:\"true\", ttype:UNARY},\n{input:\"\\\\textstyle\",tag:\"mstyle\",atname:\"displaystyle\",atval:\"false\", ttype:UNARY},\n{input:\"\\\\scriptstyle\",tag:\"mstyle\",atname:\"scriptlevel\",atval:\"1\", ttype:UNARY},\n{input:\"\\\\scriptscriptstyle\",tag:\"mstyle\",atname:\"scriptlevel\",atval:\"2\", ttype:UNARY},\n{input:\"\\\\textrm\", tag:\"mstyle\", output:\"\\\\mathrm\", ttype: DEFINITION},\n{input:\"\\\\mathbf\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"bold\", ttype:UNARY},\n{input:\"\\\\textbf\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"bold\", ttype:UNARY},\n{input:\"\\\\mathit\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"italic\", ttype:UNARY},\n{input:\"\\\\textit\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"italic\", ttype:UNARY},\n{input:\"\\\\mathtt\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"monospace\", ttype:UNARY},\n{input:\"\\\\texttt\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"monospace\", ttype:UNARY},\n{input:\"\\\\mathsf\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"sans-serif\", ttype:UNARY},\n{input:\"\\\\mathbb\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"double-struck\", ttype:UNARY, codes:AMbbb},\n{input:\"\\\\mathcal\",tag:\"mstyle\", atname:\"mathvariant\", atval:\"script\", ttype:UNARY, codes:AMcal},\n{input:\"\\\\mathfrak\",tag:\"mstyle\",atname:\"mathvariant\", atval:\"fraktur\",ttype:UNARY, codes:AMfrk}\n];\n\nvar LMnames = []; //list of input symbols\n\nfunction LMremoveCharsAndBlanks(str,n) {\n//remove n characters and any following blanks\n var st;\n st = str.slice(n);\n for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);\n return st.slice(i);\n}\n\nfunction LMgetSymbol(str) {\n//return maximal initial substring of str that appears in names\n//return null if there is none\n var k = 0; //new pos\n var j = 0; //old pos\n var mk; //match pos\n var st;\n var tagst;\n var match = \"\";\n var more = true;\n for (var i=1; i<=str.length && more; i++) {\n st = str.slice(0,i); //initial substring of length i\n j = k;\n k = position(LMnames, st, j);\n if (k<LMnames.length && str.slice(0,LMnames[k].length)==LMnames[k]){\n match = LMnames[k];\n mk = k;\n i = match.length;\n }\n more = k<LMnames.length && str.slice(0,LMnames[k].length)>=LMnames[k];\n }\n LMpreviousSymbol=LMcurrentSymbol;\n if (match!=\"\"){\n LMcurrentSymbol=LMsymbols[mk].ttype;\n return LMsymbols[mk];\n }\n LMcurrentSymbol=CONST;\n k = 1;\n st = str.slice(0,1); //take 1 character\n if (\"0\"<=st && st<=\"9\") tagst = \"mn\";\n else tagst = ((\"A\">st || st>\"Z\") && (\"a\">st || st>\"z\")?\"mo\":\"mi\");\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n return {input:st, tag:tagst, output:st, ttype:CONST};\n}\n\n\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n\nvar LMpreviousSymbol,LMcurrentSymbol;\n\nfunction LMparseSexpr(str) { //parses str and returns [node,tailstr,(node)tag]\n var symbol, node, result, result2, i, st,// rightvert = false,\n newFrag = document.createDocumentFragment();\n str = LMremoveCharsAndBlanks(str,0);\n symbol = LMgetSymbol(str); //either a token or a bracket or empty\n if (symbol == null || symbol.ttype == RIGHTBRACKET)\n return [null,str,null];\n if (symbol.ttype == DEFINITION) {\n str = symbol.output+LMremoveCharsAndBlanks(str,symbol.input.length);\n symbol = LMgetSymbol(str);\n if (symbol == null || symbol.ttype == RIGHTBRACKET)\n return [null,str,null];\n }\n str = LMremoveCharsAndBlanks(str,symbol.input.length);\n switch (symbol.ttype) {\n case SPACE:\n node = createMmlNode(symbol.tag);\n node.setAttribute(symbol.atname,symbol.atval);\n return [node,str,symbol.tag];\n case UNDEROVER:\n if (isIE) {\n if (symbol.input.substr(0,4) == \"\\\\big\") { // botch for missing symbols\n\tstr = \"\\\\\"+symbol.input.substr(4)+str;\t // make \\bigcup = \\cup etc.\n\tsymbol = LMgetSymbol(str);\n\tsymbol.ttype = UNDEROVER;\n\tstr = LMremoveCharsAndBlanks(str,symbol.input.length);\n }\n }\n return [createMmlNode(symbol.tag,\n\t\t\tdocument.createTextNode(symbol.output)),str,symbol.tag];\n case CONST:\n var output = symbol.output;\n if (isIE) {\n if (symbol.input == \"'\")\n\toutput = \"\\u2032\";\n else if (symbol.input == \"''\")\n\toutput = \"\\u2033\";\n else if (symbol.input == \"'''\")\n\toutput = \"\\u2033\\u2032\";\n else if (symbol.input == \"''''\")\n\toutput = \"\\u2033\\u2033\";\n else if (symbol.input == \"\\\\square\")\n\toutput = \"\\u25A1\";\t// same as \\Box\n else if (symbol.input.substr(0,5) == \"\\\\frac\") {\n\t\t\t\t\t\t// botch for missing fractions\n\tvar denom = symbol.input.substr(6,1);\n\tif (denom == \"5\" || denom == \"6\") {\n\t str = symbol.input.replace(/\\\\frac/,\"\\\\frac \")+str;\n\t return [node,str,symbol.tag];\n\t}\n }\n }\n node = createMmlNode(symbol.tag,document.createTextNode(output));\n return [node,str,symbol.tag];\n case LONG: // added by DRW\n node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));\n node.setAttribute(\"minsize\",\"1.5\");\n node.setAttribute(\"maxsize\",\"1.5\");\n node = createMmlNode(\"mover\",node);\n node.appendChild(createMmlNode(\"mspace\"));\n return [node,str,symbol.tag];\n case STRETCHY: // added by DRW\n if (isIE && symbol.input == \"\\\\backslash\")\n\tsymbol.output = \"\\\\\";\t// doesn't expand, but then nor does \"\\u2216\"\n node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));\n if (symbol.input == \"|\" || symbol.input == \"\\\\vert\" ||\n\tsymbol.input == \"\\\\|\" || symbol.input == \"\\\\Vert\") {\n\t node.setAttribute(\"lspace\",\"0em\");\n\t node.setAttribute(\"rspace\",\"0em\");\n }\n node.setAttribute(\"maxsize\",symbol.atval); // don't allow to stretch here\n if (symbol.rtag != null)\n return [node,str,symbol.rtag];\n else\n return [node,str,symbol.tag];\n case BIG: // added by DRW\n var atval = symbol.atval;\n if (isIE)\n atval = symbol.ieval;\n symbol = LMgetSymbol(str);\n if (symbol == null)\n\treturn [null,str,null];\n str = LMremoveCharsAndBlanks(str,symbol.input.length);\n node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));\n if (isIE) {\t\t// to get brackets to expand\n var space = createMmlNode(\"mspace\");\n space.setAttribute(\"height\",atval+\"ex\");\n node = createMmlNode(\"mrow\",node);\n node.appendChild(space);\n } else {\t\t// ignored in IE\n node.setAttribute(\"minsize\",atval);\n node.setAttribute(\"maxsize\",atval);\n }\n return [node,str,symbol.tag];\n case LEFTBRACKET: //read (expr+)\n if (symbol.input == \"\\\\left\") { // left what?\n symbol = LMgetSymbol(str);\n if (symbol != null) {\n\tif (symbol.input == \".\")\n\t symbol.invisible = true;\n\tstr = LMremoveCharsAndBlanks(str,symbol.input.length);\n }\n }\n result = LMparseExpr(str,true,false);\n if (symbol==null ||\n\t(typeof symbol.invisible == \"boolean\" && symbol.invisible))\n node = createMmlNode(\"mrow\",result[0]);\n else {\n node = createMmlNode(\"mo\",document.createTextNode(symbol.output));\n node = createMmlNode(\"mrow\",node);\n node.appendChild(result[0]);\n }\n return [node,result[1],result[2]];\n case MATRIX:\t //read (expr+)\n if (symbol.input == \"\\\\begin{array}\") {\n var mask = \"\";\n symbol = LMgetSymbol(str);\n str = LMremoveCharsAndBlanks(str,0);\n if (symbol == null)\n\tmask = \"l\";\n else {\n\tstr = LMremoveCharsAndBlanks(str,symbol.input.length);\n\tif (symbol.input != \"{\")\n\t mask = \"l\";\n\telse do {\n\t symbol = LMgetSymbol(str);\n\t if (symbol != null) {\n\t str = LMremoveCharsAndBlanks(str,symbol.input.length);\n\t if (symbol.input != \"}\")\n\t mask = mask+symbol.input;\n\t }\n\t} while (symbol != null && symbol.input != \"\" && symbol.input != \"}\");\n }\n result = LMparseExpr(\"{\"+str,true,true);\n// if (result[0]==null) return [createMmlNode(\"mo\",\n//\t\t\t document.createTextNode(symbol.input)),str];\n node = createMmlNode(\"mtable\",result[0]);\n mask = mask.replace(/l/g,\"left \");\n mask = mask.replace(/r/g,\"right \");\n mask = mask.replace(/c/g,\"center \");\n node.setAttribute(\"columnalign\",mask);\n node.setAttribute(\"displaystyle\",\"false\");\n if (isIE)\n\treturn [node,result[1],null];\n// trying to get a *little* bit of space around the array\n// (IE already includes it)\n var lspace = createMmlNode(\"mspace\");\n lspace.setAttribute(\"width\",\"0.167em\");\n var rspace = createMmlNode(\"mspace\");\n rspace.setAttribute(\"width\",\"0.167em\");\n var node1 = createMmlNode(\"mrow\",lspace);\n node1.appendChild(node);\n node1.appendChild(rspace);\n return [node1,result[1],null];\n } else {\t// eqnarray\n result = LMparseExpr(\"{\"+str,true,true);\n node = createMmlNode(\"mtable\",result[0]);\n if (isIE)\n\tnode.setAttribute(\"columnspacing\",\"0.25em\"); // best in practice?\n else\n\tnode.setAttribute(\"columnspacing\",\"0.167em\"); // correct (but ignored?)\n node.setAttribute(\"columnalign\",\"right center left\");\n node.setAttribute(\"displaystyle\",\"true\");\n node = createMmlNode(\"mrow\",node);\n return [node,result[1],null];\n }\n case TEXT:\n if (str.charAt(0)==\"{\") i=str.indexOf(\"}\");\n else i = 0;\n if (i==-1)\n\t\t i = str.length;\n st = str.slice(1,i);\n if (st.charAt(0) == \" \") {\n\tnode = createMmlNode(\"mspace\");\n\tnode.setAttribute(\"width\",\"0.33em\");\t// was 1ex\n\tnewFrag.appendChild(node);\n }\n newFrag.appendChild(\n createMmlNode(symbol.tag,document.createTextNode(st)));\n if (st.charAt(st.length-1) == \" \") {\n\tnode = createMmlNode(\"mspace\");\n\tnode.setAttribute(\"width\",\"0.33em\");\t// was 1ex\n\tnewFrag.appendChild(node);\n }\n str = LMremoveCharsAndBlanks(str,i+1);\n return [createMmlNode(\"mrow\",newFrag),str,null];\n case UNARY:\n result = LMparseSexpr(str);\n if (result[0]==null) return [createMmlNode(symbol.tag,\n document.createTextNode(symbol.output)),str];\n if (typeof symbol.func == \"boolean\" && symbol.func) { // functions hack\n\tst = str.charAt(0);\n//\tif (st==\"^\" || st==\"_\" || st==\"/\" || st==\"|\" || st==\",\") {\n\tif (st==\"^\" || st==\"_\" || st==\",\") {\n\t return [createMmlNode(symbol.tag,\n\t\t document.createTextNode(symbol.output)),str,symbol.tag];\n } else {\n\t node = createMmlNode(\"mrow\",\n\t createMmlNode(symbol.tag,document.createTextNode(symbol.output)));\n\t if (isIE) {\n\t var space = createMmlNode(\"mspace\");\n\t space.setAttribute(\"width\",\"0.167em\");\n\t node.appendChild(space);\n\t }\n\t node.appendChild(result[0]);\n\t return [node,result[1],symbol.tag];\n }\n }\n if (symbol.input == \"\\\\sqrt\") {\t\t// sqrt\n\tif (isIE) {\t// set minsize, for \\surd\n\t var space = createMmlNode(\"mspace\");\n\t space.setAttribute(\"height\",\"1.2ex\");\n\t space.setAttribute(\"width\",\"0em\");\t// probably no effect\n\t node = createMmlNode(symbol.tag,result[0])\n//\t node.setAttribute(\"minsize\",\"1\");\t// ignored\n//\t node = createMmlNode(\"mrow\",node); // hopefully unnecessary\n\t node.appendChild(space);\n\t return [node,result[1],symbol.tag];\n\t} else\n\t return [createMmlNode(symbol.tag,result[0]),result[1],symbol.tag];\n } else if (typeof symbol.acc == \"boolean\" && symbol.acc) { // accent\n node = createMmlNode(symbol.tag,result[0]);\n\tvar output = symbol.output;\n\tif (isIE) {\n\t\tif (symbol.input == \"\\\\hat\")\n\t\t\toutput = \"\\u0302\";\n\t\telse if (symbol.input == \"\\\\widehat\")\n\t\t\toutput = \"\\u005E\";\n\t\telse if (symbol.input == \"\\\\bar\")\n\t\t\toutput = \"\\u00AF\";\n\t\telse if (symbol.input == \"\\\\grave\")\n\t\t\toutput = \"\\u0300\";\n\t\telse if (symbol.input == \"\\\\tilde\")\n\t\t\toutput = \"\\u0303\";\n\t}\n\tvar node1 = createMmlNode(\"mo\",document.createTextNode(output));\n\tif (symbol.input == \"\\\\vec\" || symbol.input == \"\\\\check\")\n\t\t\t\t\t\t// don't allow to stretch\n\t node1.setAttribute(\"maxsize\",\"1.2\");\n\t\t // why doesn't \"1\" work? \\vec nearly disappears in firefox\n\tif (isIE && symbol.input == \"\\\\bar\")\n\t node1.setAttribute(\"maxsize\",\"0.5\");\n\tif (symbol.input == \"\\\\underbrace\" || symbol.input == \"\\\\underline\")\n\t node1.setAttribute(\"accentunder\",\"true\");\n\telse\n\t node1.setAttribute(\"accent\",\"true\");\n\tnode.appendChild(node1);\n\tif (symbol.input == \"\\\\overbrace\" || symbol.input == \"\\\\underbrace\")\n\t node.ttype = UNDEROVER;\n\treturn [node,result[1],symbol.tag];\n } else {\t\t\t // font change or displaystyle command\n if (!isIE && typeof symbol.codes != \"undefined\") {\n for (i=0; i<result[0].childNodes.length; i++)\n if (result[0].childNodes[i].nodeName==\"mi\" || result[0].nodeName==\"mi\") {\n st = (result[0].nodeName==\"mi\"?result[0].firstChild.nodeValue:\n result[0].childNodes[i].firstChild.nodeValue);\n var newst = [];\n for (var j=0; j<st.length; j++)\n if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst +\n String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);\n else newst = newst + st.charAt(j);\n if (result[0].nodeName==\"mi\")\n result[0]=createMmlNode(\"mo\").\n appendChild(document.createTextNode(newst));\n else result[0].replaceChild(createMmlNode(\"mo\").\n appendChild(document.createTextNode(newst)),result[0].childNodes[i]);\n }\n }\n node = createMmlNode(symbol.tag,result[0]);\n node.setAttribute(symbol.atname,symbol.atval);\n\tif (symbol.input == \"\\\\scriptstyle\" ||\n\t symbol.input == \"\\\\scriptscriptstyle\")\n\t\tnode.setAttribute(\"displaystyle\",\"false\");\n\treturn [node,result[1],symbol.tag];\n }\n case BINARY:\n result = LMparseSexpr(str);\n if (result[0]==null) return [createMmlNode(\"mo\",\n\t\t\t document.createTextNode(symbol.input)),str,null];\n result2 = LMparseSexpr(result[1]);\n if (result2[0]==null) return [createMmlNode(\"mo\",\n\t\t\t document.createTextNode(symbol.input)),str,null];\n if (symbol.input==\"\\\\root\" || symbol.input==\"\\\\stackrel\")\n newFrag.appendChild(result2[0]);\n newFrag.appendChild(result[0]);\n if (symbol.input==\"\\\\frac\") newFrag.appendChild(result2[0]);\n return [createMmlNode(symbol.tag,newFrag),result2[1],symbol.tag];\n case INFIX:\n str = LMremoveCharsAndBlanks(str,symbol.input.length);\n return [createMmlNode(\"mo\",document.createTextNode(symbol.output)),\n\tstr,symbol.tag];\n default:\n return [createMmlNode(symbol.tag, //its a constant\n\tdocument.createTextNode(symbol.output)),str,symbol.tag];\n }\n}\n\nfunction LMparseIexpr(str) {\n var symbol, sym1, sym2, node, result, tag, underover;\n str = LMremoveCharsAndBlanks(str,0);\n sym1 = LMgetSymbol(str);\n result = LMparseSexpr(str);\n node = result[0];\n str = result[1];\n tag = result[2];\n symbol = LMgetSymbol(str);\n if (symbol.ttype == INFIX) {\n str = LMremoveCharsAndBlanks(str,symbol.input.length);\n result = LMparseSexpr(str);\n if (result[0] == null) // show box in place of missing argument\n result[0] = createMmlNode(\"mo\",document.createTextNode(\"\\u25A1\"));\n str = result[1];\n tag = result[2];\n if (symbol.input == \"_\" || symbol.input == \"^\") {\n sym2 = LMgetSymbol(str);\n tag = null;\t// no space between x^2 and a following sin, cos, etc.\n// This is for \\underbrace and \\overbrace\n underover = ((sym1.ttype == UNDEROVER) || (node.ttype == UNDEROVER));\n// underover = (sym1.ttype == UNDEROVER);\n if (symbol.input == \"_\" && sym2.input == \"^\") {\n str = LMremoveCharsAndBlanks(str,sym2.input.length);\n var res2 = LMparseSexpr(str);\n\tstr = res2[1];\n\ttag = res2[2]; // leave space between x_1^2 and a following sin etc.\n node = createMmlNode((underover?\"munderover\":\"msubsup\"),node);\n node.appendChild(result[0]);\n node.appendChild(res2[0]);\n } else if (symbol.input == \"_\") {\n\tnode = createMmlNode((underover?\"munder\":\"msub\"),node);\n node.appendChild(result[0]);\n } else {\n\tnode = createMmlNode((underover?\"mover\":\"msup\"),node);\n node.appendChild(result[0]);\n }\n node = createMmlNode(\"mrow\",node); // so sum does not stretch\n } else {\n node = createMmlNode(symbol.tag,node);\n if (symbol.input == \"\\\\atop\" || symbol.input == \"\\\\choose\")\n\tnode.setAttribute(\"linethickness\",\"0ex\");\n node.appendChild(result[0]);\n if (symbol.input == \"\\\\choose\")\n\tnode = createMmlNode(\"mfenced\",node);\n }\n }\n return [node,str,tag];\n}\n\nfunction LMparseExpr(str,rightbracket,matrix) {\n var symbol, node, result, i, tag,\n newFrag = document.createDocumentFragment();\n do {\n str = LMremoveCharsAndBlanks(str,0);\n result = LMparseIexpr(str);\n node = result[0];\n str = result[1];\n tag = result[2];\n symbol = LMgetSymbol(str);\n if (node!=undefined) {\n if ((tag == \"mn\" || tag == \"mi\") && symbol!=null &&\n\ttypeof symbol.func == \"boolean\" && symbol.func) {\n\t\t\t// Add space before \\sin in 2\\sin x or x\\sin x\n\t var space = createMmlNode(\"mspace\");\n\t space.setAttribute(\"width\",\"0.167em\");\n\t node = createMmlNode(\"mrow\",node);\n\t node.appendChild(space);\n }\n newFrag.appendChild(node);\n }\n } while ((symbol.ttype != RIGHTBRACKET)\n && symbol!=null && symbol.output!=\"\");\n tag = null;\n if (symbol.ttype == RIGHTBRACKET) {\n if (symbol.input == \"\\\\right\") { // right what?\n str = LMremoveCharsAndBlanks(str,symbol.input.length);\n symbol = LMgetSymbol(str);\n if (symbol != null && symbol.input == \".\")\n\tsymbol.invisible = true;\n if (symbol != null)\n\ttag = symbol.rtag;\n }\n if (symbol!=null)\n str = LMremoveCharsAndBlanks(str,symbol.input.length); // ready to return\n var len = newFrag.childNodes.length;\n if (matrix &&\n len>0 && newFrag.childNodes[len-1].nodeName == \"mrow\" && len>1 &&\n newFrag.childNodes[len-2].nodeName == \"mo\" &&\n newFrag.childNodes[len-2].firstChild.nodeValue == \"&\") { //matrix\n\tvar pos = []; // positions of ampersands\n var m = newFrag.childNodes.length;\n for (i=0; matrix && i<m; i=i+2) {\n pos[i] = [];\n node = newFrag.childNodes[i];\n\t for (var j=0; j<node.childNodes.length; j++)\n\t if (node.childNodes[j].firstChild.nodeValue==\"&\")\n\t pos[i][pos[i].length]=j;\n }\n\tvar row, frag, n, k, table = document.createDocumentFragment();\n\tfor (i=0; i<m; i=i+2) {\n\t row = document.createDocumentFragment();\n\t frag = document.createDocumentFragment();\n\t node = newFrag.firstChild; // <mrow> -&-&...&-&- </mrow>\n\t n = node.childNodes.length;\n\t k = 0;\n\t for (j=0; j<n; j++) {\n\t if (typeof pos[i][k] != \"undefined\" && j==pos[i][k]){\n\t node.removeChild(node.firstChild); //remove &\n\t row.appendChild(createMmlNode(\"mtd\",frag));\n\t k++;\n\t } else frag.appendChild(node.firstChild);\n\t }\n\t row.appendChild(createMmlNode(\"mtd\",frag));\n\t if (newFrag.childNodes.length>2) {\n\t newFrag.removeChild(newFrag.firstChild); //remove <mrow> </mrow>\n\t newFrag.removeChild(newFrag.firstChild); //remove <mo>&</mo>\n\t }\n\t table.appendChild(createMmlNode(\"mtr\",row));\n\t}\n\treturn [table,str];\n }\n if (typeof symbol.invisible != \"boolean\" || !symbol.invisible) {\n node = createMmlNode(\"mo\",document.createTextNode(symbol.output));\n newFrag.appendChild(node);\n }\n }\n return [newFrag,str,tag];\n}\n\nvar tcnt = 0, dcnt = 0; //theorem and definition counters\n\nfunction simpleLaTeXformatting(st) {\n st = st.replace(/\\$\\$((.|\\n)*?)\\$\\$/g,\"<p align=\\\"center\\\">$\\\\displaystyle{$1}$</p>\");\n st = st.replace(/\\\\begin{(theorem|lemma|proposition|corollary)}((.|\\n)*?)\\\\end{\\1}/g,function(r,s,t){tcnt++; return \"<b>\"+s.charAt(0).toUpperCase()+s.slice(1)+\" \"+tcnt+\".</b> <i>\"+t.replace(/^\\s*<\\/?\\w+\\/?>|\\s*<\\/?\\w+\\/?>$/g,\"\")+\"</i>\"});\n st = st.replace(/\\\\begin{(definition|example|remark|problem|exercise|conjecture|solution)}((.|\\n)*?)\\\\end{\\1}/g,function(r,s,t){dcnt++; return \"<b>\"+s.charAt(0).toUpperCase()+s.slice(1)+\" \"+dcnt+\".</b> \"+t.replace(/^\\s*<\\/?\\w+\\/?>|\\s*<\\/?\\w+\\/?>$/g,\"\")});\n st = st.replace(/\\\\begin{proof}((.|\\n)*?)\\\\end{proof}/g,function(s,t){return \"<i>Proof:</i> \"+t.replace(/^\\s*<\\/?\\w+\\/?>|\\s*<\\/?\\w+\\/?>$/g,\"\")+\" □\"});\n st = st.replace(/\\\\emph{(.*?)}/g,\"<em>$1</em>\");\n st = st.replace(/\\\\textbf{(.*?)}/g,\"<b>$1</b>\");\n st = st.replace(/\\\\cite{(.*?)}/g,\"[$1]\");\n st = st.replace(/\\\\chapter{(.*?)}/g,\"<h2>$1</h2>\");\n st = st.replace(/\\\\section{(.*?)}(\\s*<\\/?(br|p)\\s?\\/?>)?/g,\"<h3>$1</h3>\");\n st = st.replace(/\\\\subsection{((.|\\n)*?)}/g,\"<h4>$1</h4>\");\n st = st.replace(/\\\\begin{itemize}(\\s*<\\/?(br|p)\\s?\\/?>)?/g,\"<ul>\");\n st = st.replace(/\\\\item\\s((.|\\n)*?)(?=(\\\\item|\\\\end))/g,\"<li>$1</li>\");\n st = st.replace(/\\\\end{itemize}(\\s*<\\/?(br|p)\\s?\\/?>)?/g,\"</ul>\");\n st = st.replace(/\\\\begin{enumerate}(\\s*<\\/?(br|p)\\s?\\/?>)?/g,\"<ol>\");\n st = st.replace(/\\\\end{enumerate}(\\s*<\\/?(br|p)\\s?\\/?>)?/g,\"</ol>\");\n st = st.replace(/\\\\item\\[(.*?)]{(.*?)}/g,\"<dt>$1</dt><dd>$2</dd>\");\n st = st.replace(/\\\\begin{description}/g,\"<dl>\");\n st = st.replace(/\\\\end{description}/g,\"</dl>\");\n st = st.replace(/\\\\newline\\b/g,\"<br/>\");\n st = st.replace(/\\\\newpage\\b/g,\"<br style=\\\"page-break-after:always;\\\">\");\n st = st.replace(/\\\\par\\b/g,\"<p> </p>\");\n st = st.replace(/\\\\bigskip/g,\"<p style=\\\"margin-bottom:0.5in\\\"> </p>\");\n st = st.replace(/\\\\medskip/g,\"<p style=\\\"margin-bottom:0.3in\\\"> </p>\");\n st = st.replace(/\\\\smallskip/g,\"<p style=\\\"margin-bottom:0.15in\\\"> </p>\");\n st = st.replace(/\\\\begin{center}((.|\\n)*?)\\\\end{center}/g,\"<center>$1</center>\");\n return st\n}\n\nfunction ASCIIandgraphformatting(st) {\n st = st.replace(/<sup>(.*?)<\\/sup>(\\s|(\\S))/gi,\"^{$1} $3\");\n//st = st.replace(/<\\/?font.*?>/gi,\"\"); // do this only in amath...endamath\n st = st.replace(/(Proof:)/g,\"<i>$1</i>\");\n st = st.replace(/QED/g,\" □\");\n st = st.replace(/(\\\\?end{?a?math}?)/ig,\"<span></span>$1\");\n st = st.replace(/(\\bamath\\b|\\\\begin{a?math})/ig,\"<span></span>$1\");\n st = st.replace(/([>\\n])(Theorem|Lemma|Proposition|Corollary|Definition|Example|Remark|Problem|Exercise|Conjecture|Solution)(:|\\W\\W?(\\w|\\s|-|\\.)*?\\W?:)/g,\"$1<b>$2$3</b>\");\n st = st.replace(/<embed\\s+class\\s?=\\s?\"?ASCIIsvg\"?/gi,\"<embed class=\\\"ASCIIsvg\\\" src=\\\"\"+dsvglocation+\"d.svg\\\" wmode=\\\"transparent\\\"\");\n st = st.replace(/(?:\\\\begin{a?graph}|\\bagraph|\\(:graph\\s)((.|\\n)*?)(?:\\\\end{a?graph}|enda?graph|:\\))/g,function(s,t){return \"<table><tr><td><div class=\\\"ASCIIsvg\\\"><embed class=\\\"ASCIIsvg\\\" src=\\\"\"+dsvglocation+\"d.svg\\\" wmode=\\\"transparent\\\" script=\\'\"+t.replace(/<\\/?(br|p|pre)\\s?\\/?>/gi,\"\\n\")+\"\\'/></div></td></tr></table>\"});\n st = st.replace(/insertASCIIMathCalculator/g,\"<div class=\\\"ASCIIMathCalculator\\\"></div>\");\n//alert(dsvglocation)\n return st\n}\n\nfunction LMprocessNode(n) {\n var frag,st;\n try {\n st = n.innerHTML;\n } catch(err) {}\n var am = /amath\\b|graph/i.test(st);\n if ((st==null || st.indexOf(\"\\$ \")!=-1 || st.indexOf(\"\\$<\")!=-1 || \n st.indexOf(\"\\\\begin\")!=-1 || am || st.slice(-1)==\"$\" ||\n st.indexOf(\"\\$\\n\")!=-1)&& !/edit-content|HTMLArea|wikiedit|wpTextbox1/.test(st)){\n if (!avoidinnerHTML && translateLaTeXformatting) \n st = simpleLaTeXformatting(st);\n if (st!=null && am && !avoidinnerHTML) {\n st = ASCIIandgraphformatting(st);\n }\n st = st.replace(/%7E/g,\"~\"); // else PmWiki has url issues\n//alert(st)\n if (!avoidinnerHTML) n.innerHTML = st;\n processNodeR(n,false,true);\n }\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n}\n\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n\n// you can change these\nvar checkIfSVGavailable = true;\nvar notifyIfNoSVG = true;\nvar alertIfNoSVG = false;\nvar noSVG = false;\n\n// global defaults used if not specified by graph (you can change these)\nvar defaultwidth = 300; defaultheight = 200; // in pixels\nvar defaultxmin = -5.5; defaultxmax = 5.5; // in usercoords\nvar defaultborder = 0; border = defaultborder; // in pixel\nvar defaultstrokewidth = \"1\"; // default line width in pixel\nvar defaultstroke = \"blue\"; // default line color\nvar defaultstrokeopacity = 1; // transparent = 0, solid =1\nvar defaultstrokedasharray = null; // \"10,10\" gives 10px long dashes\nvar defaultfill = \"none\"; // default fill color\nvar defaultfillopacity = 1; // transparent = 0, solid =1\nvar defaultfontstyle = \"normal\"; // default text shape normal|italic|inherit\nvar defaultfontfamily = \"times\"; // default font times|ariel|helvetica|...\nvar defaultfontsize = \"16\"; // default size (scaled automatically)\nvar defaultfontweight = \"normal\";// normal|bold|bolder|lighter|100|...|900\nvar defaultfontstroke = \"none\"; // default font outline color\nvar defaultfontfill = \"none\"; // default font color\nvar defaultmarker = \"none\"; // \"dot\" | \"arrow\" | \"+\" | \"-\" | \"|\"\nvar defaultendpoints = \"\"; // \"c-d\" where c is <|o|* and d is >|o|*\n\n// global values used for all pictures (you can change these)\nvar showcoordinates = true;\nvar markerstrokewidth = \"1\";\nvar markerstroke = \"black\";\nvar markerfill = \"yellow\";\nvar markersize = 4;\nvar arrowfill = stroke;\nvar dotradius = 4;\nvar ticklength = 4;\nvar axesstroke = \"black\";\nvar gridstroke = \"grey\";\nvar backgroundstyle = \"fill-opacity:0; fill:white\";\nvar singlelettersitalic = true;\n\n// internal variables (probably no need to change these)\nvar picturepos = null; // position of picture relative to top of HTML page\nvar xunitlength; // in pixels, used to convert to user coordinates\nvar yunitlength; // in pixels\nvar origin = [0,0]; // in pixels (default is bottom left corner)\nvar above = \"above\"; // shorthands (to avoid typing quotes)\nvar below = \"below\";\nvar left = \"left\";\nvar right = \"right\";\nvar aboveleft = \"aboveleft\";\nvar aboveright = \"aboveright\";\nvar belowleft = \"belowleft\";\nvar belowright = \"belowright\";\nvar xmin, xmax, ymin, ymax, xscl, yscl, \n xgrid, ygrid, xtick, ytick, initialized;\nvar strokewidth, strokedasharray, stroke, fill, strokeopacity, fillopacity;\nvar fontstyle, fontfamily, fontsize, fontweight, fontstroke, fontfill;\nvar marker, endpoints, dynamic = {};\nvar picture, svgpicture, doc, width, height;\nvar isIE = document.createElementNS==null;\n\n//this is not used! var cpi = \"\\u03C0\", ctheta = \"\\u03B8\"; // character for pi, theta\nvar log = function(x) { return ln(x)/ln(10) };\nvar pi = Math.PI, e = Math.E, ln = Math.log, sqrt = Math.sqrt;\nvar floor = Math.floor, ceil = Math.ceil, abs = Math.abs;\nvar sin = Math.sin, cos = Math.cos, tan = Math.tan;\nvar arcsin = Math.asin, arccos = Math.acos, arctan = Math.atan;\nvar sec = function(x) { return 1/Math.cos(x) };\nvar csc = function(x) { return 1/Math.sin(x) };\nvar cot = function(x) { return 1/Math.tan(x) };\nvar arcsec = function(x) { return arccos(1/x) };\nvar arccsc = function(x) { return arcsin(1/x) };\nvar arccot = function(x) { return arctan(1/x) };\nvar sinh = function(x) { return (Math.exp(x)-Math.exp(-x))/2 };\nvar cosh = function(x) { return (Math.exp(x)+Math.exp(-x))/2 };\nvar tanh = \n function(x) { return (Math.exp(x)-Math.exp(-x))/(Math.exp(x)+Math.exp(-x)) };\nvar sech = function(x) { return 1/cosh(x) };\nvar csch = function(x) { return 1/sinh(x) };\nvar coth = function(x) { return 1/tanh(x) };\nvar arcsinh = function(x) { return ln(x+Math.sqrt(x*x+1)) };\nvar arccosh = function(x) { return ln(x+Math.sqrt(x*x-1)) };\nvar arctanh = function(x) { return ln((1+x)/(1-x))/2 };\nvar sech = function(x) { return 1/cosh(x) };\nvar csch = function(x) { return 1/sinh(x) };\nvar coth = function(x) { return 1/tanh(x) };\nvar arcsech = function(x) { return arccosh(1/x) };\nvar arccsch = function(x) { return arcsinh(1/x) };\nvar arccoth = function(x) { return arctanh(1/x) };\nvar sign = function(x) { return (x==0?0:(x<0?-1:1)) };\n\nfunction factorial(x,n) { // Factorial function\n if (n==null) n=1;\n if (Math.abs(x-Math.round(x*1000000)/1000000)<1e-15)\n x = Math.round(x*1000000)/1000000;\n if (x-Math.floor(x)!=0) return NaN;\n for (var i=x-n; i>0; i-=n) x*=i;\n return (x<0?NaN:(x==0?1:x));\n}\n\nfunction C(x,k) { // Binomial coefficient function\n var res=1;\n for (var i=0; i<k; i++) res*=(x-i)/(k-i);\n return res;\n}\n\nfunction chop(x,n) { // Truncate decimal number to n places after decimal point\n if (n==null) n=0;\n return Math.floor(x*Math.pow(10,n))/Math.pow(10,n);\n}\n\nfunction ran(a,b,n) { // Generate random number in [a,b] with n digits after .\n if (n==null) n=0;\n return chop((b+Math.pow(10,-n)-a)*Math.random()+a,n);\n}\n\nfunction myCreateElementSVG(t) {\n if (isIE) return doc.createElement(t);\n else return doc.createElementNS(\"http://www.w3.org/2000/svg\",t);\n}\n\nfunction getElementsByClass(container, tagName, clsName){\n var list = new Array(0);\n var collection = container.getElementsByTagName(tagName);\n for(var i = 0; i < collection.length; i++)\n if(collection[i].className.slice(0,clsName.length)==clsName)\n list[list.length] = collection[i];\n return list;\n}\n\nfunction showobj(obj) {\n var st=\"\", i;\n for (i in obj) \n st += (obj.getAttribute(i)==null?\"\":\" \"+i+\":\"+obj.getAttribute(i));\n return st;\n}\n\nfunction findPos(obj) { // top-left corner of obj on HTML page in pixel\n var curleft = curtop = 0;\n if (obj.offsetParent) {\n curleft = obj.offsetLeft\n curtop = obj.offsetTop\n while (obj = obj.offsetParent) {\n curleft += obj.offsetLeft\n curtop += obj.offsetTop\n//alert(showobj(obj)+[curleft,curtop])\n }\n }\n return [curleft,curtop];\n}\n\nfunction checkSVG(){\n if (navigator.appName.slice(0,8)==\"Netscape\") \n if (window['SVGElement']) noSVG = null;\n else noSVG = true;\n else if (navigator.appName.slice(0,9)==\"Microsoft\")\n try {\n var oSVG=eval(\"new ActiveXObject('Adobe.SVGCtl.3');\");\n noSVG = null;\n } catch (e) {\n noSVG = true;\n }\n else if (navigator.appName.slice(0,5)==\"Opera\") // works only for 9.50b1\n noSVG = null;\n else noSVG = true;\n//noSVG = true; //uncomment to check\n if (noSVG && notifyIfNoSVG) {\n var msg = \"To view the ASCIIsvg images use Internet Explorer + Adobe SVGviewer or Mozilla Firefox 2.0 or later.\"\n if (alertIfNoSVG)\n alert(msg);\n else return msg;\n }\n}\n\nfunction setText(st,id) { // add text to an existing node with given id\n var node = document.getElementById(id);\n if (node!=null)\n if (node.childNodes.length!=0) node.childNodes[0].nodeValue = st;\n else node.appendChild(document.createTextNode(st));\n}\n\nfunction getX(evt) { // return mouse x-coord in user coordinate system\n var svgroot = evt.target.parentNode;\n pos = findPos(svgroot.parentNode);\n return (evt.clientX+(isIE?0:window.pageXOffset)-pos[0]-svgroot.getAttribute(\"ox\"))/parseFloat(svgroot.getAttribute(\"xunitlength\"));\n}\n\nfunction getY(evt) { // return mouse y-coord in user coordinate system\n var svgroot = evt.target.parentNode;\n pos = findPos(svgroot.parentNode);\n//alert(showobj(svgroot)+svgroot.getAttribute(\"mytop\"))\n return (svgroot.getAttribute(\"height\")-svgroot.getAttribute(\"oy\")-(evt.clientY+(isIE?0:window.pageYOffset)-pos[1]))/parseFloat(svgroot.getAttribute(\"yunitlength\"));\n}\n\nfunction translateandeval(src) { //modify user input to JavaScript syntax\n var errstr;\n // replace plot(f(x),...) with plot(\"f(x)\",...) \n src = src.replace(/plot\\(\\x20*([^\\\"f\\[][^\\n\\r;]+?)\\,/g,\"plot\\(\\\"$1\\\",\");\n src = src.replace(/plot\\(\\x20*([^\\\"f\\[][^\\n\\r;]+)\\)/g,\"plot(\\\"$1\\\")\");\n\n // replace (expr,expr) by [expr,expr] where expr has no (,) in it\n src = src.replace(/([=[(,]\\x20*)\\(([-a-z0-9./+*]+?),([-a-z0-9./+*]+?)\\)/g,\"$1[$2,$3]\");\n//alert(src)\n // insert * between digit and letter e.g. 2x --> 2*x\n src = src.replace(/([0-9])([a-df-zA-Z]|e^)/g,\"$1*$2\");\n src = src.replace(/\\)([\\(0-9a-zA-Z])/g,\"\\)*$1\");\n\n try {\n with (Math) eval(src); // here the svgpicture object is created\n } catch(err) {\n if (err!=\"wait\") {\n//alert(dsvglocation)\n if (typeof err==\"object\") \n errstr = err.name+\" \"+err.message+\" \"+err.number+\" \"+err.description;\n else errstr = err;\n alert(errstr+\"\\n\"+src)\n }\n }\n}\n\nvar lastSlot = 0;\n\nfunction drawPictures() { // main routine; called after webpage has loaded\n var src, id, dsvg, nd, node, ht, index, cols, arr, i, node2;\n var ASbody = document.getElementsByTagName(\"body\")[0];\n pictures = getElementsByClass(ASbody,\"embed\",\"ASCIIsvg\");\n var len = pictures.length;\n if(len==0) return;\n for (index = lastSlot; index < len+lastSlot; index++) {\n width = null; height = null; \n xmin = null; xmax = null; ymin = null; ymax = null;\n xscl = null; xgrid = null; yscl = null; ygrid = null;\n initialized = false;\n picture = pictures[index-lastSlot]; // current picture object\n src = picture.getAttribute(\"script\"); // get the ASCIIsvg code\n if (src==null) src = \"\";\n // insert \"axes()\" if not present ******** experimental\n if (!/axes\\b|initPicture/.test(src)) {\n var i = 0;\n while (/((yscl|ymax|ymin|xscl|xmax|xmin|\\bwidth|\\bheight)\\s*=\\s*-?\\d*(\\d\\.|\\.\\d|\\d)\\d*\\s*;?)/.test(src.slice(i))) i++;\n src = (i==0?\"axes(); \"+src: src.slice(0,i)+src.slice(i).replace(/((scl|max|min|idth|eight)\\s*=\\s*-?\\d*(\\d\\.|\\.\\d|\\d)\\d*\\s*;?)/,\"$1\\naxes();\"));\n }\n ht = picture.getAttribute(\"height\");\n if (isIE) {\n picture.setAttribute(\"wmode\",\"transparent\");\n//alert(\"*\"+picture.getAttribute(\"src\")+dsvglocation);\n//adding d.svg dynamically greates problems in IE...\n// if (picture.getAttribute(\"src\")==\"\") picture.setAttribute(\"src\",dsvglocation+\"d.svg\");\n }\n if (document.getElementById(\"picture\"+(index+1)+\"mml\")==null) {\n picture.parentNode.style.position = \"relative\";\n node = createElementXHTML(\"div\");\n node.style.position = \"absolute\";\n node.style.top = \"0px\";\n node.style.left = \"0px\";\n node.setAttribute(\"id\",\"picture\"+(index+1)+\"mml\");\n picture.parentNode.insertBefore(node,picture.nextSibling);\n }\n if (ht==null) ht =\"\";\n// if (ht!=\"\") defaultborder = 25;\n if (ht==\"\" || src==\"\") \n if (document.getElementById(\"picture\"+(index+1)+\"input\")==null) {\n node = createElementXHTML(\"textarea\");\n arr = src.split(\"\\n\");\n cols = 0;\n for (i=0;i<arr.length;i++) cols = Math.max(cols,arr[i].length);\n node.setAttribute(\"rows\",Math.min(10,arr.length)+1);\n node.setAttribute(\"cols\",Math.max(Math.min(60,cols),20)+5);\n// node.setAttribute(\"style\",\"display:block\");\n if (isIE) src = src.replace(/([^\\r])\\n/g,\"$1\\r\");\n node.appendChild(document.createTextNode(src));\n if (src.indexOf(\"showcode()\")==-1) node.style.display = \"none\";\n node.setAttribute(\"id\",\"picture\"+(index+1)+\"input\");\n picture.parentNode.insertBefore(node,picture.nextSibling);\n picture.parentNode.insertBefore(createElementXHTML(\"br\"),node);\n node2 = createElementXHTML(\"button\");\n node2.setAttribute(\"id\",\"picture\"+(index+1)+\"button\");\n if (isIE) node2.onclick = function() {updatePicture(this)};\n else node2.setAttribute(\"onclick\",\"updatePicture(this)\");\n node2.appendChild(document.createTextNode(\"Update\"));\n if (src.indexOf(\"showcode()\")==-1) node2.style.display = \"none\";\n picture.parentNode.insertBefore(node2,node);\n// picture.parentNode.insertBefore(document.createTextNode(\"ASCII\"),node);\n picture.parentNode.insertBefore(createElementXHTML(\"br\"),node);\n } else src = document.getElementById(\"picture\"+(index+1)+\"input\").value;\n id = picture.getAttribute(\"id\");\n dsvg = picture.getAttribute(\"src\");\n if (id == null || id == \"\") {\n id = \"picture\"+(index+1);\n picture.setAttribute(\"id\",id);\n }\n translateandeval(src);\n }\n lastSlot+=len;\n}\n\nfunction setdefaults() { //called before each graph is evaluated\n strokewidth = defaultstrokewidth;\n stroke = defaultstroke;\n strokeopacity = defaultstrokeopacity;\n strokedasharray = defaultstrokedasharray;\n fill = defaultfill;\n fillopacity = defaultfillopacity;\n fontstyle = defaultfontstyle;\n fontfamily = defaultfontfamily;\n fontsize = defaultfontsize;\n fontweight = defaultfontweight;\n fontstroke = defaultfontstroke;\n fontfill = defaultfontfill;\n marker = defaultmarker;\n endpoints = defaultendpoints;\n}\n\nfunction switchTo(id) { // used by dynamic code to select appropriate graph\n if (id==undefined) return;\n var name = id;\n if (typeof name!=\"string\") name = id.target.parentNode.getAttribute(\"name\");\n picture = document.getElementById(name);\n width = picture.getAttribute(\"width\")-0;\n height = picture.getAttribute(\"height\")-0;\n setdefaults();\n if ((picture.nodeName == \"EMBED\" || picture.nodeName == \"embed\") && isIE) {\n svgpicture = picture.getSVGDocument().getElementById(\"root\");\n doc = picture.getSVGDocument();\n } else {\n svgpicture = picture;\n doc = document;\n }\n xunitlength = parseFloat(svgpicture.getAttribute(\"xunitlength\"));\n yunitlength = parseFloat(svgpicture.getAttribute(\"yunitlength\"));\n xmin = parseFloat(svgpicture.getAttribute(\"xmin\"));\n xmax = parseFloat(svgpicture.getAttribute(\"xmax\"));\n ymin = parseFloat(svgpicture.getAttribute(\"ymin\"));\n ymax = parseFloat(svgpicture.getAttribute(\"ymax\"));\n origin = [svgpicture.getAttribute(\"ox\")-0,svgpicture.getAttribute(\"oy\")-0];\n}\n\nfunction updatePicture(obj) {\n var node, src, id, top, left;\n if (typeof obj==\"object\") id = obj.id.slice(0,-6);\n else id = (typeof obj==\"string\"?obj:\"picture\"+(obj+1));\n src = document.getElementById(id+\"input\").value;\n xmin = null; xmax = null; ymin = null; ymax = null;\n xscl = null; xgrid = null; yscl = null; ygrid = null;\n initialized = false;\n picture = document.getElementById(id);\n translateandeval(src)\n}\n\nfunction changepicturesize(evt,factor) {\n var obj = evt.target;\n var name = obj.parentNode.getAttribute(\"name\");\n var pic = document.getElementById(name);\n var src = document.getElementById(name+\"input\").value;\n if (!/height/.test(src)) src = \"height=0; \"+src;\n if (!/width/.test(src)) src = \"width=0; \"+src;\n src = src.replace(/width\\s*=\\s*\\d+/,\"width=\"+(factor*(pic.getAttribute(\"width\")-0)));\n src = src.replace(/height\\s*=\\s*\\d+/,\"height=\"+(factor*(pic.getAttribute(\"height\")-0)));\n document.getElementById(name+\"input\").value = src;\n//alert(getKey(evt.keycode))\n updatePicture(name);\n}\n\nfunction zoom(evt,factor) {\n switchTo(evt);\n var obj = evt.target;\n var name = obj.parentNode.getAttribute(\"name\");\n var pic = document.getElementById(name);\n var src = document.getElementById(name+\"input\").value;\n var xlen = (xmax-xmin)/2;\n var ylen = (ymax-ymin)/2;\n var xcen = getX(evt), ycen = getY(evt);\n if (!/ymax/.test(src)) src = \"ymax=0; \"+src;\n if (!/ymin/.test(src)) src = \"ymin=0; \"+src;\n if (!/xmax/.test(src)) src = \"xmax=0; \"+src;\n if (!/xmin/.test(src)) src = \"xmin=0; \"+src;\n src = src.replace(/xmin\\s*=\\s*[-\\d.e]+/,\"xmin=\"+(xcen-factor*xlen));\n src = src.replace(/xmax\\s*=\\s*[-\\d.e]+/,\"xmax=\"+(xcen+factor*xlen));\n src = src.replace(/ymin\\s*=\\s*[-\\d.e]+/,\"ymin=\"+(ycen-factor*ylen));\n src = src.replace(/ymax\\s*=\\s*[-\\d.e]+/,\"ymax=\"+(ycen+factor*ylen));\n document.getElementById(name+\"input\").value = src;\n updatePicture(name);\n}\n\nvar sinceFirstClick = 0; // ondblclick simulation from \nvar dblClkTimer; // http://www.enja.org/david/?cat=13 Thanks!\nfunction timer() {\n if(sinceFirstClick<60) {\n sinceFirstClick++;\n setTimeout(\"timer()\",10);\n } else {\n clearTimeout(dblClkTimer);\n dblClkTimer = \"\";\n }\n}\nfunction mClick(evt) {\n if(sinceFirstClick!=0) {\n if(sinceFirstClick <= 40) {\n if (evt.shiftKey) {\n if (evt.altKey) changepicturesize(evt,2);\n else zoom(evt,.5);\n } else if (evt.altKey) zoom(evt,2);//changepicturesize(evt,.5);\n else showHideCode(evt); // do this on dblclick\n clearTimeout(dblClkTimer);\n dblClkTimer = \"\";\n } else {\n clearTimeout(dblClkTimer);\n sinceFirstClick = 0;\n dblClkTimer = setTimeout(\"timer()\",10);\n }\t \n } else {\n sinceFirstClick = 0;\n dblClkTimer = setTimeout(\"timer()\",10);\n }\n}\n\nfunction showHideCode(evt) { // called by onclick event\n// if (evt.getDetail()==2) {//getDetail unfortunately not in Firefox\n var obj=evt.target;\n var name = obj.parentNode.getAttribute(\"name\");\n var node = document.getElementById(name+\"input\");\n node.style.display = (node.style.display == \"none\"?\"\":\"none\");\n var node = document.getElementById(name+\"button\");\n node.style.display = (node.style.display == \"none\"?\"\":\"none\");\n// }\n}\n\nfunction showcode() {} // do nothing\n\nfunction setBorder(x) { border = x } //deprecate\n\nfunction initPicture(x_min,x_max,y_min,y_max) { // set up the graph\n// usually called by axes() or noaxes(), but can be used directly\n if (!initialized) {\n setdefaults();\n initialized = true;\n if (x_min!=null) xmin = x_min;\n if (x_max!=null) xmax = x_max;\n if (y_min!=null) ymin = y_min;\n if (y_max!=null) ymax = y_max;\n if (xmin==null) xmin = defaultxmin;\n if (xmax==null) xmax = defaultxmax;\n if (typeof xmin != \"number\" || typeof xmax != \"number\" || xmin >= xmax) \n alert(\"Picture requires at least two numbers: xmin < xmax\");\n else if (y_max != null && (typeof y_min != \"number\" || \n typeof y_max != \"number\" || y_min >= y_max))\n alert(\"initPicture(xmin,xmax,ymin,ymax) requires numbers ymin < ymax\");\n else {\n if (width==null) {\n width = picture.getAttribute(\"width\");\n if (width==null || width==\"\") width=defaultwidth;\n }\n picture.setAttribute(\"width\",width);\n if (height==null) { \n height = picture.getAttribute(\"height\");\n if (height==null || height==\"\") height=defaultheight;\n }\n picture.setAttribute(\"height\",height);\n xunitlength = (width-2*border)/(xmax-xmin);\n yunitlength = xunitlength;\n//alert(xmin+\" \"+xmax+\" \"+ymin+\" \"+ymax)\n if (ymin==null) {\n origin = [-xmin*xunitlength+border,height/2];\n ymin = -(height-2*border)/(2*yunitlength);\n ymax = -ymin;\n } else {\n if (ymax!=null) yunitlength = (height-2*border)/(ymax-ymin);\n else ymax = (height-2*border)/yunitlength + ymin;\n origin = [-xmin*xunitlength+border,-ymin*yunitlength+border];\n }\n if (isIE) {\n if (picture.FULLSCREEN==undefined) {\n setTimeout('drawPictures()',50);\n throw \"wait\";\n }\n svgpicture = picture.getSVGDocument().getElementById(\"root\");\n if (svgpicture==null) {\n setTimeout('drawPictures()',50);\n throw \"wait\";\n }\n svgpicture = picture.getSVGDocument().getElementById(\"root\");\n while (svgpicture.childNodes.length>0) \n svgpicture.removeChild(svgpicture.lastChild); \n svgpicture.setAttribute(\"width\",width);\n svgpicture.setAttribute(\"height\",height);\n svgpicture.setAttribute(\"name\",picture.getAttribute(\"id\"));\n doc = picture.getSVGDocument();\n } else {\n var qnode = document.createElementNS(\"http://www.w3.org/2000/svg\",\"svg\");\n qnode.setAttribute(\"id\",picture.getAttribute(\"id\"));\n qnode.setAttribute(\"name\",picture.getAttribute(\"id\"));\n// qnode.setAttribute(\"style\",\"display:inline\");\n qnode.setAttribute(\"width\",picture.getAttribute(\"width\"));\n qnode.setAttribute(\"height\",picture.getAttribute(\"height\"));\n picturepos = findPos(picture);\n// qnode.setAttribute(\"xmlns:xlink\",\"http://www.w3.org/1999/xlink\");\n if (picture.parentNode!=null) {\n picture.parentNode.replaceChild(qnode,picture);\n } else {\n svgpicture.parentNode.replaceChild(qnode,svgpicture);\n }\n svgpicture = qnode;\n doc = document;\n }\n var nd = document.getElementById(picture.getAttribute(\"id\")+\"mml\");\n if (nd!=null) // clear out MathML layer\n while (nd.childNodes.length>0) nd.removeChild(nd.lastChild); \n svgpicture.setAttribute(\"xunitlength\",xunitlength);\n svgpicture.setAttribute(\"yunitlength\",yunitlength);\n svgpicture.setAttribute(\"xmin\",xmin);\n svgpicture.setAttribute(\"xmax\",xmax);\n svgpicture.setAttribute(\"ymin\",ymin);\n svgpicture.setAttribute(\"ymax\",ymax);\n svgpicture.setAttribute(\"ox\",origin[0]);\n svgpicture.setAttribute(\"oy\",origin[1]);\n var node = myCreateElementSVG(\"rect\");\n node.setAttribute(\"x\",\"0\");\n node.setAttribute(\"y\",\"0\");\n node.setAttribute(\"width\",width);\n node.setAttribute(\"height\",height);\n node.setAttribute(\"style\",backgroundstyle);\n svgpicture.appendChild(node);\n svgpicture.setAttribute(\"onmousemove\",\"displayCoord(evt)\");\n svgpicture.setAttribute(\"onmouseout\",\"removeCoord(evt)\");\n svgpicture.setAttribute(\"onclick\",\"mClick(evt)\");\n node = myCreateElementSVG(\"text\"); // used for displayCoord\n node.appendChild(doc.createTextNode(\" \"));\n node.setAttribute(\"id\",\"coords\");\n svgpicture.appendChild(node);\n node = myCreateElementSVG(\"text\"); // used for text display\n node.appendChild(doc.createTextNode(\" \"));\n node.setAttribute(\"id\",\"coords\");\n svgpicture.appendChild(node);\n border = defaultborder;\n }\n }\n}\n\n//////////////////////////user graphics commands start/////////////////////////\n\nfunction line(p,q,id,endpts) { // segment connecting points p,q (coordinates in units)\n var node;\n if (id!=null) node = doc.getElementById(id);\n if (node==null) {\n node = myCreateElementSVG(\"path\");\n node.setAttribute(\"id\", id);\n svgpicture.appendChild(node);\n }\n node.setAttribute(\"d\",\"M\"+(p[0]*xunitlength+origin[0])+\",\"+\n (height-p[1]*yunitlength-origin[1])+\" \"+\n (q[0]*xunitlength+origin[0])+\",\"+(height-q[1]*yunitlength-origin[1]));\n node.setAttribute(\"stroke-width\", strokewidth);\n if (strokedasharray!=null) \n node.setAttribute(\"stroke-dasharray\", strokedasharray);\n node.setAttribute(\"stroke\", stroke);\n node.setAttribute(\"fill\", fill);\n node.setAttribute(\"stroke-opacity\", strokeopacity);\n node.setAttribute(\"fill-opacity\", fillopacity);\n if (marker==\"dot\" || marker==\"arrowdot\") {\n ASdot(p,markersize,markerstroke,markerfill);\n if (marker==\"arrowdot\") arrowhead(p,q);\n ASdot(q,markersize,markerstroke,markerfill);\n } else if (marker==\"arrow\") arrowhead(p,q);\n if (endpts==null && endpoints!=\"\") endpts = endpoints;\n if (endpts!=null) {\n if (endpts.indexOf(\"<-\") != -1) arrowhead(q,p);\n if (endpts.indexOf(\"o-\") != -1) dot(p, \"open\");\n if (endpts.indexOf(\"*-\") != -1) dot(p, \"closed\");\n if (endpts.indexOf(\"->\") != -1) arrowhead(p,q);\n if (endpts.indexOf(\"-o\") != -1) dot(q, \"open\");\n if (endpts.indexOf(\"-*\") != -1) dot(q, \"closed\");\n }\n}\n\nfunction path(plist,id,c,endpts) {\n if (c==null) c=\"\";\n var node, st, i;\n if (id!=null) node = doc.getElementById(id);\n if (node==null) {\n node = myCreateElementSVG(\"path\");\n node.setAttribute(\"id\", id);\n svgpicture.appendChild(node);\n }\n if (typeof plist == \"string\") st = plist;\n else {\n st = \"M\";\n st += (plist[0][0]*xunitlength+origin[0])+\",\"+\n (height-plist[0][1]*yunitlength-origin[1])+\" \"+c;\n for (i=1; i<plist.length; i++)\n st += (plist[i][0]*xunitlength+origin[0])+\",\"+\n (height-plist[i][1]*yunitlength-origin[1])+\" \";\n }\n node.setAttribute(\"d\", st);\n node.setAttribute(\"stroke-width\", strokewidth);\n if (strokedasharray!=null) \n node.setAttribute(\"stroke-dasharray\", strokedasharray);\n node.setAttribute(\"stroke\", stroke);\n node.setAttribute(\"fill\", fill);\n node.setAttribute(\"stroke-opacity\", strokeopacity);\n node.setAttribute(\"fill-opacity\", fillopacity);\n if (marker==\"dot\" || marker==\"arrowdot\")\n for (i=0; i<plist.length; i++)\n if (c!=\"C\" && c!=\"T\" || i!=1 && i!=2)\n ASdot(plist[i],markersize,markerstroke,markerfill);\n if (endpts==null && endpoints!=\"\") endpts = endpoints;\n if (endpts!=null) {\n if (endpts.indexOf(\"<-\") != -1) arrowhead(plist[1],plist[0]);\n if (endpts.indexOf(\"o-\") != -1) dot(plist[0], \"open\");\n if (endpts.indexOf(\"*-\") != -1) dot(plist[0], \"closed\");\n if (endpts.indexOf(\"->\") != -1) arrowhead(plist[plist.length-2],plist[plist.length-1]);\n if (endpts.indexOf(\"-o\") != -1) dot(plist[plist.length-1], \"open\");\n if (endpts.indexOf(\"-*\") != -1) dot(plist[plist.length-1], \"closed\");\n }\n}\n\nfunction curve(plist,id,endpts) {\n path(plist,id,\"T\",endpts);\n}\n\nfunction vector(p,q,id) {\n line(p,q,id,\"\",\"->\");\n}\n\nfunction circle(center,radius,id) { // coordinates in units\n var node;\n if (id!=null) node = doc.getElementById(id);\n if (node==null) {\n node = myCreateElementSVG(\"circle\");\n node.setAttribute(\"id\", id);\n svgpicture.appendChild(node);\n }\n node.setAttribute(\"cx\",center[0]*xunitlength+origin[0]);\n node.setAttribute(\"cy\",height-center[1]*yunitlength-origin[1]);\n node.setAttribute(\"r\",radius*xunitlength);\n node.setAttribute(\"stroke-width\", strokewidth);\n node.setAttribute(\"stroke\", stroke);\n node.setAttribute(\"fill\", fill);\n node.setAttribute(\"stroke-opacity\", strokeopacity);\n node.setAttribute(\"fill-opacity\", fillopacity);\n}\n\nfunction loop(p,d,id) { \n// d is a direction vector e.g. [1,0] means loop starts in that direction\n if (d==null) d=[1,0];\n path([p,[p[0]+d[0],p[1]+d[1]],[p[0]-d[1],p[1]+d[0]],p],id,\"C\");\n if (marker==\"arrow\" || marker==\"arrowdot\") \n arrowhead([p[0]+Math.cos(1.4)*d[0]-Math.sin(1.4)*d[1],\n p[1]+Math.sin(1.4)*d[0]+Math.cos(1.4)*d[1]],p);\n}\n\nfunction arc(start,end,radius,id,largearc) { // coordinates in units\n var node, v;\n//alert([fill, stroke, origin, xunitlength, yunitlength, height])\n if (id!=null) node = doc.getElementById(id);\n if (largearc==null) largearc=0;\n if (radius==null) {\n v=[end[0]-start[0],end[1]-start[1]];\n radius = Math.sqrt(v[0]*v[0]+v[1]*v[1]);\n }\n if (node==null) {\n node = myCreateElementSVG(\"path\");\n node.setAttribute(\"id\", id);\n svgpicture.appendChild(node);\n }\n node.setAttribute(\"d\",\"M\"+(start[0]*xunitlength+origin[0])+\",\"+\n (height-start[1]*yunitlength-origin[1])+\" A\"+radius*xunitlength+\",\"+\n radius*yunitlength+\" 0 \"+largearc+\",0 \"+(end[0]*xunitlength+origin[0])+\",\"+\n (height-end[1]*yunitlength-origin[1]));\n node.setAttribute(\"stroke-width\", strokewidth);\n node.setAttribute(\"stroke\", stroke);\n node.setAttribute(\"fill\", fill);\n node.setAttribute(\"stroke-opacity\", strokeopacity);\n node.setAttribute(\"fill-opacity\", fillopacity);\n if (marker==\"arrow\" || marker==\"arrowdot\") {\n u = [(end[1]-start[1])/4,(start[0]-end[0])/4];\n v = [(end[0]-start[0])/2,(end[1]-start[1])/2];\n//alert([u,v])\n v = [start[0]+v[0]+u[0],start[1]+v[1]+u[1]];\n } else v=[start[0],start[1]];\n if (marker==\"dot\" || marker==\"arrowdot\") {\n ASdot(start,markersize,markerstroke,markerfill);\n if (marker==\"arrowdot\") arrowhead(v,end);\n ASdot(end,markersize,markerstroke,markerfill);\n } else if (marker==\"arrow\") arrowhead(v,end);\n}\n\nfunction sector(center,start,end,id) { // center,start,end should be isoceles\n var rx = start[0]-center[0], ry = start[1]-center[1];\n arc(start,end,Math.sqrt(rx*rx+ry*ry),id+\"arc\");\n path([end,center,start],id+\"path\");\n}\n\nfunction ellipse(center,rx,ry,id) { // coordinates in units\n var node;\n if (id!=null) node = doc.getElementById(id);\n if (node==null) {\n node = myCreateElementSVG(\"ellipse\");\n node.setAttribute(\"id\", id);\n svgpicture.appendChild(node);\n }\n node.setAttribute(\"cx\",center[0]*xunitlength+origin[0]);\n node.setAttribute(\"cy\",height-center[1]*yunitlength-origin[1]);\n node.setAttribute(\"rx\",rx*xunitlength);\n node.setAttribute(\"ry\",ry*yunitlength);\n node.setAttribute(\"stroke-width\", strokewidth);\n node.setAttribute(\"stroke\", stroke);\n node.setAttribute(\"fill\", fill);\n node.setAttribute(\"stroke-opacity\", strokeopacity);\n node.setAttribute(\"fill-opacity\", fillopacity);\n}\n\nfunction triangle(p,q,r,id) {\n path([p,q,r,p],id)\n}\n\nfunction rect(p,q,id,rx,ry) { // opposite corners in units, rounded by radii\n var node;\n if (id!=null) node = doc.getElementById(id);\n if (node==null) {\n node = myCreateElementSVG(\"rect\");\n node.setAttribute(\"id\", id);\n svgpicture.appendChild(node);\n }\n node.setAttribute(\"x\",p[0]*xunitlength+origin[0]);\n node.setAttribute(\"y\",height-q[1]*yunitlength-origin[1]);\n node.setAttribute(\"width\",(q[0]-p[0])*xunitlength);\n node.setAttribute(\"height\",(q[1]-p[1])*yunitlength);\n if (rx!=null) node.setAttribute(\"rx\",rx*xunitlength);\n if (ry!=null) node.setAttribute(\"ry\",ry*yunitlength);\n node.setAttribute(\"stroke-width\", strokewidth);\n node.setAttribute(\"stroke\", stroke);\n node.setAttribute(\"fill\", fill);\n node.setAttribute(\"stroke-opacity\", strokeopacity);\n node.setAttribute(\"fill-opacity\", fillopacity);\n}\n\nfunction text(p,st,pos,id,fontsty) {\n var dnode, node, dx = 0, dy = fontsize/3, str = st.toString();\n if (/(`|\\$)/.test(str)) { // layer for ASCIIMathML and LaTeXMathML\n dnode = document.getElementById(svgpicture.getAttribute(\"name\")+\"mml\");\n if (dnode!=null) {\n if (id!=null) node = document.getElementById(id);\n if (node==null) {\n//alert(dnode.childNodes.length)\n node = createElementXHTML(\"div\");\n node.setAttribute(\"id\", id);\n node.style.position = \"absolute\";\n dnode.appendChild(node);\n }\n while (node.childNodes.length>0) node.removeChild(node.lastChild); \n node.appendChild(document.createTextNode(str));\n if (/`/.test(str)) AMprocessNode(node); else LMprocessNode(node);\n dx = -node.offsetWidth/2;\n dy = -node.offsetHeight/2;\n if (pos!=null) {\n if (/above/.test(pos)) dy = -node.offsetHeight;\n if (/below/.test(pos)) dy = 0;\n if (/right/.test(pos)) dx = 0;\n if ( /left/.test(pos)) dx = -node.offsetWidth;\n }\n node.style.left = \"\"+(p[0]*xunitlength+origin[0]+dx)+\"px\";\n node.style.top = \"\"+(height-p[1]*yunitlength-origin[1]+dy)+\"px\";\n }\n return p;\n }\n var textanchor = \"middle\"; // regular text goes into SVG\n if (pos!=null) {\n if (/above/.test(pos)) dy = -fontsize/2;\n if (/below/.test(pos)) dy = fontsize-0;\n if (/right/.test(pos)) {textanchor = \"start\"; dx = fontsize/4;}\n if ( /left/.test(pos)) {textanchor = \"end\"; dx = -fontsize/4;}\n }\n if (id!=null) node = doc.getElementById(id);\n if (node==null) {\n node = myCreateElementSVG(\"text\");\n node.setAttribute(\"id\", id);\n svgpicture.appendChild(node);\n node.appendChild(doc.createTextNode(str));\n }\n while (node.childNodes.length>1) node.removeChild(node.lastChild); \n node.lastChild.nodeValue = \"\\xA0\"+str+\"\\xA0\";\n node.setAttribute(\"x\",p[0]*xunitlength+origin[0]+dx);\n node.setAttribute(\"y\",height-p[1]*yunitlength-origin[1]+dy);\n node.setAttribute(\"font-style\",(fontsty!=null?fontsty:\n (str.search(/^[a-zA-Z]$/)!=-1?\"italic\":fontstyle)));\n node.setAttribute(\"font-family\",fontfamily);\n node.setAttribute(\"font-size\",fontsize);\n node.setAttribute(\"font-weight\",fontweight);\n node.setAttribute(\"text-anchor\",textanchor);\n if (fontstroke!=\"none\") node.setAttribute(\"stroke\",fontstroke);\n if (fontfill!=\"none\") node.setAttribute(\"fill\",fontfill);\n return p;\n}\n\nfunction mtext(p,st,pos,fontsty,fontsz) { // method for updating text on an svg\n// \"this\" is the text object or the svgpicture object\n var textanchor = \"middle\";\n var dx = 0; var dy = fontsize/3;\n if (pos!=null) {\n if (pos.slice(0,5)==\"above\") dy = -fontsize/2;\n if (pos.slice(0,5)==\"below\") dy = fontsize-0;\n if (pos.slice(0,5)==\"right\" || pos.slice(5,10)==\"right\") {\n textanchor = \"start\";\n dx = fontsize/2;\n }\n if (pos.slice(0,4)==\"left\" || pos.slice(5,9)==\"left\") {\n textanchor = \"end\";\n dx = -fontsize/2;\n }\n }\n var node = this;\n if (this.nodeName==\"svg\") {\n node = myCreateElementSVG(\"text\");\n this.appendChild(node);\n node.appendChild(doc.createTextNode(st));\n }\n node.lastChild.nodeValue = st;\n node.setAttribute(\"x\",p[0]+dx);\n node.setAttribute(\"y\",p[1]+dy);\n node.setAttribute(\"font-style\",(fontsty!=null?fontsty:fontstyle));\n node.setAttribute(\"font-family\",fontfamily);\n node.setAttribute(\"font-size\",(fontsz!=null?fontsz:fontsize));\n node.setAttribute(\"font-weight\",fontweight);\n node.setAttribute(\"text-anchor\",textanchor);\n if (fontstroke!=\"none\") node.setAttribute(\"stroke\",fontstroke);\n if (fontfill!=\"none\") node.setAttribute(\"fill\",fontfill);\n}\n\nfunction image(imgurl,p,w,h,id) { // not working yet\n var node;\n if (id!=null) node = doc.getElementById(id);\n if (node==null) {\n node = myCreateElementSVG(\"image\");\n node.setAttribute(\"id\", id);\n svgpicture.appendChild(node);\n }\n node.setAttribute(\"x\",p[0]*xunitlength+origin[0]);\n node.setAttribute(\"y\",height-p[1]*yunitlength-origin[1]);\n node.setAttribute(\"width\",w);\n node.setAttribute(\"height\",h);\n node.setAttribute(\"xlink:href\", imgurl);\n}\n\nfunction ASdot(center,radius,s,f) { // coordinates in units, radius in pixel\n if (s==null) s = stroke; if (f==null) f = fill;\n var node = myCreateElementSVG(\"circle\");\n node.setAttribute(\"cx\",center[0]*xunitlength+origin[0]);\n node.setAttribute(\"cy\",height-center[1]*yunitlength-origin[1]);\n node.setAttribute(\"r\",radius);\n node.setAttribute(\"stroke-width\", strokewidth);\n node.setAttribute(\"stroke\", s);\n node.setAttribute(\"fill\", f);\n svgpicture.appendChild(node);\n}\n\nfunction dot(center, typ, label, pos, id) {\n var node;\n var cx = center[0]*xunitlength+origin[0];\n var cy = height-center[1]*yunitlength-origin[1];\n if (id!=null) node = doc.getElementById(id);\n if (typ==\"+\" || typ==\"-\" || typ==\"|\") {\n if (node==null) {\n node = myCreateElementSVG(\"path\");\n node.setAttribute(\"id\", id);\n svgpicture.appendChild(node);\n }\n if (typ==\"+\") {\n node.setAttribute(\"d\",\n \" M \"+(cx-ticklength)+\" \"+cy+\" L \"+(cx+ticklength)+\" \"+cy+\n \" M \"+cx+\" \"+(cy-ticklength)+\" L \"+cx+\" \"+(cy+ticklength));\n node.setAttribute(\"stroke-width\", .5);\n node.setAttribute(\"stroke\", axesstroke);\n } else {\n if (typ==\"-\") node.setAttribute(\"d\",\n \" M \"+(cx-ticklength)+\" \"+cy+\" L \"+(cx+ticklength)+\" \"+cy);\n else node.setAttribute(\"d\",\n \" M \"+cx+\" \"+(cy-ticklength)+\" L \"+cx+\" \"+(cy+ticklength));\n node.setAttribute(\"stroke-width\", strokewidth);\n node.setAttribute(\"stroke\", stroke);\n }\n } else {\n if (node==null) {\n node = myCreateElementSVG(\"circle\");\n node.setAttribute(\"id\", id);\n svgpicture.appendChild(node);\n }\n node.setAttribute(\"cx\",cx);\n node.setAttribute(\"cy\",cy);\n node.setAttribute(\"r\",dotradius);\n node.setAttribute(\"stroke-width\", strokewidth);\n node.setAttribute(\"stroke\", stroke);\n node.setAttribute(\"fill\", (typ==\"open\"?\"white\":\n (typ==\"closed\"?stroke:markerfill)));\n }\n if (label!=null) \n text(center,label,(pos==null?\"below\":pos),(id==null?id:id+\"label\"))\n}\n\npoint = dot; //alternative name\n\nfunction arrowhead(p,q) { // draw arrowhead at q (in units) add size param\n var up;\n var v = [p[0]*xunitlength+origin[0],height-p[1]*yunitlength-origin[1]];\n var w = [q[0]*xunitlength+origin[0],height-q[1]*yunitlength-origin[1]];\n var u = [w[0]-v[0],w[1]-v[1]];\n var d = Math.sqrt(u[0]*u[0]+u[1]*u[1]);\n if (d > 0.00000001) {\n u = [u[0]/d, u[1]/d];\n up = [-u[1],u[0]];\n var node = myCreateElementSVG(\"path\");\n node.setAttribute(\"d\",\"M \"+(w[0]-15*u[0]-4*up[0])+\" \"+\n (w[1]-15*u[1]-4*up[1])+\" L \"+(w[0]-3*u[0])+\" \"+(w[1]-3*u[1])+\" L \"+\n (w[0]-15*u[0]+4*up[0])+\" \"+(w[1]-15*u[1]+4*up[1])+\" z\");\n node.setAttribute(\"stroke-width\", markerstrokewidth);\n node.setAttribute(\"stroke\", stroke); /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n node.setAttribute(\"fill\", stroke); /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n node.setAttribute(\"stroke-opacity\", strokeopacity);\n node.setAttribute(\"fill-opacity\", fillopacity);\n svgpicture.appendChild(node); \n }\n}\n\nfunction chopZ(st) {\n var k = st.indexOf(\".\");\n if (k==-1) return st;\n for (var i=st.length-1; i>k && st.charAt(i)==\"0\"; i--);\n if (i==k) i--;\n return st.slice(0,i+1);\n}\n\nfunction grid(dx,dy) { // for backward compatibility\n axes(dx,dy,null,dx,dy)\n}\n\nfunction noaxes() {\n if (!initialized) initPicture();\n}\n\nfunction axes(dx,dy,labels,gdx,gdy) {\n//xscl=x is equivalent to xtick=x; xgrid=x; labels=true;\n var x, y, ldx, ldy, lx, ly, lxp, lyp, pnode, st;\n if (!initialized) initPicture();\n if (typeof dx==\"string\") { labels = dx; dx = null; }\n if (typeof dy==\"string\") { gdx = dy; dy = null; }\n if (xscl!=null) {dx = xscl; gdx = xscl; labels = dx}\n if (yscl!=null) {dy = yscl; gdy = yscl}\n if (xtick!=null) {dx = xtick}\n if (ytick!=null) {dy = ytick}\n dx = (dx==null?xunitlength:dx*xunitlength);\n dy = (dy==null?dx:dy*yunitlength);\n fontsize = Math.min(dx/2,dy/2,16); //alert(fontsize)\n ticklength = fontsize/4;\n if (xgrid!=null) gdx = xgrid;\n if (ygrid!=null) gdy = ygrid;\n if (gdx!=null) {\n gdx = (typeof gdx==\"string\"?dx:gdx*xunitlength);\n gdy = (gdy==null?dy:gdy*yunitlength);\n pnode = myCreateElementSVG(\"path\");\n st=\"\";\n for (x = origin[0]; x<width; x = x+gdx)\n st += \" M\"+x+\",0\"+\" \"+x+\",\"+height;\n for (x = origin[0]-gdx; x>0; x = x-gdx)\n st += \" M\"+x+\",0\"+\" \"+x+\",\"+height;\n for (y = height-origin[1]; y<height; y = y+gdy)\n st += \" M0,\"+y+\" \"+width+\",\"+y;\n for (y = height-origin[1]-gdy; y>0; y = y-gdy)\n st += \" M0,\"+y+\" \"+width+\",\"+y;\n pnode.setAttribute(\"d\",st);\n pnode.setAttribute(\"stroke-width\", .5);\n pnode.setAttribute(\"stroke\", gridstroke);\n pnode.setAttribute(\"fill\", fill);\n svgpicture.appendChild(pnode);\n }\n pnode = myCreateElementSVG(\"path\");\n st=\"M0,\"+(height-origin[1])+\" \"+width+\",\"+\n (height-origin[1])+\" M\"+origin[0]+\",0 \"+origin[0]+\",\"+height;\n for (x = origin[0]+dx; x<width; x = x+dx)\n st += \" M\"+x+\",\"+(height-origin[1]+ticklength)+\" \"+x+\",\"+\n (height-origin[1]-ticklength);\n for (x = origin[0]-dx; x>0; x = x-dx)\n st += \" M\"+x+\",\"+(height-origin[1]+ticklength)+\" \"+x+\",\"+\n (height-origin[1]-ticklength);\n for (y = height-origin[1]+dy; y<height; y = y+dy)\n st += \" M\"+(origin[0]+ticklength)+\",\"+y+\" \"+(origin[0]-ticklength)+\",\"+y;\n for (y = height-origin[1]-dy; y>0; y = y-dy)\n st += \" M\"+(origin[0]+ticklength)+\",\"+y+\" \"+(origin[0]-ticklength)+\",\"+y;\n if (labels!=null) with (Math) {\n ldx = dx/xunitlength;\n ldy = dy/yunitlength;\n lx = (xmin>0 || xmax<0?xmin:0);\n ly = (ymin>0 || ymax<0?ymin:0);\n lxp = (ly==0?\"below\":\"above\");\n lyp = (lx==0?\"left\":\"right\");\n var ddx = floor(1.1-log(ldx)/log(10))+1;\n var ddy = floor(1.1-log(ldy)/log(10))+1;\n for (x = ldx; x<=xmax; x = x+ldx)\n text([x,ly],chopZ(x.toFixed(ddx)),lxp);\n for (x = -ldx; xmin<=x; x = x-ldx)\n text([x,ly],chopZ(x.toFixed(ddx)),lxp);\n for (y = ldy; y<=ymax; y = y+ldy)\n text([lx,y],chopZ(y.toFixed(ddy)),lyp);\n for (y = -ldy; ymin<=y; y = y-ldy)\n text([lx,y],chopZ(y.toFixed(ddy)),lyp);\n }\n fontsize = defaultfontsize;\n pnode.setAttribute(\"d\",st);\n pnode.setAttribute(\"stroke-width\", .5);\n pnode.setAttribute(\"stroke\", axesstroke);\n pnode.setAttribute(\"fill\", fill);\n pnode.setAttribute(\"stroke-opacity\", strokeopacity);\n pnode.setAttribute(\"fill-opacity\", fillopacity);\n svgpicture.appendChild(pnode);\n}\n\nfunction mathjs(st) {\n //translate a math formula to js function notation\n // a^b --> pow(a,b)\n // na --> n*a\n // (...)d --> (...)*d\n // n! --> factorial(n)\n // sin^-1 --> arcsin etc.\n //while ^ in string, find term on left and right\n //slice and concat new formula string\n st = st.replace(/\\s/g,\"\");\n if (st.indexOf(\"^-1\")!=-1) {\n st = st.replace(/sin\\^-1/g,\"arcsin\");\n st = st.replace(/cos\\^-1/g,\"arccos\");\n st = st.replace(/tan\\^-1/g,\"arctan\");\n st = st.replace(/sec\\^-1/g,\"arcsec\");\n st = st.replace(/csc\\^-1/g,\"arccsc\");\n st = st.replace(/cot\\^-1/g,\"arccot\");\n st = st.replace(/sinh\\^-1/g,\"arcsinh\");\n st = st.replace(/cosh\\^-1/g,\"arccosh\");\n st = st.replace(/tanh\\^-1/g,\"arctanh\");\n st = st.replace(/sech\\^-1/g,\"arcsech\");\n st = st.replace(/csch\\^-1/g,\"arccsch\");\n st = st.replace(/coth\\^-1/g,\"arccoth\");\n }\n st = st.replace(/^e$/g,\"(Math.E)\");\n st = st.replace(/^e([^a-zA-Z])/g,\"(Math.E)$1\");\n st = st.replace(/([^a-zA-Z])e/g,\"$1(Math.E)\");\n// st = st.replace(/([^a-zA-Z])e([^a-zA-Z])/g,\"$1(Math.E)$2\");\n st = st.replace(/([0-9])([\\(a-zA-Z])/g,\"$1*$2\");\n st = st.replace(/\\)([\\(0-9a-zA-Z])/g,\"\\)*$1\");\n var i,j,k, ch, nested;\n while ((i=st.indexOf(\"^\"))!=-1) {\n //find left argument\n if (i==0) return \"Error: missing argument\";\n j = i-1;\n ch = st.charAt(j);\n if (ch>=\"0\" && ch<=\"9\") {// look for (decimal) number\n j--;\n while (j>=0 && (ch=st.charAt(j))>=\"0\" && ch<=\"9\") j--;\n if (ch==\".\") {\n j--;\n while (j>=0 && (ch=st.charAt(j))>=\"0\" && ch<=\"9\") j--;\n }\n } else if (ch==\")\") {// look for matching opening bracket and function name\n nested = 1;\n j--;\n while (j>=0 && nested>0) {\n ch = st.charAt(j);\n if (ch==\"(\") nested--;\n else if (ch==\")\") nested++;\n j--;\n }\n while (j>=0 && (ch=st.charAt(j))>=\"a\" && ch<=\"z\" || ch>=\"A\" && ch<=\"Z\")\n j--;\n } else if (ch>=\"a\" && ch<=\"z\" || ch>=\"A\" && ch<=\"Z\") {// look for variable\n j--;\n while (j>=0 && (ch=st.charAt(j))>=\"a\" && ch<=\"z\" || ch>=\"A\" && ch<=\"Z\")\n j--;\n } else { \n return \"Error: incorrect syntax in \"+st+\" at position \"+j;\n }\n //find right argument\n if (i==st.length-1) return \"Error: missing argument\";\n k = i+1;\n ch = st.charAt(k);\n if (ch>=\"0\" && ch<=\"9\" || ch==\"-\") {// look for signed (decimal) number\n k++;\n while (k<st.length && (ch=st.charAt(k))>=\"0\" && ch<=\"9\") k++;\n if (ch==\".\") {\n k++;\n while (k<st.length && (ch=st.charAt(k))>=\"0\" && ch<=\"9\") k++;\n }\n } else if (ch==\"(\") {// look for matching closing bracket and function name\n nested = 1;\n k++;\n while (k<st.length && nested>0) {\n ch = st.charAt(k);\n if (ch==\"(\") nested++;\n else if (ch==\")\") nested--;\n k++;\n }\n } else if (ch>=\"a\" && ch<=\"z\" || ch>=\"A\" && ch<=\"Z\") {// look for variable\n k++;\n while (k<st.length && (ch=st.charAt(k))>=\"a\" && ch<=\"z\" ||\n ch>=\"A\" && ch<=\"Z\") k++;\n } else { \n return \"Error: incorrect syntax in \"+st+\" at position \"+k;\n }\n st = st.slice(0,j+1)+\"Math.pow(\"+st.slice(j+1,i)+\",\"+st.slice(i+1,k)+\")\"+\n st.slice(k);\n }\n while ((i=st.indexOf(\"!\"))!=-1) {\n //find left argument\n if (i==0) return \"Error: missing argument\";\n j = i-1;\n ch = st.charAt(j);\n if (ch>=\"0\" && ch<=\"9\") {// look for (decimal) number\n j--;\n while (j>=0 && (ch=st.charAt(j))>=\"0\" && ch<=\"9\") j--;\n if (ch==\".\") {\n j--;\n while (j>=0 && (ch=st.charAt(j))>=\"0\" && ch<=\"9\") j--;\n }\n } else if (ch==\")\") {// look for matching opening bracket and function name\n nested = 1;\n j--;\n while (j>=0 && nested>0) {\n ch = st.charAt(j);\n if (ch==\"(\") nested--;\n else if (ch==\")\") nested++;\n j--;\n }\n while (j>=0 && (ch=st.charAt(j))>=\"a\" && ch<=\"z\" || ch>=\"A\" && ch<=\"Z\")\n j--;\n } else if (ch>=\"a\" && ch<=\"z\" || ch>=\"A\" && ch<=\"Z\") {// look for variable\n j--;\n while (j>=0 && (ch=st.charAt(j))>=\"a\" && ch<=\"z\" || ch>=\"A\" && ch<=\"Z\")\n j--;\n } else { \n return \"Error: incorrect syntax in \"+st+\" at position \"+j;\n }\n st = st.slice(0,j+1)+\"factorial(\"+st.slice(j+1,i)+\")\"+st.slice(i+1);\n }\n return st;\n}\n\nfunction plot(fun,x_min,x_max,points,id,endpts) {\n var pth = [];\n var f = function(x) { return x }, g = fun;\n var name = null;\n if (typeof fun==\"string\") \n eval(\"g = function(x){ with(Math) return \"+mathjs(fun)+\" }\");\n else if (typeof fun==\"object\") {\n eval(\"f = function(t){ with(Math) return \"+mathjs(fun[0])+\" }\");\n eval(\"g = function(t){ with(Math) return \"+mathjs(fun[1])+\" }\");\n }\n if (typeof x_min==\"string\") { name = x_min; x_min = xmin }\n else name = id;\n var min = (x_min==null?xmin:x_min);\n var max = (x_max==null?xmax:x_max);\n var inc = max-min-0.000001*(max-min);\n inc = (points==null?inc/200:inc/points);\n var gt;\n//alert(typeof g(min))\n for (var t = min; t <= max; t += inc) {\n gt = g(t);\n if (!(isNaN(gt)||Math.abs(gt)==\"Infinity\")) pth[pth.length] = [f(t), gt];\n }\n path(pth,name,null,endpts);\n return pth;\n}\n\n// make polar plot\n\n// make Riemann sums\n\nfunction slopefield(fun,dx,dy) {\n var g = fun;\n if (typeof fun==\"string\") \n eval(\"g = function(x,y){ with(Math) return \"+mathjs(fun)+\" }\");\n var gxy,x,y,u,v,dz;\n if (dx==null) dx=1;\n if (dy==null) dy=1;\n dz = Math.sqrt(dx*dx+dy*dy)/6;\n var x_min = Math.ceil(xmin/dx);\n var y_min = Math.ceil(ymin/dy);\n for (x = x_min; x <= xmax; x += dx)\n for (y = y_min; y <= ymax; y += dy) {\n gxy = g(x,y);\n if (!isNaN(gxy)) {\n if (Math.abs(gxy)==\"Infinity\") {u = 0; v = dz;}\n else {u = dz/Math.sqrt(1+gxy*gxy); v = gxy*u;}\n line([x-u,y-v],[x+u,y+v]);\n }\n }\n}\n\n///////////////////////user graphics commands end here/////////////////////////\n\nfunction show_props(obj) {\n var result = \"\";\n for (var i=0; i< obj.childNodes.length; i++)\n result += obj.childNodes.item(i) + \"\\n\";\n return result;\n}\n\nfunction displayCoord(evt) {\n if (showcoordinates) {\n var svgroot = evt.target.parentNode;\n var nl = svgroot.childNodes;\n for (var i=0; i<nl.length && nl.item(i).nodeName!=\"text\"; i++);\n var cnode = nl.item(i);\n cnode.mtext = mtext;\n cnode.mtext([svgroot.getAttribute(\"width\")-(-7),svgroot.getAttribute(\"height\")-7],\"(\"+getX(evt).toFixed(2)+\", \"+getY(evt).toFixed(2)+\")\", \"left\", \"\", \"11\");\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */ }\n}\n\nfunction removeCoord(evt) {\n var svgroot = evt.target.parentNode;\n var nl = svgroot.childNodes;\n for (var i=0; i<nl.length && nl.item(i).nodeName!=\"text\"; i++);\n var cnode = nl.item(i);\n cnode.mtext = mtext;\n cnode.mtext([svgroot.getAttribute(\"width\")-0,svgroot.getAttribute(\"height\")-0],\"\", \"aboveleft\", \"\");\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */}\n\nfunction initASCIIMathCalculators(li) {\n var i;\n for (i=0; i<li.length; i++) {\n li[i].innerHTML = calcstr;\n AMprocessNode(li[i]);\n }\n li = document.getElementsByTagName(\"textarea\");\n var st;\n for (i=0; i<li.length; i++) {\n st = li[i].getAttribute(\"onkeyup\");\n if (st!=null) eval(String(st).replace(/function anonymous\\(\\)/,\"\"));\n }\n}\n\nfunction calculate(inputId,outputId) {\n var str = document.getElementById(inputId).value;\n var err = \"\";\n var ind = str.lastIndexOf(\"\\n\");\n if (ind==str.length-1) str = str.slice(0,ind);\n str = str.slice(str.lastIndexOf(\"\\n\")+1);\n try {\n var res = eval(mathjs(str));\n } catch(e) {\n err = \"syntax incomplete\";\n }\n if (!isNaN(res) && res!=\"Infinity\") \n str = \"`\"+str+\" =` \"+(Math.abs(res-Math.round(res*1000000)/1000000)<1e-15?Math.round(res*1000000)/1000000:res)+err; \n else if (str!=\"\") str = \"`\"+str+\"` = undefined\"; //debug:+mathjs(str);\n var outnode = document.getElementById(outputId);\n var n = outnode.childNodes.length;\n for (var i=0; i<n; i++)\n outnode.removeChild(outnode.firstChild);\n outnode.appendChild(document.createTextNode(str));\n AMprocessNode(outnode);\n}\n\nfunction append(st){\n document.getElementById('in').value+=st;\n calculate('in','out');\n document.getElementById('in').scrollTop = 1000;\n document.getElementById('in').focus();\n}\n\nfunction clearTextArea(){\n document.getElementById('in').value=\"\";\n calculate('in','out');\n document.getElementById('in').focus();\n}\n\nvar calcstr = \"<table align=\\\"center\\\">\\n<tr><th>\\nASCIIMath Scientific Calculator\\n</th></tr>\\n<tr><td>\\nClick in the box to use your keyboard or use the buttons\\n</td></tr>\\n<tr><td>\\n<textarea id=\\\"in\\\" rows=\\\"3\\\" cols=\\\"40\\\" onkeyup=\\\"calculate('in','out')\\\"></textarea></td></tr>\\n<tr><td height=\\\"50\\\">Result: <span id=\\\"out\\\"></span></td></tr>\\n</table>\\n<table align=\\\"center\\\" cellspacing=\\\"0\\\" cellpadding=\\\"0\\\">\\n<tbody align=\\\"center\\\">\\n<tr>\\n<td colspan=\\\"4\\\">\\n<button onclick=\\\"append('sin^-1(')\\\"><font size=2>`sin^-1`</font></button><button onclick=\\\"append('cos^-1(')\\\"><font size=2>`cos^-1`</font></button><button onclick=\\\"append('tan^-1(')\\\"><font size=2>`tan^-1`</font></button></td>\\n<td><button onclick=\\\"clearTextArea()\\\"> `C` </button></td>\\n\\n</tr>\\n<tr>\\n<td><button onclick=\\\"append('pi')\\\"> `pi` </button></td>\\n<td><button onclick=\\\"append('sin(')\\\"> `sin`</button></td>\\n<td><button onclick=\\\"append('cos(')\\\"> `cos`</button></td>\\n<td><button onclick=\\\"append('tan(')\\\"> `tan`</button></td>\\n<td><button onclick=\\\"append('^')\\\">`x^y`</button></td>\\n</tr>\\n<tr>\\n<td><button onclick=\\\"append('!')\\\"> `!` </button></td>\\n\\n<td><button onclick=\\\"append('(')\\\"><font size=2> `(` </font></button></td>\\n<td><button onclick=\\\"append(')')\\\"><font size=2> `)` </font></button></td>\\n<td><button onclick=\\\"append('sqrt(')\\\"><font size=2>`sqrt({::}^\\ )`</font></button></td>\\n<td><button onclick=\\\"append('/')\\\"> `-:\\ `</button></td>\\n</tr>\\n<tr>\\n<td><button onclick=\\\"append('log(')\\\">`log`</button></td>\\n<td><button onclick=\\\"append('7')\\\"> `7` </button></td>\\n<td><button onclick=\\\"append('8')\\\"> `8` </button></td>\\n\\n<td><button onclick=\\\"append('9')\\\"> `9` </button></td>\\n<td><button onclick=\\\"append('*')\\\"> `times` </button></td>\\n</tr>\\n<tr>\\n<td><button onclick=\\\"append('ln(')\\\"> `ln` </button></td>\\n<td><button onclick=\\\"append('4')\\\"> `4` </button></td>\\n<td><button onclick=\\\"append('5')\\\"> `5` </button></td>\\n<td><button onclick=\\\"append('6')\\\"> `6` </button></td>\\n\\n<td><button onclick=\\\"append('-')\\\"> `-{::}` </button></td>\\n</tr>\\n<tr>\\n<td><button onclick=\\\"append('e')\\\"> `e` </button></td>\\n<td><button onclick=\\\"append('1')\\\"> `1` </button></td>\\n<td><button onclick=\\\"append('2')\\\"> `2` </button></td>\\n<td><button onclick=\\\"append('3')\\\"> `3` </button></td>\\n<td><button onclick=\\\"append('+')\\\"> `+{::}` </button></td>\\n\\n</tr>\\n<tr>\\n<td> <!--button onclick=\\\"append('pi')\\\"> `pi` </button--></td>\\n<td><button onclick=\\\"append('0')\\\"> `0` </button></td>\\n<td><button onclick=\\\"append('.')\\\"> `.` </button></td>\\n<td><button onclick=\\\"append('\\\\n')\\\"> `\\\"ent\\\"`</button></td>\\n</tr>\\n</tbody>\\n</table>\";\n\n// GO1.1 Generic onload by Brothercake\n// http://www.brothercake.com/\n//onload function (replaces the onload=\"translate()\" in the <body> tag)\nfunction generic()\n{\n if(!init()) return;\n if (translateOnLoad) {\n var nd = document.getElementById(\"processasciimathinmoodle\");\n if (nd!=null) dsvglocation = nd.className;\n if (nd!=null || !checkforprocessasciimathinmoodle) {\n translate();\n if (!noSVG && translateASCIIsvg) drawPictures();\n }\n var li = getElementsByClass(document,\"div\",\"ASCIIMathCalculator\");\n if (!noMathML && li.length>0) initASCIIMathCalculators(li);\n }\n};\n//setup onload function\nif(typeof window.addEventListener != 'undefined')\n{\n //.. gecko, safari, konqueror and standard\n window.addEventListener('load', generic, false);\n}\nelse if(typeof document.addEventListener != 'undefined')\n{\n //.. opera 7\n document.addEventListener('load', generic, false);\n}\nelse if(typeof window.attachEvent != 'undefined')\n{\n //.. win/ie\n window.attachEvent('onload', generic);\n}\n//** remove this condition to degrade older browsers\nelse\n{\n //.. mac/ie5 and anything else that gets this far\n //if there's an existing onload function\n if(typeof window.onload == 'function')\n {\n //store it\n var existing = onload;\n //add new onload handler\n window.onload = function()\n {\n //call existing onload function\n existing();\n //call generic onload function\n generic();\n };\n }\n else\n {\n //setup onload function\n window.onload = generic;\n }\n}\n</script>\n"+
+ Text/Pandoc/Blocks.hs view
@@ -0,0 +1,145 @@+{-+Copyright (C) 2007 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.Blocks+ Copyright : Copyright (C) 2007 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Functions for the manipulation of fixed-width blocks of text.+These are used in the construction of plain-text tables.+-}++module Text.Pandoc.Blocks+ ( + TextBlock (..),+ docToBlock,+ blockToDoc,+ widthOfBlock,+ heightOfBlock,+ hcatBlocks,+ hsepBlocks,+ centerAlignBlock,+ leftAlignBlock,+ rightAlignBlock+ )+where+import Text.PrettyPrint+import Data.List ( intersperse )++-- | A fixed-width block of text. Parameters are width of block,+-- height of block, and list of lines.+data TextBlock = TextBlock Int Int [String]+instance Show TextBlock where+ show x = show $ blockToDoc x++-- | Break lines in a list of lines so that none are greater than+-- a given width.+breakLines :: Int -- ^ Maximum length of lines.+ -> [String] -- ^ List of lines.+ -> [String]+breakLines width [] = []+breakLines width (l:ls) =+ if length l > width+ then (take width l):(breakLines width ((drop width l):ls))+ else l:(breakLines width ls)++-- | Convert a @Doc@ element into a @TextBlock@ with a specified width. +docToBlock :: Int -- ^ Width of text block.+ -> Doc -- ^ @Doc@ to convert.+ -> TextBlock+docToBlock width doc =+ let rendered = renderStyle (style {lineLength = width, + ribbonsPerLine = 1}) doc+ lns = breakLines width $ lines rendered+ in TextBlock width (length lns) lns++-- | Convert a @TextBlock@ to a @Doc@ element.+blockToDoc :: TextBlock -> Doc+blockToDoc (TextBlock _ _ lns) = + if null lns+ then empty+ else vcat $ map text lns++-- | Returns width of a @TextBlock@ (number of columns).+widthOfBlock :: TextBlock -> Int+widthOfBlock (TextBlock width _ _) = width++-- | Returns height of a @TextBlock@ (number of rows).+heightOfBlock :: TextBlock -> Int+heightOfBlock (TextBlock _ height _) = height++-- | Pads a string out to a given width using spaces.+hPad :: Int -- ^ Desired width.+ -> String -- ^ String to pad.+ -> String+hPad width line = + let lineLength = length line+ in if lineLength <= width + then line ++ replicate (width - lineLength) ' '+ else take width line++-- | Concatenates a list of @TextBlock@s into a new @TextBlock@ in+-- which they appear side by side.+hcatBlocks :: [TextBlock] -> TextBlock+hcatBlocks [] = TextBlock 0 0 []+hcatBlocks [x] = x -- This is not redundant! We don't want last item hPad'd.+hcatBlocks ((TextBlock width1 height1 lns1):xs) = + let (TextBlock width2 height2 lns2) = hcatBlocks xs+ height = max height1 height2+ width = width1 + width2+ lns1' = map (hPad width1) $ lns1 ++ replicate (height - height1) ""+ lns2' = lns2 ++ replicate (height - height2) ""+ lns = zipWith (++) lns1' lns2'+ in TextBlock width height lns ++-- | Like @hcatBlocks@, but inserts space between the @TextBlock@s.+hsepBlocks :: [TextBlock] -> TextBlock+hsepBlocks = hcatBlocks . (intersperse (TextBlock 1 1 [" "]))++isWhitespace x = x `elem` " \t"++-- | Left-aligns the contents of a @TextBlock@ within the block.+leftAlignBlock :: TextBlock -> TextBlock+leftAlignBlock (TextBlock width height lns) =+ TextBlock width height $ map (dropWhile isWhitespace) lns++-- | Right-aligns the contents of a @TextBlock@ within the block.+rightAlignBlock :: TextBlock -> TextBlock+rightAlignBlock (TextBlock width height lns) =+ let rightAlignLine ln = + let (spaces, rest) = span isWhitespace $ reverse $ hPad width ln+ in reverse (rest ++ spaces)+ in TextBlock width height $ map rightAlignLine lns++-- | Centers the contents of a @TextBlock@ within the block.+centerAlignBlock :: TextBlock -> TextBlock+centerAlignBlock (TextBlock width height lns) = + let centerAlignLine ln =+ let ln' = hPad width ln+ (startSpaces, rest) = span isWhitespace ln'+ endSpaces = takeWhile isWhitespace (reverse ln')+ numSpaces = length (startSpaces ++ endSpaces)+ startSpaces' = replicate (quot numSpaces 2) ' '+ in startSpaces' ++ rest + in TextBlock width height $ map centerAlignLine lns+
+ Text/Pandoc/CharacterReferences.hs view
@@ -0,0 +1,327 @@+{-+Copyright (C) 2006-7 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.CharacterReferences+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Functions for parsing character references.+-}+module Text.Pandoc.CharacterReferences (+ characterReference,+ decodeCharacterReferences,+ ) where+import Data.Char ( chr )+import Text.ParserCombinators.Parsec+import qualified Data.Map as Map++-- | Parse character entity.+characterReference :: GenParser Char st Char+characterReference = try $ do+ st <- char '&'+ character <- numRef <|> entity+ end <- char ';'+ return character ++numRef :: GenParser Char st Char+numRef = do+ char '#'+ num <- hexNum <|> decNum+ return $ chr $ num ++hexNum :: GenParser Char st Int +hexNum = oneOf "Xx" >> many1 hexDigit >>= return . read . ("0x" ++)++decNum :: GenParser Char st Int +decNum = many1 digit >>= return . read++entity :: GenParser Char st Char+entity = do+ body <- many1 alphaNum+ return $ Map.findWithDefault '?' body entityTable++-- | Convert entities in a string to characters.+decodeCharacterReferences :: String -> String+decodeCharacterReferences str = + case parse (many (characterReference <|> anyChar)) str str of+ Left err -> error $ "\nError: " ++ show err+ Right result -> result++entityTable :: Map.Map String Char+entityTable = Map.fromList entityTableList++entityTableList :: [(String, Char)]+entityTableList = [+ ("quot", chr 34),+ ("amp", chr 38),+ ("lt", chr 60),+ ("gt", chr 62),+ ("nbsp", chr 160),+ ("iexcl", chr 161),+ ("cent", chr 162),+ ("pound", chr 163),+ ("curren", chr 164),+ ("yen", chr 165),+ ("brvbar", chr 166),+ ("sect", chr 167),+ ("uml", chr 168),+ ("copy", chr 169),+ ("ordf", chr 170),+ ("laquo", chr 171),+ ("not", chr 172),+ ("shy", chr 173),+ ("reg", chr 174),+ ("macr", chr 175),+ ("deg", chr 176),+ ("plusmn", chr 177),+ ("sup2", chr 178),+ ("sup3", chr 179),+ ("acute", chr 180),+ ("micro", chr 181),+ ("para", chr 182),+ ("middot", chr 183),+ ("cedil", chr 184),+ ("sup1", chr 185),+ ("ordm", chr 186),+ ("raquo", chr 187),+ ("frac14", chr 188),+ ("frac12", chr 189),+ ("frac34", chr 190),+ ("iquest", chr 191),+ ("Agrave", chr 192),+ ("Aacute", chr 193),+ ("Acirc", chr 194),+ ("Atilde", chr 195),+ ("Auml", chr 196),+ ("Aring", chr 197),+ ("AElig", chr 198),+ ("Ccedil", chr 199),+ ("Egrave", chr 200),+ ("Eacute", chr 201),+ ("Ecirc", chr 202),+ ("Euml", chr 203),+ ("Igrave", chr 204),+ ("Iacute", chr 205),+ ("Icirc", chr 206),+ ("Iuml", chr 207),+ ("ETH", chr 208),+ ("Ntilde", chr 209),+ ("Ograve", chr 210),+ ("Oacute", chr 211),+ ("Ocirc", chr 212),+ ("Otilde", chr 213),+ ("Ouml", chr 214),+ ("times", chr 215),+ ("Oslash", chr 216),+ ("Ugrave", chr 217),+ ("Uacute", chr 218),+ ("Ucirc", chr 219),+ ("Uuml", chr 220),+ ("Yacute", chr 221),+ ("THORN", chr 222),+ ("szlig", chr 223),+ ("agrave", chr 224),+ ("aacute", chr 225),+ ("acirc", chr 226),+ ("atilde", chr 227),+ ("auml", chr 228),+ ("aring", chr 229),+ ("aelig", chr 230),+ ("ccedil", chr 231),+ ("egrave", chr 232),+ ("eacute", chr 233),+ ("ecirc", chr 234),+ ("euml", chr 235),+ ("igrave", chr 236),+ ("iacute", chr 237),+ ("icirc", chr 238),+ ("iuml", chr 239),+ ("eth", chr 240),+ ("ntilde", chr 241),+ ("ograve", chr 242),+ ("oacute", chr 243),+ ("ocirc", chr 244),+ ("otilde", chr 245),+ ("ouml", chr 246),+ ("divide", chr 247),+ ("oslash", chr 248),+ ("ugrave", chr 249),+ ("uacute", chr 250),+ ("ucirc", chr 251),+ ("uuml", chr 252),+ ("yacute", chr 253),+ ("thorn", chr 254),+ ("yuml", chr 255),+ ("OElig", chr 338),+ ("oelig", chr 339),+ ("Scaron", chr 352),+ ("scaron", chr 353),+ ("Yuml", chr 376),+ ("fnof", chr 402),+ ("circ", chr 710),+ ("tilde", chr 732),+ ("Alpha", chr 913),+ ("Beta", chr 914),+ ("Gamma", chr 915),+ ("Delta", chr 916),+ ("Epsilon", chr 917),+ ("Zeta", chr 918),+ ("Eta", chr 919),+ ("Theta", chr 920),+ ("Iota", chr 921),+ ("Kappa", chr 922),+ ("Lambda", chr 923),+ ("Mu", chr 924),+ ("Nu", chr 925),+ ("Xi", chr 926),+ ("Omicron", chr 927),+ ("Pi", chr 928),+ ("Rho", chr 929),+ ("Sigma", chr 931),+ ("Tau", chr 932),+ ("Upsilon", chr 933),+ ("Phi", chr 934),+ ("Chi", chr 935),+ ("Psi", chr 936),+ ("Omega", chr 937),+ ("alpha", chr 945),+ ("beta", chr 946),+ ("gamma", chr 947),+ ("delta", chr 948),+ ("epsilon", chr 949),+ ("zeta", chr 950),+ ("eta", chr 951),+ ("theta", chr 952),+ ("iota", chr 953),+ ("kappa", chr 954),+ ("lambda", chr 955),+ ("mu", chr 956),+ ("nu", chr 957),+ ("xi", chr 958),+ ("omicron", chr 959),+ ("pi", chr 960),+ ("rho", chr 961),+ ("sigmaf", chr 962),+ ("sigma", chr 963),+ ("tau", chr 964),+ ("upsilon", chr 965),+ ("phi", chr 966),+ ("chi", chr 967),+ ("psi", chr 968),+ ("omega", chr 969),+ ("thetasym", chr 977),+ ("upsih", chr 978),+ ("piv", chr 982),+ ("ensp", chr 8194),+ ("emsp", chr 8195),+ ("thinsp", chr 8201),+ ("zwnj", chr 8204),+ ("zwj", chr 8205),+ ("lrm", chr 8206),+ ("rlm", chr 8207),+ ("ndash", chr 8211),+ ("mdash", chr 8212),+ ("lsquo", chr 8216),+ ("rsquo", chr 8217),+ ("sbquo", chr 8218),+ ("ldquo", chr 8220),+ ("rdquo", chr 8221),+ ("bdquo", chr 8222),+ ("dagger", chr 8224),+ ("Dagger", chr 8225),+ ("bull", chr 8226),+ ("hellip", chr 8230),+ ("permil", chr 8240),+ ("prime", chr 8242),+ ("Prime", chr 8243),+ ("lsaquo", chr 8249),+ ("rsaquo", chr 8250),+ ("oline", chr 8254),+ ("frasl", chr 8260),+ ("euro", chr 8364),+ ("image", chr 8465),+ ("weierp", chr 8472),+ ("real", chr 8476),+ ("trade", chr 8482),+ ("alefsym", chr 8501),+ ("larr", chr 8592),+ ("uarr", chr 8593),+ ("rarr", chr 8594),+ ("darr", chr 8595),+ ("harr", chr 8596),+ ("crarr", chr 8629),+ ("lArr", chr 8656),+ ("uArr", chr 8657),+ ("rArr", chr 8658),+ ("dArr", chr 8659),+ ("hArr", chr 8660),+ ("forall", chr 8704),+ ("part", chr 8706),+ ("exist", chr 8707),+ ("empty", chr 8709),+ ("nabla", chr 8711),+ ("isin", chr 8712),+ ("notin", chr 8713),+ ("ni", chr 8715),+ ("prod", chr 8719),+ ("sum", chr 8721),+ ("minus", chr 8722),+ ("lowast", chr 8727),+ ("radic", chr 8730),+ ("prop", chr 8733),+ ("infin", chr 8734),+ ("ang", chr 8736),+ ("and", chr 8743),+ ("or", chr 8744),+ ("cap", chr 8745),+ ("cup", chr 8746),+ ("int", chr 8747),+ ("there4", chr 8756),+ ("sim", chr 8764),+ ("cong", chr 8773),+ ("asymp", chr 8776),+ ("ne", chr 8800),+ ("equiv", chr 8801),+ ("le", chr 8804),+ ("ge", chr 8805),+ ("sub", chr 8834),+ ("sup", chr 8835),+ ("nsub", chr 8836),+ ("sube", chr 8838),+ ("supe", chr 8839),+ ("oplus", chr 8853),+ ("otimes", chr 8855),+ ("perp", chr 8869),+ ("sdot", chr 8901),+ ("lceil", chr 8968),+ ("rceil", chr 8969),+ ("lfloor", chr 8970),+ ("rfloor", chr 8971),+ ("lang", chr 9001),+ ("rang", chr 9002),+ ("loz", chr 9674),+ ("spades", chr 9824),+ ("clubs", chr 9827),+ ("hearts", chr 9829),+ ("diams", chr 9830)+ ]
+ Text/Pandoc/Definition.hs view
@@ -0,0 +1,117 @@+{-+Copyright (C) 2006-7 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.Definition+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Definition of 'Pandoc' data structure for format-neutral representation+of documents.+-}+module Text.Pandoc.Definition where++data Pandoc = Pandoc Meta [Block] deriving (Eq, Read, Show)++-- | Bibliographic information for the document: title (list of 'Inline'),+-- authors (list of strings), date (string).+data Meta = Meta [Inline] -- title+ [String] -- authors+ String -- date+ deriving (Eq, Show, Read)++-- | Alignment of a table column.+data Alignment = AlignLeft + | AlignRight + | AlignCenter + | AlignDefault deriving (Eq, Show, Read)++-- | List attributes.+type ListAttributes = (Int, ListNumberStyle, ListNumberDelim)++-- | Style of list numbers.+data ListNumberStyle = DefaultStyle+ | Decimal + | LowerRoman + | UpperRoman+ | LowerAlpha + | UpperAlpha deriving (Eq, Show, Read)++-- | Delimiter of list numbers.+data ListNumberDelim = DefaultDelim+ | Period+ | OneParen + | TwoParens deriving (Eq, Show, Read)+ +-- | Block element.+data Block + = Plain [Inline] -- ^ Plain text, not a paragraph+ | Para [Inline] -- ^ Paragraph+ | CodeBlock String -- ^ Code block (literal)+ | RawHtml String -- ^ Raw HTML block (literal)+ | BlockQuote [Block] -- ^ Block quote (list of blocks)+ | OrderedList ListAttributes [[Block]] -- ^ Ordered list (attributes+ -- and a list of items, each a list of blocks)+ | BulletList [[Block]] -- ^ Bullet list (list of items, each+ -- a list of blocks)+ | DefinitionList [([Inline],[Block])] -- ^ Definition list + -- (list of items, each a pair of an inline list,+ -- the term, and a block list)+ | Header Int [Inline] -- ^ Header - level (integer) and text (inlines) + | HorizontalRule -- ^ Horizontal rule+ | Table [Inline] [Alignment] [Float] [[Block]] [[[Block]]] -- ^ Table,+ -- with caption, column alignments,+ -- relative column widths, column headers+ -- (each a list of blocks), and rows+ -- (each a list of lists of blocks)+ | Null -- ^ Nothing+ deriving (Eq, Read, Show)++-- | Type of quotation marks to use in Quoted inline.+data QuoteType = SingleQuote | DoubleQuote deriving (Show, Eq, Read)++type Target = (String, String) -- ^ Link target (URL, title)++-- | Inline elements.+data Inline + = Str String -- ^ Text (string)+ | Emph [Inline] -- ^ Emphasized text (list of inlines)+ | Strong [Inline] -- ^ Strongly emphasized text (list of inlines)+ | Strikeout [Inline] -- ^ Strikeout text (list of inlines)+ | Superscript [Inline] -- ^ Superscripted text (list of inlines)+ | Subscript [Inline] -- ^ Subscripted text (list of inlines)+ | Quoted QuoteType [Inline] -- ^ Quoted text (list of inlines)+ | Code String -- ^ Inline code (literal)+ | Space -- ^ Inter-word space+ | EmDash -- ^ Em dash+ | EnDash -- ^ En dash+ | Apostrophe -- ^ Apostrophe+ | Ellipses -- ^ Ellipses+ | LineBreak -- ^ Hard line break+ | Math String -- ^ TeX math (literal)+ | TeX String -- ^ LaTeX code (literal)+ | HtmlInline String -- ^ HTML code (literal)+ | Link [Inline] Target -- ^ Hyperlink: text (list of inlines), target+ | Image [Inline] Target -- ^ Image: alt text (list of inlines), target+ -- and target+ | Note [Block] -- ^ Footnote or endnote + deriving (Show, Eq, Read)
+ Text/Pandoc/Readers/HTML.hs view
@@ -0,0 +1,496 @@+{-+Copyright (C) 2006-7 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.Readers.HTML+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha + Portability : portable++Conversion of HTML to 'Pandoc' document.+-}+module Text.Pandoc.Readers.HTML ( + readHtml, + rawHtmlInline, + rawHtmlBlock, + anyHtmlBlockTag, + anyHtmlInlineTag, + anyHtmlTag,+ anyHtmlEndTag,+ htmlEndTag,+ extractTagType,+ htmlBlockElement + ) where++import Text.ParserCombinators.Parsec+import Text.Pandoc.Definition+import Text.Pandoc.Shared +import Text.Pandoc.CharacterReferences ( characterReference, + decodeCharacterReferences )+import Data.Maybe ( fromMaybe )+import Data.List ( takeWhile, dropWhile, isPrefixOf, isSuffixOf )+import Data.Char ( toUpper, toLower, isAlphaNum )++-- | Convert HTML-formatted string to 'Pandoc' document.+readHtml :: ParserState -- ^ Parser state+ -> String -- ^ String to parse+ -> Pandoc+readHtml = readWith parseHtml++--+-- Constants+--++eitherBlockOrInline = ["applet", "button", "del", "iframe", "ins",+ "map", "area", "object", "script"]++inlineHtmlTags = ["a", "abbr", "acronym", "b", "basefont", "bdo", "big",+ "br", "cite", "code", "dfn", "em", "font", "i", "img",+ "input", "kbd", "label", "q", "s", "samp", "select",+ "small", "span", "strike", "strong", "sub", "sup",+ "textarea", "tt", "u", "var"] ++ eitherBlockOrInline++blockHtmlTags = ["address", "blockquote", "center", "dir", "div",+ "dl", "fieldset", "form", "h1", "h2", "h3", "h4",+ "h5", "h6", "hr", "isindex", "menu", "noframes",+ "noscript", "ol", "p", "pre", "table", "ul", "dd",+ "dt", "frameset", "li", "tbody", "td", "tfoot",+ "th", "thead", "tr"] ++ eitherBlockOrInline++--+-- HTML utility functions+--++-- | Read blocks until end tag.+blocksTilEnd tag = do+ blocks <- manyTill (block >>~ spaces) (htmlEndTag tag)+ return $ filter (/= Null) blocks++-- | Read inlines until end tag.+inlinesTilEnd tag = manyTill inline (htmlEndTag tag)++-- | Parse blocks between open and close tag.+blocksIn tag = try $ htmlTag tag >> spaces >> blocksTilEnd tag++-- | Parse inlines between open and close tag.+inlinesIn tag = try $ htmlTag tag >> spaces >> inlinesTilEnd tag++-- | Extract type from a tag: e.g. @br@ from @\<br\>@+extractTagType :: String -> String+extractTagType ('<':rest) = + let isSpaceOrSlash c = c `elem` "/ \n\t" in+ map toLower $ takeWhile isAlphaNum $ dropWhile isSpaceOrSlash rest+extractTagType _ = ""++-- | Parse any HTML tag (opening or self-closing) and return text of tag+anyHtmlTag = try $ do+ char '<'+ spaces+ tag <- many1 alphaNum+ attribs <- many htmlAttribute+ spaces+ ender <- option "" (string "/")+ let ender' = if null ender then "" else " /"+ spaces+ char '>'+ return $ "<" ++ tag ++ + concatMap (\(_, _, raw) -> (' ':raw)) attribs ++ ender' ++ ">"++anyHtmlEndTag = try $ do+ char '<' + spaces+ char '/'+ spaces+ tagType <- many1 alphaNum+ spaces+ char '>'+ return $ "</" ++ tagType ++ ">"++htmlTag :: String -> GenParser Char st (String, [(String, String)])+htmlTag tag = try $ do+ char '<'+ spaces+ stringAnyCase tag+ attribs <- many htmlAttribute+ spaces+ optional (string "/")+ spaces+ char '>'+ return (tag, (map (\(name, content, raw) -> (name, content)) attribs))++-- parses a quoted html attribute value+quoted quoteChar = do+ result <- between (char quoteChar) (char quoteChar) + (many (noneOf [quoteChar]))+ return (result, [quoteChar])++htmlAttribute = htmlRegularAttribute <|> htmlMinimizedAttribute++-- minimized boolean attribute+htmlMinimizedAttribute = try $ do+ many1 space+ name <- many1 (choice [letter, oneOf ".-_:"])+ return (name, name, name)++htmlRegularAttribute = try $ do+ many1 space+ name <- many1 (choice [letter, oneOf ".-_:"])+ spaces+ char '='+ spaces+ (content, quoteStr) <- choice [ (quoted '\''), + (quoted '"'), + (do+ a <- many (alphaNum <|> (oneOf "-._:"))+ return (a,"")) ]+ return (name, content,+ (name ++ "=" ++ quoteStr ++ content ++ quoteStr))++-- | Parse an end tag of type 'tag'+htmlEndTag tag = try $ do+ char '<' + spaces+ char '/'+ spaces+ stringAnyCase tag+ spaces+ char '>'+ return $ "</" ++ tag ++ ">"++-- | Returns @True@ if the tag is (or can be) an inline tag.+isInline tag = (extractTagType tag) `elem` inlineHtmlTags++-- | Returns @True@ if the tag is (or can be) a block tag.+isBlock tag = (extractTagType tag) `elem` blockHtmlTags ++anyHtmlBlockTag = try $ do+ tag <- anyHtmlTag <|> anyHtmlEndTag+ if isBlock tag then return tag else fail "inline tag"++anyHtmlInlineTag = try $ do+ tag <- anyHtmlTag <|> anyHtmlEndTag+ if isInline tag then return tag else fail "not an inline tag"++-- | Parses material between script tags.+-- Scripts must be treated differently, because they can contain '<>' etc.+htmlScript = try $ do+ open <- string "<script"+ rest <- manyTill anyChar (htmlEndTag "script")+ return $ open ++ rest ++ "</script>"++htmlBlockElement = choice [ htmlScript, htmlComment, xmlDec, definition ]++rawHtmlBlock = try $ do+ notFollowedBy' (htmlTag "/body" <|> htmlTag "/html")+ body <- htmlBlockElement <|> anyHtmlTag <|> anyHtmlEndTag+ sp <- many space+ state <- getState+ if stateParseRaw state then return (RawHtml (body ++ sp)) else return Null++-- | Parses an HTML comment.+htmlComment = try $ do+ string "<!--"+ comment <- manyTill anyChar (try (string "-->"))+ return $ "<!--" ++ comment ++ "-->"++--+-- parsing documents+--++xmlDec = try $ do+ string "<?"+ rest <- manyTill anyChar (char '>')+ return $ "<?" ++ rest ++ ">"++definition = try $ do+ string "<!"+ rest <- manyTill anyChar (char '>')+ return $ "<!" ++ rest ++ ">"++nonTitleNonHead = try $ notFollowedBy' (htmlTag "title" <|> htmlTag "/head") >>+ ((rawHtmlBlock >> return ' ') <|> anyChar)++parseTitle = try $ do+ (tag, _) <- htmlTag "title"+ contents <- inlinesTilEnd tag+ spaces+ return contents++-- parse header and return meta-information (for now, just title)+parseHead = try $ do+ htmlTag "head"+ spaces+ skipMany nonTitleNonHead+ contents <- option [] parseTitle+ skipMany nonTitleNonHead+ htmlTag "/head"+ return (contents, [], "")++skipHtmlTag tag = optional (htmlTag tag)++-- h1 class="title" representation of title in body+bodyTitle = try $ do+ (tag, attribs) <- htmlTag "h1" + cl <- case (extractAttribute "class" attribs) of+ Just "title" -> return ""+ otherwise -> fail "not title"+ inlinesTilEnd "h1"++parseHtml = do+ sepEndBy (choice [xmlDec, definition, htmlComment]) spaces+ skipHtmlTag "html"+ spaces+ (title, authors, date) <- option ([], [], "") parseHead + spaces+ skipHtmlTag "body"+ spaces+ optional bodyTitle -- skip title in body, because it's represented in meta+ blocks <- parseBlocks+ spaces+ optional (htmlEndTag "body")+ spaces+ optional (htmlEndTag "html" >> many anyChar) -- ignore anything after </html>+ eof+ return $ Pandoc (Meta title authors date) blocks++--+-- parsing blocks+--++parseBlocks = spaces >> sepEndBy block spaces >>= (return . filter (/= Null))++block = choice [ codeBlock+ , header+ , hrule+ , list+ , blockQuote+ , para+ , plain+ , rawHtmlBlock ] <?> "block"++--+-- header blocks+--++header = choice (map headerLevel (enumFromTo 1 5)) <?> "header"++headerLevel n = try $ do+ let level = "h" ++ show n+ (tag, attribs) <- htmlTag level+ contents <- inlinesTilEnd level+ return $ Header n (normalizeSpaces contents)++--+-- hrule block+--++hrule = try $ do+ (tag, attribs) <- htmlTag "hr"+ state <- getState+ if not (null attribs) && stateParseRaw state+ then unexpected "attributes in hr" -- parse as raw in this case+ else return HorizontalRule++--+-- code blocks+--++-- Note: HTML tags in code blocks (e.g. for syntax highlighting) are +-- skipped, because they are not portable to output formats other than HTML.+codeBlock = try $ do+ htmlTag "pre" + result <- manyTill + (many1 (satisfy (/= '<')) <|> + ((anyHtmlTag <|> anyHtmlEndTag) >> return ""))+ (htmlEndTag "pre")+ let result' = concat result+ -- drop leading newline if any+ let result'' = if "\n" `isPrefixOf` result'+ then drop 1 result'+ else result'+ -- drop trailing newline if any+ let result''' = if "\n" `isSuffixOf` result''+ then init result''+ else result''+ return $ CodeBlock $ decodeCharacterReferences result'''++--+-- block quotes+--++blockQuote = try $ htmlTag "blockquote" >> spaces >> + blocksTilEnd "blockquote" >>= (return . BlockQuote)++--+-- list blocks+--++list = choice [ bulletList, orderedList, definitionList ] <?> "list"++orderedList = try $ do+ (_, attribs) <- htmlTag "ol"+ (start, style) <- option (1, DefaultStyle) $+ do failIfStrict+ let sta = fromMaybe "1" $ + lookup "start" attribs+ let sty = fromMaybe (fromMaybe "" $+ lookup "style" attribs) $+ lookup "class" attribs+ let sty' = case sty of+ "lower-roman" -> LowerRoman+ "upper-roman" -> UpperRoman+ "lower-alpha" -> LowerAlpha+ "upper-alpha" -> UpperAlpha+ "decimal" -> Decimal+ _ -> DefaultStyle+ return (read sta, sty')+ spaces+ items <- sepEndBy1 (blocksIn "li") spaces+ htmlEndTag "ol"+ return $ OrderedList (start, style, DefaultDelim) items++bulletList = try $ do+ htmlTag "ul"+ spaces+ items <- sepEndBy1 (blocksIn "li") spaces+ htmlEndTag "ul"+ return $ BulletList items++definitionList = try $ do+ failIfStrict -- def lists not part of standard markdown+ tag <- htmlTag "dl"+ spaces+ items <- sepEndBy1 definitionListItem spaces+ htmlEndTag "dl"+ return $ DefinitionList items++definitionListItem = try $ do+ terms <- sepEndBy1 (inlinesIn "dt") spaces+ defs <- sepEndBy1 (blocksIn "dd") spaces+ let term = joinWithSep [LineBreak] terms+ return (term, concat defs)++--+-- paragraph block+--++para = try $ htmlTag "p" >> inlinesTilEnd "p" >>= + return . Para . normalizeSpaces++-- +-- plain block+--++plain = many1 inline >>= return . Plain . normalizeSpaces++-- +-- inline+--++inline = choice [ charRef+ , strong+ , emph+ , superscript+ , subscript+ , strikeout+ , spanStrikeout+ , code+ , str+ , linebreak+ , whitespace+ , link+ , image+ , rawHtmlInline+ ] <?> "inline"++code = try $ do + htmlTag "code"+ result <- manyTill anyChar (htmlEndTag "code")+ -- remove internal line breaks, leading and trailing space,+ -- and decode character references+ return $ Code $ decodeCharacterReferences $ removeLeadingTrailingSpace $ + joinWithSep " " $ lines result ++rawHtmlInline = do+ result <- htmlScript <|> htmlComment <|> anyHtmlInlineTag+ state <- getState+ if stateParseRaw state then return (HtmlInline result) else return (Str "")++betweenTags tag = try $ htmlTag tag >> inlinesTilEnd tag >>= + return . normalizeSpaces++emph = (betweenTags "em" <|> betweenTags "it") >>= return . Emph++strong = (betweenTags "b" <|> betweenTags "strong") >>= return . Strong++superscript = failIfStrict >> betweenTags "sup" >>= return . Superscript++subscript = failIfStrict >> betweenTags "sub" >>= return . Subscript++strikeout = failIfStrict >> (betweenTags "s" <|> betweenTags "strike") >>=+ return . Strikeout++spanStrikeout = try $ do+ failIfStrict -- strict markdown has no strikeout, so treat as raw HTML+ (tag, attributes) <- htmlTag "span" + result <- case (extractAttribute "class" attributes) of+ Just "strikeout" -> inlinesTilEnd "span"+ _ -> fail "not a strikeout"+ return $ Strikeout result++whitespace = many1 space >> return Space++-- hard line break+linebreak = htmlTag "br" >> optional newline >> return LineBreak++str = many1 (noneOf "<& \t\n") >>= return . Str++--+-- links and images+--++-- extract contents of attribute (attribute names are case-insensitive)+extractAttribute name [] = Nothing+extractAttribute name ((attrName, contents):rest) = + let name' = map toLower name + attrName' = map toLower attrName+ in if attrName' == name'+ then Just (decodeCharacterReferences contents)+ else extractAttribute name rest++link = try $ do+ (tag, attributes) <- htmlTag "a" + url <- case (extractAttribute "href" attributes) of+ Just url -> return url+ Nothing -> fail "no href"+ let title = fromMaybe "" $ extractAttribute "title" attributes+ label <- inlinesTilEnd "a"+ return $ Link (normalizeSpaces label) (url, title)++image = try $ do+ (tag, attributes) <- htmlTag "img" + url <- case (extractAttribute "src" attributes) of+ Just url -> return url+ Nothing -> fail "no src"+ let title = fromMaybe "" $ extractAttribute "title" attributes+ let alt = fromMaybe "" (extractAttribute "alt" attributes)+ return $ Image [Str alt] (url, title)+
+ Text/Pandoc/Readers/LaTeX.hs view
@@ -0,0 +1,652 @@+{-+Copyright (C) 2006-7 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.Readers.LaTeX+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of LaTeX to 'Pandoc' document.+-}+module Text.Pandoc.Readers.LaTeX ( + readLaTeX,+ rawLaTeXInline,+ rawLaTeXEnvironment+ ) where++import Text.ParserCombinators.Parsec+import Text.Pandoc.Definition+import Text.Pandoc.Shared +import Data.Maybe ( fromMaybe )+import Data.Char ( chr )+import Data.List ( isPrefixOf, isSuffixOf )++-- | Parse LaTeX from string and return 'Pandoc' document.+readLaTeX :: ParserState -- ^ Parser state, including options for parser+ -> String -- ^ String to parse+ -> Pandoc+readLaTeX = readWith parseLaTeX++-- characters with special meaning+specialChars = "\\`$%^&_~#{}\n \t|<>'\"-"++--+-- utility functions+--++-- | Returns text between brackets and its matching pair.+bracketedText openB closeB = do+ result <- charsInBalanced' openB closeB+ return $ [openB] ++ result ++ [closeB]++-- | Returns an option or argument of a LaTeX command.+optOrArg = bracketedText '{' '}' <|> bracketedText '[' ']'++-- | True if the string begins with '{'.+isArg ('{':rest) = True+isArg other = False++-- | Returns list of options and arguments of a LaTeX command.+commandArgs = many optOrArg++-- | Parses LaTeX command, returns (name, star, list of options or arguments).+command = do+ char '\\'+ name <- many1 letter+ star <- option "" (string "*") -- some commands have starred versions+ args <- commandArgs+ return (name, star, args)++begin name = try $ do+ string $ "\\begin{" ++ name ++ "}"+ optional commandArgs+ spaces+ return name++end name = try $ do+ string $ "\\end{" ++ name ++ "}"+ spaces+ return name++-- | Returns a list of block elements containing the contents of an+-- environment.+environment name = try $ begin name >> spaces >> manyTill block (end name)++anyEnvironment = try $ do+ string "\\begin{"+ name <- many letter+ star <- option "" (string "*") -- some environments have starred variants+ char '}'+ optional commandArgs+ spaces+ contents <- manyTill block (end (name ++ star))+ return $ BlockQuote contents++--+-- parsing documents+--++-- | Process LaTeX preamble, extracting metadata.+processLaTeXPreamble = try $ manyTill + (choice [bibliographic, comment, unknownCommand, nullBlock]) + (try (string "\\begin{document}")) >> + spaces++-- | Parse LaTeX and return 'Pandoc'.+parseLaTeX = do+ optional processLaTeXPreamble -- preamble might not be present (fragment)+ spaces+ blocks <- parseBlocks+ spaces+ optional $ try (string "\\end{document}" >> many anyChar) + -- might not be present (fragment)+ spaces+ eof+ state <- getState+ let blocks' = filter (/= Null) blocks+ let title' = stateTitle state+ let authors' = stateAuthors state+ let date' = stateDate state+ return $ Pandoc (Meta title' authors' date') blocks'++--+-- parsing blocks+--++parseBlocks = spaces >> many block++block = choice [ hrule+ , codeBlock+ , header+ , list+ , blockQuote+ , mathBlock+ , comment+ , bibliographic+ , para+ , specialEnvironment+ , itemBlock+ , unknownEnvironment+ , unknownCommand ] <?> "block"++--+-- header blocks+--++header = try $ do+ char '\\'+ subs <- many (try (string "sub"))+ string "section"+ optional (char '*')+ char '{'+ title <- manyTill inline (char '}')+ spaces+ return $ Header (length subs + 1) (normalizeSpaces title)++--+-- hrule block+--++hrule = oneOfStrings [ "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n\n", + "\\newpage" ] >> spaces >> return HorizontalRule++--+-- code blocks+--++codeBlock = codeBlock1 <|> codeBlock2++codeBlock1 = try $ do+ string "\\begin{verbatim}" -- don't use begin function because it + -- gobbles whitespace+ optional blanklines -- we want to gobble blank lines, but not + -- leading space+ contents <- manyTill anyChar (try (string "\\end{verbatim}"))+ spaces+ return $ CodeBlock (stripTrailingNewlines contents)++codeBlock2 = try $ do+ string "\\begin{Verbatim}" -- used by fancyvrb package+ option "" blanklines+ contents <- manyTill anyChar (try (string "\\end{Verbatim}"))+ spaces+ return $ CodeBlock (stripTrailingNewlines contents)++--+-- block quotes+--++blockQuote = (environment "quote" <|> environment "quotation") >>~ spaces >>= + return . BlockQuote++--+-- math block+--++mathBlock = mathBlockWith (begin "equation") (end "equation") <|> + mathBlockWith (begin "displaymath") (end "displaymath") <|>+ mathBlockWith (try $ string "\\[") (try $ string "\\]") <?> + "math block"++mathBlockWith start end = try $ do+ start+ spaces+ result <- manyTill anyChar end+ spaces+ return $ BlockQuote [Para [Math result]]++--+-- list blocks+--++list = bulletList <|> orderedList <|> definitionList <?> "list"++listItem = try $ do+ ("item", _, args) <- command+ spaces+ state <- getState+ let oldParserContext = stateParserContext state+ updateState (\state -> state {stateParserContext = ListItemState})+ blocks <- many block+ updateState (\state -> state {stateParserContext = oldParserContext})+ opt <- case args of+ ([x]) | "[" `isPrefixOf` x && "]" `isSuffixOf` x -> + parseFromString (many inline) $ tail $ init x+ _ -> return []+ return (opt, blocks)++orderedList = try $ do+ string "\\begin{enumerate}"+ (_, style, delim) <- option (1, DefaultStyle, DefaultDelim) $+ try $ do failIfStrict+ char '['+ res <- anyOrderedListMarker+ char ']'+ return res+ spaces+ option "" $ try $ do string "\\setlength{\\itemindent}"+ char '{'+ manyTill anyChar (char '}')+ spaces+ start <- option 1 $ try $ do failIfStrict+ string "\\setcounter{enum"+ many1 (oneOf "iv")+ string "}{"+ num <- many1 digit+ char '}' + spaces+ return $ (read num) + 1+ items <- many listItem+ end "enumerate"+ spaces+ return $ OrderedList (start, style, delim) $ map snd items++bulletList = try $ do+ begin "itemize"+ spaces+ items <- many listItem+ end "itemize"+ spaces+ return (BulletList $ map snd items)++definitionList = try $ do+ begin "description"+ spaces+ items <- many listItem+ end "description"+ spaces+ return (DefinitionList items)++--+-- paragraph block+--++para = many1 inline >>~ spaces >>= return . Para . normalizeSpaces++--+-- title authors date+--++bibliographic = choice [ maketitle, title, authors, date ]++maketitle = try (string "\\maketitle") >> spaces >> return Null++title = try $ do+ string "\\title{"+ tit <- manyTill inline (char '}')+ spaces+ updateState (\state -> state { stateTitle = tit })+ return Null++authors = try $ do+ string "\\author{"+ authors <- manyTill anyChar (char '}')+ spaces+ let authors' = map removeLeadingTrailingSpace $ lines $+ substitute "\\\\" "\n" authors+ updateState (\state -> state { stateAuthors = authors' })+ return Null++date = try $ do+ string "\\date{"+ date' <- manyTill anyChar (char '}')+ spaces+ updateState (\state -> state { stateDate = date' })+ return Null++--+-- item block+-- for use in unknown environments that aren't being parsed as raw latex+--++-- this forces items to be parsed in different blocks+itemBlock = try $ do+ ("item", _, args) <- command+ state <- getState+ if (stateParserContext state == ListItemState)+ then fail "item should be handled by list block"+ else if null args + then return Null+ else return $ Plain [Str (stripFirstAndLast (head args))]++--+-- raw LaTeX +--++specialEnvironment = do -- these are always parsed as raw+ lookAhead (choice (map (\name -> begin name) ["tabular", "figure",+ "tabbing", "eqnarry", "picture", "table", "verse", "theorem"]))+ rawLaTeXEnvironment++-- | Parse any LaTeX environment and return a Para block containing+-- the whole literal environment as raw TeX.+rawLaTeXEnvironment :: GenParser Char st Block+rawLaTeXEnvironment = try $ do+ string "\\begin{"+ name <- many1 letter+ star <- option "" (string "*") -- for starred variants+ let name' = name ++ star+ char '}'+ args <- option [] commandArgs+ let argStr = concat args+ contents <- manyTill (choice [ (many1 (noneOf "\\")), + (do + (Para [TeX str]) <- rawLaTeXEnvironment+ return str),+ string "\\" ]) + (end name')+ spaces+ return $ Para [TeX $ "\\begin{" ++ name' ++ "}" ++ argStr ++ + concat contents ++ "\\end{" ++ name' ++ "}"]++unknownEnvironment = try $ do+ state <- getState+ result <- if stateParseRaw state -- check whether we should include raw TeX + then rawLaTeXEnvironment -- if so, get whole raw environment+ else anyEnvironment -- otherwise just the contents+ return result++unknownCommand = try $ do+ notFollowedBy' $ choice $ map end ["itemize", "enumerate", "description", + "document"]+ (name, star, args) <- command+ spaces+ let argStr = concat args+ state <- getState+ if name == "item" && (stateParserContext state) == ListItemState+ then fail "should not be parsed as raw"+ else string ""+ if stateParseRaw state+ then return $ Plain [TeX ("\\" ++ name ++ star ++ argStr)]+ else return $ Plain [Str (joinWithSep " " args)]++-- latex comment+comment = try $ char '%' >> manyTill anyChar newline >> spaces >> return Null++-- +-- inline+--++inline = choice [ str+ , endline+ , whitespace+ , quoted+ , apostrophe+ , spacer+ , strong+ , math+ , ellipses+ , emDash+ , enDash+ , hyphen+ , emph+ , strikeout+ , superscript+ , subscript+ , ref+ , lab+ , code+ , url+ , link+ , image+ , footnote+ , linebreak+ , accentedChar+ , specialChar+ , rawLaTeXInline+ , escapedChar+ , unescapedChar+ ] <?> "inline"++accentedChar = normalAccentedChar <|> specialAccentedChar++normalAccentedChar = try $ do+ char '\\'+ accent <- oneOf "'`^\"~"+ character <- (try $ char '{' >> letter >>~ char '}') <|> letter+ let table = fromMaybe [] $ lookup character accentTable + let result = case lookup accent table of+ Just num -> chr num+ Nothing -> '?'+ return $ Str [result]++-- an association list of letters and association list of accents+-- and decimal character numbers.+accentTable = + [ ('A', [('`', 192), ('\'', 193), ('^', 194), ('~', 195), ('"', 196)]),+ ('E', [('`', 200), ('\'', 201), ('^', 202), ('"', 203)]),+ ('I', [('`', 204), ('\'', 205), ('^', 206), ('"', 207)]),+ ('N', [('~', 209)]),+ ('O', [('`', 210), ('\'', 211), ('^', 212), ('~', 213), ('"', 214)]),+ ('U', [('`', 217), ('\'', 218), ('^', 219), ('"', 220)]),+ ('a', [('`', 224), ('\'', 225), ('^', 227), ('"', 228)]),+ ('e', [('`', 232), ('\'', 233), ('^', 234), ('"', 235)]),+ ('i', [('`', 236), ('\'', 237), ('^', 238), ('"', 239)]),+ ('n', [('~', 241)]),+ ('o', [('`', 242), ('\'', 243), ('^', 244), ('~', 245), ('"', 246)]),+ ('u', [('`', 249), ('\'', 250), ('^', 251), ('"', 252)]) ]++specialAccentedChar = choice [ ccedil, aring, iuml, szlig, aelig,+ oslash, pound, euro, copyright, sect ]++ccedil = try $ do+ char '\\'+ letter <- oneOfStrings ["cc", "cC"]+ let num = if letter == "cc" then 231 else 199+ return $ Str [chr num]++aring = try $ do+ char '\\'+ letter <- oneOfStrings ["aa", "AA"]+ let num = if letter == "aa" then 229 else 197+ return $ Str [chr num]++iuml = try (string "\\\"") >> oneOfStrings ["\\i", "{\\i}"] >> + return (Str [chr 239])++icirc = try (string "\\^") >> oneOfStrings ["\\i", "{\\i}"] >>+ return (Str [chr 238])++szlig = try (string "\\ss") >> return (Str [chr 223])++oslash = try $ do+ char '\\'+ letter <- choice [char 'o', char 'O']+ let num = if letter == 'o' then 248 else 216+ return $ Str [chr num]++aelig = try $ do+ char '\\'+ letter <- oneOfStrings ["ae", "AE"]+ let num = if letter == "ae" then 230 else 198+ return $ Str [chr num]++pound = try (string "\\pounds") >> return (Str [chr 163])++euro = try (string "\\euro") >> return (Str [chr 8364])++copyright = try (string "\\copyright") >> return (Str [chr 169])++sect = try (string "\\S") >> return (Str [chr 167])++escapedChar = do+ result <- escaped (oneOf " $%&_#{}\n")+ return $ if result == Str "\n" then Str " " else result++-- ignore standalone, nonescaped special characters+unescapedChar = oneOf "`$^&_#{}|<>" >> return (Str "")++specialChar = choice [ backslash, tilde, caret, bar, lt, gt, doubleQuote ]++backslash = try (string "\\textbackslash") >> return (Str "\\")++tilde = try (string "\\ensuremath{\\sim}") >> return (Str "~")++caret = try (string "\\^{}") >> return (Str "^")++bar = try (string "\\textbar") >> return (Str "\\")++lt = try (string "\\textless") >> return (Str "<")++gt = try (string "\\textgreater") >> return (Str ">")++doubleQuote = char '"' >> return (Str "\"")++code = code1 <|> code2++code1 = try $ do + string "\\verb"+ marker <- anyChar+ result <- manyTill anyChar (char marker)+ return $ Code $ removeLeadingTrailingSpace result++code2 = try $ do+ string "\\texttt{"+ result <- manyTill (noneOf "\\\n~$%^&{}") (char '}')+ return $ Code result++emph = try $ oneOfStrings [ "\\emph{", "\\textit{" ] >>+ manyTill inline (char '}') >>= return . Emph++strikeout = try $ string "\\sout{" >> manyTill inline (char '}') >>=+ return . Strikeout++superscript = try $ string "\\textsuperscript{" >> + manyTill inline (char '}') >>= return . Superscript++-- note: \textsubscript isn't a standard latex command, but we use+-- a defined version in pandoc.+subscript = try $ string "\\textsubscript{" >> manyTill inline (char '}') >>=+ return . Subscript++apostrophe = char '\'' >> return Apostrophe++quoted = doubleQuoted <|> singleQuoted++singleQuoted = enclosed singleQuoteStart singleQuoteEnd inline >>=+ return . Quoted SingleQuote . normalizeSpaces++doubleQuoted = enclosed doubleQuoteStart doubleQuoteEnd inline >>=+ return . Quoted DoubleQuote . normalizeSpaces++singleQuoteStart = char '`'++singleQuoteEnd = try $ char '\'' >> notFollowedBy alphaNum++doubleQuoteStart = string "``"++doubleQuoteEnd = try $ string "''"++ellipses = try $ string "\\ldots" >> optional (try (string "{}")) >>+ return Ellipses++enDash = try (string "--") >> return EnDash++emDash = try (string "---") >> return EmDash++hyphen = char '-' >> return (Str "-")++lab = try $ do+ string "\\label{"+ result <- manyTill anyChar (char '}')+ return $ Str $ "(" ++ result ++ ")"++ref = try (string "\\ref{") >> manyTill anyChar (char '}') >>= return . Str++strong = try (string "\\textbf{") >> manyTill inline (char '}') >>=+ return . Strong++whitespace = many1 (oneOf "~ \t") >> return Space++-- hard line break+linebreak = try (string "\\\\") >> return LineBreak++spacer = try (string "\\,") >> return (Str "")++str = many1 (noneOf specialChars) >>= return . Str++-- endline internal to paragraph+endline = try $ newline >> notFollowedBy blankline >> return Space++-- math+math = math1 <|> math2 <?> "math"++math1 = try $ do+ char '$'+ result <- many (noneOf "$")+ char '$'+ return $ Math result++math2 = try $ do+ string "\\("+ result <- many (noneOf "$")+ string "\\)"+ return $ Math result++--+-- links and images+--++url = try $ do+ string "\\url"+ url <- charsInBalanced '{' '}'+ return $ Link [Code url] (url, "")++link = try $ do+ string "\\href{"+ url <- manyTill anyChar (char '}')+ char '{'+ label <- manyTill inline (char '}') + return $ Link (normalizeSpaces label) (url, "")++image = try $ do+ ("includegraphics", _, args) <- command+ let args' = filter isArg args -- filter out options+ let src = if null args' then+ ("", "")+ else+ (stripFirstAndLast (head args'), "")+ return $ Image [Str "image"] src++footnote = try $ do+ (name, _, (contents:[])) <- command+ if ((name == "footnote") || (name == "thanks"))+ then string ""+ else fail "not a footnote or thanks command"+ let contents' = stripFirstAndLast contents+ -- parse the extracted block, which may contain various block elements:+ rest <- getInput+ setInput $ contents'+ blocks <- parseBlocks+ setInput rest+ return $ Note blocks++-- | Parse any LaTeX command and return it in a raw TeX inline element.+rawLaTeXInline :: GenParser Char ParserState Inline+rawLaTeXInline = try $ do+ (name, star, args) <- command+ state <- getState+ if ((name == "begin") || (name == "end") || (name == "item"))+ then fail "not an inline command" + else string ""+ return $ TeX ("\\" ++ name ++ star ++ concat args)+
+ Text/Pandoc/Readers/Markdown.hs view
@@ -0,0 +1,906 @@+{-+Copyright (C) 2006-7 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.Readers.Markdown+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of markdown-formatted plain text to 'Pandoc' document.+-}+module Text.Pandoc.Readers.Markdown ( + readMarkdown + ) where++import Data.List ( transpose, isPrefixOf, isSuffixOf, lookup, sortBy, findIndex )+import Data.Ord ( comparing )+import Data.Char ( isAlphaNum )+import Data.Maybe ( fromMaybe )+import Network.URI ( isURI )+import Text.Pandoc.Definition+import Text.Pandoc.Shared +import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXEnvironment )+import Text.Pandoc.Readers.HTML ( rawHtmlBlock, anyHtmlBlockTag, + anyHtmlInlineTag, anyHtmlTag,+ anyHtmlEndTag, htmlEndTag, extractTagType,+ htmlBlockElement )+import Text.Pandoc.CharacterReferences ( decodeCharacterReferences )+import Text.ParserCombinators.Parsec++-- | Read markdown from an input string and return a Pandoc document.+readMarkdown :: ParserState -> String -> Pandoc+readMarkdown state str = (readWith parseMarkdown) state (str ++ "\n\n")++--+-- Constants and data structure definitions+--++spaceChars = " \t"+bulletListMarkers = "*+-"+hruleChars = "*-_"+setextHChars = "=-"++-- treat these as potentially non-text when parsing inline:+specialChars = "\\[]*_~`<>$!^-.&'\"\8216\8217\8220\8221"++--+-- auxiliary functions+--++indentSpaces = try $ do+ state <- getState+ let tabStop = stateTabStop state+ try (count tabStop (char ' ')) <|> + (many (char ' ') >> string "\t") <?> "indentation"++nonindentSpaces = do+ state <- getState+ let tabStop = stateTabStop state+ sps <- many (char ' ')+ if length sps < tabStop + then return sps+ else unexpected "indented line"++-- | Fail unless we're at beginning of a line.+failUnlessBeginningOfLine = do+ pos <- getPosition+ if sourceColumn pos == 1 then return () else fail "not beginning of line"++-- | Fail unless we're in "smart typography" mode.+failUnlessSmart = do+ state <- getState+ if stateSmart state then return () else fail "Smart typography feature"++-- | Parse an inline Str element with a given content.+inlineString str = try $ do + (Str res) <- inline + if res == str then return res else fail $ "unexpected Str content"++-- | Parse a sequence of inline elements between a string+-- @opener@ and a string @closer@, including inlines+-- between balanced pairs of @opener@ and a @closer@.+inlinesInBalanced :: String -> String -> GenParser Char ParserState [Inline]+inlinesInBalanced opener closer = try $ do+ string opener+ result <- manyTill ( (do lookAhead (inlineString opener)+ -- because it might be a link...+ bal <- inlinesInBalanced opener closer + return $ [Str opener] ++ bal ++ [Str closer])+ <|> (count 1 inline)) + (try (string closer))+ return $ concat result++--+-- document structure+--++titleLine = try $ char '%' >> skipSpaces >> manyTill inline newline++authorsLine = try $ do + char '%'+ skipSpaces+ authors <- sepEndBy (many1 (noneOf ",;\n")) (oneOf ",;")+ newline+ return $ map (decodeCharacterReferences . removeLeadingTrailingSpace) authors++dateLine = try $ do+ char '%'+ skipSpaces+ date <- many (noneOf "\n")+ newline+ return $ decodeCharacterReferences $ removeTrailingSpace date++titleBlock = try $ do+ failIfStrict+ title <- option [] titleLine+ author <- option [] authorsLine+ date <- option "" dateLine+ optional blanklines+ return (title, author, date)++parseMarkdown = do+ -- markdown allows raw HTML+ updateState (\state -> state { stateParseRaw = True })+ startPos <- getPosition+ -- go through once just to get list of reference keys+ -- docMinusKeys is the raw document with blanks where the keys were...+ docMinusKeys <- manyTill (referenceKey <|> lineClump) eof >>= + return . concat+ setInput docMinusKeys+ setPosition startPos+ st <- getState+ -- go through again for notes unless strict...+ if stateStrict st+ then return ()+ else do docMinusNotes <- manyTill (noteBlock <|> lineClump) eof >>= + return . concat+ st <- getState+ let reversedNotes = stateNotes st+ updateState $ \st -> st { stateNotes = reverse reversedNotes }+ setInput docMinusNotes+ setPosition startPos+ -- now parse it for real...+ (title, author, date) <- option ([],[],"") titleBlock+ blocks <- parseBlocks + return $ Pandoc (Meta title author date) $ filter (/= Null) blocks++-- +-- initial pass for references and notes+--++referenceKey = try $ do+ startPos <- getPosition+ nonindentSpaces+ label <- reference+ char ':'+ skipSpaces+ optional (char '<')+ src <- many (noneOf "> \n\t")+ optional (char '>')+ tit <- option "" referenceTitle+ blanklines+ endPos <- getPosition+ let newkey = (label, (removeTrailingSpace src, tit))+ st <- getState+ let oldkeys = stateKeys st+ updateState $ \st -> st { stateKeys = newkey : oldkeys }+ -- return blanks so line count isn't affected+ return $ replicate (sourceLine endPos - sourceLine startPos) '\n'++referenceTitle = try $ do + (many1 spaceChar >> option '\n' newline) <|> newline+ skipSpaces+ tit <- (charsInBalanced '(' ')' >>= return . unwords . words)+ <|> do delim <- char '\'' <|> char '"'+ manyTill anyChar (try (char delim >> skipSpaces >>+ notFollowedBy (noneOf ")\n")))+ return $ decodeCharacterReferences tit++noteMarker = string "[^" >> manyTill (noneOf " \t\n") (char ']')++rawLine = do+ notFollowedBy blankline+ notFollowedBy' noteMarker+ contents <- many1 nonEndline+ end <- option "" (newline >> optional indentSpaces >> return "\n") + return $ contents ++ end++rawLines = many1 rawLine >>= return . concat++noteBlock = try $ do+ startPos <- getPosition+ ref <- noteMarker+ char ':'+ optional blankline+ optional indentSpaces+ raw <- sepBy rawLines (try (blankline >> indentSpaces))+ optional blanklines+ endPos <- getPosition+ -- parse the extracted text, which may contain various block elements:+ contents <- parseFromString parseBlocks $ (joinWithSep "\n" raw) ++ "\n\n"+ let newnote = (ref, contents)+ st <- getState+ let oldnotes = stateNotes st+ updateState $ \st -> st { stateNotes = newnote : oldnotes }+ -- return blanks so line count isn't affected+ return $ replicate (sourceLine endPos - sourceLine startPos) '\n'++--+-- parsing blocks+--++parseBlocks = manyTill block eof++block = choice [ header + , table+ , codeBlock+ , hrule+ , list+ , blockQuote+ , htmlBlock+ , rawLaTeXEnvironment'+ , para+ , plain+ , nullBlock ] <?> "block"++--+-- header blocks+--++header = atxHeader <|> setextHeader <?> "header"++atxHeader = try $ do+ level <- many1 (char '#') >>= return . length+ notFollowedBy (char '.' <|> char ')') -- this would be a list+ skipSpaces+ text <- manyTill inline atxClosing >>= return . normalizeSpaces+ return $ Header level text++atxClosing = try $ skipMany (char '#') >> blanklines++setextHeader = try $ do+ text <- many1Till inline newline+ underlineChar <- oneOf setextHChars+ many (char underlineChar)+ blanklines+ let level = (fromMaybe 0 $ findIndex (== underlineChar) setextHChars) + 1+ return $ Header level (normalizeSpaces text)++--+-- hrule block+--++hrule = try $ do+ skipSpaces+ start <- oneOf hruleChars+ count 2 (skipSpaces >> char start)+ skipMany (skipSpaces >> char start)+ newline+ optional blanklines+ return HorizontalRule++--+-- code blocks+--++indentedLine = indentSpaces >> manyTill anyChar newline >>= return . (++ "\n")++codeBlock = do+ contents <- many1 (indentedLine <|> + try (do b <- blanklines+ l <- indentedLine+ return $ b ++ l))+ optional blanklines+ return $ CodeBlock $ stripTrailingNewlines $ concat contents++--+-- block quotes+--++emailBlockQuoteStart = try $ nonindentSpaces >> char '>' >>~ optional (char ' ')++emailBlockQuote = try $ do+ emailBlockQuoteStart+ raw <- sepBy (many (nonEndline <|> + (try (endline >> notFollowedBy emailBlockQuoteStart >>+ return '\n'))))+ (try (newline >> emailBlockQuoteStart))+ newline <|> (eof >> return '\n')+ optional blanklines+ return raw++blockQuote = do + raw <- emailBlockQuote+ -- parse the extracted block, which may contain various block elements:+ contents <- parseFromString parseBlocks $ (joinWithSep "\n" raw) ++ "\n\n"+ return $ BlockQuote contents+ +--+-- list blocks+--++list = choice [ bulletList, orderedList, definitionList ] <?> "list"++bulletListStart = try $ do+ optional newline -- if preceded by a Plain block in a list context+ nonindentSpaces+ notFollowedBy' hrule -- because hrules start out just like lists+ oneOf bulletListMarkers+ spaceChar+ skipSpaces++anyOrderedListStart = try $ do+ optional newline -- if preceded by a Plain block in a list context+ nonindentSpaces+ notFollowedBy $ string "p." >> spaceChar >> digit -- page number+ state <- getState+ if stateStrict state+ then do many1 digit+ char '.'+ spaceChar+ return (1, DefaultStyle, DefaultDelim)+ else anyOrderedListMarker >>~ spaceChar++orderedListStart style delim = try $ do+ optional newline -- if preceded by a Plain block in a list context+ nonindentSpaces+ state <- getState+ num <- if stateStrict state+ then do many1 digit+ char '.'+ return 1+ else orderedListMarker style delim + if delim == Period && (style == UpperAlpha || (style == UpperRoman &&+ num `elem` [1, 5, 10, 50, 100, 500, 1000]))+ then char '\t' <|> (spaceChar >> spaceChar)+ else spaceChar+ skipSpaces++-- parse a line of a list item (start = parser for beginning of list item)+listLine start = try $ do+ notFollowedBy' start+ notFollowedBy blankline+ notFollowedBy' (do indentSpaces+ many (spaceChar)+ bulletListStart <|> (anyOrderedListStart >> return ()))+ line <- manyTill anyChar newline+ return $ line ++ "\n"++-- parse raw text for one list item, excluding start marker and continuations+rawListItem start = try $ do+ start+ result <- many1 (listLine start)+ blanks <- many blankline+ return $ concat result ++ blanks++-- continuation of a list item - indented and separated by blankline +-- or (in compact lists) endline.+-- note: nested lists are parsed as continuations+listContinuation start = try $ do+ lookAhead indentSpaces+ result <- many1 (listContinuationLine start)+ blanks <- many blankline+ return $ concat result ++ blanks++listContinuationLine start = try $ do+ notFollowedBy blankline+ notFollowedBy' start+ optional indentSpaces+ result <- manyTill anyChar newline+ return $ result ++ "\n"++listItem start = try $ do + first <- rawListItem start+ continuations <- many (listContinuation start)+ -- parsing with ListItemState forces markers at beginning of lines to+ -- count as list item markers, even if not separated by blank space.+ -- see definition of "endline"+ state <- getState+ let oldContext = stateParserContext state+ setState $ state {stateParserContext = ListItemState}+ -- parse the extracted block, which may contain various block elements:+ let raw = concat (first:continuations)+ contents <- parseFromString parseBlocks raw+ updateState (\st -> st {stateParserContext = oldContext})+ return contents++orderedList = try $ do+ (start, style, delim) <- lookAhead anyOrderedListStart+ items <- many1 (listItem (orderedListStart style delim))+ return $ OrderedList (start, style, delim) $ compactify items++bulletList = many1 (listItem bulletListStart) >>= + return . BulletList . compactify++-- definition lists++definitionListItem = try $ do+ notFollowedBy blankline+ notFollowedBy' indentSpaces+ -- first, see if this has any chance of being a definition list:+ lookAhead (anyLine >> char ':')+ term <- manyTill inline newline+ raw <- many1 defRawBlock+ state <- getState+ let oldContext = stateParserContext state+ -- parse the extracted block, which may contain various block elements:+ contents <- parseFromString parseBlocks $ concat raw+ updateState (\st -> st {stateParserContext = oldContext})+ return ((normalizeSpaces term), contents)++defRawBlock = try $ do+ char ':'+ state <- getState+ let tabStop = stateTabStop state+ try (count (tabStop - 1) (char ' ')) <|> (many (char ' ') >> string "\t")+ firstline <- anyLine+ rawlines <- many (notFollowedBy blankline >> indentSpaces >> anyLine)+ trailing <- option "" blanklines+ return $ firstline ++ "\n" ++ unlines rawlines ++ trailing++definitionList = do+ failIfStrict+ items <- many1 definitionListItem+ let (terms, defs) = unzip items+ let defs' = compactify defs+ let items' = zip terms defs'+ return $ DefinitionList items'++--+-- paragraph block+--++para = try $ do + result <- many1 inline+ newline+ blanklines <|> do st <- getState+ if stateStrict st+ then lookAhead (blockQuote <|> header) >> return ""+ else pzero+ return $ Para $ normalizeSpaces result++plain = many1 inline >>= return . Plain . normalizeSpaces ++-- +-- raw html+--++htmlElement = strictHtmlBlock <|> htmlBlockElement <?> "html element"++htmlBlock = do+ st <- getState+ if stateStrict st+ then try $ do failUnlessBeginningOfLine+ first <- htmlElement+ finalSpace <- many (oneOf spaceChars)+ finalNewlines <- many newline+ return $ RawHtml $ first ++ finalSpace ++ finalNewlines+ else rawHtmlBlocks++-- True if tag is self-closing+isSelfClosing tag = + isSuffixOf "/>" $ filter (not . (`elem` " \n\t")) tag++strictHtmlBlock = try $ do+ tag <- anyHtmlBlockTag + let tag' = extractTagType tag+ if isSelfClosing tag || tag' == "hr" + then return tag+ else do contents <- many (notFollowedBy' (htmlEndTag tag') >> + (htmlElement <|> (count 1 anyChar)))+ end <- htmlEndTag tag'+ return $ tag ++ concat contents ++ end++rawHtmlBlocks = do+ htmlBlocks <- many1 rawHtmlBlock + let combined = concatMap (\(RawHtml str) -> str) htmlBlocks+ let combined' = if not (null combined) && last combined == '\n'+ then init combined -- strip extra newline + else combined + return $ RawHtml combined'++--+-- LaTeX+--++rawLaTeXEnvironment' = failIfStrict >> rawLaTeXEnvironment++--+-- Tables+-- ++-- Parse a dashed line with optional trailing spaces; return its length+-- and the length including trailing space.+dashedLine ch = do+ dashes <- many1 (char ch)+ sp <- many spaceChar+ return $ (length dashes, length $ dashes ++ sp)++-- Parse a table header with dashed lines of '-' preceded by +-- one line of text.+simpleTableHeader = try $ do+ rawContent <- anyLine+ initSp <- nonindentSpaces+ dashes <- many1 (dashedLine '-')+ newline+ let (lengths, lines) = unzip dashes+ let indices = scanl (+) (length initSp) lines+ let rawHeads = tail $ splitByIndices (init indices) rawContent+ let aligns = zipWith alignType (map (\a -> [a]) rawHeads) lengths+ return (rawHeads, aligns, indices)++-- Parse a table footer - dashed lines followed by blank line.+tableFooter = try $ nonindentSpaces >> many1 (dashedLine '-') >> blanklines++-- Parse a table separator - dashed line.+tableSep = try $ nonindentSpaces >> many1 (dashedLine '-') >> string "\n"++-- Parse a raw line and split it into chunks by indices.+rawTableLine indices = do+ notFollowedBy' (blanklines <|> tableFooter)+ line <- many1Till anyChar newline+ return $ map removeLeadingTrailingSpace $ tail $ + splitByIndices (init indices) line++-- Parse a table line and return a list of lists of blocks (columns).+tableLine indices = rawTableLine indices >>= mapM (parseFromString (many plain))++-- Parse a multiline table row and return a list of blocks (columns).+multilineRow indices = do+ colLines <- many1 (rawTableLine indices)+ optional blanklines+ let cols = map unlines $ transpose colLines+ mapM (parseFromString (many plain)) cols++-- Calculate relative widths of table columns, based on indices+widthsFromIndices :: Int -- Number of columns on terminal+ -> [Int] -- Indices+ -> [Float] -- Fractional relative sizes of columns+widthsFromIndices _ [] = [] +widthsFromIndices numColumns indices = + let lengths = zipWith (-) indices (0:indices)+ totLength = sum lengths+ quotient = if totLength > numColumns+ then fromIntegral totLength+ else fromIntegral numColumns+ fracs = map (\l -> (fromIntegral l) / quotient) lengths in+ tail fracs++-- Parses a table caption: inlines beginning with 'Table:'+-- and followed by blank lines.+tableCaption = try $ do+ nonindentSpaces+ string "Table:"+ result <- many1 inline+ blanklines+ return $ normalizeSpaces result++-- Parse a table using 'headerParser', 'lineParser', and 'footerParser'.+tableWith headerParser lineParser footerParser = try $ do+ (rawHeads, aligns, indices) <- headerParser+ lines <- many1Till (lineParser indices) footerParser+ caption <- option [] tableCaption+ heads <- mapM (parseFromString (many plain)) rawHeads+ state <- getState+ let numColumns = stateColumns state+ let widths = widthsFromIndices numColumns indices+ return $ Table caption aligns widths heads lines++-- Parse a simple table with '---' header and one line per row.+simpleTable = tableWith simpleTableHeader tableLine blanklines++-- Parse a multiline table: starts with row of '-' on top, then header+-- (which may be multiline), then the rows,+-- which may be multiline, separated by blank lines, and+-- ending with a footer (dashed line followed by blank line).+multilineTable = tableWith multilineTableHeader multilineRow tableFooter++multilineTableHeader = try $ do+ tableSep + rawContent <- many1 (notFollowedBy' tableSep >> many1Till anyChar newline)+ initSp <- nonindentSpaces+ dashes <- many1 (dashedLine '-')+ newline+ let (lengths, lines) = unzip dashes+ let indices = scanl (+) (length initSp) lines+ let rawHeadsList = transpose $ map + (\ln -> tail $ splitByIndices (init indices) ln)+ rawContent+ let rawHeads = map (joinWithSep " ") rawHeadsList+ let aligns = zipWith alignType rawHeadsList lengths+ return ((map removeLeadingTrailingSpace rawHeads), aligns, indices)++-- Returns an alignment type for a table, based on a list of strings+-- (the rows of the column header) and a number (the length of the+-- dashed line under the rows.+alignType :: [String] -> Int -> Alignment+alignType [] len = AlignDefault+alignType strLst len =+ let str = head $ sortBy (comparing length) $ + map removeTrailingSpace strLst+ leftSpace = if null str then False else (str !! 0) `elem` " \t"+ rightSpace = length str < len || (str !! (len - 1)) `elem` " \t"+ in case (leftSpace, rightSpace) of+ (True, False) -> AlignRight+ (False, True) -> AlignLeft+ (True, True) -> AlignCenter+ (False, False) -> AlignDefault++table = failIfStrict >> (simpleTable <|> multilineTable) <?> "table"++-- +-- inline+--++inline = choice [ str+ , smartPunctuation+ , whitespace+ , endline+ , code+ , charRef+ , strong+ , emph+ , note+ , inlineNote+ , link+ , image+ , math+ , strikeout+ , superscript+ , subscript+ , autoLink+ , rawHtmlInline'+ , rawLaTeXInline'+ , escapedChar+ , symbol+ , ltSign ] <?> "inline"++escapedChar = do+ char '\\'+ state <- getState+ result <- option '\\' $ if stateStrict state + then oneOf "\\`*_{}[]()>#+-.!~"+ else satisfy (not . isAlphaNum)+ return $ Str [result]++ltSign = do+ st <- getState+ if stateStrict st+ then char '<'+ else notFollowedBy' rawHtmlBlocks >> char '<' -- unless it starts html+ return $ Str ['<']++specialCharsMinusLt = filter (/= '<') specialChars++symbol = do + result <- oneOf specialCharsMinusLt+ return $ Str [result]++-- parses inline code, between n `s and n `s+code = try $ do + starts <- many1 (char '`')+ skipSpaces+ result <- many1Till (many1 (noneOf "`\n") <|> many1 (char '`') <|>+ (char '\n' >> return " ")) + (try (skipSpaces >> count (length starts) (char '`') >> + notFollowedBy (char '`')))+ return $ Code $ removeLeadingTrailingSpace $ concat result++mathWord = many1 ((noneOf " \t\n\\$") <|>+ (try (char '\\') >>~ notFollowedBy (char '$')))++math = try $ do+ failIfStrict+ char '$'+ notFollowedBy space+ words <- sepBy1 mathWord (many1 space)+ char '$'+ return $ Math $ joinWithSep " " words++emph = ((enclosed (char '*') (char '*') inline) <|>+ (enclosed (char '_') (char '_' >> notFollowedBy alphaNum) inline)) >>= + return . Emph . normalizeSpaces++strong = ((enclosed (string "**") (try $ string "**") inline) <|> + (enclosed (string "__") (try $ string "__") inline)) >>=+ return . Strong . normalizeSpaces++strikeout = failIfStrict >> enclosed (string "~~") (try $ string "~~") inline >>=+ return . Strikeout . normalizeSpaces++superscript = failIfStrict >> enclosed (char '^') (char '^') + (notFollowedBy' whitespace >> inline) >>= -- may not contain Space+ return . Superscript++subscript = failIfStrict >> enclosed (char '~') (char '~')+ (notFollowedBy' whitespace >> inline) >>= -- may not contain Space+ return . Subscript ++smartPunctuation = failUnlessSmart >> + choice [ quoted, apostrophe, dash, ellipses ]++apostrophe = (char '\'' <|> char '\8217') >> return Apostrophe++quoted = doubleQuoted <|> singleQuoted ++withQuoteContext context parser = do+ oldState <- getState+ let oldQuoteContext = stateQuoteContext oldState+ setState oldState { stateQuoteContext = context }+ result <- parser+ newState <- getState+ setState newState { stateQuoteContext = oldQuoteContext }+ return result++singleQuoted = try $ do+ singleQuoteStart+ withQuoteContext InSingleQuote $ many1Till inline singleQuoteEnd >>=+ return . Quoted SingleQuote . normalizeSpaces++doubleQuoted = try $ do + doubleQuoteStart+ withQuoteContext InDoubleQuote $ many1Till inline doubleQuoteEnd >>=+ return . Quoted DoubleQuote . normalizeSpaces++failIfInQuoteContext context = do+ st <- getState+ if stateQuoteContext st == context+ then fail "already inside quotes"+ else return ()++singleQuoteStart = do + failIfInQuoteContext InSingleQuote+ char '\8216' <|> + (try $ do char '\'' + notFollowedBy (oneOf ")!],.;:-? \t\n")+ notFollowedBy (try (oneOfStrings ["s","t","m","ve","ll","re"] >>+ satisfy (not . isAlphaNum))) + -- possess/contraction+ return '\'')++singleQuoteEnd = try $ do+ char '\8217' <|> char '\''+ notFollowedBy alphaNum+ return '\''++doubleQuoteStart = do+ failIfInQuoteContext InDoubleQuote+ char '\8220' <|>+ (try $ do char '"'+ notFollowedBy (oneOf " \t\n")+ return '"')++doubleQuoteEnd = char '\8221' <|> char '"'++ellipses = oneOfStrings ["...", " . . . ", ". . .", " . . ."] >> return Ellipses++dash = enDash <|> emDash++enDash = try $ char '-' >> notFollowedBy (noneOf "0123456789") >> return EnDash++emDash = try $ skipSpaces >> oneOfStrings ["---", "--"] >>+ skipSpaces >> return EmDash++whitespace = do+ sps <- many1 (oneOf spaceChars)+ if length sps >= 2+ then option Space (endline >> return LineBreak)+ else return Space <?> "whitespace"++nonEndline = satisfy (/='\n')++strChar = noneOf (specialChars ++ spaceChars ++ "\n")++str = many1 strChar >>= return . Str++-- an endline character that can be treated as a space, not a structural break+endline = try $ do+ newline+ notFollowedBy blankline+ st <- getState+ if stateStrict st + then do notFollowedBy emailBlockQuoteStart+ notFollowedBy (char '#') -- atx header+ else return () + -- parse potential list-starts differently if in a list:+ if stateParserContext st == ListItemState+ then notFollowedBy' (bulletListStart <|> + (anyOrderedListStart >> return ()))+ else return ()+ return Space++--+-- links+--++-- a reference label for a link+reference = notFollowedBy' (string "[^") >> -- footnote reference+ inlinesInBalanced "[" "]" >>= (return . normalizeSpaces)++-- source for a link, with optional title+source = try $ do + char '('+ optional (char '<')+ src <- many (noneOf ")> \t\n")+ optional (char '>')+ tit <- option "" linkTitle+ skipSpaces+ char ')'+ return (removeTrailingSpace src, tit)++linkTitle = try $ do + (many1 spaceChar >> option '\n' newline) <|> newline+ skipSpaces+ delim <- char '\'' <|> char '"'+ tit <- manyTill anyChar (try (char delim >> skipSpaces >>+ notFollowedBy (noneOf ")\n")))+ return $ decodeCharacterReferences tit++link = try $ do+ label <- reference+ src <- source <|> referenceLink label+ return $ Link label src++-- a link like [this][ref] or [this][] or [this]+referenceLink label = do+ ref <- option [] (try (optional (char ' ') >> + optional (newline >> skipSpaces) >> reference))+ let ref' = if null ref then label else ref+ state <- getState+ case lookupKeySrc (stateKeys state) ref' of+ Nothing -> fail "no corresponding key" + Just target -> return target ++emailAddress = try $ do+ name <- many1 (alphaNum <|> char '+')+ char '@'+ first <- many1 alphaNum+ rest <- many1 (char '.' >> many1 alphaNum)+ return $ "mailto:" ++ name ++ "@" ++ joinWithSep "." (first:rest)++uri = try $ do+ str <- many1 (noneOf "\n\t >")+ if isURI str+ then return str+ else fail "not a URI"++autoLink = try $ do+ char '<'+ src <- uri <|> emailAddress+ char '>'+ let src' = if "mailto:" `isPrefixOf` src+ then drop 7 src+ else src + st <- getState+ return $ if stateStrict st+ then Link [Str src'] (src, "")+ else Link [Code src'] (src, "")++image = try $ do+ char '!'+ (Link label src) <- link+ return $ Image label src++note = try $ do+ failIfStrict+ ref <- noteMarker+ state <- getState+ let notes = stateNotes state+ case lookup ref notes of+ Nothing -> fail "note not found"+ Just contents -> return $ Note contents++inlineNote = try $ do+ failIfStrict+ char '^'+ contents <- inlinesInBalanced "[" "]"+ return $ Note [Para contents]++rawLaTeXInline' = failIfStrict >> rawLaTeXInline++rawHtmlInline' = do+ st <- getState+ result <- choice $ if stateStrict st+ then [htmlBlockElement, anyHtmlTag, anyHtmlEndTag] + else [htmlBlockElement, anyHtmlInlineTag]+ return $ HtmlInline result+
+ Text/Pandoc/Readers/RST.hs view
@@ -0,0 +1,640 @@+{-+Copyright (C) 2006-7 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.Readers.RST + Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion from reStructuredText to 'Pandoc' document.+-}+module Text.Pandoc.Readers.RST ( + readRST+ ) where+import Text.Pandoc.Definition+import Text.Pandoc.Shared +import Text.ParserCombinators.Parsec+import Data.List ( findIndex, delete )++-- | Parse reStructuredText string and return Pandoc document.+readRST :: ParserState -> String -> Pandoc+readRST state str = (readWith parseRST) state (str ++ "\n\n")++--+-- Constants and data structure definitions+---++bulletListMarkers = "*+-"+underlineChars = "!\"#$&'()*+,-./:;<=>?@[\\]^_`{|}~"++-- treat these as potentially non-text when parsing inline:+specialChars = "\\`|*_<>$:[-"++--+-- parsing documents+--++isAnonKey (ref, src) = ref == [Str "_"]++isHeader :: Int -> Block -> Bool+isHeader n (Header x _) = x == n+isHeader _ _ = False++-- | Promote all headers in a list of blocks. (Part of+-- title transformation for RST.)+promoteHeaders :: Int -> [Block] -> [Block]+promoteHeaders num ((Header level text):rest) = + (Header (level - num) text):(promoteHeaders num rest)+promoteHeaders num (other:rest) = other:(promoteHeaders num rest)+promoteHeaders num [] = []++-- | If list of blocks starts with a header (or a header and subheader)+-- of level that are not found elsewhere, return it as a title and+-- promote all the other headers. +titleTransform :: [Block] -- ^ list of blocks+ -> ([Block], [Inline]) -- ^ modified list of blocks, title+titleTransform ((Header 1 head1):(Header 2 head2):rest) = -- title subtitle+ if (any (isHeader 1) rest) || (any (isHeader 2) rest)+ then ((Header 1 head1):(Header 2 head2):rest, [])+ else ((promoteHeaders 2 rest), head1 ++ [Str ":", Space] ++ head2)+titleTransform ((Header 1 head1):rest) = -- title, no subtitle+ if (any (isHeader 1) rest)+ then ((Header 1 head1):rest, [])+ else ((promoteHeaders 1 rest), head1)+titleTransform blocks = (blocks, [])++parseRST = do+ startPos <- getPosition+ -- go through once just to get list of reference keys+ -- docMinusKeys is the raw document with blanks where the keys were...+ docMinusKeys <- manyTill (referenceKey <|> lineClump) eof >>= return . concat+ setInput docMinusKeys+ setPosition startPos+ st <- getState+ let reversedKeys = stateKeys st+ updateState $ \st -> st { stateKeys = reverse reversedKeys }+ -- now parse it for real...+ blocks <- parseBlocks + let blocks' = filter (/= Null) blocks+ state <- getState+ let (blocks'', title) = if stateStandalone state+ then titleTransform blocks'+ else (blocks', [])+ let authors = stateAuthors state+ let date = stateDate state+ let title' = if (null title) then (stateTitle state) else title+ return $ Pandoc (Meta title' authors date) blocks''++--+-- parsing blocks+--++parseBlocks = manyTill block eof++block = choice [ codeBlock+ , rawHtmlBlock+ , rawLaTeXBlock+ , fieldList+ , blockQuote+ , imageBlock+ , unknownDirective+ , header+ , hrule+ , list+ , lineBlock+ , para+ , plain+ , nullBlock ] <?> "block"++--+-- field list+--++fieldListItem indent = try $ do+ string indent+ char ':'+ name <- many1 alphaNum+ string ": "+ skipSpaces+ first <- manyTill anyChar newline+ rest <- option "" $ try $ lookAhead (string indent >> oneOf " \t") >> + indentedBlock+ return (name, joinWithSep " " (first:(lines rest)))++fieldList = try $ do+ indent <- lookAhead $ many (oneOf " \t")+ items <- many1 $ fieldListItem indent+ blanklines+ let authors = case lookup "Authors" items of+ Just auth -> [auth]+ Nothing -> map snd (filter (\(x,y) -> x == "Author") items)+ if null authors + then return () + else updateState $ \st -> st {stateAuthors = authors}+ case (lookup "Date" items) of+ Just dat -> updateState $ \st -> st {stateDate = dat}+ Nothing -> return ()+ case (lookup "Title" items) of+ Just tit -> parseFromString (many inline) tit >>=+ \t -> updateState $ \st -> st {stateTitle = t}+ Nothing -> return ()+ let remaining = filter (\(x,y) -> (x /= "Authors") && (x /= "Author") && + (x /= "Date") && (x /= "Title")) items+ if null remaining+ then return Null+ else do terms <- mapM (return . (:[]) . Str . fst) remaining+ defs <- mapM (parseFromString (many block) . snd) + remaining+ return $ DefinitionList $ zip terms defs++--+-- line block+--++lineBlockLine = try $ do+ string "| "+ white <- many (oneOf " \t")+ line <- manyTill inline newline+ return $ (if null white then [] else [Str white]) ++ line ++ [LineBreak]++lineBlock = try $ do+ lines <- many1 lineBlockLine+ blanklines+ return $ Para (concat lines)++--+-- paragraph block+--++para = paraBeforeCodeBlock <|> paraNormal <?> "paragraph"++codeBlockStart = string "::" >> blankline >> blankline++-- paragraph that ends in a :: starting a code block+paraBeforeCodeBlock = try $ do+ result <- many1 (notFollowedBy' codeBlockStart >> inline)+ lookAhead (string "::")+ return $ Para $ if last result == Space+ then normalizeSpaces result+ else (normalizeSpaces result) ++ [Str ":"]++-- regular paragraph+paraNormal = try $ do + result <- many1 inline+ newline+ blanklines+ return $ Para $ normalizeSpaces result++plain = many1 inline >>= return . Plain . normalizeSpaces ++--+-- image block+--++imageBlock = try $ do+ string ".. image:: "+ src <- manyTill anyChar newline+ fields <- option [] $ do indent <- lookAhead $ many (oneOf " /t")+ many1 $ fieldListItem indent+ optional blanklines+ case lookup "alt" fields of+ Just alt -> return $ Plain [Image [Str alt] (src, alt)]+ Nothing -> return $ Plain [Image [Str "image"] (src, "")]+--+-- header blocks+--++header = doubleHeader <|> singleHeader <?> "header"++-- a header with lines on top and bottom+doubleHeader = try $ do+ c <- oneOf underlineChars+ rest <- many (char c) -- the top line+ let lenTop = length (c:rest)+ skipSpaces+ newline+ txt <- many1 (notFollowedBy blankline >> inline)+ pos <- getPosition+ let len = (sourceColumn pos) - 1+ if (len > lenTop) then fail "title longer than border" else return ()+ blankline -- spaces and newline+ count lenTop (char c) -- the bottom line+ blanklines+ -- check to see if we've had this kind of header before. + -- if so, get appropriate level. if not, add to list.+ state <- getState+ let headerTable = stateHeaderTable state+ let (headerTable',level) = case findIndex (== DoubleHeader c) headerTable of+ Just ind -> (headerTable, ind + 1)+ Nothing -> (headerTable ++ [DoubleHeader c], (length headerTable) + 1)+ setState (state { stateHeaderTable = headerTable' })+ return $ Header level (normalizeSpaces txt)++-- a header with line on the bottom only+singleHeader = try $ do + notFollowedBy' whitespace+ txt <- many1 (do {notFollowedBy blankline; inline})+ pos <- getPosition+ let len = (sourceColumn pos) - 1+ blankline+ c <- oneOf underlineChars+ rest <- count (len - 1) (char c)+ many (char c)+ blanklines+ state <- getState+ let headerTable = stateHeaderTable state+ let (headerTable',level) = case findIndex (== SingleHeader c) headerTable of+ Just ind -> (headerTable, ind + 1)+ Nothing -> (headerTable ++ [SingleHeader c], (length headerTable) + 1)+ setState (state { stateHeaderTable = headerTable' })+ return $ Header level (normalizeSpaces txt)++--+-- hrule block+--++hrule = try $ do+ chr <- oneOf underlineChars+ count 3 (char chr)+ skipMany (char chr)+ blankline+ blanklines+ return HorizontalRule++--+-- code blocks+--++-- read a line indented by a given string+indentedLine indents = try $ do+ string indents+ result <- manyTill anyChar newline+ return $ result ++ "\n"++-- two or more indented lines, possibly separated by blank lines.+-- any amount of indentation will work.+indentedBlock = do + indents <- lookAhead $ many1 (oneOf " \t")+ lns <- many $ choice $ [ indentedLine indents,+ try $ do b <- blanklines+ l <- indentedLine indents+ return (b ++ l) ]+ optional blanklines + return $ concat lns++codeBlock = try $ do+ codeBlockStart+ result <- indentedBlock+ return $ CodeBlock $ stripTrailingNewlines result++--+-- raw html+--++rawHtmlBlock = try $ string ".. raw:: html" >> blanklines >>+ indentedBlock >>= return . RawHtml++--+-- raw latex+--++rawLaTeXBlock = try $ do+ string ".. raw:: latex"+ blanklines+ result <- indentedBlock+ return $ Para [(TeX result)]++--+-- block quotes+--++blockQuote = do+ raw <- indentedBlock+ -- parse the extracted block, which may contain various block elements:+ contents <- parseFromString parseBlocks $ raw ++ "\n\n"+ return $ BlockQuote contents++--+-- list blocks+--++list = choice [ bulletList, orderedList, definitionList ] <?> "list"++definitionListItem = try $ do+ term <- many1Till inline endline+ raw <- indentedBlock+ -- parse the extracted block, which may contain various block elements:+ contents <- parseFromString parseBlocks $ raw ++ "\n\n"+ return (normalizeSpaces term, contents)++definitionList = many1 definitionListItem >>= return . DefinitionList++-- parses bullet list start and returns its length (inc. following whitespace)+bulletListStart = try $ do+ notFollowedBy' hrule -- because hrules start out just like lists+ marker <- oneOf bulletListMarkers+ white <- many1 spaceChar+ return $ length (marker:white)++-- parses ordered list start and returns its length (inc following whitespace)+orderedListStart style delim = try $ do+ (_, markerLen) <- withHorizDisplacement (orderedListMarker style delim)+ white <- many1 spaceChar+ return $ markerLen + length white++-- parse a line of a list item+listLine markerLength = try $ do+ notFollowedBy blankline+ indentWith markerLength+ line <- manyTill anyChar newline+ return $ line ++ "\n"++-- indent by specified number of spaces (or equiv. tabs)+indentWith num = do+ state <- getState+ let tabStop = stateTabStop state+ if (num < tabStop)+ then count num (char ' ')+ else choice [ try (count num (char ' ')), + (try (char '\t' >> count (num - tabStop) (char ' '))) ] ++-- parse raw text for one list item, excluding start marker and continuations+rawListItem start = do+ markerLength <- start+ firstLine <- manyTill anyChar newline+ restLines <- many (listLine markerLength)+ return (markerLength, (firstLine ++ "\n" ++ (concat restLines)))++-- continuation of a list item - indented and separated by blankline or +-- (in compact lists) endline. +-- Note: nested lists are parsed as continuations.+listContinuation markerLength = try $ do+ blanks <- many1 blankline+ result <- many1 (listLine markerLength)+ return $ blanks ++ concat result++listItem start = try $ do + (markerLength, first) <- rawListItem start+ rest <- many (listContinuation markerLength)+ blanks <- choice [ try (many blankline >>~ lookAhead start),+ many1 blankline ] -- whole list must end with blank.+ -- parsing with ListItemState forces markers at beginning of lines to+ -- count as list item markers, even if not separated by blank space.+ -- see definition of "endline"+ state <- getState+ let oldContext = stateParserContext state+ setState $ state {stateParserContext = ListItemState}+ -- parse the extracted block, which may itself contain block elements+ parsed <- parseFromString parseBlocks $ concat (first:rest) ++ blanks+ updateState (\st -> st {stateParserContext = oldContext})+ return parsed++orderedList = do+ (start, style, delim) <- lookAhead (anyOrderedListMarker >>~ spaceChar)+ items <- many1 (listItem (orderedListStart style delim))+ let items' = compactify items+ return $ OrderedList (start, style, delim) items'++bulletList = many1 (listItem bulletListStart) >>= + return . BulletList . compactify++--+-- unknown directive (e.g. comment)+--++unknownDirective = try $ do+ string ".. "+ manyTill anyChar newline+ many (string " :" >> many1 (noneOf "\n:") >> char ':' >>+ many1 (noneOf "\n") >> newline)+ optional blanklines+ return Null++-- +-- reference key+--++referenceKey = do+ startPos <- getPosition+ key <- choice [imageKey, anonymousKey, regularKeyQuoted, regularKey]+ st <- getState+ let oldkeys = stateKeys st+ updateState $ \st -> st { stateKeys = key : oldkeys }+ optional blanklines+ endPos <- getPosition+ -- return enough blanks to replace key+ return $ replicate (sourceLine endPos - sourceLine startPos) '\n'++targetURI = do+ skipSpaces+ optional newline+ contents <- many1 (try (many spaceChar >> newline >> + many1 spaceChar >> noneOf " \t\n") <|> noneOf "\n")+ blanklines+ return contents++imageKey = try $ do+ string ".. |"+ ref <- manyTill inline (char '|')+ skipSpaces+ string "image::"+ src <- targetURI+ return (normalizeSpaces ref, (removeLeadingTrailingSpace src, ""))++anonymousKey = try $ do+ oneOfStrings [".. __:", "__"]+ src <- targetURI+ state <- getState+ return ([Str "_"], (removeLeadingTrailingSpace src, ""))++regularKeyQuoted = try $ do+ string ".. _`"+ ref <- manyTill inline (char '`')+ char ':'+ src <- targetURI+ return (normalizeSpaces ref, (removeLeadingTrailingSpace src, ""))++regularKey = try $ do+ string ".. _"+ ref <- manyTill inline (char ':')+ src <- targetURI+ return (normalizeSpaces ref, (removeLeadingTrailingSpace src, ""))++ -- + -- inline+ --++inline = choice [ link+ , str+ , whitespace+ , endline+ , strong+ , emph+ , code+ , image+ , hyphens+ , superscript+ , subscript+ , escapedChar+ , symbol ] <?> "inline"++hyphens = do+ result <- many1 (char '-')+ option Space endline + -- don't want to treat endline after hyphen or dash as a space+ return $ Str result++escapedChar = escaped anyChar++symbol = do + result <- oneOf specialChars+ return $ Str [result]++-- parses inline code, between codeStart and codeEnd+code = try $ do + string "``"+ result <- manyTill anyChar (try (string "``"))+ return $ Code $ removeLeadingTrailingSpace $ joinWithSep " " $ lines result++emph = enclosed (char '*') (char '*') inline >>= + return . Emph . normalizeSpaces++strong = enclosed (string "**") (try $ string "**") inline >>= + return . Strong . normalizeSpaces++interpreted role = try $ do+ optional $ try $ string "\\ "+ result <- enclosed (string $ ":" ++ role ++ ":`") (char '`') anyChar+ nextChar <- lookAhead anyChar+ try (string "\\ ") <|> lookAhead (count 1 $ oneOf " \t\n") <|> (eof >> return "")+ return [Str result]++superscript = interpreted "sup" >>= (return . Superscript)++subscript = interpreted "sub" >>= (return . Subscript)++whitespace = many1 spaceChar >> return Space <?> "whitespace"++str = notFollowedBy' oneWordReference >> + many1 (noneOf (specialChars ++ "\t\n ")) >>= return . Str++-- an endline character that can be treated as a space, not a structural break+endline = try $ do+ newline+ notFollowedBy blankline+ -- parse potential list-starts at beginning of line differently in a list:+ st <- getState+ if (stateParserContext st) == ListItemState+ then notFollowedBy (anyOrderedListMarker >> spaceChar) >>+ notFollowedBy' bulletListStart+ else return ()+ return Space++--+-- links+--++link = choice [explicitLink, referenceLink, autoLink] <?> "link"++explicitLink = try $ do+ char '`'+ notFollowedBy (char '`') -- `` is marks start of inline code+ label <- manyTill inline (try (do {spaces; char '<'}))+ src <- manyTill (noneOf ">\n ") (char '>')+ skipSpaces+ string "`_"+ return $ Link (normalizeSpaces label) (removeLeadingTrailingSpace src, "")++reference = try $ do+ char '`'+ notFollowedBy (char '`')+ label <- many1Till inline (char '`') + char '_'+ return label++oneWordReference = do+ raw <- many1 alphaNum+ char '_'+ notFollowedBy alphaNum -- because this_is_not a link+ return [Str raw]++referenceLink = try $ do+ label <- reference <|> oneWordReference+ key <- option label (do{char '_'; return [Str "_"]}) -- anonymous link+ state <- getState+ let keyTable = stateKeys state+ src <- case lookupKeySrc keyTable key of+ Nothing -> fail "no corresponding key"+ Just target -> return target+ -- if anonymous link, remove first anon key so it won't be used again+ let keyTable' = if (key == [Str "_"]) -- anonymous link? + then delete ([Str "_"], src) keyTable -- remove first anon key + else keyTable + setState $ state { stateKeys = keyTable' }+ return $ Link (normalizeSpaces label) src ++uriScheme = oneOfStrings [ "http://", "https://", "ftp://", "file://", + "mailto:", "news:", "telnet:" ]++uri = try $ do+ scheme <- uriScheme+ identifier <- many1 (noneOf " \t\n")+ return $ scheme ++ identifier++autoURI = do+ src <- uri+ return $ Link [Str src] (src, "")++emailChar = alphaNum <|> oneOf "-+_."++emailAddress = try $ do+ firstLetter <- alphaNum+ restAddr <- many emailChar+ let addr = firstLetter:restAddr+ char '@'+ dom <- domain+ return $ addr ++ '@':dom++domainChar = alphaNum <|> char '-'++domain = do+ first <- many1 domainChar+ dom <- many1 (try (do{ char '.'; many1 domainChar }))+ return $ joinWithSep "." (first:dom)++autoEmail = do+ src <- emailAddress+ return $ Link [Str src] ("mailto:" ++ src, "")++autoLink = autoURI <|> autoEmail++-- For now, we assume that all substitution references are for images.+image = try $ do+ char '|'+ ref <- manyTill inline (char '|')+ state <- getState+ let keyTable = stateKeys state+ src <- case lookupKeySrc keyTable ref of+ Nothing -> fail "no corresponding key"+ Just target -> return target+ return $ Image (normalizeSpaces ref) src+
+ Text/Pandoc/Readers/TeXMath.hs view
@@ -0,0 +1,222 @@+{-+Copyright (C) 2007 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.Readers.TeXMath+ Copyright : Copyright (C) 2007 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of TeX math to a list of 'Pandoc' inline elements.+-}+module Text.Pandoc.Readers.TeXMath ( + readTeXMath + ) where++import Text.ParserCombinators.Parsec+import Text.Pandoc.UTF8+import Text.Pandoc.Definition+import Text.Pandoc.Shared++-- | Converts a string of raw TeX math to a list of 'Pandoc' inlines. +readTeXMath :: String -> [Inline]+readTeXMath inp = case parse teXMath ("formula: " ++ inp) inp of+ Left err -> [Str inp] -- if unparseable, just include original+ Right res -> res++teXMath = manyTill mathPart eof >>= return . concat++mathPart = whitespace <|> superscript <|> subscript <|> symbol <|> + argument <|> digits <|> letters <|> misc++whitespace = many1 space >> return []++symbol = try $ do+ char '\\'+ res <- many1 letter+ case lookup res teXsymbols of+ Just m -> return [Str m]+ Nothing -> return [Str $ "\\" ++ res]++argument = try $ do+ char '{'+ res <- many mathPart+ char '}'+ return $ if null res + then [Str " "]+ else [Str "{"] ++ concat res ++ [Str "}"]++digits = do+ res <- many1 digit+ return [Str res]++letters = do+ res <- many1 letter+ return [Emph [Str res]]++misc = do+ res <- noneOf "}"+ return [Str [res]] ++scriptArg = try $ do+ (try (do{char '{'; r <- many mathPart; char '}'; return $ concat r}))+ <|> symbol+ <|> (do{c <- (letter <|> digit); return [Str [c]]})+ +superscript = try $ do+ char '^'+ arg <- scriptArg+ return [Superscript arg]++subscript = try $ do+ char '_'+ arg <- scriptArg+ return [Subscript arg]+ +withThinSpace str = "\x2009" ++ str ++ "\x2009"++teXsymbols = + [("alpha","\x3B1")+ ,("beta", "\x3B2")+ ,("chi", "\x3C7")+ ,("delta", "\x3B4")+ ,("Delta", "\x394")+ ,("epsilon", "\x3B5")+ ,("varepsilon", "\x25B")+ ,("eta", "\x3B7")+ ,("gamma", "\x3B3")+ ,("Gamma", "\x393")+ ,("iota", "\x3B9")+ ,("kappa", "\x3BA")+ ,("lambda", "\x3BB")+ ,("Lambda", "\x39B")+ ,("mu", "\x3BC")+ ,("nu", "\x3BD")+ ,("omega", "\x3C9")+ ,("Omega", "\x3A9")+ ,("phi", "\x3C6")+ ,("varphi", "\x3D5")+ ,("Phi", "\x3A6")+ ,("pi", "\x3C0")+ ,("Pi", "\x3A0")+ ,("psi", "\x3C8")+ ,("Psi", "\x3A8")+ ,("rho", "\x3C1")+ ,("sigma", "\x3C3")+ ,("Sigma", "\x3A3")+ ,("tau", "\x3C4")+ ,("theta", "\x3B8")+ ,("vartheta", "\x3D1")+ ,("Theta", "\x398")+ ,("upsilon", "\x3C5")+ ,("xi", "\x3BE")+ ,("Xi", "\x39E")+ ,("zeta", "\x3B6")+ ,("ne", "\x2260")+ ,("lt", withThinSpace "<")+ ,("le", withThinSpace "\x2264")+ ,("leq", withThinSpace "\x2264")+ ,("ge", withThinSpace "\x2265")+ ,("geq", withThinSpace "\x2265")+ ,("prec", withThinSpace "\x227A")+ ,("succ", withThinSpace "\x227B")+ ,("preceq", withThinSpace "\x2AAF")+ ,("succeq", withThinSpace "\x2AB0")+ ,("in", withThinSpace "\x2208")+ ,("notin", withThinSpace "\x2209")+ ,("subset", withThinSpace "\x2282")+ ,("supset", withThinSpace "\x2283")+ ,("subseteq", withThinSpace "\x2286")+ ,("supseteq", withThinSpace "\x2287")+ ,("equiv", withThinSpace "\x2261")+ ,("cong", withThinSpace "\x2245")+ ,("approx", withThinSpace "\x2248")+ ,("propto", withThinSpace "\x221D")+ ,("cdot", withThinSpace "\x22C5")+ ,("star", withThinSpace "\x22C6")+ ,("backslash", "\\")+ ,("times", withThinSpace "\x00D7")+ ,("divide", withThinSpace "\x00F7")+ ,("circ", withThinSpace "\x2218")+ ,("oplus", withThinSpace "\x2295")+ ,("otimes", withThinSpace "\x2297")+ ,("odot", withThinSpace "\x2299")+ ,("sum", "\x2211")+ ,("prod", "\x220F")+ ,("wedge", withThinSpace "\x2227")+ ,("bigwedge", withThinSpace "\x22C0")+ ,("vee", withThinSpace "\x2228")+ ,("bigvee", withThinSpace "\x22C1")+ ,("cap", withThinSpace "\x2229")+ ,("bigcap", withThinSpace "\x22C2")+ ,("cup", withThinSpace "\x222A")+ ,("bigcup", withThinSpace "\x22C3")+ ,("neg", "\x00AC")+ ,("implies", withThinSpace "\x21D2")+ ,("iff", withThinSpace "\x21D4")+ ,("forall", "\x2200")+ ,("exists", "\x2203")+ ,("bot", "\x22A5")+ ,("top", "\x22A4")+ ,("vdash", "\x22A2")+ ,("models", withThinSpace "\x22A8")+ ,("uparrow", "\x2191")+ ,("downarrow", "\x2193")+ ,("rightarrow", withThinSpace "\x2192")+ ,("to", withThinSpace "\x2192")+ ,("rightarrowtail", "\x21A3")+ ,("twoheadrightarrow", withThinSpace "\x21A0")+ ,("twoheadrightarrowtail", withThinSpace "\x2916")+ ,("mapsto", withThinSpace "\x21A6")+ ,("leftarrow", withThinSpace "\x2190")+ ,("leftrightarrow", withThinSpace "\x2194")+ ,("Rightarrow", withThinSpace "\x21D2")+ ,("Leftarrow", withThinSpace "\x21D0")+ ,("Leftrightarrow", withThinSpace "\x21D4")+ ,("partial", "\x2202")+ ,("nabla", "\x2207")+ ,("pm", "\x00B1")+ ,("emptyset", "\x2205")+ ,("infty", "\x221E")+ ,("aleph", "\x2135")+ ,("ldots", "...")+ ,("therefore", "\x2234")+ ,("angle", "\x2220")+ ,("quad", "\x00A0\x00A0")+ ,("cdots", "\x22EF")+ ,("vdots", "\x22EE")+ ,("ddots", "\x22F1")+ ,("diamond", "\x22C4")+ ,("Box", "\x25A1")+ ,("lfloor", "\x230A")+ ,("rfloor", "\x230B")+ ,("lceiling", "\x2308")+ ,("rceiling", "\x2309")+ ,("langle", "\x2329")+ ,("rangle", "\x232A")+ ,("{", "{")+ ,("}", "}")+ ,("[", "[")+ ,("]", "]")+ ,("|", "|")+ ,("||", "||")+ ]+
@@ -0,0 +1,843 @@+{-+Copyright (C) 2006-7 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.Shared+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Utility functions and definitions used by the various Pandoc modules.+-}+module Text.Pandoc.Shared ( + -- * List processing+ splitBy,+ splitByIndices,+ substitute,+ joinWithSep,+ -- * Text processing+ backslashEscapes,+ escapeStringUsing,+ stripTrailingNewlines,+ removeLeadingTrailingSpace,+ removeLeadingSpace,+ removeTrailingSpace,+ stripFirstAndLast,+ camelCaseToHyphenated,+ toRomanNumeral,+ wrapped,+ wrapIfNeeded,+ wrappedTeX,+ wrapTeXIfNeeded,+ -- * Parsing+ (>>~),+ anyLine,+ many1Till,+ notFollowedBy',+ oneOfStrings,+ spaceChar,+ skipSpaces,+ blankline,+ blanklines,+ enclosed,+ stringAnyCase,+ parseFromString,+ lineClump,+ charsInBalanced,+ charsInBalanced',+ romanNumeral,+ withHorizDisplacement,+ nullBlock,+ failIfStrict,+ escaped,+ anyOrderedListMarker,+ orderedListMarker,+ charRef,+ readWith,+ testStringWith,+ ParserState (..),+ defaultParserState,+ HeaderType (..),+ ParserContext (..),+ QuoteContext (..),+ NoteTable,+ KeyTable,+ lookupKeySrc,+ refsMatch,+ -- * Native format prettyprinting+ prettyPandoc,+ -- * Pandoc block and inline list processing+ orderedListMarkers,+ normalizeSpaces,+ compactify,+ Element (..),+ hierarchicalize,+ isHeaderBlock,+ -- * Writer options+ HTMLMathMethod (..),+ WriterOptions (..),+ defaultWriterOptions+ ) where++import Text.Pandoc.Definition+import Text.ParserCombinators.Parsec+import Text.PrettyPrint.HughesPJ ( Doc, fsep, ($$), (<>), empty )+import qualified Text.PrettyPrint.HughesPJ as PP+import Text.Pandoc.CharacterReferences ( characterReference )+import Data.Char ( toLower, toUpper, ord, isLower, isUpper )+import Data.List ( find, isPrefixOf )+import Control.Monad ( join )++--+-- List processing+--++-- | Split list by groups of one or more sep.+splitBy :: (Eq a) => a -> [a] -> [[a]]+splitBy _ [] = []+splitBy sep lst = + let (first, rest) = break (== sep) lst+ rest' = dropWhile (== sep) rest+ in first:(splitBy sep rest')++-- | Split list into chunks divided at specified indices.+splitByIndices :: [Int] -> [a] -> [[a]]+splitByIndices [] lst = [lst]+splitByIndices (x:xs) lst =+ let (first, rest) = splitAt x lst in+ first:(splitByIndices (map (\y -> y - x) xs) rest)++-- | Replace each occurrence of one sublist in a list with another.+substitute :: (Eq a) => [a] -> [a] -> [a] -> [a]+substitute _ _ [] = []+substitute [] _ lst = lst+substitute target replacement lst = + if target `isPrefixOf` lst+ then replacement ++ (substitute target replacement $ drop (length target) lst)+ else (head lst):(substitute target replacement $ tail lst)++-- | Joins a list of lists, separated by another list.+joinWithSep :: [a] -- ^ List to use as separator+ -> [[a]] -- ^ Lists to join+ -> [a]+joinWithSep _ [] = []+joinWithSep sep lst = foldr1 (\a b -> a ++ sep ++ b) lst++--+-- Text processing+--++-- | Returns an association list of backslash escapes for the+-- designated characters.+backslashEscapes :: [Char] -- ^ list of special characters to escape+ -> [(Char, String)]+backslashEscapes = map (\ch -> (ch, ['\\',ch]))++-- | Escape a string of characters, using an association list of+-- characters and strings.+escapeStringUsing :: [(Char, String)] -> String -> String+escapeStringUsing _ [] = ""+escapeStringUsing escapeTable (x:xs) = + case (lookup x escapeTable) of+ Just str -> str ++ rest+ Nothing -> x:rest+ where rest = escapeStringUsing escapeTable xs++-- | Strip trailing newlines from string.+stripTrailingNewlines :: String -> String+stripTrailingNewlines = reverse . dropWhile (== '\n') . reverse++-- | Remove leading and trailing space (including newlines) from string.+removeLeadingTrailingSpace :: String -> String+removeLeadingTrailingSpace = removeLeadingSpace . removeTrailingSpace++-- | Remove leading space (including newlines) from string.+removeLeadingSpace :: String -> String+removeLeadingSpace = dropWhile (`elem` " \n\t")++-- | Remove trailing space (including newlines) from string.+removeTrailingSpace :: String -> String+removeTrailingSpace = reverse . removeLeadingSpace . reverse++-- | Strip leading and trailing characters from string+stripFirstAndLast :: String -> String+stripFirstAndLast str =+ drop 1 $ take ((length str) - 1) str++-- | Change CamelCase word to hyphenated lowercase (e.g., camel-case). +camelCaseToHyphenated :: String -> String+camelCaseToHyphenated [] = ""+camelCaseToHyphenated (a:b:rest) | isLower a && isUpper b =+ a:'-':(toLower b):(camelCaseToHyphenated rest)+camelCaseToHyphenated (a:rest) = (toLower a):(camelCaseToHyphenated rest)++-- | Convert number < 4000 to uppercase roman numeral.+toRomanNumeral :: Int -> String+toRomanNumeral x =+ if x >= 4000 || x < 0+ then "?"+ else case x of+ _ | x >= 1000 -> "M" ++ toRomanNumeral (x - 1000)+ _ | x >= 900 -> "CM" ++ toRomanNumeral (x - 900)+ _ | x >= 500 -> "D" ++ toRomanNumeral (x - 500)+ _ | x >= 400 -> "CD" ++ toRomanNumeral (x - 400)+ _ | x >= 100 -> "C" ++ toRomanNumeral (x - 100)+ _ | x >= 90 -> "XC" ++ toRomanNumeral (x - 90)+ _ | x >= 50 -> "L" ++ toRomanNumeral (x - 50)+ _ | x >= 40 -> "XL" ++ toRomanNumeral (x - 40)+ _ | x >= 10 -> "X" ++ toRomanNumeral (x - 10)+ _ | x >= 9 -> "IX" ++ toRomanNumeral (x - 5)+ _ | x >= 5 -> "V" ++ toRomanNumeral (x - 5)+ _ | x >= 4 -> "IV" ++ toRomanNumeral (x - 4)+ _ | x >= 1 -> "I" ++ toRomanNumeral (x - 1)+ _ -> ""++-- | Wrap inlines to line length.+wrapped :: Monad m => ([Inline] -> m Doc) -> [Inline] -> m Doc+wrapped listWriter sect = (mapM listWriter $ splitBy Space sect) >>= + return . fsep++-- | Wrap inlines if the text wrap option is selected.+wrapIfNeeded :: Monad m => WriterOptions -> ([Inline] -> m Doc) -> + [Inline] -> m Doc+wrapIfNeeded opts = if writerWrapText opts+ then wrapped + else ($)++-- auxiliary function for wrappedTeX+isNote (Note _) = True+isNote _ = False++-- | Wrap inlines to line length, treating footnotes in a way that+-- makes sense in LaTeX and ConTeXt.+wrappedTeX :: Monad m + => Bool+ -> ([Inline] -> m Doc) + -> [Inline] + -> m Doc+wrappedTeX includePercent listWriter sect = do+ let (firstpart, rest) = break isNote sect+ firstpartWrapped <- wrapped listWriter firstpart+ if null rest+ then return firstpartWrapped+ else do let (note:rest') = rest+ restWrapped <- if null rest'+ then return empty+ else wrappedTeX includePercent listWriter rest'+ noteText <- listWriter [note]+ return $ firstpartWrapped <> + (if includePercent then PP.char '%' else empty) $$ + noteText $$ restWrapped ++-- | Wrap inlines if the text wrap option is selected, specialized +-- for LaTeX and ConTeXt.+wrapTeXIfNeeded :: Monad m + => WriterOptions+ -> Bool+ -> ([Inline] -> m Doc) + -> [Inline] + -> m Doc+wrapTeXIfNeeded opts includePercent = if writerWrapText opts+ then wrappedTeX includePercent+ else ($)++--+-- Parsing+--++-- | Like >>, but returns the operation on the left.+-- (Suggested by Tillmann Rendel on Haskell-cafe list.)+(>>~) :: (Monad m) => m a -> m b -> m a+a >>~ b = a >>= \x -> b >> return x++-- | Parse any line of text+anyLine :: GenParser Char st [Char]+anyLine = manyTill anyChar newline++-- | Like @manyTill@, but reads at least one item.+many1Till :: GenParser tok st a+ -> GenParser tok st end+ -> GenParser tok st [a]+many1Till p end = do+ first <- p+ rest <- manyTill p end+ return (first:rest)++-- | A more general form of @notFollowedBy@. This one allows any +-- type of parser to be specified, and succeeds only if that parser fails.+-- It does not consume any input.+notFollowedBy' :: Show b => GenParser a st b -> GenParser a st ()+notFollowedBy' p = try $ join $ do a <- try p+ return (unexpected (show a))+ <|>+ return (return ())+-- (This version due to Andrew Pimlott on the Haskell mailing list.)++-- | Parses one of a list of strings (tried in order). +oneOfStrings :: [String] -> GenParser Char st String+oneOfStrings listOfStrings = choice $ map (try . string) listOfStrings++-- | Parses a space or tab.+spaceChar :: CharParser st Char+spaceChar = char ' ' <|> char '\t'++-- | Skips zero or more spaces or tabs.+skipSpaces :: GenParser Char st ()+skipSpaces = skipMany spaceChar++-- | Skips zero or more spaces or tabs, then reads a newline.+blankline :: GenParser Char st Char+blankline = try $ skipSpaces >> newline++-- | Parses one or more blank lines and returns a string of newlines.+blanklines :: GenParser Char st [Char]+blanklines = many1 blankline++-- | Parses material enclosed between start and end parsers.+enclosed :: GenParser Char st t -- ^ start parser+ -> GenParser Char st end -- ^ end parser+ -> GenParser Char st a -- ^ content parser (to be used repeatedly)+ -> GenParser Char st [a]+enclosed start end parser = try $ + start >> notFollowedBy space >> many1Till parser end++-- | Parse string, case insensitive.+stringAnyCase :: [Char] -> CharParser st String+stringAnyCase [] = string ""+stringAnyCase (x:xs) = do+ firstChar <- char (toUpper x) <|> char (toLower x)+ rest <- stringAnyCase xs+ return (firstChar:rest)++-- | Parse contents of 'str' using 'parser' and return result.+parseFromString :: GenParser tok st a -> [tok] -> GenParser tok st a+parseFromString parser str = do+ oldPos <- getPosition+ oldInput <- getInput+ setInput str+ result <- parser+ setInput oldInput+ setPosition oldPos+ return result++-- | Parse raw line block up to and including blank lines.+lineClump :: GenParser Char st String+lineClump = blanklines + <|> (many1 (notFollowedBy blankline >> anyLine) >>= return . unlines)++-- | Parse a string of characters between an open character+-- and a close character, including text between balanced+-- pairs of open and close, which must be different. For example,+-- @charsInBalanced '(' ')'@ will parse "(hello (there))"+-- and return "hello (there)". Stop if a blank line is+-- encountered.+charsInBalanced :: Char -> Char -> GenParser Char st String+charsInBalanced open close = try $ do+ char open+ raw <- many $ (many1 (noneOf [open, close, '\n']))+ <|> (do res <- charsInBalanced open close+ return $ [open] ++ res ++ [close])+ <|> try (string "\n" >>~ notFollowedBy' blanklines)+ char close+ return $ concat raw++-- | Like @charsInBalanced@, but allow blank lines in the content.+charsInBalanced' :: Char -> Char -> GenParser Char st String+charsInBalanced' open close = try $ do+ char open+ raw <- many $ (many1 (noneOf [open, close]))+ <|> (do res <- charsInBalanced' open close+ return $ [open] ++ res ++ [close])+ char close+ return $ concat raw++-- Auxiliary functions for romanNumeral:++lowercaseRomanDigits = ['i','v','x','l','c','d','m']+uppercaseRomanDigits = map toUpper lowercaseRomanDigits++-- | Parses a roman numeral (uppercase or lowercase), returns number.+romanNumeral :: Bool -- ^ Uppercase if true+ -> GenParser Char st Int+romanNumeral upperCase = do+ let romanDigits = if upperCase + then uppercaseRomanDigits + else lowercaseRomanDigits+ lookAhead $ oneOf romanDigits + let [one, five, ten, fifty, hundred, fivehundred, thousand] = + map char romanDigits+ thousands <- many thousand >>= (return . (1000 *) . length)+ ninehundreds <- option 0 $ try $ hundred >> thousand >> return 900+ fivehundreds <- many fivehundred >>= (return . (500 *) . length)+ fourhundreds <- option 0 $ try $ hundred >> fivehundred >> return 400+ hundreds <- many hundred >>= (return . (100 *) . length)+ nineties <- option 0 $ try $ ten >> hundred >> return 90+ fifties <- many fifty >>= (return . (50 *) . length)+ forties <- option 0 $ try $ ten >> fifty >> return 40+ tens <- many ten >>= (return . (10 *) . length)+ nines <- option 0 $ try $ one >> ten >> return 9+ fives <- many five >>= (return . (5 *) . length)+ fours <- option 0 $ try $ one >> five >> return 4+ ones <- many one >>= (return . length)+ let total = thousands + ninehundreds + fivehundreds + fourhundreds ++ hundreds + nineties + fifties + forties + tens + nines ++ fives + fours + ones+ if total == 0+ then fail "not a roman numeral"+ else return total++-- | Applies a parser, returns tuple of its results and its horizontal+-- displacement (the difference between the source column at the end+-- and the source column at the beginning). Vertical displacement+-- (source row) is ignored.+withHorizDisplacement :: GenParser Char st a -- ^ Parser to apply+ -> GenParser Char st (a, Int) -- ^ (result, displacement)+withHorizDisplacement parser = do+ pos1 <- getPosition+ result <- parser+ pos2 <- getPosition+ return (result, sourceColumn pos2 - sourceColumn pos1)++-- | Parses a character and returns 'Null' (so that the parser can move on+-- if it gets stuck).+nullBlock :: GenParser Char st Block+nullBlock = anyChar >> return Null++-- | Fail if reader is in strict markdown syntax mode.+failIfStrict :: GenParser Char ParserState ()+failIfStrict = do+ state <- getState+ if stateStrict state then fail "strict mode" else return ()++-- | Parses backslash, then applies character parser.+escaped :: GenParser Char st Char -- ^ Parser for character to escape+ -> GenParser Char st Inline+escaped parser = try $ do+ char '\\'+ result <- parser+ return (Str [result])++-- | Parses an uppercase roman numeral and returns (UpperRoman, number).+upperRoman :: GenParser Char st (ListNumberStyle, Int)+upperRoman = do+ num <- romanNumeral True+ return (UpperRoman, num)++-- | Parses a lowercase roman numeral and returns (LowerRoman, number).+lowerRoman :: GenParser Char st (ListNumberStyle, Int)+lowerRoman = do+ num <- romanNumeral False+ return (LowerRoman, num)++-- | Parses a decimal numeral and returns (Decimal, number).+decimal :: GenParser Char st (ListNumberStyle, Int)+decimal = do+ num <- many1 digit+ return (Decimal, read num)++-- | Parses a '#' returns (DefaultStyle, 1).+defaultNum :: GenParser Char st (ListNumberStyle, Int)+defaultNum = do+ char '#'+ return (DefaultStyle, 1)++-- | Parses a lowercase letter and returns (LowerAlpha, number).+lowerAlpha :: GenParser Char st (ListNumberStyle, Int)+lowerAlpha = do+ ch <- oneOf ['a'..'z']+ return (LowerAlpha, ord ch - ord 'a' + 1)++-- | Parses an uppercase letter and returns (UpperAlpha, number).+upperAlpha :: GenParser Char st (ListNumberStyle, Int)+upperAlpha = do+ ch <- oneOf ['A'..'Z']+ return (UpperAlpha, ord ch - ord 'A' + 1)++-- | Parses a roman numeral i or I+romanOne :: GenParser Char st (ListNumberStyle, Int)+romanOne = (char 'i' >> return (LowerRoman, 1)) <|>+ (char 'I' >> return (UpperRoman, 1))++-- | Parses an ordered list marker and returns list attributes.+anyOrderedListMarker :: GenParser Char st ListAttributes +anyOrderedListMarker = choice $ + [delimParser numParser | delimParser <- [inPeriod, inOneParen, inTwoParens],+ numParser <- [decimal, defaultNum, romanOne,+ lowerAlpha, lowerRoman, upperAlpha, upperRoman]]++-- | Parses a list number (num) followed by a period, returns list attributes.+inPeriod :: GenParser Char st (ListNumberStyle, Int)+ -> GenParser Char st ListAttributes +inPeriod num = try $ do+ (style, start) <- num+ char '.'+ let delim = if style == DefaultStyle+ then DefaultDelim+ else Period+ return (start, style, delim)+ +-- | Parses a list number (num) followed by a paren, returns list attributes.+inOneParen :: GenParser Char st (ListNumberStyle, Int)+ -> GenParser Char st ListAttributes +inOneParen num = try $ do+ (style, start) <- num+ char ')'+ return (start, style, OneParen)++-- | Parses a list number (num) enclosed in parens, returns list attributes.+inTwoParens :: GenParser Char st (ListNumberStyle, Int)+ -> GenParser Char st ListAttributes +inTwoParens num = try $ do+ char '('+ (style, start) <- num+ char ')'+ return (start, style, TwoParens)++-- | Parses an ordered list marker with a given style and delimiter,+-- returns number.+orderedListMarker :: ListNumberStyle + -> ListNumberDelim + -> GenParser Char st Int+orderedListMarker style delim = do+ let num = case style of+ DefaultStyle -> decimal <|> defaultNum+ Decimal -> decimal+ UpperRoman -> upperRoman+ LowerRoman -> lowerRoman+ UpperAlpha -> upperAlpha+ LowerAlpha -> lowerAlpha+ let context = case delim of+ DefaultDelim -> inPeriod+ Period -> inPeriod+ OneParen -> inOneParen+ TwoParens -> inTwoParens+ (start, _, _) <- context num+ return start++-- | Parses a character reference and returns a Str element.+charRef :: GenParser Char st Inline+charRef = do+ c <- characterReference+ return $ Str [c]++-- | Parse a string with a given parser and state.+readWith :: GenParser Char ParserState a -- ^ parser+ -> ParserState -- ^ initial state+ -> String -- ^ input string+ -> a+readWith parser state input = + case runParser parser state "source" input of+ Left err -> error $ "\nError:\n" ++ show err+ Right result -> result++-- | Parse a string with @parser@ (for testing).+testStringWith :: (Show a) => GenParser Char ParserState a+ -> String+ -> IO ()+testStringWith parser str = putStrLn $ show $ + readWith parser defaultParserState str++-- | Parsing options.+data ParserState = ParserState+ { stateParseRaw :: Bool, -- ^ Parse raw HTML and LaTeX?+ stateParserContext :: ParserContext, -- ^ Inside list?+ stateQuoteContext :: QuoteContext, -- ^ Inside quoted environment?+ stateKeys :: KeyTable, -- ^ List of reference keys+ stateNotes :: NoteTable, -- ^ List of notes+ stateTabStop :: Int, -- ^ Tab stop+ stateStandalone :: Bool, -- ^ Parse bibliographic info?+ stateTitle :: [Inline], -- ^ Title of document+ stateAuthors :: [String], -- ^ Authors of document+ stateDate :: String, -- ^ Date of document+ stateStrict :: Bool, -- ^ Use strict markdown syntax?+ stateSmart :: Bool, -- ^ Use smart typography?+ stateColumns :: Int, -- ^ Number of columns in terminal+ stateHeaderTable :: [HeaderType] -- ^ Ordered list of header types used+ }+ deriving Show++defaultParserState :: ParserState+defaultParserState = + ParserState { stateParseRaw = False,+ stateParserContext = NullState,+ stateQuoteContext = NoQuote,+ stateKeys = [],+ stateNotes = [],+ stateTabStop = 4,+ stateStandalone = False,+ stateTitle = [],+ stateAuthors = [],+ stateDate = [],+ stateStrict = False,+ stateSmart = False,+ stateColumns = 80,+ stateHeaderTable = [] }++data HeaderType + = SingleHeader Char -- ^ Single line of characters underneath+ | DoubleHeader Char -- ^ Lines of characters above and below+ deriving (Eq, Show)++data ParserContext + = ListItemState -- ^ Used when running parser on list item contents+ | NullState -- ^ Default state+ deriving (Eq, Show)++data QuoteContext+ = InSingleQuote -- ^ Used when parsing inside single quotes+ | InDoubleQuote -- ^ Used when parsing inside double quotes+ | NoQuote -- ^ Used when not parsing inside quotes+ deriving (Eq, Show)++type NoteTable = [(String, [Block])]++type KeyTable = [([Inline], Target)]++-- | Look up key in key table and return target object.+lookupKeySrc :: KeyTable -- ^ Key table+ -> [Inline] -- ^ Key+ -> Maybe Target+lookupKeySrc table key = case find (refsMatch key . fst) table of+ Nothing -> Nothing+ Just (_, src) -> Just src++-- | Returns @True@ if keys match (case insensitive).+refsMatch :: [Inline] -> [Inline] -> Bool+refsMatch ((Str x):restx) ((Str y):resty) = + ((map toLower x) == (map toLower y)) && refsMatch restx resty+refsMatch ((Emph x):restx) ((Emph y):resty) = + refsMatch x y && refsMatch restx resty+refsMatch ((Strong x):restx) ((Strong y):resty) = + refsMatch x y && refsMatch restx resty+refsMatch ((Strikeout x):restx) ((Strikeout y):resty) = + refsMatch x y && refsMatch restx resty+refsMatch ((Superscript x):restx) ((Superscript y):resty) = + refsMatch x y && refsMatch restx resty+refsMatch ((Subscript x):restx) ((Subscript y):resty) = + refsMatch x y && refsMatch restx resty+refsMatch ((Quoted t x):restx) ((Quoted u y):resty) = + t == u && refsMatch x y && refsMatch restx resty+refsMatch ((Code x):restx) ((Code y):resty) = + ((map toLower x) == (map toLower y)) && refsMatch restx resty+refsMatch ((Math x):restx) ((Math y):resty) = + ((map toLower x) == (map toLower y)) && refsMatch restx resty+refsMatch ((TeX x):restx) ((TeX y):resty) = + ((map toLower x) == (map toLower y)) && refsMatch restx resty+refsMatch ((HtmlInline x):restx) ((HtmlInline y):resty) = + ((map toLower x) == (map toLower y)) && refsMatch restx resty+refsMatch (x:restx) (y:resty) = (x == y) && refsMatch restx resty+refsMatch [] x = null x+refsMatch x [] = null x++--+-- Native format prettyprinting+--+ +-- | Indent string as a block.+indentBy :: Int -- ^ Number of spaces to indent the block + -> Int -- ^ Number of spaces (rel to block) to indent first line+ -> String -- ^ Contents of block to indent+ -> String+indentBy _ _ [] = ""+indentBy num first str = + let (firstLine:restLines) = lines str + firstLineIndent = num + first+ in (replicate firstLineIndent ' ') ++ firstLine ++ "\n" ++ + (joinWithSep "\n" $ map ((replicate num ' ') ++ ) restLines)++-- | Prettyprint list of Pandoc blocks elements.+prettyBlockList :: Int -- ^ Number of spaces to indent list of blocks+ -> [Block] -- ^ List of blocks+ -> String+prettyBlockList indent [] = indentBy indent 0 "[]"+prettyBlockList indent blocks = indentBy indent (-2) $ "[ " ++ + (joinWithSep "\n, " (map prettyBlock blocks)) ++ " ]"++-- | Prettyprint Pandoc block element.+prettyBlock :: Block -> String+prettyBlock (BlockQuote blocks) = "BlockQuote\n " ++ + (prettyBlockList 2 blocks) +prettyBlock (OrderedList attribs blockLists) = + "OrderedList " ++ show attribs ++ "\n" ++ indentBy 2 0 ("[ " ++ + (joinWithSep ", " $ map (\blocks -> prettyBlockList 2 blocks) + blockLists)) ++ " ]"+prettyBlock (BulletList blockLists) = "BulletList\n" ++ + indentBy 2 0 ("[ " ++ (joinWithSep ", " + (map (\blocks -> prettyBlockList 2 blocks) blockLists))) ++ " ]" +prettyBlock (DefinitionList blockLists) = "DefinitionList\n" ++ + indentBy 2 0 ("[" ++ (joinWithSep ",\n" + (map (\(term, blocks) -> " (" ++ show term ++ ",\n" ++ + indentBy 1 2 (prettyBlockList 2 blocks) ++ " )") blockLists))) ++ " ]" +prettyBlock (Table caption aligns widths header rows) = + "Table " ++ show caption ++ " " ++ show aligns ++ " " ++ + show widths ++ "\n" ++ prettyRow header ++ " [\n" ++ + (joinWithSep ",\n" (map prettyRow rows)) ++ " ]"+ where prettyRow cols = indentBy 2 0 ("[ " ++ (joinWithSep ", "+ (map (\blocks -> prettyBlockList 2 blocks) + cols))) ++ " ]"+prettyBlock block = show block++-- | Prettyprint Pandoc document.+prettyPandoc :: Pandoc -> String+prettyPandoc (Pandoc meta blocks) = "Pandoc " ++ "(" ++ show meta ++ + ")\n" ++ (prettyBlockList 0 blocks) ++ "\n"++--+-- Pandoc block and inline list processing+--++-- | Generate infinite lazy list of markers for an ordered list,+-- depending on list attributes.+orderedListMarkers :: (Int, ListNumberStyle, ListNumberDelim) -> [String]+orderedListMarkers (start, numstyle, numdelim) = + let singleton c = [c]+ nums = case numstyle of+ DefaultStyle -> map show [start..]+ Decimal -> map show [start..]+ UpperAlpha -> drop (start - 1) $ cycle $ + map singleton ['A'..'Z']+ LowerAlpha -> drop (start - 1) $ cycle $+ map singleton ['a'..'z']+ UpperRoman -> map toRomanNumeral [start..]+ LowerRoman -> map (map toLower . toRomanNumeral) [start..]+ inDelim str = case numdelim of+ DefaultDelim -> str ++ "."+ Period -> str ++ "."+ OneParen -> str ++ ")"+ TwoParens -> "(" ++ str ++ ")"+ in map inDelim nums++-- | Normalize a list of inline elements: remove leading and trailing+-- @Space@ elements, collapse double @Space@s into singles, and+-- remove empty Str elements.+normalizeSpaces :: [Inline] -> [Inline]+normalizeSpaces [] = []+normalizeSpaces list = + let removeDoubles [] = []+ removeDoubles (Space:Space:rest) = removeDoubles (Space:rest)+ removeDoubles (Space:(Str ""):Space:rest) = removeDoubles (Space:rest)+ removeDoubles ((Str ""):rest) = removeDoubles rest + removeDoubles (x:rest) = x:(removeDoubles rest)+ removeLeading (Space:xs) = removeLeading xs+ removeLeading x = x+ removeTrailing [] = []+ removeTrailing lst = if (last lst == Space)+ then init lst+ else lst+ in removeLeading $ removeTrailing $ removeDoubles list++-- | Change final list item from @Para@ to @Plain@ if the list should +-- be compact.+compactify :: [[Block]] -- ^ List of list items (each a list of blocks)+ -> [[Block]]+compactify [] = []+compactify items =+ let final = last items+ others = init items+ in case final of+ [Para a] -> if any containsPara others+ then items+ else others ++ [[Plain a]]+ _ -> items++containsPara :: [Block] -> Bool+containsPara [] = False+containsPara ((Para _):_) = True+containsPara ((BulletList items):rest) = any containsPara items ||+ containsPara rest+containsPara ((OrderedList _ items):rest) = any containsPara items ||+ containsPara rest+containsPara ((DefinitionList items):rest) = any containsPara (map snd items) ||+ containsPara rest+containsPara (_:rest) = containsPara rest++-- | Data structure for defining hierarchical Pandoc documents+data Element = Blk Block + | Sec [Inline] [Element] deriving (Eq, Read, Show)++-- | Returns @True@ on Header block with at least the specified level+headerAtLeast :: Int -> Block -> Bool+headerAtLeast level (Header x _) = x <= level+headerAtLeast _ _ = False++-- | Convert list of Pandoc blocks into (hierarchical) list of Elements+hierarchicalize :: [Block] -> [Element]+hierarchicalize [] = []+hierarchicalize (block:rest) = + case block of+ (Header level title) -> + let (thisSection, rest') = break (headerAtLeast level) rest+ in (Sec title (hierarchicalize thisSection)):(hierarchicalize rest') + x -> (Blk x):(hierarchicalize rest)++-- | True if block is a Header block.+isHeaderBlock :: Block -> Bool+isHeaderBlock (Header _ _) = True+isHeaderBlock _ = False++--+-- Writer options+--++data HTMLMathMethod = PlainMath + | ASCIIMathML (Maybe String) -- url of ASCIIMathML.js+ | GladTeX+ | MimeTeX String -- url of mimetex.cgi + deriving (Show, Read, Eq)++-- | Options for writers+data WriterOptions = WriterOptions+ { writerStandalone :: Bool -- ^ Include header and footer+ , writerHeader :: String -- ^ Header for the document+ , writerTitlePrefix :: String -- ^ Prefix for HTML titles+ , writerTabStop :: Int -- ^ Tabstop for conversion btw spaces and tabs+ , writerTableOfContents :: Bool -- ^ Include table of contents+ , writerS5 :: Bool -- ^ We're writing S5 + , writerHTMLMathMethod :: HTMLMathMethod -- ^ How to print math in HTML+ , writerIgnoreNotes :: Bool -- ^ Ignore footnotes (used in making toc)+ , writerIncremental :: Bool -- ^ Incremental S5 lists+ , writerNumberSections :: Bool -- ^ Number sections in LaTeX+ , writerIncludeBefore :: String -- ^ String to include before the body+ , writerIncludeAfter :: String -- ^ String to include after the body+ , writerStrictMarkdown :: Bool -- ^ Use strict markdown syntax+ , writerReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst+ , writerWrapText :: Bool -- ^ Wrap text to line length+ } deriving Show++-- | Default writer options.+defaultWriterOptions :: WriterOptions+defaultWriterOptions = + WriterOptions { writerStandalone = False+ , writerHeader = ""+ , writerTitlePrefix = ""+ , writerTabStop = 4+ , writerTableOfContents = False+ , writerS5 = False+ , writerHTMLMathMethod = PlainMath+ , writerIgnoreNotes = False+ , writerIncremental = False+ , writerNumberSections = False+ , writerIncludeBefore = ""+ , writerIncludeAfter = ""+ , writerStrictMarkdown = False+ , writerReferenceLinks = False+ , writerWrapText = True+ }
+ Text/Pandoc/UTF8.hs view
@@ -0,0 +1,45 @@+-- | Functions for converting Unicode strings to UTF-8 and vice versa.+-- +-- Taken from <http://www.cse.ogi.edu/~hallgren/Talks/LHiH/base/lib/UTF8.hs>.+-- (c) 2003, OGI School of Science & Engineering, Oregon Health and+-- Science University. +--+-- Modified by Martin Norbaeck+-- to pass illegal UTF-8 sequences through unchanged.+module Text.Pandoc.UTF8 ( + fromUTF8, + toUTF8 + ) where++-- From the Char module supplied with HBC.++-- | Take a UTF-8 string and decode it into a Unicode string.+fromUTF8 :: String -> String+fromUTF8 "" = ""+fromUTF8 ('\xef':'\xbb':'\xbf':cs) = fromUTF8 cs -- skip BOM (byte order marker)+fromUTF8 (c:c':cs) | '\xc0' <= c && c <= '\xdf' && + '\x80' <= c' && c' <= '\xbf' =+ toEnum ((fromEnum c `mod` 0x20) * 0x40 + fromEnum c' `mod` 0x40) : fromUTF8 cs+fromUTF8 (c:c':c'':cs) | '\xe0' <= c && c <= '\xef' && + '\x80' <= c' && c' <= '\xbf' &&+ '\x80' <= c'' && c'' <= '\xbf' =+ toEnum ((fromEnum c `mod` 0x10 * 0x1000) + (fromEnum c' `mod` 0x40) * 0x40 + fromEnum c'' `mod` 0x40) : fromUTF8 cs+fromUTF8 (c:cs) = c : fromUTF8 cs++-- | Take a Unicode string and encode it as a UTF-8 string.+toUTF8 :: String -> String+toUTF8 "" = ""+toUTF8 (c:cs) =+ if c > '\x0000' && c < '\x0080' then+ c : toUTF8 cs+ else if c < toEnum 0x0800 then+ let i = fromEnum c+ in toEnum (0xc0 + i `div` 0x40) : + toEnum (0x80 + i `mod` 0x40) : + toUTF8 cs+ else+ let i = fromEnum c+ in toEnum (0xe0 + i `div` 0x1000) : + toEnum (0x80 + (i `mod` 0x1000) `div` 0x40) : + toEnum (0x80 + i `mod` 0x40) : + toUTF8 cs
+ Text/Pandoc/Writers/ConTeXt.hs view
@@ -0,0 +1,300 @@+{-+Copyright (C) 2007 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 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.+-}+module Text.Pandoc.Writers.ConTeXt ( writeConTeXt ) where+import Text.Pandoc.Definition+import Text.Pandoc.Shared+import Text.Printf ( printf )+import Data.List ( (\\), intersperse, isSuffixOf )+import Control.Monad.State+import Text.PrettyPrint.HughesPJ hiding ( Str )++data WriterState = + WriterState { stNextRef :: Int -- number of next URL reference+ , stOrderedListLevel :: Int -- level of ordered list+ , stOptions :: WriterOptions -- writer options+ }++orderedListStyles = cycle ["[n]","[a]", "[r]", "[g]"] ++-- | Convert Pandoc to ConTeXt.+writeConTeXt :: WriterOptions -> Pandoc -> String+writeConTeXt options document = + let defaultWriterState = WriterState { stNextRef = 1+ , stOrderedListLevel = 0+ , stOptions = options+ } + in render $ + evalState (pandocToConTeXt options document) defaultWriterState ++pandocToConTeXt :: WriterOptions -> Pandoc -> State WriterState Doc+pandocToConTeXt options (Pandoc meta blocks) = do+ main <- blockListToConTeXt blocks + let before = if null (writerIncludeBefore options)+ then empty+ else text $ writerIncludeBefore options+ let after = if null (writerIncludeAfter options)+ then empty+ else text $ writerIncludeAfter options+ let body = before $$ main $$ after+ head <- if writerStandalone options+ then contextHeader options meta+ else return empty+ let toc = if writerTableOfContents options+ then text "\\placecontent\n"+ else empty + let foot = if writerStandalone options+ then text "\\stoptext\n"+ else empty + return $ head $$ toc $$ body $$ foot++-- | Insert bibliographic information into ConTeXt header.+contextHeader :: WriterOptions -- ^ Options, including ConTeXt header+ -> Meta -- ^ Meta with bibliographic information+ -> State WriterState Doc+contextHeader options (Meta title authors date) = do+ titletext <- if null title+ then return empty + else inlineListToConTeXt title+ let authorstext = if null authors+ then ""+ else if length authors == 1+ then stringToConTeXt $ head authors+ else stringToConTeXt $ (joinWithSep ", " $+ init authors) ++ " & " ++ last authors+ let datetext = if date == ""+ then "" + else stringToConTeXt date+ let titleblock = text "\\doctitle{" <> titletext <> char '}' $$+ text ("\\author{" ++ authorstext ++ "}") $$+ text ("\\date{" ++ datetext ++ "}")+ let header = text $ writerHeader options+ return $ header $$ titleblock $$ text "\\starttext\n\\maketitle\n"++-- escape things as needed for ConTeXt++escapeCharForConTeXt :: Char -> String+escapeCharForConTeXt ch =+ case ch of+ '{' -> "\\letteropenbrace{}"+ '}' -> "\\letterclosebrace{}"+ '\\' -> "\\letterbackslash{}"+ '$' -> "\\$"+ '|' -> "\\letterbar{}"+ '^' -> "\\letterhat{}"+ '%' -> "\\%"+ '~' -> "\\lettertilde{}"+ '&' -> "\\&"+ '#' -> "\\#"+ '<' -> "\\letterless{}"+ '>' -> "\\lettermore{}"+ '_' -> "\\letterunderscore{}"+ x -> [x]++-- | Escape string for ConTeXt+stringToConTeXt :: String -> String+stringToConTeXt = concatMap escapeCharForConTeXt++-- | Convert Pandoc block element to ConTeXt.+blockToConTeXt :: Block + -> State WriterState Doc +blockToConTeXt Null = return empty+blockToConTeXt (Plain lst) = do+ st <- get+ let options = stOptions st+ contents <- wrapTeXIfNeeded options False inlineListToConTeXt lst + return contents+blockToConTeXt (Para lst) = do + st <- get+ let options = stOptions st+ contents <- wrapTeXIfNeeded options False inlineListToConTeXt lst+ return $ contents <> char '\n'+blockToConTeXt (BlockQuote lst) = do+ contents <- blockListToConTeXt lst+ return $ text "\\startblockquote\n" $$ contents $$ text "\\stopblockquote"+blockToConTeXt (CodeBlock str) = + return $ text $ "\\starttyping\n" ++ str ++ "\n\\stoptyping\n" -- \n needed+ -- because \stoptyping can't have anything after it+blockToConTeXt (RawHtml str) = return empty+blockToConTeXt (BulletList lst) = do + contents <- mapM listItemToConTeXt lst+ return $ text "\\startitemize" $$ vcat contents $$ text "\\stopitemize\n"+blockToConTeXt (OrderedList (start, style, delim) lst) = do+ st <- get+ let level = stOrderedListLevel st+ put $ st {stOrderedListLevel = level + 1}+ contents <- mapM listItemToConTeXt lst+ put $ st {stOrderedListLevel = level} + let start' = if start == 1 then "" else "start=" ++ show start+ let delim' = case delim of+ DefaultDelim -> ""+ Period -> "stopper=." + OneParen -> "stopper=)" + TwoParens -> "left=(,stopper=)"+ let width = maximum $ map length $ take (length contents) + (orderedListMarkers (start, style, delim))+ let width' = (toEnum width + 1) / 2+ let width'' = if width' > 1.5 + then "width=" ++ show width' ++ "em" + else ""+ let specs2Items = filter (not . null) [start', delim', width'']+ let specs2 = if null specs2Items+ then ""+ else "[" ++ joinWithSep "," specs2Items ++ "]"+ let style' = case style of+ DefaultStyle -> orderedListStyles !! level+ Decimal -> "[n]" + LowerRoman -> "[r]"+ UpperRoman -> "[R]"+ LowerAlpha -> "[a]"+ UpperAlpha -> "[A]"+ let specs = style' ++ specs2+ return $ text ("\\startitemize" ++ specs) $$ vcat contents $$ + text "\\stopitemize\n"+blockToConTeXt (DefinitionList lst) =+ mapM defListItemToConTeXt lst >>= return . (<> char '\n') . vcat+blockToConTeXt HorizontalRule = return $ text "\\thinrule\n"+blockToConTeXt (Header level lst) = do+ contents <- inlineListToConTeXt lst+ st <- get+ let opts = stOptions st+ let base = if writerNumberSections opts then "section" else "subject"+ return $ if level >= 1 && level <= 5+ then char '\\' <> text (concat (replicate (level - 1) "sub")) <> + text base <> char '{' <> contents <> char '}' <> char '\n'+ else contents <> char '\n'+blockToConTeXt (Table caption aligns widths heads rows) = do+ let colWidths = map printDecimal widths+ let colDescriptor colWidth alignment = (case alignment of+ AlignLeft -> 'l' + AlignRight -> 'r'+ AlignCenter -> 'c'+ AlignDefault -> 'l'):+ "p(" ++ colWidth ++ "\\textwidth)|"+ let colDescriptors = "|" ++ (concat $ + zipWith colDescriptor colWidths aligns)+ headers <- tableRowToConTeXt heads + captionText <- inlineListToConTeXt caption + let captionText' = if null caption then text "none" else captionText+ rows' <- mapM tableRowToConTeXt rows + return $ text "\\placetable[here]{" <> captionText' <> char '}' $$+ text "\\starttable[" <> text colDescriptors <> char ']' $$+ text "\\HL" $$ headers $$ text "\\HL" $$+ vcat rows' $$ text "\\HL\n\\stoptable\n" ++printDecimal :: Float -> String+printDecimal = printf "%.2f" ++tableRowToConTeXt cols = do+ cols' <- mapM blockListToConTeXt cols+ return $ (vcat (map (text "\\NC " <>) cols')) $$ + text "\\NC\\AR"++listItemToConTeXt list = blockListToConTeXt list >>=+ return . (text "\\item " $$) . (nest 2)++orderedListItemToConTeXt marker list = blockListToConTeXt list >>=+ return . (text ("\\sym{" ++ marker ++ "} ") $$) . (nest 2)++defListItemToConTeXt (term, def) = do+ term' <- inlineListToConTeXt term+ def' <- blockListToConTeXt def+ return $ text "\\startdescr{" <> term' <> char '}' $$ def' $$ text "\\stopdescr"++-- | Convert list of block elements to ConTeXt.+blockListToConTeXt :: [Block] -> State WriterState Doc+blockListToConTeXt lst = mapM blockToConTeXt lst >>= return . vcat++-- | Convert list of inline elements to ConTeXt.+inlineListToConTeXt :: [Inline] -- ^ Inlines to convert+ -> State WriterState Doc+inlineListToConTeXt lst = mapM inlineToConTeXt lst >>= return . hcat++isQuoted :: Inline -> Bool+isQuoted (Quoted _ _) = True+isQuoted Apostrophe = True+isQuoted _ = False++-- | Convert inline element to ConTeXt+inlineToConTeXt :: Inline -- ^ Inline to convert+ -> State WriterState Doc+inlineToConTeXt (Emph lst) = do + contents <- inlineListToConTeXt lst+ return $ text "{\\em " <> contents <> char '}'+inlineToConTeXt (Strong lst) = do+ contents <- inlineListToConTeXt lst+ return $ text "{\\bf " <> contents <> char '}'+inlineToConTeXt (Strikeout lst) = do+ contents <- inlineListToConTeXt lst+ return $ text "\\overstrikes{" <> contents <> char '}'+inlineToConTeXt (Superscript lst) = do+ contents <- inlineListToConTeXt lst+ return $ text "\\high{" <> contents <> char '}'+inlineToConTeXt (Subscript lst) = do+ contents <- inlineListToConTeXt lst+ return $ text "\\low{" <> contents <> char '}'+inlineToConTeXt (Code str) = return $ text $ "\\type{" ++ str ++ "}"+inlineToConTeXt (Quoted SingleQuote lst) = do+ contents <- inlineListToConTeXt lst+ return $ text "\\quote{" <> contents <> char '}'+inlineToConTeXt (Quoted DoubleQuote lst) = do+ contents <- inlineListToConTeXt lst+ return $ text "\\quotation{" <> contents <> char '}'+inlineToConTeXt Apostrophe = return $ char '\''+inlineToConTeXt EmDash = return $ text "---"+inlineToConTeXt EnDash = return $ text "--"+inlineToConTeXt Ellipses = return $ text "\\ldots{}"+inlineToConTeXt (Str str) = return $ text $ stringToConTeXt str+inlineToConTeXt (Math str) = return $ char '$' <> text str <> char '$'+inlineToConTeXt (TeX str) = return $ text str+inlineToConTeXt (HtmlInline str) = return empty+inlineToConTeXt (LineBreak) = return $ text "\\crlf\n"+inlineToConTeXt Space = return $ char ' '+inlineToConTeXt (Link [Code str] (src, tit)) = -- since ConTeXt has its own + inlineToConTeXt (Link [Str str] (src, tit)) -- way of printing links... +inlineToConTeXt (Link txt (src, _)) = do+ st <- get+ let next = stNextRef st+ put $ st {stNextRef = next + 1}+ let ref = show next+ label <- inlineListToConTeXt txt+ return $ text "\\useURL[" <> text ref <> text "][" <> text src <>+ text "][][" <> label <> text "]\\from[" <> text ref <> char ']'+inlineToConTeXt (Image alternate (src, tit)) = do+ alt <- inlineListToConTeXt alternate+ return $ text "\\placefigure\n[]\n[fig:" <> alt <> text "]\n{" <> + text tit <> text "}\n{\\externalfigure[" <> text src <> text "]}" +inlineToConTeXt (Note contents) = do+ contents' <- blockListToConTeXt contents+ let rawnote = stripTrailingNewlines $ render contents'+ -- note: a \n before } is needed when note ends with a \stoptyping+ let optNewline = "\\stoptyping" `isSuffixOf` rawnote+ return $ text "\\footnote{" <> + text rawnote <> (if optNewline then char '\n' else empty) <> char '}'+
+ Text/Pandoc/Writers/DefaultHeaders.hs view
@@ -0,0 +1,59 @@+----------------------------------------------------+-- Do not edit this file by hand. Edit +-- 'templates/DefaultHeaders.hs'+-- and run ./fillTemplates.pl Text/Pandoc/Writers/DefaultHeaders.hs+----------------------------------------------------++{-+Copyright (C) 2006-7 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.DefaultHeaders+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Default headers for Pandoc writers.+-}+module Text.Pandoc.Writers.DefaultHeaders (+ defaultLaTeXHeader,+ defaultConTeXtHeader,+ defaultDocbookHeader,+ defaultS5Header,+ defaultRTFHeader+ ) where+import Text.Pandoc.Writers.S5++defaultLaTeXHeader :: String+defaultLaTeXHeader = "\\documentclass{article}\n\\usepackage[mathletters]{ucs}\n\\usepackage[utf8x]{inputenc}\n\\setlength{\\parindent}{0pt}\n\\setlength{\\parskip}{6pt plus 2pt minus 1pt}\n"++defaultConTeXtHeader :: String+defaultConTeXtHeader = "\\enableregime[utf] % use UTF-8\n\n\\setupcolors[state=start]\n\\setupinteraction[state=start, color=middleblue] % needed for hyperlinks\n\n\\setuppapersize[letter][letter] % use letter paper\n\\setuplayout[width=middle, backspace=1.5in, cutspace=1.5in,\n height=middle, header=0.75in, footer=0.75in] % page layout\n\\setuppagenumbering[location={footer,center}] % number pages\n\\setupbodyfont[11pt] % 11pt font\n\\setupwhitespace[medium] % inter-paragraph spacing\n\n\\setuphead[section][style=\\tfc]\n\\setuphead[subsection][style=\\tfb]\n\\setuphead[subsubsection][style=\\bf]\n\n% define title block commands\n\\unprotect\n\\def\\doctitle#1{\\gdef\\@title{#1}}\n\\def\\author#1{\\gdef\\@author{#1}}\n\\def\\date#1{\\gdef\\@date{#1}}\n\\date{\\currentdate} % Default to today unless specified otherwise.\n\\def\\maketitle{%\n \\startalignment[center]\n \\blank[2*big]\n {\\tfd \\@title}\n \\blank[3*medium]\n {\\tfa \\@author}\n \\blank[2*medium]\n {\\tfa \\@date}\n \\blank[3*medium]\n \\stopalignment}\n\\protect\n\n% define descr (for definition lists)\n\\definedescription[descr][\n headstyle=bold,style=normal,align=left,location=hanging,\n width=broad,margin=1cm]\n\n% define defaults for bulleted lists \n\\setupitemize[1][symbol=1][indentnext=no]\n\\setupitemize[2][symbol=2][indentnext=no]\n\\setupitemize[3][symbol=3][indentnext=no]\n\\setupitemize[4][symbol=4][indentnext=no]\n\n\\setupthinrules[width=15em] % width of horizontal rules\n\n% for block quotations\n\\unprotect\n\n\\startvariables all\nblockquote: blockquote\n\\stopvariables\n\n\\definedelimitedtext\n[\\v!blockquote][\\v!quotation]\n\n\\setupdelimitedtext\n[\\v!blockquote]\n[\\c!left=,\n\\c!right=,\nbefore={\\blank[medium]},\nafter={\\blank[medium]},\n]\n\n\\protect\n\t\n"++defaultDocbookHeader :: String+defaultDocbookHeader = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!DOCTYPE article PUBLIC \"-//OASIS//DTD DocBook XML V4.4//EN\"\n \"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd\">\n"++defaultS5Header :: String+defaultS5Header = s5Meta ++ s5CSS ++ s5Javascript++defaultRTFHeader :: String+defaultRTFHeader = "{\\rtf1\\ansi\\deff0{\\fonttbl{\\f0 \\fswiss Helvetica;}{\\f1 Courier;}}\n{\\colortbl;\\red255\\green0\\blue0;\\red0\\green0\\blue255;}\n\\widowctrl\\hyphauto\n\n"+
+ Text/Pandoc/Writers/Docbook.hs view
@@ -0,0 +1,301 @@+{-+Copyright (C) 2006-7 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.Docbook+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to Docbook XML.+-}+module Text.Pandoc.Writers.Docbook ( writeDocbook) where+import Text.Pandoc.Definition+import Text.Pandoc.Shared+import Text.Pandoc.Readers.TeXMath+import Data.List ( isPrefixOf, drop )+import Text.PrettyPrint.HughesPJ hiding ( Str )++--+-- code to format XML+--++-- | Escape one character as needed for XML.+escapeCharForXML :: Char -> String+escapeCharForXML x = case x of+ '&' -> "&"+ '<' -> "<"+ '>' -> ">"+ '"' -> """+ '\160' -> " "+ c -> [c] ++-- | True if the character needs to be escaped.+needsEscaping :: Char -> Bool+needsEscaping c = c `elem` "&<>\"\160"++-- | Escape string as needed for XML. Entity references are not preserved.+escapeStringForXML :: String -> String+escapeStringForXML "" = ""+escapeStringForXML str = + case break needsEscaping str of+ (okay, "") -> okay+ (okay, (c:cs)) -> okay ++ escapeCharForXML c ++ escapeStringForXML cs ++-- | Return a text object with a string of formatted XML attributes. +attributeList :: [(String, String)] -> Doc+attributeList = text . concatMap + (\(a, b) -> " " ++ escapeStringForXML a ++ "=\"" ++ + escapeStringForXML b ++ "\"") ++-- | Put the supplied contents between start and end tags of tagType,+-- with specified attributes and (if specified) indentation.+inTags:: Bool -> String -> [(String, String)] -> Doc -> Doc+inTags isIndented tagType attribs contents = + let openTag = char '<' <> text tagType <> attributeList attribs <> + char '>'+ closeTag = text "</" <> text tagType <> char '>'+ in if isIndented+ then openTag $$ nest 2 contents $$ closeTag+ else openTag <> contents <> closeTag++-- | Return a self-closing tag of tagType with specified attributes+selfClosingTag :: String -> [(String, String)] -> Doc+selfClosingTag tagType attribs = + char '<' <> text tagType <> attributeList attribs <> text " />" + +-- | Put the supplied contents between start and end tags of tagType.+inTagsSimple :: String -> Doc -> Doc+inTagsSimple tagType = inTags False tagType []++-- | Put the supplied contents in indented block btw start and end tags.+inTagsIndented :: String -> Doc -> Doc+inTagsIndented tagType = inTags True tagType []++--+-- Docbook writer+--++-- | Convert list of authors to a docbook <author> section+authorToDocbook :: [Char] -> Doc+authorToDocbook name = inTagsIndented "author" $ + if ',' `elem` name+ then -- last name first+ let (lastname, rest) = break (==',') name + firstname = removeLeadingSpace rest in+ inTagsSimple "firstname" (text $ escapeStringForXML firstname) <> + inTagsSimple "surname" (text $ escapeStringForXML lastname) + else -- last name last+ let namewords = words name+ lengthname = length namewords + (firstname, lastname) = case lengthname of+ 0 -> ("","") + 1 -> ("", name)+ n -> (joinWithSep " " (take (n-1) namewords), last namewords)+ in inTagsSimple "firstname" (text $ escapeStringForXML firstname) $$ + inTagsSimple "surname" (text $ escapeStringForXML lastname) ++-- | Convert Pandoc document to string in Docbook format.+writeDocbook :: WriterOptions -> Pandoc -> String+writeDocbook opts (Pandoc (Meta title authors date) blocks) = + let head = if writerStandalone opts+ then text (writerHeader opts)+ else empty+ meta = if writerStandalone opts+ then inTagsIndented "articleinfo" $+ (inTagsSimple "title" (wrap opts title)) $$ + (vcat (map authorToDocbook authors)) $$ + (inTagsSimple "date" (text $ escapeStringForXML date)) + else empty+ elements = hierarchicalize blocks+ before = writerIncludeBefore opts+ after = writerIncludeAfter opts+ body = (if null before then empty else text before) $$+ vcat (map (elementToDocbook opts) elements) $$+ (if null after then empty else text after)+ body' = if writerStandalone opts+ then inTagsIndented "article" (meta $$ body)+ else body + in render $ head $$ body' $$ text ""++-- | Convert an Element to Docbook.+elementToDocbook :: WriterOptions -> Element -> Doc+elementToDocbook opts (Blk block) = blockToDocbook opts block +elementToDocbook opts (Sec title elements) =+ -- Docbook doesn't allow sections with no content, so insert some if needed+ let elements' = if null elements+ then [Blk (Para [])]+ else elements+ in inTagsIndented "section" $+ inTagsSimple "title" (wrap opts title) $$+ vcat (map (elementToDocbook opts) elements') ++-- | Convert a list of Pandoc blocks to Docbook.+blocksToDocbook :: WriterOptions -> [Block] -> Doc+blocksToDocbook opts = vcat . map (blockToDocbook opts)++-- | Auxiliary function to convert Plain block to Para.+plainToPara (Plain x) = Para x+plainToPara x = x++-- | Convert a list of pairs of terms and definitions into a list of +-- Docbook varlistentrys.+deflistItemsToDocbook :: WriterOptions -> [([Inline],[Block])] -> Doc+deflistItemsToDocbook opts items = + vcat $ map (\(term, def) -> deflistItemToDocbook opts term def) items++-- | Convert a term and a list of blocks into a Docbook varlistentry.+deflistItemToDocbook :: WriterOptions -> [Inline] -> [Block] -> Doc+deflistItemToDocbook opts term def =+ let def' = map plainToPara def+ in inTagsIndented "varlistentry" $+ inTagsIndented "term" (inlinesToDocbook opts term) $$+ inTagsIndented "listitem" (blocksToDocbook opts def')++-- | Convert a list of lists of blocks to a list of Docbook list items.+listItemsToDocbook :: WriterOptions -> [[Block]] -> Doc+listItemsToDocbook opts items = vcat $ map (listItemToDocbook opts) items++-- | Convert a list of blocks into a Docbook list item.+listItemToDocbook :: WriterOptions -> [Block] -> Doc+listItemToDocbook opts item =+ inTagsIndented "listitem" $ blocksToDocbook opts $ map plainToPara item++-- | Convert a Pandoc block element to Docbook.+blockToDocbook :: WriterOptions -> Block -> Doc+blockToDocbook opts Null = empty+blockToDocbook opts (Plain lst) = wrap opts lst+blockToDocbook opts (Para lst) = inTagsIndented "para" $ wrap opts lst+blockToDocbook opts (BlockQuote blocks) =+ inTagsIndented "blockquote" $ blocksToDocbook opts blocks+blockToDocbook opts (CodeBlock str) = + text "<screen>\n" <> text (escapeStringForXML str) <> text "\n</screen>"+blockToDocbook opts (BulletList lst) = + inTagsIndented "itemizedlist" $ listItemsToDocbook opts lst +blockToDocbook opts (OrderedList _ []) = empty +blockToDocbook opts (OrderedList (start, numstyle, numdelim) (first:rest)) =+ let attribs = case numstyle of+ DefaultStyle -> []+ Decimal -> [("numeration", "arabic")]+ UpperAlpha -> [("numeration", "upperalpha")]+ LowerAlpha -> [("numeration", "loweralpha")]+ UpperRoman -> [("numeration", "upperroman")]+ LowerRoman -> [("numeration", "lowerroman")]+ items = if start == 1+ then listItemsToDocbook opts (first:rest)+ else (inTags True "listitem" [("override",show start)]+ (blocksToDocbook opts $ map plainToPara first)) $$ + listItemsToDocbook opts rest + in inTags True "orderedlist" attribs items+blockToDocbook opts (DefinitionList lst) = + inTagsIndented "variablelist" $ deflistItemsToDocbook opts lst +blockToDocbook opts (RawHtml str) = text str -- raw XML block +blockToDocbook opts HorizontalRule = empty -- not semantic+blockToDocbook opts (Table caption aligns widths headers rows) =+ let alignStrings = map alignmentToString aligns+ captionDoc = if null caption+ then empty+ else inTagsIndented "caption" + (inlinesToDocbook opts caption)+ tableType = if isEmpty captionDoc then "informaltable" else "table"+ in inTagsIndented tableType $ captionDoc $$+ (colHeadsToDocbook opts alignStrings widths headers) $$ + (vcat $ map (tableRowToDocbook opts alignStrings) rows)++colHeadsToDocbook opts alignStrings widths headers =+ let heads = zipWith3 (\align width item -> + tableItemToDocbook opts "th" align width item) + alignStrings widths headers+ in inTagsIndented "tr" $ vcat heads++alignmentToString alignment = case alignment of+ AlignLeft -> "left"+ AlignRight -> "right"+ AlignCenter -> "center"+ AlignDefault -> "left"++tableRowToDocbook opts aligns cols = inTagsIndented "tr" $ + vcat $ zipWith3 (tableItemToDocbook opts "td") aligns (repeat 0) cols++tableItemToDocbook opts tag align width item =+ let attrib = [("align", align)] ++ + if width /= 0+ then [("style", "{width: " ++ + show (truncate (100*width)) ++ "%;}")]+ else [] + in inTags True tag attrib $ vcat $ map (blockToDocbook opts) item++-- | Take list of inline elements and return wrapped doc.+wrap :: WriterOptions -> [Inline] -> Doc+wrap opts lst = if writerWrapText opts+ then fsep $ map (inlinesToDocbook opts) (splitBy Space lst)+ else inlinesToDocbook opts lst++-- | Convert a list of inline elements to Docbook.+inlinesToDocbook :: WriterOptions -> [Inline] -> Doc+inlinesToDocbook opts lst = hcat $ map (inlineToDocbook opts) lst++-- | Convert an inline element to Docbook.+inlineToDocbook :: WriterOptions -> Inline -> Doc+inlineToDocbook opts (Str str) = text $ escapeStringForXML str +inlineToDocbook opts (Emph lst) = + inTagsSimple "emphasis" $ inlinesToDocbook opts lst+inlineToDocbook opts (Strong lst) = + inTags False "emphasis" [("role", "strong")] $ inlinesToDocbook opts lst+inlineToDocbook opts (Strikeout lst) = + inTags False "emphasis" [("role", "strikethrough")] $+ inlinesToDocbook opts lst+inlineToDocbook opts (Superscript lst) = + inTagsSimple "superscript" $ inlinesToDocbook opts lst+inlineToDocbook opts (Subscript lst) = + inTagsSimple "subscript" $ inlinesToDocbook opts lst+inlineToDocbook opts (Quoted _ lst) = + inTagsSimple "quote" $ inlinesToDocbook opts lst+inlineToDocbook opts Apostrophe = char '\''+inlineToDocbook opts Ellipses = text "…"+inlineToDocbook opts EmDash = text "—" +inlineToDocbook opts EnDash = text "–" +inlineToDocbook opts (Code str) = + inTagsSimple "literal" $ text (escapeStringForXML str)+inlineToDocbook opts (Math str) = inlinesToDocbook opts $ readTeXMath str+inlineToDocbook opts (TeX str) = empty+inlineToDocbook opts (HtmlInline str) = empty+inlineToDocbook opts LineBreak = text $ "<literallayout></literallayout>" +inlineToDocbook opts Space = char ' '+inlineToDocbook opts (Link txt (src, tit)) =+ if isPrefixOf "mailto:" src+ then let src' = drop 7 src+ emailLink = inTagsSimple "email" $ text $ + escapeStringForXML $ src'+ in if txt == [Code src']+ then emailLink+ else inlinesToDocbook opts txt <+> char '(' <> emailLink <> + char ')'+ else inTags False "ulink" [("url", src)] $ inlinesToDocbook opts txt+inlineToDocbook opts (Image alt (src, tit)) = + let titleDoc = if null tit+ then empty+ else inTagsIndented "objectinfo" $+ inTagsIndented "title" (text $ escapeStringForXML tit)+ in inTagsIndented "inlinemediaobject" $ inTagsIndented "imageobject" $+ titleDoc $$ selfClosingTag "imagedata" [("fileref", src)] +inlineToDocbook opts (Note contents) = + inTagsIndented "footnote" $ blocksToDocbook opts contents
+ Text/Pandoc/Writers/HTML.hs view
@@ -0,0 +1,473 @@+{-+Copyright (C) 2006-7 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.HTML + Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to HTML.+-}+module Text.Pandoc.Writers.HTML ( writeHtml , writeHtmlString ) where+import Text.Pandoc.Definition+import Text.Pandoc.ASCIIMathML+import Text.Pandoc.CharacterReferences ( decodeCharacterReferences )+import Text.Pandoc.Shared+import Text.Pandoc.Readers.TeXMath+import Text.Regex ( mkRegex, matchRegex )+import Numeric ( showHex )+import Data.Char ( ord, toLower )+import Data.List ( isPrefixOf, intersperse )+import qualified Data.Set as S+import Control.Monad.State+import Text.XHtml.Transitional++data WriterState = WriterState+ { stNotes :: [Html] -- ^ List of notes+ , stIds :: [String] -- ^ List of header identifiers+ , stMath :: Bool -- ^ Math is used in document+ , stCSS :: S.Set String -- ^ CSS to include in header+ } deriving Show++defaultWriterState :: WriterState+defaultWriterState = WriterState {stNotes= [], stIds = [], + stMath = False, stCSS = S.empty}++-- Helpers to render HTML with the appropriate function.+render opts = if writerWrapText opts then renderHtml else showHtml+renderFragment opts = if writerWrapText opts+ then renderHtmlFragment+ else showHtmlFragment++-- | Convert Pandoc document to Html string.+writeHtmlString :: WriterOptions -> Pandoc -> String+writeHtmlString opts = + if writerStandalone opts+ then render opts . writeHtml opts+ else renderFragment opts . writeHtml opts++-- | Convert Pandoc document to Html structure.+writeHtml :: WriterOptions -> Pandoc -> Html+writeHtml opts (Pandoc (Meta tit authors date) blocks) = + let titlePrefix = writerTitlePrefix opts+ topTitle = evalState (inlineListToHtml opts tit) defaultWriterState+ topTitle' = if null titlePrefix+ then topTitle+ else titlePrefix +++ " - " +++ topTitle+ metadata = thetitle topTitle' +++ + meta ! [httpequiv "Content-Type", + content "text/html; charset=UTF-8"] ++++ meta ! [name "generator", content "pandoc"] ++++ (toHtmlFromList $ + map (\a -> meta ! [name "author", content a]) authors) ++++ (if null date+ then noHtml+ else meta ! [name "date", content date])+ titleHeader = if writerStandalone opts && not (null tit) && + not (writerS5 opts)+ then h1 ! [theclass "title"] $ topTitle+ else noHtml+ headerBlocks = filter isHeaderBlock blocks+ ids = uniqueIdentifiers $ + map (\(Header _ lst) -> lst) headerBlocks+ toc = if writerTableOfContents opts + then tableOfContents opts headerBlocks ids+ else noHtml+ (blocks', newstate) = + runState (blockListToHtml opts blocks)+ (defaultWriterState {stIds = ids})+ cssLines = stCSS newstate+ css = if S.null cssLines+ then noHtml+ else style ! [thetype "text/css"] $ primHtml $+ '\n':(unlines $ S.toList cssLines)+ math = if stMath newstate+ then case writerHTMLMathMethod opts of+ ASCIIMathML Nothing -> + primHtml asciiMathMLScript+ ASCIIMathML (Just url) ->+ script ! + [src url, thetype "text/javascript"] $+ noHtml+ _ -> noHtml+ else noHtml+ head = header $ metadata +++ math +++ css +++ + primHtml (writerHeader opts)+ notes = reverse (stNotes newstate)+ before = primHtml $ writerIncludeBefore opts+ after = primHtml $ writerIncludeAfter opts+ thebody = before +++ titleHeader +++ toc +++ blocks' ++++ footnoteSection opts notes +++ after+ in if writerStandalone opts+ then head +++ body thebody+ else thebody++-- | Construct table of contents from list of header blocks and identifiers.+-- Assumes there are as many identifiers as header blocks.+tableOfContents :: WriterOptions -> [Block] -> [String] -> Html+tableOfContents _ [] _ = noHtml+tableOfContents opts headers ids =+ let opts' = opts { writerIgnoreNotes = True }+ contentsTree = hierarchicalize headers+ contents = evalState (mapM (elementToListItem opts') contentsTree) + (defaultWriterState {stIds = ids})+ in thediv ! [identifier "toc"] $ unordList contents++-- | Converts an Element to a list item for a table of contents,+-- retrieving the appropriate identifier from state.+elementToListItem :: WriterOptions -> Element -> State WriterState Html+elementToListItem opts (Blk _) = return noHtml+elementToListItem opts (Sec headerText subsecs) = do+ st <- get+ let ids = stIds st+ let (id, rest) = if null ids+ then ("", [])+ else (head ids, tail ids)+ put $ st {stIds = rest}+ txt <- inlineListToHtml opts headerText+ subHeads <- mapM (elementToListItem opts) subsecs+ let subList = if null subHeads+ then noHtml+ else unordList subHeads + return $ (anchor ! [href ("#" ++ id), identifier ("TOC-" ++ id)] $ txt) +++ + subList++-- | Convert list of Note blocks to a footnote <div>.+-- Assumes notes are sorted.+footnoteSection :: WriterOptions -> [Html] -> Html+footnoteSection opts notes =+ if null notes + then noHtml+ else thediv ! [theclass "footnotes"] $ hr +++ (olist << notes)++-- | Obfuscate a "mailto:" link using Javascript.+obfuscateLink :: WriterOptions -> String -> String -> Html+obfuscateLink opts text src =+ let emailRegex = mkRegex "^mailto:([^@]*)@(.*)$"+ src' = map toLower src+ in case (matchRegex emailRegex src') of+ (Just [name, domain]) ->+ let domain' = substitute "." " dot " domain+ at' = obfuscateChar '@'+ (linkText, altText) = + if text == drop 7 src' -- autolink+ then ("'<code>'+e+'</code>'", name ++ " at " ++ domain')+ else ("'" ++ text ++ "'", text ++ " (" ++ name ++ " at " ++ + domain' ++ ")")+ in if writerStrictMarkdown opts+ then -- need to use primHtml or &'s are escaped to & in URL+ primHtml $ "<a href=\"" ++ (obfuscateString src')+ ++ "\">" ++ (obfuscateString text) ++ "</a>"+ else (script ! [thetype "text/javascript"] $+ primHtml ("\n<!--\nh='" ++ + obfuscateString domain ++ "';a='" ++ at' ++ "';n='" ++ + obfuscateString name ++ "';e=n+a+h;\n" +++ "document.write('<a h'+'ref'+'=\"ma'+'ilto'+':'+e+'\">'+" ++ + linkText ++ "+'<\\/'+'a'+'>');\n// -->\n")) +++ + noscript (primHtml $ obfuscateString altText)+ _ -> anchor ! [href src] $ primHtml text -- malformed email++-- | Obfuscate character as entity.+obfuscateChar :: Char -> String+obfuscateChar char = + let num = ord char+ numstr = if even num then show num else "x" ++ showHex num ""+ in "&#" ++ numstr ++ ";"++-- | Obfuscate string using entities.+obfuscateString :: String -> String+obfuscateString = concatMap obfuscateChar . decodeCharacterReferences++-- | True if character is a punctuation character (unicode).+isPunctuation :: Char -> Bool+isPunctuation c =+ let c' = ord c+ in if c `elem` "!\"'()*,-./:;<>?[\\]`{|}~" || c' >= 0x2000 && c' <= 0x206F ||+ c' >= 0xE000 && c' <= 0xE0FF+ then True+ else False++-- | Add CSS for document header.+addToCSS :: String -> State WriterState ()+addToCSS item = do+ st <- get+ let current = stCSS st+ put $ st {stCSS = S.insert item current}++-- | Convert Pandoc inline list to plain text identifier.+inlineListToIdentifier :: [Inline] -> String+inlineListToIdentifier [] = ""+inlineListToIdentifier (x:xs) = + xAsText ++ inlineListToIdentifier xs+ where xAsText = case x of+ Str s -> filter (\c -> c == '-' || not (isPunctuation c)) $+ concat $ intersperse "-" $ words $ map toLower s+ Emph lst -> inlineListToIdentifier lst+ Strikeout lst -> inlineListToIdentifier lst+ Superscript lst -> inlineListToIdentifier lst+ Subscript lst -> inlineListToIdentifier lst+ Strong lst -> inlineListToIdentifier lst+ Quoted _ lst -> inlineListToIdentifier lst+ Code s -> s+ Space -> "-"+ EmDash -> "-"+ EnDash -> "-"+ Apostrophe -> ""+ Ellipses -> ""+ LineBreak -> "-"+ Math _ -> ""+ TeX _ -> ""+ HtmlInline _ -> ""+ Link lst _ -> inlineListToIdentifier lst+ Image lst _ -> inlineListToIdentifier lst+ Note _ -> ""++-- | Return unique identifiers for list of inline lists.+uniqueIdentifiers :: [[Inline]] -> [String]+uniqueIdentifiers ls =+ let addIdentifier (nonuniqueIds, uniqueIds) l =+ let new = inlineListToIdentifier l+ matches = length $ filter (== new) nonuniqueIds+ new' = new ++ if matches > 0 then ("-" ++ show matches) else ""+ in (new:nonuniqueIds, new':uniqueIds)+ in reverse $ snd $ foldl addIdentifier ([],[]) ls++-- | Convert Pandoc block element to HTML.+blockToHtml :: WriterOptions -> Block -> State WriterState Html+blockToHtml opts Null = return $ noHtml +blockToHtml opts (Plain lst) = inlineListToHtml opts lst+blockToHtml opts (Para lst) = inlineListToHtml opts lst >>= (return . paragraph)+blockToHtml opts (RawHtml str) = return $ primHtml str+blockToHtml opts (HorizontalRule) = return $ hr+blockToHtml opts (CodeBlock str) = return $ pre $ thecode << (str ++ "\n") + -- the final \n for consistency with Markdown.pl+blockToHtml opts (BlockQuote blocks) =+ -- in S5, treat list in blockquote specially+ -- if default is incremental, make it nonincremental; + -- otherwise incremental+ if writerS5 opts+ then let inc = not (writerIncremental opts) in+ case blocks of + [BulletList lst] -> blockToHtml (opts {writerIncremental = inc})+ (BulletList lst)+ [OrderedList attribs lst] -> + blockToHtml (opts {writerIncremental = inc})+ (OrderedList attribs lst)+ otherwise -> blockListToHtml opts blocks >>= + (return . blockquote)+ else blockListToHtml opts blocks >>= (return . blockquote)+blockToHtml opts (Header level lst) = do + contents <- inlineListToHtml opts lst+ st <- get+ let ids = stIds st+ let (id, rest) = if null ids+ then ("", [])+ else (head ids, tail ids)+ put $ st {stIds = rest}+ let attribs = if writerStrictMarkdown opts && not (writerTableOfContents opts)+ then []+ else [identifier id]+ let contents' = if writerTableOfContents opts+ then anchor ! [href ("#TOC-" ++ id)] $ contents+ else contents+ return $ case level of+ 1 -> h1 contents' ! attribs+ 2 -> h2 contents' ! attribs+ 3 -> h3 contents' ! attribs+ 4 -> h4 contents' ! attribs+ 5 -> h5 contents' ! attribs+ 6 -> h6 contents' ! attribs+ _ -> paragraph contents' ! attribs+blockToHtml opts (BulletList lst) = do+ contents <- mapM (blockListToHtml opts) lst+ let attribs = if writerIncremental opts+ then [theclass "incremental"]+ else []+ return $ unordList ! attribs $ contents+blockToHtml opts (OrderedList (startnum, numstyle, _) lst) = do+ contents <- mapM (blockListToHtml opts) lst+ let numstyle' = camelCaseToHyphenated $ show numstyle+ let attribs = (if writerIncremental opts+ then [theclass "incremental"]+ else []) +++ (if startnum /= 1+ then [start startnum]+ else []) +++ (if numstyle /= DefaultStyle+ then [theclass numstyle']+ else [])+ if numstyle /= DefaultStyle+ then addToCSS $ "ol." ++ numstyle' ++ + " { list-style-type: " ++ + numstyle' ++ "; }"+ else return ()+ return $ ordList ! attribs $ contents+blockToHtml opts (DefinitionList lst) = do+ contents <- mapM (\(term, def) -> do term' <- inlineListToHtml opts term+ def' <- blockListToHtml opts def+ return $ (term', def')) lst+ let attribs = if writerIncremental opts+ then [theclass "incremental"]+ else []+ return $ defList ! attribs $ contents+blockToHtml opts (Table capt aligns widths headers rows) = do+ let alignStrings = map alignmentToString aligns+ captionDoc <- if null capt+ then return noHtml+ else inlineListToHtml opts capt >>= return . caption+ colHeads <- colHeadsToHtml opts alignStrings + widths headers+ rows' <- mapM (tableRowToHtml opts alignStrings) rows+ return $ table $ captionDoc +++ colHeads +++ rows'++colHeadsToHtml opts alignStrings widths headers = do+ heads <- sequence $ zipWith3 + (\align width item -> tableItemToHtml opts th align width item) + alignStrings widths headers+ return $ tr $ toHtmlFromList heads++alignmentToString alignment = case alignment of+ AlignLeft -> "left"+ AlignRight -> "right"+ AlignCenter -> "center"+ AlignDefault -> "left"++tableRowToHtml opts aligns cols = + (sequence $ zipWith3 (tableItemToHtml opts td) aligns (repeat 0) cols) >>=+ return . tr . toHtmlFromList++tableItemToHtml opts tag align' width item = do+ contents <- blockListToHtml opts item+ let attrib = [align align'] ++ + if width /= 0 + then [thestyle ("width: " ++ show (truncate (100*width)) ++ + "%;")]+ else [] + return $ tag ! attrib $ contents++blockListToHtml :: WriterOptions -> [Block] -> State WriterState Html+blockListToHtml opts lst = + mapM (blockToHtml opts) lst >>= return . toHtmlFromList++-- | Convert list of Pandoc inline elements to HTML.+inlineListToHtml :: WriterOptions -> [Inline] -> State WriterState Html+inlineListToHtml opts lst = + mapM (inlineToHtml opts) lst >>= return . toHtmlFromList++-- | Convert Pandoc inline element to HTML.+inlineToHtml :: WriterOptions -> Inline -> State WriterState Html+inlineToHtml opts inline =+ case inline of + (Str str) -> return $ stringToHtml str+ (Space) -> return $ stringToHtml " "+ (LineBreak) -> return $ br+ (EmDash) -> return $ primHtmlChar "mdash"+ (EnDash) -> return $ primHtmlChar "ndash"+ (Ellipses) -> return $ primHtmlChar "hellip"+ (Apostrophe) -> return $ primHtmlChar "rsquo"+ (Emph lst) -> inlineListToHtml opts lst >>= return . emphasize+ (Strong lst) -> inlineListToHtml opts lst >>= return . strong+ (Code str) -> return $ thecode << str+ (Strikeout lst) -> addToCSS + ".strikeout { text-decoration: line-through; }" >> + inlineListToHtml opts lst >>=+ return . (thespan ! [theclass "strikeout"])+ (Superscript lst) -> inlineListToHtml opts lst >>= return . sup+ (Subscript lst) -> inlineListToHtml opts lst >>= return . sub+ (Quoted quoteType lst) ->+ let (leftQuote, rightQuote) = case quoteType of+ SingleQuote -> (primHtmlChar "lsquo", + primHtmlChar "rsquo")+ DoubleQuote -> (primHtmlChar "ldquo", + primHtmlChar "rdquo")+ in do contents <- inlineListToHtml opts lst+ return $ leftQuote +++ contents +++ rightQuote+ (Math str) -> modify (\st -> st {stMath = True}) >> + (case writerHTMLMathMethod opts of+ ASCIIMathML _ -> + return $ stringToHtml ("$" ++ str ++ "$")+ MimeTeX url -> + return $ image ! [src (url ++ "?" ++ str),+ alt str, title str]+ GladTeX ->+ return $ primHtml $ "<EQ>" ++ str ++ "</EQ>"+ PlainMath -> + inlineListToHtml opts (readTeXMath str) >>=+ return . (thespan ! [theclass "math"])) + (TeX str) -> return noHtml+ (HtmlInline str) -> return $ primHtml str + (Link [Code str] (src,tit)) | "mailto:" `isPrefixOf` src ->+ return $ obfuscateLink opts str src+ (Link txt (src,tit)) | "mailto:" `isPrefixOf` src -> do+ linkText <- inlineListToHtml opts txt + return $ obfuscateLink opts (show linkText) src+ (Link txt (src,tit)) -> do+ linkText <- inlineListToHtml opts txt+ return $ anchor ! ([href src] ++ + if null tit then [] else [title tit]) $ + linkText+ (Image txt (source,tit)) -> do+ alternate <- inlineListToHtml opts txt+ let alternate' = renderFragment opts alternate+ let attributes = [src source] +++ (if null tit + then [] + else [title tit]) ++ + if null txt + then [] + else [alt alternate']+ return $ image ! attributes + -- note: null title included, as in Markdown.pl + (Note contents) -> do + st <- get+ let notes = stNotes st+ let number = (length notes) + 1+ let ref = show number+ htmlContents <- blockListToNote opts ref contents + -- push contents onto front of notes+ put $ st {stNotes = (htmlContents:notes)} + return $ anchor ! [href ("#fn" ++ ref),+ theclass "footnoteRef",+ identifier ("fnref" ++ ref)] << + sup << ref++blockListToNote :: WriterOptions -> String -> [Block] -> State WriterState Html+blockListToNote opts ref blocks =+ -- If last block is Para or Plain, include the backlink at the end of+ -- that block. Otherwise, insert a new Plain block with the backlink.+ let backlink = [HtmlInline $ " <a href=\"#fnref" ++ ref ++ + "\" class=\"footnoteBackLink\"" +++ " title=\"Jump back to footnote " ++ ref ++ "\">↩</a>"]+ blocks' = if null blocks+ then []+ else let lastBlock = last blocks+ otherBlocks = init blocks+ in case lastBlock of+ (Para lst) -> otherBlocks +++ [Para (lst ++ backlink)]+ (Plain lst) -> otherBlocks +++ [Plain (lst ++ backlink)]+ _ -> otherBlocks ++ [lastBlock,+ Plain backlink]+ in do contents <- blockListToHtml opts blocks'+ return $ li ! [identifier ("fn" ++ ref)] $ contents+
+ Text/Pandoc/Writers/LaTeX.hs view
@@ -0,0 +1,319 @@+{-+Copyright (C) 2006-7 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.LaTeX+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha + Portability : portable++Conversion of 'Pandoc' format into LaTeX.+-}+module Text.Pandoc.Writers.LaTeX ( writeLaTeX ) where+import Text.Pandoc.Definition+import Text.Pandoc.Shared+import Text.Printf ( printf )+import Data.List ( (\\), isInfixOf, isSuffixOf, intersperse )+import Data.Char ( toLower )+import qualified Data.Set as S+import Control.Monad.State+import Text.PrettyPrint.HughesPJ hiding ( Str )++data WriterState = + WriterState { stIncludes :: S.Set String -- strings to include in header+ , stInNote :: Bool -- @True@ if we're in a note+ , stOLLevel :: Int -- level of ordered list nesting+ , stOptions :: WriterOptions -- writer options, so they don't have to be parameter + }++-- | Add line to header.+addToHeader :: String -> State WriterState ()+addToHeader str = do+ st <- get+ let includes = stIncludes st+ put st {stIncludes = S.insert str includes}++-- | Convert Pandoc to LaTeX.+writeLaTeX :: WriterOptions -> Pandoc -> String+writeLaTeX options document = + render $ evalState (pandocToLaTeX options document) $ + WriterState { stIncludes = S.empty, stInNote = False, stOLLevel = 1, stOptions = options } ++pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState Doc+pandocToLaTeX options (Pandoc meta blocks) = do+ main <- blockListToLaTeX blocks+ head <- if writerStandalone options+ then latexHeader options meta+ else return empty+ let before = if null (writerIncludeBefore options)+ then empty+ else text (writerIncludeBefore options)+ let after = if null (writerIncludeAfter options)+ then empty+ else text (writerIncludeAfter options)+ let body = before $$ main $$ after+ let toc = if writerTableOfContents options+ then text "\\tableofcontents\n"+ else empty + let foot = if writerStandalone options+ then text "\\end{document}"+ else empty + return $ head $$ toc $$ body $$ foot++-- | Insert bibliographic information into LaTeX header.+latexHeader :: WriterOptions -- ^ Options, including LaTeX header+ -> Meta -- ^ Meta with bibliographic information+ -> State WriterState Doc+latexHeader options (Meta title authors date) = do+ titletext <- if null title+ then return empty+ else inlineListToLaTeX title >>= return . inCmd "title"+ headerIncludes <- get >>= return . S.toList . stIncludes+ let extras = text $ unlines headerIncludes+ let verbatim = if "\\usepackage{fancyvrb}" `elem` headerIncludes+ then text "\\VerbatimFootnotes % allows verbatim text in footnotes"+ else empty+ let authorstext = text $ "\\author{" ++ + joinWithSep "\\\\" (map stringToLaTeX authors) ++ "}"+ let datetext = if date == ""+ then empty + else text $ "\\date{" ++ stringToLaTeX date ++ "}"+ let maketitle = if null title then empty else text "\\maketitle"+ let secnumline = if (writerNumberSections options)+ then empty + else text "\\setcounter{secnumdepth}{0}"+ let baseHeader = text $ writerHeader options+ let header = baseHeader $$ extras+ return $ header $$ secnumline $$ verbatim $$ titletext $$ authorstext $$+ datetext $$ text "\\begin{document}" $$ maketitle $$ text ""++-- escape things as needed for LaTeX++stringToLaTeX :: String -> String+stringToLaTeX = escapeStringUsing latexEscapes+ where latexEscapes = backslashEscapes "{}$%&_#" ++ + [ ('^', "\\^{}")+ , ('\\', "\\textbackslash{}")+ , ('~', "\\ensuremath{\\sim}")+ , ('|', "\\textbar{}")+ , ('<', "\\textless{}")+ , ('>', "\\textgreater{}")+ ]++-- | Puts contents into LaTeX command.+inCmd :: String -> Doc -> Doc+inCmd cmd contents = char '\\' <> text cmd <> braces contents++-- | Remove all code elements from list of inline elements+-- (because it's illegal to have verbatim inside some command arguments)+deVerb :: [Inline] -> [Inline]+deVerb [] = []+deVerb ((Code str):rest) = + (TeX $ "\\texttt{" ++ stringToLaTeX str ++ "}"):(deVerb rest)+deVerb (other:rest) = other:(deVerb rest)++-- | Convert Pandoc block element to LaTeX.+blockToLaTeX :: Block -- ^ Block to convert+ -> State WriterState Doc+blockToLaTeX Null = return empty+blockToLaTeX (Plain lst) = do+ st <- get+ let opts = stOptions st+ wrapTeXIfNeeded opts True inlineListToLaTeX lst+blockToLaTeX (Para lst) = do+ st <- get+ let opts = stOptions st+ result <- wrapTeXIfNeeded opts True inlineListToLaTeX lst+ return $ result <> char '\n'+blockToLaTeX (BlockQuote lst) = do+ contents <- blockListToLaTeX lst+ return $ text "\\begin{quote}" $$ contents $$ text "\\end{quote}"+blockToLaTeX (CodeBlock str) = do+ st <- get+ env <- if stInNote st+ then do addToHeader "\\usepackage{fancyvrb}"+ return "Verbatim"+ else return "verbatim"+ return $ text ("\\begin{" ++ env ++ "}\n") <> text str <> + text ("\n\\end{" ++ env ++ "}")+blockToLaTeX (RawHtml str) = return empty+blockToLaTeX (BulletList lst) = do+ items <- mapM listItemToLaTeX lst+ return $ text "\\begin{itemize}" $$ vcat items $$ text "\\end{itemize}"+blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do+ st <- get+ let oldlevel = stOLLevel st+ put $ st {stOLLevel = oldlevel + 1}+ items <- mapM listItemToLaTeX lst+ modify (\st -> st {stOLLevel = oldlevel})+ exemplar <- if numstyle /= DefaultStyle || numdelim /= DefaultDelim+ then do addToHeader "\\usepackage{enumerate}"+ return $ char '[' <> + text (head (orderedListMarkers (1, numstyle,+ numdelim))) <> char ']'+ else return empty+ let resetcounter = if start /= 1 && oldlevel <= 4+ then text $ "\\setcounter{enum" ++ + map toLower (toRomanNumeral oldlevel) +++ "}{" ++ show (start - 1) ++ "}"+ else empty + return $ text "\\begin{enumerate}" <> exemplar $$ resetcounter $$+ vcat items $$ text "\\end{enumerate}"+blockToLaTeX (DefinitionList lst) = do+ items <- mapM defListItemToLaTeX lst+ return $ text "\\begin{description}" $$ vcat items $$+ text "\\end{description}"+blockToLaTeX HorizontalRule = return $ text $+ "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n"+blockToLaTeX (Header level lst) = do+ txt <- inlineListToLaTeX (deVerb lst)+ return $ if (level > 0) && (level <= 3)+ then text ("\\" ++ (concat (replicate (level - 1) "sub")) ++ + "section{") <> txt <> text "}\n"+ else txt <> char '\n'+blockToLaTeX (Table caption aligns widths heads rows) = do+ headers <- tableRowToLaTeX heads+ captionText <- inlineListToLaTeX caption+ rows' <- mapM tableRowToLaTeX rows+ let colWidths = map (printf "%.2f") widths+ let colDescriptors = concat $ zipWith+ (\width align -> ">{\\PBS" ++ + (case align of + AlignLeft -> "\\raggedright"+ AlignRight -> "\\raggedleft"+ AlignCenter -> "\\centering"+ AlignDefault -> "\\raggedright") +++ "\\hspace{0pt}}p{" ++ width ++ + "\\columnwidth}")+ colWidths aligns+ let tableBody = text ("\\begin{tabular}{" ++ colDescriptors ++ "}") $$+ headers $$ text "\\hline" $$ vcat rows' $$ + text "\\end{tabular}" + let centered txt = text "\\begin{center}" $$ txt $$ text "\\end{center}"+ addToHeader "\\usepackage{array}\n\+ \% This is needed because raggedright in table elements redefines \\\\:\n\+ \\\newcommand{\\PreserveBackslash}[1]{\\let\\temp=\\\\#1\\let\\\\=\\temp}\n\+ \\\let\\PBS=\\PreserveBackslash"+ return $ if isEmpty captionText+ then centered tableBody <> char '\n'+ else text "\\begin{table}[h]" $$ centered tableBody $$ + inCmd "caption" captionText $$ text "\\end{table}\n" ++blockListToLaTeX lst = mapM blockToLaTeX lst >>= return . vcat++tableRowToLaTeX cols = mapM blockListToLaTeX cols >>= + return . ($$ text "\\\\") . foldl (\row item -> row $$+ (if isEmpty row then empty else text " & ") <> item) empty++listItemToLaTeX lst = blockListToLaTeX lst >>= return . (text "\\item " $$) .+ (nest 2)++defListItemToLaTeX (term, def) = do+ term' <- inlineListToLaTeX $ deVerb term+ def' <- blockListToLaTeX def+ return $ text "\\item[" <> term' <> text "]" $$ def'++-- | Convert list of inline elements to LaTeX.+inlineListToLaTeX :: [Inline] -- ^ Inlines to convert+ -> State WriterState Doc+inlineListToLaTeX lst = mapM inlineToLaTeX lst >>= return . hcat++isQuoted :: Inline -> Bool+isQuoted (Quoted _ _) = True+isQuoted Apostrophe = True+isQuoted _ = False++-- | Convert inline element to LaTeX+inlineToLaTeX :: Inline -- ^ Inline to convert+ -> State WriterState Doc+inlineToLaTeX (Emph lst) =+ inlineListToLaTeX (deVerb lst) >>= return . inCmd "emph"+inlineToLaTeX (Strong lst) = + inlineListToLaTeX (deVerb lst) >>= return . inCmd "textbf" +inlineToLaTeX (Strikeout lst) = do+ contents <- inlineListToLaTeX $ deVerb lst+ addToHeader "\\usepackage[normalem]{ulem}"+ return $ inCmd "sout" contents+inlineToLaTeX (Superscript lst) = + inlineListToLaTeX (deVerb lst) >>= return . inCmd "textsuperscript"+inlineToLaTeX (Subscript lst) = do+ contents <- inlineListToLaTeX $ deVerb lst+ -- oddly, latex includes \textsuperscript but not \textsubscript+ -- so we have to define it:+ addToHeader "\\newcommand{\\textsubscript}[1]{\\ensuremath{_{\\scriptsize\\textrm{#1}}}}"+ return $ inCmd "textsubscript" contents+inlineToLaTeX (Code str) = do+ st <- get+ if stInNote st+ then do addToHeader "\\usepackage{fancyvrb}"+ else return ()+ let chr = ((enumFromTo '!' '~') \\ str) !! 0+ return $ text $ "\\verb" ++ [chr] ++ str ++ [chr]+inlineToLaTeX (Quoted SingleQuote lst) = do+ contents <- inlineListToLaTeX lst+ let s1 = if (not (null lst)) && (isQuoted (head lst))+ then text "\\,"+ else empty + let s2 = if (not (null lst)) && (isQuoted (last lst))+ then text "\\,"+ else empty+ return $ char '`' <> s1 <> contents <> s2 <> char '\''+inlineToLaTeX (Quoted DoubleQuote lst) = do+ contents <- inlineListToLaTeX lst+ let s1 = if (not (null lst)) && (isQuoted (head lst))+ then text "\\,"+ else empty + let s2 = if (not (null lst)) && (isQuoted (last lst))+ then text "\\,"+ else empty+ return $ text "``" <> s1 <> contents <> s2 <> text "''"+inlineToLaTeX Apostrophe = return $ char '\''+inlineToLaTeX EmDash = return $ text "---"+inlineToLaTeX EnDash = return $ text "--"+inlineToLaTeX Ellipses = return $ text "\\ldots{}"+inlineToLaTeX (Str str) = return $ text $ stringToLaTeX str+inlineToLaTeX (Math str) = return $ char '$' <> text str <> char '$'+inlineToLaTeX (TeX str) = return $ text str+inlineToLaTeX (HtmlInline str) = return empty+inlineToLaTeX (LineBreak) = return $ text "\\\\" +inlineToLaTeX Space = return $ char ' '+inlineToLaTeX (Link txt (src, _)) = do+ addToHeader "\\usepackage[breaklinks=true]{hyperref}"+ case txt of+ [Code x] | x == src -> -- autolink+ do addToHeader "\\usepackage{url}" + return $ text $ "\\url{" ++ x ++ "}"+ _ -> do contents <- inlineListToLaTeX $ deVerb txt+ return $ text ("\\href{" ++ src ++ "}{") <> contents <> + char '}'+inlineToLaTeX (Image alternate (source, tit)) = do+ addToHeader "\\usepackage{graphicx}"+ return $ text $ "\\includegraphics{" ++ source ++ "}" +inlineToLaTeX (Note contents) = do+ st <- get+ put (st {stInNote = True})+ contents' <- blockListToLaTeX contents+ modify (\st -> st {stInNote = False})+ let rawnote = stripTrailingNewlines $ render contents'+ -- note: a \n before } is needed when note ends with a Verbatim environment+ let optNewline = "\\end{Verbatim}" `isSuffixOf` rawnote+ return $ text "\\footnote{" <> + text rawnote <> (if optNewline then char '\n' else empty) <> char '}'
+ Text/Pandoc/Writers/Man.hs view
@@ -0,0 +1,295 @@+{-+Copyright (C) 2007 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.Man + Copyright : Copyright (C) 2007 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to groff man page format.++-}+module Text.Pandoc.Writers.Man ( writeMan) where+import Text.Pandoc.Definition+import Text.Pandoc.Shared+import Text.Pandoc.Readers.TeXMath+import Text.Printf ( printf )+import Data.List ( isPrefixOf, drop, nub, intersperse )+import Text.PrettyPrint.HughesPJ hiding ( Str )+import Control.Monad.State++type Notes = [[Block]]+type Preprocessors = [String] -- e.g. "t" for tbl+type WriterState = (Notes, Preprocessors)++-- | Convert Pandoc to Man.+writeMan :: WriterOptions -> Pandoc -> String+writeMan opts document = render $ evalState (pandocToMan opts document) ([],[]) ++-- | Return groff man representation of document.+pandocToMan :: WriterOptions -> Pandoc -> State WriterState Doc+pandocToMan opts (Pandoc meta blocks) = do+ let before = writerIncludeBefore opts+ let after = writerIncludeAfter opts+ let before' = if null before then empty else text before+ let after' = if null after then empty else text after+ (head, foot) <- metaToMan opts meta+ body <- blockListToMan opts blocks+ (notes, preprocessors) <- get+ let preamble = if null preprocessors || not (writerStandalone opts)+ then empty+ else text $ ".\\\" " ++ concat (nub preprocessors)+ notes' <- notesToMan opts (reverse notes)+ return $ preamble $$ head $$ before' $$ body $$ notes' $$ foot $$ after'++-- | Insert bibliographic information into Man header and footer.+metaToMan :: WriterOptions -- ^ Options, including Man header+ -> Meta -- ^ Meta with bibliographic information+ -> State WriterState (Doc, Doc)+metaToMan options (Meta title authors date) = do+ titleText <- inlineListToMan options title+ let (cmdName, rest) = break (== ' ') $ render titleText+ let (title', section) = case reverse cmdName of+ (')':d:'(':xs) | d `elem` ['0'..'9'] -> + (text (reverse xs), char d)+ xs -> (text (reverse xs), doubleQuotes empty) + let extras = map (doubleQuotes . text . removeLeadingTrailingSpace) $+ splitBy '|' rest+ let head = (text ".TH") <+> title' <+> section <+> + doubleQuotes (text date) <+> hsep extras+ let foot = case length authors of+ 0 -> empty+ 1 -> text ".SH AUTHOR" $$ (text $ joinWithSep ", " authors)+ 2 -> text ".SH AUTHORS" $$ (text $ joinWithSep ", " authors)+ return $ if writerStandalone options+ then (head, foot)+ else (empty, empty)++-- | Return man representation of notes.+notesToMan :: WriterOptions -> [[Block]] -> State WriterState Doc+notesToMan opts notes =+ if null notes+ then return empty+ else mapM (\(num, note) -> noteToMan opts num note) (zip [1..] notes) >>= + return . (text ".SH NOTES" $$) . vcat++-- | Return man representation of a note.+noteToMan :: WriterOptions -> Int -> [Block] -> State WriterState Doc+noteToMan opts num note = do+ contents <- blockListToMan opts note+ let marker = text "\n.SS [" <> text (show num) <> char ']'+ return $ marker $$ contents ++-- | Association list of characters to escape.+manEscapes :: [(Char, String)]+manEscapes = [('\160', "\\ "), ('\'', "\\[aq]")] ++ backslashEscapes "\".@\\"++-- | Escape special characters for Man.+escapeString :: String -> String+escapeString = escapeStringUsing manEscapes++-- | Escape a literal (code) section for Man.+escapeCode :: String -> String+escapeCode = escapeStringUsing (manEscapes ++ backslashEscapes "\t ")++-- | Convert Pandoc block element to man.+blockToMan :: WriterOptions -- ^ Options+ -> Block -- ^ Block element+ -> State WriterState Doc +blockToMan opts Null = return empty+blockToMan opts (Plain inlines) = + wrapIfNeeded opts (inlineListToMan opts) inlines+blockToMan opts (Para inlines) = do+ contents <- wrapIfNeeded opts (inlineListToMan opts) inlines+ return $ text ".PP" $$ contents +blockToMan opts (RawHtml str) = return $ text str+blockToMan opts HorizontalRule = return $ text $ ".PP\n * * * * *"+blockToMan opts (Header level inlines) = do+ contents <- inlineListToMan opts inlines+ let heading = case level of+ 1 -> ".SH "+ _ -> ".SS "+ return $ text heading <> contents +blockToMan opts (CodeBlock str) = return $+ text ".PP" $$ text "\\f[CR]" $$ + text ((unlines . map (" " ++) . lines) (escapeCode str)) <> text "\\f[]"+blockToMan opts (BlockQuote blocks) = do + contents <- blockListToMan opts blocks+ return $ text ".RS" $$ contents $$ text ".RE"+blockToMan opts (Table caption alignments widths headers rows) = + let aligncode AlignLeft = "l"+ aligncode AlignRight = "r"+ aligncode AlignCenter = "c"+ aligncode AlignDefault = "l"+ in do+ caption' <- inlineListToMan opts caption+ modify (\(notes, preprocessors) -> (notes, "t":preprocessors))+ let iwidths = map (printf "w(%0.2fn)" . (70 *)) widths + -- 78n default width - 8n indent = 70n+ let coldescriptions = text $ joinWithSep " " + (zipWith (\align width -> aligncode align ++ width) + alignments iwidths) ++ "."+ colheadings <- mapM (blockListToMan opts) headers+ let makeRow cols = text "T{" $$ + (vcat $ intersperse (text "T}@T{") cols) $$ + text "T}"+ let colheadings' = makeRow colheadings+ body <- mapM (\row -> do + cols <- mapM (blockListToMan opts) row+ return $ makeRow cols) rows+ return $ text ".PP" $$ caption' $$ + text ".TS" $$ text "tab(@);" $$ coldescriptions $$ + colheadings' $$ char '_' $$ vcat body $$ text ".TE"++blockToMan opts (BulletList items) = do+ contents <- mapM (bulletListItemToMan opts) items+ return (vcat contents) +blockToMan opts (OrderedList attribs items) = do+ let markers = take (length items) $ orderedListMarkers attribs + let indent = 1 + (maximum $ map length markers)+ contents <- mapM (\(num, item) -> orderedListItemToMan opts num indent item) $+ zip markers items + return (vcat contents)+blockToMan opts (DefinitionList items) = do + contents <- mapM (definitionListItemToMan opts) items+ return (vcat contents)++-- | Convert bullet list item (list of blocks) to man.+bulletListItemToMan :: WriterOptions -> [Block] -> State WriterState Doc+bulletListItemToMan opts [] = return empty+bulletListItemToMan opts ((Para first):rest) = + bulletListItemToMan opts ((Plain first):rest)+bulletListItemToMan opts ((Plain first):rest) = do+ first' <- blockToMan opts (Plain first) + rest' <- blockListToMan opts rest+ let first'' = text ".IP \\[bu] 2" $$ first'+ let rest'' = if null rest+ then empty+ else text ".RS 2" $$ rest' $$ text ".RE"+ return (first'' $$ rest'') +bulletListItemToMan opts (first:rest) = do+ first' <- blockToMan opts first+ rest' <- blockListToMan opts rest+ return $ text "\\[bu] .RS 2" $$ first' $$ rest' $$ text ".RE"+ +-- | Convert ordered list item (a list of blocks) to man.+orderedListItemToMan :: WriterOptions -- ^ options+ -> String -- ^ order marker for list item+ -> Int -- ^ number of spaces to indent+ -> [Block] -- ^ list item (list of blocks)+ -> State WriterState Doc+orderedListItemToMan _ _ _ [] = return empty+orderedListItemToMan opts num indent ((Para first):rest) = + orderedListItemToMan opts num indent ((Plain first):rest)+orderedListItemToMan opts num indent (first:rest) = do+ first' <- blockToMan opts first+ rest' <- blockListToMan opts rest+ let num' = printf ("%" ++ show (indent - 1) ++ "s") num+ let first'' = text (".IP \"" ++ num' ++ "\" " ++ show indent) $$ first'+ let rest'' = if null rest+ then empty+ else text ".RS 4" $$ rest' $$ text ".RE"+ return $ first'' $$ rest'' ++-- | Convert definition list item (label, list of blocks) to man.+definitionListItemToMan :: WriterOptions+ -> ([Inline],[Block]) + -> State WriterState Doc+definitionListItemToMan opts (label, items) = do+ labelText <- inlineListToMan opts label+ contents <- if null items+ then return empty+ else do + let (first, rest) = case items of+ ((Para x):y) -> (Plain x,y)+ (x:y) -> (x,y)+ rest' <- mapM (\item -> blockToMan opts item)+ rest >>= (return . vcat)+ first' <- blockToMan opts first+ return $ first' $$ text ".RS" $$ rest' $$ text ".RE"+ return $ text ".TP\n.B " <> labelText $+$ contents++-- | Convert list of Pandoc block elements to man.+blockListToMan :: WriterOptions -- ^ Options+ -> [Block] -- ^ List of block elements+ -> State WriterState Doc +blockListToMan opts blocks =+ mapM (blockToMan opts) blocks >>= (return . vcat)++-- | Convert list of Pandoc inline elements to man.+inlineListToMan :: WriterOptions -> [Inline] -> State WriterState Doc+inlineListToMan opts lst = mapM (inlineToMan opts) lst >>= (return . hcat)++-- | Convert Pandoc inline element to man.+inlineToMan :: WriterOptions -> Inline -> State WriterState Doc+inlineToMan opts (Emph lst) = do + contents <- inlineListToMan opts lst+ return $ text "\\f[I]" <> contents <> text "\\f[]"+inlineToMan opts (Strong lst) = do+ contents <- inlineListToMan opts lst+ return $ text "\\f[B]" <> contents <> text "\\f[]"+inlineToMan opts (Strikeout lst) = do+ contents <- inlineListToMan opts lst+ return $ text "[STRIKEOUT:" <> contents <> char ']'+inlineToMan opts (Superscript lst) = do+ contents <- inlineListToMan opts lst+ return $ char '^' <> contents <> char '^'+inlineToMan opts (Subscript lst) = do+ contents <- inlineListToMan opts lst+ return $ char '~' <> contents <> char '~'+inlineToMan opts (Quoted SingleQuote lst) = do+ contents <- inlineListToMan opts lst+ return $ char '`' <> contents <> char '\''+inlineToMan opts (Quoted DoubleQuote lst) = do+ contents <- inlineListToMan opts lst+ return $ text "\\[lq]" <> contents <> text "\\[rq]"+inlineToMan opts EmDash = return $ text "\\[em]"+inlineToMan opts EnDash = return $ text "\\[en]"+inlineToMan opts Apostrophe = return $ char '\''+inlineToMan opts Ellipses = return $ text "\\&..."+inlineToMan opts (Code str) =+ return $ text $ "\\f[B]" ++ escapeCode str ++ "\\f[]"+inlineToMan opts (Str str) = return $ text $ escapeString str+inlineToMan opts (Math str) = inlineToMan opts (Code str)+inlineToMan opts (TeX str) = return empty+inlineToMan opts (HtmlInline str) = return $ text $ escapeCode str +inlineToMan opts (LineBreak) = return $ text "\n.PD 0\n.P\n.PD\n"+inlineToMan opts Space = return $ char ' '+inlineToMan opts (Link txt (src, _)) = do+ linktext <- inlineListToMan opts txt+ let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src+ return $ if txt == [Code srcSuffix]+ then char '<' <> text srcSuffix <> char '>' + else linktext <> text " (" <> text src <> char ')' +inlineToMan opts (Image alternate (source, tit)) = do+ let txt = if (null alternate) || (alternate == [Str ""]) || + (alternate == [Str source]) -- to prevent autolinks+ then [Str "image"]+ else alternate+ linkPart <- inlineToMan opts (Link txt (source, tit)) + return $ char '[' <> text "IMAGE: " <> linkPart <> char ']'+inlineToMan opts (Note contents) = do + modify (\(notes, prep) -> (contents:notes, prep)) -- add to notes in state+ (notes, _) <- get+ let ref = show $ (length notes)+ return $ char '[' <> text ref <> char ']'+
+ Text/Pandoc/Writers/Markdown.hs view
@@ -0,0 +1,374 @@+{-+Copyright (C) 2006-7 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.Markdown + Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to markdown-formatted plain text.++Markdown: <http://daringfireball.net/projects/markdown/>+-}+module Text.Pandoc.Writers.Markdown ( writeMarkdown) where+import Text.Pandoc.Definition+import Text.Pandoc.Shared +import Text.Pandoc.Blocks+import Text.ParserCombinators.Parsec ( parse, (<|>), GenParser )+import Data.List ( group, isPrefixOf, drop, find, intersperse )+import Text.PrettyPrint.HughesPJ hiding ( Str )+import Control.Monad.State++type Notes = [[Block]]+type Refs = KeyTable+type WriterState = (Notes, Refs)++-- | Convert Pandoc to Markdown.+writeMarkdown :: WriterOptions -> Pandoc -> String+writeMarkdown opts document = + render $ evalState (pandocToMarkdown opts document) ([],[]) ++-- | Return markdown representation of document.+pandocToMarkdown :: WriterOptions -> Pandoc -> State WriterState Doc+pandocToMarkdown opts (Pandoc meta blocks) = do+ let before = writerIncludeBefore opts+ let after = writerIncludeAfter opts+ let before' = if null before then empty else text before+ let after' = if null after then empty else text after+ metaBlock <- metaToMarkdown opts meta+ let head = if writerStandalone opts+ then metaBlock $+$ text (writerHeader opts)+ else empty+ let headerBlocks = filter isHeaderBlock blocks+ let toc = if writerTableOfContents opts + then tableOfContents opts headerBlocks+ else empty+ body <- blockListToMarkdown opts blocks+ (notes, _) <- get+ notes' <- notesToMarkdown opts (reverse notes)+ (_, refs) <- get -- note that the notes may contain refs+ refs' <- keyTableToMarkdown opts (reverse refs)+ return $ head $+$ before' $+$ toc $+$ body $+$ text "" $+$ + notes' $+$ text "" $+$ refs' $+$ after'++-- | Return markdown representation of reference key table.+keyTableToMarkdown :: WriterOptions -> KeyTable -> State WriterState Doc+keyTableToMarkdown opts refs = mapM (keyToMarkdown opts) refs >>= return . vcat+ +-- | Return markdown representation of a reference key. +keyToMarkdown :: WriterOptions + -> ([Inline], (String, String)) + -> State WriterState Doc+keyToMarkdown opts (label, (src, tit)) = do+ label' <- inlineListToMarkdown opts label+ let tit' = if null tit then empty else text $ " \"" ++ tit ++ "\""+ return $ text " " <> char '[' <> label' <> char ']' <> text ": " <>+ text src <> tit' ++-- | Return markdown representation of notes.+notesToMarkdown :: WriterOptions -> [[Block]] -> State WriterState Doc+notesToMarkdown opts notes = + mapM (\(num, note) -> noteToMarkdown opts num note) (zip [1..] notes) >>= + return . vcat++-- | Return markdown representation of a note.+noteToMarkdown :: WriterOptions -> Int -> [Block] -> State WriterState Doc+noteToMarkdown opts num blocks = do+ contents <- blockListToMarkdown opts blocks+ let marker = text "[^" <> text (show num) <> text "]:"+ return $ hang marker (writerTabStop opts) contents ++-- | Escape special characters for Markdown.+escapeString :: String -> String+escapeString = escapeStringUsing markdownEscapes+ where markdownEscapes = ('\160', " "):(backslashEscapes "`<\\*_^~")++-- | Convert bibliographic information into Markdown header.+metaToMarkdown :: WriterOptions -> Meta -> State WriterState Doc+metaToMarkdown opts (Meta title authors date) = do+ title' <- titleToMarkdown opts title+ authors' <- authorsToMarkdown authors+ date' <- dateToMarkdown date+ return $ title' $+$ authors' $+$ date'++titleToMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc+titleToMarkdown opts [] = return empty+titleToMarkdown opts lst = do+ contents <- inlineListToMarkdown opts lst+ return $ text "% " <> contents ++authorsToMarkdown :: [String] -> State WriterState Doc+authorsToMarkdown [] = return empty+authorsToMarkdown lst = return $ + text "% " <> text (joinWithSep ", " (map escapeString lst))++dateToMarkdown :: String -> State WriterState Doc+dateToMarkdown [] = return empty+dateToMarkdown str = return $ text "% " <> text (escapeString str)++-- | Construct table of contents from list of header blocks.+tableOfContents :: WriterOptions -> [Block] -> Doc +tableOfContents opts headers =+ let opts' = opts { writerIgnoreNotes = True }+ contents = BulletList $ map elementToListItem $ hierarchicalize headers+ in evalState (blockToMarkdown opts' contents) ([],[])++-- | Converts an Element to a list item for a table of contents,+elementToListItem :: Element -> [Block]+elementToListItem (Blk _) = []+elementToListItem (Sec headerText subsecs) = [Plain headerText] ++ + if null subsecs+ then []+ else [BulletList $ map elementToListItem subsecs]++-- | Ordered list start parser for use in Para below.+olMarker :: GenParser Char st Char+olMarker = do (start, style, delim) <- anyOrderedListMarker+ if delim == Period && + (style == UpperAlpha || (style == UpperRoman &&+ start `elem` [1, 5, 10, 50, 100, 500, 1000]))+ then spaceChar >> spaceChar+ else spaceChar++-- | True if string begins with an ordered list marker+beginsWithOrderedListMarker :: String -> Bool+beginsWithOrderedListMarker str = + case parse olMarker "para start" str of+ Left _ -> False + Right _ -> True++wrappedMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc+wrappedMarkdown opts inlines = do+ let chunks = splitBy LineBreak inlines+ let chunks' = if null chunks+ then []+ else (map (++ [Str " "]) $ init chunks) ++ [last chunks]+ lns <- mapM (wrapIfNeeded opts (inlineListToMarkdown opts)) chunks'+ return $ vcat lns++-- | Convert Pandoc block element to markdown.+blockToMarkdown :: WriterOptions -- ^ Options+ -> Block -- ^ Block element+ -> State WriterState Doc +blockToMarkdown opts Null = return empty+blockToMarkdown opts (Plain inlines) = + wrappedMarkdown opts inlines+blockToMarkdown opts (Para inlines) = do+ contents <- wrappedMarkdown opts inlines+ -- escape if para starts with ordered list marker+ let esc = if (not (writerStrictMarkdown opts)) && + beginsWithOrderedListMarker (render contents)+ then char '\\'+ else empty + return $ esc <> contents <> text "\n"+blockToMarkdown opts (RawHtml str) = return $ text str+blockToMarkdown opts HorizontalRule = return $ text "\n* * * * *\n"+blockToMarkdown opts (Header level inlines) = do+ contents <- inlineListToMarkdown opts inlines+ return $ text ((replicate level '#') ++ " ") <> contents <> text "\n"+blockToMarkdown opts (CodeBlock str) = return $+ (nest (writerTabStop opts) $ vcat $ map text (lines str)) <> text "\n"+blockToMarkdown opts (BlockQuote blocks) = do+ contents <- blockListToMarkdown opts blocks+ return $ (vcat $ map (text . ("> " ++)) $ lines $ render contents) <> + text "\n"+blockToMarkdown opts (Table caption aligns widths headers rows) = do+ caption' <- inlineListToMarkdown opts caption+ let caption'' = if null caption+ then empty+ else text "" $+$ (text "Table: " <> caption')+ headers' <- mapM (blockListToMarkdown opts) headers+ let widthsInChars = map (floor . (78 *)) widths+ let alignHeader alignment = case alignment of+ AlignLeft -> leftAlignBlock+ AlignCenter -> centerAlignBlock+ AlignRight -> rightAlignBlock+ AlignDefault -> leftAlignBlock + let makeRow = hsepBlocks . (zipWith alignHeader aligns) . + (zipWith docToBlock widthsInChars)+ let head = makeRow headers'+ rows' <- mapM (\row -> do cols <- mapM (blockListToMarkdown opts) row+ return $ makeRow cols) rows+ let tableWidth = sum widthsInChars+ let maxRowHeight = maximum $ map heightOfBlock (head:rows')+ let isMultilineTable = maxRowHeight > 1+ let underline = hsep $ + map (\width -> text $ replicate width '-') widthsInChars+ let border = if isMultilineTable+ then text $ replicate (sum widthsInChars + (length widthsInChars - 1)) '-'+ else empty+ let spacer = if isMultilineTable+ then text ""+ else empty+ let body = vcat $ intersperse spacer $ map blockToDoc rows'+ return $ (nest 2 $ border $+$ (blockToDoc head) $+$ underline $+$ body $+$ + border $+$ caption'') <> text "\n"+blockToMarkdown opts (BulletList items) = do+ contents <- mapM (bulletListItemToMarkdown opts) items+ return $ (vcat contents) <> text "\n"+blockToMarkdown opts (OrderedList attribs items) = do+ let markers = orderedListMarkers attribs+ let markers' = map (\m -> if length m < 3+ then m ++ replicate (3 - length m) ' '+ else m) markers + contents <- mapM (\(item, num) -> orderedListItemToMarkdown opts item num) $+ zip markers' items + return $ (vcat contents) <> text "\n"+blockToMarkdown opts (DefinitionList items) = do+ contents <- mapM (definitionListItemToMarkdown opts) items+ return $ (vcat contents) <> text "\n"++-- | Convert bullet list item (list of blocks) to markdown.+bulletListItemToMarkdown :: WriterOptions -> [Block] -> State WriterState Doc+bulletListItemToMarkdown opts items = do+ contents <- blockListToMarkdown opts items+ return $ hang (text "- ") (writerTabStop opts) contents++-- | Convert ordered list item (a list of blocks) to markdown.+orderedListItemToMarkdown :: WriterOptions -- ^ options+ -> String -- ^ list item marker+ -> [Block] -- ^ list item (list of blocks)+ -> State WriterState Doc+orderedListItemToMarkdown opts marker items = do+ contents <- blockListToMarkdown opts items+ -- The complexities here are needed to ensure that if the list+ -- marker is 4 characters or longer, the second and following+ -- lines are indented 4 spaces but the list item begins after the marker.+ return $ sep [nest (min (3 - length marker) 0) (text marker), + nest (writerTabStop opts) contents]++-- | Convert definition list item (label, list of blocks) to markdown.+definitionListItemToMarkdown :: WriterOptions+ -> ([Inline],[Block]) + -> State WriterState Doc+definitionListItemToMarkdown opts (label, items) = do+ labelText <- inlineListToMarkdown opts label+ let tabStop = writerTabStop opts+ let leader = char ':'+ contents <- mapM (\item -> blockToMarkdown opts item >>= + (\txt -> return (leader $$ nest tabStop txt)))+ items >>= return . vcat+ return $ labelText $+$ contents++-- | Convert list of Pandoc block elements to markdown.+blockListToMarkdown :: WriterOptions -- ^ Options+ -> [Block] -- ^ List of block elements+ -> State WriterState Doc +blockListToMarkdown opts blocks =+ mapM (blockToMarkdown opts) blocks >>= return . vcat++-- | Get reference for target; if none exists, create unique one and return.+-- Prefer label if possible; otherwise, generate a unique key.+getReference :: [Inline] -> Target -> State WriterState [Inline]+getReference label (src, tit) = do+ (_,refs) <- get+ case find ((== (src, tit)) . snd) refs of+ Just (ref, _) -> return ref+ Nothing -> do+ let label' = case find ((== label) . fst) refs of+ Just _ -> -- label is used; generate numerical label+ case find (\n -> not (any (== [Str (show n)])+ (map fst refs))) [1..10000] of+ Just x -> [Str (show x)]+ Nothing -> error "no unique label"+ Nothing -> label+ modify (\(notes, refs) -> (notes, (label', (src,tit)):refs))+ return label'++-- | Convert list of Pandoc inline elements to markdown.+inlineListToMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc+inlineListToMarkdown opts lst =+ mapM (inlineToMarkdown opts) lst >>= return . hcat++-- | Convert Pandoc inline element to markdown.+inlineToMarkdown :: WriterOptions -> Inline -> State WriterState Doc+inlineToMarkdown opts (Emph lst) = do + contents <- inlineListToMarkdown opts lst+ return $ char '*' <> contents <> char '*'+inlineToMarkdown opts (Strong lst) = do+ contents <- inlineListToMarkdown opts lst+ return $ text "**" <> contents <> text "**"+inlineToMarkdown opts (Strikeout lst) = do+ contents <- inlineListToMarkdown opts lst+ return $ text "~~" <> contents <> text "~~"+inlineToMarkdown opts (Superscript lst) = do+ contents <- inlineListToMarkdown opts lst+ let contents' = text $ substitute " " "\\ " $ render contents+ return $ char '^' <> contents' <> char '^'+inlineToMarkdown opts (Subscript lst) = do+ contents <- inlineListToMarkdown opts lst+ let contents' = text $ substitute " " "\\ " $ render contents+ return $ char '~' <> contents' <> char '~'+inlineToMarkdown opts (Quoted SingleQuote lst) = do+ contents <- inlineListToMarkdown opts lst+ return $ char '\'' <> contents <> char '\''+inlineToMarkdown opts (Quoted DoubleQuote lst) = do+ contents <- inlineListToMarkdown opts lst+ return $ char '"' <> contents <> char '"'+inlineToMarkdown opts EmDash = return $ text "--"+inlineToMarkdown opts EnDash = return $ char '-'+inlineToMarkdown opts Apostrophe = return $ char '\''+inlineToMarkdown opts Ellipses = return $ text "..."+inlineToMarkdown opts (Code str) =+ let tickGroups = filter (\s -> '`' `elem` s) $ group str + longest = if null tickGroups+ then 0+ else maximum $ map length tickGroups + marker = replicate (longest + 1) '`' + spacer = if (longest == 0) then "" else " " in+ return $ text (marker ++ spacer ++ str ++ spacer ++ marker)+inlineToMarkdown opts (Str str) = return $ text $ escapeString str+inlineToMarkdown opts (Math str) = return $ char '$' <> text str <> char '$'+inlineToMarkdown opts (TeX str) = return $ text str+inlineToMarkdown opts (HtmlInline str) = return $ text str +inlineToMarkdown opts (LineBreak) = return $ text " \n"+inlineToMarkdown opts Space = return $ char ' '+inlineToMarkdown opts (Link txt (src, tit)) = do+ linktext <- inlineListToMarkdown opts txt+ let linktitle = if null tit then empty else text $ " \"" ++ tit ++ "\""+ let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src+ let useRefLinks = writerReferenceLinks opts+ let useAuto = null tit && txt == [Code srcSuffix]+ ref <- if useRefLinks then getReference txt (src, tit) else return []+ reftext <- inlineListToMarkdown opts ref+ return $ if useAuto+ then char '<' <> text srcSuffix <> char '>' + else if useRefLinks+ then let first = char '[' <> linktext <> char ']'+ second = if txt == ref+ then text "[]"+ else char '[' <> reftext <> char ']'+ in first <> second+ else char '[' <> linktext <> char ']' <> + char '(' <> text src <> linktitle <> char ')' +inlineToMarkdown opts (Image alternate (source, tit)) = do+ let txt = if (null alternate) || (alternate == [Str ""]) || + (alternate == [Str source]) -- to prevent autolinks+ then [Str "image"]+ else alternate+ linkPart <- inlineToMarkdown opts (Link txt (source, tit)) + return $ char '!' <> linkPart+inlineToMarkdown opts (Note contents) = do + modify (\(notes, refs) -> (contents:notes, refs)) -- add to notes in state+ (notes, _) <- get+ let ref = show $ (length notes)+ return $ text "[^" <> text ref <> char ']'
+ Text/Pandoc/Writers/RST.hs view
@@ -0,0 +1,324 @@+{-+Copyright (C) 2006-7 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.RST + Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to reStructuredText.++reStructuredText: <http://docutils.sourceforge.net/rst.html>+-}+module Text.Pandoc.Writers.RST ( writeRST) where+import Text.Pandoc.Definition+import Text.Pandoc.Shared +import Text.Pandoc.Readers.TeXMath+import Text.Pandoc.Blocks+import Data.List ( isPrefixOf, isSuffixOf, drop, intersperse )+import Text.PrettyPrint.HughesPJ hiding ( Str )+import Control.Monad.State++type Notes = [[Block]]+type Refs = KeyTable+type WriterState = (Notes, Refs, Refs) -- first Refs is links, second pictures++-- | Convert Pandoc to RST.+writeRST :: WriterOptions -> Pandoc -> String+writeRST opts document = + render $ evalState (pandocToRST opts document) ([],[],[]) ++-- | Return RST representation of document.+pandocToRST :: WriterOptions -> Pandoc -> State WriterState Doc+pandocToRST opts (Pandoc meta blocks) = do+ let before = writerIncludeBefore opts+ let after = writerIncludeAfter opts+ before' = if null before then empty else text before+ after' = if null after then empty else text after+ metaBlock <- metaToRST opts meta+ let head = if (writerStandalone opts)+ then metaBlock $+$ text (writerHeader opts)+ else empty+ body <- blockListToRST opts blocks+ (notes, _, _) <- get+ notes' <- notesToRST opts (reverse notes)+ (_, refs, pics) <- get -- note that the notes may contain refs+ refs' <- keyTableToRST opts (reverse refs)+ pics' <- pictTableToRST opts (reverse pics)+ return $ head $+$ before' $+$ body $+$ notes' $+$ text "" $+$ refs' $+$ + pics' $+$ after'++-- | Return RST representation of reference key table.+keyTableToRST :: WriterOptions -> KeyTable -> State WriterState Doc+keyTableToRST opts refs = mapM (keyToRST opts) refs >>= return . vcat+ +-- | Return RST representation of a reference key. +keyToRST :: WriterOptions + -> ([Inline], (String, String)) + -> State WriterState Doc+keyToRST opts (label, (src, tit)) = do+ label' <- inlineListToRST opts label+ let label'' = if ':' `elem` (render label')+ then char '`' <> label' <> char '`'+ else label'+ return $ text ".. _" <> label'' <> text ": " <> text src++-- | Return RST representation of notes.+notesToRST :: WriterOptions -> [[Block]] -> State WriterState Doc+notesToRST opts notes = + mapM (\(num, note) -> noteToRST opts num note) (zip [1..] notes) >>= + return . vcat++-- | Return RST representation of a note.+noteToRST :: WriterOptions -> Int -> [Block] -> State WriterState Doc+noteToRST opts num note = do+ contents <- blockListToRST opts note+ let marker = text ".. [" <> text (show num) <> text "] "+ return $ hang marker 3 contents ++-- | Return RST representation of picture reference table.+pictTableToRST :: WriterOptions -> KeyTable -> State WriterState Doc+pictTableToRST opts refs = mapM (pictToRST opts) refs >>= return . vcat+ +-- | Return RST representation of a picture substitution reference. +pictToRST :: WriterOptions + -> ([Inline], (String, String)) + -> State WriterState Doc+pictToRST opts (label, (src, _)) = do+ label' <- inlineListToRST opts label+ return $ text ".. " <> char '|' <> label' <> char '|' <> text " image:: " <>+ text src++-- | Take list of inline elements and return wrapped doc.+wrappedRST :: WriterOptions -> [Inline] -> State WriterState Doc+wrappedRST opts inlines = mapM (wrapIfNeeded opts (inlineListToRST opts))+ (splitBy LineBreak inlines) >>= return . vcat++-- | Escape special characters for RST.+escapeString :: String -> String+escapeString = escapeStringUsing (backslashEscapes "`\\|*_")++-- | Convert bibliographic information into RST header.+metaToRST :: WriterOptions -> Meta -> State WriterState Doc+metaToRST opts (Meta title authors date) = do+ title' <- titleToRST opts title+ authors' <- authorsToRST authors+ date' <- dateToRST date+ let toc = if writerTableOfContents opts+ then text "" $+$ text ".. contents::"+ else empty+ return $ title' $+$ authors' $+$ date' $+$ toc++titleToRST :: WriterOptions -> [Inline] -> State WriterState Doc+titleToRST opts [] = return empty+titleToRST opts lst = do+ contents <- inlineListToRST opts lst+ let titleLength = length $ render contents+ let border = text (replicate titleLength '=')+ return $ border $+$ contents $+$ border <> text "\n"++authorsToRST :: [String] -> State WriterState Doc+authorsToRST [] = return empty+authorsToRST (first:rest) = do+ rest' <- authorsToRST rest+ return $ (text ":Author: " <> text first) $+$ rest'++dateToRST :: String -> State WriterState Doc+dateToRST [] = return empty+dateToRST str = return $ text ":Date: " <> text (escapeString str)++-- | Convert Pandoc block element to RST. +blockToRST :: WriterOptions -- ^ Options+ -> Block -- ^ Block element+ -> State WriterState Doc +blockToRST opts Null = return empty+blockToRST opts (Plain inlines) = wrappedRST opts inlines+blockToRST opts (Para inlines) = do+ contents <- wrappedRST opts inlines+ return $ contents <> text "\n"+blockToRST opts (RawHtml str) = + let str' = if "\n" `isSuffixOf` str then str ++ "\n" else str ++ "\n\n" in+ return $ hang (text "\n.. raw:: html\n") 3 $ vcat $ map text (lines str')+blockToRST opts HorizontalRule = return $ text "--------------\n"+blockToRST opts (Header level inlines) = do+ contents <- inlineListToRST opts inlines+ let headerLength = length $ render contents+ let headerChar = if level > 5 then ' ' else "=-~^'" !! (level - 1)+ let border = text $ replicate headerLength headerChar+ return $ contents $+$ border <> text "\n"+blockToRST opts (CodeBlock str) = return $ (text "::\n") $+$ + (nest (writerTabStop opts) $ vcat $ map text (lines str)) <> text "\n"+blockToRST opts (BlockQuote blocks) = do+ contents <- blockListToRST opts blocks + return $ (nest (writerTabStop opts) contents) <> text "\n"+blockToRST opts (Table caption aligns widths headers rows) = do+ caption' <- inlineListToRST opts caption+ let caption'' = if null caption+ then empty+ else text "" $+$ (text "Table: " <> caption')+ headers' <- mapM (blockListToRST opts) headers+ let widthsInChars = map (floor . (78 *)) widths+ let alignHeader alignment = case alignment of+ AlignLeft -> leftAlignBlock+ AlignCenter -> centerAlignBlock+ AlignRight -> rightAlignBlock+ AlignDefault -> leftAlignBlock + let hpipeBlocks blocks = hcatBlocks [beg, middle, end] + where height = maximum (map heightOfBlock blocks)+ sep = TextBlock 3 height (replicate height " | ")+ beg = TextBlock 2 height (replicate height "| ")+ end = TextBlock 2 height (replicate height " |")+ middle = hcatBlocks $ intersperse sep blocks+ let makeRow = hpipeBlocks . zipWith docToBlock widthsInChars+ let head = makeRow headers'+ rows' <- mapM (\row -> do cols <- mapM (blockListToRST opts) row+ return $ makeRow cols) rows+ let tableWidth = sum widthsInChars+ let maxRowHeight = maximum $ map heightOfBlock (head:rows')+ let border ch = char '+' <> char ch <>+ (hcat $ intersperse (char ch <> char '+' <> char ch) $ + map (\l -> text $ replicate l ch) widthsInChars) <>+ char ch <> char '+'+ let body = vcat $ intersperse (border '-') $ map blockToDoc rows'+ return $ border '-' $+$ blockToDoc head $+$ border '=' $+$ body $+$ + border '-' $$ caption'' $$ text ""+blockToRST opts (BulletList items) = do+ contents <- mapM (bulletListItemToRST opts) items+ -- ensure that sublists have preceding blank line+ return $ text "" $+$ vcat contents <> text "\n"+blockToRST opts (OrderedList (start, style, delim) items) = do+ let markers = if start == 1 && style == DefaultStyle && delim == DefaultDelim + then take (length items) $ repeat "#."+ else take (length items) $ orderedListMarkers + (start, style, delim)+ let maxMarkerLength = maximum $ map length markers+ let markers' = map (\m -> let s = maxMarkerLength - length m+ in m ++ replicate s ' ') markers+ contents <- mapM (\(item, num) -> orderedListItemToRST opts item num) $+ zip markers' items + -- ensure that sublists have preceding blank line+ return $ text "" $+$ vcat contents <> text "\n"+blockToRST opts (DefinitionList items) = do+ contents <- mapM (definitionListItemToRST opts) items+ return $ (vcat contents) <> text "\n"++-- | Convert bullet list item (list of blocks) to RST.+bulletListItemToRST :: WriterOptions -> [Block] -> State WriterState Doc+bulletListItemToRST opts items = do+ contents <- blockListToRST opts items+ return $ hang (text "- ") 3 contents++-- | Convert ordered list item (a list of blocks) to RST.+orderedListItemToRST :: WriterOptions -- ^ options+ -> String -- ^ marker for list item+ -> [Block] -- ^ list item (list of blocks)+ -> State WriterState Doc+orderedListItemToRST opts marker items = do+ contents <- blockListToRST opts items+ return $ hang (text marker) (length marker + 1) contents ++-- | Convert defintion list item (label, list of blocks) to RST.+definitionListItemToRST :: WriterOptions -> ([Inline], [Block]) -> State WriterState Doc+definitionListItemToRST opts (label, items) = do+ label <- inlineListToRST opts label+ contents <- blockListToRST opts items+ return $ label $+$ nest (writerTabStop opts) contents++-- | Convert list of Pandoc block elements to RST.+blockListToRST :: WriterOptions -- ^ Options+ -> [Block] -- ^ List of block elements+ -> State WriterState Doc +blockListToRST opts blocks =+ mapM (blockToRST opts) blocks >>= return . vcat++-- | Convert list of Pandoc inline elements to RST.+inlineListToRST :: WriterOptions -> [Inline] -> State WriterState Doc+inlineListToRST opts lst = mapM (inlineToRST opts) lst >>= return . hcat++-- | Convert Pandoc inline element to RST.+inlineToRST :: WriterOptions -> Inline -> State WriterState Doc+inlineToRST opts (Emph lst) = do + contents <- inlineListToRST opts lst+ return $ char '*' <> contents <> char '*'+inlineToRST opts (Strong lst) = do+ contents <- inlineListToRST opts lst+ return $ text "**" <> contents <> text "**"+inlineToRST opts (Strikeout lst) = do + contents <- inlineListToRST opts lst+ return $ text "[STRIKEOUT:" <> contents <> char ']'+inlineToRST opts (Superscript lst) = do + contents <- inlineListToRST opts lst+ return $ text "\\ :sup:`" <> contents <> text "`\\ "+inlineToRST opts (Subscript lst) = do + contents <- inlineListToRST opts lst+ return $ text "\\ :sub:`" <> contents <> text "`\\ "+inlineToRST opts (Quoted SingleQuote lst) = do+ contents <- inlineListToRST opts lst+ return $ char '\'' <> contents <> char '\''+inlineToRST opts (Quoted DoubleQuote lst) = do+ contents <- inlineListToRST opts lst+ return $ char '"' <> contents <> char '"'+inlineToRST opts EmDash = return $ text "--"+inlineToRST opts EnDash = return $ char '-'+inlineToRST opts Apostrophe = return $ char '\''+inlineToRST opts Ellipses = return $ text "..."+inlineToRST opts (Code str) = return $ text $ "``" ++ str ++ "``"+inlineToRST opts (Str str) = return $ text $ escapeString str+inlineToRST opts (Math str) = return $ text $ "$" ++ str ++ "$"+inlineToRST opts (TeX str) = return empty+inlineToRST opts (HtmlInline str) = return empty+inlineToRST opts (LineBreak) = return $ char ' ' -- RST doesn't have linebreaks +inlineToRST opts Space = return $ char ' '+inlineToRST opts (Link [Code str] (src, tit)) | src == str ||+ src == "mailto:" ++ str = do+ let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src+ return $ text srcSuffix+inlineToRST opts (Link txt (src, tit)) = do+ let useReferenceLinks = writerReferenceLinks opts+ linktext <- inlineListToRST opts $ normalizeSpaces txt+ if useReferenceLinks+ then do (notes, refs, pics) <- get+ let refs' = if (txt, (src, tit)) `elem` refs+ then refs+ else (txt, (src, tit)):refs+ put (notes, refs', pics)+ return $ char '`' <> linktext <> text "`_"+ else return $ char '`' <> linktext <> text " <" <> text src <> text ">`_"+inlineToRST opts (Image alternate (source, tit)) = do+ (notes, refs, pics) <- get+ let labelsUsed = map fst pics + let txt = if null alternate || alternate == [Str ""] || + alternate `elem` labelsUsed+ then [Str $ "image" ++ show (length refs)]+ else alternate+ let pics' = if (txt, (source, tit)) `elem` pics+ then pics+ else (txt, (source, tit)):pics+ put (notes, refs, pics')+ label <- inlineListToRST opts txt+ return $ char '|' <> label <> char '|'+inlineToRST opts (Note contents) = do + -- add to notes in state+ modify (\(notes, refs, pics) -> (contents:notes, refs, pics))+ (notes, _, _) <- get+ let ref = show $ (length notes)+ return $ text " [" <> text ref <> text "]_"
+ Text/Pandoc/Writers/RTF.hs view
@@ -0,0 +1,288 @@+{-+Copyright (C) 2006-7 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.RTF+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha + Portability : portable++Conversion of 'Pandoc' documents to RTF (rich text format).+-}+module Text.Pandoc.Writers.RTF ( writeRTF ) where+import Text.Pandoc.Definition+import Text.Pandoc.Shared+import Text.Pandoc.Readers.TeXMath+import Text.Regex ( matchRegexAll, mkRegex )+import Data.List ( isSuffixOf )+import Data.Char ( ord )++-- | Convert Pandoc to a string in rich text format.+writeRTF :: WriterOptions -> Pandoc -> String+writeRTF options (Pandoc meta blocks) = + let head = if writerStandalone options+ then rtfHeader (writerHeader options) meta + else ""+ toc = if writerTableOfContents options+ then tableOfContents $ filter isHeaderBlock blocks+ else "" + foot = if writerStandalone options then "\n}\n" else "" + body = writerIncludeBefore options ++ + concatMap (blockToRTF 0 AlignDefault) blocks ++ + writerIncludeAfter options+ in head ++ toc ++ body ++ foot++-- | Construct table of contents from list of header blocks.+tableOfContents :: [Block] -> String +tableOfContents headers =+ let contentsTree = hierarchicalize headers+ in concatMap (blockToRTF 0 AlignDefault) $ + [Header 1 [Str "Contents"], + BulletList (map elementToListItem contentsTree)]++elementToListItem :: Element -> [Block]+elementToListItem (Blk _) = []+elementToListItem (Sec sectext subsecs) = [Plain sectext] +++ if null subsecs+ then []+ else [BulletList (map elementToListItem subsecs)]++-- | Convert unicode characters (> 127) into rich text format representation.+handleUnicode :: String -> String+handleUnicode [] = []+handleUnicode (c:cs) =+ if ord c > 127 + then '\\':'u':(show (ord c)) ++ "?" ++ handleUnicode cs+ else c:(handleUnicode cs)++-- | Escape special characters.+escapeSpecial :: String -> String+escapeSpecial = escapeStringUsing (('\t',"\\tab "):(backslashEscapes "{\\}"))++-- | Escape strings as needed for rich text format.+stringToRTF :: String -> String+stringToRTF = handleUnicode . escapeSpecial++-- | Escape things as needed for code block in RTF.+codeStringToRTF :: String -> String+codeStringToRTF str = joinWithSep "\\line\n" $ lines (stringToRTF str)++-- | Deal with raw LaTeX.+latexToRTF :: String -> String+latexToRTF str = "{\\cf1 " ++ (stringToRTF str) ++ "\\cf0 } "++-- | Make a paragraph with first-line indent, block indent, and space after.+rtfParSpaced :: Int -- ^ space after (in twips)+ -> Int -- ^ block indent (in twips)+ -> Int -- ^ first line indent (relative to block) (in twips)+ -> Alignment -- ^ alignment+ -> String -- ^ string with content+ -> String +rtfParSpaced spaceAfter indent firstLineIndent alignment content = + let alignString = case alignment of+ AlignLeft -> "\\ql "+ AlignRight -> "\\qr "+ AlignCenter -> "\\qc "+ AlignDefault -> "\\ql "+ in "{\\pard " ++ alignString +++ "\\f0 \\sa" ++ (show spaceAfter) ++ " \\li" ++ (show indent) ++ + " \\fi" ++ (show firstLineIndent) ++ " " ++ content ++ "\\par}\n"++-- | Default paragraph. +rtfPar :: Int -- ^ block indent (in twips)+ -> Int -- ^ first line indent (relative to block) (in twips)+ -> Alignment -- ^ alignment+ -> String -- ^ string with content+ -> String +rtfPar = rtfParSpaced 180 ++-- | Compact paragraph (e.g. for compact list items).+rtfCompact :: Int -- ^ block indent (in twips)+ -> Int -- ^ first line indent (relative to block) (in twips)+ -> Alignment -- ^ alignment+ -> String -- ^ string with content+ -> String +rtfCompact = rtfParSpaced 0 ++-- number of twips to indent+indentIncrement = 720+listIncrement = 360++-- | Returns appropriate bullet list marker for indent level.+bulletMarker :: Int -> String+bulletMarker indent = case indent `mod` 720 of+ 0 -> "\\bullet "+ otherwise -> "\\endash "++-- | Returns appropriate (list of) ordered list markers for indent level.+orderedMarkers :: Int -> ListAttributes -> [String]+orderedMarkers indent (start, style, delim) = + if style == DefaultStyle && delim == DefaultDelim+ then case indent `mod` 720 of+ 0 -> orderedListMarkers (start, Decimal, Period)+ otherwise -> orderedListMarkers (start, LowerAlpha, Period)+ else orderedListMarkers (start, style, delim)++-- | Returns RTF header.+rtfHeader :: String -- ^ header text+ -> Meta -- ^ bibliographic information+ -> String+rtfHeader headerText (Meta title authors date) =+ let titletext = if null title+ then "" + else rtfPar 0 0 AlignCenter $+ "\\b \\fs36 " ++ inlineListToRTF title+ authorstext = if null authors+ then "" + else rtfPar 0 0 AlignCenter (" " ++ (joinWithSep "\\" $+ map stringToRTF authors))+ datetext = if date == "" + then ""+ else rtfPar 0 0 AlignCenter (" " ++ stringToRTF date) in+ let spacer = if null (titletext ++ authorstext ++ datetext)+ then ""+ else rtfPar 0 0 AlignDefault "" in+ headerText ++ titletext ++ authorstext ++ datetext ++ spacer++-- | Convert Pandoc block element to RTF.+blockToRTF :: Int -- ^ indent level+ -> Alignment -- ^ alignment+ -> Block -- ^ block to convert+ -> String+blockToRTF _ _ Null = ""+blockToRTF indent alignment (Plain lst) = + rtfCompact indent 0 alignment $ inlineListToRTF lst+blockToRTF indent alignment (Para lst) = + rtfPar indent 0 alignment $ inlineListToRTF lst+blockToRTF indent alignment (BlockQuote lst) = + concatMap (blockToRTF (indent + indentIncrement) alignment) lst +blockToRTF indent _ (CodeBlock str) =+ rtfPar indent 0 AlignLeft ("\\f1 " ++ (codeStringToRTF str))+blockToRTF _ _ (RawHtml str) = ""+blockToRTF indent alignment (BulletList lst) = spaceAtEnd $ + concatMap (listItemToRTF alignment indent (bulletMarker indent)) lst+blockToRTF indent alignment (OrderedList attribs lst) = spaceAtEnd $ concat $ + zipWith (listItemToRTF alignment indent) (orderedMarkers indent attribs) lst+blockToRTF indent alignment (DefinitionList lst) = spaceAtEnd $ + concatMap (definitionListItemToRTF alignment indent) lst+blockToRTF indent _ HorizontalRule = + rtfPar indent 0 AlignCenter "\\emdash\\emdash\\emdash\\emdash\\emdash"+blockToRTF indent alignment (Header level lst) = rtfPar indent 0 alignment $+ "\\b \\fs" ++ (show (40 - (level * 4))) ++ " " ++ inlineListToRTF lst+blockToRTF indent alignment (Table caption aligns sizes headers rows) = + tableRowToRTF True indent aligns sizes headers ++ + concatMap (tableRowToRTF False indent aligns sizes) rows +++ rtfPar indent 0 alignment (inlineListToRTF caption)++tableRowToRTF :: Bool -> Int -> [Alignment] -> [Float] -> [[Block]] -> String +tableRowToRTF header indent aligns sizes cols =+ let columns = concat $ zipWith (tableItemToRTF indent) aligns cols+ totalTwips = 6 * 1440 -- 6 inches+ rightEdges = tail $ scanl (\sofar new -> sofar + floor (new * totalTwips))+ 0 sizes+ cellDefs = map (\edge -> (if header+ then "\\clbrdrb\\brdrs"+ else "") ++ "\\cellx" ++ show edge)+ rightEdges+ start = "{\n\\trowd \\trgaph120\n" ++ concat cellDefs ++ "\n" +++ "\\trkeep\\intbl\n{\n"+ end = "}\n\\intbl\\row}\n"+ in start ++ columns ++ end++tableItemToRTF :: Int -> Alignment -> [Block] -> String +tableItemToRTF indent alignment item =+ let contents = concatMap (blockToRTF indent alignment) item+ in "{\\intbl " ++ contents ++ "\\cell}\n"++-- | Ensure that there's the same amount of space after compact+-- lists as after regular lists.+spaceAtEnd :: String -> String+spaceAtEnd str = + if isSuffixOf "\\par}\n" str+ then (take ((length str) - 6) str) ++ "\\sa180\\par}\n"+ else str++-- | Convert list item (list of blocks) to RTF.+listItemToRTF :: Alignment -- ^ alignment+ -> Int -- ^ indent level+ -> String -- ^ list start marker+ -> [Block] -- ^ list item (list of blocks)+ -> [Char]+listItemToRTF alignment indent marker [] = + rtfCompact (indent + listIncrement) (0 - listIncrement) alignment + (marker ++ "\\tx" ++ (show listIncrement) ++ "\\tab ") +listItemToRTF alignment indent marker list = + let (first:rest) = map (blockToRTF (indent + listIncrement) alignment) list in+ -- insert the list marker into the (processed) first block+ let modFirst = case matchRegexAll (mkRegex "\\\\fi-?[0-9]+") first of+ Just (before, matched, after, _) -> + before ++ "\\fi" ++ show (0 - listIncrement) ++ + " " ++ marker ++ "\\tx" ++ + show listIncrement ++ "\\tab" ++ after+ Nothing -> first in+ modFirst ++ concat rest++-- | Convert definition list item (label, list of blocks) to RTF.+definitionListItemToRTF :: Alignment -- ^ alignment+ -> Int -- ^ indent level+ -> ([Inline],[Block]) -- ^ list item (list of blocks)+ -> [Char]+definitionListItemToRTF alignment indent (label, items) =+ let labelText = blockToRTF indent alignment (Plain label)+ itemsText = concatMap (blockToRTF (indent + listIncrement) alignment) items+ in labelText ++ itemsText ++-- | Convert list of inline items to RTF.+inlineListToRTF :: [Inline] -- ^ list of inlines to convert+ -> String+inlineListToRTF lst = concatMap inlineToRTF lst++-- | Convert inline item to RTF.+inlineToRTF :: Inline -- ^ inline to convert+ -> String+inlineToRTF (Emph lst) = "{\\i " ++ (inlineListToRTF lst) ++ "} "+inlineToRTF (Strong lst) = "{\\b " ++ (inlineListToRTF lst) ++ "} "+inlineToRTF (Strikeout lst) = "{\\strike " ++ (inlineListToRTF lst) ++ "} "+inlineToRTF (Superscript lst) = "{\\super " ++ (inlineListToRTF lst) ++ "} "+inlineToRTF (Subscript lst) = "{\\sub " ++ (inlineListToRTF lst) ++ "} "+inlineToRTF (Quoted SingleQuote lst) = + "\\u8216'" ++ (inlineListToRTF lst) ++ "\\u8217'"+inlineToRTF (Quoted DoubleQuote lst) = + "\\u8220\"" ++ (inlineListToRTF lst) ++ "\\u8221\""+inlineToRTF Apostrophe = "\\u8217'"+inlineToRTF Ellipses = "\\u8230?"+inlineToRTF EmDash = "\\u8212-"+inlineToRTF EnDash = "\\u8211-"+inlineToRTF (Code str) = "{\\f1 " ++ (codeStringToRTF str) ++ "} "+inlineToRTF (Str str) = stringToRTF str+inlineToRTF (Math str) = inlineListToRTF $ readTeXMath str+inlineToRTF (TeX str) = ""+inlineToRTF (HtmlInline str) = ""+inlineToRTF (LineBreak) = "\\line "+inlineToRTF Space = " "+inlineToRTF (Link text (src, tit)) = + "{\\field{\\*\\fldinst{HYPERLINK \"" ++ (codeStringToRTF src) ++ + "\"}}{\\fldrslt{\\ul\n" ++ (inlineListToRTF text) ++ "\n}}}\n"+inlineToRTF (Image alternate (source, tit)) = + "{\\cf1 [image: " ++ source ++ "]\\cf0}" +inlineToRTF (Note contents) =+ "{\\super\\chftn}{\\*\\footnote\\chftn\\~\\plain\\pard " ++ + (concatMap (blockToRTF 0 AlignDefault) contents) ++ "}"
+ Text/Pandoc/Writers/S5.hs view
@@ -0,0 +1,140 @@+----------------------------------------------------+-- Do not edit this file by hand. Edit +-- 'templates/S5.hs'+-- and run ./fillTemplates.pl Text/Pandoc/Writers/S5.hs+----------------------------------------------------++{-+Copyright (C) 2006-7 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.S5+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Definitions for creation of S5 powerpoint-like HTML.+(See <http://meyerweb.com/eric/tools/s5/>.)+-}+module Text.Pandoc.Writers.S5 (+ -- * Strings+ s5Meta,+ s5Javascript,+ s5CSS,+ s5Links,+ -- * Functions+ writeS5,+ writeS5String,+ insertS5Structure+ ) where+import Text.Pandoc.Shared ( joinWithSep, WriterOptions )+import Text.Pandoc.Writers.HTML ( writeHtml, writeHtmlString )+import Text.Pandoc.Definition+import Text.XHtml.Strict++s5Meta :: String+s5Meta = "<!-- configuration parameters -->\n<meta name=\"defaultView\" content=\"slideshow\" />\n<meta name=\"controlVis\" content=\"hidden\" />\n"++s5Javascript :: String+s5Javascript = "<script type=\"text/javascript\">\n// S5 v1.1 slides.js -- released into the Public Domain\n//\n// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information \n// about all the wonderful and talented contributors to this code!\n\nvar undef;\nvar slideCSS = '';\nvar snum = 0;\nvar smax = 1;\nvar incpos = 0;\nvar number = undef;\nvar s5mode = true;\nvar defaultView = 'slideshow';\nvar controlVis = 'visible';\n\nvar isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0;\nvar isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0;\nvar isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0;\n\nfunction hasClass(object, className) {\n\tif (!object.className) return false;\n\treturn (object.className.search('(^|\\\\s)' + className + '(\\\\s|$)') != -1);\n}\n\nfunction hasValue(object, value) {\n\tif (!object) return false;\n\treturn (object.search('(^|\\\\s)' + value + '(\\\\s|$)') != -1);\n}\n\nfunction removeClass(object,className) {\n\tif (!object) return;\n\tobject.className = object.className.replace(new RegExp('(^|\\\\s)'+className+'(\\\\s|$)'), RegExp.$1+RegExp.$2);\n}\n\nfunction addClass(object,className) {\n\tif (!object || hasClass(object, className)) return;\n\tif (object.className) {\n\t\tobject.className += ' '+className;\n\t} else {\n\t\tobject.className = className;\n\t}\n}\n\nfunction GetElementsWithClassName(elementName,className) {\n\tvar allElements = document.getElementsByTagName(elementName);\n\tvar elemColl = new Array();\n\tfor (var i = 0; i< allElements.length; i++) {\n\t\tif (hasClass(allElements[i], className)) {\n\t\t\telemColl[elemColl.length] = allElements[i];\n\t\t}\n\t}\n\treturn elemColl;\n}\n\nfunction isParentOrSelf(element, id) {\n\tif (element == null || element.nodeName=='BODY') return false;\n\telse if (element.id == id) return true;\n\telse return isParentOrSelf(element.parentNode, id);\n}\n\nfunction nodeValue(node) {\n\tvar result = \"\";\n\tif (node.nodeType == 1) {\n\t\tvar children = node.childNodes;\n\t\tfor (var i = 0; i < children.length; ++i) {\n\t\t\tresult += nodeValue(children[i]);\n\t\t}\t\t\n\t}\n\telse if (node.nodeType == 3) {\n\t\tresult = node.nodeValue;\n\t}\n\treturn(result);\n}\n\nfunction slideLabel() {\n\tvar slideColl = GetElementsWithClassName('*','slide');\n\tvar list = document.getElementById('jumplist');\n\tsmax = slideColl.length;\n\tfor (var n = 0; n < smax; n++) {\n\t\tvar obj = slideColl[n];\n\n\t\tvar did = 'slide' + n.toString();\n\t\tobj.setAttribute('id',did);\n\t\tif (isOp) continue;\n\n\t\tvar otext = '';\n\t\tvar menu = obj.firstChild;\n\t\tif (!menu) continue; // to cope with empty slides\n\t\twhile (menu && menu.nodeType == 3) {\n\t\t\tmenu = menu.nextSibling;\n\t\t}\n\t \tif (!menu) continue; // to cope with slides with only text nodes\n\n\t\tvar menunodes = menu.childNodes;\n\t\tfor (var o = 0; o < menunodes.length; o++) {\n\t\t\totext += nodeValue(menunodes[o]);\n\t\t}\n\t\tlist.options[list.length] = new Option(n + ' : ' + otext, n);\n\t}\n}\n\nfunction currentSlide() {\n\tvar cs;\n\tif (document.getElementById) {\n\t\tcs = document.getElementById('currentSlide');\n\t} else {\n\t\tcs = document.currentSlide;\n\t}\n\tcs.innerHTML = '<span id=\"csHere\">' + snum + '<\\/span> ' + \n\t\t'<span id=\"csSep\">\\/<\\/span> ' + \n\t\t'<span id=\"csTotal\">' + (smax-1) + '<\\/span>';\n\tif (snum == 0) {\n\t\tcs.style.visibility = 'hidden';\n\t} else {\n\t\tcs.style.visibility = 'visible';\n\t}\n}\n\nfunction go(step) {\n\tif (document.getElementById('slideProj').disabled || step == 0) return;\n\tvar jl = document.getElementById('jumplist');\n\tvar cid = 'slide' + snum;\n\tvar ce = document.getElementById(cid);\n\tif (incrementals[snum].length > 0) {\n\t\tfor (var i = 0; i < incrementals[snum].length; i++) {\n\t\t\tremoveClass(incrementals[snum][i], 'current');\n\t\t\tremoveClass(incrementals[snum][i], 'incremental');\n\t\t}\n\t}\n\tif (step != 'j') {\n\t\tsnum += step;\n\t\tlmax = smax - 1;\n\t\tif (snum > lmax) snum = lmax;\n\t\tif (snum < 0) snum = 0;\n\t} else\n\t\tsnum = parseInt(jl.value);\n\tvar nid = 'slide' + snum;\n\tvar ne = document.getElementById(nid);\n\tif (!ne) {\n\t\tne = document.getElementById('slide0');\n\t\tsnum = 0;\n\t}\n\tif (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;}\n\tif (incrementals[snum].length > 0 && incpos == 0) {\n\t\tfor (var i = 0; i < incrementals[snum].length; i++) {\n\t\t\tif (hasClass(incrementals[snum][i], 'current'))\n\t\t\t\tincpos = i + 1;\n\t\t\telse\n\t\t\t\taddClass(incrementals[snum][i], 'incremental');\n\t\t}\n\t}\n\tif (incrementals[snum].length > 0 && incpos > 0)\n\t\taddClass(incrementals[snum][incpos - 1], 'current');\n\tce.style.visibility = 'hidden';\n\tne.style.visibility = 'visible';\n\tjl.selectedIndex = snum;\n\tcurrentSlide();\n\tnumber = 0;\n}\n\nfunction goTo(target) {\n\tif (target >= smax || target == snum) return;\n\tgo(target - snum);\n}\n\nfunction subgo(step) {\n\tif (step > 0) {\n\t\tremoveClass(incrementals[snum][incpos - 1],'current');\n\t\tremoveClass(incrementals[snum][incpos], 'incremental');\n\t\taddClass(incrementals[snum][incpos],'current');\n\t\tincpos++;\n\t} else {\n\t\tincpos--;\n\t\tremoveClass(incrementals[snum][incpos],'current');\n\t\taddClass(incrementals[snum][incpos], 'incremental');\n\t\taddClass(incrementals[snum][incpos - 1],'current');\n\t}\n}\n\nfunction toggle() {\n\tvar slideColl = GetElementsWithClassName('*','slide');\n\tvar slides = document.getElementById('slideProj');\n\tvar outline = document.getElementById('outlineStyle');\n\tif (!slides.disabled) {\n\t\tslides.disabled = true;\n\t\toutline.disabled = false;\n\t\ts5mode = false;\n\t\tfontSize('1em');\n\t\tfor (var n = 0; n < smax; n++) {\n\t\t\tvar slide = slideColl[n];\n\t\t\tslide.style.visibility = 'visible';\n\t\t}\n\t} else {\n\t\tslides.disabled = false;\n\t\toutline.disabled = true;\n\t\ts5mode = true;\n\t\tfontScale();\n\t\tfor (var n = 0; n < smax; n++) {\n\t\t\tvar slide = slideColl[n];\n\t\t\tslide.style.visibility = 'hidden';\n\t\t}\n\t\tslideColl[snum].style.visibility = 'visible';\n\t}\n}\n\nfunction showHide(action) {\n\tvar obj = GetElementsWithClassName('*','hideme')[0];\n\tswitch (action) {\n\tcase 's': obj.style.visibility = 'visible'; break;\n\tcase 'h': obj.style.visibility = 'hidden'; break;\n\tcase 'k':\n\t\tif (obj.style.visibility != 'visible') {\n\t\t\tobj.style.visibility = 'visible';\n\t\t} else {\n\t\t\tobj.style.visibility = 'hidden';\n\t\t}\n\tbreak;\n\t}\n}\n\n// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/)\nfunction keys(key) {\n\tif (!key) {\n\t\tkey = event;\n\t\tkey.which = key.keyCode;\n\t}\n\tif (key.which == 84) {\n\t\ttoggle();\n\t\treturn;\n\t}\n\tif (s5mode) {\n\t\tswitch (key.which) {\n\t\t\tcase 10: // return\n\t\t\tcase 13: // enter\n\t\t\t\tif (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;\n\t\t\t\tif (key.target && isParentOrSelf(key.target, 'controls')) return;\n\t\t\t\tif(number != undef) {\n\t\t\t\t\tgoTo(number);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tcase 32: // spacebar\n\t\t\tcase 34: // page down\n\t\t\tcase 39: // rightkey\n\t\t\tcase 40: // downkey\n\t\t\t\tif(number != undef) {\n\t\t\t\t\tgo(number);\n\t\t\t\t} else if (!incrementals[snum] || incpos >= incrementals[snum].length) {\n\t\t\t\t\tgo(1);\n\t\t\t\t} else {\n\t\t\t\t\tsubgo(1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 33: // page up\n\t\t\tcase 37: // leftkey\n\t\t\tcase 38: // upkey\n\t\t\t\tif(number != undef) {\n\t\t\t\t\tgo(-1 * number);\n\t\t\t\t} else if (!incrementals[snum] || incpos <= 0) {\n\t\t\t\t\tgo(-1);\n\t\t\t\t} else {\n\t\t\t\t\tsubgo(-1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 36: // home\n\t\t\t\tgoTo(0);\n\t\t\t\tbreak;\n\t\t\tcase 35: // end\n\t\t\t\tgoTo(smax-1);\n\t\t\t\tbreak;\n\t\t\tcase 67: // c\n\t\t\t\tshowHide('k');\n\t\t\t\tbreak;\n\t\t}\n\t\tif (key.which < 48 || key.which > 57) {\n\t\t\tnumber = undef;\n\t\t} else {\n\t\t\tif (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;\n\t\t\tif (key.target && isParentOrSelf(key.target, 'controls')) return;\n\t\t\tnumber = (((number != undef) ? number : 0) * 10) + (key.which - 48);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction clicker(e) {\n\tnumber = undef;\n\tvar target;\n\tif (window.event) {\n\t\ttarget = window.event.srcElement;\n\t\te = window.event;\n\t} else target = e.target;\n\tif (target.getAttribute('href') != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true;\n\tif (!e.which || e.which == 1) {\n\t\tif (!incrementals[snum] || incpos >= incrementals[snum].length) {\n\t\t\tgo(1);\n\t\t} else {\n\t\t\tsubgo(1);\n\t\t}\n\t}\n}\n\nfunction findSlide(hash) {\n\tvar target = null;\n\tvar slides = GetElementsWithClassName('*','slide');\n\tfor (var i = 0; i < slides.length; i++) {\n\t\tvar targetSlide = slides[i];\n\t\tif ( (targetSlide.name && targetSlide.name == hash)\n\t\t || (targetSlide.id && targetSlide.id == hash) ) {\n\t\t\ttarget = targetSlide;\n\t\t\tbreak;\n\t\t}\n\t}\n\twhile(target != null && target.nodeName != 'BODY') {\n\t\tif (hasClass(target, 'slide')) {\n\t\t\treturn parseInt(target.id.slice(5));\n\t\t}\n\t\ttarget = target.parentNode;\n\t}\n\treturn null;\n}\n\nfunction slideJump() {\n\tif (window.location.hash == null) return;\n\tvar sregex = /^#slide(\\d+)$/;\n\tvar matches = sregex.exec(window.location.hash);\n\tvar dest = null;\n\tif (matches != null) {\n\t\tdest = parseInt(matches[1]);\n\t} else {\n\t\tdest = findSlide(window.location.hash.slice(1));\n\t}\n\tif (dest != null)\n\t\tgo(dest - snum);\n}\n\nfunction fixLinks() {\n\tvar thisUri = window.location.href;\n\tthisUri = thisUri.slice(0, thisUri.length - window.location.hash.length);\n\tvar aelements = document.getElementsByTagName('A');\n\tfor (var i = 0; i < aelements.length; i++) {\n\t\tvar a = aelements[i].href;\n\t\tvar slideID = a.match('\\#slide[0-9]{1,2}');\n\t\tif ((slideID) && (slideID[0].slice(0,1) == '#')) {\n\t\t\tvar dest = findSlide(slideID[0].slice(1));\n\t\t\tif (dest != null) {\n\t\t\t\tif (aelements[i].addEventListener) {\n\t\t\t\t\taelements[i].addEventListener(\"click\", new Function(\"e\",\n\t\t\t\t\t\t\"if (document.getElementById('slideProj').disabled) return;\" +\n\t\t\t\t\t\t\"go(\"+dest+\" - snum); \" +\n\t\t\t\t\t\t\"if (e.preventDefault) e.preventDefault();\"), true);\n\t\t\t\t} else if (aelements[i].attachEvent) {\n\t\t\t\t\taelements[i].attachEvent(\"onclick\", new Function(\"\",\n\t\t\t\t\t\t\"if (document.getElementById('slideProj').disabled) return;\" +\n\t\t\t\t\t\t\"go(\"+dest+\" - snum); \" +\n\t\t\t\t\t\t\"event.returnValue = false;\"));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction externalLinks() {\n\tif (!document.getElementsByTagName) return;\n\tvar anchors = document.getElementsByTagName('a');\n\tfor (var i=0; i<anchors.length; i++) {\n\t\tvar anchor = anchors[i];\n\t\tif (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) {\n\t\t\tanchor.target = '_blank';\n\t\t\taddClass(anchor,'external');\n\t\t}\n\t}\n}\n\nfunction createControls() {\n\tvar controlsDiv = document.getElementById(\"controls\");\n\tif (!controlsDiv) return;\n\tvar hider = ' onmouseover=\"showHide(\\'s\\');\" onmouseout=\"showHide(\\'h\\');\"';\n\tvar hideDiv, hideList = '';\n\tif (controlVis == 'hidden') {\n\t\thideDiv = hider;\n\t} else {\n\t\thideList = hider;\n\t}\n\tcontrolsDiv.innerHTML = '<form action=\"#\" id=\"controlForm\"' + hideDiv + '>' +\n\t'<div id=\"navLinks\">' +\n\t'<a accesskey=\"t\" id=\"toggle\" href=\"javascript:toggle();\">Ø<\\/a>' +\n\t'<a accesskey=\"z\" id=\"prev\" href=\"javascript:go(-1);\">«<\\/a>' +\n\t'<a accesskey=\"x\" id=\"next\" href=\"javascript:go(1);\">»<\\/a>' +\n\t'<div id=\"navList\"' + hideList + '><select id=\"jumplist\" onchange=\"go(\\'j\\');\"><\\/select><\\/div>' +\n\t'<\\/div><\\/form>';\n\tif (controlVis == 'hidden') {\n\t\tvar hidden = document.getElementById('navLinks');\n\t} else {\n\t\tvar hidden = document.getElementById('jumplist');\n\t}\n\taddClass(hidden,'hideme');\n}\n\nfunction fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers\n\tif (!s5mode) return false;\n\tvar vScale = 22; // both yield 32 (after rounding) at 1024x768\n\tvar hScale = 32; // perhaps should auto-calculate based on theme's declared value?\n\tif (window.innerHeight) {\n\t\tvar vSize = window.innerHeight;\n\t\tvar hSize = window.innerWidth;\n\t} else if (document.documentElement.clientHeight) {\n\t\tvar vSize = document.documentElement.clientHeight;\n\t\tvar hSize = document.documentElement.clientWidth;\n\t} else if (document.body.clientHeight) {\n\t\tvar vSize = document.body.clientHeight;\n\t\tvar hSize = document.body.clientWidth;\n\t} else {\n\t\tvar vSize = 700; // assuming 1024x768, minus chrome and such\n\t\tvar hSize = 1024; // these do not account for kiosk mode or Opera Show\n\t}\n\tvar newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale));\n\tfontSize(newSize + 'px');\n\tif (isGe) { // hack to counter incremental reflow bugs\n\t\tvar obj = document.getElementsByTagName('body')[0];\n\t\tobj.style.display = 'none';\n\t\tobj.style.display = 'block';\n\t}\n}\n\nfunction fontSize(value) {\n\tif (!(s5ss = document.getElementById('s5ss'))) {\n\t\tif (!isIE) {\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style'));\n\t\t\ts5ss.setAttribute('media','screen, projection');\n\t\t\ts5ss.setAttribute('id','s5ss');\n\t\t} else {\n\t\t\tdocument.createStyleSheet();\n\t\t\tdocument.s5ss = document.styleSheets[document.styleSheets.length - 1];\n\t\t}\n\t}\n\tif (!isIE) {\n\t\twhile (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild);\n\t\ts5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}'));\n\t} else {\n\t\tdocument.s5ss.addRule('body','font-size: ' + value + ' !important;');\n\t}\n}\n\nfunction notOperaFix() {\n\tslideCSS = document.getElementById('slideProj').href;\n\tvar slides = document.getElementById('slideProj');\n\tvar outline = document.getElementById('outlineStyle');\n\tslides.setAttribute('media','screen');\n\toutline.disabled = true;\n\tif (isGe) {\n\t\tslides.setAttribute('href','null'); // Gecko fix\n\t\tslides.setAttribute('href',slideCSS); // Gecko fix\n\t}\n\tif (isIE && document.styleSheets && document.styleSheets[0]) {\n\t\tdocument.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)');\n\t\tdocument.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)');\n\t\tdocument.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)');\n\t}\n}\n\nfunction getIncrementals(obj) {\n\tvar incrementals = new Array();\n\tif (!obj) \n\t\treturn incrementals;\n\tvar children = obj.childNodes;\n\tfor (var i = 0; i < children.length; i++) {\n\t\tvar child = children[i];\n\t\tif (hasClass(child, 'incremental')) {\n\t\t\tif (child.nodeName == 'OL' || child.nodeName == 'UL') {\n\t\t\t\tremoveClass(child, 'incremental');\n\t\t\t\tfor (var j = 0; j < child.childNodes.length; j++) {\n\t\t\t\t\tif (child.childNodes[j].nodeType == 1) {\n\t\t\t\t\t\taddClass(child.childNodes[j], 'incremental');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tincrementals[incrementals.length] = child;\n\t\t\t\tremoveClass(child,'incremental');\n\t\t\t}\n\t\t}\n\t\tif (hasClass(child, 'show-first')) {\n\t\t\tif (child.nodeName == 'OL' || child.nodeName == 'UL') {\n\t\t\t\tremoveClass(child, 'show-first');\n\t\t\t\tif (child.childNodes[isGe].nodeType == 1) {\n\t\t\t\t\tremoveClass(child.childNodes[isGe], 'incremental');\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tincrementals[incrementals.length] = child;\n\t\t\t}\n\t\t}\n\t\tincrementals = incrementals.concat(getIncrementals(child));\n\t}\n\treturn incrementals;\n}\n\nfunction createIncrementals() {\n\tvar incrementals = new Array();\n\tfor (var i = 0; i < smax; i++) {\n\t\tincrementals[i] = getIncrementals(document.getElementById('slide'+i));\n\t}\n\treturn incrementals;\n}\n\nfunction defaultCheck() {\n\tvar allMetas = document.getElementsByTagName('meta');\n\tfor (var i = 0; i< allMetas.length; i++) {\n\t\tif (allMetas[i].name == 'defaultView') {\n\t\t\tdefaultView = allMetas[i].content;\n\t\t}\n\t\tif (allMetas[i].name == 'controlVis') {\n\t\t\tcontrolVis = allMetas[i].content;\n\t\t}\n\t}\n}\n\n// Key trap fix, new function body for trap()\nfunction trap(e) {\n\tif (!e) {\n\t\te = event;\n\t\te.which = e.keyCode;\n\t}\n\ttry {\n\t\tmodifierKey = e.ctrlKey || e.altKey || e.metaKey;\n\t}\n\tcatch(e) {\n\t\tmodifierKey = false;\n\t}\n\treturn modifierKey || e.which == 0;\n}\n\nfunction startup() {\n\tdefaultCheck();\n\tif (!isOp) \n\t\tcreateControls();\n\tslideLabel();\n\tfixLinks();\n\texternalLinks();\n\tfontScale();\n\tif (!isOp) {\n\t\tnotOperaFix();\n\t\tincrementals = createIncrementals();\n\t\tslideJump();\n\t\tif (defaultView == 'outline') {\n\t\t\ttoggle();\n\t\t}\n\t\tdocument.onkeyup = keys;\n\t\tdocument.onkeypress = trap;\n\t\tdocument.onclick = clicker;\n\t}\n}\n\nwindow.onload = startup;\nwindow.onresize = function(){setTimeout('fontScale()', 50);}</script>\n" ++s5CoreCSS :: String+s5CoreCSS = "/* Do not edit or override these styles! The system will likely break if you do. */\n\ndiv#header, div#footer, div#controls, .slide {position: absolute;}\nhtml>body div#header, html>body div#footer, \n html>body div#controls, html>body .slide {position: fixed;}\n.handout {display: none;}\n.layout {display: block;}\n.slide, .hideme, .incremental {visibility: hidden;}\n#slide0 {visibility: visible;}\n"++s5FramingCSS :: String+s5FramingCSS = "/* The following styles size, place, and layer the slide components.\n Edit these if you want to change the overall slide layout.\n The commented lines can be uncommented (and modified, if necessary) \n to help you with the rearrangement process. */\n\n/* target = 1024x768 */\n\ndiv#header, div#footer, .slide {width: 100%; top: 0; left: 0;}\ndiv#header {top: 0; height: 3em; z-index: 1;}\ndiv#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;}\n.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;}\ndiv#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}\ndiv#controls form {position: absolute; bottom: 0; right: 0; width: 100%;\n margin: 0;}\n#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;}\nhtml>body #currentSlide {position: fixed;}\n\n/*\ndiv#header {background: #FCC;}\ndiv#footer {background: #CCF;}\ndiv#controls {background: #BBD;}\ndiv#currentSlide {background: #FFC;}\n*/\n"++s5PrettyCSS :: String+s5PrettyCSS = "/* Following are the presentation styles -- edit away! */\n\nbody {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2em;}\n:link, :visited {text-decoration: none; color: #00C;}\n#controls :active {color: #88A !important;}\n#controls :focus {outline: 1px dotted #227;}\nh1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}\nul, pre {margin: 0; line-height: 1em;}\nhtml, body {margin: 0; padding: 0;}\n\nblockquote, q {font-style: italic;}\nblockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;}\nblockquote p {margin: 0;}\nblockquote i {font-style: normal;}\nblockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;}\nblockquote b i {font-style: italic;}\n\nkbd {font-weight: bold; font-size: 1em;}\nsup {font-size: smaller; line-height: 1px;}\n\n.slide code {padding: 2px 0.25em; font-weight: bold; color: #533;}\n.slide code.bad, code del {color: red;}\n.slide code.old {color: silver;}\n.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;}\n.slide pre code {display: block;}\n.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;}\n.slide li {margin-top: 0.75em; margin-right: 0;}\n.slide ul ul {line-height: 1;}\n.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;}\n.slide img.leader {display: block; margin: 0 auto;}\n\ndiv#header, div#footer {background: #005; color: #AAB;\n font-family: Verdana, Helvetica, sans-serif;}\ndiv#header {background: #005 url(bodybg.gif) -16px 0 no-repeat;\n line-height: 1px;}\ndiv#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;}\n#footer h1, #footer h2 {display: block; padding: 0 1em;}\n#footer h2 {font-style: italic;}\n\ndiv.long {font-size: 0.75em;}\n.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1;\n margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap;\n font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize;\n color: #DDE; background: #005;}\n.slide h3 {font-size: 130%;}\nh1 abbr {font-variant: small-caps;}\n\ndiv#controls {position: absolute; left: 50%; bottom: 0;\n width: 50%;\n text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;}\nhtml>body div#controls {position: fixed; padding: 0 0 1em 0;\n top: auto;}\ndiv#controls form {position: absolute; bottom: 0; right: 0; width: 100%;\n margin: 0; padding: 0;}\n#controls #navLinks a {padding: 0; margin: 0 0.5em; \n background: #005; border: none; color: #779; \n cursor: pointer;}\n#controls #navList {height: 1em;}\n#controls #navList #jumplist {position: absolute; bottom: 0; right: 0; background: #DDD; color: #227;}\n\n#currentSlide {text-align: center; font-size: 0.5em; color: #449;}\n\n#slide0 {padding-top: 3.5em; font-size: 90%;}\n#slide0 h1 {position: static; margin: 1em 0 0; padding: 0;\n font: bold 2em Helvetica, sans-serif; white-space: normal;\n color: #000; background: transparent;}\n#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;}\n#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}\n#slide0 h4 {margin-top: 0; font-size: 1em;}\n\nul.urls {list-style: none; display: inline; margin: 0;}\n.urls li {display: inline; margin: 0;}\n.note {display: none;}\n.external {border-bottom: 1px dotted gray;}\nhtml>body .external {border-bottom: none;}\n.external:after {content: \" \\274F\"; font-size: smaller; color: #77B;}\n\n.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;}\nimg.incremental {visibility: hidden;}\n.slide .current {color: #B02;}\n\n\n/* diagnostics\n\nli:after {content: \" [\" attr(class) \"]\"; color: #F88;}\n */"++s5OperaCSS :: String+s5OperaCSS = "/* DO NOT CHANGE THESE unless you really want to break Opera Show */\n.slide {\n\tvisibility: visible !important;\n\tposition: static !important;\n\tpage-break-before: always;\n}\n#slide0 {page-break-before: avoid;}\n"++s5OutlineCSS :: String+s5OutlineCSS = "/* don't change this unless you want the layout stuff to show up in the outline view! */\n\n.layout div, #footer *, #controlForm * {display: none;}\n#footer, #controls, #controlForm, #navLinks, #toggle {\n display: block; visibility: visible; margin: 0; padding: 0;}\n#toggle {float: right; padding: 0.5em;}\nhtml>body #toggle {position: fixed; top: 0; right: 0;}\n\n/* making the outline look pretty-ish */\n\n#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;}\n#slide0 h1 {padding-top: 1.5em;}\n.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em;\n border-top: 1px solid #888; border-bottom: 1px solid #AAA;}\n#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;}\n"++s5PrintCSS :: String+s5PrintCSS = "/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */\n.slide, ul {page-break-inside: avoid; visibility: visible !important;}\nh1 {page-break-after: avoid;}\n\nbody {font-size: 12pt; background: white;}\n* {color: black;}\n\n#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}\n#slide0 h3 {margin: 0; padding: 0;}\n#slide0 h4 {margin: 0 0 0.5em; padding: 0;}\n#slide0 {margin-bottom: 3em;}\n\nh1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}\n.extra {background: transparent !important;}\ndiv.extra, pre.extra, .example {font-size: 10pt; color: #333;}\nul.extra a {font-weight: bold;}\np.example {display: none;}\n\n#header {display: none;}\n#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}\n#footer h2, #controls {display: none;}\n\n/* The following rule keeps the layout stuff out of print. Remove at your own risk! */\n.layout, .layout * {display: none !important;}\n"++s5CSS :: String+s5CSS = "<style type=\"text/css\" media=\"projection\" id=\"slideProj\">\n" ++ s5CoreCSS ++ "\n" ++ s5FramingCSS ++ "\n" ++ s5PrettyCSS ++ "\n</style>\n<style type=\"text/css\" media=\"projection\" id=\"operaFix\">\n" ++ s5OperaCSS ++ "\n</style>\n<style type=\"text/css\" media=\"screen\" id=\"outlineStyle\">\n" ++ s5OutlineCSS ++ "\n</style>\n<style type=\"text/css\" media=\"print\" id=\"slidePrint\">\n" ++ s5PrintCSS ++ "\n</style>\n"++s5Links :: String+s5Links = "<!-- style sheet links -->\n<link rel=\"stylesheet\" href=\"ui/default/slides.css\" type=\"text/css\" media=\"projection\" id=\"slideProj\" />\n<link rel=\"stylesheet\" href=\"ui/default/outline.css\" type=\"text/css\" media=\"screen\" id=\"outlineStyle\" />\n<link rel=\"stylesheet\" href=\"ui/default/print.css\" type=\"text/css\" media=\"print\" id=\"slidePrint\" />\n<link rel=\"stylesheet\" href=\"ui/default/opera.css\" type=\"text/css\" media=\"projection\" id=\"operaFix\" />\n<!-- S5 JS -->\n<script src=\"ui/default/slides.js\" type=\"text/javascript\"></script>\n"++-- | Converts Pandoc document to an S5 HTML presentation (Html structure).+writeS5 :: WriterOptions -> Pandoc -> Html+writeS5 options = (writeHtml options) . insertS5Structure++-- | Converts Pandoc document to an S5 HTML presentation (string).+writeS5String :: WriterOptions -> Pandoc -> String+writeS5String options = (writeHtmlString options) . insertS5Structure++-- | Inserts HTML needed for an S5 presentation (e.g. around slides).+layoutDiv :: [Inline] -- ^ Title of document (for header or footer)+ -> String -- ^ Date of document (for header or footer)+ -> [Block] -- ^ List of block elements returned+layoutDiv title date = [(RawHtml "<div class=\"layout\">\n<div id=\"controls\"></div>\n<div id=\"currentSlide\"></div>\n<div id=\"header\"></div>\n<div id=\"footer\">\n"), (Header 1 [Str date]), (Header 2 title), (RawHtml "</div>\n</div>\n")]++presentationStart = RawHtml "<div class=\"presentation\">\n\n"++presentationEnd = RawHtml "</div>\n"++slideStart = RawHtml "<div class=\"slide\">\n"++slideEnd = RawHtml "</div>\n"++-- | Returns 'True' if block is a Header 1.+isH1 :: Block -> Bool+isH1 (Header 1 _) = True+isH1 _ = False ++-- | Insert HTML around sections to make individual slides.+insertSlides :: Bool -> [Block] -> [Block]+insertSlides beginning blocks = + let (beforeHead, rest) = break isH1 blocks in+ if (null rest) then + if beginning then+ beforeHead + else+ beforeHead ++ [slideEnd]+ else+ if beginning then+ beforeHead ++ + slideStart:(head rest):(insertSlides False (tail rest))+ else+ beforeHead ++ + slideEnd:slideStart:(head rest):(insertSlides False (tail rest)) ++-- | Insert blocks into 'Pandoc' for slide structure.+insertS5Structure :: Pandoc -> Pandoc+insertS5Structure (Pandoc meta []) = Pandoc meta []+insertS5Structure (Pandoc (Meta title authors date) blocks) = + let slides = insertSlides True blocks + firstSlide = if not (null title)+ then [slideStart, (Header 1 title), + (Header 3 [Str (joinWithSep ", " authors)]),+ (Header 4 [Str date]), slideEnd]+ else []+ newBlocks = (layoutDiv title date) ++ presentationStart:firstSlide +++ slides ++ [presentationEnd]+ in Pandoc (Meta title authors date) newBlocks+
debian/changelog view
@@ -1,3 +1,270 @@+pandoc (0.45) unstable; urgency=low++ [ John MacFarlane ]++ * Simplified parsing of reference keys and notes in markdown and RST+ readers: The Reference data structure from Text.Pandoc.Shared is no+ longer needed, since referenceKey and noteBlock parses return strings+ (as many blank lines as were occupied by the key or note) and update+ state themselves. getPosition and setPosition are now used to ensure+ that error messages will give the correct line number. This yields+ cleaner (and slightly faster) code, with more accurate parsing error+ messages.++ * Added new Math inline element:++ + Markdown and LaTeX readers now convert TeX math into Math elements,+ not TeX.+ + This allows math to be treated differently from raw TeX in output.+ TeX elements are no longer printed in output formats other than+ Markdown, LaTeX, and ConTeXt. But Math elements are always printed.++ * New default handling of math in writers:++ + New module Text.Pandoc.Readers.TeXMath exports readTeXMath, which+ parses raw TeX math and outputs a string of Pandoc inlines that+ tries to render it as far as possible using unicode characters,+ lapsing into literal TeX when needed.+ + readTeXMath is now used for default HTML output in HTML, S5, RTF,+ and Docbook, if no other method for displaying math in HTML is+ specified. Enclosing $'s are no longer printed by default.+ + By default, math is put inside <span class="math">. This way it can be+ distinguished from the surrounding text, e.g. put in a different+ font.++ * New --gladtex and --mimetex options for display of math in HTML:++ + If --gladtex is specified, math is output between <eq> tags, so+ it can be processed by gladTeX.+ + If --mimetex is specified, math is put in <img> tags with a link+ to the mimetex CGI script (or any other script that takes TeX math+ as input and outputs an image). The URL of the script may be+ specified, but defaults to /cgi-bin/mimetex.cgi.+ + HTMLMathMethod structure in WriterOptions keeps track of how to+ display math in HTML output.+ + Updated README with a description of the four options for displaying+ math in HTML.++ * HTML reader:+ + + Fixed bug: parser for minimized attributes should not swallow+ trailing spaces.+ + Simplified HTML attribute parsing.+ + Changed parsing of code blocks in HTML reader: <code> tag is no+ longer needed. <pre> suffices. All HTML tags in the code block+ (e.g. for syntax highlighting) are skipped, because they are not+ portable to other output formats. A <code>...</code> block not+ surrounded by <pre> now counts as inline HTML, not a code block.+ + Remove just one leading and one trailing newline from contents of+ <pre>...</pre> in codeBlock parser.+ + * Markdown reader:++ + Removed support for box-style block quotes.+ + Require space before title in links and references.+ This fixes a bug in parsing URLs like http://silly/url(withparen).+ + Improved and simplified setextHeader parser.+ + Fixed logic in smart quote parsing, adding some needed 'try'+ statements.+ + Fixed smart quote parsing so that unicode characters 8216 and 8217+ are recognized as single quotes, and 8220 and 8221 as double quotes.++ * RST reader:++ + Fixed bug in parsing of code blocks. Previously a full tab indent+ was required, but RST allows code to be indented any amount.+ Resolves Issue #27.+ + Allow field lists to be indented.+ + Parse the contents of field lists instead of treating as a raw string.+ + Represent field lists as definition lists instead of blockquotes. + + Fixed bug in which metadata would be overridden if the document+ contained multiple field lists.+ + Parse fields associated with '.. image::' blocks, and use 'alt'+ field, if given, for image alt and title attributes. ++ * LaTeX reader: ++ + Modified specialChar so that '"' characters are parsed.+ + Fixed a bug in parsing of \[ \] math blocks (thanks to Mark Kalderon).++ * HTML writer:++ + Changes in handling of math (see above).+ + Don't produce HTML for table of contents if there are+ no headers. (This would be an empty list, which is invalid XHTML.)++ * Markdown writer:+ + + Don't print title attribute if title is empty. (This differs from+ the behavior of Markdown.pl, and agrees with PHP Markdown. But John+ Gruber has indicated that he prefers this behavior.) Adjusted test+ suite accordingly.+ + Fixed incorrect line wrapping in paragraphs including hard line+ breaks. Resolves Issue #25.+ + Fixed bug in markdown writer: If an ordered list item began with+ a marker greater than 3 characters in width, and the item took more+ than one line, it would appear on the line after the list marker,+ e.g.:+ + (12)+ My list item.+ Multiline.+ + Now it works as follows:+ + (12) My list item.+ Multiline.+ + * RST writer+ + + Fixed bug in RST writer's handling of ordered lists. Previously,+ list items with multiple lines would not always line up with+ single-line list items. Now, list items are nested the length of+ the list marker + 1. This looks better and ensures that list items+ all line up. (Note that list markers are padded to the length of+ the longest list marker in the series.)+ + Use 3-space indent for unordered lists.+ + If label for a link reference contains a colon, surround it by `+ signs so it won't be interpreted as the end of the link label.++ * LaTeX writer:++ + Cleaner output for footnotes. Footnotes now always begin on a new+ line, and the final } is on a line by itself only when it needs to+ be (i.e. only when the note ends with a Verbatim environment).+ + Added writer options to state, so state doesn't need to be passed as+ a parameter.+ + Text wrapping now provided, using wrapTeXIfNeeded.++ * ConTeXt writer: many improvements for more idiomatic ConTeXt output+ (thanks to Idris Samawi Hamid for suggestions).++ + PrettyPrint module now used for output.+ + Writer options are now in state, so they don't have to be passed as+ a parameter.+ + Text wrapping now provided, using wrapTeXIfNeeded.+ + Better treatment of footnotes: footnotes are always on lines by+ themselves, and the final } is on a line by itself only when+ it needs to be (after \stoptyping).+ + Use \subject, \subsubject, ... or \section, \subsection, ... for headings,+ depending on whether --number-sections option is selected.+ + Extra blank line inserted after \stopitemize+ + Use new, "official" definition of blockquote environment. Also, use+ blank line after \startblockquote to balance blank line at the end.+ + Both itemized and enumerated lists are now generated using+ \start-stopitemize, with appropriate options. Removed definitions+ of ltxenum and ltxitem, which are no longer needed. Provided+ defaults for itemized lists in the preamble. State keeps track of+ ordered list level, so that when default numbering is specified,+ the appropriate scheme can be used.+ + Changed \useurl to \useURL.+ + Changed link color from red to blue.+ + Use \subsubsubsubsection etc., since these are supported + (up to at least sub x 5).++ * Text.Pandoc.Shared:++ + Save and restore position in parseFromString, so that accurate+ error messages can be given.+ + Improved efficiency of romanNumeral parser.+ + Added wrappedTeX and wrapTeXIfNeeded functions. These ensure+ that footnotes occur on lines by themselves (to make them+ easier to see and move) and do not screw up line wrapping.++ * Text.Pandoc.UTF8: modified fromUTF8 to strip out the BOM+ if present. Windows Notepad and other applications insert a+ BOM at the beginning of a UTF8 file.++ * Main.hs (tabFilter): Treat '\r' at end of line as newline (in+ addition to "\r\n" and '\n').++ * Added a writer option for wrapped text and a command-line option+ '--no-wrap', which disables text wrapping and minimizes whitespace+ in HTML. (Resolves Issue #26.)++ + Added support for '--no-wrap' to Main.hs.+ + Added wrapIfNeeded function to Text.Pandoc.Shared.+ + Use wrapIfNeeded instead of wrapped in the RST, Man, Docbook, and+ Markdown writers.+ + Added render and renderFragment helpers to HTML writer.++ * Modified html2markdown to run tidy only if the HTML cannot be+ parsed. Previously html2markdown piped all input through tidy+ before passing it to pandoc. This caused problems on certain pages+ (e.g. http://daringfireball.com/markdown) which have well-formed+ XHTML that causes tidy to choke. The solution is to pipe through+ tidy only if pandoc cannot parse the input by itself. This means+ that a temp file is now always used, even when input comes from a+ local file or standard input.++ * Removed 'version' constant from Main.hs; added 'pandocVersion' to+ Text.Pandoc library.++ * pandoc.cabal:++ + Modified to work with GHC 6.8 and Cabal configurations. (For GHC+ 6.8, pretty and containers must be added to Build-Depends, and it+ is desirable to use the -O2 compiler option.) Cabal configurations+ allows one to select options depending on the compiler version.+ For GHC 6.6, the splitBase option can be disabled.+ + pandoc.cabal.ghc66 is provided for users with older versions of+ Cabal, which do not support configurations.+ + Use Ghc-Prof-Options to ensure that '-auto-all' is used when+ '--enable-(executable|library)-profiling' is specified. Updated+ PROFILING instructions accordingly.++ * Makefile:++ + Makefile now checks GHC version. If GHC is 6.6, pandoc.cabal.ghc66+ is copied to pandoc.cabal, and the old pandoc.cabal is copied+ to pandoc.cabal.orig. Otherwise, pandoc.cabal is copied to+ pandoc.cabal.orig but otherwise unmodified. This way, the Makefile+ will work properly with either GHC 6.6 or 6.8.+ + Changed BUILDCONF to point to dist/setup-config, not .setup-config.+ This is where current versions of Cabal put it. + + Added $(BUILDCMD) target, so setup doesn't get compiled every time.+ + Removed dependency of templates on ./templates, which is circular+ now that templates is a subdirectory of the top-level.++ * MacPorts Portfile:++ + Modified to install the pandoc library in addition to programs. + + Installation must be done manually rather than using Makefile's+ install-all.+ + Note that the library must be registered in the activate phase,+ after the library files have been copied out of the destroot.+ Cabal generates a 'register.sh' script that will do this.++ * debian/control: Added libghc6-network-dev, libghc6-xhtml-dev, and+ libghc6-mtl-dev as dependencies for libghc6-pandoc-dev.+ Closes: #445235++ * debian/rules: Converted to UTF-8.++ * Changed pandoc home page to http://johnmacfarlane.net/pandoc/.++ * Updated ASCIIMathML.js to latest version.++ * Directory structure:++ + Moved everything from src into the top-level directory.+ + Changed references to source directory in Makefile and+ pandoc.cabal.*.+ + Moved ASCIIMathML.js, headers, and ui into templates directory.+ + Modified fillTemplates.pl to reflect new paths.++ [ Recai Oktaş ]++ * Makefile: Fixed the issue of having two copies of the library+ documentation under some usage scenarios.++ * Replaced 'ghc' with '$(GHC)' in Makefile, and made GHC+ and GHC_PKG configurable through the environment, to support+ unusual ghc installations. For example:+ GHC=/opt/ghc/bin/ghc GHC_PKG=/opt/ghc/bin/ghc-pkg make++ -- Recai Oktaş <roktas@debian.org> Sun, 07 Oct 2007 20:51:43 +0300+ pandoc (0.44) unstable; urgency=low [ John MacFarlane ]
debian/control view
@@ -4,6 +4,7 @@ Maintainer: Recai Oktaş <roktas@debian.org> Build-Depends: debhelper (>= 4.0.0), haskell-devscripts (>=0.5.12), ghc6 (>= 6.6-1), libghc6-xhtml-dev, libghc6-mtl-dev, libghc6-network-dev, perl Build-Depends-Indep: haddock+Build-Conflicts: ghc6 (>= 6.8), ghc6 (<= 6.4) Standards-Version: 3.7.2.0 XS-Vcs-Svn: http://pandoc.googlecode.com/svn/trunk XS-Vcs-Browser: http://pandoc.googlecode.com/svn/trunk@@ -33,12 +34,12 @@ this native representation into a target format. Thus, adding an input or output format requires only adding a reader or writer. .- Homepage: http://sophos.berkeley.edu/macfarlane/pandoc/+ Homepage: http://johnmacfarlane.net/pandoc/ Package: libghc6-pandoc-dev Section: libdevel Architecture: any-Depends: ${haskell:Depends}+Depends: ${haskell:Depends}, libghc6-xhtml-dev, libghc6-mtl-dev, libghc6-network-dev Suggests: pandoc-doc Description: general markup converter Pandoc is a Haskell library for converting from one markup format to@@ -62,7 +63,7 @@ . This package contains the libraries compiled for GHC 6. .- Homepage: http://sophos.berkeley.edu/macfarlane/pandoc/+ Homepage: http://johnmacfarlane.net/pandoc/ Package: pandoc-doc Section: doc@@ -89,4 +90,4 @@ . This package contains the library documentation for Pandoc. .- Homepage: http://sophos.berkeley.edu/macfarlane/pandoc/+ Homepage: http://johnmacfarlane.net/pandoc/
debian/copyright view
@@ -25,7 +25,7 @@ Pandoc's complete source code is available from the [Pandoc home page]. -[Pandoc home page]: http://sophos.berkeley.edu/macfarlane/pandoc/ +[Pandoc home page]: http://johnmacfarlane.net/pandoc/ Pandoc includes some code from other authors. The copyright and license statements for these sources are included below. All are GPL-compatible
debian/rules view
@@ -12,6 +12,8 @@ THIS := $(shell sed -ne 's/^Source: \(.*\)/\1/p' debian/control) PREFIX := /usr DESTDIR := debian/$(THIS)+DATADIR := $(THIS)+DOCDIR := doc/$(THIS) # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1@@ -29,7 +31,7 @@ endif # Export all variables which will be used in various stages of build process.-export PREFIX DESTDIR HCFLAGS+export PREFIX DESTDIR DATADIR DOCDIR HCFLAGS configure: configure-stamp configure-stamp:
freebsd/pkg-descr view
@@ -16,4 +16,4 @@ this native representation into a target format. Thus, adding an input or output format requires only adding a reader or writer. -WWW: http://sophos.berkeley.edu/macfarlane/pandoc/+WWW: http://johnmacfarlane.net/pandoc/
html2markdown view
@@ -146,28 +146,28 @@ inurl="$argument" fi +# As a security measure refuse to proceed if mktemp is not available.+pathfind mktemp || { err "Couldn't find 'mktemp'; aborting."; exit 1; }++# Avoid issues with /tmp directory on Windows/Cygwin +cygwin=+cygwin=$(uname | sed -ne '/^CYGWIN/p')+if [ -n "$cygwin" ]; then+ TMPDIR=.+ export TMPDIR+fi++THIS_TEMPDIR=+THIS_TEMPDIR="$(mktemp -d -t $THIS.XXXXXXXX)" || exit 1+readonly THIS_TEMPDIR++trap 'exitcode=$?+ [ -z "$THIS_TEMPDIR" ] || rm -rf "$THIS_TEMPDIR"+ exit $exitcode' 0 1 2 3 13 15+ if [ -n "$inurl" ]; then err "Attempting to fetch file from '$inurl'..." - # As a security measure refuse to proceed if mktemp is not available.- pathfind mktemp || { err "Couldn't find 'mktemp'; aborting."; exit 1; }- - # Avoid issues with /tmp directory on Windows/Cygwin - cygwin=- cygwin=$(uname | sed -ne '/^CYGWIN/p')- if [ -n "$cygwin" ]; then- TMPDIR=.- export TMPDIR- fi- - THIS_TEMPDIR=- THIS_TEMPDIR="$(mktemp -d -t $THIS.XXXXXXXX)" || exit 1- readonly THIS_TEMPDIR- - trap 'exitcode=$?- [ -z "$THIS_TEMPDIR" ] || rm -rf "$THIS_TEMPDIR"- exit $exitcode' 0 1 2 3 13 15- grabber_out=$THIS_TEMPDIR/grabber.out grabber_log=$THIS_TEMPDIR/grabber.log if ! grab_url_with "$inurl" "$grabber" 1>$grabber_out 2>$grabber_log; then@@ -203,14 +203,19 @@ alias to_utf8='cat' fi +htmlinput=$THIS_TEMPDIR/htmlinput+ if [ -z "$argument" ]; then- tidy -asxhtml -utf8 2>/dev/null | pandoc --ignore-args -r html -w markdown "$@"+ to_utf8 > $htmlinput # read from STDIN+elif [ -f "$argument" ]; then+ to_utf8 "$argument" > $htmlinput # read from file else- if [ -f "$argument" ]; then- to_utf8 "$argument" | - tidy -asxhtml -utf8 2>/dev/null | pandoc --ignore-args -r html -w markdown "$@"- else- err "File '$argument' not found."- exit 1- fi+ err "File '$argument' not found."+ exit 1+fi++if ! cat $htmlinput | pandoc --ignore-args -r html -w markdown "$@" ; then+ err "Failed to parse HTML. Trying again with tidy..."+ tidy -q -asxhtml -utf8 $htmlinput | \+ pandoc --ignore-args -r html -w markdown "$@" fi
macports/Portfile.in view
@@ -13,7 +13,7 @@ HTML, and LaTeX, and it can write markdown, reStructuredText, HTML, \ LaTeX, ConTeXt, DocBook, RTF, groff man pages, and S5 HTML slide shows. -homepage http://sophos.berkeley.edu/pandoc/+homepage http://johnmacfarlane.net/pandoc/ platforms darwin master_sites http://pandoc.googlecode.com/files/ checksums md5 @TARBALLMD5SUM@@@ -23,4 +23,37 @@ use_configure no build.args PREFIX=${prefix} build.target build-all-destroot.target install-all++destroot { + # install pandoc executable, libraries, and library documentation:+ system "(cd ${worksrcpath}; ./setup copy --destdir=${destroot})"+ # strip the pandoc binary:+ system "strip ${destroot}${prefix}/bin/pandoc"+ # create scripts to register libraries in post-activate phase:+ system "(cd ${worksrcpath}; ./setup register --gen-script)"+ system "(cd ${worksrcpath}; ./setup unregister --gen-script)"+ # install register/unregister scripts:+ xinstall -d ${destroot}${prefix}/libexec/${name}-${version}+ xinstall -m 755 ${worksrcpath}/register.sh \+ ${destroot}${prefix}/libexec/${name}-${version}+ xinstall -m 755 ${worksrcpath}/unregister.sh \+ ${destroot}${prefix}/libexec/${name}-${version}+ # install shell scripts:+ xinstall -m 755 -W ${worksrcpath} html2markdown hsmarkdown markdown2pdf \+ ${destroot}${prefix}/bin+ # install user documentation and man pages:+ xinstall -d ${destroot}${prefix}/share/doc/${name}+ xinstall -m 644 -W ${worksrcpath} README README.html COPYRIGHT BUGS \+ ${destroot}${prefix}/share/doc/${name}+ xinstall -m 644 -W ${worksrcpath}/man/man1 pandoc.1 hsmarkdown.1 \+ markdown2pdf.1 html2markdown.1 ${destroot}${prefix}/share/man/man1+}+ +post-activate { + # Register the library with the ghc package database:+ system "${prefix}/libexec/${name}-${version}/register.sh" +}++#pre-deactivate {+# system "${prefix}/libexec/${name}-${version}/unregister.sh" +#}
man/man1/hsmarkdown.1.md view
@@ -39,4 +39,4 @@ file distributed with Pandoc contains full documentation. The Pandoc source code and all documentation may be downloaded from-<http://sophos.berkeley.edu/macfarlane/pandoc/>.+<http://johnmacfarlane.net/pandoc/>.
man/man1/html2markdown.1.md view
@@ -48,6 +48,9 @@ -R, \--parse-raw : Parse untranslatable HTML codes as raw HTML. +\--no-wrap+: Disable text wrapping in output. (Default is to wrap text.)+ -H *FILE*, \--include-in-header=*FILE* : Include contents of *FILE* at the end of the header. Implies `-s`.
man/man1/pandoc.1.md view
@@ -1,6 +1,6 @@ % PANDOC(1) Pandoc User Manuals % John MacFarlane-% June 30, 2007+% November 30, 2007 # NAME @@ -102,11 +102,20 @@ when the output format is `latex` or `context`.) -m*URL*, \--asciimathml=*URL*-: Use ASCIIMathML to display embedded LaTeX math in HTML output.+: Use ASCIIMathML to display embedded TeX math in HTML output. To insert a link to a local copy of the `ASCIIMathML.js` script, provide a *URL*. If no *URL* is provided, the contents of the script will be inserted directly into the HTML header. +\--gladtex+: Enclose TeX math in `<eq>` tags in HTML output. These can then+ be processed by gladTeX to produce links to images of the typeset+ formulas. ++\--mimetex=*URL*+: Render TeX math using the mimeTeX CGI script. If *URL* is not specified,+ it is assumed that the script is at `/cgi-bin/mimetex.cgi`.+ -i, \--incremental : Make list items in S5 display incrementally (one by one). @@ -114,6 +123,9 @@ : Number section headings in LaTeX output. (Default is not to number them.) +\--no-wrap+: Disable text wrapping in output. (Default is to wrap text.)+ \--toc, \--table-of-contents : Include an automatically generated table of contents (HTML, markdown, RTF) or an instruction to create one (LaTeX, reStructuredText).@@ -176,5 +188,5 @@ The *README* file distributed with Pandoc contains full documentation. The Pandoc source code and all documentation may be downloaded from-<http://sophos.berkeley.edu/macfarlane/pandoc/>.+<http://johnmacfarlane.net/pandoc/>.
pandoc.cabal view
@@ -1,12 +1,13 @@ Name: pandoc-Version: 0.44+Version: 0.45+Cabal-Version: >= 1.2 License: GPL License-File: COPYING Copyright: (c) 2006-2007 John MacFarlane Author: John MacFarlane <jgm@berkeley.edu> Maintainer: John MacFarlane <jgm@berkeley.edu> Stability: alpha-Homepage: http://sophos.berkeley.edu/macfarlane/pandoc+Homepage: http://johnmacfarlane.net/pandoc Package-URL: http://pandoc.googlecode.com/files/pandoc-0.4.tar.gz Category: Text Tested-With: GHC@@ -31,32 +32,44 @@ which convert this native representation into a target format. Thus, adding an input or output format requires only adding a reader or writer.-Build-Depends: base, parsec, xhtml, mtl, regex-compat, network-Hs-Source-Dirs: src-Exposed-Modules: Text.Pandoc,- Text.Pandoc.Blocks,- Text.Pandoc.Definition,- Text.Pandoc.CharacterReferences,- Text.Pandoc.Shared,- Text.Pandoc.UTF8,- Text.Pandoc.ASCIIMathML,- Text.Pandoc.Readers.HTML,- Text.Pandoc.Readers.LaTeX,- Text.Pandoc.Readers.Markdown,- Text.Pandoc.Readers.RST,- Text.Pandoc.Writers.DefaultHeaders,- Text.Pandoc.Writers.Docbook,- Text.Pandoc.Writers.HTML,- Text.Pandoc.Writers.LaTeX,- Text.Pandoc.Writers.ConTeXt,- Text.Pandoc.Writers.Man,- Text.Pandoc.Writers.Markdown,- Text.Pandoc.Writers.RST,- Text.Pandoc.Writers.RTF,- Text.Pandoc.Writers.S5-Ghc-Options: -O0+Flag splitBase+ Description: Choose the new, smaller, split-up base package.+ Default: True -Executable: pandoc-Hs-Source-Dirs: src-Main-Is: Main.hs-Ghc-Options: -O0+Library+ if flag(splitBase)+ Build-Depends: base >= 3, pretty, containers+ else+ Build-Depends: base < 3+ Build-Depends: parsec, xhtml, mtl, regex-compat, network+ Hs-Source-Dirs: .+ Exposed-Modules: Text.Pandoc,+ Text.Pandoc.Blocks,+ Text.Pandoc.Definition,+ Text.Pandoc.CharacterReferences,+ Text.Pandoc.Shared,+ Text.Pandoc.UTF8,+ Text.Pandoc.ASCIIMathML,+ Text.Pandoc.Readers.HTML,+ Text.Pandoc.Readers.LaTeX,+ Text.Pandoc.Readers.Markdown,+ Text.Pandoc.Readers.RST,+ Text.Pandoc.Readers.TeXMath,+ Text.Pandoc.Writers.DefaultHeaders,+ Text.Pandoc.Writers.Docbook,+ Text.Pandoc.Writers.HTML,+ Text.Pandoc.Writers.LaTeX,+ Text.Pandoc.Writers.ConTeXt,+ Text.Pandoc.Writers.Man,+ Text.Pandoc.Writers.Markdown,+ Text.Pandoc.Writers.RST,+ Text.Pandoc.Writers.RTF,+ Text.Pandoc.Writers.S5+ Ghc-Options: -O2+ Ghc-Prof-Options: -auto-all++Executable pandoc+ Hs-Source-Dirs: .+ Main-Is: Main.hs+ Ghc-Options: -O2+ Ghc-Prof-Options: -auto-all
+ pandoc.cabal.ghc66 view
@@ -0,0 +1,63 @@+Name: pandoc+Version: 0.45+License: GPL+License-File: COPYING+Copyright: (c) 2006-2007 John MacFarlane+Author: John MacFarlane <jgm@berkeley.edu>+Maintainer: John MacFarlane <jgm@berkeley.edu>+Stability: alpha+Homepage: http://johnmacfarlane.net/pandoc+Package-URL: http://pandoc.googlecode.com/files/pandoc-0.4.tar.gz+Category: Text+Tested-With: GHC+Synopsis: Conversion between markup formats+Description: Pandoc is a Haskell library for converting from one markup+ format to another, and a command-line tool that uses+ this library. It can read markdown and (subsets of)+ reStructuredText, HTML, and LaTeX, and it can write+ markdown, reStructuredText, HTML, LaTeX, ConTeXt, Docbook,+ RTF, groff man pages, and S5 HTML slide shows.+ .+ Pandoc extends standard markdown syntax with footnotes,+ embedded LaTeX, definition lists, tables, and other+ features. A compatibility mode is provided for those+ who need a drop-in replacement for Markdown.pl.+ .+ In contrast to existing tools for converting markdown+ to HTML, which use regex substitutions, pandoc has+ a modular design: it consists of a set of readers,+ which parse text in a given format and produce a native+ representation of the document, and a set of writers,+ which convert this native representation into a target+ format. Thus, adding an input or output format requires+ only adding a reader or writer.+Build-Depends: base, parsec, xhtml, mtl, regex-compat, network+Hs-Source-Dirs: .+Exposed-Modules: Text.Pandoc,+ Text.Pandoc.Blocks,+ Text.Pandoc.Definition,+ Text.Pandoc.CharacterReferences,+ Text.Pandoc.Shared,+ Text.Pandoc.UTF8,+ Text.Pandoc.ASCIIMathML,+ Text.Pandoc.Readers.HTML,+ Text.Pandoc.Readers.LaTeX,+ Text.Pandoc.Readers.Markdown,+ Text.Pandoc.Readers.RST,+ Text.Pandoc.Readers.TeXMath,+ Text.Pandoc.Writers.DefaultHeaders,+ Text.Pandoc.Writers.Docbook,+ Text.Pandoc.Writers.HTML,+ Text.Pandoc.Writers.LaTeX,+ Text.Pandoc.Writers.ConTeXt,+ Text.Pandoc.Writers.Man,+ Text.Pandoc.Writers.Markdown,+ Text.Pandoc.Writers.RST,+ Text.Pandoc.Writers.RTF,+ Text.Pandoc.Writers.S5+Ghc-Options: -O0++Executable: pandoc+Hs-Source-Dirs: .+Main-Is: Main.hs+Ghc-Options: -O0
− src/ASCIIMathML.js
@@ -1,945 +0,0 @@-/*-ASCIIMathML.js-==============-This file contains JavaScript functions to convert ASCII math notation-to Presentation MathML. The conversion is done while the (X)HTML page -loads, and should work with Firefox/Mozilla/Netscape 7+ and Internet -Explorer 6+MathPlayer (http://www.dessci.com/en/products/mathplayer/).-Just add the next line to your (X)HTML page with this file in the same folder:-<script type="text/javascript" src="ASCIIMathML.js"></script>-This is a convenient and inexpensive solution for authoring MathML.--Version 1.4.7 Dec 15, 2005, (c) Peter Jipsen http://www.chapman.edu/~jipsen-Latest version at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML.js-For changes see http://www.chapman.edu/~jipsen/mathml/asciimathchanges.txt-If you use it on a webpage, please send the URL to jipsen@chapman.edu--Modified July 2006 by John MacFarlane (added CODE to list of contexts-in which replacement does not occur, modified AMisMathMLAvailable-to better identify Safari browser, changed mathcolor to "").--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 (at http://www.gnu.org/copyleft/gpl.html) -for more details.-*/--var checkForMathML = true; // check if browser can display MathML-var notifyIfNoMathML = true; // display note if no MathML capability-var alertIfNoMathML = false; // show alert box if no MathML capability-var mathcolor = ""; // change it to "" (to inherit) or any other color-var mathfontfamily = "serif"; // change to "" to inherit (works in IE) - // or another family (e.g. "arial")-var displaystyle = true; // puts limits above and below large operators-var showasciiformulaonhover = true; // helps students learn ASCIIMath-var decimalsign = "."; // change to "," if you like, beware of `(1,2)`!-var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters-var AMdelimiter2 = "$", AMescape2 = "\\\\\\$", AMdelimiter2regexp = "\\$";-var doubleblankmathdelimiter = false; // if true, x+1 is equal to `x+1`- // for IE this works only in <!-- -->-//var separatetokens;// has been removed (email me if this is a problem)-var isIE = document.createElementNS==null;--if (document.getElementById==null) - alert("This webpage requires a recent browser such as\-\nMozilla/Netscape 7+ or Internet Explorer 6+MathPlayer")--// all further global variables start with "AM"--function AMcreateElementXHTML(t) {- if (isIE) return document.createElement(t);- else return document.createElementNS("http://www.w3.org/1999/xhtml",t);-}--function AMnoMathMLNote() {- var nd = AMcreateElementXHTML("h3");- nd.setAttribute("align","center")- nd.appendChild(AMcreateElementXHTML("p"));- nd.appendChild(document.createTextNode("To view the "));- var an = AMcreateElementXHTML("a");- an.appendChild(document.createTextNode("ASCIIMathML"));- an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html");- nd.appendChild(an);- nd.appendChild(document.createTextNode(" notation use Internet Explorer 6+")); - an = AMcreateElementXHTML("a");- an.appendChild(document.createTextNode("MathPlayer"));- an.setAttribute("href","http://www.dessci.com/en/products/mathplayer/download.htm");- nd.appendChild(an);- nd.appendChild(document.createTextNode(" or Netscape/Mozilla/Firefox"));- nd.appendChild(AMcreateElementXHTML("p"));- return nd;-}--function AMisMathMLavailable() {- var regex = /KHTML/; /* This line and the next two modified by JM for better Safari detection */- if (navigator.appName.slice(0,8)=="Netscape")- if (navigator.appVersion.slice(0,1)>="5" && !regex.test(navigator.userAgent)) return null;- else return AMnoMathMLNote();- else if (navigator.appName.slice(0,9)=="Microsoft")- try {- var ActiveX = new ActiveXObject("MathPlayer.Factory.1");- return null;- } catch (e) {- return AMnoMathMLNote();- }- else return AMnoMathMLNote();-}--// character lists for Mozilla/Netscape fonts-var AMcal = [0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];-var AMfrk = [0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];-var AMbbb = [0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];--var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4, - RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,- LEFTRIGHT = 9, TEXT = 10; // token types--var AMsqrt = {input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY},- AMroot = {input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY},- AMfrac = {input:"frac", tag:"mfrac", output:"/", tex:null, ttype:BINARY},- AMdiv = {input:"/", tag:"mfrac", output:"/", tex:null, ttype:INFIX},- AMover = {input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},- AMsub = {input:"_", tag:"msub", output:"_", tex:null, ttype:INFIX},- AMsup = {input:"^", tag:"msup", output:"^", tex:null, ttype:INFIX},- AMtext = {input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT},- AMmbox = {input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT},- AMquote = {input:"\"", tag:"mtext", output:"mbox", tex:null, ttype:TEXT};--var AMsymbols = [-//some greek symbols-{input:"alpha", tag:"mi", output:"\u03B1", tex:null, ttype:CONST},-{input:"beta", tag:"mi", output:"\u03B2", tex:null, ttype:CONST},-{input:"chi", tag:"mi", output:"\u03C7", tex:null, ttype:CONST},-{input:"delta", tag:"mi", output:"\u03B4", tex:null, ttype:CONST},-{input:"Delta", tag:"mo", output:"\u0394", tex:null, ttype:CONST},-{input:"epsi", tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST},-{input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST},-{input:"eta", tag:"mi", output:"\u03B7", tex:null, ttype:CONST},-{input:"gamma", tag:"mi", output:"\u03B3", tex:null, ttype:CONST},-{input:"Gamma", tag:"mo", output:"\u0393", tex:null, ttype:CONST},-{input:"iota", tag:"mi", output:"\u03B9", tex:null, ttype:CONST},-{input:"kappa", tag:"mi", output:"\u03BA", tex:null, ttype:CONST},-{input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},-{input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},-{input:"mu", tag:"mi", output:"\u03BC", tex:null, ttype:CONST},-{input:"nu", tag:"mi", output:"\u03BD", tex:null, ttype:CONST},-{input:"omega", tag:"mi", output:"\u03C9", tex:null, ttype:CONST},-{input:"Omega", tag:"mo", output:"\u03A9", tex:null, ttype:CONST},-{input:"phi", tag:"mi", output:"\u03C6", tex:null, ttype:CONST},-{input:"varphi", tag:"mi", output:"\u03D5", tex:null, ttype:CONST},-{input:"Phi", tag:"mo", output:"\u03A6", tex:null, ttype:CONST},-{input:"pi", tag:"mi", output:"\u03C0", tex:null, ttype:CONST},-{input:"Pi", tag:"mo", output:"\u03A0", tex:null, ttype:CONST},-{input:"psi", tag:"mi", output:"\u03C8", tex:null, ttype:CONST},-{input:"Psi", tag:"mi", output:"\u03A8", tex:null, ttype:CONST},-{input:"rho", tag:"mi", output:"\u03C1", tex:null, ttype:CONST},-{input:"sigma", tag:"mi", output:"\u03C3", tex:null, ttype:CONST},-{input:"Sigma", tag:"mo", output:"\u03A3", tex:null, ttype:CONST},-{input:"tau", tag:"mi", output:"\u03C4", tex:null, ttype:CONST},-{input:"theta", tag:"mi", output:"\u03B8", tex:null, ttype:CONST},-{input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST},-{input:"Theta", tag:"mo", output:"\u0398", tex:null, ttype:CONST},-{input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST},-{input:"xi", tag:"mi", output:"\u03BE", tex:null, ttype:CONST},-{input:"Xi", tag:"mo", output:"\u039E", tex:null, ttype:CONST},-{input:"zeta", tag:"mi", output:"\u03B6", tex:null, ttype:CONST},--//binary operation symbols-{input:"*", tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST},-{input:"**", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST},-{input:"//", tag:"mo", output:"/", tex:null, ttype:CONST},-{input:"\\\\", tag:"mo", output:"\\", tex:"backslash", ttype:CONST},-{input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST},-{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST},-{input:"-:", tag:"mo", output:"\u00F7", tex:"divide", ttype:CONST},-{input:"@", tag:"mo", output:"\u2218", tex:"circ", ttype:CONST},-{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST},-{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST},-{input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST},-{input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER},-{input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER},-{input:"^^", tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST},-{input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER},-{input:"vv", tag:"mo", output:"\u2228", tex:"vee", ttype:CONST},-{input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER},-{input:"nn", tag:"mo", output:"\u2229", tex:"cap", ttype:CONST},-{input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER},-{input:"uu", tag:"mo", output:"\u222A", tex:"cup", ttype:CONST},-{input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER},--//binary relation symbols-{input:"!=", tag:"mo", output:"\u2260", tex:"ne", ttype:CONST},-{input:":=", tag:"mo", output:":=", tex:null, ttype:CONST},-{input:"lt", tag:"mo", output:"<", tex:null, ttype:CONST},-{input:"<=", tag:"mo", output:"\u2264", tex:"le", ttype:CONST},-{input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST},-{input:">=", tag:"mo", output:"\u2265", tex:"ge", ttype:CONST},-{input:"geq", tag:"mo", output:"\u2265", tex:null, ttype:CONST},-{input:"-<", tag:"mo", output:"\u227A", tex:"prec", ttype:CONST},-{input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST},-{input:">-", tag:"mo", output:"\u227B", tex:"succ", ttype:CONST},-{input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST},-{input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST},-{input:"in", tag:"mo", output:"\u2208", tex:null, ttype:CONST},-{input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST},-{input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST},-{input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST},-{input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST},-{input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST},-{input:"-=", tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST},-{input:"~=", tag:"mo", output:"\u2245", tex:"cong", ttype:CONST},-{input:"~~", tag:"mo", output:"\u2248", tex:"approx", ttype:CONST},-{input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST},--//logical symbols-{input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE},-{input:"or", tag:"mtext", output:"or", tex:null, ttype:SPACE},-{input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST},-{input:"=>", tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST},-{input:"if", tag:"mo", output:"if", tex:null, ttype:SPACE},-{input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST},-{input:"AA", tag:"mo", output:"\u2200", tex:"forall", ttype:CONST},-{input:"EE", tag:"mo", output:"\u2203", tex:"exists", ttype:CONST},-{input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST},-{input:"TT", tag:"mo", output:"\u22A4", tex:"top", ttype:CONST},-{input:"|--", tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST},-{input:"|==", tag:"mo", output:"\u22A8", tex:"models", ttype:CONST},--//grouping brackets-{input:"(", tag:"mo", output:"(", tex:null, ttype:LEFTBRACKET},-{input:")", tag:"mo", output:")", tex:null, ttype:RIGHTBRACKET},-{input:"[", tag:"mo", output:"[", tex:null, ttype:LEFTBRACKET},-{input:"]", tag:"mo", output:"]", tex:null, ttype:RIGHTBRACKET},-{input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET},-{input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET},-{input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT},-//{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},-{input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET},-{input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET},-{input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET},-{input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET},-{input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true},-{input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true},--//miscellaneous symbols-{input:"int", tag:"mo", output:"\u222B", tex:null, ttype:CONST},-{input:"dx", tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION},-{input:"dy", tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION},-{input:"dz", tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION},-{input:"dt", tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION},-{input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST},-{input:"del", tag:"mo", output:"\u2202", tex:"partial", ttype:CONST},-{input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST},-{input:"+-", tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST},-{input:"O/", tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST},-{input:"oo", tag:"mo", output:"\u221E", tex:"infty", ttype:CONST},-{input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST},-{input:"...", tag:"mo", output:"...", tex:"ldots", ttype:CONST},-{input:":.", tag:"mo", output:"\u2234", tex:"therefore", ttype:CONST},-{input:"/_", tag:"mo", output:"\u2220", tex:"angle", ttype:CONST},-{input:"\\ ", tag:"mo", output:"\u00A0", tex:null, ttype:CONST},-{input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST},-{input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST},-{input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST},-{input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST},-{input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST},-{input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST},-{input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST},-{input:"|__", tag:"mo", output:"\u230A", tex:"lfloor", ttype:CONST},-{input:"__|", tag:"mo", output:"\u230B", tex:"rfloor", ttype:CONST},-{input:"|~", tag:"mo", output:"\u2308", tex:"lceiling", ttype:CONST},-{input:"~|", tag:"mo", output:"\u2309", tex:"rceiling", ttype:CONST},-{input:"CC", tag:"mo", output:"\u2102", tex:null, ttype:CONST},-{input:"NN", tag:"mo", output:"\u2115", tex:null, ttype:CONST},-{input:"QQ", tag:"mo", output:"\u211A", tex:null, ttype:CONST},-{input:"RR", tag:"mo", output:"\u211D", tex:null, ttype:CONST},-{input:"ZZ", tag:"mo", output:"\u2124", tex:null, ttype:CONST},-{input:"f", tag:"mi", output:"f", tex:null, ttype:UNARY, func:true},-{input:"g", tag:"mi", output:"g", tex:null, ttype:UNARY, func:true},--//standard functions-{input:"lim", tag:"mo", output:"lim", tex:null, ttype:UNDEROVER},-{input:"Lim", tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER},-{input:"sin", tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true},-{input:"cos", tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true},-{input:"tan", tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true},-{input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true},-{input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true},-{input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true},-{input:"cot", tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true},-{input:"sec", tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true},-{input:"csc", tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true},-{input:"log", tag:"mo", output:"log", tex:null, ttype:UNARY, func:true},-{input:"ln", tag:"mo", output:"ln", tex:null, ttype:UNARY, func:true},-{input:"det", tag:"mo", output:"det", tex:null, ttype:UNARY, func:true},-{input:"dim", tag:"mo", output:"dim", tex:null, ttype:CONST},-{input:"mod", tag:"mo", output:"mod", tex:null, ttype:CONST},-{input:"gcd", tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true},-{input:"lcm", tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true},-{input:"lub", tag:"mo", output:"lub", tex:null, ttype:CONST},-{input:"glb", tag:"mo", output:"glb", tex:null, ttype:CONST},-{input:"min", tag:"mo", output:"min", tex:null, ttype:UNDEROVER},-{input:"max", tag:"mo", output:"max", tex:null, ttype:UNDEROVER},--//arrows-{input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST},-{input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST},-{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST},-{input:"->", tag:"mo", output:"\u2192", tex:"to", ttype:CONST},-{input:"|->", tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST},-{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST},-{input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST},-{input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST},-{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST},-{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST},--//commands with argument-AMsqrt, AMroot, AMfrac, AMdiv, AMover, AMsub, AMsup,-{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true},-{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true},-{input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true},-{input:"dot", tag:"mover", output:".", tex:null, ttype:UNARY, acc:true},-{input:"ddot", tag:"mover", output:"..", tex:null, ttype:UNARY, acc:true},-{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true},-AMtext, AMmbox, AMquote,-{input:"bb", tag:"mstyle", atname:"fontweight", atval:"bold", output:"bb", tex:null, ttype:UNARY},-{input:"mathbf", tag:"mstyle", atname:"fontweight", atval:"bold", output:"mathbf", tex:null, ttype:UNARY},-{input:"sf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY},-{input:"mathsf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY},-{input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb},-{input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb},-{input:"cc", tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal},-{input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal},-{input:"tt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"tt", tex:null, ttype:UNARY},-{input:"mathtt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY},-{input:"fr", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk},-{input:"mathfrak", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk}-];--function compareNames(s1,s2) {- if (s1.input > s2.input) return 1- else return -1;-}--var AMnames = []; //list of input symbols--function AMinitSymbols() {- var texsymbols = [], i;- for (i=0; i<AMsymbols.length; i++)- if (AMsymbols[i].tex) - texsymbols[texsymbols.length] = {input:AMsymbols[i].tex, - tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype};- AMsymbols = AMsymbols.concat(texsymbols);- AMsymbols.sort(compareNames);- for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;-}--var AMmathml = "http://www.w3.org/1998/Math/MathML";--function AMcreateElementMathML(t) {- if (isIE) return document.createElement("m:"+t);- else return document.createElementNS(AMmathml,t);-}--function AMcreateMmlNode(t,frag) {-// var node = AMcreateElementMathML(name);- if (isIE) var node = document.createElement("m:"+t);- else var node = document.createElementNS(AMmathml,t);- node.appendChild(frag);- return node;-}--function newcommand(oldstr,newstr) {- AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr, - tex:null, ttype:DEFINITION}]);-}--function AMremoveCharsAndBlanks(str,n) {-//remove n characters and any following blanks- var st;- if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ") - st = str.slice(n+1);- else st = str.slice(n);- for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);- return st.slice(i);-}--function AMposition(arr, str, n) { -// return position >=n where str appears or would be inserted-// assumes arr is sorted- if (n==0) {- var h,m;- n = -1;- h = arr.length;- while (n+1<h) {- m = (n+h) >> 1;- if (arr[m]<str) n = m; else h = m;- }- return h;- } else- for (var i=n; i<arr.length && arr[i]<str; i++);- return i; // i=arr.length || arr[i]>=str-}--function AMgetSymbol(str) {-//return maximal initial substring of str that appears in names-//return null if there is none- var k = 0; //new pos- var j = 0; //old pos- var mk; //match pos- var st;- var tagst;- var match = "";- var more = true;- for (var i=1; i<=str.length && more; i++) {- st = str.slice(0,i); //initial substring of length i- j = k;- k = AMposition(AMnames, st, j);- if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){- match = AMnames[k];- mk = k;- i = match.length;- }- more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];- }- AMpreviousSymbol=AMcurrentSymbol;- if (match!=""){- AMcurrentSymbol=AMsymbols[mk].ttype;- return AMsymbols[mk]; - }-// if str[0] is a digit or - return maxsubstring of digits.digits- AMcurrentSymbol=CONST;- k = 1;- st = str.slice(0,1);- var integ = true;- while ("0"<=st && st<="9" && k<=str.length) {- st = str.slice(k,k+1);- k++;- }- if (st == decimalsign) {- st = str.slice(k,k+1);- if ("0"<=st && st<="9") {- integ = false;- k++;- while ("0"<=st && st<="9" && k<=str.length) {- st = str.slice(k,k+1);- k++;- }- }- }- if ((integ && k>1) || k>2) {- st = str.slice(0,k-1);- tagst = "mn";- } else {- k = 2;- st = str.slice(0,1); //take 1 character- tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");- }- if (st=="-" && AMpreviousSymbol==INFIX) {- AMcurrentSymbol = INFIX; //trick "/" into recognizing "-" on second parse- return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};- }- return {input:st, tag:tagst, output:st, ttype:CONST};-}--function AMremoveBrackets(node) {- var st;- if (node.nodeName=="mrow") {- st = node.firstChild.firstChild.nodeValue;- if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild);- }- if (node.nodeName=="mrow") {- st = node.lastChild.firstChild.nodeValue;- if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild);- }-}--/*Parsing ASCII math expressions with the following grammar-v ::= [A-Za-z] | greek letters | numbers | other constant symbols-u ::= sqrt | text | bb | other unary symbols for font commands-b ::= frac | root | stackrel binary symbols-l ::= ( | [ | { | (: | {: left brackets-r ::= ) | ] | } | :) | :} right brackets-S ::= v | lEr | uS | bSS Simple expression-I ::= S_S | S^S | S_S^S | S Intermediate expression-E ::= IE | I/I Expression-Each terminal symbol is translated into a corresponding mathml node.*/--var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;--function AMparseSexpr(str) { //parses str and returns [node,tailstr]- var symbol, node, result, i, st,// rightvert = false,- newFrag = document.createDocumentFragment();- str = AMremoveCharsAndBlanks(str,0);- symbol = AMgetSymbol(str); //either a token or a bracket or empty- if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {- return [null,str];- }- if (symbol.ttype == DEFINITION) {- str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length); - symbol = AMgetSymbol(str);- }- switch (symbol.ttype) {- case UNDEROVER:- case CONST:- str = AMremoveCharsAndBlanks(str,symbol.input.length); - return [AMcreateMmlNode(symbol.tag, //its a constant- document.createTextNode(symbol.output)),str];- case LEFTBRACKET: //read (expr+)- AMnestingDepth++;- str = AMremoveCharsAndBlanks(str,symbol.input.length); - result = AMparseExpr(str,true);- AMnestingDepth--;- if (typeof symbol.invisible == "boolean" && symbol.invisible) - node = AMcreateMmlNode("mrow",result[0]);- else {- node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));- node = AMcreateMmlNode("mrow",node);- node.appendChild(result[0]);- }- return [node,result[1]];- case TEXT:- if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);- if (str.charAt(0)=="{") i=str.indexOf("}");- else if (str.charAt(0)=="(") i=str.indexOf(")");- else if (str.charAt(0)=="[") i=str.indexOf("]");- else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1;- else i = 0;- if (i==-1) i = str.length;- st = str.slice(1,i);- if (st.charAt(0) == " ") {- node = AMcreateElementMathML("mspace");- node.setAttribute("width","1ex");- newFrag.appendChild(node);- }- newFrag.appendChild(- AMcreateMmlNode(symbol.tag,document.createTextNode(st)));- if (st.charAt(st.length-1) == " ") {- node = AMcreateElementMathML("mspace");- node.setAttribute("width","1ex");- newFrag.appendChild(node);- }- str = AMremoveCharsAndBlanks(str,i+1);- return [AMcreateMmlNode("mrow",newFrag),str];- case UNARY:- str = AMremoveCharsAndBlanks(str,symbol.input.length); - result = AMparseSexpr(str);- if (result[0]==null) return [AMcreateMmlNode(symbol.tag,- document.createTextNode(symbol.output)),str];- if (typeof symbol.func == "boolean" && symbol.func) { // functions hack- st = str.charAt(0);- if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {- return [AMcreateMmlNode(symbol.tag,- document.createTextNode(symbol.output)),str];- } else {- node = AMcreateMmlNode("mrow",- AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));- node.appendChild(result[0]);- return [node,result[1]];- }- }- AMremoveBrackets(result[0]);- if (symbol.input == "sqrt") { // sqrt- return [AMcreateMmlNode(symbol.tag,result[0]),result[1]];- } else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent- node = AMcreateMmlNode(symbol.tag,result[0]);- node.appendChild(AMcreateMmlNode("mo",document.createTextNode(symbol.output)));- return [node,result[1]];- } else { // font change command- if (!isIE && typeof symbol.codes != "undefined") {- for (i=0; i<result[0].childNodes.length; i++)- if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {- st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:- result[0].childNodes[i].firstChild.nodeValue);- var newst = [];- for (var j=0; j<st.length; j++)- if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst +- String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);- else newst = newst + st.charAt(j);- if (result[0].nodeName=="mi")- result[0]=AMcreateElementMathML("mo").- appendChild(document.createTextNode(newst));- else result[0].replaceChild(AMcreateElementMathML("mo").- appendChild(document.createTextNode(newst)),result[0].childNodes[i]);- }- }- node = AMcreateMmlNode(symbol.tag,result[0]);- node.setAttribute(symbol.atname,symbol.atval);- return [node,result[1]];- }- case BINARY:- str = AMremoveCharsAndBlanks(str,symbol.input.length); - result = AMparseSexpr(str);- if (result[0]==null) return [AMcreateMmlNode("mo",- document.createTextNode(symbol.input)),str];- AMremoveBrackets(result[0]);- var result2 = AMparseSexpr(result[1]);- if (result2[0]==null) return [AMcreateMmlNode("mo",- document.createTextNode(symbol.input)),str];- AMremoveBrackets(result2[0]);- if (symbol.input=="root" || symbol.input=="stackrel") - newFrag.appendChild(result2[0]);- newFrag.appendChild(result[0]);- if (symbol.input=="frac") newFrag.appendChild(result2[0]);- return [AMcreateMmlNode(symbol.tag,newFrag),result2[1]];- case INFIX:- str = AMremoveCharsAndBlanks(str,symbol.input.length); - return [AMcreateMmlNode("mo",document.createTextNode(symbol.output)),str];- case SPACE:- str = AMremoveCharsAndBlanks(str,symbol.input.length); - node = AMcreateElementMathML("mspace");- node.setAttribute("width","1ex");- newFrag.appendChild(node);- newFrag.appendChild(- AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));- node = AMcreateElementMathML("mspace");- node.setAttribute("width","1ex");- newFrag.appendChild(node);- return [AMcreateMmlNode("mrow",newFrag),str];- case LEFTRIGHT:-// if (rightvert) return [null,str]; else rightvert = true;- AMnestingDepth++;- str = AMremoveCharsAndBlanks(str,symbol.input.length); - result = AMparseExpr(str,false);- AMnestingDepth--;- var st = "";- if (result[0].lastChild!=null)- st = result[0].lastChild.firstChild.nodeValue;- if (st == "|") { // its an absolute value subterm- node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));- node = AMcreateMmlNode("mrow",node);- node.appendChild(result[0]);- return [node,result[1]];- } else { // the "|" is a \mid- node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));- node = AMcreateMmlNode("mrow",node);- return [node,str];- }- default:-//alert("default");- str = AMremoveCharsAndBlanks(str,symbol.input.length); - return [AMcreateMmlNode(symbol.tag, //its a constant- document.createTextNode(symbol.output)),str];- }-}--function AMparseIexpr(str) {- var symbol, sym1, sym2, node, result, underover;- str = AMremoveCharsAndBlanks(str,0);- sym1 = AMgetSymbol(str);- result = AMparseSexpr(str);- node = result[0];- str = result[1];- symbol = AMgetSymbol(str);- if (symbol.ttype == INFIX && symbol.input != "/") {- str = AMremoveCharsAndBlanks(str,symbol.input.length);-// if (symbol.input == "/") result = AMparseIexpr(str); else ...- result = AMparseSexpr(str);- if (result[0] == null) // show box in place of missing argument- result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1"));- else AMremoveBrackets(result[0]);- str = result[1];-// if (symbol.input == "/") AMremoveBrackets(node);- if (symbol.input == "_") {- sym2 = AMgetSymbol(str);- underover = (sym1.ttype == UNDEROVER);- if (sym2.input == "^") {- str = AMremoveCharsAndBlanks(str,sym2.input.length);- var res2 = AMparseSexpr(str);- AMremoveBrackets(res2[0]);- str = res2[1];- node = AMcreateMmlNode((underover?"munderover":"msubsup"),node);- node.appendChild(result[0]);- node.appendChild(res2[0]);- node = AMcreateMmlNode("mrow",node); // so sum does not stretch- } else {- node = AMcreateMmlNode((underover?"munder":"msub"),node);- node.appendChild(result[0]);- }- } else {- node = AMcreateMmlNode(symbol.tag,node);- node.appendChild(result[0]);- }- }- return [node,str];-}--function AMparseExpr(str,rightbracket) {- var symbol, node, result, i, nodeList = [],- newFrag = document.createDocumentFragment();- do {- str = AMremoveCharsAndBlanks(str,0);- result = AMparseIexpr(str);- node = result[0];- str = result[1];- symbol = AMgetSymbol(str);- if (symbol.ttype == INFIX && symbol.input == "/") {- str = AMremoveCharsAndBlanks(str,symbol.input.length);- result = AMparseIexpr(str);- if (result[0] == null) // show box in place of missing argument- result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1"));- else AMremoveBrackets(result[0]);- str = result[1];- AMremoveBrackets(node);- node = AMcreateMmlNode(symbol.tag,node);- node.appendChild(result[0]);- newFrag.appendChild(node);- symbol = AMgetSymbol(str);- } - else if (node!=undefined) newFrag.appendChild(node);- } while ((symbol.ttype != RIGHTBRACKET && - (symbol.ttype != LEFTRIGHT || rightbracket)- || AMnestingDepth == 0) && symbol!=null && symbol.output!="");- if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {-// if (AMnestingDepth > 0) AMnestingDepth--;- var len = newFrag.childNodes.length;- if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&- newFrag.childNodes[len-2].nodeName == "mo" &&- newFrag.childNodes[len-2].firstChild.nodeValue == ",") { //matrix- var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;- if (right==")" || right=="]") {- var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;- if (left=="(" && right==")" && symbol.output != "}" || - left=="[" && right=="]") {- var pos = []; // positions of commas- var matrix = true;- var m = newFrag.childNodes.length;- for (i=0; matrix && i<m; i=i+2) {- pos[i] = [];- node = newFrag.childNodes[i];- if (matrix) matrix = node.nodeName=="mrow" && - (i==m-1 || node.nextSibling.nodeName=="mo" && - node.nextSibling.firstChild.nodeValue==",")&&- node.firstChild.firstChild.nodeValue==left &&- node.lastChild.firstChild.nodeValue==right;- if (matrix) - for (var j=0; j<node.childNodes.length; j++)- if (node.childNodes[j].firstChild.nodeValue==",")- pos[i][pos[i].length]=j;- if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;- }- if (matrix) {- var row, frag, n, k, table = document.createDocumentFragment();- for (i=0; i<m; i=i+2) {- row = document.createDocumentFragment();- frag = document.createDocumentFragment();- node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>- n = node.childNodes.length;- k = 0;- node.removeChild(node.firstChild); //remove (- for (j=1; j<n-1; j++) {- if (typeof pos[i][k] != "undefined" && j==pos[i][k]){- node.removeChild(node.firstChild); //remove ,- row.appendChild(AMcreateMmlNode("mtd",frag));- k++;- } else frag.appendChild(node.firstChild);- }- row.appendChild(AMcreateMmlNode("mtd",frag));- if (newFrag.childNodes.length>2) {- newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>- newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>- }- table.appendChild(AMcreateMmlNode("mtr",row));- }- node = AMcreateMmlNode("mtable",table);- if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left");- newFrag.replaceChild(node,newFrag.firstChild);- }- }- }- }- str = AMremoveCharsAndBlanks(str,symbol.input.length);- if (typeof symbol.invisible != "boolean" || !symbol.invisible) {- node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));- newFrag.appendChild(node);- }- }- return [newFrag,str];-}--function AMparseMath(str) {- var result, node = AMcreateElementMathML("mstyle");- if (mathcolor != "") node.setAttribute("mathcolor",mathcolor);- if (displaystyle) node.setAttribute("displaystyle","true");- if (mathfontfamily != "") node.setAttribute("fontfamily",mathfontfamily);- AMnestingDepth = 0;- node.appendChild(AMparseExpr(str.replace(/^\s+/g,""),false)[0]);- node = AMcreateMmlNode("math",node);- if (showasciiformulaonhover) //fixed by djhsu so newline- node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko- if (mathfontfamily != "" && (isIE || mathfontfamily != "serif")) {- var fnode = AMcreateElementXHTML("font");- fnode.setAttribute("face",mathfontfamily);- fnode.appendChild(node);- return fnode;- }- return node;-}--function AMstrarr2docFrag(arr, linebreaks) {- var newFrag=document.createDocumentFragment();- var expr = false;- for (var i=0; i<arr.length; i++) {- if (expr) newFrag.appendChild(AMparseMath(arr[i]));- else {- var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);- newFrag.appendChild(AMcreateElementXHTML("span").- appendChild(document.createTextNode(arri[0])));- for (var j=1; j<arri.length; j++) {- newFrag.appendChild(AMcreateElementXHTML("p"));- newFrag.appendChild(AMcreateElementXHTML("span").- appendChild(document.createTextNode(arri[j])));- }- }- expr = !expr;- }- return newFrag;-}--function AMprocessNodeR(n, linebreaks) {- var mtch, str, arr, frg, i;- if (n.childNodes.length == 0) {- if ((n.nodeType!=8 || linebreaks) &&- n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&- n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" &&- n.parentNode.nodeName!="code" && n.parentNode.nodeName!="CODE" && /* added by JM */- n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE") {- str = n.nodeValue;- if (!(str == null)) {- str = str.replace(/\r\n\r\n/g,"\n\n");- if (doubleblankmathdelimiter) {- str = str.replace(/\x20\x20\./g," "+AMdelimiter1+".");- str = str.replace(/\x20\x20,/g," "+AMdelimiter1+",");- str = str.replace(/\x20\x20/g," "+AMdelimiter1+" ");- }- str = str.replace(/\x20+/g," ");- str = str.replace(/\s*\r\n/g," ");- mtch = false;- str = str.replace(new RegExp(AMescape2, "g"),- function(st){mtch=true;return "AMescape2"});- str = str.replace(new RegExp(AMescape1, "g"),- function(st){mtch=true;return "AMescape1"});- str = str.replace(new RegExp(AMdelimiter2regexp, "g"),AMdelimiter1);- arr = str.split(AMdelimiter1);- for (i=0; i<arr.length; i++)- arr[i]=arr[i].replace(/AMescape2/g,AMdelimiter2).- replace(/AMescape1/g,AMdelimiter1);- if (arr.length>1 || mtch) {- if (checkForMathML) {- checkForMathML = false;- var nd = AMisMathMLavailable();- AMnoMathML = nd != null;- if (AMnoMathML && notifyIfNoMathML) - if (alertIfNoMathML)- alert("To view the ASCIIMathML notation use Internet Explorer 6 +\nMathPlayer (free from www.dessci.com)\n\- or Firefox/Mozilla/Netscape");- else AMbody.insertBefore(nd,AMbody.childNodes[0]);- }- if (!AMnoMathML) {- frg = AMstrarr2docFrag(arr,n.nodeType==8);- var len = frg.childNodes.length;- n.parentNode.replaceChild(frg,n);- return len-1;- } else return 0;- }- }- } else return 0;- } else if (n.nodeName!="math") {- for (i=0; i<n.childNodes.length; i++)- i += AMprocessNodeR(n.childNodes[i], linebreaks);- }- return 0;-}--function AMprocessNode(n, linebreaks, spanclassAM) {- var frag,st;- if (spanclassAM!=null) {- frag = document.getElementsByTagName("span")- for (var i=0;i<frag.length;i++)- if (frag[i].className == "AM")- AMprocessNodeR(frag[i],linebreaks);- } else {- try {- st = n.innerHTML;- } catch(err) {}- if (st==null || - st.indexOf(AMdelimiter1)!=-1 || st.indexOf(AMdelimiter2)!=-1) - AMprocessNodeR(n,linebreaks);- }- if (isIE) { //needed to match size and font of formula to surrounding text- frag = document.getElementsByTagName('math');- for (var i=0;i<frag.length;i++) frag[i].update()- }-}--var AMbody;-var AMnoMathML = false, AMtranslated = false;--function translate(spanclassAM) {- if (!AMtranslated) { // run this only once- AMtranslated = true;- AMinitSymbols();- AMbody = document.getElementsByTagName("body")[0];- AMprocessNode(AMbody, false, spanclassAM);- }-}--if (isIE) { // avoid adding MathPlayer info explicitly to each webpage- document.write("<object id=\"mathplayer\"\- classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");- document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");-}--// GO1.1 Generic onload by Brothercake -// http://www.brothercake.com/-//onload function (replaces the onload="translate()" in the <body> tag)-function generic()-{- translate();-};-//setup onload function-if(typeof window.addEventListener != 'undefined')-{- //.. gecko, safari, konqueror and standard- window.addEventListener('load', generic, false);-}-else if(typeof document.addEventListener != 'undefined')-{- //.. opera 7- document.addEventListener('load', generic, false);-}-else if(typeof window.attachEvent != 'undefined')-{- //.. win/ie- window.attachEvent('onload', generic);-}-//** remove this condition to degrade older browsers-else-{- //.. mac/ie5 and anything else that gets this far- //if there's an existing onload function- if(typeof window.onload == 'function')- {- //store it- var existing = onload;- //add new onload handler- window.onload = function()- {- //call existing onload function- existing();- //call generic onload function- generic();- };- }- else- {- //setup onload function- window.onload = generic;- }-}
− src/Main.hs
@@ -1,505 +0,0 @@-{--Copyright (C) 2006-7 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 : Main- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley@edu>- Stability : alpha - Portability : portable--Parses command-line options and calls the appropriate readers and-writers.--}-module Main where-import Text.Pandoc-import Text.Pandoc.UTF8-import Text.Pandoc.Shared ( joinWithSep )-import Text.Regex ( mkRegex, matchRegex )-import System.Environment ( getArgs, getProgName, getEnvironment )-import System.Exit ( exitWith, ExitCode (..) )-import System.Console.GetOpt-import System.IO-import Data.Maybe ( fromMaybe )-import Data.List ( isPrefixOf )-import Data.Char ( toLower )-import Control.Monad ( (>>=) )--version :: String-version = "0.44"--copyrightMessage :: String-copyrightMessage = "\nCopyright (C) 2006-7 John MacFarlane\n\- \Web: http://sophos.berkeley.edu/macfarlane/pandoc\n\- \This is free software; see the source for copying conditions. There is no\n\- \warranty, not even for merchantability or fitness for a particular purpose."---- | Association list of formats and readers.-readers :: [(String, ParserState -> String -> Pandoc)]-readers = [("native" , readPandoc)- ,("markdown" , readMarkdown)- ,("rst" , readRST)- ,("html" , readHtml)- ,("latex" , readLaTeX)- ]---- | Reader for native Pandoc format.-readPandoc :: ParserState -> String -> Pandoc-readPandoc state input = read input- --- | Association list of formats and pairs of writers and default headers.-writers :: [ ( String, ( WriterOptions -> Pandoc -> String, String ) ) ]-writers = [("native" , (writeDoc, ""))- ,("html" , (writeHtmlString, ""))- ,("s5" , (writeS5String, defaultS5Header))- ,("docbook" , (writeDocbook, defaultDocbookHeader))- ,("latex" , (writeLaTeX, defaultLaTeXHeader))- ,("context" , (writeConTeXt, defaultConTeXtHeader))- ,("man" , (writeMan, ""))- ,("markdown" , (writeMarkdown, ""))- ,("rst" , (writeRST, ""))- ,("rtf" , (writeRTF, defaultRTFHeader))- ]---- | Writer for Pandoc native format.-writeDoc :: WriterOptions -> Pandoc -> String-writeDoc options = prettyPandoc ---- | Data structure for command line options.-data Opt = Opt- { optPreserveTabs :: Bool -- ^ Convert tabs to spaces- , optTabStop :: Int -- ^ Number of spaces per tab- , optStandalone :: Bool -- ^ Include header, footer- , optReader :: String -- ^ Reader format- , optWriter :: String -- ^ Writer format- , optParseRaw :: Bool -- ^ Parse unconvertable HTML and TeX- , optCSS :: String -- ^ CSS file to link to- , optTableOfContents :: Bool -- ^ Include table of contents- , optIncludeInHeader :: String -- ^ File to include in header- , optIncludeBeforeBody :: String -- ^ File to include at top of body- , optIncludeAfterBody :: String -- ^ File to include at end of body- , optCustomHeader :: String -- ^ Custom header to use, or "DEFAULT"- , optTitlePrefix :: String -- ^ Optional prefix for HTML title- , optOutputFile :: String -- ^ Name of output file- , optNumberSections :: Bool -- ^ Number sections in LaTeX- , optIncremental :: Bool -- ^ Use incremental lists in S5- , optSmart :: Bool -- ^ Use smart typography- , optUseASCIIMathML :: Bool -- ^ Use ASCIIMathML- , optASCIIMathMLURL :: Maybe String -- ^ URL to ASCIIMathML.js- , optDumpArgs :: Bool -- ^ Output command-line arguments- , optIgnoreArgs :: Bool -- ^ Ignore command-line arguments- , optStrict :: Bool -- ^ Use strict markdown syntax- , optReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst- }---- | Defaults for command-line options.-defaultOpts :: Opt-defaultOpts = Opt- { optPreserveTabs = False- , optTabStop = 4- , optStandalone = False- , optReader = "" -- null for default reader- , optWriter = "" -- null for default writer- , optParseRaw = False- , optCSS = ""- , optTableOfContents = False- , optIncludeInHeader = ""- , optIncludeBeforeBody = ""- , optIncludeAfterBody = ""- , optCustomHeader = "DEFAULT"- , optTitlePrefix = ""- , optOutputFile = "-" -- "-" means stdout- , optNumberSections = False- , optIncremental = False- , optSmart = False- , optUseASCIIMathML = False- , optASCIIMathMLURL = Nothing- , optDumpArgs = False- , optIgnoreArgs = False- , optStrict = False- , optReferenceLinks = False- }---- | A list of functions, each transforming the options data structure--- in response to a command-line option.-options :: [OptDescr (Opt -> IO Opt)]-options =- [ Option "fr" ["from","read"]- (ReqArg- (\arg opt -> return opt { optReader = map toLower arg })- "FORMAT")- "" -- ("(" ++ (joinWithSep ", " $ map fst readers) ++ ")")-- , Option "tw" ["to","write"]- (ReqArg- (\arg opt -> return opt { optWriter = map toLower arg })- "FORMAT")- "" -- ("(" ++ (joinWithSep ", " $ map fst writers) ++ ")")- - , Option "s" ["standalone"]- (NoArg- (\opt -> return opt { optStandalone = True }))- "" -- "Include needed header and footer on output"-- , Option "o" ["output"]- (ReqArg- (\arg opt -> return opt { optOutputFile = arg })- "FILENAME")- "" -- "Name of output file"-- , Option "p" ["preserve-tabs"]- (NoArg- (\opt -> return opt { optPreserveTabs = True }))- "" -- "Preserve tabs instead of converting to spaces"-- , Option "" ["tab-stop"]- (ReqArg- (\arg opt -> return opt { optTabStop = (read arg) } )- "TABSTOP")- "" -- "Tab stop (default 4)"-- , Option "" ["strict"]- (NoArg- (\opt -> return opt { optStrict = True } ))- "" -- "Disable markdown syntax extensions"-- , Option "" ["reference-links"]- (NoArg- (\opt -> return opt { optReferenceLinks = True } ))- "" -- "Use reference links in parsing HTML"-- , Option "R" ["parse-raw"]- (NoArg- (\opt -> return opt { optParseRaw = True }))- "" -- "Parse untranslatable HTML codes and LaTeX environments as raw"-- , Option "S" ["smart"]- (NoArg- (\opt -> return opt { optSmart = True }))- "" -- "Use smart quotes, dashes, and ellipses"-- , Option "m" ["asciimathml"]- (OptArg- (\arg opt -> return opt { optUseASCIIMathML = True,- optASCIIMathMLURL = arg, - optStandalone = True })- "URL")- "" -- "Use ASCIIMathML script in html output"-- , Option "i" ["incremental"]- (NoArg- (\opt -> return opt { optIncremental = True }))- "" -- "Make list items display incrementally in S5"-- , Option "N" ["number-sections"]- (NoArg- (\opt -> return opt { optNumberSections = True }))- "" -- "Number sections in LaTeX"-- , Option "" ["toc", "table-of-contents"]- (NoArg- (\opt -> return opt { optTableOfContents = True }))- "" -- "Include table of contents" -- , Option "c" ["css"]- (ReqArg- (\arg opt -> return opt { optCSS = arg, - optStandalone = True })- "CSS")- "" -- "Link to CSS style sheet"-- , Option "H" ["include-in-header"]- (ReqArg- (\arg opt -> do- text <- readFile arg- return opt { optIncludeInHeader = fromUTF8 text, - optStandalone = True })- "FILENAME")- "" -- "File to include at end of header (implies -s)"-- , Option "B" ["include-before-body"]- (ReqArg- (\arg opt -> do- text <- readFile arg- return opt { optIncludeBeforeBody = fromUTF8 text })- "FILENAME")- "" -- "File to include before document body"-- , Option "A" ["include-after-body"]- (ReqArg- (\arg opt -> do- text <- readFile arg- return opt { optIncludeAfterBody = fromUTF8 text })- "FILENAME")- "" -- "File to include after document body"-- , Option "C" ["custom-header"]- (ReqArg- (\arg opt -> do- text <- readFile arg- return opt { optCustomHeader = fromUTF8 text, - optStandalone = True })- "FILENAME")- "" -- "File to use for custom header (implies -s)"-- , Option "T" ["title-prefix"]- (ReqArg- (\arg opt -> return opt { optTitlePrefix = arg, - optStandalone = True })- "STRING")- "" -- "String to prefix to HTML window title"- - , Option "D" ["print-default-header"]- (ReqArg- (\arg opt -> do- let header = case (lookup arg writers) of- Just (writer, head) -> head- Nothing -> error ("Unknown reader: " ++ arg) - hPutStr stdout header- exitWith ExitSuccess)- "FORMAT")- "" -- "Print default header for FORMAT"-- , Option "" ["dump-args"]- (NoArg- (\opt -> return opt { optDumpArgs = True }))- "" -- "Print output filename and arguments to stdout."-- , Option "" ["ignore-args"]- (NoArg- (\opt -> return opt { optIgnoreArgs = True }))- "" -- "Ignore command-line arguments."- - , Option "v" ["version"]- (NoArg- (\_ -> do- prg <- getProgName- hPutStrLn stderr (prg ++ " " ++ version ++ - copyrightMessage)- exitWith $ ExitFailure 4))- "" -- "Print version"-- , Option "h" ["help"]- (NoArg- (\_ -> do- prg <- getProgName- hPutStr stderr (usageMessage prg options)- exitWith $ ExitFailure 2))- "" -- "Show help"- ]---- Returns usage message-usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String-usageMessage programName options = usageInfo - (programName ++ " [OPTIONS] [FILES]" ++ "\nInput formats: " ++ - (joinWithSep ", " $ map fst readers) ++ "\nOutput formats: " ++ - (joinWithSep ", " $ map fst writers) ++ "\nOptions:")- options- --- Determine default reader based on source file extensions-defaultReaderName :: [String] -> String-defaultReaderName [] = "markdown"-defaultReaderName (x:xs) = - let x' = map toLower x in- case (matchRegex (mkRegex ".*\\.(.*)") x') of- Nothing -> defaultReaderName xs -- no extension- Just ["xhtml"] -> "html"- Just ["html"] -> "html"- Just ["htm"] -> "html"- Just ["tex"] -> "latex"- Just ["latex"] -> "latex"- Just ["ltx"] -> "latex"- Just ["rst"] -> "rst"- Just ["native"] -> "native"- Just _ -> "markdown"---- Determine default writer based on output file extension-defaultWriterName :: String -> String-defaultWriterName "-" = "html" -- no output file-defaultWriterName x =- let x' = map toLower x in- case (matchRegex (mkRegex ".*\\.(.*)") x') of- Nothing -> "markdown" -- no extension- Just [""] -> "markdown" -- empty extension - Just ["tex"] -> "latex"- Just ["latex"] -> "latex"- Just ["ltx"] -> "latex"- Just ["context"] -> "context"- Just ["ctx"] -> "context"- Just ["rtf"] -> "rtf"- Just ["rst"] -> "rst"- Just ["s5"] -> "s5"- Just ["native"] -> "native"- Just ["txt"] -> "markdown"- Just ["text"] -> "markdown"- Just ["md"] -> "markdown"- Just ["markdown"] -> "markdown"- Just ["db"] -> "docbook"- Just ["xml"] -> "docbook"- Just ["sgml"] -> "docbook"- Just [[x]] | x `elem` ['1'..'9'] -> "man"- Just _ -> "html"--main = do-- rawArgs <- getArgs- prg <- getProgName- let compatMode = (prg == "hsmarkdown")-- let (actions, args, errors) = if compatMode- then ([], rawArgs, [])- else getOpt Permute options rawArgs-- if (not (null errors))- then do- name <- getProgName- mapM (\e -> hPutStrLn stderr e) errors- hPutStr stderr (usageMessage name options)- exitWith $ ExitFailure 2- else- return ()-- let defaultOpts' = if compatMode - then defaultOpts { optReader = "markdown"- , optWriter = "html"- , optStrict = True }- else defaultOpts-- -- thread option data structure through all supplied option actions- opts <- foldl (>>=) (return defaultOpts') actions-- let Opt { optPreserveTabs = preserveTabs- , optTabStop = tabStop- , optStandalone = standalone- , optReader = readerName- , optWriter = writerName- , optParseRaw = parseRaw- , optCSS = css- , optTableOfContents = toc- , optIncludeInHeader = includeHeader- , optIncludeBeforeBody = includeBefore- , optIncludeAfterBody = includeAfter- , optCustomHeader = customHeader- , optTitlePrefix = titlePrefix- , optOutputFile = outputFile- , optNumberSections = numberSections- , optIncremental = incremental- , optSmart = smart- , optUseASCIIMathML = useAsciiMathML- , optASCIIMathMLURL = asciiMathMLURL- , optDumpArgs = dumpArgs- , optIgnoreArgs = ignoreArgs- , optStrict = strict- , optReferenceLinks = referenceLinks- } = opts-- if dumpArgs- then do- hPutStrLn stdout outputFile- mapM (\arg -> hPutStrLn stdout arg) args- exitWith $ ExitSuccess- else return ()-- let sources = if ignoreArgs then [] else args-- -- assign reader and writer based on options and filenames- let readerName' = if null readerName - then defaultReaderName sources- else readerName-- let writerName' = if null writerName - then defaultWriterName outputFile- else writerName-- reader <- case (lookup readerName' readers) of- Just r -> return r- Nothing -> error ("Unknown reader: " ++ readerName')-- (writer, defaultHeader) <- case (lookup writerName' writers) of- Just (w,h) -> return (w, h)- Nothing -> error ("Unknown writer: " ++ writerName')-- output <- if (outputFile == "-")- then return stdout - else openFile outputFile WriteMode-- environment <- getEnvironment- let columns = case lookup "COLUMNS" environment of- Just cols -> read cols- Nothing -> stateColumns defaultParserState-- let tabFilter _ [] = ""- tabFilter _ ('\n':xs) = '\n':(tabFilter tabStop xs)- tabFilter _ ('\r':'\n':xs) = '\n':(tabFilter tabStop xs)- -- remove DOS line endings- tabFilter spsToNextStop ('\t':xs) = - if preserveTabs- then '\t':(tabFilter tabStop xs) - else replicate spsToNextStop ' ' ++ tabFilter tabStop xs - tabFilter 1 (x:xs) = - x:(tabFilter tabStop xs)- tabFilter spsToNextStop (x:xs) = - x:(tabFilter (spsToNextStop - 1) xs)-- let startParserState = - defaultParserState { stateParseRaw = parseRaw,- stateTabStop = tabStop, - stateStandalone = standalone && (not strict),- stateSmart = smart || writerName' `elem` - ["latex", "context"],- stateColumns = columns,- stateStrict = strict }- let csslink = if (css == "")- then "" - else "<link rel=\"stylesheet\" href=\"" ++ css ++ - "\" type=\"text/css\" media=\"all\" />\n"- let header = (if (customHeader == "DEFAULT") - then defaultHeader- else customHeader) ++ csslink ++ includeHeader- let writerOptions = WriterOptions { writerStandalone = standalone &&- (not strict), - writerHeader = header, - writerTitlePrefix = titlePrefix,- writerTabStop = tabStop, - writerTableOfContents = toc &&- (not strict) &&- writerName/="s5",- writerUseASCIIMathML = useAsciiMathML,- writerASCIIMathMLURL = asciiMathMLURL,- writerS5 = (writerName=="s5"),- writerIgnoreNotes = False,- writerIncremental = incremental, - writerNumberSections = numberSections,- writerIncludeBefore = includeBefore, - writerIncludeAfter = includeAfter,- writerStrictMarkdown = strict,- writerReferenceLinks = referenceLinks }-- (readSources sources) >>= (hPutStrLn output . toUTF8 . - (writer writerOptions) . - (reader startParserState) . tabFilter tabStop .- fromUTF8 . (joinWithSep "\n")) >> - hClose output-- where - readSources [] = mapM readSource ["-"]- readSources sources = mapM readSource sources- readSource "-" = getContents- readSource source = readFile source
− src/Text/Pandoc.hs
@@ -1,105 +0,0 @@-{--Copyright (C) 2006-7 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- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha - Portability : portable--This helper module exports the main writers, readers, and data-structure definitions from the Pandoc libraries.--A typical application will chain together a reader and a writer-to convert strings from one format to another. For example, the-following simple program will act as a filter converting markdown-fragments to reStructuredText, using reference-style links instead of-inline links:--> module Main where-> import Text.Pandoc-> -> markdownToRST :: String -> String-> markdownToRST = toUTF8 .-> (writeRST defaultWriterOptions {writerReferenceLinks = True}) .-> (readMarkdown defaultParserState) . fromUTF8-> -> main = interact markdownToRST---}--module Text.Pandoc- ( - -- * Definitions- module Text.Pandoc.Definition- -- * Readers: converting /to/ Pandoc format- , readMarkdown- , readRST- , readLaTeX- , readHtml- -- * Parser state used in readers- , ParserState (..)- , defaultParserState- , ParserContext (..)- , QuoteContext (..)- , KeyTable- , NoteTable- , HeaderType (..)- -- * Writers: converting /from/ Pandoc format- , writeMarkdown- , writeRST- , writeLaTeX- , writeConTeXt- , writeHtml- , writeHtmlString- , writeS5- , writeS5String- , writeDocbook- , writeMan- , writeRTF- , prettyPandoc- -- * Writer options used in writers - , WriterOptions (..)- , defaultWriterOptions- -- * Default headers for various output formats- , module Text.Pandoc.Writers.DefaultHeaders- -- * Functions for converting to and from UTF-8- , module Text.Pandoc.UTF8- ) where--import Text.Pandoc.Definition-import Text.Pandoc.Readers.Markdown-import Text.Pandoc.Readers.RST-import Text.Pandoc.Readers.LaTeX-import Text.Pandoc.Readers.HTML-import Text.Pandoc.Writers.Markdown-import Text.Pandoc.Writers.RST -import Text.Pandoc.Writers.LaTeX-import Text.Pandoc.Writers.ConTeXt-import Text.Pandoc.Writers.HTML-import Text.Pandoc.Writers.S5-import Text.Pandoc.Writers.Docbook-import Text.Pandoc.Writers.Man-import Text.Pandoc.Writers.RTF -import Text.Pandoc.Writers.DefaultHeaders-import Text.Pandoc.UTF8-import Text.Pandoc.Shared-
− src/Text/Pandoc/ASCIIMathML.hs
@@ -1,14 +0,0 @@-------------------------------------------------------- Do not edit this file by hand. Edit --- 'templates/ASCIIMathML.hs'--- and run ./fillTemplates.pl Text/Pandoc/ASCIIMathML.hs--------------------------------------------------------- | Definitions for use of ASCIIMathML in HTML. --- (See <http://www1.chapman.edu/~jipsen/mathml/asciimath.html>.)-module Text.Pandoc.ASCIIMathML ( asciiMathMLScript ) where---- | String containing ASCIIMathML javascript.-asciiMathMLScript :: String-asciiMathMLScript = "<script type=\"text/javascript\">\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n\nvar checkForMathML = true; // check if browser can display MathML\nvar notifyIfNoMathML = true; // display note if no MathML capability\nvar alertIfNoMathML = false; // show alert box if no MathML capability\nvar mathcolor = \"\"; // change it to \"\" (to inherit) or any other color\nvar mathfontfamily = \"serif\"; // change to \"\" to inherit (works in IE) \n // or another family (e.g. \"arial\")\nvar displaystyle = true; // puts limits above and below large operators\nvar showasciiformulaonhover = true; // helps students learn ASCIIMath\nvar decimalsign = \".\"; // change to \",\" if you like, beware of `(1,2)`!\nvar AMdelimiter1 = \"`\", AMescape1 = \"\\\\\\\\`\"; // can use other characters\nvar AMdelimiter2 = \"$\", AMescape2 = \"\\\\\\\\\\\\$\", AMdelimiter2regexp = \"\\\\$\";\nvar doubleblankmathdelimiter = false; // if true, x+1 is equal to `x+1`\n // for IE this works only in <!-- -->\n//var separatetokens;// has been removed (email me if this is a problem)\nvar isIE = document.createElementNS==null;\n\nif (document.getElementById==null) \n alert(\"This webpage requires a recent browser such as\\\n\\nMozilla/Netscape 7+ or Internet Explorer 6+MathPlayer\")\n\n// all further global variables start with \"AM\"\n\nfunction AMcreateElementXHTML(t) {\n if (isIE) return document.createElement(t);\n else return document.createElementNS(\"http://www.w3.org/1999/xhtml\",t);\n}\n\nfunction AMnoMathMLNote() {\n var nd = AMcreateElementXHTML(\"h3\");\n nd.setAttribute(\"align\",\"center\")\n nd.appendChild(AMcreateElementXHTML(\"p\"));\n nd.appendChild(document.createTextNode(\"To view the \"));\n var an = AMcreateElementXHTML(\"a\");\n an.appendChild(document.createTextNode(\"ASCIIMathML\"));\n an.setAttribute(\"href\",\"http://www.chapman.edu/~jipsen/asciimath.html\");\n nd.appendChild(an);\n nd.appendChild(document.createTextNode(\" notation use Internet Explorer 6+\")); \n an = AMcreateElementXHTML(\"a\");\n an.appendChild(document.createTextNode(\"MathPlayer\"));\n an.setAttribute(\"href\",\"http://www.dessci.com/en/products/mathplayer/download.htm\");\n nd.appendChild(an);\n nd.appendChild(document.createTextNode(\" or Netscape/Mozilla/Firefox\"));\n nd.appendChild(AMcreateElementXHTML(\"p\"));\n return nd;\n}\n\nfunction AMisMathMLavailable() {\n var regex = /KHTML/; /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n if (navigator.appName.slice(0,8)==\"Netscape\")\n if (navigator.appVersion.slice(0,1)>=\"5\" && !regex.test(navigator.userAgent)) return null;\n else return AMnoMathMLNote();\n else if (navigator.appName.slice(0,9)==\"Microsoft\")\n try {\n var ActiveX = new ActiveXObject(\"MathPlayer.Factory.1\");\n return null;\n } catch (e) {\n return AMnoMathMLNote();\n }\n else return AMnoMathMLNote();\n}\n\n// character lists for Mozilla/Netscape fonts\nvar AMcal = [0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];\nvar AMfrk = [0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];\nvar AMbbb = [0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];\n\nvar CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4, \n RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,\n LEFTRIGHT = 9, TEXT = 10; // token types\n\nvar AMsqrt = {input:\"sqrt\", tag:\"msqrt\", output:\"sqrt\", tex:null, ttype:UNARY},\n AMroot = {input:\"root\", tag:\"mroot\", output:\"root\", tex:null, ttype:BINARY},\n AMfrac = {input:\"frac\", tag:\"mfrac\", output:\"/\", tex:null, ttype:BINARY},\n AMdiv = {input:\"/\", tag:\"mfrac\", output:\"/\", tex:null, ttype:INFIX},\n AMover = {input:\"stackrel\", tag:\"mover\", output:\"stackrel\", tex:null, ttype:BINARY},\n AMsub = {input:\"_\", tag:\"msub\", output:\"_\", tex:null, ttype:INFIX},\n AMsup = {input:\"^\", tag:\"msup\", output:\"^\", tex:null, ttype:INFIX},\n AMtext = {input:\"text\", tag:\"mtext\", output:\"text\", tex:null, ttype:TEXT},\n AMmbox = {input:\"mbox\", tag:\"mtext\", output:\"mbox\", tex:null, ttype:TEXT},\n AMquote = {input:\"\\\"\", tag:\"mtext\", output:\"mbox\", tex:null, ttype:TEXT};\n\nvar AMsymbols = [\n//some greek symbols\n{input:\"alpha\", tag:\"mi\", output:\"\\u03B1\", tex:null, ttype:CONST},\n{input:\"beta\", tag:\"mi\", output:\"\\u03B2\", tex:null, ttype:CONST},\n{input:\"chi\", tag:\"mi\", output:\"\\u03C7\", tex:null, ttype:CONST},\n{input:\"delta\", tag:\"mi\", output:\"\\u03B4\", tex:null, ttype:CONST},\n{input:\"Delta\", tag:\"mo\", output:\"\\u0394\", tex:null, ttype:CONST},\n{input:\"epsi\", tag:\"mi\", output:\"\\u03B5\", tex:\"epsilon\", ttype:CONST},\n{input:\"varepsilon\", tag:\"mi\", output:\"\\u025B\", tex:null, ttype:CONST},\n{input:\"eta\", tag:\"mi\", output:\"\\u03B7\", tex:null, ttype:CONST},\n{input:\"gamma\", tag:\"mi\", output:\"\\u03B3\", tex:null, ttype:CONST},\n{input:\"Gamma\", tag:\"mo\", output:\"\\u0393\", tex:null, ttype:CONST},\n{input:\"iota\", tag:\"mi\", output:\"\\u03B9\", tex:null, ttype:CONST},\n{input:\"kappa\", tag:\"mi\", output:\"\\u03BA\", tex:null, ttype:CONST},\n{input:\"lambda\", tag:\"mi\", output:\"\\u03BB\", tex:null, ttype:CONST},\n{input:\"Lambda\", tag:\"mo\", output:\"\\u039B\", tex:null, ttype:CONST},\n{input:\"mu\", tag:\"mi\", output:\"\\u03BC\", tex:null, ttype:CONST},\n{input:\"nu\", tag:\"mi\", output:\"\\u03BD\", tex:null, ttype:CONST},\n{input:\"omega\", tag:\"mi\", output:\"\\u03C9\", tex:null, ttype:CONST},\n{input:\"Omega\", tag:\"mo\", output:\"\\u03A9\", tex:null, ttype:CONST},\n{input:\"phi\", tag:\"mi\", output:\"\\u03C6\", tex:null, ttype:CONST},\n{input:\"varphi\", tag:\"mi\", output:\"\\u03D5\", tex:null, ttype:CONST},\n{input:\"Phi\", tag:\"mo\", output:\"\\u03A6\", tex:null, ttype:CONST},\n{input:\"pi\", tag:\"mi\", output:\"\\u03C0\", tex:null, ttype:CONST},\n{input:\"Pi\", tag:\"mo\", output:\"\\u03A0\", tex:null, ttype:CONST},\n{input:\"psi\", tag:\"mi\", output:\"\\u03C8\", tex:null, ttype:CONST},\n{input:\"Psi\", tag:\"mi\", output:\"\\u03A8\", tex:null, ttype:CONST},\n{input:\"rho\", tag:\"mi\", output:\"\\u03C1\", tex:null, ttype:CONST},\n{input:\"sigma\", tag:\"mi\", output:\"\\u03C3\", tex:null, ttype:CONST},\n{input:\"Sigma\", tag:\"mo\", output:\"\\u03A3\", tex:null, ttype:CONST},\n{input:\"tau\", tag:\"mi\", output:\"\\u03C4\", tex:null, ttype:CONST},\n{input:\"theta\", tag:\"mi\", output:\"\\u03B8\", tex:null, ttype:CONST},\n{input:\"vartheta\", tag:\"mi\", output:\"\\u03D1\", tex:null, ttype:CONST},\n{input:\"Theta\", tag:\"mo\", output:\"\\u0398\", tex:null, ttype:CONST},\n{input:\"upsilon\", tag:\"mi\", output:\"\\u03C5\", tex:null, ttype:CONST},\n{input:\"xi\", tag:\"mi\", output:\"\\u03BE\", tex:null, ttype:CONST},\n{input:\"Xi\", tag:\"mo\", output:\"\\u039E\", tex:null, ttype:CONST},\n{input:\"zeta\", tag:\"mi\", output:\"\\u03B6\", tex:null, ttype:CONST},\n\n//binary operation symbols\n{input:\"*\", tag:\"mo\", output:\"\\u22C5\", tex:\"cdot\", ttype:CONST},\n{input:\"**\", tag:\"mo\", output:\"\\u22C6\", tex:\"star\", ttype:CONST},\n{input:\"//\", tag:\"mo\", output:\"/\", tex:null, ttype:CONST},\n{input:\"\\\\\\\\\", tag:\"mo\", output:\"\\\\\", tex:\"backslash\", ttype:CONST},\n{input:\"setminus\", tag:\"mo\", output:\"\\\\\", tex:null, ttype:CONST},\n{input:\"xx\", tag:\"mo\", output:\"\\u00D7\", tex:\"times\", ttype:CONST},\n{input:\"-:\", tag:\"mo\", output:\"\\u00F7\", tex:\"divide\", ttype:CONST},\n{input:\"@\", tag:\"mo\", output:\"\\u2218\", tex:\"circ\", ttype:CONST},\n{input:\"o+\", tag:\"mo\", output:\"\\u2295\", tex:\"oplus\", ttype:CONST},\n{input:\"ox\", tag:\"mo\", output:\"\\u2297\", tex:\"otimes\", ttype:CONST},\n{input:\"o.\", tag:\"mo\", output:\"\\u2299\", tex:\"odot\", ttype:CONST},\n{input:\"sum\", tag:\"mo\", output:\"\\u2211\", tex:null, ttype:UNDEROVER},\n{input:\"prod\", tag:\"mo\", output:\"\\u220F\", tex:null, ttype:UNDEROVER},\n{input:\"^^\", tag:\"mo\", output:\"\\u2227\", tex:\"wedge\", ttype:CONST},\n{input:\"^^^\", tag:\"mo\", output:\"\\u22C0\", tex:\"bigwedge\", ttype:UNDEROVER},\n{input:\"vv\", tag:\"mo\", output:\"\\u2228\", tex:\"vee\", ttype:CONST},\n{input:\"vvv\", tag:\"mo\", output:\"\\u22C1\", tex:\"bigvee\", ttype:UNDEROVER},\n{input:\"nn\", tag:\"mo\", output:\"\\u2229\", tex:\"cap\", ttype:CONST},\n{input:\"nnn\", tag:\"mo\", output:\"\\u22C2\", tex:\"bigcap\", ttype:UNDEROVER},\n{input:\"uu\", tag:\"mo\", output:\"\\u222A\", tex:\"cup\", ttype:CONST},\n{input:\"uuu\", tag:\"mo\", output:\"\\u22C3\", tex:\"bigcup\", ttype:UNDEROVER},\n\n//binary relation symbols\n{input:\"!=\", tag:\"mo\", output:\"\\u2260\", tex:\"ne\", ttype:CONST},\n{input:\":=\", tag:\"mo\", output:\":=\", tex:null, ttype:CONST},\n{input:\"lt\", tag:\"mo\", output:\"<\", tex:null, ttype:CONST},\n{input:\"<=\", tag:\"mo\", output:\"\\u2264\", tex:\"le\", ttype:CONST},\n{input:\"lt=\", tag:\"mo\", output:\"\\u2264\", tex:\"leq\", ttype:CONST},\n{input:\">=\", tag:\"mo\", output:\"\\u2265\", tex:\"ge\", ttype:CONST},\n{input:\"geq\", tag:\"mo\", output:\"\\u2265\", tex:null, ttype:CONST},\n{input:\"-<\", tag:\"mo\", output:\"\\u227A\", tex:\"prec\", ttype:CONST},\n{input:\"-lt\", tag:\"mo\", output:\"\\u227A\", tex:null, ttype:CONST},\n{input:\">-\", tag:\"mo\", output:\"\\u227B\", tex:\"succ\", ttype:CONST},\n{input:\"-<=\", tag:\"mo\", output:\"\\u2AAF\", tex:\"preceq\", ttype:CONST},\n{input:\">-=\", tag:\"mo\", output:\"\\u2AB0\", tex:\"succeq\", ttype:CONST},\n{input:\"in\", tag:\"mo\", output:\"\\u2208\", tex:null, ttype:CONST},\n{input:\"!in\", tag:\"mo\", output:\"\\u2209\", tex:\"notin\", ttype:CONST},\n{input:\"sub\", tag:\"mo\", output:\"\\u2282\", tex:\"subset\", ttype:CONST},\n{input:\"sup\", tag:\"mo\", output:\"\\u2283\", tex:\"supset\", ttype:CONST},\n{input:\"sube\", tag:\"mo\", output:\"\\u2286\", tex:\"subseteq\", ttype:CONST},\n{input:\"supe\", tag:\"mo\", output:\"\\u2287\", tex:\"supseteq\", ttype:CONST},\n{input:\"-=\", tag:\"mo\", output:\"\\u2261\", tex:\"equiv\", ttype:CONST},\n{input:\"~=\", tag:\"mo\", output:\"\\u2245\", tex:\"cong\", ttype:CONST},\n{input:\"~~\", tag:\"mo\", output:\"\\u2248\", tex:\"approx\", ttype:CONST},\n{input:\"prop\", tag:\"mo\", output:\"\\u221D\", tex:\"propto\", ttype:CONST},\n\n//logical symbols\n{input:\"and\", tag:\"mtext\", output:\"and\", tex:null, ttype:SPACE},\n{input:\"or\", tag:\"mtext\", output:\"or\", tex:null, ttype:SPACE},\n{input:\"not\", tag:\"mo\", output:\"\\u00AC\", tex:\"neg\", ttype:CONST},\n{input:\"=>\", tag:\"mo\", output:\"\\u21D2\", tex:\"implies\", ttype:CONST},\n{input:\"if\", tag:\"mo\", output:\"if\", tex:null, ttype:SPACE},\n{input:\"<=>\", tag:\"mo\", output:\"\\u21D4\", tex:\"iff\", ttype:CONST},\n{input:\"AA\", tag:\"mo\", output:\"\\u2200\", tex:\"forall\", ttype:CONST},\n{input:\"EE\", tag:\"mo\", output:\"\\u2203\", tex:\"exists\", ttype:CONST},\n{input:\"_|_\", tag:\"mo\", output:\"\\u22A5\", tex:\"bot\", ttype:CONST},\n{input:\"TT\", tag:\"mo\", output:\"\\u22A4\", tex:\"top\", ttype:CONST},\n{input:\"|--\", tag:\"mo\", output:\"\\u22A2\", tex:\"vdash\", ttype:CONST},\n{input:\"|==\", tag:\"mo\", output:\"\\u22A8\", tex:\"models\", ttype:CONST},\n\n//grouping brackets\n{input:\"(\", tag:\"mo\", output:\"(\", tex:null, ttype:LEFTBRACKET},\n{input:\")\", tag:\"mo\", output:\")\", tex:null, ttype:RIGHTBRACKET},\n{input:\"[\", tag:\"mo\", output:\"[\", tex:null, ttype:LEFTBRACKET},\n{input:\"]\", tag:\"mo\", output:\"]\", tex:null, ttype:RIGHTBRACKET},\n{input:\"{\", tag:\"mo\", output:\"{\", tex:null, ttype:LEFTBRACKET},\n{input:\"}\", tag:\"mo\", output:\"}\", tex:null, ttype:RIGHTBRACKET},\n{input:\"|\", tag:\"mo\", output:\"|\", tex:null, ttype:LEFTRIGHT},\n//{input:\"||\", tag:\"mo\", output:\"||\", tex:null, ttype:LEFTRIGHT},\n{input:\"(:\", tag:\"mo\", output:\"\\u2329\", tex:\"langle\", ttype:LEFTBRACKET},\n{input:\":)\", tag:\"mo\", output:\"\\u232A\", tex:\"rangle\", ttype:RIGHTBRACKET},\n{input:\"<<\", tag:\"mo\", output:\"\\u2329\", tex:null, ttype:LEFTBRACKET},\n{input:\">>\", tag:\"mo\", output:\"\\u232A\", tex:null, ttype:RIGHTBRACKET},\n{input:\"{:\", tag:\"mo\", output:\"{:\", tex:null, ttype:LEFTBRACKET, invisible:true},\n{input:\":}\", tag:\"mo\", output:\":}\", tex:null, ttype:RIGHTBRACKET, invisible:true},\n\n//miscellaneous symbols\n{input:\"int\", tag:\"mo\", output:\"\\u222B\", tex:null, ttype:CONST},\n{input:\"dx\", tag:\"mi\", output:\"{:d x:}\", tex:null, ttype:DEFINITION},\n{input:\"dy\", tag:\"mi\", output:\"{:d y:}\", tex:null, ttype:DEFINITION},\n{input:\"dz\", tag:\"mi\", output:\"{:d z:}\", tex:null, ttype:DEFINITION},\n{input:\"dt\", tag:\"mi\", output:\"{:d t:}\", tex:null, ttype:DEFINITION},\n{input:\"oint\", tag:\"mo\", output:\"\\u222E\", tex:null, ttype:CONST},\n{input:\"del\", tag:\"mo\", output:\"\\u2202\", tex:\"partial\", ttype:CONST},\n{input:\"grad\", tag:\"mo\", output:\"\\u2207\", tex:\"nabla\", ttype:CONST},\n{input:\"+-\", tag:\"mo\", output:\"\\u00B1\", tex:\"pm\", ttype:CONST},\n{input:\"O/\", tag:\"mo\", output:\"\\u2205\", tex:\"emptyset\", ttype:CONST},\n{input:\"oo\", tag:\"mo\", output:\"\\u221E\", tex:\"infty\", ttype:CONST},\n{input:\"aleph\", tag:\"mo\", output:\"\\u2135\", tex:null, ttype:CONST},\n{input:\"...\", tag:\"mo\", output:\"...\", tex:\"ldots\", ttype:CONST},\n{input:\":.\", tag:\"mo\", output:\"\\u2234\", tex:\"therefore\", ttype:CONST},\n{input:\"/_\", tag:\"mo\", output:\"\\u2220\", tex:\"angle\", ttype:CONST},\n{input:\"\\\\ \", tag:\"mo\", output:\"\\u00A0\", tex:null, ttype:CONST},\n{input:\"quad\", tag:\"mo\", output:\"\\u00A0\\u00A0\", tex:null, ttype:CONST},\n{input:\"qquad\", tag:\"mo\", output:\"\\u00A0\\u00A0\\u00A0\\u00A0\", tex:null, ttype:CONST},\n{input:\"cdots\", tag:\"mo\", output:\"\\u22EF\", tex:null, ttype:CONST},\n{input:\"vdots\", tag:\"mo\", output:\"\\u22EE\", tex:null, ttype:CONST},\n{input:\"ddots\", tag:\"mo\", output:\"\\u22F1\", tex:null, ttype:CONST},\n{input:\"diamond\", tag:\"mo\", output:\"\\u22C4\", tex:null, ttype:CONST},\n{input:\"square\", tag:\"mo\", output:\"\\u25A1\", tex:null, ttype:CONST},\n{input:\"|__\", tag:\"mo\", output:\"\\u230A\", tex:\"lfloor\", ttype:CONST},\n{input:\"__|\", tag:\"mo\", output:\"\\u230B\", tex:\"rfloor\", ttype:CONST},\n{input:\"|~\", tag:\"mo\", output:\"\\u2308\", tex:\"lceiling\", ttype:CONST},\n{input:\"~|\", tag:\"mo\", output:\"\\u2309\", tex:\"rceiling\", ttype:CONST},\n{input:\"CC\", tag:\"mo\", output:\"\\u2102\", tex:null, ttype:CONST},\n{input:\"NN\", tag:\"mo\", output:\"\\u2115\", tex:null, ttype:CONST},\n{input:\"QQ\", tag:\"mo\", output:\"\\u211A\", tex:null, ttype:CONST},\n{input:\"RR\", tag:\"mo\", output:\"\\u211D\", tex:null, ttype:CONST},\n{input:\"ZZ\", tag:\"mo\", output:\"\\u2124\", tex:null, ttype:CONST},\n{input:\"f\", tag:\"mi\", output:\"f\", tex:null, ttype:UNARY, func:true},\n{input:\"g\", tag:\"mi\", output:\"g\", tex:null, ttype:UNARY, func:true},\n\n//standard functions\n{input:\"lim\", tag:\"mo\", output:\"lim\", tex:null, ttype:UNDEROVER},\n{input:\"Lim\", tag:\"mo\", output:\"Lim\", tex:null, ttype:UNDEROVER},\n{input:\"sin\", tag:\"mo\", output:\"sin\", tex:null, ttype:UNARY, func:true},\n{input:\"cos\", tag:\"mo\", output:\"cos\", tex:null, ttype:UNARY, func:true},\n{input:\"tan\", tag:\"mo\", output:\"tan\", tex:null, ttype:UNARY, func:true},\n{input:\"sinh\", tag:\"mo\", output:\"sinh\", tex:null, ttype:UNARY, func:true},\n{input:\"cosh\", tag:\"mo\", output:\"cosh\", tex:null, ttype:UNARY, func:true},\n{input:\"tanh\", tag:\"mo\", output:\"tanh\", tex:null, ttype:UNARY, func:true},\n{input:\"cot\", tag:\"mo\", output:\"cot\", tex:null, ttype:UNARY, func:true},\n{input:\"sec\", tag:\"mo\", output:\"sec\", tex:null, ttype:UNARY, func:true},\n{input:\"csc\", tag:\"mo\", output:\"csc\", tex:null, ttype:UNARY, func:true},\n{input:\"log\", tag:\"mo\", output:\"log\", tex:null, ttype:UNARY, func:true},\n{input:\"ln\", tag:\"mo\", output:\"ln\", tex:null, ttype:UNARY, func:true},\n{input:\"det\", tag:\"mo\", output:\"det\", tex:null, ttype:UNARY, func:true},\n{input:\"dim\", tag:\"mo\", output:\"dim\", tex:null, ttype:CONST},\n{input:\"mod\", tag:\"mo\", output:\"mod\", tex:null, ttype:CONST},\n{input:\"gcd\", tag:\"mo\", output:\"gcd\", tex:null, ttype:UNARY, func:true},\n{input:\"lcm\", tag:\"mo\", output:\"lcm\", tex:null, ttype:UNARY, func:true},\n{input:\"lub\", tag:\"mo\", output:\"lub\", tex:null, ttype:CONST},\n{input:\"glb\", tag:\"mo\", output:\"glb\", tex:null, ttype:CONST},\n{input:\"min\", tag:\"mo\", output:\"min\", tex:null, ttype:UNDEROVER},\n{input:\"max\", tag:\"mo\", output:\"max\", tex:null, ttype:UNDEROVER},\n\n//arrows\n{input:\"uarr\", tag:\"mo\", output:\"\\u2191\", tex:\"uparrow\", ttype:CONST},\n{input:\"darr\", tag:\"mo\", output:\"\\u2193\", tex:\"downarrow\", ttype:CONST},\n{input:\"rarr\", tag:\"mo\", output:\"\\u2192\", tex:\"rightarrow\", ttype:CONST},\n{input:\"->\", tag:\"mo\", output:\"\\u2192\", tex:\"to\", ttype:CONST},\n{input:\"|->\", tag:\"mo\", output:\"\\u21A6\", tex:\"mapsto\", ttype:CONST},\n{input:\"larr\", tag:\"mo\", output:\"\\u2190\", tex:\"leftarrow\", ttype:CONST},\n{input:\"harr\", tag:\"mo\", output:\"\\u2194\", tex:\"leftrightarrow\", ttype:CONST},\n{input:\"rArr\", tag:\"mo\", output:\"\\u21D2\", tex:\"Rightarrow\", ttype:CONST},\n{input:\"lArr\", tag:\"mo\", output:\"\\u21D0\", tex:\"Leftarrow\", ttype:CONST},\n{input:\"hArr\", tag:\"mo\", output:\"\\u21D4\", tex:\"Leftrightarrow\", ttype:CONST},\n\n//commands with argument\nAMsqrt, AMroot, AMfrac, AMdiv, AMover, AMsub, AMsup,\n{input:\"hat\", tag:\"mover\", output:\"\\u005E\", tex:null, ttype:UNARY, acc:true},\n{input:\"bar\", tag:\"mover\", output:\"\\u00AF\", tex:\"overline\", ttype:UNARY, acc:true},\n{input:\"vec\", tag:\"mover\", output:\"\\u2192\", tex:null, ttype:UNARY, acc:true},\n{input:\"dot\", tag:\"mover\", output:\".\", tex:null, ttype:UNARY, acc:true},\n{input:\"ddot\", tag:\"mover\", output:\"..\", tex:null, ttype:UNARY, acc:true},\n{input:\"ul\", tag:\"munder\", output:\"\\u0332\", tex:\"underline\", ttype:UNARY, acc:true},\nAMtext, AMmbox, AMquote,\n{input:\"bb\", tag:\"mstyle\", atname:\"fontweight\", atval:\"bold\", output:\"bb\", tex:null, ttype:UNARY},\n{input:\"mathbf\", tag:\"mstyle\", atname:\"fontweight\", atval:\"bold\", output:\"mathbf\", tex:null, ttype:UNARY},\n{input:\"sf\", tag:\"mstyle\", atname:\"fontfamily\", atval:\"sans-serif\", output:\"sf\", tex:null, ttype:UNARY},\n{input:\"mathsf\", tag:\"mstyle\", atname:\"fontfamily\", atval:\"sans-serif\", output:\"mathsf\", tex:null, ttype:UNARY},\n{input:\"bbb\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"double-struck\", output:\"bbb\", tex:null, ttype:UNARY, codes:AMbbb},\n{input:\"mathbb\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"double-struck\", output:\"mathbb\", tex:null, ttype:UNARY, codes:AMbbb},\n{input:\"cc\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"script\", output:\"cc\", tex:null, ttype:UNARY, codes:AMcal},\n{input:\"mathcal\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"script\", output:\"mathcal\", tex:null, ttype:UNARY, codes:AMcal},\n{input:\"tt\", tag:\"mstyle\", atname:\"fontfamily\", atval:\"monospace\", output:\"tt\", tex:null, ttype:UNARY},\n{input:\"mathtt\", tag:\"mstyle\", atname:\"fontfamily\", atval:\"monospace\", output:\"mathtt\", tex:null, ttype:UNARY},\n{input:\"fr\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"fraktur\", output:\"fr\", tex:null, ttype:UNARY, codes:AMfrk},\n{input:\"mathfrak\", tag:\"mstyle\", atname:\"mathvariant\", atval:\"fraktur\", output:\"mathfrak\", tex:null, ttype:UNARY, codes:AMfrk}\n];\n\nfunction compareNames(s1,s2) {\n if (s1.input > s2.input) return 1\n else return -1;\n}\n\nvar AMnames = []; //list of input symbols\n\nfunction AMinitSymbols() {\n var texsymbols = [], i;\n for (i=0; i<AMsymbols.length; i++)\n if (AMsymbols[i].tex) \n texsymbols[texsymbols.length] = {input:AMsymbols[i].tex, \n tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype};\n AMsymbols = AMsymbols.concat(texsymbols);\n AMsymbols.sort(compareNames);\n for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;\n}\n\nvar AMmathml = \"http://www.w3.org/1998/Math/MathML\";\n\nfunction AMcreateElementMathML(t) {\n if (isIE) return document.createElement(\"m:\"+t);\n else return document.createElementNS(AMmathml,t);\n}\n\nfunction AMcreateMmlNode(t,frag) {\n// var node = AMcreateElementMathML(name);\n if (isIE) var node = document.createElement(\"m:\"+t);\n else var node = document.createElementNS(AMmathml,t);\n node.appendChild(frag);\n return node;\n}\n\nfunction newcommand(oldstr,newstr) {\n AMsymbols = AMsymbols.concat([{input:oldstr, tag:\"mo\", output:newstr, \n tex:null, ttype:DEFINITION}]);\n}\n\nfunction AMremoveCharsAndBlanks(str,n) {\n//remove n characters and any following blanks\n var st;\n if (str.charAt(n)==\"\\\\\" && str.charAt(n+1)!=\"\\\\\" && str.charAt(n+1)!=\" \") \n st = str.slice(n+1);\n else st = str.slice(n);\n for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);\n return st.slice(i);\n}\n\nfunction AMposition(arr, str, n) { \n// return position >=n where str appears or would be inserted\n// assumes arr is sorted\n if (n==0) {\n var h,m;\n n = -1;\n h = arr.length;\n while (n+1<h) {\n m = (n+h) >> 1;\n if (arr[m]<str) n = m; else h = m;\n }\n return h;\n } else\n for (var i=n; i<arr.length && arr[i]<str; i++);\n return i; // i=arr.length || arr[i]>=str\n}\n\nfunction AMgetSymbol(str) {\n//return maximal initial substring of str that appears in names\n//return null if there is none\n var k = 0; //new pos\n var j = 0; //old pos\n var mk; //match pos\n var st;\n var tagst;\n var match = \"\";\n var more = true;\n for (var i=1; i<=str.length && more; i++) {\n st = str.slice(0,i); //initial substring of length i\n j = k;\n k = AMposition(AMnames, st, j);\n if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){\n match = AMnames[k];\n mk = k;\n i = match.length;\n }\n more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];\n }\n AMpreviousSymbol=AMcurrentSymbol;\n if (match!=\"\"){\n AMcurrentSymbol=AMsymbols[mk].ttype;\n return AMsymbols[mk]; \n }\n// if str[0] is a digit or - return maxsubstring of digits.digits\n AMcurrentSymbol=CONST;\n k = 1;\n st = str.slice(0,1);\n var integ = true;\n while (\"0\"<=st && st<=\"9\" && k<=str.length) {\n st = str.slice(k,k+1);\n k++;\n }\n if (st == decimalsign) {\n st = str.slice(k,k+1);\n if (\"0\"<=st && st<=\"9\") {\n integ = false;\n k++;\n while (\"0\"<=st && st<=\"9\" && k<=str.length) {\n st = str.slice(k,k+1);\n k++;\n }\n }\n }\n if ((integ && k>1) || k>2) {\n st = str.slice(0,k-1);\n tagst = \"mn\";\n } else {\n k = 2;\n st = str.slice(0,1); //take 1 character\n tagst = ((\"A\">st || st>\"Z\") && (\"a\">st || st>\"z\")?\"mo\":\"mi\");\n }\n if (st==\"-\" && AMpreviousSymbol==INFIX) {\n AMcurrentSymbol = INFIX; //trick \"/\" into recognizing \"-\" on second parse\n return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};\n }\n return {input:st, tag:tagst, output:st, ttype:CONST};\n}\n\nfunction AMremoveBrackets(node) {\n var st;\n if (node.nodeName==\"mrow\") {\n st = node.firstChild.firstChild.nodeValue;\n if (st==\"(\" || st==\"[\" || st==\"{\") node.removeChild(node.firstChild);\n }\n if (node.nodeName==\"mrow\") {\n st = node.lastChild.firstChild.nodeValue;\n if (st==\")\" || st==\"]\" || st==\"}\") node.removeChild(node.lastChild);\n }\n}\n\n/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n\nvar AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;\n\nfunction AMparseSexpr(str) { //parses str and returns [node,tailstr]\n var symbol, node, result, i, st,// rightvert = false,\n newFrag = document.createDocumentFragment();\n str = AMremoveCharsAndBlanks(str,0);\n symbol = AMgetSymbol(str); //either a token or a bracket or empty\n if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {\n return [null,str];\n }\n if (symbol.ttype == DEFINITION) {\n str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length); \n symbol = AMgetSymbol(str);\n }\n switch (symbol.ttype) {\n case UNDEROVER:\n case CONST:\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n return [AMcreateMmlNode(symbol.tag, //its a constant\n document.createTextNode(symbol.output)),str];\n case LEFTBRACKET: //read (expr+)\n AMnestingDepth++;\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n result = AMparseExpr(str,true);\n AMnestingDepth--;\n if (typeof symbol.invisible == \"boolean\" && symbol.invisible) \n node = AMcreateMmlNode(\"mrow\",result[0]);\n else {\n node = AMcreateMmlNode(\"mo\",document.createTextNode(symbol.output));\n node = AMcreateMmlNode(\"mrow\",node);\n node.appendChild(result[0]);\n }\n return [node,result[1]];\n case TEXT:\n if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);\n if (str.charAt(0)==\"{\") i=str.indexOf(\"}\");\n else if (str.charAt(0)==\"(\") i=str.indexOf(\")\");\n else if (str.charAt(0)==\"[\") i=str.indexOf(\"]\");\n else if (symbol==AMquote) i=str.slice(1).indexOf(\"\\\"\")+1;\n else i = 0;\n if (i==-1) i = str.length;\n st = str.slice(1,i);\n if (st.charAt(0) == \" \") {\n node = AMcreateElementMathML(\"mspace\");\n node.setAttribute(\"width\",\"1ex\");\n newFrag.appendChild(node);\n }\n newFrag.appendChild(\n AMcreateMmlNode(symbol.tag,document.createTextNode(st)));\n if (st.charAt(st.length-1) == \" \") {\n node = AMcreateElementMathML(\"mspace\");\n node.setAttribute(\"width\",\"1ex\");\n newFrag.appendChild(node);\n }\n str = AMremoveCharsAndBlanks(str,i+1);\n return [AMcreateMmlNode(\"mrow\",newFrag),str];\n case UNARY:\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n result = AMparseSexpr(str);\n if (result[0]==null) return [AMcreateMmlNode(symbol.tag,\n document.createTextNode(symbol.output)),str];\n if (typeof symbol.func == \"boolean\" && symbol.func) { // functions hack\n st = str.charAt(0);\n if (st==\"^\" || st==\"_\" || st==\"/\" || st==\"|\" || st==\",\") {\n return [AMcreateMmlNode(symbol.tag,\n document.createTextNode(symbol.output)),str];\n } else {\n node = AMcreateMmlNode(\"mrow\",\n AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));\n node.appendChild(result[0]);\n return [node,result[1]];\n }\n }\n AMremoveBrackets(result[0]);\n if (symbol.input == \"sqrt\") { // sqrt\n return [AMcreateMmlNode(symbol.tag,result[0]),result[1]];\n } else if (typeof symbol.acc == \"boolean\" && symbol.acc) { // accent\n node = AMcreateMmlNode(symbol.tag,result[0]);\n node.appendChild(AMcreateMmlNode(\"mo\",document.createTextNode(symbol.output)));\n return [node,result[1]];\n } else { // font change command\n if (!isIE && typeof symbol.codes != \"undefined\") {\n for (i=0; i<result[0].childNodes.length; i++)\n if (result[0].childNodes[i].nodeName==\"mi\" || result[0].nodeName==\"mi\") {\n st = (result[0].nodeName==\"mi\"?result[0].firstChild.nodeValue:\n result[0].childNodes[i].firstChild.nodeValue);\n var newst = [];\n for (var j=0; j<st.length; j++)\n if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst +\n String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);\n else newst = newst + st.charAt(j);\n if (result[0].nodeName==\"mi\")\n result[0]=AMcreateElementMathML(\"mo\").\n appendChild(document.createTextNode(newst));\n else result[0].replaceChild(AMcreateElementMathML(\"mo\").\n appendChild(document.createTextNode(newst)),result[0].childNodes[i]);\n }\n }\n node = AMcreateMmlNode(symbol.tag,result[0]);\n node.setAttribute(symbol.atname,symbol.atval);\n return [node,result[1]];\n }\n case BINARY:\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n result = AMparseSexpr(str);\n if (result[0]==null) return [AMcreateMmlNode(\"mo\",\n document.createTextNode(symbol.input)),str];\n AMremoveBrackets(result[0]);\n var result2 = AMparseSexpr(result[1]);\n if (result2[0]==null) return [AMcreateMmlNode(\"mo\",\n document.createTextNode(symbol.input)),str];\n AMremoveBrackets(result2[0]);\n if (symbol.input==\"root\" || symbol.input==\"stackrel\") \n newFrag.appendChild(result2[0]);\n newFrag.appendChild(result[0]);\n if (symbol.input==\"frac\") newFrag.appendChild(result2[0]);\n return [AMcreateMmlNode(symbol.tag,newFrag),result2[1]];\n case INFIX:\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n return [AMcreateMmlNode(\"mo\",document.createTextNode(symbol.output)),str];\n case SPACE:\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n node = AMcreateElementMathML(\"mspace\");\n node.setAttribute(\"width\",\"1ex\");\n newFrag.appendChild(node);\n newFrag.appendChild(\n AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));\n node = AMcreateElementMathML(\"mspace\");\n node.setAttribute(\"width\",\"1ex\");\n newFrag.appendChild(node);\n return [AMcreateMmlNode(\"mrow\",newFrag),str];\n case LEFTRIGHT:\n// if (rightvert) return [null,str]; else rightvert = true;\n AMnestingDepth++;\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n result = AMparseExpr(str,false);\n AMnestingDepth--;\n var st = \"\";\n if (result[0].lastChild!=null)\n st = result[0].lastChild.firstChild.nodeValue;\n if (st == \"|\") { // its an absolute value subterm\n node = AMcreateMmlNode(\"mo\",document.createTextNode(symbol.output));\n node = AMcreateMmlNode(\"mrow\",node);\n node.appendChild(result[0]);\n return [node,result[1]];\n } else { // the \"|\" is a \\mid\n node = AMcreateMmlNode(\"mo\",document.createTextNode(symbol.output));\n node = AMcreateMmlNode(\"mrow\",node);\n return [node,str];\n }\n default:\n//alert(\"default\");\n str = AMremoveCharsAndBlanks(str,symbol.input.length); \n return [AMcreateMmlNode(symbol.tag, //its a constant\n document.createTextNode(symbol.output)),str];\n }\n}\n\nfunction AMparseIexpr(str) {\n var symbol, sym1, sym2, node, result, underover;\n str = AMremoveCharsAndBlanks(str,0);\n sym1 = AMgetSymbol(str);\n result = AMparseSexpr(str);\n node = result[0];\n str = result[1];\n symbol = AMgetSymbol(str);\n if (symbol.ttype == INFIX && symbol.input != \"/\") {\n str = AMremoveCharsAndBlanks(str,symbol.input.length);\n// if (symbol.input == \"/\") result = AMparseIexpr(str); else ...\n result = AMparseSexpr(str);\n if (result[0] == null) // show box in place of missing argument\n result[0] = AMcreateMmlNode(\"mo\",document.createTextNode(\"\\u25A1\"));\n else AMremoveBrackets(result[0]);\n str = result[1];\n// if (symbol.input == \"/\") AMremoveBrackets(node);\n if (symbol.input == \"_\") {\n sym2 = AMgetSymbol(str);\n underover = (sym1.ttype == UNDEROVER);\n if (sym2.input == \"^\") {\n str = AMremoveCharsAndBlanks(str,sym2.input.length);\n var res2 = AMparseSexpr(str);\n AMremoveBrackets(res2[0]);\n str = res2[1];\n node = AMcreateMmlNode((underover?\"munderover\":\"msubsup\"),node);\n node.appendChild(result[0]);\n node.appendChild(res2[0]);\n node = AMcreateMmlNode(\"mrow\",node); // so sum does not stretch\n } else {\n node = AMcreateMmlNode((underover?\"munder\":\"msub\"),node);\n node.appendChild(result[0]);\n }\n } else {\n node = AMcreateMmlNode(symbol.tag,node);\n node.appendChild(result[0]);\n }\n }\n return [node,str];\n}\n\nfunction AMparseExpr(str,rightbracket) {\n var symbol, node, result, i, nodeList = [],\n newFrag = document.createDocumentFragment();\n do {\n str = AMremoveCharsAndBlanks(str,0);\n result = AMparseIexpr(str);\n node = result[0];\n str = result[1];\n symbol = AMgetSymbol(str);\n if (symbol.ttype == INFIX && symbol.input == \"/\") {\n str = AMremoveCharsAndBlanks(str,symbol.input.length);\n result = AMparseIexpr(str);\n if (result[0] == null) // show box in place of missing argument\n result[0] = AMcreateMmlNode(\"mo\",document.createTextNode(\"\\u25A1\"));\n else AMremoveBrackets(result[0]);\n str = result[1];\n AMremoveBrackets(node);\n node = AMcreateMmlNode(symbol.tag,node);\n node.appendChild(result[0]);\n newFrag.appendChild(node);\n symbol = AMgetSymbol(str);\n } \n else if (node!=undefined) newFrag.appendChild(node);\n } while ((symbol.ttype != RIGHTBRACKET && \n (symbol.ttype != LEFTRIGHT || rightbracket)\n || AMnestingDepth == 0) && symbol!=null && symbol.output!=\"\");\n if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {\n// if (AMnestingDepth > 0) AMnestingDepth--;\n var len = newFrag.childNodes.length;\n if (len>0 && newFrag.childNodes[len-1].nodeName == \"mrow\" && len>1 &&\n newFrag.childNodes[len-2].nodeName == \"mo\" &&\n newFrag.childNodes[len-2].firstChild.nodeValue == \",\") { //matrix\n var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;\n if (right==\")\" || right==\"]\") {\n var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;\n if (left==\"(\" && right==\")\" && symbol.output != \"}\" || \n left==\"[\" && right==\"]\") {\n var pos = []; // positions of commas\n var matrix = true;\n var m = newFrag.childNodes.length;\n for (i=0; matrix && i<m; i=i+2) {\n pos[i] = [];\n node = newFrag.childNodes[i];\n if (matrix) matrix = node.nodeName==\"mrow\" && \n (i==m-1 || node.nextSibling.nodeName==\"mo\" && \n node.nextSibling.firstChild.nodeValue==\",\")&&\n node.firstChild.firstChild.nodeValue==left &&\n node.lastChild.firstChild.nodeValue==right;\n if (matrix) \n for (var j=0; j<node.childNodes.length; j++)\n if (node.childNodes[j].firstChild.nodeValue==\",\")\n pos[i][pos[i].length]=j;\n if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;\n }\n if (matrix) {\n var row, frag, n, k, table = document.createDocumentFragment();\n for (i=0; i<m; i=i+2) {\n row = document.createDocumentFragment();\n frag = document.createDocumentFragment();\n node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>\n n = node.childNodes.length;\n k = 0;\n node.removeChild(node.firstChild); //remove (\n for (j=1; j<n-1; j++) {\n if (typeof pos[i][k] != \"undefined\" && j==pos[i][k]){\n node.removeChild(node.firstChild); //remove ,\n row.appendChild(AMcreateMmlNode(\"mtd\",frag));\n k++;\n } else frag.appendChild(node.firstChild);\n }\n row.appendChild(AMcreateMmlNode(\"mtd\",frag));\n if (newFrag.childNodes.length>2) {\n newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>\n newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>\n }\n table.appendChild(AMcreateMmlNode(\"mtr\",row));\n }\n node = AMcreateMmlNode(\"mtable\",table);\n if (typeof symbol.invisible == \"boolean\" && symbol.invisible) node.setAttribute(\"columnalign\",\"left\");\n newFrag.replaceChild(node,newFrag.firstChild);\n }\n }\n }\n }\n str = AMremoveCharsAndBlanks(str,symbol.input.length);\n if (typeof symbol.invisible != \"boolean\" || !symbol.invisible) {\n node = AMcreateMmlNode(\"mo\",document.createTextNode(symbol.output));\n newFrag.appendChild(node);\n }\n }\n return [newFrag,str];\n}\n\nfunction AMparseMath(str) {\n var result, node = AMcreateElementMathML(\"mstyle\");\n if (mathcolor != \"\") node.setAttribute(\"mathcolor\",mathcolor);\n if (displaystyle) node.setAttribute(\"displaystyle\",\"true\");\n if (mathfontfamily != \"\") node.setAttribute(\"fontfamily\",mathfontfamily);\n AMnestingDepth = 0;\n node.appendChild(AMparseExpr(str.replace(/^\\s+/g,\"\"),false)[0]);\n node = AMcreateMmlNode(\"math\",node);\n if (showasciiformulaonhover) //fixed by djhsu so newline\n node.setAttribute(\"title\",str.replace(/\\s+/g,\" \"));//does not show in Gecko\n if (mathfontfamily != \"\" && (isIE || mathfontfamily != \"serif\")) {\n var fnode = AMcreateElementXHTML(\"font\");\n fnode.setAttribute(\"face\",mathfontfamily);\n fnode.appendChild(node);\n return fnode;\n }\n return node;\n}\n\nfunction AMstrarr2docFrag(arr, linebreaks) {\n var newFrag=document.createDocumentFragment();\n var expr = false;\n for (var i=0; i<arr.length; i++) {\n if (expr) newFrag.appendChild(AMparseMath(arr[i]));\n else {\n var arri = (linebreaks ? arr[i].split(\"\\n\\n\") : [arr[i]]);\n newFrag.appendChild(AMcreateElementXHTML(\"span\").\n appendChild(document.createTextNode(arri[0])));\n for (var j=1; j<arri.length; j++) {\n newFrag.appendChild(AMcreateElementXHTML(\"p\"));\n newFrag.appendChild(AMcreateElementXHTML(\"span\").\n appendChild(document.createTextNode(arri[j])));\n }\n }\n expr = !expr;\n }\n return newFrag;\n}\n\nfunction AMprocessNodeR(n, linebreaks) {\n var mtch, str, arr, frg, i;\n if (n.childNodes.length == 0) {\n if ((n.nodeType!=8 || linebreaks) &&\n n.parentNode.nodeName!=\"form\" && n.parentNode.nodeName!=\"FORM\" &&\n n.parentNode.nodeName!=\"textarea\" && n.parentNode.nodeName!=\"TEXTAREA\" &&\n n.parentNode.nodeName!=\"code\" && n.parentNode.nodeName!=\"CODE\" && /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL\nSee http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */\n n.parentNode.nodeName!=\"pre\" && n.parentNode.nodeName!=\"PRE\") {\n str = n.nodeValue;\n if (!(str == null)) {\n str = str.replace(/\\r\\n\\r\\n/g,\"\\n\\n\");\n if (doubleblankmathdelimiter) {\n str = str.replace(/\\x20\\x20\\./g,\" \"+AMdelimiter1+\".\");\n str = str.replace(/\\x20\\x20,/g,\" \"+AMdelimiter1+\",\");\n str = str.replace(/\\x20\\x20/g,\" \"+AMdelimiter1+\" \");\n }\n str = str.replace(/\\x20+/g,\" \");\n str = str.replace(/\\s*\\r\\n/g,\" \");\n mtch = false;\n str = str.replace(new RegExp(AMescape2, \"g\"),\n function(st){mtch=true;return \"AMescape2\"});\n str = str.replace(new RegExp(AMescape1, \"g\"),\n function(st){mtch=true;return \"AMescape1\"});\n str = str.replace(new RegExp(AMdelimiter2regexp, \"g\"),AMdelimiter1);\n arr = str.split(AMdelimiter1);\n for (i=0; i<arr.length; i++)\n arr[i]=arr[i].replace(/AMescape2/g,AMdelimiter2).\n replace(/AMescape1/g,AMdelimiter1);\n if (arr.length>1 || mtch) {\n if (checkForMathML) {\n checkForMathML = false;\n var nd = AMisMathMLavailable();\n AMnoMathML = nd != null;\n if (AMnoMathML && notifyIfNoMathML) \n if (alertIfNoMathML)\n alert(\"To view the ASCIIMathML notation use Internet Explorer 6 +\\nMathPlayer (free from www.dessci.com)\\n\\\n or Firefox/Mozilla/Netscape\");\n else AMbody.insertBefore(nd,AMbody.childNodes[0]);\n }\n if (!AMnoMathML) {\n frg = AMstrarr2docFrag(arr,n.nodeType==8);\n var len = frg.childNodes.length;\n n.parentNode.replaceChild(frg,n);\n return len-1;\n } else return 0;\n }\n }\n } else return 0;\n } else if (n.nodeName!=\"math\") {\n for (i=0; i<n.childNodes.length; i++)\n i += AMprocessNodeR(n.childNodes[i], linebreaks);\n }\n return 0;\n}\n\nfunction AMprocessNode(n, linebreaks, spanclassAM) {\n var frag,st;\n if (spanclassAM!=null) {\n frag = document.getElementsByTagName(\"span\")\n for (var i=0;i<frag.length;i++)\n if (frag[i].className == \"AM\")\n AMprocessNodeR(frag[i],linebreaks);\n } else {\n try {\n st = n.innerHTML;\n } catch(err) {}\n if (st==null || \n st.indexOf(AMdelimiter1)!=-1 || st.indexOf(AMdelimiter2)!=-1) \n AMprocessNodeR(n,linebreaks);\n }\n if (isIE) { //needed to match size and font of formula to surrounding text\n frag = document.getElementsByTagName('math');\n for (var i=0;i<frag.length;i++) frag[i].update()\n }\n}\n\nvar AMbody;\nvar AMnoMathML = false, AMtranslated = false;\n\nfunction translate(spanclassAM) {\n if (!AMtranslated) { // run this only once\n AMtranslated = true;\n AMinitSymbols();\n AMbody = document.getElementsByTagName(\"body\")[0];\n AMprocessNode(AMbody, false, spanclassAM);\n }\n}\n\nif (isIE) { // avoid adding MathPlayer info explicitly to each webpage\n document.write(\"<object id=\\\"mathplayer\\\"\\\n classid=\\\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\\\"></object>\");\n document.write(\"<?import namespace=\\\"m\\\" implementation=\\\"#mathplayer\\\"?>\");\n}\n\n// GO1.1 Generic onload by Brothercake \n// http://www.brothercake.com/\n//onload function (replaces the onload=\"translate()\" in the <body> tag)\nfunction generic()\n{\n translate();\n};\n//setup onload function\nif(typeof window.addEventListener != 'undefined')\n{\n //.. gecko, safari, konqueror and standard\n window.addEventListener('load', generic, false);\n}\nelse if(typeof document.addEventListener != 'undefined')\n{\n //.. opera 7\n document.addEventListener('load', generic, false);\n}\nelse if(typeof window.attachEvent != 'undefined')\n{\n //.. win/ie\n window.attachEvent('onload', generic);\n}\n//** remove this condition to degrade older browsers\nelse\n{\n //.. mac/ie5 and anything else that gets this far\n //if there's an existing onload function\n if(typeof window.onload == 'function')\n {\n //store it\n var existing = onload;\n //add new onload handler\n window.onload = function()\n {\n //call existing onload function\n existing();\n //call generic onload function\n generic();\n };\n }\n else\n {\n //setup onload function\n window.onload = generic;\n }\n}\n</script>\n"-
− src/Text/Pandoc/Blocks.hs
@@ -1,145 +0,0 @@-{--Copyright (C) 2007 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.Blocks- Copyright : Copyright (C) 2007 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Functions for the manipulation of fixed-width blocks of text.-These are used in the construction of plain-text tables.--}--module Text.Pandoc.Blocks- ( - TextBlock (..),- docToBlock,- blockToDoc,- widthOfBlock,- heightOfBlock,- hcatBlocks,- hsepBlocks,- centerAlignBlock,- leftAlignBlock,- rightAlignBlock- )-where-import Text.PrettyPrint-import Data.List ( intersperse )---- | A fixed-width block of text. Parameters are width of block,--- height of block, and list of lines.-data TextBlock = TextBlock Int Int [String]-instance Show TextBlock where- show x = show $ blockToDoc x---- | Break lines in a list of lines so that none are greater than--- a given width.-breakLines :: Int -- ^ Maximum length of lines.- -> [String] -- ^ List of lines.- -> [String]-breakLines width [] = []-breakLines width (l:ls) =- if length l > width- then (take width l):(breakLines width ((drop width l):ls))- else l:(breakLines width ls)---- | Convert a @Doc@ element into a @TextBlock@ with a specified width. -docToBlock :: Int -- ^ Width of text block.- -> Doc -- ^ @Doc@ to convert.- -> TextBlock-docToBlock width doc =- let rendered = renderStyle (style {lineLength = width, - ribbonsPerLine = 1}) doc- lns = breakLines width $ lines rendered- in TextBlock width (length lns) lns---- | Convert a @TextBlock@ to a @Doc@ element.-blockToDoc :: TextBlock -> Doc-blockToDoc (TextBlock _ _ lns) = - if null lns- then empty- else vcat $ map text lns---- | Returns width of a @TextBlock@ (number of columns).-widthOfBlock :: TextBlock -> Int-widthOfBlock (TextBlock width _ _) = width---- | Returns height of a @TextBlock@ (number of rows).-heightOfBlock :: TextBlock -> Int-heightOfBlock (TextBlock _ height _) = height---- | Pads a string out to a given width using spaces.-hPad :: Int -- ^ Desired width.- -> String -- ^ String to pad.- -> String-hPad width line = - let lineLength = length line- in if lineLength <= width - then line ++ replicate (width - lineLength) ' '- else take width line---- | Concatenates a list of @TextBlock@s into a new @TextBlock@ in--- which they appear side by side.-hcatBlocks :: [TextBlock] -> TextBlock-hcatBlocks [] = TextBlock 0 0 []-hcatBlocks [x] = x -- This is not redundant! We don't want last item hPad'd.-hcatBlocks ((TextBlock width1 height1 lns1):xs) = - let (TextBlock width2 height2 lns2) = hcatBlocks xs- height = max height1 height2- width = width1 + width2- lns1' = map (hPad width1) $ lns1 ++ replicate (height - height1) ""- lns2' = lns2 ++ replicate (height - height2) ""- lns = zipWith (++) lns1' lns2'- in TextBlock width height lns ---- | Like @hcatBlocks@, but inserts space between the @TextBlock@s.-hsepBlocks :: [TextBlock] -> TextBlock-hsepBlocks = hcatBlocks . (intersperse (TextBlock 1 1 [" "]))--isWhitespace x = x `elem` " \t"---- | Left-aligns the contents of a @TextBlock@ within the block.-leftAlignBlock :: TextBlock -> TextBlock-leftAlignBlock (TextBlock width height lns) =- TextBlock width height $ map (dropWhile isWhitespace) lns---- | Right-aligns the contents of a @TextBlock@ within the block.-rightAlignBlock :: TextBlock -> TextBlock-rightAlignBlock (TextBlock width height lns) =- let rightAlignLine ln = - let (spaces, rest) = span isWhitespace $ reverse $ hPad width ln- in reverse (rest ++ spaces)- in TextBlock width height $ map rightAlignLine lns---- | Centers the contents of a @TextBlock@ within the block.-centerAlignBlock :: TextBlock -> TextBlock-centerAlignBlock (TextBlock width height lns) = - let centerAlignLine ln =- let ln' = hPad width ln- (startSpaces, rest) = span isWhitespace ln'- endSpaces = takeWhile isWhitespace (reverse ln')- numSpaces = length (startSpaces ++ endSpaces)- startSpaces' = replicate (quot numSpaces 2) ' '- in startSpaces' ++ rest - in TextBlock width height $ map centerAlignLine lns-
− src/Text/Pandoc/CharacterReferences.hs
@@ -1,327 +0,0 @@-{--Copyright (C) 2006-7 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.CharacterReferences- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Functions for parsing character references.--}-module Text.Pandoc.CharacterReferences (- characterReference,- decodeCharacterReferences,- ) where-import Data.Char ( chr )-import Text.ParserCombinators.Parsec-import qualified Data.Map as Map---- | Parse character entity.-characterReference :: GenParser Char st Char-characterReference = try $ do- st <- char '&'- character <- numRef <|> entity- end <- char ';'- return character --numRef :: GenParser Char st Char-numRef = do- char '#'- num <- hexNum <|> decNum- return $ chr $ num --hexNum :: GenParser Char st Int -hexNum = oneOf "Xx" >> many1 hexDigit >>= return . read . ("0x" ++)--decNum :: GenParser Char st Int -decNum = many1 digit >>= return . read--entity :: GenParser Char st Char-entity = do- body <- many1 alphaNum- return $ Map.findWithDefault '?' body entityTable---- | Convert entities in a string to characters.-decodeCharacterReferences :: String -> String-decodeCharacterReferences str = - case parse (many (characterReference <|> anyChar)) str str of- Left err -> error $ "\nError: " ++ show err- Right result -> result--entityTable :: Map.Map String Char-entityTable = Map.fromList entityTableList--entityTableList :: [(String, Char)]-entityTableList = [- ("quot", chr 34),- ("amp", chr 38),- ("lt", chr 60),- ("gt", chr 62),- ("nbsp", chr 160),- ("iexcl", chr 161),- ("cent", chr 162),- ("pound", chr 163),- ("curren", chr 164),- ("yen", chr 165),- ("brvbar", chr 166),- ("sect", chr 167),- ("uml", chr 168),- ("copy", chr 169),- ("ordf", chr 170),- ("laquo", chr 171),- ("not", chr 172),- ("shy", chr 173),- ("reg", chr 174),- ("macr", chr 175),- ("deg", chr 176),- ("plusmn", chr 177),- ("sup2", chr 178),- ("sup3", chr 179),- ("acute", chr 180),- ("micro", chr 181),- ("para", chr 182),- ("middot", chr 183),- ("cedil", chr 184),- ("sup1", chr 185),- ("ordm", chr 186),- ("raquo", chr 187),- ("frac14", chr 188),- ("frac12", chr 189),- ("frac34", chr 190),- ("iquest", chr 191),- ("Agrave", chr 192),- ("Aacute", chr 193),- ("Acirc", chr 194),- ("Atilde", chr 195),- ("Auml", chr 196),- ("Aring", chr 197),- ("AElig", chr 198),- ("Ccedil", chr 199),- ("Egrave", chr 200),- ("Eacute", chr 201),- ("Ecirc", chr 202),- ("Euml", chr 203),- ("Igrave", chr 204),- ("Iacute", chr 205),- ("Icirc", chr 206),- ("Iuml", chr 207),- ("ETH", chr 208),- ("Ntilde", chr 209),- ("Ograve", chr 210),- ("Oacute", chr 211),- ("Ocirc", chr 212),- ("Otilde", chr 213),- ("Ouml", chr 214),- ("times", chr 215),- ("Oslash", chr 216),- ("Ugrave", chr 217),- ("Uacute", chr 218),- ("Ucirc", chr 219),- ("Uuml", chr 220),- ("Yacute", chr 221),- ("THORN", chr 222),- ("szlig", chr 223),- ("agrave", chr 224),- ("aacute", chr 225),- ("acirc", chr 226),- ("atilde", chr 227),- ("auml", chr 228),- ("aring", chr 229),- ("aelig", chr 230),- ("ccedil", chr 231),- ("egrave", chr 232),- ("eacute", chr 233),- ("ecirc", chr 234),- ("euml", chr 235),- ("igrave", chr 236),- ("iacute", chr 237),- ("icirc", chr 238),- ("iuml", chr 239),- ("eth", chr 240),- ("ntilde", chr 241),- ("ograve", chr 242),- ("oacute", chr 243),- ("ocirc", chr 244),- ("otilde", chr 245),- ("ouml", chr 246),- ("divide", chr 247),- ("oslash", chr 248),- ("ugrave", chr 249),- ("uacute", chr 250),- ("ucirc", chr 251),- ("uuml", chr 252),- ("yacute", chr 253),- ("thorn", chr 254),- ("yuml", chr 255),- ("OElig", chr 338),- ("oelig", chr 339),- ("Scaron", chr 352),- ("scaron", chr 353),- ("Yuml", chr 376),- ("fnof", chr 402),- ("circ", chr 710),- ("tilde", chr 732),- ("Alpha", chr 913),- ("Beta", chr 914),- ("Gamma", chr 915),- ("Delta", chr 916),- ("Epsilon", chr 917),- ("Zeta", chr 918),- ("Eta", chr 919),- ("Theta", chr 920),- ("Iota", chr 921),- ("Kappa", chr 922),- ("Lambda", chr 923),- ("Mu", chr 924),- ("Nu", chr 925),- ("Xi", chr 926),- ("Omicron", chr 927),- ("Pi", chr 928),- ("Rho", chr 929),- ("Sigma", chr 931),- ("Tau", chr 932),- ("Upsilon", chr 933),- ("Phi", chr 934),- ("Chi", chr 935),- ("Psi", chr 936),- ("Omega", chr 937),- ("alpha", chr 945),- ("beta", chr 946),- ("gamma", chr 947),- ("delta", chr 948),- ("epsilon", chr 949),- ("zeta", chr 950),- ("eta", chr 951),- ("theta", chr 952),- ("iota", chr 953),- ("kappa", chr 954),- ("lambda", chr 955),- ("mu", chr 956),- ("nu", chr 957),- ("xi", chr 958),- ("omicron", chr 959),- ("pi", chr 960),- ("rho", chr 961),- ("sigmaf", chr 962),- ("sigma", chr 963),- ("tau", chr 964),- ("upsilon", chr 965),- ("phi", chr 966),- ("chi", chr 967),- ("psi", chr 968),- ("omega", chr 969),- ("thetasym", chr 977),- ("upsih", chr 978),- ("piv", chr 982),- ("ensp", chr 8194),- ("emsp", chr 8195),- ("thinsp", chr 8201),- ("zwnj", chr 8204),- ("zwj", chr 8205),- ("lrm", chr 8206),- ("rlm", chr 8207),- ("ndash", chr 8211),- ("mdash", chr 8212),- ("lsquo", chr 8216),- ("rsquo", chr 8217),- ("sbquo", chr 8218),- ("ldquo", chr 8220),- ("rdquo", chr 8221),- ("bdquo", chr 8222),- ("dagger", chr 8224),- ("Dagger", chr 8225),- ("bull", chr 8226),- ("hellip", chr 8230),- ("permil", chr 8240),- ("prime", chr 8242),- ("Prime", chr 8243),- ("lsaquo", chr 8249),- ("rsaquo", chr 8250),- ("oline", chr 8254),- ("frasl", chr 8260),- ("euro", chr 8364),- ("image", chr 8465),- ("weierp", chr 8472),- ("real", chr 8476),- ("trade", chr 8482),- ("alefsym", chr 8501),- ("larr", chr 8592),- ("uarr", chr 8593),- ("rarr", chr 8594),- ("darr", chr 8595),- ("harr", chr 8596),- ("crarr", chr 8629),- ("lArr", chr 8656),- ("uArr", chr 8657),- ("rArr", chr 8658),- ("dArr", chr 8659),- ("hArr", chr 8660),- ("forall", chr 8704),- ("part", chr 8706),- ("exist", chr 8707),- ("empty", chr 8709),- ("nabla", chr 8711),- ("isin", chr 8712),- ("notin", chr 8713),- ("ni", chr 8715),- ("prod", chr 8719),- ("sum", chr 8721),- ("minus", chr 8722),- ("lowast", chr 8727),- ("radic", chr 8730),- ("prop", chr 8733),- ("infin", chr 8734),- ("ang", chr 8736),- ("and", chr 8743),- ("or", chr 8744),- ("cap", chr 8745),- ("cup", chr 8746),- ("int", chr 8747),- ("there4", chr 8756),- ("sim", chr 8764),- ("cong", chr 8773),- ("asymp", chr 8776),- ("ne", chr 8800),- ("equiv", chr 8801),- ("le", chr 8804),- ("ge", chr 8805),- ("sub", chr 8834),- ("sup", chr 8835),- ("nsub", chr 8836),- ("sube", chr 8838),- ("supe", chr 8839),- ("oplus", chr 8853),- ("otimes", chr 8855),- ("perp", chr 8869),- ("sdot", chr 8901),- ("lceil", chr 8968),- ("rceil", chr 8969),- ("lfloor", chr 8970),- ("rfloor", chr 8971),- ("lang", chr 9001),- ("rang", chr 9002),- ("loz", chr 9674),- ("spades", chr 9824),- ("clubs", chr 9827),- ("hearts", chr 9829),- ("diams", chr 9830)- ]
− src/Text/Pandoc/Definition.hs
@@ -1,116 +0,0 @@-{--Copyright (C) 2006-7 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.Definition- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Definition of 'Pandoc' data structure for format-neutral representation-of documents.--}-module Text.Pandoc.Definition where--data Pandoc = Pandoc Meta [Block] deriving (Eq, Read, Show)---- | Bibliographic information for the document: title (list of 'Inline'),--- authors (list of strings), date (string).-data Meta = Meta [Inline] -- title- [String] -- authors- String -- date- deriving (Eq, Show, Read)---- | Alignment of a table column.-data Alignment = AlignLeft - | AlignRight - | AlignCenter - | AlignDefault deriving (Eq, Show, Read)---- | List attributes.-type ListAttributes = (Int, ListNumberStyle, ListNumberDelim)---- | Style of list numbers.-data ListNumberStyle = DefaultStyle- | Decimal - | LowerRoman - | UpperRoman- | LowerAlpha - | UpperAlpha deriving (Eq, Show, Read)---- | Delimiter of list numbers.-data ListNumberDelim = DefaultDelim- | Period- | OneParen - | TwoParens deriving (Eq, Show, Read)- --- | Block element.-data Block - = Plain [Inline] -- ^ Plain text, not a paragraph- | Para [Inline] -- ^ Paragraph- | CodeBlock String -- ^ Code block (literal)- | RawHtml String -- ^ Raw HTML block (literal)- | BlockQuote [Block] -- ^ Block quote (list of blocks)- | OrderedList ListAttributes [[Block]] -- ^ Ordered list (attributes- -- and a list of items, each a list of blocks)- | BulletList [[Block]] -- ^ Bullet list (list of items, each- -- a list of blocks)- | DefinitionList [([Inline],[Block])] -- ^ Definition list - -- (list of items, each a pair of an inline list,- -- the term, and a block list)- | Header Int [Inline] -- ^ Header - level (integer) and text (inlines) - | HorizontalRule -- ^ Horizontal rule- | Table [Inline] [Alignment] [Float] [[Block]] [[[Block]]] -- ^ Table,- -- with caption, column alignments,- -- relative column widths, column headers- -- (each a list of blocks), and rows- -- (each a list of lists of blocks)- | Null -- ^ Nothing- deriving (Eq, Read, Show)---- | Type of quotation marks to use in Quoted inline.-data QuoteType = SingleQuote | DoubleQuote deriving (Show, Eq, Read)--type Target = (String, String) -- ^ Link target (URL, title)---- | Inline elements.-data Inline - = Str String -- ^ Text (string)- | Emph [Inline] -- ^ Emphasized text (list of inlines)- | Strong [Inline] -- ^ Strongly emphasized text (list of inlines)- | Strikeout [Inline] -- ^ Strikeout text (list of inlines)- | Superscript [Inline] -- ^ Superscripted text (list of inlines)- | Subscript [Inline] -- ^ Subscripted text (list of inlines)- | Quoted QuoteType [Inline] -- ^ Quoted text (list of inlines)- | Code String -- ^ Inline code (literal)- | Space -- ^ Inter-word space- | EmDash -- ^ Em dash- | EnDash -- ^ En dash- | Apostrophe -- ^ Apostrophe- | Ellipses -- ^ Ellipses- | LineBreak -- ^ Hard line break- | TeX String -- ^ LaTeX code (literal)- | HtmlInline String -- ^ HTML code (literal)- | Link [Inline] Target -- ^ Hyperlink: text (list of inlines), target- | Image [Inline] Target -- ^ Image: alt text (list of inlines), target- -- and target- | Note [Block] -- ^ Footnote or endnote - deriving (Show, Eq, Read)
− src/Text/Pandoc/Readers/HTML.hs
@@ -1,499 +0,0 @@-{--Copyright (C) 2006-7 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.Readers.HTML- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha - Portability : portable--Conversion of HTML to 'Pandoc' document.--}-module Text.Pandoc.Readers.HTML ( - readHtml, - rawHtmlInline, - rawHtmlBlock, - anyHtmlBlockTag, - anyHtmlInlineTag, - anyHtmlTag,- anyHtmlEndTag,- htmlEndTag,- extractTagType,- htmlBlockElement - ) where--import Text.ParserCombinators.Parsec-import Text.Pandoc.Definition-import Text.Pandoc.Shared -import Text.Pandoc.CharacterReferences ( characterReference, - decodeCharacterReferences )-import Data.Maybe ( fromMaybe )-import Data.List ( takeWhile, dropWhile )-import Data.Char ( toUpper, toLower, isAlphaNum )---- | Convert HTML-formatted string to 'Pandoc' document.-readHtml :: ParserState -- ^ Parser state- -> String -- ^ String to parse- -> Pandoc-readHtml = readWith parseHtml------- Constants-----eitherBlockOrInline = ["applet", "button", "del", "iframe", "ins",- "map", "area", "object", "script"]--inlineHtmlTags = ["a", "abbr", "acronym", "b", "basefont", "bdo", "big",- "br", "cite", "code", "dfn", "em", "font", "i", "img",- "input", "kbd", "label", "q", "s", "samp", "select",- "small", "span", "strike", "strong", "sub", "sup",- "textarea", "tt", "u", "var"] ++ eitherBlockOrInline--blockHtmlTags = ["address", "blockquote", "center", "dir", "div",- "dl", "fieldset", "form", "h1", "h2", "h3", "h4",- "h5", "h6", "hr", "isindex", "menu", "noframes",- "noscript", "ol", "p", "pre", "table", "ul", "dd",- "dt", "frameset", "li", "tbody", "td", "tfoot",- "th", "thead", "tr"] ++ eitherBlockOrInline------- HTML utility functions------- | Read blocks until end tag.-blocksTilEnd tag = do- blocks <- manyTill (block >>~ spaces) (htmlEndTag tag)- return $ filter (/= Null) blocks---- | Read inlines until end tag.-inlinesTilEnd tag = manyTill inline (htmlEndTag tag)---- | Parse blocks between open and close tag.-blocksIn tag = try $ htmlTag tag >> spaces >> blocksTilEnd tag---- | Parse inlines between open and close tag.-inlinesIn tag = try $ htmlTag tag >> spaces >> inlinesTilEnd tag---- | Extract type from a tag: e.g. @br@ from @\<br\>@-extractTagType :: String -> String-extractTagType ('<':rest) = - let isSpaceOrSlash c = c `elem` "/ \n\t" in- map toLower $ takeWhile isAlphaNum $ dropWhile isSpaceOrSlash rest-extractTagType _ = ""---- | Parse any HTML tag (closing or opening) and return text of tag-anyHtmlTag = try $ do- char '<'- spaces- tag <- many1 alphaNum- attribs <- htmlAttributes- spaces- ender <- option "" (string "/")- let ender' = if null ender then "" else " /"- spaces- char '>'- return $ "<" ++ tag ++ attribs ++ ender' ++ ">"--anyHtmlEndTag = try $ do- char '<' - spaces- char '/'- spaces- tagType <- many1 alphaNum- spaces- char '>'- return $ "</" ++ tagType ++ ">"--htmlTag :: String -> GenParser Char st (String, [(String, String)])-htmlTag tag = try $ do- char '<'- spaces- stringAnyCase tag- attribs <- many htmlAttribute- spaces- optional (string "/")- spaces- char '>'- return (tag, (map (\(name, content, raw) -> (name, content)) attribs))---- parses a quoted html attribute value-quoted quoteChar = do- result <- between (char quoteChar) (char quoteChar) - (many (noneOf [quoteChar]))- return (result, [quoteChar])--htmlAttributes = do- attrList <- many htmlAttribute- return $ concatMap (\(name, content, raw) -> raw) attrList--htmlAttribute = htmlRegularAttribute <|> htmlMinimizedAttribute---- minimized boolean attribute-htmlMinimizedAttribute = try $ do- many1 space- name <- many1 (choice [letter, oneOf ".-_:"])- spaces- notFollowedBy (char '=')- let content = name- return (name, content, (" " ++ name))--htmlRegularAttribute = try $ do- many1 space- name <- many1 (choice [letter, oneOf ".-_:"])- spaces- char '='- spaces- (content, quoteStr) <- choice [ (quoted '\''), - (quoted '"'), - (do- a <- many (alphaNum <|> (oneOf "-._:"))- return (a,"")) ]- return (name, content,- (" " ++ name ++ "=" ++ quoteStr ++ content ++ quoteStr))---- | Parse an end tag of type 'tag'-htmlEndTag tag = try $ do- char '<' - spaces- char '/'- spaces- stringAnyCase tag- spaces- char '>'- return $ "</" ++ tag ++ ">"---- | Returns @True@ if the tag is (or can be) an inline tag.-isInline tag = (extractTagType tag) `elem` inlineHtmlTags---- | Returns @True@ if the tag is (or can be) a block tag.-isBlock tag = (extractTagType tag) `elem` blockHtmlTags --anyHtmlBlockTag = try $ do- tag <- anyHtmlTag <|> anyHtmlEndTag- if isBlock tag then return tag else fail "inline tag"--anyHtmlInlineTag = try $ do- tag <- anyHtmlTag <|> anyHtmlEndTag- if isInline tag then return tag else fail "not an inline tag"---- | Parses material between script tags.--- Scripts must be treated differently, because they can contain '<>' etc.-htmlScript = try $ do- open <- string "<script"- rest <- manyTill anyChar (htmlEndTag "script")- return $ open ++ rest ++ "</script>"--htmlBlockElement = choice [ htmlScript, htmlComment, xmlDec, definition ]--rawHtmlBlock = try $ do- notFollowedBy' (htmlTag "/body" <|> htmlTag "/html")- body <- htmlBlockElement <|> anyHtmlTag <|> anyHtmlEndTag- sp <- many space- state <- getState- if stateParseRaw state then return (RawHtml (body ++ sp)) else return Null---- | Parses an HTML comment.-htmlComment = try $ do- string "<!--"- comment <- manyTill anyChar (try (string "-->"))- return $ "<!--" ++ comment ++ "-->"------- parsing documents-----xmlDec = try $ do- string "<?"- rest <- manyTill anyChar (char '>')- return $ "<?" ++ rest ++ ">"--definition = try $ do- string "<!"- rest <- manyTill anyChar (char '>')- return $ "<!" ++ rest ++ ">"--nonTitleNonHead = try $ notFollowedBy' (htmlTag "title" <|> htmlTag "/head") >>- ((rawHtmlBlock >> return ' ') <|> anyChar)--parseTitle = try $ do- (tag, _) <- htmlTag "title"- contents <- inlinesTilEnd tag- spaces- return contents---- parse header and return meta-information (for now, just title)-parseHead = try $ do- htmlTag "head"- spaces- skipMany nonTitleNonHead- contents <- option [] parseTitle- skipMany nonTitleNonHead- htmlTag "/head"- return (contents, [], "")--skipHtmlTag tag = optional (htmlTag tag)---- h1 class="title" representation of title in body-bodyTitle = try $ do- (tag, attribs) <- htmlTag "h1" - cl <- case (extractAttribute "class" attribs) of- Just "title" -> return ""- otherwise -> fail "not title"- inlinesTilEnd "h1"--parseHtml = do- sepEndBy (choice [xmlDec, definition, htmlComment]) spaces- skipHtmlTag "html"- spaces- (title, authors, date) <- option ([], [], "") parseHead - spaces- skipHtmlTag "body"- spaces- optional bodyTitle -- skip title in body, because it's represented in meta- blocks <- parseBlocks- spaces- optional (htmlEndTag "body")- spaces- optional (htmlEndTag "html" >> many anyChar) -- ignore anything after </html>- eof- return $ Pandoc (Meta title authors date) blocks------- parsing blocks-----parseBlocks = spaces >> sepEndBy block spaces >>= (return . filter (/= Null))--block = choice [ codeBlock- , header- , hrule- , list- , blockQuote- , para- , plain- , rawHtmlBlock ] <?> "block"------- header blocks-----header = choice (map headerLevel (enumFromTo 1 5)) <?> "header"--headerLevel n = try $ do- let level = "h" ++ show n- (tag, attribs) <- htmlTag level- contents <- inlinesTilEnd level- return $ Header n (normalizeSpaces contents)------- hrule block-----hrule = try $ do- (tag, attribs) <- htmlTag "hr"- state <- getState- if not (null attribs) && stateParseRaw state- then unexpected "attributes in hr" -- parse as raw in this case- else return HorizontalRule------- code blocks-----codeBlock = preCodeBlock <|> bareCodeBlock <?> "code block"--preCodeBlock = try $ do- htmlTag "pre" - spaces- result <- bareCodeBlock- spaces- htmlEndTag "pre"- return result--bareCodeBlock = try $ do- htmlTag "code"- result <- manyTill anyChar (htmlEndTag "code")- return $ CodeBlock $ stripTrailingNewlines $ - decodeCharacterReferences result------- block quotes-----blockQuote = try $ htmlTag "blockquote" >> spaces >> - blocksTilEnd "blockquote" >>= (return . BlockQuote)------- list blocks-----list = choice [ bulletList, orderedList, definitionList ] <?> "list"--orderedList = try $ do- (_, attribs) <- htmlTag "ol"- (start, style) <- option (1, DefaultStyle) $- do failIfStrict- let sta = fromMaybe "1" $ - lookup "start" attribs- let sty = fromMaybe (fromMaybe "" $- lookup "style" attribs) $- lookup "class" attribs- let sty' = case sty of- "lower-roman" -> LowerRoman- "upper-roman" -> UpperRoman- "lower-alpha" -> LowerAlpha- "upper-alpha" -> UpperAlpha- "decimal" -> Decimal- _ -> DefaultStyle- return (read sta, sty')- spaces- items <- sepEndBy1 (blocksIn "li") spaces- htmlEndTag "ol"- return $ OrderedList (start, style, DefaultDelim) items--bulletList = try $ do- htmlTag "ul"- spaces- items <- sepEndBy1 (blocksIn "li") spaces- htmlEndTag "ul"- return $ BulletList items--definitionList = try $ do- failIfStrict -- def lists not part of standard markdown- tag <- htmlTag "dl"- spaces- items <- sepEndBy1 definitionListItem spaces- htmlEndTag "dl"- return $ DefinitionList items--definitionListItem = try $ do- terms <- sepEndBy1 (inlinesIn "dt") spaces- defs <- sepEndBy1 (blocksIn "dd") spaces- let term = joinWithSep [LineBreak] terms- return (term, concat defs)------- paragraph block-----para = try $ htmlTag "p" >> inlinesTilEnd "p" >>= - return . Para . normalizeSpaces---- --- plain block-----plain = many1 inline >>= return . Plain . normalizeSpaces---- --- inline-----inline = choice [ charRef- , strong- , emph- , superscript- , subscript- , strikeout- , spanStrikeout- , code- , str- , linebreak- , whitespace- , link- , image- , rawHtmlInline- ] <?> "inline"--code = try $ do - htmlTag "code"- result <- manyTill anyChar (htmlEndTag "code")- -- remove internal line breaks, leading and trailing space,- -- and decode character references- return $ Code $ decodeCharacterReferences $ removeLeadingTrailingSpace $ - joinWithSep " " $ lines result --rawHtmlInline = do- result <- htmlScript <|> htmlComment <|> anyHtmlInlineTag- state <- getState- if stateParseRaw state then return (HtmlInline result) else return (Str "")--betweenTags tag = try $ htmlTag tag >> inlinesTilEnd tag >>= - return . normalizeSpaces--emph = (betweenTags "em" <|> betweenTags "it") >>= return . Emph--strong = (betweenTags "b" <|> betweenTags "strong") >>= return . Strong--superscript = failIfStrict >> betweenTags "sup" >>= return . Superscript--subscript = failIfStrict >> betweenTags "sub" >>= return . Subscript--strikeout = failIfStrict >> (betweenTags "s" <|> betweenTags "strike") >>=- return . Strikeout--spanStrikeout = try $ do- failIfStrict -- strict markdown has no strikeout, so treat as raw HTML- (tag, attributes) <- htmlTag "span" - result <- case (extractAttribute "class" attributes) of- Just "strikeout" -> inlinesTilEnd "span"- _ -> fail "not a strikeout"- return $ Strikeout result--whitespace = many1 space >> return Space---- hard line break-linebreak = htmlTag "br" >> optional newline >> return LineBreak--str = many1 (noneOf "<& \t\n") >>= return . Str------- links and images------- extract contents of attribute (attribute names are case-insensitive)-extractAttribute name [] = Nothing-extractAttribute name ((attrName, contents):rest) = - let name' = map toLower name - attrName' = map toLower attrName- in if attrName' == name'- then Just (decodeCharacterReferences contents)- else extractAttribute name rest--link = try $ do- (tag, attributes) <- htmlTag "a" - url <- case (extractAttribute "href" attributes) of- Just url -> return url- Nothing -> fail "no href"- let title = fromMaybe "" $ extractAttribute "title" attributes- label <- inlinesTilEnd "a"- return $ Link (normalizeSpaces label) (url, title)--image = try $ do- (tag, attributes) <- htmlTag "img" - url <- case (extractAttribute "src" attributes) of- Just url -> return url- Nothing -> fail "no src"- let title = fromMaybe "" $ extractAttribute "title" attributes- let alt = fromMaybe "" (extractAttribute "alt" attributes)- return $ Image [Str alt] (url, title)-
− src/Text/Pandoc/Readers/LaTeX.hs
@@ -1,649 +0,0 @@-{--Copyright (C) 2006-7 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.Readers.LaTeX- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion of LaTeX to 'Pandoc' document.--}-module Text.Pandoc.Readers.LaTeX ( - readLaTeX,- rawLaTeXInline,- rawLaTeXEnvironment- ) where--import Text.ParserCombinators.Parsec-import Text.Pandoc.Definition-import Text.Pandoc.Shared -import Data.Maybe ( fromMaybe )-import Data.Char ( chr )-import Data.List ( isPrefixOf, isSuffixOf )---- | Parse LaTeX from string and return 'Pandoc' document.-readLaTeX :: ParserState -- ^ Parser state, including options for parser- -> String -- ^ String to parse- -> Pandoc-readLaTeX = readWith parseLaTeX---- characters with special meaning-specialChars = "\\`$%^&_~#{}\n \t|<>'\"-"------- utility functions------- | Returns text between brackets and its matching pair.-bracketedText openB closeB = do- result <- charsInBalanced' openB closeB- return $ [openB] ++ result ++ [closeB]---- | Returns an option or argument of a LaTeX command.-optOrArg = bracketedText '{' '}' <|> bracketedText '[' ']'---- | True if the string begins with '{'.-isArg ('{':rest) = True-isArg other = False---- | Returns list of options and arguments of a LaTeX command.-commandArgs = many optOrArg---- | Parses LaTeX command, returns (name, star, list of options or arguments).-command = do- char '\\'- name <- many1 letter- star <- option "" (string "*") -- some commands have starred versions- args <- commandArgs- return (name, star, args)--begin name = try $ do- string $ "\\begin{" ++ name ++ "}"- optional commandArgs- spaces- return name--end name = try $ do- string $ "\\end{" ++ name ++ "}"- spaces- return name---- | Returns a list of block elements containing the contents of an--- environment.-environment name = try $ begin name >> spaces >> manyTill block (end name)--anyEnvironment = try $ do- string "\\begin{"- name <- many letter- star <- option "" (string "*") -- some environments have starred variants- char '}'- optional commandArgs- spaces- contents <- manyTill block (end (name ++ star))- return $ BlockQuote contents------- parsing documents------- | Process LaTeX preamble, extracting metadata.-processLaTeXPreamble = try $ manyTill - (choice [bibliographic, comment, unknownCommand, nullBlock]) - (try (string "\\begin{document}")) >> - spaces---- | Parse LaTeX and return 'Pandoc'.-parseLaTeX = do- optional processLaTeXPreamble -- preamble might not be present (fragment)- spaces- blocks <- parseBlocks- spaces- optional $ try (string "\\end{document}" >> many anyChar) - -- might not be present (fragment)- spaces- eof- state <- getState- let blocks' = filter (/= Null) blocks- let title' = stateTitle state- let authors' = stateAuthors state- let date' = stateDate state- return $ Pandoc (Meta title' authors' date') blocks'------- parsing blocks-----parseBlocks = spaces >> many block--block = choice [ hrule- , codeBlock- , header- , list- , blockQuote- , mathBlock- , comment- , bibliographic- , para- , specialEnvironment- , itemBlock- , unknownEnvironment- , unknownCommand ] <?> "block"------- header blocks-----header = try $ do- char '\\'- subs <- many (try (string "sub"))- string "section"- optional (char '*')- char '{'- title <- manyTill inline (char '}')- spaces- return $ Header (length subs + 1) (normalizeSpaces title)------- hrule block-----hrule = oneOfStrings [ "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n\n", - "\\newpage" ] >> spaces >> return HorizontalRule------- code blocks-----codeBlock = codeBlock1 <|> codeBlock2--codeBlock1 = try $ do- string "\\begin{verbatim}" -- don't use begin function because it - -- gobbles whitespace- optional blanklines -- we want to gobble blank lines, but not - -- leading space- contents <- manyTill anyChar (try (string "\\end{verbatim}"))- spaces- return $ CodeBlock (stripTrailingNewlines contents)--codeBlock2 = try $ do- string "\\begin{Verbatim}" -- used by fancyvrb package- option "" blanklines- contents <- manyTill anyChar (try (string "\\end{Verbatim}"))- spaces- return $ CodeBlock (stripTrailingNewlines contents)------- block quotes-----blockQuote = (environment "quote" <|> environment "quotation") >>~ spaces >>= - return . BlockQuote------- math block-----mathBlock = mathBlockWith (begin "equation") (end "equation") <|> - mathBlockWith (begin "displaymath") (end "displaymath") <|>- mathBlockWith (string "\\[") (string "\\]") <?> "math block"--mathBlockWith start end = try $ do- start- spaces- result <- manyTill anyChar end- spaces- return $ BlockQuote [Para [TeX ("$" ++ result ++ "$")]]------- list blocks-----list = bulletList <|> orderedList <|> definitionList <?> "list"--listItem = try $ do- ("item", _, args) <- command- spaces- state <- getState- let oldParserContext = stateParserContext state- updateState (\state -> state {stateParserContext = ListItemState})- blocks <- many block- updateState (\state -> state {stateParserContext = oldParserContext})- opt <- case args of- ([x]) | "[" `isPrefixOf` x && "]" `isSuffixOf` x -> - parseFromString (many inline) $ tail $ init x- _ -> return []- return (opt, blocks)--orderedList = try $ do- string "\\begin{enumerate}"- (_, style, delim) <- option (1, DefaultStyle, DefaultDelim) $- try $ do failIfStrict- char '['- res <- anyOrderedListMarker- char ']'- return res- spaces- option "" $ try $ do string "\\setlength{\\itemindent}"- char '{'- manyTill anyChar (char '}')- spaces- start <- option 1 $ try $ do failIfStrict- string "\\setcounter{enum"- many1 (oneOf "iv")- string "}{"- num <- many1 digit- char '}' - spaces- return $ (read num) + 1- items <- many listItem- end "enumerate"- spaces- return $ OrderedList (start, style, delim) $ map snd items--bulletList = try $ do- begin "itemize"- spaces- items <- many listItem- end "itemize"- spaces- return (BulletList $ map snd items)--definitionList = try $ do- begin "description"- spaces- items <- many listItem- end "description"- spaces- return (DefinitionList items)------- paragraph block-----para = many1 inline >>~ spaces >>= return . Para . normalizeSpaces------- title authors date-----bibliographic = choice [ maketitle, title, authors, date ]--maketitle = try (string "\\maketitle") >> spaces >> return Null--title = try $ do- string "\\title{"- tit <- manyTill inline (char '}')- spaces- updateState (\state -> state { stateTitle = tit })- return Null--authors = try $ do- string "\\author{"- authors <- manyTill anyChar (char '}')- spaces- let authors' = map removeLeadingTrailingSpace $ lines $- substitute "\\\\" "\n" authors- updateState (\state -> state { stateAuthors = authors' })- return Null--date = try $ do- string "\\date{"- date' <- manyTill anyChar (char '}')- spaces- updateState (\state -> state { stateDate = date' })- return Null------- item block--- for use in unknown environments that aren't being parsed as raw latex------- this forces items to be parsed in different blocks-itemBlock = try $ do- ("item", _, args) <- command- state <- getState- if (stateParserContext state == ListItemState)- then fail "item should be handled by list block"- else if null args - then return Null- else return $ Plain [Str (stripFirstAndLast (head args))]------- raw LaTeX -----specialEnvironment = do -- these are always parsed as raw- lookAhead (choice (map (\name -> begin name) ["tabular", "figure",- "tabbing", "eqnarry", "picture", "table", "verse", "theorem"]))- rawLaTeXEnvironment---- | Parse any LaTeX environment and return a Para block containing--- the whole literal environment as raw TeX.-rawLaTeXEnvironment :: GenParser Char st Block-rawLaTeXEnvironment = try $ do- string "\\begin{"- name <- many1 letter- star <- option "" (string "*") -- for starred variants- let name' = name ++ star- char '}'- args <- option [] commandArgs- let argStr = concat args- contents <- manyTill (choice [ (many1 (noneOf "\\")), - (do - (Para [TeX str]) <- rawLaTeXEnvironment- return str),- string "\\" ]) - (end name')- spaces- return $ Para [TeX $ "\\begin{" ++ name' ++ "}" ++ argStr ++ - concat contents ++ "\\end{" ++ name' ++ "}"]--unknownEnvironment = try $ do- state <- getState- result <- if stateParseRaw state -- check whether we should include raw TeX - then rawLaTeXEnvironment -- if so, get whole raw environment- else anyEnvironment -- otherwise just the contents- return result--unknownCommand = try $ do- notFollowedBy' $ choice $ map end ["itemize", "enumerate", "description", - "document"]- (name, star, args) <- command- spaces- let argStr = concat args- state <- getState- if name == "item" && (stateParserContext state) == ListItemState- then fail "should not be parsed as raw"- else string ""- if stateParseRaw state- then return $ Plain [TeX ("\\" ++ name ++ star ++ argStr)]- else return $ Plain [Str (joinWithSep " " args)]---- latex comment-comment = try $ char '%' >> manyTill anyChar newline >> spaces >> return Null---- --- inline-----inline = choice [ str- , endline- , whitespace- , quoted- , apostrophe- , spacer- , strong- , math- , ellipses- , emDash- , enDash- , hyphen- , emph- , strikeout- , superscript- , subscript- , ref- , lab- , code- , url- , link- , image- , footnote- , linebreak- , accentedChar- , specialChar- , rawLaTeXInline- , escapedChar- , unescapedChar- ] <?> "inline"--accentedChar = normalAccentedChar <|> specialAccentedChar--normalAccentedChar = try $ do- char '\\'- accent <- oneOf "'`^\"~"- character <- (try $ char '{' >> letter >>~ char '}') <|> letter- let table = fromMaybe [] $ lookup character accentTable - let result = case lookup accent table of- Just num -> chr num- Nothing -> '?'- return $ Str [result]---- an association list of letters and association list of accents--- and decimal character numbers.-accentTable = - [ ('A', [('`', 192), ('\'', 193), ('^', 194), ('~', 195), ('"', 196)]),- ('E', [('`', 200), ('\'', 201), ('^', 202), ('"', 203)]),- ('I', [('`', 204), ('\'', 205), ('^', 206), ('"', 207)]),- ('N', [('~', 209)]),- ('O', [('`', 210), ('\'', 211), ('^', 212), ('~', 213), ('"', 214)]),- ('U', [('`', 217), ('\'', 218), ('^', 219), ('"', 220)]),- ('a', [('`', 224), ('\'', 225), ('^', 227), ('"', 228)]),- ('e', [('`', 232), ('\'', 233), ('^', 234), ('"', 235)]),- ('i', [('`', 236), ('\'', 237), ('^', 238), ('"', 239)]),- ('n', [('~', 241)]),- ('o', [('`', 242), ('\'', 243), ('^', 244), ('~', 245), ('"', 246)]),- ('u', [('`', 249), ('\'', 250), ('^', 251), ('"', 252)]) ]--specialAccentedChar = choice [ ccedil, aring, iuml, szlig, aelig,- oslash, pound, euro, copyright, sect ]--ccedil = try $ do- char '\\'- letter <- oneOfStrings ["cc", "cC"]- let num = if letter == "cc" then 231 else 199- return $ Str [chr num]--aring = try $ do- char '\\'- letter <- oneOfStrings ["aa", "AA"]- let num = if letter == "aa" then 229 else 197- return $ Str [chr num]--iuml = try (string "\\\"") >> oneOfStrings ["\\i", "{\\i}"] >> - return (Str [chr 239])--icirc = try (string "\\^") >> oneOfStrings ["\\i", "{\\i}"] >>- return (Str [chr 238])--szlig = try (string "\\ss") >> return (Str [chr 223])--oslash = try $ do- char '\\'- letter <- choice [char 'o', char 'O']- let num = if letter == 'o' then 248 else 216- return $ Str [chr num]--aelig = try $ do- char '\\'- letter <- oneOfStrings ["ae", "AE"]- let num = if letter == "ae" then 230 else 198- return $ Str [chr num]--pound = try (string "\\pounds") >> return (Str [chr 163])--euro = try (string "\\euro") >> return (Str [chr 8364])--copyright = try (string "\\copyright") >> return (Str [chr 169])--sect = try (string "\\S") >> return (Str [chr 167])--escapedChar = do- result <- escaped (oneOf " $%&_#{}\n")- return $ if result == Str "\n" then Str " " else result---- ignore standalone, nonescaped special characters-unescapedChar = oneOf "`$^&_#{}|<>" >> return (Str "")--specialChar = choice [ backslash, tilde, caret, bar, lt, gt ]--backslash = try (string "\\textbackslash") >> return (Str "\\")--tilde = try (string "\\ensuremath{\\sim}") >> return (Str "~")--caret = try (string "\\^{}") >> return (Str "^")--bar = try (string "\\textbar") >> return (Str "\\")--lt = try (string "\\textless") >> return (Str "<")--gt = try (string "\\textgreater") >> return (Str ">")--code = code1 <|> code2--code1 = try $ do - string "\\verb"- marker <- anyChar- result <- manyTill anyChar (char marker)- return $ Code $ removeLeadingTrailingSpace result--code2 = try $ do- string "\\texttt{"- result <- manyTill (noneOf "\\\n~$%^&{}") (char '}')- return $ Code result--emph = try $ oneOfStrings [ "\\emph{", "\\textit{" ] >>- manyTill inline (char '}') >>= return . Emph--strikeout = try $ string "\\sout{" >> manyTill inline (char '}') >>=- return . Strikeout--superscript = try $ string "\\textsuperscript{" >> - manyTill inline (char '}') >>= return . Superscript---- note: \textsubscript isn't a standard latex command, but we use--- a defined version in pandoc.-subscript = try $ string "\\textsubscript{" >> manyTill inline (char '}') >>=- return . Subscript--apostrophe = char '\'' >> return Apostrophe--quoted = doubleQuoted <|> singleQuoted--singleQuoted = enclosed singleQuoteStart singleQuoteEnd inline >>=- return . Quoted SingleQuote . normalizeSpaces--doubleQuoted = enclosed doubleQuoteStart doubleQuoteEnd inline >>=- return . Quoted DoubleQuote . normalizeSpaces--singleQuoteStart = char '`'--singleQuoteEnd = try $ char '\'' >> notFollowedBy alphaNum--doubleQuoteStart = string "``"--doubleQuoteEnd = try $ string "''"--ellipses = try $ string "\\ldots" >> optional (try (string "{}")) >>- return Ellipses--enDash = try (string "--") >> return EnDash--emDash = try (string "---") >> return EmDash--hyphen = char '-' >> return (Str "-")--lab = try $ do- string "\\label{"- result <- manyTill anyChar (char '}')- return $ Str $ "(" ++ result ++ ")"--ref = try (string "\\ref{") >> manyTill anyChar (char '}') >>= return . Str--strong = try (string "\\textbf{") >> manyTill inline (char '}') >>=- return . Strong--whitespace = many1 (oneOf "~ \t") >> return Space---- hard line break-linebreak = try (string "\\\\") >> return LineBreak--spacer = try (string "\\,") >> return (Str "")--str = many1 (noneOf specialChars) >>= return . Str---- endline internal to paragraph-endline = try $ newline >> notFollowedBy blankline >> return Space---- math-math = math1 <|> math2 <?> "math"--math1 = try $ do- char '$'- result <- many (noneOf "$")- char '$'- return $ TeX ("$" ++ result ++ "$")--math2 = try $ do- string "\\("- result <- many (noneOf "$")- string "\\)"- return $ TeX ("$" ++ result ++ "$")------- links and images-----url = try $ do- string "\\url"- url <- charsInBalanced '{' '}'- return $ Link [Code url] (url, "")--link = try $ do- string "\\href{"- url <- manyTill anyChar (char '}')- char '{'- label <- manyTill inline (char '}') - return $ Link (normalizeSpaces label) (url, "")--image = try $ do- ("includegraphics", _, args) <- command- let args' = filter isArg args -- filter out options- let src = if null args' then- ("", "")- else- (stripFirstAndLast (head args'), "")- return $ Image [Str "image"] src--footnote = try $ do- (name, _, (contents:[])) <- command- if ((name == "footnote") || (name == "thanks"))- then string ""- else fail "not a footnote or thanks command"- let contents' = stripFirstAndLast contents- -- parse the extracted block, which may contain various block elements:- rest <- getInput- setInput $ contents'- blocks <- parseBlocks- setInput rest- return $ Note blocks---- | Parse any LaTeX command and return it in a raw TeX inline element.-rawLaTeXInline :: GenParser Char ParserState Inline-rawLaTeXInline = try $ do- (name, star, args) <- command- state <- getState- if ((name == "begin") || (name == "end") || (name == "item"))- then fail "not an inline command" - else string ""- return $ TeX ("\\" ++ name ++ star ++ concat args)-
− src/Text/Pandoc/Readers/Markdown.hs
@@ -1,898 +0,0 @@-{--Copyright (C) 2006-7 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.Readers.Markdown- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion of markdown-formatted plain text to 'Pandoc' document.--}-module Text.Pandoc.Readers.Markdown ( - readMarkdown - ) where--import Data.List ( transpose, isPrefixOf, isSuffixOf, lookup, sortBy )-import Data.Ord ( comparing )-import Data.Char ( isAlphaNum )-import Network.URI ( isURI )-import Text.Pandoc.Definition-import Text.Pandoc.Shared -import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXEnvironment )-import Text.Pandoc.Readers.HTML ( rawHtmlBlock, anyHtmlBlockTag, - anyHtmlInlineTag, anyHtmlTag,- anyHtmlEndTag, htmlEndTag, extractTagType,- htmlBlockElement )-import Text.Pandoc.CharacterReferences ( decodeCharacterReferences )-import Text.ParserCombinators.Parsec---- | Read markdown from an input string and return a Pandoc document.-readMarkdown :: ParserState -> String -> Pandoc-readMarkdown state str = (readWith parseMarkdown) state (str ++ "\n\n")------- Constants and data structure definitions-----spaceChars = " \t"-bulletListMarkers = "*+-"-hruleChars = "*-_"-titleOpeners = "\"'("-setextHChars = "=-"---- treat these as potentially non-text when parsing inline:-specialChars = "\\[]*_~`<>$!^-.&'\""------- auxiliary functions-----indentSpaces = try $ do- state <- getState- let tabStop = stateTabStop state- try (count tabStop (char ' ')) <|> - (many (char ' ') >> string "\t") <?> "indentation"--nonindentSpaces = do- state <- getState- let tabStop = stateTabStop state- sps <- many (char ' ')- if length sps < tabStop - then return sps- else unexpected "indented line"---- | Fail unless we're at beginning of a line.-failUnlessBeginningOfLine = do- pos <- getPosition- if sourceColumn pos == 1 then return () else fail "not beginning of line"---- | Fail unless we're in "smart typography" mode.-failUnlessSmart = do- state <- getState- if stateSmart state then return () else fail "Smart typography feature"---- | Parse an inline Str element with a given content.-inlineString str = try $ do - (Str res) <- inline - if res == str then return res else fail $ "unexpected Str content"---- | Parse a sequence of inline elements between a string--- @opener@ and a string @closer@, including inlines--- between balanced pairs of @opener@ and a @closer@.-inlinesInBalanced :: String -> String -> GenParser Char ParserState [Inline]-inlinesInBalanced opener closer = try $ do- string opener- result <- manyTill ( (do lookAhead (inlineString opener)- -- because it might be a link...- bal <- inlinesInBalanced opener closer - return $ [Str opener] ++ bal ++ [Str closer])- <|> (count 1 inline)) - (try (string closer))- return $ concat result------- document structure-----titleLine = try $ char '%' >> skipSpaces >> manyTill inline newline--authorsLine = try $ do - char '%'- skipSpaces- authors <- sepEndBy (many1 (noneOf ",;\n")) (oneOf ",;")- newline- return $ map (decodeCharacterReferences . removeLeadingTrailingSpace) authors--dateLine = try $ do- char '%'- skipSpaces- date <- many (noneOf "\n")- newline- return $ decodeCharacterReferences $ removeTrailingSpace date--titleBlock = try $ do- failIfStrict- title <- option [] titleLine- author <- option [] authorsLine- date <- option "" dateLine- optional blanklines- return (title, author, date)--parseMarkdown = do- -- markdown allows raw HTML- updateState (\state -> state { stateParseRaw = True })- (title, author, date) <- option ([],[],"") titleBlock- -- go through once just to get list of reference keys- refs <- manyTill (referenceKey <|> (lineClump >>= return . LineClump)) eof- let keys = map (\(KeyBlock label target) -> (label, target)) $- filter isKeyBlock refs- -- strip out keys- setInput $ concatMap (\(LineClump ln) -> ln) $ filter isLineClump refs- updateState (\state -> state { stateKeys = keys })- st <- getState- if stateStrict st- then return ()- else do -- go through for notes (which may contain refs - hence 2nd pass)- refs' <- manyTill (noteBlock <|> - (lineClump >>= return . LineClump)) eof - let notes = map (\(NoteBlock label blocks) -> (label, blocks)) $ - filter isNoteBlock refs'- updateState (\state -> state { stateNotes = notes })- setInput $ concatMap (\(LineClump ln) -> ln) $ - filter isLineClump refs'- -- go through again, with note blocks and keys stripped out- blocks <- parseBlocks - return $ Pandoc (Meta title author date) $ filter (/= Null) blocks---- --- initial pass for references and notes-----referenceKey = try $ do- nonindentSpaces- label <- reference- char ':'- skipSpaces- optional (char '<')- src <- many (noneOf "> \n\t")- optional (char '>')- tit <- option "" referenceTitle- blanklines- return $ KeyBlock label (removeTrailingSpace src, tit)--referenceTitle = try $ do - skipSpaces- optional newline- skipSpaces- tit <- (charsInBalanced '(' ')' >>= return . unwords . words)- <|> do delim <- char '\'' <|> char '"'- manyTill anyChar (try (char delim >> skipSpaces >>- notFollowedBy (noneOf ")\n")))- return $ decodeCharacterReferences tit--noteMarker = string "[^" >> manyTill (noneOf " \t\n") (char ']')--rawLine = do- notFollowedBy blankline- notFollowedBy' noteMarker- contents <- many1 nonEndline- end <- option "" (newline >> optional indentSpaces >> return "\n") - return $ contents ++ end--rawLines = many1 rawLine >>= return . concat--noteBlock = try $ do- ref <- noteMarker- char ':'- optional blankline- optional indentSpaces- raw <- sepBy rawLines (try (blankline >> indentSpaces))- optional blanklines- -- parse the extracted text, which may contain various block elements:- contents <- parseFromString parseBlocks $ (joinWithSep "\n" raw) ++ "\n\n"- return $ NoteBlock ref contents------- parsing blocks-----parseBlocks = manyTill block eof--block = choice [ header - , table- , codeBlock- , hrule- , list- , blockQuote- , htmlBlock- , rawLaTeXEnvironment'- , para- , plain- , nullBlock ] <?> "block"------- header blocks-----header = atxHeader <|> setextHeader <?> "header"--atxHeader = try $ do- level <- many1 (char '#') >>= return . length- notFollowedBy (char '.' <|> char ')') -- this would be a list- skipSpaces- text <- manyTill inline atxClosing >>= return . normalizeSpaces- return $ Header level text--atxClosing = try $ skipMany (char '#') >> blanklines--setextHeader = try $ do- -- first, see if this block has any chance of being a setextHeader:- lookAhead (anyLine >> oneOf setextHChars)- text <- many1Till inline newline >>= return . normalizeSpaces- level <- choice $ zipWith - (\ch lev -> try (many1 $ char ch) >> blanklines >> return lev)- setextHChars [1..(length setextHChars)]- return $ Header level text------- hrule block-----hrule = try $ do- skipSpaces- start <- oneOf hruleChars- count 2 (skipSpaces >> char start)- skipMany (skipSpaces >> char start)- newline- optional blanklines- return HorizontalRule------- code blocks-----indentedLine = indentSpaces >> manyTill anyChar newline >>= return . (++ "\n")--codeBlock = do- contents <- many1 (indentedLine <|> - try (do b <- blanklines- l <- indentedLine- return $ b ++ l))- optional blanklines- return $ CodeBlock $ stripTrailingNewlines $ concat contents------- block quotes-----emacsBoxQuote = try $ do- failIfStrict- string ",----"- manyTill anyChar newline- raw <- manyTill - (try (char '|' >> optional (char ' ') >> manyTill anyChar newline))- (try (string "`----"))- blanklines- return raw--emailBlockQuoteStart = try $ nonindentSpaces >> char '>' >>~ optional (char ' ')--emailBlockQuote = try $ do- emailBlockQuoteStart- raw <- sepBy (many (nonEndline <|> - (try (endline >> notFollowedBy emailBlockQuoteStart >>- return '\n'))))- (try (newline >> emailBlockQuoteStart))- newline <|> (eof >> return '\n')- optional blanklines- return raw--blockQuote = do - raw <- emailBlockQuote <|> emacsBoxQuote- -- parse the extracted block, which may contain various block elements:- contents <- parseFromString parseBlocks $ (joinWithSep "\n" raw) ++ "\n\n"- return $ BlockQuote contents- ------ list blocks-----list = choice [ bulletList, orderedList, definitionList ] <?> "list"--bulletListStart = try $ do- optional newline -- if preceded by a Plain block in a list context- nonindentSpaces- notFollowedBy' hrule -- because hrules start out just like lists- oneOf bulletListMarkers- spaceChar- skipSpaces--anyOrderedListStart = try $ do- optional newline -- if preceded by a Plain block in a list context- nonindentSpaces- notFollowedBy $ string "p." >> spaceChar >> digit -- page number- state <- getState- if stateStrict state- then do many1 digit- char '.'- spaceChar- return (1, DefaultStyle, DefaultDelim)- else anyOrderedListMarker >>~ spaceChar--orderedListStart style delim = try $ do- optional newline -- if preceded by a Plain block in a list context- nonindentSpaces- state <- getState- num <- if stateStrict state- then do many1 digit- char '.'- return 1- else orderedListMarker style delim - if delim == Period && (style == UpperAlpha || (style == UpperRoman &&- num `elem` [1, 5, 10, 50, 100, 500, 1000]))- then char '\t' <|> (spaceChar >> spaceChar)- else spaceChar- skipSpaces---- parse a line of a list item (start = parser for beginning of list item)-listLine start = try $ do- notFollowedBy' start- notFollowedBy blankline- notFollowedBy' (do indentSpaces- many (spaceChar)- bulletListStart <|> (anyOrderedListStart >> return ()))- line <- manyTill anyChar newline- return $ line ++ "\n"---- parse raw text for one list item, excluding start marker and continuations-rawListItem start = try $ do- start- result <- many1 (listLine start)- blanks <- many blankline- return $ concat result ++ blanks---- continuation of a list item - indented and separated by blankline --- or (in compact lists) endline.--- note: nested lists are parsed as continuations-listContinuation start = try $ do- lookAhead indentSpaces- result <- many1 (listContinuationLine start)- blanks <- many blankline- return $ concat result ++ blanks--listContinuationLine start = try $ do- notFollowedBy blankline- notFollowedBy' start- optional indentSpaces- result <- manyTill anyChar newline- return $ result ++ "\n"--listItem start = try $ do - first <- rawListItem start- continuations <- many (listContinuation start)- -- parsing with ListItemState forces markers at beginning of lines to- -- count as list item markers, even if not separated by blank space.- -- see definition of "endline"- state <- getState- let oldContext = stateParserContext state- setState $ state {stateParserContext = ListItemState}- -- parse the extracted block, which may contain various block elements:- let raw = concat (first:continuations)- contents <- parseFromString parseBlocks raw- updateState (\st -> st {stateParserContext = oldContext})- return contents--orderedList = try $ do- (start, style, delim) <- lookAhead anyOrderedListStart- items <- many1 (listItem (orderedListStart style delim))- return $ OrderedList (start, style, delim) $ compactify items--bulletList = many1 (listItem bulletListStart) >>= - return . BulletList . compactify---- definition lists--definitionListItem = try $ do- notFollowedBy blankline- notFollowedBy' indentSpaces- -- first, see if this has any chance of being a definition list:- lookAhead (anyLine >> char ':')- term <- manyTill inline newline- raw <- many1 defRawBlock- state <- getState- let oldContext = stateParserContext state- -- parse the extracted block, which may contain various block elements:- contents <- parseFromString parseBlocks $ concat raw- updateState (\st -> st {stateParserContext = oldContext})- return ((normalizeSpaces term), contents)--defRawBlock = try $ do- char ':'- state <- getState- let tabStop = stateTabStop state- try (count (tabStop - 1) (char ' ')) <|> (many (char ' ') >> string "\t")- firstline <- anyLine- rawlines <- many (notFollowedBy blankline >> indentSpaces >> anyLine)- trailing <- option "" blanklines- return $ firstline ++ "\n" ++ unlines rawlines ++ trailing--definitionList = do- failIfStrict- items <- many1 definitionListItem- let (terms, defs) = unzip items- let defs' = compactify defs- let items' = zip terms defs'- return $ DefinitionList items'------- paragraph block-----para = try $ do - result <- many1 inline- newline- blanklines <|> do st <- getState- if stateStrict st- then lookAhead (blockQuote <|> header) >> return ""- else lookAhead emacsBoxQuote >> return ""- return $ Para $ normalizeSpaces result--plain = many1 inline >>= return . Plain . normalizeSpaces ---- --- raw html-----htmlElement = strictHtmlBlock <|> htmlBlockElement <?> "html element"--htmlBlock = do- st <- getState- if stateStrict st- then try $ do failUnlessBeginningOfLine- first <- htmlElement- finalSpace <- many (oneOf spaceChars)- finalNewlines <- many newline- return $ RawHtml $ first ++ finalSpace ++ finalNewlines- else rawHtmlBlocks---- True if tag is self-closing-isSelfClosing tag = - isSuffixOf "/>" $ filter (not . (`elem` " \n\t")) tag--strictHtmlBlock = try $ do- tag <- anyHtmlBlockTag - let tag' = extractTagType tag- if isSelfClosing tag || tag' == "hr" - then return tag- else do contents <- many (notFollowedBy' (htmlEndTag tag') >> - (htmlElement <|> (count 1 anyChar)))- end <- htmlEndTag tag'- return $ tag ++ concat contents ++ end--rawHtmlBlocks = do- htmlBlocks <- many1 rawHtmlBlock - let combined = concatMap (\(RawHtml str) -> str) htmlBlocks- let combined' = if not (null combined) && last combined == '\n'- then init combined -- strip extra newline - else combined - return $ RawHtml combined'------- LaTeX-----rawLaTeXEnvironment' = failIfStrict >> rawLaTeXEnvironment------- Tables--- ---- Parse a dashed line with optional trailing spaces; return its length--- and the length including trailing space.-dashedLine ch = do- dashes <- many1 (char ch)- sp <- many spaceChar- return $ (length dashes, length $ dashes ++ sp)---- Parse a table header with dashed lines of '-' preceded by --- one line of text.-simpleTableHeader = try $ do- rawContent <- anyLine- initSp <- nonindentSpaces- dashes <- many1 (dashedLine '-')- newline- let (lengths, lines) = unzip dashes- let indices = scanl (+) (length initSp) lines- let rawHeads = tail $ splitByIndices (init indices) rawContent- let aligns = zipWith alignType (map (\a -> [a]) rawHeads) lengths- return (rawHeads, aligns, indices)---- Parse a table footer - dashed lines followed by blank line.-tableFooter = try $ nonindentSpaces >> many1 (dashedLine '-') >> blanklines---- Parse a table separator - dashed line.-tableSep = try $ nonindentSpaces >> many1 (dashedLine '-') >> string "\n"---- Parse a raw line and split it into chunks by indices.-rawTableLine indices = do- notFollowedBy' (blanklines <|> tableFooter)- line <- many1Till anyChar newline- return $ map removeLeadingTrailingSpace $ tail $ - splitByIndices (init indices) line---- Parse a table line and return a list of lists of blocks (columns).-tableLine indices = rawTableLine indices >>= mapM (parseFromString (many plain))---- Parse a multiline table row and return a list of blocks (columns).-multilineRow indices = do- colLines <- many1 (rawTableLine indices)- optional blanklines- let cols = map unlines $ transpose colLines- mapM (parseFromString (many plain)) cols---- Calculate relative widths of table columns, based on indices-widthsFromIndices :: Int -- Number of columns on terminal- -> [Int] -- Indices- -> [Float] -- Fractional relative sizes of columns-widthsFromIndices _ [] = [] -widthsFromIndices numColumns indices = - let lengths = zipWith (-) indices (0:indices)- totLength = sum lengths- quotient = if totLength > numColumns- then fromIntegral totLength- else fromIntegral numColumns- fracs = map (\l -> (fromIntegral l) / quotient) lengths in- tail fracs---- Parses a table caption: inlines beginning with 'Table:'--- and followed by blank lines.-tableCaption = try $ do- nonindentSpaces- string "Table:"- result <- many1 inline- blanklines- return $ normalizeSpaces result---- Parse a table using 'headerParser', 'lineParser', and 'footerParser'.-tableWith headerParser lineParser footerParser = try $ do- (rawHeads, aligns, indices) <- headerParser- lines <- many1Till (lineParser indices) footerParser- caption <- option [] tableCaption- heads <- mapM (parseFromString (many plain)) rawHeads- state <- getState- let numColumns = stateColumns state- let widths = widthsFromIndices numColumns indices- return $ Table caption aligns widths heads lines---- Parse a simple table with '---' header and one line per row.-simpleTable = tableWith simpleTableHeader tableLine blanklines---- Parse a multiline table: starts with row of '-' on top, then header--- (which may be multiline), then the rows,--- which may be multiline, separated by blank lines, and--- ending with a footer (dashed line followed by blank line).-multilineTable = tableWith multilineTableHeader multilineRow tableFooter--multilineTableHeader = try $ do- tableSep - rawContent <- many1 (notFollowedBy' tableSep >> many1Till anyChar newline)- initSp <- nonindentSpaces- dashes <- many1 (dashedLine '-')- newline- let (lengths, lines) = unzip dashes- let indices = scanl (+) (length initSp) lines- let rawHeadsList = transpose $ map - (\ln -> tail $ splitByIndices (init indices) ln)- rawContent- let rawHeads = map (joinWithSep " ") rawHeadsList- let aligns = zipWith alignType rawHeadsList lengths- return ((map removeLeadingTrailingSpace rawHeads), aligns, indices)---- Returns an alignment type for a table, based on a list of strings--- (the rows of the column header) and a number (the length of the--- dashed line under the rows.-alignType :: [String] -> Int -> Alignment-alignType [] len = AlignDefault-alignType strLst len =- let str = head $ sortBy (comparing length) $ - map removeTrailingSpace strLst- leftSpace = if null str then False else (str !! 0) `elem` " \t"- rightSpace = length str < len || (str !! (len - 1)) `elem` " \t"- in case (leftSpace, rightSpace) of- (True, False) -> AlignRight- (False, True) -> AlignLeft- (True, True) -> AlignCenter- (False, False) -> AlignDefault--table = failIfStrict >> (simpleTable <|> multilineTable) <?> "table"---- --- inline-----inline = choice [ str- , smartPunctuation- , whitespace- , endline- , code- , charRef- , strong- , emph- , note- , inlineNote- , link- , image- , math- , strikeout- , superscript- , subscript- , autoLink- , rawHtmlInline'- , rawLaTeXInline'- , escapedChar- , symbol- , ltSign ] <?> "inline"--escapedChar = do- char '\\'- state <- getState- result <- option '\\' $ if stateStrict state - then oneOf "\\`*_{}[]()>#+-.!~"- else satisfy (not . isAlphaNum)- return $ Str [result]--ltSign = do- st <- getState- if stateStrict st- then char '<'- else notFollowedBy' rawHtmlBlocks >> char '<' -- unless it starts html- return $ Str ['<']--specialCharsMinusLt = filter (/= '<') specialChars--symbol = do - result <- oneOf specialCharsMinusLt- return $ Str [result]---- parses inline code, between n `s and n `s-code = try $ do - starts <- many1 (char '`')- skipSpaces- result <- many1Till (many1 (noneOf "`\n") <|> many1 (char '`') <|>- (char '\n' >> return " ")) - (try (skipSpaces >> count (length starts) (char '`') >> - notFollowedBy (char '`')))- return $ Code $ removeLeadingTrailingSpace $ concat result--mathWord = many1 ((noneOf " \t\n\\$") <|>- (try (char '\\') >>~ notFollowedBy (char '$')))--math = try $ do- failIfStrict- char '$'- notFollowedBy space- words <- sepBy1 mathWord (many1 space)- char '$'- return $ TeX ("$" ++ (joinWithSep " " words) ++ "$")--emph = ((enclosed (char '*') (char '*') inline) <|>- (enclosed (char '_') (char '_' >> notFollowedBy alphaNum) inline)) >>= - return . Emph . normalizeSpaces--strong = ((enclosed (string "**") (try $ string "**") inline) <|> - (enclosed (string "__") (try $ string "__") inline)) >>=- return . Strong . normalizeSpaces--strikeout = failIfStrict >> enclosed (string "~~") (try $ string "~~") inline >>=- return . Strikeout . normalizeSpaces--superscript = failIfStrict >> enclosed (char '^') (char '^') - (notFollowedBy' whitespace >> inline) >>= -- may not contain Space- return . Superscript--subscript = failIfStrict >> enclosed (char '~') (char '~')- (notFollowedBy' whitespace >> inline) >>= -- may not contain Space- return . Subscript --smartPunctuation = failUnlessSmart >> - choice [ quoted, apostrophe, dash, ellipses ]--apostrophe = (char '\'' <|> char '\8217') >> return Apostrophe--quoted = doubleQuoted <|> singleQuoted --withQuoteContext context parser = do- oldState <- getState- let oldQuoteContext = stateQuoteContext oldState- setState oldState { stateQuoteContext = context }- result <- parser- newState <- getState- setState newState { stateQuoteContext = oldQuoteContext }- return result--singleQuoted = try $ do- singleQuoteStart- withQuoteContext InSingleQuote $ many1Till inline singleQuoteEnd >>=- return . Quoted SingleQuote . normalizeSpaces--doubleQuoted = try $ do - doubleQuoteStart- withQuoteContext InDoubleQuote $ many1Till inline doubleQuoteEnd >>=- return . Quoted DoubleQuote . normalizeSpaces--failIfInQuoteContext context = do- st <- getState- if stateQuoteContext st == context- then fail "already inside quotes"- else return ()--singleQuoteStart = do - failIfInQuoteContext InSingleQuote- char '\8216' <|> - do char '\'' - notFollowedBy (oneOf ")!],.;:-? \t\n")- notFollowedBy (try (oneOfStrings ["s","t","m","ve","ll","re"] >>- satisfy (not . isAlphaNum))) -- possess/contraction- return '\''--singleQuoteEnd = (char '\'' <|> char '\8217') >> notFollowedBy alphaNum--doubleQuoteStart = failIfInQuoteContext InDoubleQuote >>- (char '"' <|> char '\8220') >>- notFollowedBy (oneOf " \t\n")--doubleQuoteEnd = char '"' <|> char '\8221'--ellipses = oneOfStrings ["...", " . . . ", ". . .", " . . ."] >> return Ellipses--dash = enDash <|> emDash--enDash = try $ char '-' >> notFollowedBy (noneOf "0123456789") >> return EnDash--emDash = try $ skipSpaces >> oneOfStrings ["---", "--"] >>- skipSpaces >> return EmDash--whitespace = do- sps <- many1 (oneOf spaceChars)- if length sps >= 2- then option Space (endline >> return LineBreak)- else return Space <?> "whitespace"--nonEndline = satisfy (/='\n')--strChar = noneOf (specialChars ++ spaceChars ++ "\n")--str = many1 strChar >>= return . Str---- an endline character that can be treated as a space, not a structural break-endline = try $ do- newline- notFollowedBy blankline- st <- getState- if stateStrict st - then do notFollowedBy emailBlockQuoteStart- notFollowedBy (char '#') -- atx header- else return () - -- parse potential list-starts differently if in a list:- if stateParserContext st == ListItemState- then notFollowedBy' (bulletListStart <|> - (anyOrderedListStart >> return ()))- else return ()- return Space------- links------- a reference label for a link-reference = notFollowedBy' (string "[^") >> -- footnote reference- inlinesInBalanced "[" "]" >>= (return . normalizeSpaces)---- source for a link, with optional title-source = try $ do - char '('- optional (char '<')- src <- many (noneOf ")> \t\n")- optional (char '>')- tit <- option "" linkTitle- skipSpaces- char ')'- return (removeTrailingSpace src, tit)--linkTitle = try $ do - skipSpaces- optional newline- skipSpaces- delim <- char '\'' <|> char '"'- tit <- manyTill anyChar (try (char delim >> skipSpaces >>- notFollowedBy (noneOf ")\n")))- return $ decodeCharacterReferences tit--link = try $ do- label <- reference- src <- source <|> referenceLink label- return $ Link label src---- a link like [this][ref] or [this][] or [this]-referenceLink label = do- ref <- option [] (try (optional (char ' ') >> - optional (newline >> skipSpaces) >> reference))- let ref' = if null ref then label else ref- state <- getState- case lookupKeySrc (stateKeys state) ref' of- Nothing -> fail "no corresponding key" - Just target -> return target --emailAddress = try $ do- name <- many1 (alphaNum <|> char '+')- char '@'- first <- many1 alphaNum- rest <- many1 (char '.' >> many1 alphaNum)- return $ "mailto:" ++ name ++ "@" ++ joinWithSep "." (first:rest)--uri = try $ do- str <- many1 (noneOf "\n\t >")- if isURI str- then return str- else fail "not a URI"--autoLink = try $ do- char '<'- src <- uri <|> emailAddress- char '>'- let src' = if "mailto:" `isPrefixOf` src- then drop 7 src- else src - st <- getState- return $ if stateStrict st- then Link [Str src'] (src, "")- else Link [Code src'] (src, "")--image = try $ do- char '!'- (Link label src) <- link- return $ Image label src--note = try $ do- failIfStrict- ref <- noteMarker- state <- getState- let notes = stateNotes state- case lookup ref notes of- Nothing -> fail "note not found"- Just contents -> return $ Note contents--inlineNote = try $ do- failIfStrict- char '^'- contents <- inlinesInBalanced "[" "]"- return $ Note [Para contents]--rawLaTeXInline' = failIfStrict >> rawLaTeXInline--rawHtmlInline' = do- st <- getState- result <- choice $ if stateStrict st- then [htmlBlockElement, anyHtmlTag, anyHtmlEndTag] - else [htmlBlockElement, anyHtmlInlineTag]- return $ HtmlInline result-
− src/Text/Pandoc/Readers/RST.hs
@@ -1,629 +0,0 @@-{--Copyright (C) 2006-7 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.Readers.RST - Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion from reStructuredText to 'Pandoc' document.--}-module Text.Pandoc.Readers.RST ( - readRST- ) where-import Text.Pandoc.Definition-import Text.Pandoc.Shared -import Text.ParserCombinators.Parsec-import Data.List ( findIndex, delete )---- | Parse reStructuredText string and return Pandoc document.-readRST :: ParserState -> String -> Pandoc-readRST state str = (readWith parseRST) state (str ++ "\n\n")------- Constants and data structure definitions------bulletListMarkers = "*+-"-underlineChars = "!\"#$&'()*+,-./:;<=>?@[\\]^_`{|}~"---- treat these as potentially non-text when parsing inline:-specialChars = "\\`|*_<>$:[-"------- parsing documents-----isAnonKey (ref, src) = ref == [Str "_"]--isHeader :: Int -> Block -> Bool-isHeader n (Header x _) = x == n-isHeader _ _ = False---- | Promote all headers in a list of blocks. (Part of--- title transformation for RST.)-promoteHeaders :: Int -> [Block] -> [Block]-promoteHeaders num ((Header level text):rest) = - (Header (level - num) text):(promoteHeaders num rest)-promoteHeaders num (other:rest) = other:(promoteHeaders num rest)-promoteHeaders num [] = []---- | If list of blocks starts with a header (or a header and subheader)--- of level that are not found elsewhere, return it as a title and--- promote all the other headers. -titleTransform :: [Block] -- ^ list of blocks- -> ([Block], [Inline]) -- ^ modified list of blocks, title-titleTransform ((Header 1 head1):(Header 2 head2):rest) = -- title subtitle- if (any (isHeader 1) rest) || (any (isHeader 2) rest)- then ((Header 1 head1):(Header 2 head2):rest, [])- else ((promoteHeaders 2 rest), head1 ++ [Str ":", Space] ++ head2)-titleTransform ((Header 1 head1):rest) = -- title, no subtitle- if (any (isHeader 1) rest)- then ((Header 1 head1):rest, [])- else ((promoteHeaders 1 rest), head1)-titleTransform blocks = (blocks, [])--parseRST = do- -- first pass: get keys- refs <- manyTill (referenceKey <|> (lineClump >>= return . LineClump)) eof- let keys = map (\(KeyBlock label target) -> (label, target)) $- filter isKeyBlock refs- -- second pass, with keys stripped out- let rawlines = map (\(LineClump ln) -> ln) $ filter isLineClump refs- setInput $ concat rawlines - updateState (\state -> state { stateKeys = keys })- blocks <- parseBlocks- let blocks' = filter (/= Null) blocks- state <- getState- let (blocks'', title) = if stateStandalone state- then titleTransform blocks'- else (blocks', [])- let authors = stateAuthors state- let date = stateDate state- let title' = if (null title) then (stateTitle state) else title- return $ Pandoc (Meta title' authors date) blocks''------- parsing blocks-----parseBlocks = manyTill block eof--block = choice [ codeBlock- , rawHtmlBlock- , rawLaTeXBlock- , blockQuote- , imageBlock- , unknownDirective- , header- , hrule- , list- , fieldList- , lineBlock- , para- , plain- , nullBlock ] <?> "block"------- field list-----fieldListItem = try $ do- char ':'- name <- many1 alphaNum- string ": "- skipSpaces- first <- manyTill anyChar newline- rest <- many (notFollowedBy ((char ':') <|> blankline) >>- skipSpaces >> manyTill anyChar newline)- return $ (name, (joinWithSep " " (first:rest)))--fieldList = try $ do- items <- many1 fieldListItem- blanklines- let authors = case lookup "Authors" items of- Just auth -> [auth]- Nothing -> map snd (filter (\(x,y) -> x == "Author") items)- let date = case (lookup "Date" items) of- Just dat -> dat- Nothing -> ""- let title = case (lookup "Title" items) of- Just tit -> [Str tit]- Nothing -> []- let remaining = filter (\(x,y) -> (x /= "Authors") && (x /= "Author") && - (x /= "Date") && (x /= "Title")) items- let result = map (\(x,y) -> - Para [Strong [Str x], Str ":", Space, Str y]) remaining- updateState (\st -> st { stateAuthors = authors, - stateDate = date, - stateTitle = title })- return $ BlockQuote result------- line block-----lineBlockLine = try $ do- string "| "- white <- many (oneOf " \t")- line <- manyTill inline newline- return $ (if null white then [] else [Str white]) ++ line ++ [LineBreak]--lineBlock = try $ do- lines <- many1 lineBlockLine- blanklines- return $ Para (concat lines)------- paragraph block-----para = paraBeforeCodeBlock <|> paraNormal <?> "paragraph"--codeBlockStart = string "::" >> blankline >> blankline---- paragraph that ends in a :: starting a code block-paraBeforeCodeBlock = try $ do- result <- many1 (notFollowedBy' codeBlockStart >> inline)- lookAhead (string "::")- return $ Para $ if last result == Space- then normalizeSpaces result- else (normalizeSpaces result) ++ [Str ":"]---- regular paragraph-paraNormal = try $ do - result <- many1 inline- newline- blanklines- return $ Para $ normalizeSpaces result--plain = many1 inline >>= return . Plain . normalizeSpaces ------- image block-----imageBlock = try $ do- string ".. image:: "- src <- manyTill anyChar newline- return $ Plain [Image [Str "image"] (src, "")]------- header blocks-----header = doubleHeader <|> singleHeader <?> "header"---- a header with lines on top and bottom-doubleHeader = try $ do- c <- oneOf underlineChars- rest <- many (char c) -- the top line- let lenTop = length (c:rest)- skipSpaces- newline- txt <- many1 (notFollowedBy blankline >> inline)- pos <- getPosition- let len = (sourceColumn pos) - 1- if (len > lenTop) then fail "title longer than border" else return ()- blankline -- spaces and newline- count lenTop (char c) -- the bottom line- blanklines- -- check to see if we've had this kind of header before. - -- if so, get appropriate level. if not, add to list.- state <- getState- let headerTable = stateHeaderTable state- let (headerTable',level) = case findIndex (== DoubleHeader c) headerTable of- Just ind -> (headerTable, ind + 1)- Nothing -> (headerTable ++ [DoubleHeader c], (length headerTable) + 1)- setState (state { stateHeaderTable = headerTable' })- return $ Header level (normalizeSpaces txt)---- a header with line on the bottom only-singleHeader = try $ do - notFollowedBy' whitespace- txt <- many1 (do {notFollowedBy blankline; inline})- pos <- getPosition- let len = (sourceColumn pos) - 1- blankline- c <- oneOf underlineChars- rest <- count (len - 1) (char c)- many (char c)- blanklines- state <- getState- let headerTable = stateHeaderTable state- let (headerTable',level) = case findIndex (== SingleHeader c) headerTable of- Just ind -> (headerTable, ind + 1)- Nothing -> (headerTable ++ [SingleHeader c], (length headerTable) + 1)- setState (state { stateHeaderTable = headerTable' })- return $ Header level (normalizeSpaces txt)------- hrule block-----hrule = try $ do- chr <- oneOf underlineChars- count 3 (char chr)- skipMany (char chr)- blankline- blanklines- return HorizontalRule------- code blocks------- read a line indented by a given string-indentedLine indents = try $ do- string indents- result <- manyTill anyChar newline- return $ result ++ "\n"---- two or more indented lines, possibly separated by blank lines.--- if variable = True, then any indent will work, but it must be--- consistent through the block.--- if variable = False, indent should be one tab or equivalent in spaces.-indentedBlock variable = try $ do - state <- getState- let tabStop = stateTabStop state- indents <- if variable- then many1 (oneOf " \t")- else oneOfStrings ["\t", (replicate tabStop ' ')]- firstline <- manyTill anyChar newline- rest <- many (choice [ indentedLine indents, - try (do b <- blanklines- l <- indentedLine indents- return (b ++ l))])- optional blanklines- return $ firstline ++ "\n" ++ concat rest--codeBlock = try $ do- codeBlockStart- result <- indentedBlock False- -- the False means we want one tab stop indent on each line- return $ CodeBlock $ stripTrailingNewlines result------- raw html-----rawHtmlBlock = try $ string ".. raw:: html" >> blanklines >>- indentedBlock True >>= return . RawHtml------- raw latex-----rawLaTeXBlock = try $ do- string ".. raw:: latex"- blanklines- result <- indentedBlock True- return $ Para [(TeX result)]------- block quotes-----blockQuote = do- raw <- indentedBlock True- -- parse the extracted block, which may contain various block elements:- contents <- parseFromString parseBlocks $ raw ++ "\n\n"- return $ BlockQuote contents------- list blocks-----list = choice [ bulletList, orderedList, definitionList ] <?> "list"--definitionListItem = try $ do- term <- many1Till inline endline- raw <- indentedBlock True- -- parse the extracted block, which may contain various block elements:- contents <- parseFromString parseBlocks $ raw ++ "\n\n"- return (normalizeSpaces term, contents)--definitionList = many1 definitionListItem >>= return . DefinitionList---- parses bullet list start and returns its length (inc. following whitespace)-bulletListStart = try $ do- notFollowedBy' hrule -- because hrules start out just like lists- marker <- oneOf bulletListMarkers- white <- many1 spaceChar- return $ length (marker:white)---- parses ordered list start and returns its length (inc following whitespace)-orderedListStart style delim = try $ do- (_, markerLen) <- withHorizDisplacement (orderedListMarker style delim)- white <- many1 spaceChar- return $ markerLen + length white---- parse a line of a list item-listLine markerLength = try $ do- notFollowedBy blankline- indentWith markerLength- line <- manyTill anyChar newline- return $ line ++ "\n"---- indent by specified number of spaces (or equiv. tabs)-indentWith num = do- state <- getState- let tabStop = stateTabStop state- if (num < tabStop)- then count num (char ' ')- else choice [ try (count num (char ' ')), - (try (char '\t' >> count (num - tabStop) (char ' '))) ] ---- parse raw text for one list item, excluding start marker and continuations-rawListItem start = do- markerLength <- start- firstLine <- manyTill anyChar newline- restLines <- many (listLine markerLength)- return (markerLength, (firstLine ++ "\n" ++ (concat restLines)))---- continuation of a list item - indented and separated by blankline or --- (in compact lists) endline. --- Note: nested lists are parsed as continuations.-listContinuation markerLength = try $ do- blanks <- many1 blankline- result <- many1 (listLine markerLength)- return $ blanks ++ concat result--listItem start = try $ do - (markerLength, first) <- rawListItem start- rest <- many (listContinuation markerLength)- blanks <- choice [ try (many blankline >>~ lookAhead start),- many1 blankline ] -- whole list must end with blank.- -- parsing with ListItemState forces markers at beginning of lines to- -- count as list item markers, even if not separated by blank space.- -- see definition of "endline"- state <- getState- let oldContext = stateParserContext state- setState $ state {stateParserContext = ListItemState}- -- parse the extracted block, which may itself contain block elements- parsed <- parseFromString parseBlocks $ concat (first:rest) ++ blanks- updateState (\st -> st {stateParserContext = oldContext})- return parsed--orderedList = do- (start, style, delim) <- lookAhead (anyOrderedListMarker >>~ spaceChar)- items <- many1 (listItem (orderedListStart style delim))- let items' = compactify items- return $ OrderedList (start, style, delim) items'--bulletList = many1 (listItem bulletListStart) >>= - return . BulletList . compactify------- unknown directive (e.g. comment)-----unknownDirective = try $ do- string ".. "- manyTill anyChar newline- many (string " :" >> many1 (noneOf "\n:") >> char ':' >>- many1 (noneOf "\n") >> newline)- optional blanklines- return Null---- --- reference key-----referenceKey = - choice [imageKey, anonymousKey, regularKeyQuoted, regularKey] >>~ - optional blanklines--targetURI = do- skipSpaces- optional newline- contents <- many1 (try (many spaceChar >> newline >> - many1 spaceChar >> noneOf " \t\n") <|> noneOf "\n")- blanklines- return contents--imageKey = try $ do- string ".. |"- ref <- manyTill inline (char '|')- skipSpaces- string "image::"- src <- targetURI- return $ KeyBlock (normalizeSpaces ref) (removeLeadingTrailingSpace src, "")--anonymousKey = try $ do- oneOfStrings [".. __:", "__"]- src <- targetURI- state <- getState- return $ KeyBlock [Str "_"] (removeLeadingTrailingSpace src, "")--regularKeyQuoted = try $ do- string ".. _`"- ref <- manyTill inline (char '`')- char ':'- src <- targetURI- return $ KeyBlock (normalizeSpaces ref) (removeLeadingTrailingSpace src, "")--regularKey = try $ do- string ".. _"- ref <- manyTill inline (char ':')- src <- targetURI- return $ KeyBlock (normalizeSpaces ref) (removeLeadingTrailingSpace src, "")-- -- - -- inline- ----inline = choice [ link- , str- , whitespace- , endline- , strong- , emph- , code- , image- , hyphens- , superscript- , subscript- , escapedChar- , symbol ] <?> "inline"--hyphens = do- result <- many1 (char '-')- option Space endline - -- don't want to treat endline after hyphen or dash as a space- return $ Str result--escapedChar = escaped anyChar--symbol = do - result <- oneOf specialChars- return $ Str [result]---- parses inline code, between codeStart and codeEnd-code = try $ do - string "``"- result <- manyTill anyChar (try (string "``"))- return $ Code $ removeLeadingTrailingSpace $ joinWithSep " " $ lines result--emph = enclosed (char '*') (char '*') inline >>= - return . Emph . normalizeSpaces--strong = enclosed (string "**") (try $ string "**") inline >>= - return . Strong . normalizeSpaces--interpreted role = try $ do- optional $ try $ string "\\ "- result <- enclosed (string $ ":" ++ role ++ ":`") (char '`') anyChar- nextChar <- lookAhead anyChar- try (string "\\ ") <|> lookAhead (count 1 $ oneOf " \t\n") <|> (eof >> return "")- return [Str result]--superscript = interpreted "sup" >>= (return . Superscript)--subscript = interpreted "sub" >>= (return . Subscript)--whitespace = many1 spaceChar >> return Space <?> "whitespace"--str = notFollowedBy' oneWordReference >> - many1 (noneOf (specialChars ++ "\t\n ")) >>= return . Str---- an endline character that can be treated as a space, not a structural break-endline = try $ do- newline- notFollowedBy blankline- -- parse potential list-starts at beginning of line differently in a list:- st <- getState- if (stateParserContext st) == ListItemState- then notFollowedBy (anyOrderedListMarker >> spaceChar) >>- notFollowedBy' bulletListStart- else return ()- return Space------- links-----link = choice [explicitLink, referenceLink, autoLink] <?> "link"--explicitLink = try $ do- char '`'- notFollowedBy (char '`') -- `` is marks start of inline code- label <- manyTill inline (try (do {spaces; char '<'}))- src <- manyTill (noneOf ">\n ") (char '>')- skipSpaces- string "`_"- return $ Link (normalizeSpaces label) (removeLeadingTrailingSpace src, "")--reference = try $ do- char '`'- notFollowedBy (char '`')- label <- many1Till inline (char '`') - char '_'- return label--oneWordReference = do- raw <- many1 alphaNum- char '_'- notFollowedBy alphaNum -- because this_is_not a link- return [Str raw]--referenceLink = try $ do- label <- reference <|> oneWordReference- key <- option label (do{char '_'; return [Str "_"]}) -- anonymous link- state <- getState- let keyTable = stateKeys state- src <- case lookupKeySrc keyTable key of- Nothing -> fail "no corresponding key"- Just target -> return target- -- if anonymous link, remove first anon key so it won't be used again- let keyTable' = if (key == [Str "_"]) -- anonymous link? - then delete ([Str "_"], src) keyTable -- remove first anon key - else keyTable - setState $ state { stateKeys = keyTable' }- return $ Link (normalizeSpaces label) src --uriScheme = oneOfStrings [ "http://", "https://", "ftp://", "file://", - "mailto:", "news:", "telnet:" ]--uri = try $ do- scheme <- uriScheme- identifier <- many1 (noneOf " \t\n")- return $ scheme ++ identifier--autoURI = do- src <- uri- return $ Link [Str src] (src, "")--emailChar = alphaNum <|> oneOf "-+_."--emailAddress = try $ do- firstLetter <- alphaNum- restAddr <- many emailChar- let addr = firstLetter:restAddr- char '@'- dom <- domain- return $ addr ++ '@':dom--domainChar = alphaNum <|> char '-'--domain = do- first <- many1 domainChar- dom <- many1 (try (do{ char '.'; many1 domainChar }))- return $ joinWithSep "." (first:dom)--autoEmail = do- src <- emailAddress- return $ Link [Str src] ("mailto:" ++ src, "")--autoLink = autoURI <|> autoEmail---- For now, we assume that all substitution references are for images.-image = try $ do- char '|'- ref <- manyTill inline (char '|')- state <- getState- let keyTable = stateKeys state- src <- case lookupKeySrc keyTable ref of- Nothing -> fail "no corresponding key"- Just target -> return target- return $ Image (normalizeSpaces ref) src-
@@ -1,806 +0,0 @@-{--Copyright (C) 2006-7 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.Shared- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Utility functions and definitions used by the various Pandoc modules.--}-module Text.Pandoc.Shared ( - -- * List processing- splitBy,- splitByIndices,- substitute,- joinWithSep,- -- * Text processing- backslashEscapes,- escapeStringUsing,- stripTrailingNewlines,- removeLeadingTrailingSpace,- removeLeadingSpace,- removeTrailingSpace,- stripFirstAndLast,- camelCaseToHyphenated,- toRomanNumeral,- wrapped,- -- * Parsing- (>>~),- anyLine,- many1Till,- notFollowedBy',- oneOfStrings,- spaceChar,- skipSpaces,- blankline,- blanklines,- enclosed,- stringAnyCase,- parseFromString,- lineClump,- charsInBalanced,- charsInBalanced',- romanNumeral,- withHorizDisplacement,- nullBlock,- failIfStrict,- escaped,- anyOrderedListMarker,- orderedListMarker,- charRef,- readWith,- testStringWith,- ParserState (..),- defaultParserState,- Reference (..),- isNoteBlock,- isKeyBlock,- isLineClump,- HeaderType (..),- ParserContext (..),- QuoteContext (..),- NoteTable,- KeyTable,- lookupKeySrc,- refsMatch,- -- * Native format prettyprinting- prettyPandoc,- -- * Pandoc block and inline list processing- orderedListMarkers,- normalizeSpaces,- compactify,- Element (..),- hierarchicalize,- isHeaderBlock,- -- * Writer options- WriterOptions (..),- defaultWriterOptions- ) where--import Text.Pandoc.Definition-import Text.ParserCombinators.Parsec-import Text.PrettyPrint.HughesPJ ( Doc, fsep )-import Text.Pandoc.CharacterReferences ( characterReference )-import Data.Char ( toLower, toUpper, ord, isLower, isUpper )-import Data.List ( find, isPrefixOf )-import Control.Monad ( join )------- List processing------- | Split list by groups of one or more sep.-splitBy :: (Eq a) => a -> [a] -> [[a]]-splitBy _ [] = []-splitBy sep lst = - let (first, rest) = break (== sep) lst- rest' = dropWhile (== sep) rest- in first:(splitBy sep rest')---- | Split list into chunks divided at specified indices.-splitByIndices :: [Int] -> [a] -> [[a]]-splitByIndices [] lst = [lst]-splitByIndices (x:xs) lst =- let (first, rest) = splitAt x lst in- first:(splitByIndices (map (\y -> y - x) xs) rest)---- | Replace each occurrence of one sublist in a list with another.-substitute :: (Eq a) => [a] -> [a] -> [a] -> [a]-substitute _ _ [] = []-substitute [] _ lst = lst-substitute target replacement lst = - if target `isPrefixOf` lst- then replacement ++ (substitute target replacement $ drop (length target) lst)- else (head lst):(substitute target replacement $ tail lst)---- | Joins a list of lists, separated by another list.-joinWithSep :: [a] -- ^ List to use as separator- -> [[a]] -- ^ Lists to join- -> [a]-joinWithSep _ [] = []-joinWithSep sep lst = foldr1 (\a b -> a ++ sep ++ b) lst------- Text processing------- | Returns an association list of backslash escapes for the--- designated characters.-backslashEscapes :: [Char] -- ^ list of special characters to escape- -> [(Char, String)]-backslashEscapes = map (\ch -> (ch, ['\\',ch]))---- | Escape a string of characters, using an association list of--- characters and strings.-escapeStringUsing :: [(Char, String)] -> String -> String-escapeStringUsing _ [] = ""-escapeStringUsing escapeTable (x:xs) = - case (lookup x escapeTable) of- Just str -> str ++ rest- Nothing -> x:rest- where rest = escapeStringUsing escapeTable xs---- | Strip trailing newlines from string.-stripTrailingNewlines :: String -> String-stripTrailingNewlines = reverse . dropWhile (== '\n') . reverse---- | Remove leading and trailing space (including newlines) from string.-removeLeadingTrailingSpace :: String -> String-removeLeadingTrailingSpace = removeLeadingSpace . removeTrailingSpace---- | Remove leading space (including newlines) from string.-removeLeadingSpace :: String -> String-removeLeadingSpace = dropWhile (`elem` " \n\t")---- | Remove trailing space (including newlines) from string.-removeTrailingSpace :: String -> String-removeTrailingSpace = reverse . removeLeadingSpace . reverse---- | Strip leading and trailing characters from string-stripFirstAndLast :: String -> String-stripFirstAndLast str =- drop 1 $ take ((length str) - 1) str---- | Change CamelCase word to hyphenated lowercase (e.g., camel-case). -camelCaseToHyphenated :: String -> String-camelCaseToHyphenated [] = ""-camelCaseToHyphenated (a:b:rest) | isLower a && isUpper b =- a:'-':(toLower b):(camelCaseToHyphenated rest)-camelCaseToHyphenated (a:rest) = (toLower a):(camelCaseToHyphenated rest)---- | Convert number < 4000 to uppercase roman numeral.-toRomanNumeral :: Int -> String-toRomanNumeral x =- if x >= 4000 || x < 0- then "?"- else case x of- _ | x >= 1000 -> "M" ++ toRomanNumeral (x - 1000)- _ | x >= 900 -> "CM" ++ toRomanNumeral (x - 900)- _ | x >= 500 -> "D" ++ toRomanNumeral (x - 500)- _ | x >= 400 -> "CD" ++ toRomanNumeral (x - 400)- _ | x >= 100 -> "C" ++ toRomanNumeral (x - 100)- _ | x >= 90 -> "XC" ++ toRomanNumeral (x - 90)- _ | x >= 50 -> "L" ++ toRomanNumeral (x - 50)- _ | x >= 40 -> "XL" ++ toRomanNumeral (x - 40)- _ | x >= 10 -> "X" ++ toRomanNumeral (x - 10)- _ | x >= 9 -> "IX" ++ toRomanNumeral (x - 5)- _ | x >= 5 -> "V" ++ toRomanNumeral (x - 5)- _ | x >= 4 -> "IV" ++ toRomanNumeral (x - 4)- _ | x >= 1 -> "I" ++ toRomanNumeral (x - 1)- _ -> ""---- | Wrap inlines to line length.-wrapped :: Monad m => ([Inline] -> m Doc) -> [Inline] -> m Doc-wrapped listWriter sect = (mapM listWriter $ splitBy Space sect) >>= - return . fsep------- Parsing------- | Like >>, but returns the operation on the left.--- (Suggested by Tillmann Rendel on Haskell-cafe list.)-(>>~) :: (Monad m) => m a -> m b -> m a-a >>~ b = a >>= \x -> b >> return x---- | Parse any line of text-anyLine :: GenParser Char st [Char]-anyLine = manyTill anyChar newline---- | Like @manyTill@, but reads at least one item.-many1Till :: GenParser tok st a- -> GenParser tok st end- -> GenParser tok st [a]-many1Till p end = do- first <- p- rest <- manyTill p end- return (first:rest)---- | A more general form of @notFollowedBy@. This one allows any --- type of parser to be specified, and succeeds only if that parser fails.--- It does not consume any input.-notFollowedBy' :: Show b => GenParser a st b -> GenParser a st ()-notFollowedBy' p = try $ join $ do a <- try p- return (unexpected (show a))- <|>- return (return ())--- (This version due to Andrew Pimlott on the Haskell mailing list.)---- | Parses one of a list of strings (tried in order). -oneOfStrings :: [String] -> GenParser Char st String-oneOfStrings listOfStrings = choice $ map (try . string) listOfStrings---- | Parses a space or tab.-spaceChar :: CharParser st Char-spaceChar = char ' ' <|> char '\t'---- | Skips zero or more spaces or tabs.-skipSpaces :: GenParser Char st ()-skipSpaces = skipMany spaceChar---- | Skips zero or more spaces or tabs, then reads a newline.-blankline :: GenParser Char st Char-blankline = try $ skipSpaces >> newline---- | Parses one or more blank lines and returns a string of newlines.-blanklines :: GenParser Char st [Char]-blanklines = many1 blankline---- | Parses material enclosed between start and end parsers.-enclosed :: GenParser Char st t -- ^ start parser- -> GenParser Char st end -- ^ end parser- -> GenParser Char st a -- ^ content parser (to be used repeatedly)- -> GenParser Char st [a]-enclosed start end parser = try $ - start >> notFollowedBy space >> many1Till parser end---- | Parse string, case insensitive.-stringAnyCase :: [Char] -> CharParser st String-stringAnyCase [] = string ""-stringAnyCase (x:xs) = do- firstChar <- char (toUpper x) <|> char (toLower x)- rest <- stringAnyCase xs- return (firstChar:rest)---- | Parse contents of 'str' using 'parser' and return result.-parseFromString :: GenParser tok st a -> [tok] -> GenParser tok st a-parseFromString parser str = do- oldInput <- getInput- setInput str- result <- parser- setInput oldInput- return result---- | Parse raw line block up to and including blank lines.-lineClump :: GenParser Char st String-lineClump = do- lns <- many1 (notFollowedBy blankline >> anyLine)- blanks <- blanklines <|> (eof >> return "\n")- return $ (unlines lns) ++ blanks---- | Parse a string of characters between an open character--- and a close character, including text between balanced--- pairs of open and close, which must be different. For example,--- @charsInBalanced '(' ')'@ will parse "(hello (there))"--- and return "hello (there)". Stop if a blank line is--- encountered.-charsInBalanced :: Char -> Char -> GenParser Char st String-charsInBalanced open close = try $ do- char open- raw <- many $ (many1 (noneOf [open, close, '\n']))- <|> (do res <- charsInBalanced open close- return $ [open] ++ res ++ [close])- <|> try (string "\n" >>~ notFollowedBy' blanklines)- char close- return $ concat raw---- | Like @charsInBalanced@, but allow blank lines in the content.-charsInBalanced' :: Char -> Char -> GenParser Char st String-charsInBalanced' open close = try $ do- char open- raw <- many $ (many1 (noneOf [open, close]))- <|> (do res <- charsInBalanced' open close- return $ [open] ++ res ++ [close])- char close- return $ concat raw---- | Parses a roman numeral (uppercase or lowercase), returns number.-romanNumeral :: Bool -- ^ Uppercase if true- -> GenParser Char st Int-romanNumeral upperCase = do- let charAnyCase c = char (if upperCase then toUpper c else c)- let one = charAnyCase 'i'- let five = charAnyCase 'v'- let ten = charAnyCase 'x'- let fifty = charAnyCase 'l'- let hundred = charAnyCase 'c'- let fivehundred = charAnyCase 'd'- let thousand = charAnyCase 'm'- thousands <- many thousand >>= (return . (1000 *) . length)- ninehundreds <- option 0 $ try $ hundred >> thousand >> return 900- fivehundreds <- many fivehundred >>= (return . (500 *) . length)- fourhundreds <- option 0 $ try $ hundred >> fivehundred >> return 400- hundreds <- many hundred >>= (return . (100 *) . length)- nineties <- option 0 $ try $ ten >> hundred >> return 90- fifties <- many fifty >>= (return . (50 *) . length)- forties <- option 0 $ try $ ten >> fifty >> return 40- tens <- many ten >>= (return . (10 *) . length)- nines <- option 0 $ try $ one >> ten >> return 9- fives <- many five >>= (return . (5 *) . length)- fours <- option 0 $ try $ one >> five >> return 4- ones <- many one >>= (return . length)- let total = thousands + ninehundreds + fivehundreds + fourhundreds +- hundreds + nineties + fifties + forties + tens + nines +- fives + fours + ones- if total == 0- then fail "not a roman numeral"- else return total---- | Applies a parser, returns tuple of its results and its horizontal--- displacement (the difference between the source column at the end--- and the source column at the beginning). Vertical displacement--- (source row) is ignored.-withHorizDisplacement :: GenParser Char st a -- ^ Parser to apply- -> GenParser Char st (a, Int) -- ^ (result, displacement)-withHorizDisplacement parser = do- pos1 <- getPosition- result <- parser- pos2 <- getPosition- return (result, sourceColumn pos2 - sourceColumn pos1)---- | Parses a character and returns 'Null' (so that the parser can move on--- if it gets stuck).-nullBlock :: GenParser Char st Block-nullBlock = anyChar >> return Null---- | Fail if reader is in strict markdown syntax mode.-failIfStrict :: GenParser Char ParserState ()-failIfStrict = do- state <- getState- if stateStrict state then fail "strict mode" else return ()---- | Parses backslash, then applies character parser.-escaped :: GenParser Char st Char -- ^ Parser for character to escape- -> GenParser Char st Inline-escaped parser = try $ do- char '\\'- result <- parser- return (Str [result])---- | Parses an uppercase roman numeral and returns (UpperRoman, number).-upperRoman :: GenParser Char st (ListNumberStyle, Int)-upperRoman = do- num <- romanNumeral True- return (UpperRoman, num)---- | Parses a lowercase roman numeral and returns (LowerRoman, number).-lowerRoman :: GenParser Char st (ListNumberStyle, Int)-lowerRoman = do- num <- romanNumeral False- return (LowerRoman, num)---- | Parses a decimal numeral and returns (Decimal, number).-decimal :: GenParser Char st (ListNumberStyle, Int)-decimal = do- num <- many1 digit- return (Decimal, read num)---- | Parses a '#' returns (DefaultStyle, 1).-defaultNum :: GenParser Char st (ListNumberStyle, Int)-defaultNum = do- char '#'- return (DefaultStyle, 1)---- | Parses a lowercase letter and returns (LowerAlpha, number).-lowerAlpha :: GenParser Char st (ListNumberStyle, Int)-lowerAlpha = do- ch <- oneOf ['a'..'z']- return (LowerAlpha, ord ch - ord 'a' + 1)---- | Parses an uppercase letter and returns (UpperAlpha, number).-upperAlpha :: GenParser Char st (ListNumberStyle, Int)-upperAlpha = do- ch <- oneOf ['A'..'Z']- return (UpperAlpha, ord ch - ord 'A' + 1)---- | Parses a roman numeral i or I-romanOne :: GenParser Char st (ListNumberStyle, Int)-romanOne = (char 'i' >> return (LowerRoman, 1)) <|>- (char 'I' >> return (UpperRoman, 1))---- | Parses an ordered list marker and returns list attributes.-anyOrderedListMarker :: GenParser Char st ListAttributes -anyOrderedListMarker = choice $ - [delimParser numParser | delimParser <- [inPeriod, inOneParen, inTwoParens],- numParser <- [decimal, defaultNum, romanOne,- lowerAlpha, lowerRoman, upperAlpha, upperRoman]]---- | Parses a list number (num) followed by a period, returns list attributes.-inPeriod :: GenParser Char st (ListNumberStyle, Int)- -> GenParser Char st ListAttributes -inPeriod num = try $ do- (style, start) <- num- char '.'- let delim = if style == DefaultStyle- then DefaultDelim- else Period- return (start, style, delim)- --- | Parses a list number (num) followed by a paren, returns list attributes.-inOneParen :: GenParser Char st (ListNumberStyle, Int)- -> GenParser Char st ListAttributes -inOneParen num = try $ do- (style, start) <- num- char ')'- return (start, style, OneParen)---- | Parses a list number (num) enclosed in parens, returns list attributes.-inTwoParens :: GenParser Char st (ListNumberStyle, Int)- -> GenParser Char st ListAttributes -inTwoParens num = try $ do- char '('- (style, start) <- num- char ')'- return (start, style, TwoParens)---- | Parses an ordered list marker with a given style and delimiter,--- returns number.-orderedListMarker :: ListNumberStyle - -> ListNumberDelim - -> GenParser Char st Int-orderedListMarker style delim = do- let num = case style of- DefaultStyle -> decimal <|> defaultNum- Decimal -> decimal- UpperRoman -> upperRoman- LowerRoman -> lowerRoman- UpperAlpha -> upperAlpha- LowerAlpha -> lowerAlpha- let context = case delim of- DefaultDelim -> inPeriod- Period -> inPeriod- OneParen -> inOneParen- TwoParens -> inTwoParens- (start, _, _) <- context num- return start---- | Parses a character reference and returns a Str element.-charRef :: GenParser Char st Inline-charRef = do- c <- characterReference- return $ Str [c]---- | Parse a string with a given parser and state.-readWith :: GenParser Char ParserState a -- ^ parser- -> ParserState -- ^ initial state- -> String -- ^ input string- -> a-readWith parser state input = - case runParser parser state "source" input of- Left err -> error $ "\nError:\n" ++ show err- Right result -> result---- | Parse a string with @parser@ (for testing).-testStringWith :: (Show a) => GenParser Char ParserState a- -> String- -> IO ()-testStringWith parser str = putStrLn $ show $ - readWith parser defaultParserState str---- | Parsing options.-data ParserState = ParserState- { stateParseRaw :: Bool, -- ^ Parse raw HTML and LaTeX?- stateParserContext :: ParserContext, -- ^ Inside list?- stateQuoteContext :: QuoteContext, -- ^ Inside quoted environment?- stateKeys :: KeyTable, -- ^ List of reference keys- stateNotes :: NoteTable, -- ^ List of notes- stateTabStop :: Int, -- ^ Tab stop- stateStandalone :: Bool, -- ^ Parse bibliographic info?- stateTitle :: [Inline], -- ^ Title of document- stateAuthors :: [String], -- ^ Authors of document- stateDate :: String, -- ^ Date of document- stateStrict :: Bool, -- ^ Use strict markdown syntax?- stateSmart :: Bool, -- ^ Use smart typography?- stateColumns :: Int, -- ^ Number of columns in terminal- stateHeaderTable :: [HeaderType] -- ^ Ordered list of header types used- }- deriving Show--defaultParserState :: ParserState-defaultParserState = - ParserState { stateParseRaw = False,- stateParserContext = NullState,- stateQuoteContext = NoQuote,- stateKeys = [],- stateNotes = [],- stateTabStop = 4,- stateStandalone = False,- stateTitle = [],- stateAuthors = [],- stateDate = [],- stateStrict = False,- stateSmart = False,- stateColumns = 80,- stateHeaderTable = [] }---- | References from preliminary parsing.-data Reference- = KeyBlock [Inline] Target -- ^ Key for reference-style link (label URL title)- | NoteBlock String [Block] -- ^ Footnote reference and contents- | LineClump String -- ^ Raw clump of lines with blanks at end- deriving (Eq, Read, Show)---- | Auxiliary functions used in preliminary parsing.-isNoteBlock :: Reference -> Bool-isNoteBlock (NoteBlock _ _) = True-isNoteBlock _ = False--isKeyBlock :: Reference -> Bool-isKeyBlock (KeyBlock _ _) = True-isKeyBlock _ = False--isLineClump :: Reference -> Bool-isLineClump (LineClump _) = True-isLineClump _ = False--data HeaderType - = SingleHeader Char -- ^ Single line of characters underneath- | DoubleHeader Char -- ^ Lines of characters above and below- deriving (Eq, Show)--data ParserContext - = ListItemState -- ^ Used when running parser on list item contents- | NullState -- ^ Default state- deriving (Eq, Show)--data QuoteContext- = InSingleQuote -- ^ Used when parsing inside single quotes- | InDoubleQuote -- ^ Used when parsing inside double quotes- | NoQuote -- ^ Used when not parsing inside quotes- deriving (Eq, Show)--type NoteTable = [(String, [Block])]--type KeyTable = [([Inline], Target)]---- | Look up key in key table and return target object.-lookupKeySrc :: KeyTable -- ^ Key table- -> [Inline] -- ^ Key- -> Maybe Target-lookupKeySrc table key = case find (refsMatch key . fst) table of- Nothing -> Nothing- Just (_, src) -> Just src---- | Returns @True@ if keys match (case insensitive).-refsMatch :: [Inline] -> [Inline] -> Bool-refsMatch ((Str x):restx) ((Str y):resty) = - ((map toLower x) == (map toLower y)) && refsMatch restx resty-refsMatch ((Emph x):restx) ((Emph y):resty) = - refsMatch x y && refsMatch restx resty-refsMatch ((Strong x):restx) ((Strong y):resty) = - refsMatch x y && refsMatch restx resty-refsMatch ((Strikeout x):restx) ((Strikeout y):resty) = - refsMatch x y && refsMatch restx resty-refsMatch ((Superscript x):restx) ((Superscript y):resty) = - refsMatch x y && refsMatch restx resty-refsMatch ((Subscript x):restx) ((Subscript y):resty) = - refsMatch x y && refsMatch restx resty-refsMatch ((Quoted t x):restx) ((Quoted u y):resty) = - t == u && refsMatch x y && refsMatch restx resty-refsMatch ((Code x):restx) ((Code y):resty) = - ((map toLower x) == (map toLower y)) && refsMatch restx resty-refsMatch ((TeX x):restx) ((TeX y):resty) = - ((map toLower x) == (map toLower y)) && refsMatch restx resty-refsMatch ((HtmlInline x):restx) ((HtmlInline y):resty) = - ((map toLower x) == (map toLower y)) && refsMatch restx resty-refsMatch (x:restx) (y:resty) = (x == y) && refsMatch restx resty-refsMatch [] x = null x-refsMatch x [] = null x------- Native format prettyprinting---- --- | Indent string as a block.-indentBy :: Int -- ^ Number of spaces to indent the block - -> Int -- ^ Number of spaces (rel to block) to indent first line- -> String -- ^ Contents of block to indent- -> String-indentBy _ _ [] = ""-indentBy num first str = - let (firstLine:restLines) = lines str - firstLineIndent = num + first- in (replicate firstLineIndent ' ') ++ firstLine ++ "\n" ++ - (joinWithSep "\n" $ map ((replicate num ' ') ++ ) restLines)---- | Prettyprint list of Pandoc blocks elements.-prettyBlockList :: Int -- ^ Number of spaces to indent list of blocks- -> [Block] -- ^ List of blocks- -> String-prettyBlockList indent [] = indentBy indent 0 "[]"-prettyBlockList indent blocks = indentBy indent (-2) $ "[ " ++ - (joinWithSep "\n, " (map prettyBlock blocks)) ++ " ]"---- | Prettyprint Pandoc block element.-prettyBlock :: Block -> String-prettyBlock (BlockQuote blocks) = "BlockQuote\n " ++ - (prettyBlockList 2 blocks) -prettyBlock (OrderedList attribs blockLists) = - "OrderedList " ++ show attribs ++ "\n" ++ indentBy 2 0 ("[ " ++ - (joinWithSep ", " $ map (\blocks -> prettyBlockList 2 blocks) - blockLists)) ++ " ]"-prettyBlock (BulletList blockLists) = "BulletList\n" ++ - indentBy 2 0 ("[ " ++ (joinWithSep ", " - (map (\blocks -> prettyBlockList 2 blocks) blockLists))) ++ " ]" -prettyBlock (DefinitionList blockLists) = "DefinitionList\n" ++ - indentBy 2 0 ("[" ++ (joinWithSep ",\n" - (map (\(term, blocks) -> " (" ++ show term ++ ",\n" ++ - indentBy 1 2 (prettyBlockList 2 blocks) ++ " )") blockLists))) ++ " ]" -prettyBlock (Table caption aligns widths header rows) = - "Table " ++ show caption ++ " " ++ show aligns ++ " " ++ - show widths ++ "\n" ++ prettyRow header ++ " [\n" ++ - (joinWithSep ",\n" (map prettyRow rows)) ++ " ]"- where prettyRow cols = indentBy 2 0 ("[ " ++ (joinWithSep ", "- (map (\blocks -> prettyBlockList 2 blocks) - cols))) ++ " ]"-prettyBlock block = show block---- | Prettyprint Pandoc document.-prettyPandoc :: Pandoc -> String-prettyPandoc (Pandoc meta blocks) = "Pandoc " ++ "(" ++ show meta ++ - ")\n" ++ (prettyBlockList 0 blocks) ++ "\n"------- Pandoc block and inline list processing------- | Generate infinite lazy list of markers for an ordered list,--- depending on list attributes.-orderedListMarkers :: (Int, ListNumberStyle, ListNumberDelim) -> [String]-orderedListMarkers (start, numstyle, numdelim) = - let singleton c = [c]- nums = case numstyle of- DefaultStyle -> map show [start..]- Decimal -> map show [start..]- UpperAlpha -> drop (start - 1) $ cycle $ - map singleton ['A'..'Z']- LowerAlpha -> drop (start - 1) $ cycle $- map singleton ['a'..'z']- UpperRoman -> map toRomanNumeral [start..]- LowerRoman -> map (map toLower . toRomanNumeral) [start..]- inDelim str = case numdelim of- DefaultDelim -> str ++ "."- Period -> str ++ "."- OneParen -> str ++ ")"- TwoParens -> "(" ++ str ++ ")"- in map inDelim nums---- | Normalize a list of inline elements: remove leading and trailing--- @Space@ elements, collapse double @Space@s into singles, and--- remove empty Str elements.-normalizeSpaces :: [Inline] -> [Inline]-normalizeSpaces [] = []-normalizeSpaces list = - let removeDoubles [] = []- removeDoubles (Space:Space:rest) = removeDoubles (Space:rest)- removeDoubles (Space:(Str ""):Space:rest) = removeDoubles (Space:rest)- removeDoubles ((Str ""):rest) = removeDoubles rest - removeDoubles (x:rest) = x:(removeDoubles rest)- removeLeading (Space:xs) = removeLeading xs- removeLeading x = x- removeTrailing [] = []- removeTrailing lst = if (last lst == Space)- then init lst- else lst- in removeLeading $ removeTrailing $ removeDoubles list---- | Change final list item from @Para@ to @Plain@ if the list should --- be compact.-compactify :: [[Block]] -- ^ List of list items (each a list of blocks)- -> [[Block]]-compactify [] = []-compactify items =- let final = last items- others = init items- in case final of- [Para a] -> if any containsPara others- then items- else others ++ [[Plain a]]- _ -> items--containsPara :: [Block] -> Bool-containsPara [] = False-containsPara ((Para _):_) = True-containsPara ((BulletList items):rest) = any containsPara items ||- containsPara rest-containsPara ((OrderedList _ items):rest) = any containsPara items ||- containsPara rest-containsPara ((DefinitionList items):rest) = any containsPara (map snd items) ||- containsPara rest-containsPara (_:rest) = containsPara rest---- | Data structure for defining hierarchical Pandoc documents-data Element = Blk Block - | Sec [Inline] [Element] deriving (Eq, Read, Show)---- | Returns @True@ on Header block with at least the specified level-headerAtLeast :: Int -> Block -> Bool-headerAtLeast level (Header x _) = x <= level-headerAtLeast _ _ = False---- | Convert list of Pandoc blocks into (hierarchical) list of Elements-hierarchicalize :: [Block] -> [Element]-hierarchicalize [] = []-hierarchicalize (block:rest) = - case block of- (Header level title) -> - let (thisSection, rest') = break (headerAtLeast level) rest- in (Sec title (hierarchicalize thisSection)):(hierarchicalize rest') - x -> (Blk x):(hierarchicalize rest)---- | True if block is a Header block.-isHeaderBlock :: Block -> Bool-isHeaderBlock (Header _ _) = True-isHeaderBlock _ = False------- Writer options------- | Options for writers-data WriterOptions = WriterOptions- { writerStandalone :: Bool -- ^ Include header and footer- , writerHeader :: String -- ^ Header for the document- , writerTitlePrefix :: String -- ^ Prefix for HTML titles- , writerTabStop :: Int -- ^ Tabstop for conversion btw spaces and tabs- , writerTableOfContents :: Bool -- ^ Include table of contents- , writerS5 :: Bool -- ^ We're writing S5 - , writerUseASCIIMathML :: Bool -- ^ Use ASCIIMathML- , writerASCIIMathMLURL :: Maybe String -- ^ URL to asciiMathML.js - , writerIgnoreNotes :: Bool -- ^ Ignore footnotes (used in making toc)- , writerIncremental :: Bool -- ^ Incremental S5 lists- , writerNumberSections :: Bool -- ^ Number sections in LaTeX- , writerIncludeBefore :: String -- ^ String to include before the body- , writerIncludeAfter :: String -- ^ String to include after the body- , writerStrictMarkdown :: Bool -- ^ Use strict markdown syntax- , writerReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst- } deriving Show---- | Default writer options.-defaultWriterOptions :: WriterOptions-defaultWriterOptions = - WriterOptions { writerStandalone = False,- writerHeader = "",- writerTitlePrefix = "",- writerTabStop = 4,- writerTableOfContents = False,- writerS5 = False,- writerUseASCIIMathML = False,- writerASCIIMathMLURL = Nothing,- writerIgnoreNotes = False,- writerIncremental = False,- writerNumberSections = False,- writerIncludeBefore = "",- writerIncludeAfter = "",- writerStrictMarkdown = False,- writerReferenceLinks = False }
− src/Text/Pandoc/UTF8.hs
@@ -1,44 +0,0 @@--- | Functions for converting Unicode strings to UTF-8 and vice versa.--- --- Taken from <http://www.cse.ogi.edu/~hallgren/Talks/LHiH/base/lib/UTF8.hs>.--- (c) 2003, OGI School of Science & Engineering, Oregon Health and--- Science University. ------ Modified by Martin Norbaeck--- to pass illegal UTF-8 sequences through unchanged.-module Text.Pandoc.UTF8 ( - fromUTF8, - toUTF8 - ) where---- From the Char module supplied with HBC.---- | Take a UTF-8 string and decode it into a Unicode string.-fromUTF8 :: String -> String-fromUTF8 "" = ""-fromUTF8 (c:c':cs) | '\xc0' <= c && c <= '\xdf' && - '\x80' <= c' && c' <= '\xbf' =- toEnum ((fromEnum c `mod` 0x20) * 0x40 + fromEnum c' `mod` 0x40) : fromUTF8 cs-fromUTF8 (c:c':c'':cs) | '\xe0' <= c && c <= '\xef' && - '\x80' <= c' && c' <= '\xbf' &&- '\x80' <= c'' && c'' <= '\xbf' =- toEnum ((fromEnum c `mod` 0x10 * 0x1000) + (fromEnum c' `mod` 0x40) * 0x40 + fromEnum c'' `mod` 0x40) : fromUTF8 cs-fromUTF8 (c:cs) = c : fromUTF8 cs---- | Take a Unicode string and encode it as a UTF-8 string.-toUTF8 :: String -> String-toUTF8 "" = ""-toUTF8 (c:cs) =- if c > '\x0000' && c < '\x0080' then- c : toUTF8 cs- else if c < toEnum 0x0800 then- let i = fromEnum c- in toEnum (0xc0 + i `div` 0x40) : - toEnum (0x80 + i `mod` 0x40) : - toUTF8 cs- else- let i = fromEnum c- in toEnum (0xe0 + i `div` 0x1000) : - toEnum (0x80 + (i `mod` 0x1000) `div` 0x40) : - toEnum (0x80 + i `mod` 0x40) : - toUTF8 cs
− src/Text/Pandoc/Writers/ConTeXt.hs
@@ -1,248 +0,0 @@-{--Copyright (C) 2007 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 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.--}-module Text.Pandoc.Writers.ConTeXt ( writeConTeXt ) where-import Text.Pandoc.Definition-import Text.Pandoc.Shared-import Text.Printf ( printf )-import Data.List ( (\\), intersperse )-import Control.Monad.State--type WriterState = Int -- number of next URL reference ---- | Convert Pandoc to ConTeXt.-writeConTeXt :: WriterOptions -> Pandoc -> String-writeConTeXt options document = evalState (pandocToConTeXt options document) 1 --pandocToConTeXt :: WriterOptions -> Pandoc -> State WriterState String-pandocToConTeXt options (Pandoc meta blocks) = do- main <- blockListToConTeXt blocks - let body = writerIncludeBefore options ++ main ++ writerIncludeAfter options- head <- if writerStandalone options- then contextHeader options meta- else return ""- let toc = if writerTableOfContents options- then "\\placecontent\n\n"- else "" - let foot = if writerStandalone options- then "\n\\stoptext\n"- else ""- return $ head ++ toc ++ body ++ foot---- | Insert bibliographic information into ConTeXt header.-contextHeader :: WriterOptions -- ^ Options, including ConTeXt header- -> Meta -- ^ Meta with bibliographic information- -> State WriterState String-contextHeader options (Meta title authors date) = do- titletext <- if null title- then return "" - else inlineListToConTeXt title- let authorstext = if null authors- then ""- else if length authors == 1- then stringToConTeXt $ head authors- else stringToConTeXt $ (joinWithSep ", " $- init authors) ++ " & " ++ last authors- let datetext = if date == ""- then "" - else stringToConTeXt date- let titleblock = "\\doctitle{" ++ titletext ++ "}\n\- \ \\author{" ++ authorstext ++ "}\n\- \ \\date{" ++ datetext ++ "}\n\n"- let setupheads = if (writerNumberSections options)- then "\\setupheads[sectionnumber=yes, style=\\bf]\n" - else "\\setupheads[sectionnumber=no, style=\\bf]\n"- let header = writerHeader options- return $ header ++ setupheads ++ titleblock ++ "\\starttext\n\\maketitle\n\n"---- escape things as needed for ConTeXt--escapeCharForConTeXt :: Char -> String-escapeCharForConTeXt ch =- case ch of- '{' -> "\\letteropenbrace{}"- '}' -> "\\letterclosebrace{}"- '\\' -> "\\letterbackslash{}"- '$' -> "\\$"- '|' -> "\\letterbar{}"- '^' -> "\\letterhat{}"- '%' -> "\\%"- '~' -> "\\lettertilde{}"- '&' -> "\\&"- '#' -> "\\#"- '<' -> "\\letterless{}"- '>' -> "\\lettermore{}"- '_' -> "\\letterunderscore{}"- x -> [x]---- | Escape string for ConTeXt-stringToConTeXt :: String -> String-stringToConTeXt = concatMap escapeCharForConTeXt---- | Convert Pandoc block element to ConTeXt.-blockToConTeXt :: Block -> State WriterState String -blockToConTeXt Null = return ""-blockToConTeXt (Plain lst) = inlineListToConTeXt lst >>= return . (++ "\n")-blockToConTeXt (Para lst) = inlineListToConTeXt lst >>= return . (++ "\n\n")-blockToConTeXt (BlockQuote lst) = do- contents <- blockListToConTeXt lst- return $ "\\startblockquote\n" ++ contents ++ "\\stopblockquote\n\n"-blockToConTeXt (CodeBlock str) = - return $ "\\starttyping\n" ++ str ++ "\n\\stoptyping\n"-blockToConTeXt (RawHtml str) = return ""-blockToConTeXt (BulletList lst) = do - contents <- mapM listItemToConTeXt lst- return $ "\\startltxitem\n" ++ concat contents ++ "\\stopltxitem\n"-blockToConTeXt (OrderedList attribs lst) = case attribs of- (1, DefaultStyle, DefaultDelim) -> do- contents <- mapM listItemToConTeXt lst- return $ "\\startltxenum\n" ++ concat contents ++ "\\stopltxenum\n"- _ -> do- let markers = take (length lst) $ orderedListMarkers attribs- contents <- zipWithM orderedListItemToConTeXt markers lst- let markerWidth = maximum $ map length markers - let markerWidth' = if markerWidth < 3- then ""- else "[width=" ++ - show ((markerWidth + 2) `div` 2) ++ "em]"- return $ "\\startitemize" ++ markerWidth' ++ "\n" ++ concat contents ++ - "\\stopitemize\n"-blockToConTeXt (DefinitionList lst) =- mapM defListItemToConTeXt lst >>= return . (++ "\n") . concat-blockToConTeXt HorizontalRule = return "\\thinrule\n\n"-blockToConTeXt (Header level lst) = do- contents <- inlineListToConTeXt lst- return $ if level > 0 && level <= 3- then "\\" ++ concat (replicate (level - 1) "sub") ++ - "section{" ++ contents ++ "}\n\n"- else contents ++ "\n\n"-blockToConTeXt (Table caption aligns widths heads rows) = do- let colWidths = map printDecimal widths- let colDescriptor colWidth alignment = (case alignment of- AlignLeft -> 'l' - AlignRight -> 'r'- AlignCenter -> 'c'- AlignDefault -> 'l'):- "p(" ++ colWidth ++ "\\textwidth)|"- let colDescriptors = "|" ++ (concat $ - zipWith colDescriptor colWidths aligns)- headers <- tableRowToConTeXt heads - captionText <- inlineListToConTeXt caption - let captionText' = if null caption then "none" else captionText- rows' <- mapM tableRowToConTeXt rows - return $ "\\placetable[here]{" ++ captionText' ++ "}\n\\starttable[" ++ - colDescriptors ++ "]\n" ++ "\\HL\n" ++ headers ++ "\\HL\n" ++ - concat rows' ++ "\\HL\n\\stoptable\n\n" --printDecimal :: Float -> String-printDecimal = printf "%.2f" --tableRowToConTeXt cols = do- cols' <- mapM blockListToConTeXt cols- return $ "\\NC " ++ (concat $ intersperse "\\NC " cols') ++ "\\NC\\AR\n"--listItemToConTeXt list = do- contents <- blockListToConTeXt list- return $ "\\item " ++ contents--orderedListItemToConTeXt marker list = do- contents <- blockListToConTeXt list- return $ "\\sym{" ++ marker ++ "} " ++ contents--defListItemToConTeXt (term, def) = do- term' <- inlineListToConTeXt term- def' <- blockListToConTeXt def- return $ "\\startdescr{" ++ term' ++ "}\n" ++- def' ++ "\n\\stopdescr\n"---- | Convert list of block elements to ConTeXt.-blockListToConTeXt :: [Block] -> State WriterState String-blockListToConTeXt lst = mapM blockToConTeXt lst >>= return . concat---- | Convert list of inline elements to ConTeXt.-inlineListToConTeXt :: [Inline] -- ^ Inlines to convert- -> State WriterState String-inlineListToConTeXt lst = mapM inlineToConTeXt lst >>= return . concat--isQuoted :: Inline -> Bool-isQuoted (Quoted _ _) = True-isQuoted Apostrophe = True-isQuoted _ = False---- | Convert inline element to ConTeXt-inlineToConTeXt :: Inline -- ^ Inline to convert- -> State WriterState String-inlineToConTeXt (Emph lst) = do- contents <- inlineListToConTeXt lst- return $ "{\\em " ++ contents ++ "}" -inlineToConTeXt (Strong lst) = do- contents <- inlineListToConTeXt lst- return $ "{\\bf " ++ contents ++ "}" -inlineToConTeXt (Strikeout lst) = do- contents <- inlineListToConTeXt lst- return $ "\\overstrikes{" ++ contents ++ "}" -inlineToConTeXt (Superscript lst) = do- contents <- inlineListToConTeXt lst- return $ "\\high{" ++ contents ++ "}" -inlineToConTeXt (Subscript lst) = do- contents <- inlineListToConTeXt lst- return $ "\\low{" ++ contents ++ "}" -inlineToConTeXt (Code str) = return $ "\\type{" ++ str ++ "}"-inlineToConTeXt (Quoted SingleQuote lst) = do- contents <- inlineListToConTeXt lst- return $ "\\quote{" ++ contents ++ "}"-inlineToConTeXt (Quoted DoubleQuote lst) = do- contents <- inlineListToConTeXt lst- return $ "\\quotation{" ++ contents ++ "}"-inlineToConTeXt Apostrophe = return "'"-inlineToConTeXt EmDash = return "---"-inlineToConTeXt EnDash = return "--"-inlineToConTeXt Ellipses = return "\\ldots{}"-inlineToConTeXt (Str str) = return $ stringToConTeXt str-inlineToConTeXt (TeX str) = return str-inlineToConTeXt (HtmlInline str) = return ""-inlineToConTeXt (LineBreak) = return "\\crlf\n"-inlineToConTeXt Space = return " "-inlineToConTeXt (Link [Code str] (src, tit)) = -- since ConTeXt has its own - inlineToConTeXt (Link [Str str] (src, tit)) -- way of printing links... -inlineToConTeXt (Link text (src, _)) = do- next <- get- put (next + 1)- let ref = show next- label <- inlineListToConTeXt text- return $ "\\useurl[" ++ ref ++ "][" ++ src ++ "][][" ++ label ++ - "]\\from[" ++ ref ++ "]" -inlineToConTeXt (Image alternate (src, tit)) = do- alt <- inlineListToConTeXt alternate- return $ "\\placefigure\n[]\n[fig:" ++ alt ++ "]\n{" ++- tit ++ "}\n{\\externalfigure[" ++ src ++ "]}" -inlineToConTeXt (Note contents) = do- contents' <- blockListToConTeXt contents- return $ "\\footnote{" ++ contents' ++ "}"-
− src/Text/Pandoc/Writers/DefaultHeaders.hs
@@ -1,59 +0,0 @@-------------------------------------------------------- Do not edit this file by hand. Edit --- 'templates/DefaultHeaders.hs'--- and run ./fillTemplates.pl Text/Pandoc/Writers/DefaultHeaders.hs-------------------------------------------------------{--Copyright (C) 2006-7 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.DefaultHeaders- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Default headers for Pandoc writers.--}-module Text.Pandoc.Writers.DefaultHeaders (- defaultLaTeXHeader,- defaultConTeXtHeader,- defaultDocbookHeader,- defaultS5Header,- defaultRTFHeader- ) where-import Text.Pandoc.Writers.S5--defaultLaTeXHeader :: String-defaultLaTeXHeader = "\\documentclass{article}\n\\usepackage[mathletters]{ucs}\n\\usepackage[utf8x]{inputenc}\n\\setlength{\\parindent}{0pt}\n\\setlength{\\parskip}{6pt plus 2pt minus 1pt}\n"--defaultConTeXtHeader :: String-defaultConTeXtHeader = "\\enableregime[utf] % use UTF-8\n\n\\setupcolors[state=start]\n\\setupinteraction[state=start, color=middlered] % needed for hyperlinks\n\n\\setuppapersize[letter][letter] % use letter paper\n\\setuplayout[width=middle, backspace=1.5in, cutspace=1.5in,\n height=middle, header=0.75in, footer=0.75in] % page layout\n\\setuppagenumbering[location={footer,center}] % number pages\n\\setupbodyfont[11pt] % 11pt font\n\\setupwhitespace[medium] % inter-paragraph spacing\n\n\\setuphead[section][style=\\tfc]\n\\setuphead[subsection][style=\\tfb]\n\\setuphead[subsubsection][style=\\bf]\n\n% define title block commands\n\\unprotect\n\\def\\doctitle#1{\\gdef\\@title{#1}}\n\\def\\author#1{\\gdef\\@author{#1}}\n\\def\\date#1{\\gdef\\@date{#1}}\n\\date{\\currentdate} % Default to today unless specified otherwise.\n\\def\\maketitle{%\n \\startalignment[center]\n \\blank[2*big]\n {\\tfd \\@title}\n \\blank[3*medium]\n {\\tfa \\@author}\n \\blank[2*medium]\n {\\tfa \\@date}\n \\blank[3*medium]\n \\stopalignment}\n\\protect\n\n% define descr (for definition lists)\n\\definedescription[descr][\n headstyle=bold,style=normal,align=left,location=hanging,\n width=broad,margin=1cm]\n\n% define ltxitem (for bulleted lists) \n\\defineitemgroup[ltxitem][levels=4]\n\\setupitemgroup[ltxitem][1][1]\n\\setupitemgroup[ltxitem][2][2]\n\\setupitemgroup[ltxitem][3][3]\n\\setupitemgroup[ltxitem][4][4,packed]\n\n% define ltxenum (for enumerated lists)\n\\defineitemgroup[ltxenum][levels=4]\n\\setupitemgroup[ltxenum][1][n]\n\\setupitemgroup[ltxenum][2][a]\n\\setupitemgroup[ltxenum][3][r]\n\\setupitemgroup[ltxenum][4][A,packed]\n\n\\setupthinrules[width=15em] % width of horizontal rules\n\n% for block quotations\n\\definestartstop [blockquote]\n [before={\\startnarrower\\switchtobodyfont[11pt]\n \\whitespace\\setupindenting[no]},\n after={\\stopnarrower\\whitespace}]\n\n"--defaultDocbookHeader :: String-defaultDocbookHeader = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!DOCTYPE article PUBLIC \"-//OASIS//DTD DocBook XML V4.4//EN\"\n \"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd\">\n"--defaultS5Header :: String-defaultS5Header = s5Meta ++ s5CSS ++ s5Javascript--defaultRTFHeader :: String-defaultRTFHeader = "{\\rtf1\\ansi\\deff0{\\fonttbl{\\f0 \\fswiss Helvetica;}{\\f1 Courier;}}\n{\\colortbl;\\red255\\green0\\blue0;\\red0\\green0\\blue255;}\n\\widowctrl\\hyphauto\n\n"-
− src/Text/Pandoc/Writers/Docbook.hs
@@ -1,297 +0,0 @@-{--Copyright (C) 2006-7 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.Docbook- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion of 'Pandoc' documents to Docbook XML.--}-module Text.Pandoc.Writers.Docbook ( writeDocbook) where-import Text.Pandoc.Definition-import Text.Pandoc.Shared-import Data.List ( isPrefixOf, drop )-import Text.PrettyPrint.HughesPJ hiding ( Str )------- code to format XML------- | Escape one character as needed for XML.-escapeCharForXML :: Char -> String-escapeCharForXML x = case x of- '&' -> "&"- '<' -> "<"- '>' -> ">"- '"' -> """- '\160' -> " "- c -> [c] ---- | True if the character needs to be escaped.-needsEscaping :: Char -> Bool-needsEscaping c = c `elem` "&<>\"\160"---- | Escape string as needed for XML. Entity references are not preserved.-escapeStringForXML :: String -> String-escapeStringForXML "" = ""-escapeStringForXML str = - case break needsEscaping str of- (okay, "") -> okay- (okay, (c:cs)) -> okay ++ escapeCharForXML c ++ escapeStringForXML cs ---- | Return a text object with a string of formatted XML attributes. -attributeList :: [(String, String)] -> Doc-attributeList = text . concatMap - (\(a, b) -> " " ++ escapeStringForXML a ++ "=\"" ++ - escapeStringForXML b ++ "\"") ---- | Put the supplied contents between start and end tags of tagType,--- with specified attributes and (if specified) indentation.-inTags:: Bool -> String -> [(String, String)] -> Doc -> Doc-inTags isIndented tagType attribs contents = - let openTag = char '<' <> text tagType <> attributeList attribs <> - char '>'- closeTag = text "</" <> text tagType <> char '>'- in if isIndented- then openTag $$ nest 2 contents $$ closeTag- else openTag <> contents <> closeTag---- | Return a self-closing tag of tagType with specified attributes-selfClosingTag :: String -> [(String, String)] -> Doc-selfClosingTag tagType attribs = - char '<' <> text tagType <> attributeList attribs <> text " />" - --- | Put the supplied contents between start and end tags of tagType.-inTagsSimple :: String -> Doc -> Doc-inTagsSimple tagType = inTags False tagType []---- | Put the supplied contents in indented block btw start and end tags.-inTagsIndented :: String -> Doc -> Doc-inTagsIndented tagType = inTags True tagType []------- Docbook writer------- | Convert list of authors to a docbook <author> section-authorToDocbook :: [Char] -> Doc-authorToDocbook name = inTagsIndented "author" $ - if ',' `elem` name- then -- last name first- let (lastname, rest) = break (==',') name - firstname = removeLeadingSpace rest in- inTagsSimple "firstname" (text $ escapeStringForXML firstname) <> - inTagsSimple "surname" (text $ escapeStringForXML lastname) - else -- last name last- let namewords = words name- lengthname = length namewords - (firstname, lastname) = case lengthname of- 0 -> ("","") - 1 -> ("", name)- n -> (joinWithSep " " (take (n-1) namewords), last namewords)- in inTagsSimple "firstname" (text $ escapeStringForXML firstname) $$ - inTagsSimple "surname" (text $ escapeStringForXML lastname) ---- | Convert Pandoc document to string in Docbook format.-writeDocbook :: WriterOptions -> Pandoc -> String-writeDocbook opts (Pandoc (Meta title authors date) blocks) = - let head = if writerStandalone opts- then text (writerHeader opts)- else empty- meta = if writerStandalone opts- then inTagsIndented "articleinfo" $- (inTagsSimple "title" (wrap opts title)) $$ - (vcat (map authorToDocbook authors)) $$ - (inTagsSimple "date" (text $ escapeStringForXML date)) - else empty- elements = hierarchicalize blocks- before = writerIncludeBefore opts- after = writerIncludeAfter opts- body = (if null before then empty else text before) $$- vcat (map (elementToDocbook opts) elements) $$- (if null after then empty else text after)- body' = if writerStandalone opts- then inTagsIndented "article" (meta $$ body)- else body - in render $ head $$ body' $$ text ""---- | Convert an Element to Docbook.-elementToDocbook :: WriterOptions -> Element -> Doc-elementToDocbook opts (Blk block) = blockToDocbook opts block -elementToDocbook opts (Sec title elements) =- -- Docbook doesn't allow sections with no content, so insert some if needed- let elements' = if null elements- then [Blk (Para [])]- else elements- in inTagsIndented "section" $- inTagsSimple "title" (wrap opts title) $$- vcat (map (elementToDocbook opts) elements') ---- | Convert a list of Pandoc blocks to Docbook.-blocksToDocbook :: WriterOptions -> [Block] -> Doc-blocksToDocbook opts = vcat . map (blockToDocbook opts)---- | Auxiliary function to convert Plain block to Para.-plainToPara (Plain x) = Para x-plainToPara x = x---- | Convert a list of pairs of terms and definitions into a list of --- Docbook varlistentrys.-deflistItemsToDocbook :: WriterOptions -> [([Inline],[Block])] -> Doc-deflistItemsToDocbook opts items = - vcat $ map (\(term, def) -> deflistItemToDocbook opts term def) items---- | Convert a term and a list of blocks into a Docbook varlistentry.-deflistItemToDocbook :: WriterOptions -> [Inline] -> [Block] -> Doc-deflistItemToDocbook opts term def =- let def' = map plainToPara def- in inTagsIndented "varlistentry" $- inTagsIndented "term" (inlinesToDocbook opts term) $$- inTagsIndented "listitem" (blocksToDocbook opts def')---- | Convert a list of lists of blocks to a list of Docbook list items.-listItemsToDocbook :: WriterOptions -> [[Block]] -> Doc-listItemsToDocbook opts items = vcat $ map (listItemToDocbook opts) items---- | Convert a list of blocks into a Docbook list item.-listItemToDocbook :: WriterOptions -> [Block] -> Doc-listItemToDocbook opts item =- inTagsIndented "listitem" $ blocksToDocbook opts $ map plainToPara item---- | Convert a Pandoc block element to Docbook.-blockToDocbook :: WriterOptions -> Block -> Doc-blockToDocbook opts Null = empty-blockToDocbook opts (Plain lst) = wrap opts lst-blockToDocbook opts (Para lst) = inTagsIndented "para" $ wrap opts lst-blockToDocbook opts (BlockQuote blocks) =- inTagsIndented "blockquote" $ blocksToDocbook opts blocks-blockToDocbook opts (CodeBlock str) = - text "<screen>\n" <> text (escapeStringForXML str) <> text "\n</screen>"-blockToDocbook opts (BulletList lst) = - inTagsIndented "itemizedlist" $ listItemsToDocbook opts lst -blockToDocbook opts (OrderedList _ []) = empty -blockToDocbook opts (OrderedList (start, numstyle, numdelim) (first:rest)) =- let attribs = case numstyle of- DefaultStyle -> []- Decimal -> [("numeration", "arabic")]- UpperAlpha -> [("numeration", "upperalpha")]- LowerAlpha -> [("numeration", "loweralpha")]- UpperRoman -> [("numeration", "upperroman")]- LowerRoman -> [("numeration", "lowerroman")]- items = if start == 1- then listItemsToDocbook opts (first:rest)- else (inTags True "listitem" [("override",show start)]- (blocksToDocbook opts $ map plainToPara first)) $$ - listItemsToDocbook opts rest - in inTags True "orderedlist" attribs items-blockToDocbook opts (DefinitionList lst) = - inTagsIndented "variablelist" $ deflistItemsToDocbook opts lst -blockToDocbook opts (RawHtml str) = text str -- raw XML block -blockToDocbook opts HorizontalRule = empty -- not semantic-blockToDocbook opts (Table caption aligns widths headers rows) =- let alignStrings = map alignmentToString aligns- captionDoc = if null caption- then empty- else inTagsIndented "caption" - (inlinesToDocbook opts caption)- tableType = if isEmpty captionDoc then "informaltable" else "table"- in inTagsIndented tableType $ captionDoc $$- (colHeadsToDocbook opts alignStrings widths headers) $$ - (vcat $ map (tableRowToDocbook opts alignStrings) rows)--colHeadsToDocbook opts alignStrings widths headers =- let heads = zipWith3 (\align width item -> - tableItemToDocbook opts "th" align width item) - alignStrings widths headers- in inTagsIndented "tr" $ vcat heads--alignmentToString alignment = case alignment of- AlignLeft -> "left"- AlignRight -> "right"- AlignCenter -> "center"- AlignDefault -> "left"--tableRowToDocbook opts aligns cols = inTagsIndented "tr" $ - vcat $ zipWith3 (tableItemToDocbook opts "td") aligns (repeat 0) cols--tableItemToDocbook opts tag align width item =- let attrib = [("align", align)] ++ - if width /= 0- then [("style", "{width: " ++ - show (truncate (100*width)) ++ "%;}")]- else [] - in inTags True tag attrib $ vcat $ map (blockToDocbook opts) item---- | Take list of inline elements and return wrapped doc.-wrap :: WriterOptions -> [Inline] -> Doc-wrap opts lst = fsep $ map (inlinesToDocbook opts) (splitBy Space lst)---- | Convert a list of inline elements to Docbook.-inlinesToDocbook :: WriterOptions -> [Inline] -> Doc-inlinesToDocbook opts lst = hcat $ map (inlineToDocbook opts) lst---- | Convert an inline element to Docbook.-inlineToDocbook :: WriterOptions -> Inline -> Doc-inlineToDocbook opts (Str str) = text $ escapeStringForXML str -inlineToDocbook opts (Emph lst) = - inTagsSimple "emphasis" $ inlinesToDocbook opts lst-inlineToDocbook opts (Strong lst) = - inTags False "emphasis" [("role", "strong")] $ inlinesToDocbook opts lst-inlineToDocbook opts (Strikeout lst) = - inTags False "emphasis" [("role", "strikethrough")] $- inlinesToDocbook opts lst-inlineToDocbook opts (Superscript lst) = - inTagsSimple "superscript" $ inlinesToDocbook opts lst-inlineToDocbook opts (Subscript lst) = - inTagsSimple "subscript" $ inlinesToDocbook opts lst-inlineToDocbook opts (Quoted _ lst) = - inTagsSimple "quote" $ inlinesToDocbook opts lst-inlineToDocbook opts Apostrophe = char '\''-inlineToDocbook opts Ellipses = text "…"-inlineToDocbook opts EmDash = text "—" -inlineToDocbook opts EnDash = text "–" -inlineToDocbook opts (Code str) = - inTagsSimple "literal" $ text (escapeStringForXML str)-inlineToDocbook opts (TeX str) = inlineToDocbook opts (Code str)-inlineToDocbook opts (HtmlInline str) = empty-inlineToDocbook opts LineBreak = text $ "<literallayout></literallayout>" -inlineToDocbook opts Space = char ' '-inlineToDocbook opts (Link txt (src, tit)) =- if isPrefixOf "mailto:" src- then let src' = drop 7 src- emailLink = inTagsSimple "email" $ text $ - escapeStringForXML $ src'- in if txt == [Code src']- then emailLink- else inlinesToDocbook opts txt <+> char '(' <> emailLink <> - char ')'- else inTags False "ulink" [("url", src)] $ inlinesToDocbook opts txt-inlineToDocbook opts (Image alt (src, tit)) = - let titleDoc = if null tit- then empty- else inTagsIndented "objectinfo" $- inTagsIndented "title" (text $ escapeStringForXML tit)- in inTagsIndented "inlinemediaobject" $ inTagsIndented "imageobject" $- titleDoc $$ selfClosingTag "imagedata" [("fileref", src)] -inlineToDocbook opts (Note contents) = - inTagsIndented "footnote" $ blocksToDocbook opts contents
− src/Text/Pandoc/Writers/HTML.hs
@@ -1,448 +0,0 @@-{--Copyright (C) 2006-7 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.HTML - Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion of 'Pandoc' documents to HTML.--}-module Text.Pandoc.Writers.HTML ( writeHtml , writeHtmlString ) where-import Text.Pandoc.Definition-import Text.Pandoc.ASCIIMathML-import Text.Pandoc.CharacterReferences ( decodeCharacterReferences )-import Text.Pandoc.Shared-import Text.Regex ( mkRegex, matchRegex )-import Numeric ( showHex )-import Data.Char ( ord, toLower )-import Data.List ( isPrefixOf, intersperse )-import qualified Data.Set as S-import Control.Monad.State-import Text.XHtml.Transitional--data WriterState = WriterState- { stNotes :: [Html] -- ^ List of notes- , stIds :: [String] -- ^ List of header identifiers- , stMath :: Bool -- ^ Math is used in document- , stCSS :: S.Set String -- ^ CSS to include in header- } deriving Show--defaultWriterState :: WriterState-defaultWriterState = WriterState {stNotes= [], stIds = [], - stMath = False, stCSS = S.empty}---- | Convert Pandoc document to Html string.-writeHtmlString :: WriterOptions -> Pandoc -> String-writeHtmlString opts = - if writerStandalone opts- then renderHtml . writeHtml opts- else renderHtmlFragment . writeHtml opts---- | Convert Pandoc document to Html structure.-writeHtml :: WriterOptions -> Pandoc -> Html-writeHtml opts (Pandoc (Meta tit authors date) blocks) = - let titlePrefix = writerTitlePrefix opts- topTitle = evalState (inlineListToHtml opts tit) defaultWriterState- topTitle' = if null titlePrefix- then topTitle- else titlePrefix +++ " - " +++ topTitle- metadata = thetitle topTitle' +++ - meta ! [httpequiv "Content-Type", - content "text/html; charset=UTF-8"] +++- meta ! [name "generator", content "pandoc"] +++- (toHtmlFromList $ - map (\a -> meta ! [name "author", content a]) authors) +++- (if null date- then noHtml- else meta ! [name "date", content date])- titleHeader = if writerStandalone opts && not (null tit) && - not (writerS5 opts)- then h1 ! [theclass "title"] $ topTitle- else noHtml- headerBlocks = filter isHeaderBlock blocks- ids = uniqueIdentifiers $ - map (\(Header _ lst) -> lst) headerBlocks- toc = if writerTableOfContents opts - then tableOfContents opts headerBlocks ids- else noHtml- (blocks', newstate) = - runState (blockListToHtml opts blocks)- (defaultWriterState {stIds = ids})- cssLines = stCSS newstate- css = if S.null cssLines- then noHtml- else style ! [thetype "text/css"] $ primHtml $- '\n':(unlines $ S.toList cssLines)- math = if stMath newstate- then case writerASCIIMathMLURL opts of- Just path -> script ! [src path, - thetype "text/javascript"] $- noHtml- Nothing -> primHtml asciiMathMLScript- else noHtml- head = header $ metadata +++ math +++ css +++ - primHtml (writerHeader opts)- notes = reverse (stNotes newstate)- before = primHtml $ writerIncludeBefore opts- after = primHtml $ writerIncludeAfter opts- thebody = before +++ titleHeader +++ toc +++ blocks' +++- footnoteSection opts notes +++ after- in if writerStandalone opts- then head +++ body thebody- else thebody---- | Construct table of contents from list of header blocks and identifiers.--- Assumes there are as many identifiers as header blocks.-tableOfContents :: WriterOptions -> [Block] -> [String] -> Html-tableOfContents opts headers ids =- let opts' = opts { writerIgnoreNotes = True }- contentsTree = hierarchicalize headers- contents = evalState (mapM (elementToListItem opts') contentsTree) - (defaultWriterState {stIds = ids})- in thediv ! [identifier "toc"] $ unordList contents---- | Converts an Element to a list item for a table of contents,--- retrieving the appropriate identifier from state.-elementToListItem :: WriterOptions -> Element -> State WriterState Html-elementToListItem opts (Blk _) = return noHtml-elementToListItem opts (Sec headerText subsecs) = do- st <- get- let ids = stIds st- let (id, rest) = if null ids- then ("", [])- else (head ids, tail ids)- put $ st {stIds = rest}- txt <- inlineListToHtml opts headerText- subHeads <- mapM (elementToListItem opts) subsecs- let subList = if null subHeads- then noHtml- else unordList subHeads - return $ (anchor ! [href ("#" ++ id), identifier ("TOC-" ++ id)] $ txt) +++ - subList---- | Convert list of Note blocks to a footnote <div>.--- Assumes notes are sorted.-footnoteSection :: WriterOptions -> [Html] -> Html-footnoteSection opts notes =- if null notes - then noHtml- else thediv ! [theclass "footnotes"] $ hr +++ (olist << notes)---- | Obfuscate a "mailto:" link using Javascript.-obfuscateLink :: WriterOptions -> String -> String -> Html-obfuscateLink opts text src =- let emailRegex = mkRegex "^mailto:([^@]*)@(.*)$"- src' = map toLower src- in case (matchRegex emailRegex src') of- (Just [name, domain]) ->- let domain' = substitute "." " dot " domain- at' = obfuscateChar '@'- (linkText, altText) = - if text == drop 7 src' -- autolink- then ("'<code>'+e+'</code>'", name ++ " at " ++ domain')- else ("'" ++ text ++ "'", text ++ " (" ++ name ++ " at " ++ - domain' ++ ")")- in if writerStrictMarkdown opts- then -- need to use primHtml or &'s are escaped to & in URL- primHtml $ "<a href=\"" ++ (obfuscateString src')- ++ "\">" ++ (obfuscateString text) ++ "</a>"- else (script ! [thetype "text/javascript"] $- primHtml ("\n<!--\nh='" ++ - obfuscateString domain ++ "';a='" ++ at' ++ "';n='" ++ - obfuscateString name ++ "';e=n+a+h;\n" ++- "document.write('<a h'+'ref'+'=\"ma'+'ilto'+':'+e+'\">'+" ++ - linkText ++ "+'<\\/'+'a'+'>');\n// -->\n")) +++ - noscript (primHtml $ obfuscateString altText)- _ -> anchor ! [href src] $ primHtml text -- malformed email---- | Obfuscate character as entity.-obfuscateChar :: Char -> String-obfuscateChar char = - let num = ord char- numstr = if even num then show num else "x" ++ showHex num ""- in "&#" ++ numstr ++ ";"---- | Obfuscate string using entities.-obfuscateString :: String -> String-obfuscateString = concatMap obfuscateChar . decodeCharacterReferences---- | True if character is a punctuation character (unicode).-isPunctuation :: Char -> Bool-isPunctuation c =- let c' = ord c- in if c `elem` "!\"'()*,-./:;<>?[\\]`{|}~" || c' >= 0x2000 && c' <= 0x206F ||- c' >= 0xE000 && c' <= 0xE0FF- then True- else False---- | Add CSS for document header.-addToCSS :: String -> State WriterState ()-addToCSS item = do- st <- get- let current = stCSS st- put $ st {stCSS = S.insert item current}---- | Convert Pandoc inline list to plain text identifier.-inlineListToIdentifier :: [Inline] -> String-inlineListToIdentifier [] = ""-inlineListToIdentifier (x:xs) = - xAsText ++ inlineListToIdentifier xs- where xAsText = case x of- Str s -> filter (\c -> c == '-' || not (isPunctuation c)) $- concat $ intersperse "-" $ words $ map toLower s- Emph lst -> inlineListToIdentifier lst- Strikeout lst -> inlineListToIdentifier lst- Superscript lst -> inlineListToIdentifier lst- Subscript lst -> inlineListToIdentifier lst- Strong lst -> inlineListToIdentifier lst- Quoted _ lst -> inlineListToIdentifier lst- Code s -> s- Space -> "-"- EmDash -> "-"- EnDash -> "-"- Apostrophe -> ""- Ellipses -> ""- LineBreak -> "-"- TeX _ -> ""- HtmlInline _ -> ""- Link lst _ -> inlineListToIdentifier lst- Image lst _ -> inlineListToIdentifier lst- Note _ -> ""---- | Return unique identifiers for list of inline lists.-uniqueIdentifiers :: [[Inline]] -> [String]-uniqueIdentifiers ls =- let addIdentifier (nonuniqueIds, uniqueIds) l =- let new = inlineListToIdentifier l- matches = length $ filter (== new) nonuniqueIds- new' = new ++ if matches > 0 then ("-" ++ show matches) else ""- in (new:nonuniqueIds, new':uniqueIds)- in reverse $ snd $ foldl addIdentifier ([],[]) ls---- | Convert Pandoc block element to HTML.-blockToHtml :: WriterOptions -> Block -> State WriterState Html-blockToHtml opts Null = return $ noHtml -blockToHtml opts (Plain lst) = inlineListToHtml opts lst-blockToHtml opts (Para lst) = inlineListToHtml opts lst >>= (return . paragraph)-blockToHtml opts (RawHtml str) = return $ primHtml str-blockToHtml opts (HorizontalRule) = return $ hr-blockToHtml opts (CodeBlock str) = return $ pre $ thecode << (str ++ "\n") - -- the final \n for consistency with Markdown.pl-blockToHtml opts (BlockQuote blocks) =- -- in S5, treat list in blockquote specially- -- if default is incremental, make it nonincremental; - -- otherwise incremental- if writerS5 opts- then let inc = not (writerIncremental opts) in- case blocks of - [BulletList lst] -> blockToHtml (opts {writerIncremental = inc})- (BulletList lst)- [OrderedList attribs lst] -> - blockToHtml (opts {writerIncremental = inc})- (OrderedList attribs lst)- otherwise -> blockListToHtml opts blocks >>= - (return . blockquote)- else blockListToHtml opts blocks >>= (return . blockquote)-blockToHtml opts (Header level lst) = do - contents <- inlineListToHtml opts lst- st <- get- let ids = stIds st- let (id, rest) = if null ids- then ("", [])- else (head ids, tail ids)- put $ st {stIds = rest}- let attribs = if writerStrictMarkdown opts && not (writerTableOfContents opts)- then []- else [identifier id]- let contents' = if writerTableOfContents opts- then anchor ! [href ("#TOC-" ++ id)] $ contents- else contents- return $ case level of- 1 -> h1 contents' ! attribs- 2 -> h2 contents' ! attribs- 3 -> h3 contents' ! attribs- 4 -> h4 contents' ! attribs- 5 -> h5 contents' ! attribs- 6 -> h6 contents' ! attribs- _ -> paragraph contents' ! attribs-blockToHtml opts (BulletList lst) = do- contents <- mapM (blockListToHtml opts) lst- let attribs = if writerIncremental opts- then [theclass "incremental"]- else []- return $ unordList ! attribs $ contents-blockToHtml opts (OrderedList (startnum, numstyle, _) lst) = do- contents <- mapM (blockListToHtml opts) lst- let numstyle' = camelCaseToHyphenated $ show numstyle- let attribs = (if writerIncremental opts- then [theclass "incremental"]- else []) ++- (if startnum /= 1- then [start startnum]- else []) ++- (if numstyle /= DefaultStyle- then [theclass numstyle']- else [])- if numstyle /= DefaultStyle- then addToCSS $ "ol." ++ numstyle' ++ - " { list-style-type: " ++ - numstyle' ++ "; }"- else return ()- return $ ordList ! attribs $ contents-blockToHtml opts (DefinitionList lst) = do- contents <- mapM (\(term, def) -> do term' <- inlineListToHtml opts term- def' <- blockListToHtml opts def- return $ (term', def')) lst- let attribs = if writerIncremental opts- then [theclass "incremental"]- else []- return $ defList ! attribs $ contents-blockToHtml opts (Table capt aligns widths headers rows) = do- let alignStrings = map alignmentToString aligns- captionDoc <- if null capt- then return noHtml- else inlineListToHtml opts capt >>= return . caption- colHeads <- colHeadsToHtml opts alignStrings - widths headers- rows' <- mapM (tableRowToHtml opts alignStrings) rows- return $ table $ captionDoc +++ colHeads +++ rows'--colHeadsToHtml opts alignStrings widths headers = do- heads <- sequence $ zipWith3 - (\align width item -> tableItemToHtml opts th align width item) - alignStrings widths headers- return $ tr $ toHtmlFromList heads--alignmentToString alignment = case alignment of- AlignLeft -> "left"- AlignRight -> "right"- AlignCenter -> "center"- AlignDefault -> "left"--tableRowToHtml opts aligns cols = - (sequence $ zipWith3 (tableItemToHtml opts td) aligns (repeat 0) cols) >>=- return . tr . toHtmlFromList--tableItemToHtml opts tag align' width item = do- contents <- blockListToHtml opts item- let attrib = [align align'] ++ - if width /= 0 - then [thestyle ("width: " ++ show (truncate (100*width)) ++ - "%;")]- else [] - return $ tag ! attrib $ contents--blockListToHtml :: WriterOptions -> [Block] -> State WriterState Html-blockListToHtml opts lst = - mapM (blockToHtml opts) lst >>= return . toHtmlFromList---- | Convert list of Pandoc inline elements to HTML.-inlineListToHtml :: WriterOptions -> [Inline] -> State WriterState Html-inlineListToHtml opts lst = - mapM (inlineToHtml opts) lst >>= return . toHtmlFromList---- | Convert Pandoc inline element to HTML.-inlineToHtml :: WriterOptions -> Inline -> State WriterState Html-inlineToHtml opts inline =- case inline of - (Str str) -> return $ stringToHtml str- (Space) -> return $ stringToHtml " "- (LineBreak) -> return $ br- (EmDash) -> return $ primHtmlChar "mdash"- (EnDash) -> return $ primHtmlChar "ndash"- (Ellipses) -> return $ primHtmlChar "hellip"- (Apostrophe) -> return $ primHtmlChar "rsquo"- (Emph lst) -> inlineListToHtml opts lst >>= return . emphasize- (Strong lst) -> inlineListToHtml opts lst >>= return . strong- (Code str) -> return $ thecode << str- (Strikeout lst) -> addToCSS - ".strikeout { text-decoration: line-through; }" >> - inlineListToHtml opts lst >>=- return . (thespan ! [theclass "strikeout"])- (Superscript lst) -> inlineListToHtml opts lst >>= return . sup- (Subscript lst) -> inlineListToHtml opts lst >>= return . sub- (Quoted quoteType lst) ->- let (leftQuote, rightQuote) = case quoteType of- SingleQuote -> (primHtmlChar "lsquo", - primHtmlChar "rsquo")- DoubleQuote -> (primHtmlChar "ldquo", - primHtmlChar "rdquo")- in do contents <- inlineListToHtml opts lst- return $ leftQuote +++ contents +++ rightQuote- (TeX str) -> (if writerUseASCIIMathML opts- then modify (\st -> st {stMath = True})- else return ()) >> return (stringToHtml str)- (HtmlInline str) -> return $ primHtml str - (Link [Code str] (src,tit)) | "mailto:" `isPrefixOf` src ->- return $ obfuscateLink opts str src- (Link txt (src,tit)) | "mailto:" `isPrefixOf` src -> do- linkText <- inlineListToHtml opts txt - return $ obfuscateLink opts (show linkText) src- (Link txt (src,tit)) -> do- linkText <- inlineListToHtml opts txt- return $ anchor ! ([href src] ++ - if null tit then [] else [title tit]) $ - linkText- (Image txt (source,tit)) -> do- alternate <- inlineListToHtml opts txt- let alternate' = renderHtmlFragment alternate- let attributes = [src source, title tit] ++ - if null txt - then [] - else [alt alternate']- return $ image ! attributes - -- note: null title included, as in Markdown.pl - (Note contents) -> do - st <- get- let notes = stNotes st- let number = (length notes) + 1- let ref = show number- htmlContents <- blockListToNote opts ref contents - -- push contents onto front of notes- put $ st {stNotes = (htmlContents:notes)} - return $ anchor ! [href ("#fn" ++ ref),- theclass "footnoteRef",- identifier ("fnref" ++ ref)] << - sup << ref--blockListToNote :: WriterOptions -> String -> [Block] -> State WriterState Html-blockListToNote opts ref blocks =- -- If last block is Para or Plain, include the backlink at the end of- -- that block. Otherwise, insert a new Plain block with the backlink.- let backlink = [HtmlInline $ " <a href=\"#fnref" ++ ref ++ - "\" class=\"footnoteBackLink\"" ++- " title=\"Jump back to footnote " ++ ref ++ "\">↩</a>"]- blocks' = if null blocks- then []- else let lastBlock = last blocks- otherBlocks = init blocks- in case lastBlock of- (Para lst) -> otherBlocks ++- [Para (lst ++ backlink)]- (Plain lst) -> otherBlocks ++- [Plain (lst ++ backlink)]- _ -> otherBlocks ++ [lastBlock,- Plain backlink]- in do contents <- blockListToHtml opts blocks'- return $ li ! [identifier ("fn" ++ ref)] $ contents-
− src/Text/Pandoc/Writers/LaTeX.hs
@@ -1,309 +0,0 @@-{--Copyright (C) 2006-7 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.LaTeX- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha - Portability : portable--Conversion of 'Pandoc' format into LaTeX.--}-module Text.Pandoc.Writers.LaTeX ( writeLaTeX ) where-import Text.Pandoc.Definition-import Text.Pandoc.Shared-import Text.Printf ( printf )-import Data.List ( (\\), isInfixOf, intersperse )-import Data.Char ( toLower )-import qualified Data.Set as S-import Control.Monad.State-import Text.PrettyPrint.HughesPJ hiding ( Str )--data WriterState = - WriterState { stIncludes :: S.Set String -- strings to include in header- , stInNote :: Bool -- @True@ if we're in a note- , stOLLevel :: Int } -- level of ordered list nesting ---- | Add line to header.-addToHeader :: String -> State WriterState ()-addToHeader str = do- st <- get- let includes = stIncludes st- put st {stIncludes = S.insert str includes}---- | Convert Pandoc to LaTeX.-writeLaTeX :: WriterOptions -> Pandoc -> String-writeLaTeX options document = - render $ evalState (pandocToLaTeX options document) $ - WriterState { stIncludes = S.empty, stInNote = False, stOLLevel = 1 } --pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState Doc-pandocToLaTeX options (Pandoc meta blocks) = do- main <- blockListToLaTeX blocks- head <- if writerStandalone options- then latexHeader options meta- else return empty- let before = if null (writerIncludeBefore options)- then empty- else text (writerIncludeBefore options)- let after = if null (writerIncludeAfter options)- then empty- else text (writerIncludeAfter options)- let body = before $$ main $$ after- let toc = if writerTableOfContents options- then text "\\tableofcontents\n"- else empty - let foot = if writerStandalone options- then text "\\end{document}"- else empty - return $ head $$ toc $$ body $$ foot---- | Insert bibliographic information into LaTeX header.-latexHeader :: WriterOptions -- ^ Options, including LaTeX header- -> Meta -- ^ Meta with bibliographic information- -> State WriterState Doc-latexHeader options (Meta title authors date) = do- titletext <- if null title- then return empty- else inlineListToLaTeX title >>= return . inCmd "title"- headerIncludes <- get >>= return . S.toList . stIncludes- let extras = text $ unlines headerIncludes- let verbatim = if "\\usepackage{fancyvrb}" `elem` headerIncludes- then text "\\VerbatimFootnotes % allows verbatim text in footnotes"- else empty- let authorstext = text $ "\\author{" ++ - joinWithSep "\\\\" (map stringToLaTeX authors) ++ "}"- let datetext = if date == ""- then empty - else text $ "\\date{" ++ stringToLaTeX date ++ "}"- let maketitle = if null title then empty else text "\\maketitle"- let secnumline = if (writerNumberSections options)- then empty - else text "\\setcounter{secnumdepth}{0}"- let baseHeader = text $ writerHeader options- let header = baseHeader $$ extras- return $ header $$ secnumline $$ verbatim $$ titletext $$ authorstext $$- datetext $$ text "\\begin{document}" $$ maketitle $$ text ""---- escape things as needed for LaTeX--stringToLaTeX :: String -> String-stringToLaTeX = escapeStringUsing latexEscapes- where latexEscapes = backslashEscapes "{}$%&_#" ++ - [ ('^', "\\^{}")- , ('\\', "\\textbackslash{}")- , ('~', "\\ensuremath{\\sim}")- , ('|', "\\textbar{}")- , ('<', "\\textless{}")- , ('>', "\\textgreater{}")- ]---- | Puts contents into LaTeX command.-inCmd :: String -> Doc -> Doc-inCmd cmd contents = char '\\' <> text cmd <> braces contents---- | Remove all code elements from list of inline elements--- (because it's illegal to have verbatim inside some command arguments)-deVerb :: [Inline] -> [Inline]-deVerb [] = []-deVerb ((Code str):rest) = - (TeX $ "\\texttt{" ++ stringToLaTeX str ++ "}"):(deVerb rest)-deVerb (other:rest) = other:(deVerb rest)---- | Convert Pandoc block element to LaTeX.-blockToLaTeX :: Block -- ^ Block to convert- -> State WriterState Doc-blockToLaTeX Null = return empty-blockToLaTeX (Plain lst) = wrapped inlineListToLaTeX lst >>= return -blockToLaTeX (Para lst) = - wrapped inlineListToLaTeX lst >>= return . (<> char '\n')-blockToLaTeX (BlockQuote lst) = do- contents <- blockListToLaTeX lst- return $ text "\\begin{quote}" $$ contents $$ text "\\end{quote}"-blockToLaTeX (CodeBlock str) = do- st <- get- env <- if stInNote st- then do addToHeader "\\usepackage{fancyvrb}"- return "Verbatim"- else return "verbatim"- return $ text ("\\begin{" ++ env ++ "}\n") <> text str <> - text ("\n\\end{" ++ env ++ "}")-blockToLaTeX (RawHtml str) = return empty-blockToLaTeX (BulletList lst) = do- items <- mapM listItemToLaTeX lst- return $ text "\\begin{itemize}" $$ vcat items $$ text "\\end{itemize}"-blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do- st <- get- let oldlevel = stOLLevel st- put $ st {stOLLevel = oldlevel + 1}- items <- mapM listItemToLaTeX lst- modify (\st -> st {stOLLevel = oldlevel})- exemplar <- if numstyle /= DefaultStyle || numdelim /= DefaultDelim- then do addToHeader "\\usepackage{enumerate}"- return $ char '[' <> - text (head (orderedListMarkers (1, numstyle,- numdelim))) <> char ']'- else return empty- let resetcounter = if start /= 1 && oldlevel <= 4- then text $ "\\setcounter{enum" ++ - map toLower (toRomanNumeral oldlevel) ++- "}{" ++ show (start - 1) ++ "}"- else empty - return $ text "\\begin{enumerate}" <> exemplar $$ resetcounter $$- vcat items $$ text "\\end{enumerate}"-blockToLaTeX (DefinitionList lst) = do- items <- mapM defListItemToLaTeX lst- return $ text "\\begin{description}" $$ vcat items $$- text "\\end{description}"-blockToLaTeX HorizontalRule = return $ text $- "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n"-blockToLaTeX (Header level lst) = do- txt <- inlineListToLaTeX (deVerb lst)- return $ if (level > 0) && (level <= 3)- then text ("\\" ++ (concat (replicate (level - 1) "sub")) ++ - "section{") <> txt <> text "}\n"- else txt <> char '\n'-blockToLaTeX (Table caption aligns widths heads rows) = do- headers <- tableRowToLaTeX heads- captionText <- inlineListToLaTeX caption- rows' <- mapM tableRowToLaTeX rows- let colWidths = map (printf "%.2f") widths- let colDescriptors = concat $ zipWith- (\width align -> ">{\\PBS" ++ - (case align of - AlignLeft -> "\\raggedright"- AlignRight -> "\\raggedleft"- AlignCenter -> "\\centering"- AlignDefault -> "\\raggedright") ++- "\\hspace{0pt}}p{" ++ width ++ - "\\columnwidth}")- colWidths aligns- let tableBody = text ("\\begin{tabular}{" ++ colDescriptors ++ "}") $$- headers $$ text "\\hline" $$ vcat rows' $$ - text "\\end{tabular}" - let centered txt = text "\\begin{center}" $$ txt $$ text "\\end{center}"- addToHeader "\\usepackage{array}\n\- \% This is needed because raggedright in table elements redefines \\\\:\n\- \\\newcommand{\\PreserveBackslash}[1]{\\let\\temp=\\\\#1\\let\\\\=\\temp}\n\- \\\let\\PBS=\\PreserveBackslash"- return $ if isEmpty captionText- then centered tableBody <> char '\n'- else text "\\begin{table}[h]" $$ centered tableBody $$ - inCmd "caption" captionText $$ text "\\end{table}\n" --blockListToLaTeX lst = mapM blockToLaTeX lst >>= return . vcat--tableRowToLaTeX cols = mapM blockListToLaTeX cols >>= - return . ($$ text "\\\\") . foldl (\row item -> row $$- (if isEmpty row then empty else text " & ") <> item) empty--listItemToLaTeX lst = blockListToLaTeX lst >>= return . (text "\\item " $$) .- (nest 2)--defListItemToLaTeX (term, def) = do- term' <- inlineListToLaTeX $ deVerb term- def' <- blockListToLaTeX def- return $ text "\\item[" <> term' <> text "]" $$ def'---- | Convert list of inline elements to LaTeX.-inlineListToLaTeX :: [Inline] -- ^ Inlines to convert- -> State WriterState Doc-inlineListToLaTeX lst = mapM inlineToLaTeX lst >>= return . hcat--isQuoted :: Inline -> Bool-isQuoted (Quoted _ _) = True-isQuoted Apostrophe = True-isQuoted _ = False---- | Convert inline element to LaTeX-inlineToLaTeX :: Inline -- ^ Inline to convert- -> State WriterState Doc-inlineToLaTeX (Emph lst) =- inlineListToLaTeX (deVerb lst) >>= return . inCmd "emph"-inlineToLaTeX (Strong lst) = - inlineListToLaTeX (deVerb lst) >>= return . inCmd "textbf" -inlineToLaTeX (Strikeout lst) = do- contents <- inlineListToLaTeX $ deVerb lst- addToHeader "\\usepackage[normalem]{ulem}"- return $ inCmd "sout" contents-inlineToLaTeX (Superscript lst) = - inlineListToLaTeX (deVerb lst) >>= return . inCmd "textsuperscript"-inlineToLaTeX (Subscript lst) = do- contents <- inlineListToLaTeX $ deVerb lst- -- oddly, latex includes \textsuperscript but not \textsubscript- -- so we have to define it:- addToHeader "\\newcommand{\\textsubscript}[1]{\\ensuremath{_{\\scriptsize\\textrm{#1}}}}"- return $ inCmd "textsubscript" contents-inlineToLaTeX (Code str) = do- st <- get- if stInNote st- then do addToHeader "\\usepackage{fancyvrb}"- else return ()- let chr = ((enumFromTo '!' '~') \\ str) !! 0- return $ text $ "\\verb" ++ [chr] ++ str ++ [chr]-inlineToLaTeX (Quoted SingleQuote lst) = do- contents <- inlineListToLaTeX lst- let s1 = if (not (null lst)) && (isQuoted (head lst))- then text "\\,"- else empty - let s2 = if (not (null lst)) && (isQuoted (last lst))- then text "\\,"- else empty- return $ char '`' <> s1 <> contents <> s2 <> char '\''-inlineToLaTeX (Quoted DoubleQuote lst) = do- contents <- inlineListToLaTeX lst- let s1 = if (not (null lst)) && (isQuoted (head lst))- then text "\\,"- else empty - let s2 = if (not (null lst)) && (isQuoted (last lst))- then text "\\,"- else empty- return $ text "``" <> s1 <> contents <> s2 <> text "''"-inlineToLaTeX Apostrophe = return $ char '\''-inlineToLaTeX EmDash = return $ text "---"-inlineToLaTeX EnDash = return $ text "--"-inlineToLaTeX Ellipses = return $ text "\\ldots{}"-inlineToLaTeX (Str str) = return $ text $ stringToLaTeX str-inlineToLaTeX (TeX str) = return $ text str-inlineToLaTeX (HtmlInline str) = return empty-inlineToLaTeX (LineBreak) = return $ text "\\\\" -inlineToLaTeX Space = return $ char ' '-inlineToLaTeX (Link txt (src, _)) = do- addToHeader "\\usepackage[breaklinks=true]{hyperref}"- case txt of- [Code x] | x == src -> -- autolink- do addToHeader "\\usepackage{url}" - return $ text $ "\\url{" ++ x ++ "}"- _ -> do contents <- inlineListToLaTeX $ deVerb txt- return $ text ("\\href{" ++ src ++ "}{") <> contents <> - char '}'-inlineToLaTeX (Image alternate (source, tit)) = do- addToHeader "\\usepackage{graphicx}"- return $ text $ "\\includegraphics{" ++ source ++ "}" -inlineToLaTeX (Note contents) = do- st <- get- put (st {stInNote = True})- contents' <- blockListToLaTeX contents- modify (\st -> st {stInNote = False})- return $ text "\\footnote{" $$ - (nest 11 $ text (stripTrailingNewlines $ render contents') <> text "\n}")- -- note: the \n before } is important; removing it causes problems- -- if a Verbatim environment occurs at the end of the footnote.
− src/Text/Pandoc/Writers/Man.hs
@@ -1,292 +0,0 @@-{--Copyright (C) 2007 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.Man - Copyright : Copyright (C) 2007 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion of 'Pandoc' documents to groff man page format.---}-module Text.Pandoc.Writers.Man ( writeMan) where-import Text.Pandoc.Definition-import Text.Pandoc.Shared -import Text.Printf ( printf )-import Data.List ( isPrefixOf, drop, nub, intersperse )-import Text.PrettyPrint.HughesPJ hiding ( Str )-import Control.Monad.State--type Notes = [[Block]]-type Preprocessors = [String] -- e.g. "t" for tbl-type WriterState = (Notes, Preprocessors)---- | Convert Pandoc to Man.-writeMan :: WriterOptions -> Pandoc -> String-writeMan opts document = render $ evalState (pandocToMan opts document) ([],[]) ---- | Return groff man representation of document.-pandocToMan :: WriterOptions -> Pandoc -> State WriterState Doc-pandocToMan opts (Pandoc meta blocks) = do- let before = writerIncludeBefore opts- let after = writerIncludeAfter opts- let before' = if null before then empty else text before- let after' = if null after then empty else text after- (head, foot) <- metaToMan opts meta- body <- blockListToMan opts blocks- (notes, preprocessors) <- get- let preamble = if null preprocessors || not (writerStandalone opts)- then empty- else text $ ".\\\" " ++ concat (nub preprocessors)- notes' <- notesToMan opts (reverse notes)- return $ preamble $$ head $$ before' $$ body $$ notes' $$ foot $$ after'---- | Insert bibliographic information into Man header and footer.-metaToMan :: WriterOptions -- ^ Options, including Man header- -> Meta -- ^ Meta with bibliographic information- -> State WriterState (Doc, Doc)-metaToMan options (Meta title authors date) = do- titleText <- inlineListToMan options title- let (cmdName, rest) = break (== ' ') $ render titleText- let (title', section) = case reverse cmdName of- (')':d:'(':xs) | d `elem` ['0'..'9'] -> - (text (reverse xs), char d)- xs -> (text (reverse xs), doubleQuotes empty) - let extras = map (doubleQuotes . text . removeLeadingTrailingSpace) $- splitBy '|' rest- let head = (text ".TH") <+> title' <+> section <+> - doubleQuotes (text date) <+> hsep extras- let foot = case length authors of- 0 -> empty- 1 -> text ".SH AUTHOR" $$ (text $ joinWithSep ", " authors)- 2 -> text ".SH AUTHORS" $$ (text $ joinWithSep ", " authors)- return $ if writerStandalone options- then (head, foot)- else (empty, empty)---- | Return man representation of notes.-notesToMan :: WriterOptions -> [[Block]] -> State WriterState Doc-notesToMan opts notes =- if null notes- then return empty- else mapM (\(num, note) -> noteToMan opts num note) (zip [1..] notes) >>= - return . (text ".SH NOTES" $$) . vcat---- | Return man representation of a note.-noteToMan :: WriterOptions -> Int -> [Block] -> State WriterState Doc-noteToMan opts num note = do- contents <- blockListToMan opts note- let marker = text "\n.SS [" <> text (show num) <> char ']'- return $ marker $$ contents ---- | Association list of characters to escape.-manEscapes :: [(Char, String)]-manEscapes = [('\160', "\\ "), ('\'', "\\[aq]")] ++ backslashEscapes "\".@\\"---- | Escape special characters for Man.-escapeString :: String -> String-escapeString = escapeStringUsing manEscapes---- | Escape a literal (code) section for Man.-escapeCode :: String -> String-escapeCode = escapeStringUsing (manEscapes ++ backslashEscapes "\t ")---- | Convert Pandoc block element to man.-blockToMan :: WriterOptions -- ^ Options- -> Block -- ^ Block element- -> State WriterState Doc -blockToMan opts Null = return empty-blockToMan opts (Plain inlines) = wrapped (inlineListToMan opts) inlines-blockToMan opts (Para inlines) = do- contents <- wrapped (inlineListToMan opts) inlines- return $ text ".PP" $$ contents -blockToMan opts (RawHtml str) = return $ text str-blockToMan opts HorizontalRule = return $ text $ ".PP\n * * * * *"-blockToMan opts (Header level inlines) = do- contents <- inlineListToMan opts inlines- let heading = case level of- 1 -> ".SH "- _ -> ".SS "- return $ text heading <> contents -blockToMan opts (CodeBlock str) = return $- text ".PP" $$ text "\\f[CR]" $$ - text ((unlines . map (" " ++) . lines) (escapeCode str)) <> text "\\f[]"-blockToMan opts (BlockQuote blocks) = do - contents <- blockListToMan opts blocks- return $ text ".RS" $$ contents $$ text ".RE"-blockToMan opts (Table caption alignments widths headers rows) = - let aligncode AlignLeft = "l"- aligncode AlignRight = "r"- aligncode AlignCenter = "c"- aligncode AlignDefault = "l"- in do- caption' <- inlineListToMan opts caption- modify (\(notes, preprocessors) -> (notes, "t":preprocessors))- let iwidths = map (printf "w(%0.2fn)" . (70 *)) widths - -- 78n default width - 8n indent = 70n- let coldescriptions = text $ joinWithSep " " - (zipWith (\align width -> aligncode align ++ width) - alignments iwidths) ++ "."- colheadings <- mapM (blockListToMan opts) headers- let makeRow cols = text "T{" $$ - (vcat $ intersperse (text "T}@T{") cols) $$ - text "T}"- let colheadings' = makeRow colheadings- body <- mapM (\row -> do - cols <- mapM (blockListToMan opts) row- return $ makeRow cols) rows- return $ text ".PP" $$ caption' $$ - text ".TS" $$ text "tab(@);" $$ coldescriptions $$ - colheadings' $$ char '_' $$ vcat body $$ text ".TE"--blockToMan opts (BulletList items) = do- contents <- mapM (bulletListItemToMan opts) items- return (vcat contents) -blockToMan opts (OrderedList attribs items) = do- let markers = take (length items) $ orderedListMarkers attribs - let indent = 1 + (maximum $ map length markers)- contents <- mapM (\(num, item) -> orderedListItemToMan opts num indent item) $- zip markers items - return (vcat contents)-blockToMan opts (DefinitionList items) = do - contents <- mapM (definitionListItemToMan opts) items- return (vcat contents)---- | Convert bullet list item (list of blocks) to man.-bulletListItemToMan :: WriterOptions -> [Block] -> State WriterState Doc-bulletListItemToMan opts [] = return empty-bulletListItemToMan opts ((Para first):rest) = - bulletListItemToMan opts ((Plain first):rest)-bulletListItemToMan opts ((Plain first):rest) = do- first' <- blockToMan opts (Plain first) - rest' <- blockListToMan opts rest- let first'' = text ".IP \\[bu] 2" $$ first'- let rest'' = if null rest- then empty- else text ".RS 2" $$ rest' $$ text ".RE"- return (first'' $$ rest'') -bulletListItemToMan opts (first:rest) = do- first' <- blockToMan opts first- rest' <- blockListToMan opts rest- return $ text "\\[bu] .RS 2" $$ first' $$ rest' $$ text ".RE"- --- | Convert ordered list item (a list of blocks) to man.-orderedListItemToMan :: WriterOptions -- ^ options- -> String -- ^ order marker for list item- -> Int -- ^ number of spaces to indent- -> [Block] -- ^ list item (list of blocks)- -> State WriterState Doc-orderedListItemToMan _ _ _ [] = return empty-orderedListItemToMan opts num indent ((Para first):rest) = - orderedListItemToMan opts num indent ((Plain first):rest)-orderedListItemToMan opts num indent (first:rest) = do- first' <- blockToMan opts first- rest' <- blockListToMan opts rest- let num' = printf ("%" ++ show (indent - 1) ++ "s") num- let first'' = text (".IP \"" ++ num' ++ "\" " ++ show indent) $$ first'- let rest'' = if null rest- then empty- else text ".RS 4" $$ rest' $$ text ".RE"- return $ first'' $$ rest'' ---- | Convert definition list item (label, list of blocks) to man.-definitionListItemToMan :: WriterOptions- -> ([Inline],[Block]) - -> State WriterState Doc-definitionListItemToMan opts (label, items) = do- labelText <- inlineListToMan opts label- contents <- if null items- then return empty- else do - let (first, rest) = case items of- ((Para x):y) -> (Plain x,y)- (x:y) -> (x,y)- rest' <- mapM (\item -> blockToMan opts item)- rest >>= (return . vcat)- first' <- blockToMan opts first- return $ first' $$ text ".RS" $$ rest' $$ text ".RE"- return $ text ".TP\n.B " <> labelText $+$ contents---- | Convert list of Pandoc block elements to man.-blockListToMan :: WriterOptions -- ^ Options- -> [Block] -- ^ List of block elements- -> State WriterState Doc -blockListToMan opts blocks =- mapM (blockToMan opts) blocks >>= (return . vcat)---- | Convert list of Pandoc inline elements to man.-inlineListToMan :: WriterOptions -> [Inline] -> State WriterState Doc-inlineListToMan opts lst = mapM (inlineToMan opts) lst >>= (return . hcat)---- | Convert Pandoc inline element to man.-inlineToMan :: WriterOptions -> Inline -> State WriterState Doc-inlineToMan opts (Emph lst) = do - contents <- inlineListToMan opts lst- return $ text "\\f[I]" <> contents <> text "\\f[]"-inlineToMan opts (Strong lst) = do- contents <- inlineListToMan opts lst- return $ text "\\f[B]" <> contents <> text "\\f[]"-inlineToMan opts (Strikeout lst) = do- contents <- inlineListToMan opts lst- return $ text "[STRIKEOUT:" <> contents <> char ']'-inlineToMan opts (Superscript lst) = do- contents <- inlineListToMan opts lst- return $ char '^' <> contents <> char '^'-inlineToMan opts (Subscript lst) = do- contents <- inlineListToMan opts lst- return $ char '~' <> contents <> char '~'-inlineToMan opts (Quoted SingleQuote lst) = do- contents <- inlineListToMan opts lst- return $ char '`' <> contents <> char '\''-inlineToMan opts (Quoted DoubleQuote lst) = do- contents <- inlineListToMan opts lst- return $ text "\\[lq]" <> contents <> text "\\[rq]"-inlineToMan opts EmDash = return $ text "\\[em]"-inlineToMan opts EnDash = return $ text "\\[en]"-inlineToMan opts Apostrophe = return $ char '\''-inlineToMan opts Ellipses = return $ text "\\&..."-inlineToMan opts (Code str) =- return $ text $ "\\f[B]" ++ escapeCode str ++ "\\f[]"-inlineToMan opts (Str str) = return $ text $ escapeString str-inlineToMan opts (TeX str) = return $ text $ escapeCode str-inlineToMan opts (HtmlInline str) = return $ text $ escapeCode str -inlineToMan opts (LineBreak) = return $ text "\n.PD 0\n.P\n.PD\n"-inlineToMan opts Space = return $ char ' '-inlineToMan opts (Link txt (src, _)) = do- linktext <- inlineListToMan opts txt- let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src- return $ if txt == [Code srcSuffix]- then char '<' <> text srcSuffix <> char '>' - else linktext <> text " (" <> text src <> char ')' -inlineToMan opts (Image alternate (source, tit)) = do- let txt = if (null alternate) || (alternate == [Str ""]) || - (alternate == [Str source]) -- to prevent autolinks- then [Str "image"]- else alternate- linkPart <- inlineToMan opts (Link txt (source, tit)) - return $ char '[' <> text "IMAGE: " <> linkPart <> char ']'-inlineToMan opts (Note contents) = do - modify (\(notes, prep) -> (contents:notes, prep)) -- add to notes in state- (notes, _) <- get- let ref = show $ (length notes)- return $ char '[' <> text ref <> char ']'-
− src/Text/Pandoc/Writers/Markdown.hs
@@ -1,360 +0,0 @@-{--Copyright (C) 2006-7 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.Markdown - Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion of 'Pandoc' documents to markdown-formatted plain text.--Markdown: <http://daringfireball.net/projects/markdown/>--}-module Text.Pandoc.Writers.Markdown ( writeMarkdown) where-import Text.Pandoc.Definition-import Text.Pandoc.Shared -import Text.Pandoc.Blocks-import Text.ParserCombinators.Parsec ( parse, (<|>), GenParser )-import Data.List ( group, isPrefixOf, drop, find, intersperse )-import Text.PrettyPrint.HughesPJ hiding ( Str )-import Control.Monad.State--type Notes = [[Block]]-type Refs = KeyTable-type WriterState = (Notes, Refs)---- | Convert Pandoc to Markdown.-writeMarkdown :: WriterOptions -> Pandoc -> String-writeMarkdown opts document = - render $ evalState (pandocToMarkdown opts document) ([],[]) ---- | Return markdown representation of document.-pandocToMarkdown :: WriterOptions -> Pandoc -> State WriterState Doc-pandocToMarkdown opts (Pandoc meta blocks) = do- let before = writerIncludeBefore opts- let after = writerIncludeAfter opts- let before' = if null before then empty else text before- let after' = if null after then empty else text after- metaBlock <- metaToMarkdown opts meta- let head = if writerStandalone opts- then metaBlock $+$ text (writerHeader opts)- else empty- let headerBlocks = filter isHeaderBlock blocks- let toc = if writerTableOfContents opts - then tableOfContents opts headerBlocks- else empty- body <- blockListToMarkdown opts blocks- (notes, _) <- get- notes' <- notesToMarkdown opts (reverse notes)- (_, refs) <- get -- note that the notes may contain refs- refs' <- keyTableToMarkdown opts (reverse refs)- return $ head $+$ before' $+$ toc $+$ body $+$ text "" $+$ - notes' $+$ text "" $+$ refs' $+$ after'---- | Return markdown representation of reference key table.-keyTableToMarkdown :: WriterOptions -> KeyTable -> State WriterState Doc-keyTableToMarkdown opts refs = mapM (keyToMarkdown opts) refs >>= return . vcat- --- | Return markdown representation of a reference key. -keyToMarkdown :: WriterOptions - -> ([Inline], (String, String)) - -> State WriterState Doc-keyToMarkdown opts (label, (src, tit)) = do- label' <- inlineListToMarkdown opts label- let tit' = if null tit then empty else text $ " \"" ++ tit ++ "\""- return $ text " " <> char '[' <> label' <> char ']' <> text ": " <>- text src <> tit' ---- | Return markdown representation of notes.-notesToMarkdown :: WriterOptions -> [[Block]] -> State WriterState Doc-notesToMarkdown opts notes = - mapM (\(num, note) -> noteToMarkdown opts num note) (zip [1..] notes) >>= - return . vcat---- | Return markdown representation of a note.-noteToMarkdown :: WriterOptions -> Int -> [Block] -> State WriterState Doc-noteToMarkdown opts num blocks = do- contents <- blockListToMarkdown opts blocks- let marker = text "[^" <> text (show num) <> text "]:"- return $ hang marker (writerTabStop opts) contents ---- | Escape special characters for Markdown.-escapeString :: String -> String-escapeString = escapeStringUsing markdownEscapes- where markdownEscapes = ('\160', " "):(backslashEscapes "`<\\*_^~")---- | Convert bibliographic information into Markdown header.-metaToMarkdown :: WriterOptions -> Meta -> State WriterState Doc-metaToMarkdown opts (Meta title authors date) = do- title' <- titleToMarkdown opts title- authors' <- authorsToMarkdown authors- date' <- dateToMarkdown date- return $ title' $+$ authors' $+$ date'--titleToMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc-titleToMarkdown opts [] = return empty-titleToMarkdown opts lst = do- contents <- inlineListToMarkdown opts lst- return $ text "% " <> contents --authorsToMarkdown :: [String] -> State WriterState Doc-authorsToMarkdown [] = return empty-authorsToMarkdown lst = return $ - text "% " <> text (joinWithSep ", " (map escapeString lst))--dateToMarkdown :: String -> State WriterState Doc-dateToMarkdown [] = return empty-dateToMarkdown str = return $ text "% " <> text (escapeString str)---- | Construct table of contents from list of header blocks.-tableOfContents :: WriterOptions -> [Block] -> Doc -tableOfContents opts headers =- let opts' = opts { writerIgnoreNotes = True }- contents = BulletList $ map elementToListItem $ hierarchicalize headers- in evalState (blockToMarkdown opts' contents) ([],[])---- | Converts an Element to a list item for a table of contents,-elementToListItem :: Element -> [Block]-elementToListItem (Blk _) = []-elementToListItem (Sec headerText subsecs) = [Plain headerText] ++ - if null subsecs- then []- else [BulletList $ map elementToListItem subsecs]---- | Ordered list start parser for use in Para below.-olMarker :: GenParser Char st Char-olMarker = do (start, style, delim) <- anyOrderedListMarker- if delim == Period && - (style == UpperAlpha || (style == UpperRoman &&- start `elem` [1, 5, 10, 50, 100, 500, 1000]))- then spaceChar >> spaceChar- else spaceChar---- | True if string begins with an ordered list marker-beginsWithOrderedListMarker :: String -> Bool-beginsWithOrderedListMarker str = - case parse olMarker "para start" str of- Left _ -> False - Right _ -> True---- | Convert Pandoc block element to markdown.-blockToMarkdown :: WriterOptions -- ^ Options- -> Block -- ^ Block element- -> State WriterState Doc -blockToMarkdown opts Null = return empty-blockToMarkdown opts (Plain inlines) = - wrapped (inlineListToMarkdown opts) inlines-blockToMarkdown opts (Para inlines) = do- contents <- wrapped (inlineListToMarkdown opts) inlines- -- escape if para starts with ordered list marker- let esc = if (not (writerStrictMarkdown opts)) && - beginsWithOrderedListMarker (render contents)- then char '\\'- else empty - return $ esc <> contents <> text "\n"-blockToMarkdown opts (RawHtml str) = return $ text str-blockToMarkdown opts HorizontalRule = return $ text "\n* * * * *\n"-blockToMarkdown opts (Header level inlines) = do- contents <- inlineListToMarkdown opts inlines- return $ text ((replicate level '#') ++ " ") <> contents <> text "\n"-blockToMarkdown opts (CodeBlock str) = return $- (nest (writerTabStop opts) $ vcat $ map text (lines str)) <> text "\n"-blockToMarkdown opts (BlockQuote blocks) = do- contents <- blockListToMarkdown opts blocks- return $ (vcat $ map (text . ("> " ++)) $ lines $ render contents) <> - text "\n"-blockToMarkdown opts (Table caption aligns widths headers rows) = do- caption' <- inlineListToMarkdown opts caption- let caption'' = if null caption- then empty- else text "" $+$ (text "Table: " <> caption')- headers' <- mapM (blockListToMarkdown opts) headers- let widthsInChars = map (floor . (78 *)) widths- let alignHeader alignment = case alignment of- AlignLeft -> leftAlignBlock- AlignCenter -> centerAlignBlock- AlignRight -> rightAlignBlock- AlignDefault -> leftAlignBlock - let makeRow = hsepBlocks . (zipWith alignHeader aligns) . - (zipWith docToBlock widthsInChars)- let head = makeRow headers'- rows' <- mapM (\row -> do cols <- mapM (blockListToMarkdown opts) row- return $ makeRow cols) rows- let tableWidth = sum widthsInChars- let maxRowHeight = maximum $ map heightOfBlock (head:rows')- let isMultilineTable = maxRowHeight > 1- let underline = hsep $ - map (\width -> text $ replicate width '-') widthsInChars- let border = if isMultilineTable- then text $ replicate (sum widthsInChars + (length widthsInChars - 1)) '-'- else empty- let spacer = if isMultilineTable- then text ""- else empty- let body = vcat $ intersperse spacer $ map blockToDoc rows'- return $ (nest 2 $ border $+$ (blockToDoc head) $+$ underline $+$ body $+$ - border $+$ caption'') <> text "\n"-blockToMarkdown opts (BulletList items) = do- contents <- mapM (bulletListItemToMarkdown opts) items- return $ (vcat contents) <> text "\n"-blockToMarkdown opts (OrderedList attribs items) = do- let markers = orderedListMarkers attribs- let markers' = map (\m -> if length m < 3- then m ++ replicate (3 - length m) ' '- else m) markers - contents <- mapM (\(item, num) -> orderedListItemToMarkdown opts item num) $- zip markers' items - return $ (vcat contents) <> text "\n"-blockToMarkdown opts (DefinitionList items) = do- contents <- mapM (definitionListItemToMarkdown opts) items- return $ (vcat contents) <> text "\n"---- | Convert bullet list item (list of blocks) to markdown.-bulletListItemToMarkdown :: WriterOptions -> [Block] -> State WriterState Doc-bulletListItemToMarkdown opts items = do- contents <- blockListToMarkdown opts items- return $ hang (text "- ") (writerTabStop opts) contents---- | Convert ordered list item (a list of blocks) to markdown.-orderedListItemToMarkdown :: WriterOptions -- ^ options- -> String -- ^ list item marker- -> [Block] -- ^ list item (list of blocks)- -> State WriterState Doc-orderedListItemToMarkdown opts marker items = do- contents <- blockListToMarkdown opts items- return $ hang (text marker) (writerTabStop opts) contents ---- | Convert definition list item (label, list of blocks) to markdown.-definitionListItemToMarkdown :: WriterOptions- -> ([Inline],[Block]) - -> State WriterState Doc-definitionListItemToMarkdown opts (label, items) = do- labelText <- inlineListToMarkdown opts label- let tabStop = writerTabStop opts- let leader = char ':'- contents <- mapM (\item -> blockToMarkdown opts item >>= - (\txt -> return (leader $$ nest tabStop txt)))- items >>= return . vcat- return $ labelText $+$ contents---- | Convert list of Pandoc block elements to markdown.-blockListToMarkdown :: WriterOptions -- ^ Options- -> [Block] -- ^ List of block elements- -> State WriterState Doc -blockListToMarkdown opts blocks =- mapM (blockToMarkdown opts) blocks >>= return . vcat---- | Get reference for target; if none exists, create unique one and return.--- Prefer label if possible; otherwise, generate a unique key.-getReference :: [Inline] -> Target -> State WriterState [Inline]-getReference label (src, tit) = do- (_,refs) <- get- case find ((== (src, tit)) . snd) refs of- Just (ref, _) -> return ref- Nothing -> do- let label' = case find ((== label) . fst) refs of- Just _ -> -- label is used; generate numerical label- case find (\n -> not (any (== [Str (show n)])- (map fst refs))) [1..10000] of- Just x -> [Str (show x)]- Nothing -> error "no unique label"- Nothing -> label- modify (\(notes, refs) -> (notes, (label', (src,tit)):refs))- return label'---- | Convert list of Pandoc inline elements to markdown.-inlineListToMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc-inlineListToMarkdown opts lst =- mapM (inlineToMarkdown opts) lst >>= return . hcat---- | Convert Pandoc inline element to markdown.-inlineToMarkdown :: WriterOptions -> Inline -> State WriterState Doc-inlineToMarkdown opts (Emph lst) = do - contents <- inlineListToMarkdown opts lst- return $ char '*' <> contents <> char '*'-inlineToMarkdown opts (Strong lst) = do- contents <- inlineListToMarkdown opts lst- return $ text "**" <> contents <> text "**"-inlineToMarkdown opts (Strikeout lst) = do- contents <- inlineListToMarkdown opts lst- return $ text "~~" <> contents <> text "~~"-inlineToMarkdown opts (Superscript lst) = do- contents <- inlineListToMarkdown opts lst- let contents' = text $ substitute " " "\\ " $ render contents- return $ char '^' <> contents' <> char '^'-inlineToMarkdown opts (Subscript lst) = do- contents <- inlineListToMarkdown opts lst- let contents' = text $ substitute " " "\\ " $ render contents- return $ char '~' <> contents' <> char '~'-inlineToMarkdown opts (Quoted SingleQuote lst) = do- contents <- inlineListToMarkdown opts lst- return $ char '\'' <> contents <> char '\''-inlineToMarkdown opts (Quoted DoubleQuote lst) = do- contents <- inlineListToMarkdown opts lst- return $ char '"' <> contents <> char '"'-inlineToMarkdown opts EmDash = return $ text "--"-inlineToMarkdown opts EnDash = return $ char '-'-inlineToMarkdown opts Apostrophe = return $ char '\''-inlineToMarkdown opts Ellipses = return $ text "..."-inlineToMarkdown opts (Code str) =- let tickGroups = filter (\s -> '`' `elem` s) $ group str - longest = if null tickGroups- then 0- else maximum $ map length tickGroups - marker = replicate (longest + 1) '`' - spacer = if (longest == 0) then "" else " " in- return $ text (marker ++ spacer ++ str ++ spacer ++ marker)-inlineToMarkdown opts (Str str) = return $ text $ escapeString str-inlineToMarkdown opts (TeX str) = return $ text str-inlineToMarkdown opts (HtmlInline str) = return $ text str -inlineToMarkdown opts (LineBreak) = return $ text " \n"-inlineToMarkdown opts Space = return $ char ' '-inlineToMarkdown opts (Link txt (src, tit)) = do- linktext <- inlineListToMarkdown opts txt- let linktitle = if null tit then empty else text $ " \"" ++ tit ++ "\""- let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src- let useRefLinks = writerReferenceLinks opts- let useAuto = null tit && txt == [Code srcSuffix]- ref <- if useRefLinks then getReference txt (src, tit) else return []- reftext <- inlineListToMarkdown opts ref- return $ if useAuto- then char '<' <> text srcSuffix <> char '>' - else if useRefLinks- then let first = char '[' <> linktext <> char ']'- second = if txt == ref- then text "[]"- else char '[' <> reftext <> char ']'- in first <> second- else char '[' <> linktext <> char ']' <> - char '(' <> text src <> linktitle <> char ')' -inlineToMarkdown opts (Image alternate (source, tit)) = do- let txt = if (null alternate) || (alternate == [Str ""]) || - (alternate == [Str source]) -- to prevent autolinks- then [Str "image"]- else alternate- linkPart <- inlineToMarkdown opts (Link txt (source, tit)) - return $ char '!' <> linkPart-inlineToMarkdown opts (Note contents) = do - modify (\(notes, refs) -> (contents:notes, refs)) -- add to notes in state- (notes, _) <- get- let ref = show $ (length notes)- return $ text "[^" <> text ref <> char ']'
− src/Text/Pandoc/Writers/RST.hs
@@ -1,323 +0,0 @@-{--Copyright (C) 2006-7 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.RST - Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion of 'Pandoc' documents to reStructuredText.--reStructuredText: <http://docutils.sourceforge.net/rst.html>--}-module Text.Pandoc.Writers.RST ( writeRST) where-import Text.Pandoc.Definition-import Text.Pandoc.Shared -import Text.Pandoc.Blocks-import Data.List ( isPrefixOf, isSuffixOf, drop, intersperse )-import Text.PrettyPrint.HughesPJ hiding ( Str )-import Control.Monad.State--type Notes = [[Block]]-type Refs = KeyTable-type WriterState = (Notes, Refs, Refs) -- first Refs is links, second pictures---- | Convert Pandoc to RST.-writeRST :: WriterOptions -> Pandoc -> String-writeRST opts document = - render $ evalState (pandocToRST opts document) ([],[],[]) ---- | Return RST representation of document.-pandocToRST :: WriterOptions -> Pandoc -> State WriterState Doc-pandocToRST opts (Pandoc meta blocks) = do- let before = writerIncludeBefore opts- let after = writerIncludeAfter opts- before' = if null before then empty else text before- after' = if null after then empty else text after- metaBlock <- metaToRST opts meta- let head = if (writerStandalone opts)- then metaBlock $+$ text (writerHeader opts)- else empty- body <- blockListToRST opts blocks- (notes, _, _) <- get- notes' <- notesToRST opts (reverse notes)- (_, refs, pics) <- get -- note that the notes may contain refs- refs' <- keyTableToRST opts (reverse refs)- pics' <- pictTableToRST opts (reverse pics)- return $ head $+$ before' $+$ body $+$ notes' $+$ text "" $+$ refs' $+$ - pics' $+$ after'---- | Return RST representation of reference key table.-keyTableToRST :: WriterOptions -> KeyTable -> State WriterState Doc-keyTableToRST opts refs = mapM (keyToRST opts) refs >>= return . vcat- --- | Return RST representation of a reference key. -keyToRST :: WriterOptions - -> ([Inline], (String, String)) - -> State WriterState Doc-keyToRST opts (label, (src, tit)) = do- label' <- inlineListToRST opts label- return $ text ".. _" <> label' <> text ": " <> text src---- | Return RST representation of notes.-notesToRST :: WriterOptions -> [[Block]] -> State WriterState Doc-notesToRST opts notes = - mapM (\(num, note) -> noteToRST opts num note) (zip [1..] notes) >>= - return . vcat---- | Return RST representation of a note.-noteToRST :: WriterOptions -> Int -> [Block] -> State WriterState Doc-noteToRST opts num note = do- contents <- blockListToRST opts note- let marker = text ".. [" <> text (show num) <> text "] "- return $ hang marker 3 contents ---- | Return RST representation of picture reference table.-pictTableToRST :: WriterOptions -> KeyTable -> State WriterState Doc-pictTableToRST opts refs = mapM (pictToRST opts) refs >>= return . vcat- --- | Return RST representation of a picture substitution reference. -pictToRST :: WriterOptions - -> ([Inline], (String, String)) - -> State WriterState Doc-pictToRST opts (label, (src, _)) = do- label' <- inlineListToRST opts label- return $ text ".. " <> char '|' <> label' <> char '|' <> text " image:: " <>- text src---- | Take list of inline elements and return wrapped doc.-wrappedRST :: WriterOptions -> [Inline] -> State WriterState Doc-wrappedRST opts inlines = - mapM (wrapped (inlineListToRST opts)) (splitBy LineBreak inlines) >>= - return . vcat---- | Escape special characters for RST.-escapeString :: String -> String-escapeString = escapeStringUsing (backslashEscapes "`\\|*_")---- | Convert bibliographic information into RST header.-metaToRST :: WriterOptions -> Meta -> State WriterState Doc-metaToRST opts (Meta title authors date) = do- title' <- titleToRST opts title- authors' <- authorsToRST authors- date' <- dateToRST date- let toc = if writerTableOfContents opts- then text "" $+$ text ".. contents::"- else empty- return $ title' $+$ authors' $+$ date' $+$ toc--titleToRST :: WriterOptions -> [Inline] -> State WriterState Doc-titleToRST opts [] = return empty-titleToRST opts lst = do- contents <- inlineListToRST opts lst- let titleLength = length $ render contents- let border = text (replicate titleLength '=')- return $ border $+$ contents $+$ border <> text "\n"--authorsToRST :: [String] -> State WriterState Doc-authorsToRST [] = return empty-authorsToRST (first:rest) = do- rest' <- authorsToRST rest- return $ (text ":Author: " <> text first) $+$ rest'--dateToRST :: String -> State WriterState Doc-dateToRST [] = return empty-dateToRST str = return $ text ":Date: " <> text (escapeString str)---- | Convert Pandoc block element to RST. -blockToRST :: WriterOptions -- ^ Options- -> Block -- ^ Block element- -> State WriterState Doc -blockToRST opts Null = return empty-blockToRST opts (Plain inlines) = wrappedRST opts inlines-blockToRST opts (Para [TeX str]) =- let str' = if "\n" `isSuffixOf` str then str ++ "\n" else str ++ "\n\n" in- return $ hang (text "\n.. raw:: latex\n") 3 $ vcat $ map text (lines str')-blockToRST opts (Para inlines) = do- contents <- wrappedRST opts inlines- return $ contents <> text "\n"-blockToRST opts (RawHtml str) = - let str' = if "\n" `isSuffixOf` str then str ++ "\n" else str ++ "\n\n" in- return $ hang (text "\n.. raw:: html\n") 3 $ vcat $ map text (lines str')-blockToRST opts HorizontalRule = return $ text "--------------\n"-blockToRST opts (Header level inlines) = do- contents <- inlineListToRST opts inlines- let headerLength = length $ render contents- let headerChar = if level > 5 then ' ' else "=-~^'" !! (level - 1)- let border = text $ replicate headerLength headerChar- return $ contents $+$ border <> text "\n"-blockToRST opts (CodeBlock str) = return $ (text "::\n") $+$ - (nest (writerTabStop opts) $ vcat $ map text (lines str)) <> text "\n"-blockToRST opts (BlockQuote blocks) = do- contents <- blockListToRST opts blocks - return $ (nest (writerTabStop opts) contents) <> text "\n"-blockToRST opts (Table caption aligns widths headers rows) = do- caption' <- inlineListToRST opts caption- let caption'' = if null caption- then empty- else text "" $+$ (text "Table: " <> caption')- headers' <- mapM (blockListToRST opts) headers- let widthsInChars = map (floor . (78 *)) widths- let alignHeader alignment = case alignment of- AlignLeft -> leftAlignBlock- AlignCenter -> centerAlignBlock- AlignRight -> rightAlignBlock- AlignDefault -> leftAlignBlock - let hpipeBlocks blocks = hcatBlocks [beg, middle, end] - where height = maximum (map heightOfBlock blocks)- sep = TextBlock 3 height (replicate height " | ")- beg = TextBlock 2 height (replicate height "| ")- end = TextBlock 2 height (replicate height " |")- middle = hcatBlocks $ intersperse sep blocks- let makeRow = hpipeBlocks . zipWith docToBlock widthsInChars- let head = makeRow headers'- rows' <- mapM (\row -> do cols <- mapM (blockListToRST opts) row- return $ makeRow cols) rows- let tableWidth = sum widthsInChars- let maxRowHeight = maximum $ map heightOfBlock (head:rows')- let border ch = char '+' <> char ch <>- (hcat $ intersperse (char ch <> char '+' <> char ch) $ - map (\l -> text $ replicate l ch) widthsInChars) <>- char ch <> char '+'- let body = vcat $ intersperse (border '-') $ map blockToDoc rows'- return $ border '-' $+$ blockToDoc head $+$ border '=' $+$ body $+$ - border '-' $$ caption'' $$ text ""-blockToRST opts (BulletList items) = do- contents <- mapM (bulletListItemToRST opts) items- -- ensure that sublists have preceding blank line- return $ text "" $+$ vcat contents <> text "\n"-blockToRST opts (OrderedList (start, style, delim) items) = do- let markers = if start == 1 && style == DefaultStyle && delim == DefaultDelim - then take (length items) $ repeat "#."- else take (length items) $ orderedListMarkers - (start, style, delim)- let maxMarkerLength = maximum $ map length markers- let markers' = map (\m -> let s = maxMarkerLength - length m- in m ++ replicate s ' ') markers- contents <- mapM (\(item, num) -> orderedListItemToRST opts item num) $- zip markers' items - -- ensure that sublists have preceding blank line- return $ text "" $+$ vcat contents <> text "\n"-blockToRST opts (DefinitionList items) = do- contents <- mapM (definitionListItemToRST opts) items- return $ (vcat contents) <> text "\n"---- | Convert bullet list item (list of blocks) to RST.-bulletListItemToRST :: WriterOptions -> [Block] -> State WriterState Doc-bulletListItemToRST opts items = do- contents <- blockListToRST opts items- return $ hang (text "- ") (writerTabStop opts) contents---- | Convert ordered list item (a list of blocks) to RST.-orderedListItemToRST :: WriterOptions -- ^ options- -> String -- ^ marker for list item- -> [Block] -- ^ list item (list of blocks)- -> State WriterState Doc-orderedListItemToRST opts marker items = do- contents <- blockListToRST opts items- return $ hang (text marker) (writerTabStop opts) contents ---- | Convert defintion list item (label, list of blocks) to RST.-definitionListItemToRST :: WriterOptions -> ([Inline], [Block]) -> State WriterState Doc-definitionListItemToRST opts (label, items) = do- label <- inlineListToRST opts label- contents <- blockListToRST opts items- return $ label $+$ nest (writerTabStop opts) contents---- | Convert list of Pandoc block elements to RST.-blockListToRST :: WriterOptions -- ^ Options- -> [Block] -- ^ List of block elements- -> State WriterState Doc -blockListToRST opts blocks =- mapM (blockToRST opts) blocks >>= return . vcat---- | Convert list of Pandoc inline elements to RST.-inlineListToRST :: WriterOptions -> [Inline] -> State WriterState Doc-inlineListToRST opts lst = mapM (inlineToRST opts) lst >>= return . hcat---- | Convert Pandoc inline element to RST.-inlineToRST :: WriterOptions -> Inline -> State WriterState Doc-inlineToRST opts (Emph lst) = do - contents <- inlineListToRST opts lst- return $ char '*' <> contents <> char '*'-inlineToRST opts (Strong lst) = do- contents <- inlineListToRST opts lst- return $ text "**" <> contents <> text "**"-inlineToRST opts (Strikeout lst) = do - contents <- inlineListToRST opts lst- return $ text "[STRIKEOUT:" <> contents <> char ']'-inlineToRST opts (Superscript lst) = do - contents <- inlineListToRST opts lst- return $ text "\\ :sup:`" <> contents <> text "`\\ "-inlineToRST opts (Subscript lst) = do - contents <- inlineListToRST opts lst- return $ text "\\ :sub:`" <> contents <> text "`\\ "-inlineToRST opts (Quoted SingleQuote lst) = do- contents <- inlineListToRST opts lst- return $ char '\'' <> contents <> char '\''-inlineToRST opts (Quoted DoubleQuote lst) = do- contents <- inlineListToRST opts lst- return $ char '"' <> contents <> char '"'-inlineToRST opts EmDash = return $ text "--"-inlineToRST opts EnDash = return $ char '-'-inlineToRST opts Apostrophe = return $ char '\''-inlineToRST opts Ellipses = return $ text "..."-inlineToRST opts (Code str) = return $ text $ "``" ++ str ++ "``"-inlineToRST opts (Str str) = return $ text $ escapeString str-inlineToRST opts (TeX str) = return $ text str-inlineToRST opts (HtmlInline str) = return empty-inlineToRST opts (LineBreak) = return $ char ' ' -- RST doesn't have linebreaks -inlineToRST opts Space = return $ char ' '-inlineToRST opts (Link [Code str] (src, tit)) | src == str ||- src == "mailto:" ++ str = do- let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src- return $ text srcSuffix-inlineToRST opts (Link txt (src, tit)) = do- let useReferenceLinks = writerReferenceLinks opts- linktext <- inlineListToRST opts $ normalizeSpaces txt- if useReferenceLinks- then do (notes, refs, pics) <- get- let refs' = if (txt, (src, tit)) `elem` refs- then refs- else (txt, (src, tit)):refs- put (notes, refs', pics)- return $ char '`' <> linktext <> text "`_"- else return $ char '`' <> linktext <> text " <" <> text src <> text ">`_"-inlineToRST opts (Image alternate (source, tit)) = do- (notes, refs, pics) <- get- let labelsUsed = map fst pics - let txt = if null alternate || alternate == [Str ""] || - alternate `elem` labelsUsed- then [Str $ "image" ++ show (length refs)]- else alternate- let pics' = if (txt, (source, tit)) `elem` pics- then pics- else (txt, (source, tit)):pics- put (notes, refs, pics')- label <- inlineListToRST opts txt- return $ char '|' <> label <> char '|'-inlineToRST opts (Note contents) = do - -- add to notes in state- modify (\(notes, refs, pics) -> (contents:notes, refs, pics))- (notes, _, _) <- get- let ref = show $ (length notes)- return $ text " [" <> text ref <> text "]_"
− src/Text/Pandoc/Writers/RTF.hs
@@ -1,286 +0,0 @@-{--Copyright (C) 2006-7 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.RTF- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha - Portability : portable--Conversion of 'Pandoc' documents to RTF (rich text format).--}-module Text.Pandoc.Writers.RTF ( writeRTF ) where-import Text.Pandoc.Definition-import Text.Pandoc.Shared-import Text.Regex ( matchRegexAll, mkRegex )-import Data.List ( isSuffixOf )-import Data.Char ( ord )---- | Convert Pandoc to a string in rich text format.-writeRTF :: WriterOptions -> Pandoc -> String-writeRTF options (Pandoc meta blocks) = - let head = if writerStandalone options- then rtfHeader (writerHeader options) meta - else ""- toc = if writerTableOfContents options- then tableOfContents $ filter isHeaderBlock blocks- else "" - foot = if writerStandalone options then "\n}\n" else "" - body = writerIncludeBefore options ++ - concatMap (blockToRTF 0 AlignDefault) blocks ++ - writerIncludeAfter options- in head ++ toc ++ body ++ foot---- | Construct table of contents from list of header blocks.-tableOfContents :: [Block] -> String -tableOfContents headers =- let contentsTree = hierarchicalize headers- in concatMap (blockToRTF 0 AlignDefault) $ - [Header 1 [Str "Contents"], - BulletList (map elementToListItem contentsTree)]--elementToListItem :: Element -> [Block]-elementToListItem (Blk _) = []-elementToListItem (Sec sectext subsecs) = [Plain sectext] ++- if null subsecs- then []- else [BulletList (map elementToListItem subsecs)]---- | Convert unicode characters (> 127) into rich text format representation.-handleUnicode :: String -> String-handleUnicode [] = []-handleUnicode (c:cs) =- if ord c > 127 - then '\\':'u':(show (ord c)) ++ "?" ++ handleUnicode cs- else c:(handleUnicode cs)---- | Escape special characters.-escapeSpecial :: String -> String-escapeSpecial = escapeStringUsing (('\t',"\\tab "):(backslashEscapes "{\\}"))---- | Escape strings as needed for rich text format.-stringToRTF :: String -> String-stringToRTF = handleUnicode . escapeSpecial---- | Escape things as needed for code block in RTF.-codeStringToRTF :: String -> String-codeStringToRTF str = joinWithSep "\\line\n" $ lines (stringToRTF str)---- | Deal with raw LaTeX.-latexToRTF :: String -> String-latexToRTF str = "{\\cf1 " ++ (stringToRTF str) ++ "\\cf0 } "---- | Make a paragraph with first-line indent, block indent, and space after.-rtfParSpaced :: Int -- ^ space after (in twips)- -> Int -- ^ block indent (in twips)- -> Int -- ^ first line indent (relative to block) (in twips)- -> Alignment -- ^ alignment- -> String -- ^ string with content- -> String -rtfParSpaced spaceAfter indent firstLineIndent alignment content = - let alignString = case alignment of- AlignLeft -> "\\ql "- AlignRight -> "\\qr "- AlignCenter -> "\\qc "- AlignDefault -> "\\ql "- in "{\\pard " ++ alignString ++- "\\f0 \\sa" ++ (show spaceAfter) ++ " \\li" ++ (show indent) ++ - " \\fi" ++ (show firstLineIndent) ++ " " ++ content ++ "\\par}\n"---- | Default paragraph. -rtfPar :: Int -- ^ block indent (in twips)- -> Int -- ^ first line indent (relative to block) (in twips)- -> Alignment -- ^ alignment- -> String -- ^ string with content- -> String -rtfPar = rtfParSpaced 180 ---- | Compact paragraph (e.g. for compact list items).-rtfCompact :: Int -- ^ block indent (in twips)- -> Int -- ^ first line indent (relative to block) (in twips)- -> Alignment -- ^ alignment- -> String -- ^ string with content- -> String -rtfCompact = rtfParSpaced 0 ---- number of twips to indent-indentIncrement = 720-listIncrement = 360---- | Returns appropriate bullet list marker for indent level.-bulletMarker :: Int -> String-bulletMarker indent = case indent `mod` 720 of- 0 -> "\\bullet "- otherwise -> "\\endash "---- | Returns appropriate (list of) ordered list markers for indent level.-orderedMarkers :: Int -> ListAttributes -> [String]-orderedMarkers indent (start, style, delim) = - if style == DefaultStyle && delim == DefaultDelim- then case indent `mod` 720 of- 0 -> orderedListMarkers (start, Decimal, Period)- otherwise -> orderedListMarkers (start, LowerAlpha, Period)- else orderedListMarkers (start, style, delim)---- | Returns RTF header.-rtfHeader :: String -- ^ header text- -> Meta -- ^ bibliographic information- -> String-rtfHeader headerText (Meta title authors date) =- let titletext = if null title- then "" - else rtfPar 0 0 AlignCenter $- "\\b \\fs36 " ++ inlineListToRTF title- authorstext = if null authors- then "" - else rtfPar 0 0 AlignCenter (" " ++ (joinWithSep "\\" $- map stringToRTF authors))- datetext = if date == "" - then ""- else rtfPar 0 0 AlignCenter (" " ++ stringToRTF date) in- let spacer = if null (titletext ++ authorstext ++ datetext)- then ""- else rtfPar 0 0 AlignDefault "" in- headerText ++ titletext ++ authorstext ++ datetext ++ spacer---- | Convert Pandoc block element to RTF.-blockToRTF :: Int -- ^ indent level- -> Alignment -- ^ alignment- -> Block -- ^ block to convert- -> String-blockToRTF _ _ Null = ""-blockToRTF indent alignment (Plain lst) = - rtfCompact indent 0 alignment $ inlineListToRTF lst-blockToRTF indent alignment (Para lst) = - rtfPar indent 0 alignment $ inlineListToRTF lst-blockToRTF indent alignment (BlockQuote lst) = - concatMap (blockToRTF (indent + indentIncrement) alignment) lst -blockToRTF indent _ (CodeBlock str) =- rtfPar indent 0 AlignLeft ("\\f1 " ++ (codeStringToRTF str))-blockToRTF _ _ (RawHtml str) = ""-blockToRTF indent alignment (BulletList lst) = spaceAtEnd $ - concatMap (listItemToRTF alignment indent (bulletMarker indent)) lst-blockToRTF indent alignment (OrderedList attribs lst) = spaceAtEnd $ concat $ - zipWith (listItemToRTF alignment indent) (orderedMarkers indent attribs) lst-blockToRTF indent alignment (DefinitionList lst) = spaceAtEnd $ - concatMap (definitionListItemToRTF alignment indent) lst-blockToRTF indent _ HorizontalRule = - rtfPar indent 0 AlignCenter "\\emdash\\emdash\\emdash\\emdash\\emdash"-blockToRTF indent alignment (Header level lst) = rtfPar indent 0 alignment $- "\\b \\fs" ++ (show (40 - (level * 4))) ++ " " ++ inlineListToRTF lst-blockToRTF indent alignment (Table caption aligns sizes headers rows) = - tableRowToRTF True indent aligns sizes headers ++ - concatMap (tableRowToRTF False indent aligns sizes) rows ++- rtfPar indent 0 alignment (inlineListToRTF caption)--tableRowToRTF :: Bool -> Int -> [Alignment] -> [Float] -> [[Block]] -> String -tableRowToRTF header indent aligns sizes cols =- let columns = concat $ zipWith (tableItemToRTF indent) aligns cols- totalTwips = 6 * 1440 -- 6 inches- rightEdges = tail $ scanl (\sofar new -> sofar + floor (new * totalTwips))- 0 sizes- cellDefs = map (\edge -> (if header- then "\\clbrdrb\\brdrs"- else "") ++ "\\cellx" ++ show edge)- rightEdges- start = "{\n\\trowd \\trgaph120\n" ++ concat cellDefs ++ "\n" ++- "\\trkeep\\intbl\n{\n"- end = "}\n\\intbl\\row}\n"- in start ++ columns ++ end--tableItemToRTF :: Int -> Alignment -> [Block] -> String -tableItemToRTF indent alignment item =- let contents = concatMap (blockToRTF indent alignment) item- in "{\\intbl " ++ contents ++ "\\cell}\n"---- | Ensure that there's the same amount of space after compact--- lists as after regular lists.-spaceAtEnd :: String -> String-spaceAtEnd str = - if isSuffixOf "\\par}\n" str- then (take ((length str) - 6) str) ++ "\\sa180\\par}\n"- else str---- | Convert list item (list of blocks) to RTF.-listItemToRTF :: Alignment -- ^ alignment- -> Int -- ^ indent level- -> String -- ^ list start marker- -> [Block] -- ^ list item (list of blocks)- -> [Char]-listItemToRTF alignment indent marker [] = - rtfCompact (indent + listIncrement) (0 - listIncrement) alignment - (marker ++ "\\tx" ++ (show listIncrement) ++ "\\tab ") -listItemToRTF alignment indent marker list = - let (first:rest) = map (blockToRTF (indent + listIncrement) alignment) list in- -- insert the list marker into the (processed) first block- let modFirst = case matchRegexAll (mkRegex "\\\\fi-?[0-9]+") first of- Just (before, matched, after, _) -> - before ++ "\\fi" ++ show (0 - listIncrement) ++ - " " ++ marker ++ "\\tx" ++ - show listIncrement ++ "\\tab" ++ after- Nothing -> first in- modFirst ++ concat rest---- | Convert definition list item (label, list of blocks) to RTF.-definitionListItemToRTF :: Alignment -- ^ alignment- -> Int -- ^ indent level- -> ([Inline],[Block]) -- ^ list item (list of blocks)- -> [Char]-definitionListItemToRTF alignment indent (label, items) =- let labelText = blockToRTF indent alignment (Plain label)- itemsText = concatMap (blockToRTF (indent + listIncrement) alignment) items- in labelText ++ itemsText ---- | Convert list of inline items to RTF.-inlineListToRTF :: [Inline] -- ^ list of inlines to convert- -> String-inlineListToRTF lst = concatMap inlineToRTF lst---- | Convert inline item to RTF.-inlineToRTF :: Inline -- ^ inline to convert- -> String-inlineToRTF (Emph lst) = "{\\i " ++ (inlineListToRTF lst) ++ "} "-inlineToRTF (Strong lst) = "{\\b " ++ (inlineListToRTF lst) ++ "} "-inlineToRTF (Strikeout lst) = "{\\strike " ++ (inlineListToRTF lst) ++ "} "-inlineToRTF (Superscript lst) = "{\\super " ++ (inlineListToRTF lst) ++ "} "-inlineToRTF (Subscript lst) = "{\\sub " ++ (inlineListToRTF lst) ++ "} "-inlineToRTF (Quoted SingleQuote lst) = - "\\u8216'" ++ (inlineListToRTF lst) ++ "\\u8217'"-inlineToRTF (Quoted DoubleQuote lst) = - "\\u8220\"" ++ (inlineListToRTF lst) ++ "\\u8221\""-inlineToRTF Apostrophe = "\\u8217'"-inlineToRTF Ellipses = "\\u8230?"-inlineToRTF EmDash = "\\u8212-"-inlineToRTF EnDash = "\\u8211-"-inlineToRTF (Code str) = "{\\f1 " ++ (codeStringToRTF str) ++ "} "-inlineToRTF (Str str) = stringToRTF str-inlineToRTF (TeX str) = latexToRTF str-inlineToRTF (HtmlInline str) = ""-inlineToRTF (LineBreak) = "\\line "-inlineToRTF Space = " "-inlineToRTF (Link text (src, tit)) = - "{\\field{\\*\\fldinst{HYPERLINK \"" ++ (codeStringToRTF src) ++ - "\"}}{\\fldrslt{\\ul\n" ++ (inlineListToRTF text) ++ "\n}}}\n"-inlineToRTF (Image alternate (source, tit)) = - "{\\cf1 [image: " ++ source ++ "]\\cf0}" -inlineToRTF (Note contents) =- "{\\super\\chftn}{\\*\\footnote\\chftn\\~\\plain\\pard " ++ - (concatMap (blockToRTF 0 AlignDefault) contents) ++ "}"
− src/Text/Pandoc/Writers/S5.hs
@@ -1,140 +0,0 @@-------------------------------------------------------- Do not edit this file by hand. Edit --- 'templates/S5.hs'--- and run ./fillTemplates.pl Text/Pandoc/Writers/S5.hs-------------------------------------------------------{--Copyright (C) 2006-7 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.S5- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Definitions for creation of S5 powerpoint-like HTML.-(See <http://meyerweb.com/eric/tools/s5/>.)--}-module Text.Pandoc.Writers.S5 (- -- * Strings- s5Meta,- s5Javascript,- s5CSS,- s5Links,- -- * Functions- writeS5,- writeS5String,- insertS5Structure- ) where-import Text.Pandoc.Shared ( joinWithSep, WriterOptions )-import Text.Pandoc.Writers.HTML ( writeHtml, writeHtmlString )-import Text.Pandoc.Definition-import Text.XHtml.Strict--s5Meta :: String-s5Meta = "<!-- configuration parameters -->\n<meta name=\"defaultView\" content=\"slideshow\" />\n<meta name=\"controlVis\" content=\"hidden\" />\n"--s5Javascript :: String-s5Javascript = "<script type=\"text/javascript\">\n// S5 v1.1 slides.js -- released into the Public Domain\n//\n// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information \n// about all the wonderful and talented contributors to this code!\n\nvar undef;\nvar slideCSS = '';\nvar snum = 0;\nvar smax = 1;\nvar incpos = 0;\nvar number = undef;\nvar s5mode = true;\nvar defaultView = 'slideshow';\nvar controlVis = 'visible';\n\nvar isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0;\nvar isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0;\nvar isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0;\n\nfunction hasClass(object, className) {\n\tif (!object.className) return false;\n\treturn (object.className.search('(^|\\\\s)' + className + '(\\\\s|$)') != -1);\n}\n\nfunction hasValue(object, value) {\n\tif (!object) return false;\n\treturn (object.search('(^|\\\\s)' + value + '(\\\\s|$)') != -1);\n}\n\nfunction removeClass(object,className) {\n\tif (!object) return;\n\tobject.className = object.className.replace(new RegExp('(^|\\\\s)'+className+'(\\\\s|$)'), RegExp.$1+RegExp.$2);\n}\n\nfunction addClass(object,className) {\n\tif (!object || hasClass(object, className)) return;\n\tif (object.className) {\n\t\tobject.className += ' '+className;\n\t} else {\n\t\tobject.className = className;\n\t}\n}\n\nfunction GetElementsWithClassName(elementName,className) {\n\tvar allElements = document.getElementsByTagName(elementName);\n\tvar elemColl = new Array();\n\tfor (var i = 0; i< allElements.length; i++) {\n\t\tif (hasClass(allElements[i], className)) {\n\t\t\telemColl[elemColl.length] = allElements[i];\n\t\t}\n\t}\n\treturn elemColl;\n}\n\nfunction isParentOrSelf(element, id) {\n\tif (element == null || element.nodeName=='BODY') return false;\n\telse if (element.id == id) return true;\n\telse return isParentOrSelf(element.parentNode, id);\n}\n\nfunction nodeValue(node) {\n\tvar result = \"\";\n\tif (node.nodeType == 1) {\n\t\tvar children = node.childNodes;\n\t\tfor (var i = 0; i < children.length; ++i) {\n\t\t\tresult += nodeValue(children[i]);\n\t\t}\t\t\n\t}\n\telse if (node.nodeType == 3) {\n\t\tresult = node.nodeValue;\n\t}\n\treturn(result);\n}\n\nfunction slideLabel() {\n\tvar slideColl = GetElementsWithClassName('*','slide');\n\tvar list = document.getElementById('jumplist');\n\tsmax = slideColl.length;\n\tfor (var n = 0; n < smax; n++) {\n\t\tvar obj = slideColl[n];\n\n\t\tvar did = 'slide' + n.toString();\n\t\tobj.setAttribute('id',did);\n\t\tif (isOp) continue;\n\n\t\tvar otext = '';\n\t\tvar menu = obj.firstChild;\n\t\tif (!menu) continue; // to cope with empty slides\n\t\twhile (menu && menu.nodeType == 3) {\n\t\t\tmenu = menu.nextSibling;\n\t\t}\n\t \tif (!menu) continue; // to cope with slides with only text nodes\n\n\t\tvar menunodes = menu.childNodes;\n\t\tfor (var o = 0; o < menunodes.length; o++) {\n\t\t\totext += nodeValue(menunodes[o]);\n\t\t}\n\t\tlist.options[list.length] = new Option(n + ' : ' + otext, n);\n\t}\n}\n\nfunction currentSlide() {\n\tvar cs;\n\tif (document.getElementById) {\n\t\tcs = document.getElementById('currentSlide');\n\t} else {\n\t\tcs = document.currentSlide;\n\t}\n\tcs.innerHTML = '<span id=\"csHere\">' + snum + '<\\/span> ' + \n\t\t'<span id=\"csSep\">\\/<\\/span> ' + \n\t\t'<span id=\"csTotal\">' + (smax-1) + '<\\/span>';\n\tif (snum == 0) {\n\t\tcs.style.visibility = 'hidden';\n\t} else {\n\t\tcs.style.visibility = 'visible';\n\t}\n}\n\nfunction go(step) {\n\tif (document.getElementById('slideProj').disabled || step == 0) return;\n\tvar jl = document.getElementById('jumplist');\n\tvar cid = 'slide' + snum;\n\tvar ce = document.getElementById(cid);\n\tif (incrementals[snum].length > 0) {\n\t\tfor (var i = 0; i < incrementals[snum].length; i++) {\n\t\t\tremoveClass(incrementals[snum][i], 'current');\n\t\t\tremoveClass(incrementals[snum][i], 'incremental');\n\t\t}\n\t}\n\tif (step != 'j') {\n\t\tsnum += step;\n\t\tlmax = smax - 1;\n\t\tif (snum > lmax) snum = lmax;\n\t\tif (snum < 0) snum = 0;\n\t} else\n\t\tsnum = parseInt(jl.value);\n\tvar nid = 'slide' + snum;\n\tvar ne = document.getElementById(nid);\n\tif (!ne) {\n\t\tne = document.getElementById('slide0');\n\t\tsnum = 0;\n\t}\n\tif (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;}\n\tif (incrementals[snum].length > 0 && incpos == 0) {\n\t\tfor (var i = 0; i < incrementals[snum].length; i++) {\n\t\t\tif (hasClass(incrementals[snum][i], 'current'))\n\t\t\t\tincpos = i + 1;\n\t\t\telse\n\t\t\t\taddClass(incrementals[snum][i], 'incremental');\n\t\t}\n\t}\n\tif (incrementals[snum].length > 0 && incpos > 0)\n\t\taddClass(incrementals[snum][incpos - 1], 'current');\n\tce.style.visibility = 'hidden';\n\tne.style.visibility = 'visible';\n\tjl.selectedIndex = snum;\n\tcurrentSlide();\n\tnumber = 0;\n}\n\nfunction goTo(target) {\n\tif (target >= smax || target == snum) return;\n\tgo(target - snum);\n}\n\nfunction subgo(step) {\n\tif (step > 0) {\n\t\tremoveClass(incrementals[snum][incpos - 1],'current');\n\t\tremoveClass(incrementals[snum][incpos], 'incremental');\n\t\taddClass(incrementals[snum][incpos],'current');\n\t\tincpos++;\n\t} else {\n\t\tincpos--;\n\t\tremoveClass(incrementals[snum][incpos],'current');\n\t\taddClass(incrementals[snum][incpos], 'incremental');\n\t\taddClass(incrementals[snum][incpos - 1],'current');\n\t}\n}\n\nfunction toggle() {\n\tvar slideColl = GetElementsWithClassName('*','slide');\n\tvar slides = document.getElementById('slideProj');\n\tvar outline = document.getElementById('outlineStyle');\n\tif (!slides.disabled) {\n\t\tslides.disabled = true;\n\t\toutline.disabled = false;\n\t\ts5mode = false;\n\t\tfontSize('1em');\n\t\tfor (var n = 0; n < smax; n++) {\n\t\t\tvar slide = slideColl[n];\n\t\t\tslide.style.visibility = 'visible';\n\t\t}\n\t} else {\n\t\tslides.disabled = false;\n\t\toutline.disabled = true;\n\t\ts5mode = true;\n\t\tfontScale();\n\t\tfor (var n = 0; n < smax; n++) {\n\t\t\tvar slide = slideColl[n];\n\t\t\tslide.style.visibility = 'hidden';\n\t\t}\n\t\tslideColl[snum].style.visibility = 'visible';\n\t}\n}\n\nfunction showHide(action) {\n\tvar obj = GetElementsWithClassName('*','hideme')[0];\n\tswitch (action) {\n\tcase 's': obj.style.visibility = 'visible'; break;\n\tcase 'h': obj.style.visibility = 'hidden'; break;\n\tcase 'k':\n\t\tif (obj.style.visibility != 'visible') {\n\t\t\tobj.style.visibility = 'visible';\n\t\t} else {\n\t\t\tobj.style.visibility = 'hidden';\n\t\t}\n\tbreak;\n\t}\n}\n\n// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/)\nfunction keys(key) {\n\tif (!key) {\n\t\tkey = event;\n\t\tkey.which = key.keyCode;\n\t}\n\tif (key.which == 84) {\n\t\ttoggle();\n\t\treturn;\n\t}\n\tif (s5mode) {\n\t\tswitch (key.which) {\n\t\t\tcase 10: // return\n\t\t\tcase 13: // enter\n\t\t\t\tif (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;\n\t\t\t\tif (key.target && isParentOrSelf(key.target, 'controls')) return;\n\t\t\t\tif(number != undef) {\n\t\t\t\t\tgoTo(number);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tcase 32: // spacebar\n\t\t\tcase 34: // page down\n\t\t\tcase 39: // rightkey\n\t\t\tcase 40: // downkey\n\t\t\t\tif(number != undef) {\n\t\t\t\t\tgo(number);\n\t\t\t\t} else if (!incrementals[snum] || incpos >= incrementals[snum].length) {\n\t\t\t\t\tgo(1);\n\t\t\t\t} else {\n\t\t\t\t\tsubgo(1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 33: // page up\n\t\t\tcase 37: // leftkey\n\t\t\tcase 38: // upkey\n\t\t\t\tif(number != undef) {\n\t\t\t\t\tgo(-1 * number);\n\t\t\t\t} else if (!incrementals[snum] || incpos <= 0) {\n\t\t\t\t\tgo(-1);\n\t\t\t\t} else {\n\t\t\t\t\tsubgo(-1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 36: // home\n\t\t\t\tgoTo(0);\n\t\t\t\tbreak;\n\t\t\tcase 35: // end\n\t\t\t\tgoTo(smax-1);\n\t\t\t\tbreak;\n\t\t\tcase 67: // c\n\t\t\t\tshowHide('k');\n\t\t\t\tbreak;\n\t\t}\n\t\tif (key.which < 48 || key.which > 57) {\n\t\t\tnumber = undef;\n\t\t} else {\n\t\t\tif (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;\n\t\t\tif (key.target && isParentOrSelf(key.target, 'controls')) return;\n\t\t\tnumber = (((number != undef) ? number : 0) * 10) + (key.which - 48);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction clicker(e) {\n\tnumber = undef;\n\tvar target;\n\tif (window.event) {\n\t\ttarget = window.event.srcElement;\n\t\te = window.event;\n\t} else target = e.target;\n\tif (target.getAttribute('href') != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true;\n\tif (!e.which || e.which == 1) {\n\t\tif (!incrementals[snum] || incpos >= incrementals[snum].length) {\n\t\t\tgo(1);\n\t\t} else {\n\t\t\tsubgo(1);\n\t\t}\n\t}\n}\n\nfunction findSlide(hash) {\n\tvar target = null;\n\tvar slides = GetElementsWithClassName('*','slide');\n\tfor (var i = 0; i < slides.length; i++) {\n\t\tvar targetSlide = slides[i];\n\t\tif ( (targetSlide.name && targetSlide.name == hash)\n\t\t || (targetSlide.id && targetSlide.id == hash) ) {\n\t\t\ttarget = targetSlide;\n\t\t\tbreak;\n\t\t}\n\t}\n\twhile(target != null && target.nodeName != 'BODY') {\n\t\tif (hasClass(target, 'slide')) {\n\t\t\treturn parseInt(target.id.slice(5));\n\t\t}\n\t\ttarget = target.parentNode;\n\t}\n\treturn null;\n}\n\nfunction slideJump() {\n\tif (window.location.hash == null) return;\n\tvar sregex = /^#slide(\\d+)$/;\n\tvar matches = sregex.exec(window.location.hash);\n\tvar dest = null;\n\tif (matches != null) {\n\t\tdest = parseInt(matches[1]);\n\t} else {\n\t\tdest = findSlide(window.location.hash.slice(1));\n\t}\n\tif (dest != null)\n\t\tgo(dest - snum);\n}\n\nfunction fixLinks() {\n\tvar thisUri = window.location.href;\n\tthisUri = thisUri.slice(0, thisUri.length - window.location.hash.length);\n\tvar aelements = document.getElementsByTagName('A');\n\tfor (var i = 0; i < aelements.length; i++) {\n\t\tvar a = aelements[i].href;\n\t\tvar slideID = a.match('\\#slide[0-9]{1,2}');\n\t\tif ((slideID) && (slideID[0].slice(0,1) == '#')) {\n\t\t\tvar dest = findSlide(slideID[0].slice(1));\n\t\t\tif (dest != null) {\n\t\t\t\tif (aelements[i].addEventListener) {\n\t\t\t\t\taelements[i].addEventListener(\"click\", new Function(\"e\",\n\t\t\t\t\t\t\"if (document.getElementById('slideProj').disabled) return;\" +\n\t\t\t\t\t\t\"go(\"+dest+\" - snum); \" +\n\t\t\t\t\t\t\"if (e.preventDefault) e.preventDefault();\"), true);\n\t\t\t\t} else if (aelements[i].attachEvent) {\n\t\t\t\t\taelements[i].attachEvent(\"onclick\", new Function(\"\",\n\t\t\t\t\t\t\"if (document.getElementById('slideProj').disabled) return;\" +\n\t\t\t\t\t\t\"go(\"+dest+\" - snum); \" +\n\t\t\t\t\t\t\"event.returnValue = false;\"));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction externalLinks() {\n\tif (!document.getElementsByTagName) return;\n\tvar anchors = document.getElementsByTagName('a');\n\tfor (var i=0; i<anchors.length; i++) {\n\t\tvar anchor = anchors[i];\n\t\tif (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) {\n\t\t\tanchor.target = '_blank';\n\t\t\taddClass(anchor,'external');\n\t\t}\n\t}\n}\n\nfunction createControls() {\n\tvar controlsDiv = document.getElementById(\"controls\");\n\tif (!controlsDiv) return;\n\tvar hider = ' onmouseover=\"showHide(\\'s\\');\" onmouseout=\"showHide(\\'h\\');\"';\n\tvar hideDiv, hideList = '';\n\tif (controlVis == 'hidden') {\n\t\thideDiv = hider;\n\t} else {\n\t\thideList = hider;\n\t}\n\tcontrolsDiv.innerHTML = '<form action=\"#\" id=\"controlForm\"' + hideDiv + '>' +\n\t'<div id=\"navLinks\">' +\n\t'<a accesskey=\"t\" id=\"toggle\" href=\"javascript:toggle();\">Ø<\\/a>' +\n\t'<a accesskey=\"z\" id=\"prev\" href=\"javascript:go(-1);\">«<\\/a>' +\n\t'<a accesskey=\"x\" id=\"next\" href=\"javascript:go(1);\">»<\\/a>' +\n\t'<div id=\"navList\"' + hideList + '><select id=\"jumplist\" onchange=\"go(\\'j\\');\"><\\/select><\\/div>' +\n\t'<\\/div><\\/form>';\n\tif (controlVis == 'hidden') {\n\t\tvar hidden = document.getElementById('navLinks');\n\t} else {\n\t\tvar hidden = document.getElementById('jumplist');\n\t}\n\taddClass(hidden,'hideme');\n}\n\nfunction fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers\n\tif (!s5mode) return false;\n\tvar vScale = 22; // both yield 32 (after rounding) at 1024x768\n\tvar hScale = 32; // perhaps should auto-calculate based on theme's declared value?\n\tif (window.innerHeight) {\n\t\tvar vSize = window.innerHeight;\n\t\tvar hSize = window.innerWidth;\n\t} else if (document.documentElement.clientHeight) {\n\t\tvar vSize = document.documentElement.clientHeight;\n\t\tvar hSize = document.documentElement.clientWidth;\n\t} else if (document.body.clientHeight) {\n\t\tvar vSize = document.body.clientHeight;\n\t\tvar hSize = document.body.clientWidth;\n\t} else {\n\t\tvar vSize = 700; // assuming 1024x768, minus chrome and such\n\t\tvar hSize = 1024; // these do not account for kiosk mode or Opera Show\n\t}\n\tvar newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale));\n\tfontSize(newSize + 'px');\n\tif (isGe) { // hack to counter incremental reflow bugs\n\t\tvar obj = document.getElementsByTagName('body')[0];\n\t\tobj.style.display = 'none';\n\t\tobj.style.display = 'block';\n\t}\n}\n\nfunction fontSize(value) {\n\tif (!(s5ss = document.getElementById('s5ss'))) {\n\t\tif (!isIE) {\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style'));\n\t\t\ts5ss.setAttribute('media','screen, projection');\n\t\t\ts5ss.setAttribute('id','s5ss');\n\t\t} else {\n\t\t\tdocument.createStyleSheet();\n\t\t\tdocument.s5ss = document.styleSheets[document.styleSheets.length - 1];\n\t\t}\n\t}\n\tif (!isIE) {\n\t\twhile (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild);\n\t\ts5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}'));\n\t} else {\n\t\tdocument.s5ss.addRule('body','font-size: ' + value + ' !important;');\n\t}\n}\n\nfunction notOperaFix() {\n\tslideCSS = document.getElementById('slideProj').href;\n\tvar slides = document.getElementById('slideProj');\n\tvar outline = document.getElementById('outlineStyle');\n\tslides.setAttribute('media','screen');\n\toutline.disabled = true;\n\tif (isGe) {\n\t\tslides.setAttribute('href','null'); // Gecko fix\n\t\tslides.setAttribute('href',slideCSS); // Gecko fix\n\t}\n\tif (isIE && document.styleSheets && document.styleSheets[0]) {\n\t\tdocument.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)');\n\t\tdocument.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)');\n\t\tdocument.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)');\n\t}\n}\n\nfunction getIncrementals(obj) {\n\tvar incrementals = new Array();\n\tif (!obj) \n\t\treturn incrementals;\n\tvar children = obj.childNodes;\n\tfor (var i = 0; i < children.length; i++) {\n\t\tvar child = children[i];\n\t\tif (hasClass(child, 'incremental')) {\n\t\t\tif (child.nodeName == 'OL' || child.nodeName == 'UL') {\n\t\t\t\tremoveClass(child, 'incremental');\n\t\t\t\tfor (var j = 0; j < child.childNodes.length; j++) {\n\t\t\t\t\tif (child.childNodes[j].nodeType == 1) {\n\t\t\t\t\t\taddClass(child.childNodes[j], 'incremental');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tincrementals[incrementals.length] = child;\n\t\t\t\tremoveClass(child,'incremental');\n\t\t\t}\n\t\t}\n\t\tif (hasClass(child, 'show-first')) {\n\t\t\tif (child.nodeName == 'OL' || child.nodeName == 'UL') {\n\t\t\t\tremoveClass(child, 'show-first');\n\t\t\t\tif (child.childNodes[isGe].nodeType == 1) {\n\t\t\t\t\tremoveClass(child.childNodes[isGe], 'incremental');\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tincrementals[incrementals.length] = child;\n\t\t\t}\n\t\t}\n\t\tincrementals = incrementals.concat(getIncrementals(child));\n\t}\n\treturn incrementals;\n}\n\nfunction createIncrementals() {\n\tvar incrementals = new Array();\n\tfor (var i = 0; i < smax; i++) {\n\t\tincrementals[i] = getIncrementals(document.getElementById('slide'+i));\n\t}\n\treturn incrementals;\n}\n\nfunction defaultCheck() {\n\tvar allMetas = document.getElementsByTagName('meta');\n\tfor (var i = 0; i< allMetas.length; i++) {\n\t\tif (allMetas[i].name == 'defaultView') {\n\t\t\tdefaultView = allMetas[i].content;\n\t\t}\n\t\tif (allMetas[i].name == 'controlVis') {\n\t\t\tcontrolVis = allMetas[i].content;\n\t\t}\n\t}\n}\n\n// Key trap fix, new function body for trap()\nfunction trap(e) {\n\tif (!e) {\n\t\te = event;\n\t\te.which = e.keyCode;\n\t}\n\ttry {\n\t\tmodifierKey = e.ctrlKey || e.altKey || e.metaKey;\n\t}\n\tcatch(e) {\n\t\tmodifierKey = false;\n\t}\n\treturn modifierKey || e.which == 0;\n}\n\nfunction startup() {\n\tdefaultCheck();\n\tif (!isOp) \n\t\tcreateControls();\n\tslideLabel();\n\tfixLinks();\n\texternalLinks();\n\tfontScale();\n\tif (!isOp) {\n\t\tnotOperaFix();\n\t\tincrementals = createIncrementals();\n\t\tslideJump();\n\t\tif (defaultView == 'outline') {\n\t\t\ttoggle();\n\t\t}\n\t\tdocument.onkeyup = keys;\n\t\tdocument.onkeypress = trap;\n\t\tdocument.onclick = clicker;\n\t}\n}\n\nwindow.onload = startup;\nwindow.onresize = function(){setTimeout('fontScale()', 50);}</script>\n" --s5CoreCSS :: String-s5CoreCSS = "/* Do not edit or override these styles! The system will likely break if you do. */\n\ndiv#header, div#footer, div#controls, .slide {position: absolute;}\nhtml>body div#header, html>body div#footer, \n html>body div#controls, html>body .slide {position: fixed;}\n.handout {display: none;}\n.layout {display: block;}\n.slide, .hideme, .incremental {visibility: hidden;}\n#slide0 {visibility: visible;}\n"--s5FramingCSS :: String-s5FramingCSS = "/* The following styles size, place, and layer the slide components.\n Edit these if you want to change the overall slide layout.\n The commented lines can be uncommented (and modified, if necessary) \n to help you with the rearrangement process. */\n\n/* target = 1024x768 */\n\ndiv#header, div#footer, .slide {width: 100%; top: 0; left: 0;}\ndiv#header {top: 0; height: 3em; z-index: 1;}\ndiv#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;}\n.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;}\ndiv#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}\ndiv#controls form {position: absolute; bottom: 0; right: 0; width: 100%;\n margin: 0;}\n#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;}\nhtml>body #currentSlide {position: fixed;}\n\n/*\ndiv#header {background: #FCC;}\ndiv#footer {background: #CCF;}\ndiv#controls {background: #BBD;}\ndiv#currentSlide {background: #FFC;}\n*/\n"--s5PrettyCSS :: String-s5PrettyCSS = "/* Following are the presentation styles -- edit away! */\n\nbody {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2em;}\n:link, :visited {text-decoration: none; color: #00C;}\n#controls :active {color: #88A !important;}\n#controls :focus {outline: 1px dotted #227;}\nh1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}\nul, pre {margin: 0; line-height: 1em;}\nhtml, body {margin: 0; padding: 0;}\n\nblockquote, q {font-style: italic;}\nblockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;}\nblockquote p {margin: 0;}\nblockquote i {font-style: normal;}\nblockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;}\nblockquote b i {font-style: italic;}\n\nkbd {font-weight: bold; font-size: 1em;}\nsup {font-size: smaller; line-height: 1px;}\n\n.slide code {padding: 2px 0.25em; font-weight: bold; color: #533;}\n.slide code.bad, code del {color: red;}\n.slide code.old {color: silver;}\n.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;}\n.slide pre code {display: block;}\n.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;}\n.slide li {margin-top: 0.75em; margin-right: 0;}\n.slide ul ul {line-height: 1;}\n.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;}\n.slide img.leader {display: block; margin: 0 auto;}\n\ndiv#header, div#footer {background: #005; color: #AAB;\n font-family: Verdana, Helvetica, sans-serif;}\ndiv#header {background: #005 url(bodybg.gif) -16px 0 no-repeat;\n line-height: 1px;}\ndiv#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;}\n#footer h1, #footer h2 {display: block; padding: 0 1em;}\n#footer h2 {font-style: italic;}\n\ndiv.long {font-size: 0.75em;}\n.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1;\n margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap;\n font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize;\n color: #DDE; background: #005;}\n.slide h3 {font-size: 130%;}\nh1 abbr {font-variant: small-caps;}\n\ndiv#controls {position: absolute; left: 50%; bottom: 0;\n width: 50%;\n text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;}\nhtml>body div#controls {position: fixed; padding: 0 0 1em 0;\n top: auto;}\ndiv#controls form {position: absolute; bottom: 0; right: 0; width: 100%;\n margin: 0; padding: 0;}\n#controls #navLinks a {padding: 0; margin: 0 0.5em; \n background: #005; border: none; color: #779; \n cursor: pointer;}\n#controls #navList {height: 1em;}\n#controls #navList #jumplist {position: absolute; bottom: 0; right: 0; background: #DDD; color: #227;}\n\n#currentSlide {text-align: center; font-size: 0.5em; color: #449;}\n\n#slide0 {padding-top: 3.5em; font-size: 90%;}\n#slide0 h1 {position: static; margin: 1em 0 0; padding: 0;\n font: bold 2em Helvetica, sans-serif; white-space: normal;\n color: #000; background: transparent;}\n#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;}\n#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}\n#slide0 h4 {margin-top: 0; font-size: 1em;}\n\nul.urls {list-style: none; display: inline; margin: 0;}\n.urls li {display: inline; margin: 0;}\n.note {display: none;}\n.external {border-bottom: 1px dotted gray;}\nhtml>body .external {border-bottom: none;}\n.external:after {content: \" \\274F\"; font-size: smaller; color: #77B;}\n\n.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;}\nimg.incremental {visibility: hidden;}\n.slide .current {color: #B02;}\n\n\n/* diagnostics\n\nli:after {content: \" [\" attr(class) \"]\"; color: #F88;}\n */"--s5OperaCSS :: String-s5OperaCSS = "/* DO NOT CHANGE THESE unless you really want to break Opera Show */\n.slide {\n\tvisibility: visible !important;\n\tposition: static !important;\n\tpage-break-before: always;\n}\n#slide0 {page-break-before: avoid;}\n"--s5OutlineCSS :: String-s5OutlineCSS = "/* don't change this unless you want the layout stuff to show up in the outline view! */\n\n.layout div, #footer *, #controlForm * {display: none;}\n#footer, #controls, #controlForm, #navLinks, #toggle {\n display: block; visibility: visible; margin: 0; padding: 0;}\n#toggle {float: right; padding: 0.5em;}\nhtml>body #toggle {position: fixed; top: 0; right: 0;}\n\n/* making the outline look pretty-ish */\n\n#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;}\n#slide0 h1 {padding-top: 1.5em;}\n.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em;\n border-top: 1px solid #888; border-bottom: 1px solid #AAA;}\n#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;}\n"--s5PrintCSS :: String-s5PrintCSS = "/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */\n.slide, ul {page-break-inside: avoid; visibility: visible !important;}\nh1 {page-break-after: avoid;}\n\nbody {font-size: 12pt; background: white;}\n* {color: black;}\n\n#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}\n#slide0 h3 {margin: 0; padding: 0;}\n#slide0 h4 {margin: 0 0 0.5em; padding: 0;}\n#slide0 {margin-bottom: 3em;}\n\nh1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}\n.extra {background: transparent !important;}\ndiv.extra, pre.extra, .example {font-size: 10pt; color: #333;}\nul.extra a {font-weight: bold;}\np.example {display: none;}\n\n#header {display: none;}\n#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}\n#footer h2, #controls {display: none;}\n\n/* The following rule keeps the layout stuff out of print. Remove at your own risk! */\n.layout, .layout * {display: none !important;}\n"--s5CSS :: String-s5CSS = "<style type=\"text/css\" media=\"projection\" id=\"slideProj\">\n" ++ s5CoreCSS ++ "\n" ++ s5FramingCSS ++ "\n" ++ s5PrettyCSS ++ "\n</style>\n<style type=\"text/css\" media=\"projection\" id=\"operaFix\">\n" ++ s5OperaCSS ++ "\n</style>\n<style type=\"text/css\" media=\"screen\" id=\"outlineStyle\">\n" ++ s5OutlineCSS ++ "\n</style>\n<style type=\"text/css\" media=\"print\" id=\"slidePrint\">\n" ++ s5PrintCSS ++ "\n</style>\n"--s5Links :: String-s5Links = "<!-- style sheet links -->\n<link rel=\"stylesheet\" href=\"ui/default/slides.css\" type=\"text/css\" media=\"projection\" id=\"slideProj\" />\n<link rel=\"stylesheet\" href=\"ui/default/outline.css\" type=\"text/css\" media=\"screen\" id=\"outlineStyle\" />\n<link rel=\"stylesheet\" href=\"ui/default/print.css\" type=\"text/css\" media=\"print\" id=\"slidePrint\" />\n<link rel=\"stylesheet\" href=\"ui/default/opera.css\" type=\"text/css\" media=\"projection\" id=\"operaFix\" />\n<!-- S5 JS -->\n<script src=\"ui/default/slides.js\" type=\"text/javascript\"></script>\n"---- | Converts Pandoc document to an S5 HTML presentation (Html structure).-writeS5 :: WriterOptions -> Pandoc -> Html-writeS5 options = (writeHtml options) . insertS5Structure---- | Converts Pandoc document to an S5 HTML presentation (string).-writeS5String :: WriterOptions -> Pandoc -> String-writeS5String options = (writeHtmlString options) . insertS5Structure---- | Inserts HTML needed for an S5 presentation (e.g. around slides).-layoutDiv :: [Inline] -- ^ Title of document (for header or footer)- -> String -- ^ Date of document (for header or footer)- -> [Block] -- ^ List of block elements returned-layoutDiv title date = [(RawHtml "<div class=\"layout\">\n<div id=\"controls\"></div>\n<div id=\"currentSlide\"></div>\n<div id=\"header\"></div>\n<div id=\"footer\">\n"), (Header 1 [Str date]), (Header 2 title), (RawHtml "</div>\n</div>\n")]--presentationStart = RawHtml "<div class=\"presentation\">\n\n"--presentationEnd = RawHtml "</div>\n"--slideStart = RawHtml "<div class=\"slide\">\n"--slideEnd = RawHtml "</div>\n"---- | Returns 'True' if block is a Header 1.-isH1 :: Block -> Bool-isH1 (Header 1 _) = True-isH1 _ = False ---- | Insert HTML around sections to make individual slides.-insertSlides :: Bool -> [Block] -> [Block]-insertSlides beginning blocks = - let (beforeHead, rest) = break isH1 blocks in- if (null rest) then - if beginning then- beforeHead - else- beforeHead ++ [slideEnd]- else- if beginning then- beforeHead ++ - slideStart:(head rest):(insertSlides False (tail rest))- else- beforeHead ++ - slideEnd:slideStart:(head rest):(insertSlides False (tail rest)) ---- | Insert blocks into 'Pandoc' for slide structure.-insertS5Structure :: Pandoc -> Pandoc-insertS5Structure (Pandoc meta []) = Pandoc meta []-insertS5Structure (Pandoc (Meta title authors date) blocks) = - let slides = insertSlides True blocks - firstSlide = if not (null title)- then [slideStart, (Header 1 title), - (Header 3 [Str (joinWithSep ", " authors)]),- (Header 4 [Str date]), slideEnd]- else []- newBlocks = (layoutDiv title date) ++ presentationStart:firstSlide ++- slides ++ [presentationEnd]- in Pandoc (Meta title authors date) newBlocks-
− src/headers/ConTeXtHeader
@@ -1,61 +0,0 @@-\enableregime[utf] % use UTF-8--\setupcolors[state=start]-\setupinteraction[state=start, color=middlered] % needed for hyperlinks--\setuppapersize[letter][letter] % use letter paper-\setuplayout[width=middle, backspace=1.5in, cutspace=1.5in,- height=middle, header=0.75in, footer=0.75in] % page layout-\setuppagenumbering[location={footer,center}] % number pages-\setupbodyfont[11pt] % 11pt font-\setupwhitespace[medium] % inter-paragraph spacing--\setuphead[section][style=\tfc]-\setuphead[subsection][style=\tfb]-\setuphead[subsubsection][style=\bf]--% define title block commands-\unprotect-\def\doctitle#1{\gdef\@title{#1}}-\def\author#1{\gdef\@author{#1}}-\def\date#1{\gdef\@date{#1}}-\date{\currentdate} % Default to today unless specified otherwise.-\def\maketitle{%- \startalignment[center]- \blank[2*big]- {\tfd \@title}- \blank[3*medium]- {\tfa \@author}- \blank[2*medium]- {\tfa \@date}- \blank[3*medium]- \stopalignment}-\protect--% define descr (for definition lists)-\definedescription[descr][- headstyle=bold,style=normal,align=left,location=hanging,- width=broad,margin=1cm]--% define ltxitem (for bulleted lists) -\defineitemgroup[ltxitem][levels=4]-\setupitemgroup[ltxitem][1][1]-\setupitemgroup[ltxitem][2][2]-\setupitemgroup[ltxitem][3][3]-\setupitemgroup[ltxitem][4][4,packed]--% define ltxenum (for enumerated lists)-\defineitemgroup[ltxenum][levels=4]-\setupitemgroup[ltxenum][1][n]-\setupitemgroup[ltxenum][2][a]-\setupitemgroup[ltxenum][3][r]-\setupitemgroup[ltxenum][4][A,packed]--\setupthinrules[width=15em] % width of horizontal rules--% for block quotations-\definestartstop [blockquote]- [before={\startnarrower\switchtobodyfont[11pt]- \whitespace\setupindenting[no]},- after={\stopnarrower\whitespace}]-
− src/headers/DocbookHeader
@@ -1,3 +0,0 @@-<?xml version="1.0" encoding="utf-8" ?>-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"- "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
− src/headers/LaTeXHeader
@@ -1,5 +0,0 @@-\documentclass{article}-\usepackage[mathletters]{ucs}-\usepackage[utf8x]{inputenc}-\setlength{\parindent}{0pt}-\setlength{\parskip}{6pt plus 2pt minus 1pt}
− src/headers/RTFHeader
@@ -1,4 +0,0 @@-{\rtf1\ansi\deff0{\fonttbl{\f0 \fswiss Helvetica;}{\f1 Courier;}}-{\colortbl;\red255\green0\blue0;\red0\green0\blue255;}-\widowctrl\hyphauto-
− src/headers/S5Header
@@ -1,3 +0,0 @@-<!-- configuration parameters -->-<meta name="defaultView" content="slideshow" />-<meta name="controlVis" content="hidden" />
− src/templates/ASCIIMathML.hs
@@ -1,7 +0,0 @@--- | Definitions for use of ASCIIMathML in HTML. --- (See <http://www1.chapman.edu/~jipsen/mathml/asciimath.html>.)-module Text.Pandoc.ASCIIMathML ( asciiMathMLScript ) where---- | String containing ASCIIMathML javascript.-asciiMathMLScript :: String-asciiMathMLScript = "<script type=\"text/javascript\">\n@ASCIIMathML.js@</script>\n"
− src/templates/DefaultHeaders.hs
@@ -1,52 +0,0 @@-{--Copyright (C) 2006-7 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.DefaultHeaders- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Default headers for Pandoc writers.--}-module Text.Pandoc.Writers.DefaultHeaders (- defaultLaTeXHeader,- defaultConTeXtHeader,- defaultDocbookHeader,- defaultS5Header,- defaultRTFHeader- ) where-import Text.Pandoc.Writers.S5--defaultLaTeXHeader :: String-defaultLaTeXHeader = "@LaTeXHeader@"--defaultConTeXtHeader :: String-defaultConTeXtHeader = "@ConTeXtHeader@"--defaultDocbookHeader :: String-defaultDocbookHeader = "@DocbookHeader@"--defaultS5Header :: String-defaultS5Header = s5Meta ++ s5CSS ++ s5Javascript--defaultRTFHeader :: String-defaultRTFHeader = "@RTFHeader@"
− src/templates/Makefile
@@ -1,20 +0,0 @@-VPATH := ..-PROCESSOR := ./fillTemplates.pl-TARGETS := Text/Pandoc/ASCIIMathML.hs \- Text/Pandoc/Writers/S5.hs \- Text/Pandoc/Writers/DefaultHeaders.hs--all: $(TARGETS)--Text/Pandoc/ASCIIMathML.hs: ASCIIMathML.hs $(PROCESSOR) $(VPATH)/ASCIIMathML.js- perl $(PROCESSOR) $@ $(VPATH)--Text/Pandoc/Writers/S5.hs: S5.hs $(PROCESSOR) $(VPATH)/ui/default/*- perl $(PROCESSOR) $@ $(VPATH)--Text/Pandoc/Writers/DefaultHeaders.hs: DefaultHeaders.hs $(PROCESSOR) $(VPATH)/headers/*- perl $(PROCESSOR) $@ $(VPATH)--.PHONY: clean-clean:- cd $(VPATH); rm -f $(TARGETS)
− src/templates/S5.hs
@@ -1,133 +0,0 @@-{--Copyright (C) 2006-7 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.S5- Copyright : Copyright (C) 2006-7 John MacFarlane- License : GNU GPL, version 2 or above -- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Definitions for creation of S5 powerpoint-like HTML.-(See <http://meyerweb.com/eric/tools/s5/>.)--}-module Text.Pandoc.Writers.S5 (- -- * Strings- s5Meta,- s5Javascript,- s5CSS,- s5Links,- -- * Functions- writeS5,- writeS5String,- insertS5Structure- ) where-import Text.Pandoc.Shared ( joinWithSep, WriterOptions )-import Text.Pandoc.Writers.HTML ( writeHtml, writeHtmlString )-import Text.Pandoc.Definition-import Text.XHtml.Strict--s5Meta :: String-s5Meta = "<!-- configuration parameters -->\n<meta name=\"defaultView\" content=\"slideshow\" />\n<meta name=\"controlVis\" content=\"hidden\" />\n"--s5Javascript :: String-s5Javascript = "<script type=\"text/javascript\">\n@slides.js@</script>\n" --s5CoreCSS :: String-s5CoreCSS = "@s5-core.css@"--s5FramingCSS :: String-s5FramingCSS = "@framing.css@"--s5PrettyCSS :: String-s5PrettyCSS = "@pretty.css@"--s5OperaCSS :: String-s5OperaCSS = "@opera.css@"--s5OutlineCSS :: String-s5OutlineCSS = "@outline.css@"--s5PrintCSS :: String-s5PrintCSS = "@print.css@"--s5CSS :: String-s5CSS = "<style type=\"text/css\" media=\"projection\" id=\"slideProj\">\n" ++ s5CoreCSS ++ "\n" ++ s5FramingCSS ++ "\n" ++ s5PrettyCSS ++ "\n</style>\n<style type=\"text/css\" media=\"projection\" id=\"operaFix\">\n" ++ s5OperaCSS ++ "\n</style>\n<style type=\"text/css\" media=\"screen\" id=\"outlineStyle\">\n" ++ s5OutlineCSS ++ "\n</style>\n<style type=\"text/css\" media=\"print\" id=\"slidePrint\">\n" ++ s5PrintCSS ++ "\n</style>\n"--s5Links :: String-s5Links = "<!-- style sheet links -->\n<link rel=\"stylesheet\" href=\"ui/default/slides.css\" type=\"text/css\" media=\"projection\" id=\"slideProj\" />\n<link rel=\"stylesheet\" href=\"ui/default/outline.css\" type=\"text/css\" media=\"screen\" id=\"outlineStyle\" />\n<link rel=\"stylesheet\" href=\"ui/default/print.css\" type=\"text/css\" media=\"print\" id=\"slidePrint\" />\n<link rel=\"stylesheet\" href=\"ui/default/opera.css\" type=\"text/css\" media=\"projection\" id=\"operaFix\" />\n<!-- S5 JS -->\n<script src=\"ui/default/slides.js\" type=\"text/javascript\"></script>\n"---- | Converts Pandoc document to an S5 HTML presentation (Html structure).-writeS5 :: WriterOptions -> Pandoc -> Html-writeS5 options = (writeHtml options) . insertS5Structure---- | Converts Pandoc document to an S5 HTML presentation (string).-writeS5String :: WriterOptions -> Pandoc -> String-writeS5String options = (writeHtmlString options) . insertS5Structure---- | Inserts HTML needed for an S5 presentation (e.g. around slides).-layoutDiv :: [Inline] -- ^ Title of document (for header or footer)- -> String -- ^ Date of document (for header or footer)- -> [Block] -- ^ List of block elements returned-layoutDiv title date = [(RawHtml "<div class=\"layout\">\n<div id=\"controls\"></div>\n<div id=\"currentSlide\"></div>\n<div id=\"header\"></div>\n<div id=\"footer\">\n"), (Header 1 [Str date]), (Header 2 title), (RawHtml "</div>\n</div>\n")]--presentationStart = RawHtml "<div class=\"presentation\">\n\n"--presentationEnd = RawHtml "</div>\n"--slideStart = RawHtml "<div class=\"slide\">\n"--slideEnd = RawHtml "</div>\n"---- | Returns 'True' if block is a Header 1.-isH1 :: Block -> Bool-isH1 (Header 1 _) = True-isH1 _ = False ---- | Insert HTML around sections to make individual slides.-insertSlides :: Bool -> [Block] -> [Block]-insertSlides beginning blocks = - let (beforeHead, rest) = break isH1 blocks in- if (null rest) then - if beginning then- beforeHead - else- beforeHead ++ [slideEnd]- else- if beginning then- beforeHead ++ - slideStart:(head rest):(insertSlides False (tail rest))- else- beforeHead ++ - slideEnd:slideStart:(head rest):(insertSlides False (tail rest)) ---- | Insert blocks into 'Pandoc' for slide structure.-insertS5Structure :: Pandoc -> Pandoc-insertS5Structure (Pandoc meta []) = Pandoc meta []-insertS5Structure (Pandoc (Meta title authors date) blocks) = - let slides = insertSlides True blocks - firstSlide = if not (null title)- then [slideStart, (Header 1 title), - (Header 3 [Str (joinWithSep ", " authors)]),- (Header 4 [Str date]), slideEnd]- else []- newBlocks = (layoutDiv title date) ++ presentationStart:firstSlide ++- slides ++ [presentationEnd]- in Pandoc (Meta title authors date) newBlocks
− src/templates/fillTemplates.pl
@@ -1,131 +0,0 @@-#!/usr/bin/env perl-# Fills templates with haskell-escaped strings slurped from input files.-# Takes two arguments, the first specifying the pathname of the target-# relative to the root directory, the second specifying the root directory-# (defaulting to ..). The template is assumed to have the same base name-# as the target and to reside in the templates subdirectory of the root-# directory.--use strict;-use warnings;--# Utility routines:--sub slurp {- open FILE, $_[0] or die "couldn't open file '$_[0]': $!";- my $contents = do { local $/; <FILE>;};- close FILE;- return $contents;-}--sub escape_for_haskell {- my ($contents) = @_;-- $contents =~ s/\\/\\\\/g;- $contents =~ s/\t/\\t/g;- $contents =~ s/"/\\"/g;- $contents =~ s/\n/\\n/g;- return $contents;-}--# Template processors.--my %processor = (- # --------------------------------------------------------------------------- 'Text/Pandoc/Writers/S5.hs' => {- # --------------------------------------------------------------------------- proc => sub {- my ($template) = @_;-- my (@files) = qw(slides.js s5-core.css framing.css pretty.css - opera.css outline.css print.css);-- foreach my $file (@files) {- my $replacement = escape_for_haskell(slurp "ui/default/$file");- my $escapedfile = $file;- $escapedfile =~ s/\./\\./g;- $template =~ s/\@$escapedfile\@/$replacement/;- } - return $template;- },- },- # --------------------------------------------------------------------------- 'Text/Pandoc/ASCIIMathML.hs' => {- # --------------------------------------------------------------------------- proc => sub {- my ($template) = @_;-- my $script = escape_for_haskell(slurp "ASCIIMathML.js"); - my $acknowledgements =- " ASCIIMathML.js - copyright Peter Jipsen,".- " released under the GPL\\nSee ".- "http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ ";- $script =~ s/\/\*.*?\*\//\/\*$acknowledgements\*\//g; # strip comments- $template =~ s/\@ASCIIMathML\.js@/$script/;-- return $template;- },- },- # --------------------------------------------------------------------------- 'Text/Pandoc/Writers/DefaultHeaders.hs' => {- # --------------------------------------------------------------------------- proc => sub {- my ($template) = @_;-- my (@headers) = split(/\s/,`ls headers`);- foreach my $header (@headers) {- my ($replacement) = escape_for_haskell(slurp "headers/$header");- $template =~ s/\@$header\@/$replacement/;- }- - return $template;- },- },- # --------------------------------------------------------------------------- # 'foo/bar/baz' => {- # --------------------------------------------------------------------------- # template => 'optional-template-filename-defaults-to-baz'- # proc => sub {- # my ($template) = @_;- # # Process.- # return $template;- # },- #},-);--# Main.--my $target = shift @ARGV;-if (!defined $target || !length $target) {- print STDERR "Available targets:\n\n" . join "\n", keys %processor;- die "\n\nYou must supply a target!\n";-}--die "No processor exists for '$target'!\n" if ! exists $processor{$target};--my $rootdir = shift @ARGV || '..';-chdir $rootdir or die "Couldn't chdir to '$rootdir': $!";--my $template;-if (exists $processor{$target}->{template}) {- $template = $processor{$target}->{template};-}-else {- ($template = $target) =~ s!.*/+!!;-}-$template = "templates/$template";-die "No template exists for '$target'!\n" if ! -f "$template";--open OUTFILE, ">$target" or die "couldn't open file '$target': $!";-print OUTFILE <<END;-------------------------------------------------------- Do not edit this file by hand. Edit --- '$template'--- and run $0 $target-------------------------------------------------------END--print OUTFILE $processor{$target}->{proc}->(slurp($template));-print OUTFILE "\n";-close OUTFILE;
− src/ui/default/blank.gif
binary file changed (49 → absent bytes)
− src/ui/default/bodybg.gif
binary file changed (10119 → absent bytes)
− src/ui/default/framing.css
@@ -1,23 +0,0 @@-/* The following styles size, place, and layer the slide components.- Edit these if you want to change the overall slide layout.- The commented lines can be uncommented (and modified, if necessary) - to help you with the rearrangement process. */--/* target = 1024x768 */--div#header, div#footer, .slide {width: 100%; top: 0; left: 0;}-div#header {top: 0; height: 3em; z-index: 1;}-div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;}-.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;}-div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}-div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;- margin: 0;}-#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;}-html>body #currentSlide {position: fixed;}--/*-div#header {background: #FCC;}-div#footer {background: #CCF;}-div#controls {background: #BBD;}-div#currentSlide {background: #FFC;}-*/
− src/ui/default/iepngfix.htc
@@ -1,42 +0,0 @@-<public:component> -<public:attach event="onpropertychange" onevent="doFix()" /> - -<script> - -// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com -// Free usage permitted as long as this notice remains intact. - -// This must be a path to a blank image. That's all the configuration you need here. -var blankImg = 'ui/default/blank.gif'; - -var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; - -function filt(s, m) { - if (filters[f]) { - filters[f].enabled = s ? true : false; - if (s) with (filters[f]) { src = s; sizingMethod = m } - } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; -} - -function doFix() { - if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || - (event && !/(background|src)/.test(event.propertyName))) return; - - if (tagName == 'IMG') { - if ((/\.png$/i).test(src)) { - filt(src, 'image'); // was 'scale' - src = blankImg; - } else if (src.indexOf(blankImg) < 0) filt(); - } else if (style.backgroundImage) { - if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { - var s = RegExp.$1; - style.backgroundImage = ''; - filt(s, 'crop'); - } else filt(); - } -} - -doFix(); - -</script> -</public:component>
− src/ui/default/opera.css
@@ -1,7 +0,0 @@-/* DO NOT CHANGE THESE unless you really want to break Opera Show */-.slide {- visibility: visible !important;- position: static !important;- page-break-before: always;-}-#slide0 {page-break-before: avoid;}
− src/ui/default/outline.css
@@ -1,15 +0,0 @@-/* don't change this unless you want the layout stuff to show up in the outline view! */--.layout div, #footer *, #controlForm * {display: none;}-#footer, #controls, #controlForm, #navLinks, #toggle {- display: block; visibility: visible; margin: 0; padding: 0;}-#toggle {float: right; padding: 0.5em;}-html>body #toggle {position: fixed; top: 0; right: 0;}--/* making the outline look pretty-ish */--#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;}-#slide0 h1 {padding-top: 1.5em;}-.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em;- border-top: 1px solid #888; border-bottom: 1px solid #AAA;}-#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;}
− src/ui/default/pretty.css
@@ -1,86 +0,0 @@-/* Following are the presentation styles -- edit away! */--body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2em;}-:link, :visited {text-decoration: none; color: #00C;}-#controls :active {color: #88A !important;}-#controls :focus {outline: 1px dotted #227;}-h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}-ul, pre {margin: 0; line-height: 1em;}-html, body {margin: 0; padding: 0;}--blockquote, q {font-style: italic;}-blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;}-blockquote p {margin: 0;}-blockquote i {font-style: normal;}-blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;}-blockquote b i {font-style: italic;}--kbd {font-weight: bold; font-size: 1em;}-sup {font-size: smaller; line-height: 1px;}--.slide code {padding: 2px 0.25em; font-weight: bold; color: #533;}-.slide code.bad, code del {color: red;}-.slide code.old {color: silver;}-.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;}-.slide pre code {display: block;}-.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;}-.slide li {margin-top: 0.75em; margin-right: 0;}-.slide ul ul {line-height: 1;}-.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;}-.slide img.leader {display: block; margin: 0 auto;}--div#header, div#footer {background: #005; color: #AAB;- font-family: Verdana, Helvetica, sans-serif;}-div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat;- line-height: 1px;}-div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;}-#footer h1, #footer h2 {display: block; padding: 0 1em;}-#footer h2 {font-style: italic;}--div.long {font-size: 0.75em;}-.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1;- margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap;- font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize;- color: #DDE; background: #005;}-.slide h3 {font-size: 130%;}-h1 abbr {font-variant: small-caps;}--div#controls {position: absolute; left: 50%; bottom: 0;- width: 50%;- text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;}-html>body div#controls {position: fixed; padding: 0 0 1em 0;- top: auto;}-div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;- margin: 0; padding: 0;}-#controls #navLinks a {padding: 0; margin: 0 0.5em; - background: #005; border: none; color: #779; - cursor: pointer;}-#controls #navList {height: 1em;}-#controls #navList #jumplist {position: absolute; bottom: 0; right: 0; background: #DDD; color: #227;}--#currentSlide {text-align: center; font-size: 0.5em; color: #449;}--#slide0 {padding-top: 3.5em; font-size: 90%;}-#slide0 h1 {position: static; margin: 1em 0 0; padding: 0;- font: bold 2em Helvetica, sans-serif; white-space: normal;- color: #000; background: transparent;}-#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;}-#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}-#slide0 h4 {margin-top: 0; font-size: 1em;}--ul.urls {list-style: none; display: inline; margin: 0;}-.urls li {display: inline; margin: 0;}-.note {display: none;}-.external {border-bottom: 1px dotted gray;}-html>body .external {border-bottom: none;}-.external:after {content: " \274F"; font-size: smaller; color: #77B;}--.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;}-img.incremental {visibility: hidden;}-.slide .current {color: #B02;}---/* diagnostics--li:after {content: " [" attr(class) "]"; color: #F88;}- */
− src/ui/default/print.css
@@ -1,24 +0,0 @@-/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */-.slide, ul {page-break-inside: avoid; visibility: visible !important;}-h1 {page-break-after: avoid;}--body {font-size: 12pt; background: white;}-* {color: black;}--#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}-#slide0 h3 {margin: 0; padding: 0;}-#slide0 h4 {margin: 0 0 0.5em; padding: 0;}-#slide0 {margin-bottom: 3em;}--h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}-.extra {background: transparent !important;}-div.extra, pre.extra, .example {font-size: 10pt; color: #333;}-ul.extra a {font-weight: bold;}-p.example {display: none;}--#header {display: none;}-#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}-#footer h2, #controls {display: none;}--/* The following rule keeps the layout stuff out of print. Remove at your own risk! */-.layout, .layout * {display: none !important;}
− src/ui/default/s5-core.css
@@ -1,9 +0,0 @@-/* Do not edit or override these styles! The system will likely break if you do. */--div#header, div#footer, div#controls, .slide {position: absolute;}-html>body div#header, html>body div#footer, - html>body div#controls, html>body .slide {position: fixed;}-.handout {display: none;}-.layout {display: block;}-.slide, .hideme, .incremental {visibility: hidden;}-#slide0 {visibility: visible;}
− src/ui/default/slides.css
@@ -1,3 +0,0 @@-@import url(s5-core.css); /* required to make the slide show run at all */-@import url(framing.css); /* sets basic placement and size of slide components */-@import url(pretty.css); /* stuff that makes the slides look better than blah */
− src/ui/default/slides.js
@@ -1,553 +0,0 @@-// S5 v1.1 slides.js -- released into the Public Domain-//-// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information -// about all the wonderful and talented contributors to this code!--var undef;-var slideCSS = '';-var snum = 0;-var smax = 1;-var incpos = 0;-var number = undef;-var s5mode = true;-var defaultView = 'slideshow';-var controlVis = 'visible';--var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0;-var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0;-var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0;--function hasClass(object, className) {- if (!object.className) return false;- return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1);-}--function hasValue(object, value) {- if (!object) return false;- return (object.search('(^|\\s)' + value + '(\\s|$)') != -1);-}--function removeClass(object,className) {- if (!object) return;- object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2);-}--function addClass(object,className) {- if (!object || hasClass(object, className)) return;- if (object.className) {- object.className += ' '+className;- } else {- object.className = className;- }-}--function GetElementsWithClassName(elementName,className) {- var allElements = document.getElementsByTagName(elementName);- var elemColl = new Array();- for (var i = 0; i< allElements.length; i++) {- if (hasClass(allElements[i], className)) {- elemColl[elemColl.length] = allElements[i];- }- }- return elemColl;-}--function isParentOrSelf(element, id) {- if (element == null || element.nodeName=='BODY') return false;- else if (element.id == id) return true;- else return isParentOrSelf(element.parentNode, id);-}--function nodeValue(node) {- var result = "";- if (node.nodeType == 1) {- var children = node.childNodes;- for (var i = 0; i < children.length; ++i) {- result += nodeValue(children[i]);- } - }- else if (node.nodeType == 3) {- result = node.nodeValue;- }- return(result);-}--function slideLabel() {- var slideColl = GetElementsWithClassName('*','slide');- var list = document.getElementById('jumplist');- smax = slideColl.length;- for (var n = 0; n < smax; n++) {- var obj = slideColl[n];-- var did = 'slide' + n.toString();- obj.setAttribute('id',did);- if (isOp) continue;-- var otext = '';- var menu = obj.firstChild;- if (!menu) continue; // to cope with empty slides- while (menu && menu.nodeType == 3) {- menu = menu.nextSibling;- }- if (!menu) continue; // to cope with slides with only text nodes-- var menunodes = menu.childNodes;- for (var o = 0; o < menunodes.length; o++) {- otext += nodeValue(menunodes[o]);- }- list.options[list.length] = new Option(n + ' : ' + otext, n);- }-}--function currentSlide() {- var cs;- if (document.getElementById) {- cs = document.getElementById('currentSlide');- } else {- cs = document.currentSlide;- }- cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' + - '<span id="csSep">\/<\/span> ' + - '<span id="csTotal">' + (smax-1) + '<\/span>';- if (snum == 0) {- cs.style.visibility = 'hidden';- } else {- cs.style.visibility = 'visible';- }-}--function go(step) {- if (document.getElementById('slideProj').disabled || step == 0) return;- var jl = document.getElementById('jumplist');- var cid = 'slide' + snum;- var ce = document.getElementById(cid);- if (incrementals[snum].length > 0) {- for (var i = 0; i < incrementals[snum].length; i++) {- removeClass(incrementals[snum][i], 'current');- removeClass(incrementals[snum][i], 'incremental');- }- }- if (step != 'j') {- snum += step;- lmax = smax - 1;- if (snum > lmax) snum = lmax;- if (snum < 0) snum = 0;- } else- snum = parseInt(jl.value);- var nid = 'slide' + snum;- var ne = document.getElementById(nid);- if (!ne) {- ne = document.getElementById('slide0');- snum = 0;- }- if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;}- if (incrementals[snum].length > 0 && incpos == 0) {- for (var i = 0; i < incrementals[snum].length; i++) {- if (hasClass(incrementals[snum][i], 'current'))- incpos = i + 1;- else- addClass(incrementals[snum][i], 'incremental');- }- }- if (incrementals[snum].length > 0 && incpos > 0)- addClass(incrementals[snum][incpos - 1], 'current');- ce.style.visibility = 'hidden';- ne.style.visibility = 'visible';- jl.selectedIndex = snum;- currentSlide();- number = 0;-}--function goTo(target) {- if (target >= smax || target == snum) return;- go(target - snum);-}--function subgo(step) {- if (step > 0) {- removeClass(incrementals[snum][incpos - 1],'current');- removeClass(incrementals[snum][incpos], 'incremental');- addClass(incrementals[snum][incpos],'current');- incpos++;- } else {- incpos--;- removeClass(incrementals[snum][incpos],'current');- addClass(incrementals[snum][incpos], 'incremental');- addClass(incrementals[snum][incpos - 1],'current');- }-}--function toggle() {- var slideColl = GetElementsWithClassName('*','slide');- var slides = document.getElementById('slideProj');- var outline = document.getElementById('outlineStyle');- if (!slides.disabled) {- slides.disabled = true;- outline.disabled = false;- s5mode = false;- fontSize('1em');- for (var n = 0; n < smax; n++) {- var slide = slideColl[n];- slide.style.visibility = 'visible';- }- } else {- slides.disabled = false;- outline.disabled = true;- s5mode = true;- fontScale();- for (var n = 0; n < smax; n++) {- var slide = slideColl[n];- slide.style.visibility = 'hidden';- }- slideColl[snum].style.visibility = 'visible';- }-}--function showHide(action) {- var obj = GetElementsWithClassName('*','hideme')[0];- switch (action) {- case 's': obj.style.visibility = 'visible'; break;- case 'h': obj.style.visibility = 'hidden'; break;- case 'k':- if (obj.style.visibility != 'visible') {- obj.style.visibility = 'visible';- } else {- obj.style.visibility = 'hidden';- }- break;- }-}--// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/)-function keys(key) {- if (!key) {- key = event;- key.which = key.keyCode;- }- if (key.which == 84) {- toggle();- return;- }- if (s5mode) {- switch (key.which) {- case 10: // return- case 13: // enter- if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;- if (key.target && isParentOrSelf(key.target, 'controls')) return;- if(number != undef) {- goTo(number);- break;- }- case 32: // spacebar- case 34: // page down- case 39: // rightkey- case 40: // downkey- if(number != undef) {- go(number);- } else if (!incrementals[snum] || incpos >= incrementals[snum].length) {- go(1);- } else {- subgo(1);- }- break;- case 33: // page up- case 37: // leftkey- case 38: // upkey- if(number != undef) {- go(-1 * number);- } else if (!incrementals[snum] || incpos <= 0) {- go(-1);- } else {- subgo(-1);- }- break;- case 36: // home- goTo(0);- break;- case 35: // end- goTo(smax-1);- break;- case 67: // c- showHide('k');- break;- }- if (key.which < 48 || key.which > 57) {- number = undef;- } else {- if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;- if (key.target && isParentOrSelf(key.target, 'controls')) return;- number = (((number != undef) ? number : 0) * 10) + (key.which - 48);- }- }- return false;-}--function clicker(e) {- number = undef;- var target;- if (window.event) {- target = window.event.srcElement;- e = window.event;- } else target = e.target;- if (target.getAttribute('href') != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true;- if (!e.which || e.which == 1) {- if (!incrementals[snum] || incpos >= incrementals[snum].length) {- go(1);- } else {- subgo(1);- }- }-}--function findSlide(hash) {- var target = null;- var slides = GetElementsWithClassName('*','slide');- for (var i = 0; i < slides.length; i++) {- var targetSlide = slides[i];- if ( (targetSlide.name && targetSlide.name == hash)- || (targetSlide.id && targetSlide.id == hash) ) {- target = targetSlide;- break;- }- }- while(target != null && target.nodeName != 'BODY') {- if (hasClass(target, 'slide')) {- return parseInt(target.id.slice(5));- }- target = target.parentNode;- }- return null;-}--function slideJump() {- if (window.location.hash == null) return;- var sregex = /^#slide(\d+)$/;- var matches = sregex.exec(window.location.hash);- var dest = null;- if (matches != null) {- dest = parseInt(matches[1]);- } else {- dest = findSlide(window.location.hash.slice(1));- }- if (dest != null)- go(dest - snum);-}--function fixLinks() {- var thisUri = window.location.href;- thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length);- var aelements = document.getElementsByTagName('A');- for (var i = 0; i < aelements.length; i++) {- var a = aelements[i].href;- var slideID = a.match('\#slide[0-9]{1,2}');- if ((slideID) && (slideID[0].slice(0,1) == '#')) {- var dest = findSlide(slideID[0].slice(1));- if (dest != null) {- if (aelements[i].addEventListener) {- aelements[i].addEventListener("click", new Function("e",- "if (document.getElementById('slideProj').disabled) return;" +- "go("+dest+" - snum); " +- "if (e.preventDefault) e.preventDefault();"), true);- } else if (aelements[i].attachEvent) {- aelements[i].attachEvent("onclick", new Function("",- "if (document.getElementById('slideProj').disabled) return;" +- "go("+dest+" - snum); " +- "event.returnValue = false;"));- }- }- }- }-}--function externalLinks() {- if (!document.getElementsByTagName) return;- var anchors = document.getElementsByTagName('a');- for (var i=0; i<anchors.length; i++) {- var anchor = anchors[i];- if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) {- anchor.target = '_blank';- addClass(anchor,'external');- }- }-}--function createControls() {- var controlsDiv = document.getElementById("controls");- if (!controlsDiv) return;- var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"';- var hideDiv, hideList = '';- if (controlVis == 'hidden') {- hideDiv = hider;- } else {- hideList = hider;- }- controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' +- '<div id="navLinks">' +- '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' +- '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' +- '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' +- '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' +- '<\/div><\/form>';- if (controlVis == 'hidden') {- var hidden = document.getElementById('navLinks');- } else {- var hidden = document.getElementById('jumplist');- }- addClass(hidden,'hideme');-}--function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers- if (!s5mode) return false;- var vScale = 22; // both yield 32 (after rounding) at 1024x768- var hScale = 32; // perhaps should auto-calculate based on theme's declared value?- if (window.innerHeight) {- var vSize = window.innerHeight;- var hSize = window.innerWidth;- } else if (document.documentElement.clientHeight) {- var vSize = document.documentElement.clientHeight;- var hSize = document.documentElement.clientWidth;- } else if (document.body.clientHeight) {- var vSize = document.body.clientHeight;- var hSize = document.body.clientWidth;- } else {- var vSize = 700; // assuming 1024x768, minus chrome and such- var hSize = 1024; // these do not account for kiosk mode or Opera Show- }- var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale));- fontSize(newSize + 'px');- if (isGe) { // hack to counter incremental reflow bugs- var obj = document.getElementsByTagName('body')[0];- obj.style.display = 'none';- obj.style.display = 'block';- }-}--function fontSize(value) {- if (!(s5ss = document.getElementById('s5ss'))) {- if (!isIE) {- document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style'));- s5ss.setAttribute('media','screen, projection');- s5ss.setAttribute('id','s5ss');- } else {- document.createStyleSheet();- document.s5ss = document.styleSheets[document.styleSheets.length - 1];- }- }- if (!isIE) {- while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild);- s5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}'));- } else {- document.s5ss.addRule('body','font-size: ' + value + ' !important;');- }-}--function notOperaFix() {- slideCSS = document.getElementById('slideProj').href;- var slides = document.getElementById('slideProj');- var outline = document.getElementById('outlineStyle');- slides.setAttribute('media','screen');- outline.disabled = true;- if (isGe) {- slides.setAttribute('href','null'); // Gecko fix- slides.setAttribute('href',slideCSS); // Gecko fix- }- if (isIE && document.styleSheets && document.styleSheets[0]) {- document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)');- document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)');- document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)');- }-}--function getIncrementals(obj) {- var incrementals = new Array();- if (!obj) - return incrementals;- var children = obj.childNodes;- for (var i = 0; i < children.length; i++) {- var child = children[i];- if (hasClass(child, 'incremental')) {- if (child.nodeName == 'OL' || child.nodeName == 'UL') {- removeClass(child, 'incremental');- for (var j = 0; j < child.childNodes.length; j++) {- if (child.childNodes[j].nodeType == 1) {- addClass(child.childNodes[j], 'incremental');- }- }- } else {- incrementals[incrementals.length] = child;- removeClass(child,'incremental');- }- }- if (hasClass(child, 'show-first')) {- if (child.nodeName == 'OL' || child.nodeName == 'UL') {- removeClass(child, 'show-first');- if (child.childNodes[isGe].nodeType == 1) {- removeClass(child.childNodes[isGe], 'incremental');- }- } else {- incrementals[incrementals.length] = child;- }- }- incrementals = incrementals.concat(getIncrementals(child));- }- return incrementals;-}--function createIncrementals() {- var incrementals = new Array();- for (var i = 0; i < smax; i++) {- incrementals[i] = getIncrementals(document.getElementById('slide'+i));- }- return incrementals;-}--function defaultCheck() {- var allMetas = document.getElementsByTagName('meta');- for (var i = 0; i< allMetas.length; i++) {- if (allMetas[i].name == 'defaultView') {- defaultView = allMetas[i].content;- }- if (allMetas[i].name == 'controlVis') {- controlVis = allMetas[i].content;- }- }-}--// Key trap fix, new function body for trap()-function trap(e) {- if (!e) {- e = event;- e.which = e.keyCode;- }- try {- modifierKey = e.ctrlKey || e.altKey || e.metaKey;- }- catch(e) {- modifierKey = false;- }- return modifierKey || e.which == 0;-}--function startup() {- defaultCheck();- if (!isOp) - createControls();- slideLabel();- fixLinks();- externalLinks();- fontScale();- if (!isOp) {- notOperaFix();- incrementals = createIncrementals();- slideJump();- if (defaultView == 'outline') {- toggle();- }- document.onkeyup = keys;- document.onkeypress = trap;- document.onclick = clicker;- }-}--window.onload = startup;-window.onresize = function(){setTimeout('fontScale()', 50);}
− src/wrappers/common.sh
@@ -1,43 +0,0 @@-THIS=${0##*/}--NEWLINE='-'--err () { echo "$*" | fold -s -w ${COLUMNS:-110} >&2; }-errn () { printf "$*" | fold -s -w ${COLUMNS:-110} >&2; }--usage () {- err "$1 - $2" # short description- err "See the $1(1) man page for usage."-}--# Portable which(1).-pathfind () {- oldifs="$IFS"; IFS=':'- for _p in $PATH; do- if [ -x "$_p/$*" ] && [ -f "$_p/$*" ]; then- IFS="$oldifs"- return 0- fi- done- IFS="$oldifs"- return 1-}--for p in pandoc $REQUIRED; do- pathfind $p || {- err "You need '$p' to use this program!"- exit 1- }-done--CONF=$(pandoc --dump-args "$@" 2>&1) || {- errcode=$?- echo "$CONF" | sed -e '/^pandoc \[OPTIONS\] \[FILES\]/,$d' >&2- [ $errcode -eq 2 ] && usage "$THIS" "$SYNOPSIS"- exit $errcode-}--OUTPUT=$(echo "$CONF" | sed -ne '1p')-ARGS=$(echo "$CONF" | sed -e '1d')-
− src/wrappers/hsmarkdown.in
@@ -1,5 +0,0 @@-#!/bin/sh-# hsmarkdown - intended as a drop-in replacement for Markdown.pl.-# Uses pandoc to convert from markdown to HTML, using --strict mode-# for maximum compatibility with official markdown syntax.-exec pandoc --from markdown --to html --strict -- "$@"
− src/wrappers/html2markdown.in
@@ -1,157 +0,0 @@-#!/bin/sh -e-# converts HTML from a URL, file, or stdin to markdown-# uses an available program to fetch URL and tidy to normalize it first--REQUIRED="tidy"-SYNOPSIS="converts HTML from a URL, file, or STDIN to markdown-formatted text."--### common.sh--grab_url_with () {- url="${1:?internal error: grab_url_with: url required}"-- shift- cmdline="$@"-- prog=- prog_opts=- if [ -n "$cmdline" ]; then- eval "set -- $cmdline"- prog=$1- shift- prog_opts="$@"- fi-- if [ -z "$prog" ]; then- # Locate a sensible web grabber (note the order).- for p in wget lynx w3m curl links w3c; do- if pathfind $p; then- prog=$p- break- fi- done-- [ -n "$prog" ] || {- errn "$THIS: Couldn't find a program to fetch the file from URL "- err "(e.g. wget, w3m, lynx, w3c, or curl)."- return 1- }- else- pathfind "$prog" || {- err "$THIS: No such web grabber '$prog' found; aborting."- return 1- }- fi-- # Setup proper base options for known grabbers.- base_opts=- case "$prog" in- wget) base_opts="-O-" ;;- lynx) base_opts="-source" ;;- w3m) base_opts="-dump_source" ;;- curl) base_opts="" ;;- links) base_opts="-source" ;;- w3c) base_opts="-n -get" ;;- *) err "$THIS: unhandled web grabber '$prog'; hope it succeeds."- esac-- err "$THIS: invoking '$prog $base_opts $prog_opts $url'..."- eval "set -- $base_opts $prog_opts"- $prog "$@" "$url"-}--# Parse command-line arguments-parse_arguments () {- while [ $# -gt 0 ]; do- case "$1" in- --encoding=*)- wholeopt="$1"- # extract encoding from after =- encoding="${wholeopt#*=}" ;;- -e|--encoding|-encoding)- shift- encoding="$1" ;; - --grabber=*)- wholeopt="$1"- # extract encoding from after =- grabber="\"${wholeopt#*=}\"" ;;- -g|--grabber|-grabber)- shift- grabber="$1" ;; - *)- if [ -z "$argument" ]; then- argument="$1"- else- err "Warning: extra argument '$1' will be ignored."- fi ;;- esac- shift- done-}--argument=-encoding=-grabber=--oldifs="$IFS"-IFS=$NEWLINE-parse_arguments $ARGS-IFS="$oldifs"--inurl=-if [ -n "$argument" ] && ! [ -f "$argument" ]; then- # Treat given argument as an URL.- inurl="$argument"-fi--if [ -n "$inurl" ]; then- err "Attempting to fetch file from '$inurl'..."-- ### tempdir.sh-- grabber_out=$THIS_TEMPDIR/grabber.out- grabber_log=$THIS_TEMPDIR/grabber.log- if ! grab_url_with "$inurl" "$grabber" 1>$grabber_out 2>$grabber_log; then- errn "grab_url_with failed"- if [ -f $grabber_log ]; then- err " with the following error log."- err- cat >&2 $grabber_log- else- err .- fi- exit 1- fi-- argument="$grabber_out"-fi--if [ -z "$encoding" ] && [ "x$argument" != "x" ]; then- # Try to determine character encoding if not specified- # and input is not STDIN.- encoding=$(- head "$argument" |- LC_ALL=C tr 'A-Z' 'a-z' |- sed -ne '/<meta .*content-type.*charset=/ {- s/.*charset=["'\'']*\([-a-zA-Z0-9]*\).*["'\'']*/\1/p- }'- )-fi--if [ -n "$encoding" ] && pathfind iconv; then- alias to_utf8='iconv -f "$encoding" -t utf-8'-else # assume UTF-8- alias to_utf8='cat'-fi --if [ -z "$argument" ]; then- tidy -asxhtml -utf8 2>/dev/null | pandoc --ignore-args -r html -w markdown "$@"-else- if [ -f "$argument" ]; then- to_utf8 "$argument" | - tidy -asxhtml -utf8 2>/dev/null | pandoc --ignore-args -r html -w markdown "$@"- else- err "File '$argument' not found."- exit 1- fi-fi
− src/wrappers/markdown2pdf.in
@@ -1,81 +0,0 @@-#!/bin/sh -e--REQUIRED="pdflatex"-SYNOPSIS="converts markdown-formatted text to PDF, using pdflatex."--### common.sh--### tempdir.sh--texname=output-logfile=$THIS_TEMPDIR/log--pandoc -s -r markdown -w latex "$@" -o $THIS_TEMPDIR/$texname.tex--if [ "$OUTPUT" = "-" ]; then- firstinfile="$(echo $ARGS | sed -ne '1p')"- firstinfilebase="${firstinfile%.*}"- destname="${firstinfilebase:-stdin}.pdf"-else- destname="$OUTPUT"-fi--(- origdir=$(pwd)- cd $THIS_TEMPDIR- TEXINPUTS=$origdir:$TEXINPUTS:- export TEXINPUTS- finished=no- runs=0- while [ $finished = "no" ]; do- pdflatex -interaction=batchmode $texname.tex >/dev/null || {- errcode=$?- err "${THIS}: pdfLaTeX failed with error code $errcode"- [ -f $texname.log ] && {- err "${THIS}: error context:"- sed -ne '/^!/,/^[[:space:]]*$/p' \- -ne '/^[Ll]a[Tt]e[Xx] [Ww]arning/,/^[[:space:]]*$/p' \- -ne '/^[Ee]rror/,/^[[:space:]]*$/p' $texname.log >&2- if grep -q "File \`ucs.sty' not found" $texname.log; then- err "${THIS}: Please install the 'unicode' package from CTAN:"- err " http://www.ctan.org/tex-archive/macros/latex/contrib/unicode/"- fi- if grep -q "File \`ulem.sty' not found" $texname.log; then- err "${THIS}: Please install the 'ulem' package from CTAN:"- err " http://www.ctan.org/tex-archive/macros/latex/contrib/misc/ulem.sty"- fi- }- exit $errcode- }- if [ $runs -lt 3 ] && - ((grep -q "LaTeX Warning: There were undefined references." $texname.log) ||- (echo "$@" | grep -q -- "--toc\|--table-of-contents")); then- runs=$(($runs + 1))- if grep -q "LaTeX Warning:.*[Cc]itation" $texname.log; then- bibtex $texname 2>&1 >bibtex.err- if [ $runs -gt 2 ]; then- if grep -q "error message" bibtex.err ||- grep -q "Warning" bibtex.err; then- cat bibtex.err >&2- fi- fi- fi- else- finished=yes- fi- done-) || exit $?--is_target_exists=-if [ -f "$destname" ]; then- is_target_exists=1- mv "$destname" "$destname~" -fi--mv -f $THIS_TEMPDIR/$texname.pdf "$destname"--errn "Created $destname"-[ -z "$is_target_exists" ] || {- errn " (previous file has been backed up as $destname~)"-}-err .
− src/wrappers/tempdir.sh
@@ -1,18 +0,0 @@-# As a security measure refuse to proceed if mktemp is not available.-pathfind mktemp || { err "Couldn't find 'mktemp'; aborting."; exit 1; }--# Avoid issues with /tmp directory on Windows/Cygwin -cygwin=-cygwin=$(uname | sed -ne '/^CYGWIN/p')-if [ -n "$cygwin" ]; then- TMPDIR=.- export TMPDIR-fi--THIS_TEMPDIR=-THIS_TEMPDIR="$(mktemp -d -t $THIS.XXXXXXXX)" || exit 1-readonly THIS_TEMPDIR--trap 'exitcode=$?- [ -z "$THIS_TEMPDIR" ] || rm -rf "$THIS_TEMPDIR"- exit $exitcode' 0 1 2 3 13 15
+ templates/ASCIIMathML.hs view
@@ -0,0 +1,7 @@+-- | Definitions for use of ASCIIMathML in HTML. +-- (See <http://www1.chapman.edu/~jipsen/mathml/asciimath.html>.)+module Text.Pandoc.ASCIIMathML ( asciiMathMLScript ) where++-- | String containing ASCIIMathML javascript.+asciiMathMLScript :: String+asciiMathMLScript = "<script type=\"text/javascript\">\n@ASCIIMathML.js@</script>\n"
+ templates/ASCIIMathML.js view
@@ -0,0 +1,3363 @@+/*+ASCIIMathML.js+==============+This file contains JavaScript functions to convert ASCII math notation+and LaTeX to Presentation MathML. Simple graphics commands are also+translated to SVG images. The conversion is done while the (X)HTML +page loads, and should work with Firefox/Mozilla/Netscape 7+ and Internet +Explorer 6/7 + MathPlayer (http://www.dessci.com/en/products/mathplayer/) ++Adobe SVGview 3.03 (http://www.adobe.com/svg/viewer/install/).++Just add the next line to your (X)HTML page with this file in the same folder:++<script type="text/javascript" src="ASCIIMathML.js"></script>++(using the graphics in IE also requires the file "d.svg" in the same folder).+This is a convenient and inexpensive solution for authoring MathML and SVG.++Version 2.0.9 Nov 3, 2007, (c) Peter Jipsen http://www.chapman.edu/~jipsen+This version extends ASCIIMathML.js with LaTeXMathML.js and ASCIIsvg.js.+Latest version at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML.js+If you use it on a webpage, please send the URL to jipsen@chapman.edu++The LaTeXMathML modifications were made by Douglas Woodall, June 2006.+(for details see header on the LaTeXMathML part in middle of file)+Extensive clean-up and improvements by Paulo Soares, Oct 2007.++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU Lesser General Public License as published by+the Free Software Foundation; either version 2.1 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 Lesser General Public License +(at http://www.gnu.org/licences/lgpl.html) for more details.+*/++var mathcolor = ""; // change it to "" (to inherit) or another color+var mathfontsize = "1em"; // change to e.g. 1.2em for larger math+var mathfontfamily = "serif"; // change to "" to inherit (works in IE) + // or another family (e.g. "arial")+var automathrecognize = false; // writing "amath" on page makes this true+var checkForMathML = true; // check if browser can display MathML+var notifyIfNoMathML = true; // display note at top if no MathML capability+var alertIfNoMathML = false; // show alert box if no MathML capability+var translateOnLoad = true; // set to false to do call translators from js +var translateLaTeX = true; // false to preserve $..$, $$..$$+var translateLaTeXformatting = true; // false to preserve \emph,\begin{},\end{}+var translateASCIIMath = true; // false to preserve `..`+var translateASCIIsvg = true; // false to preserve agraph.., \begin{graph}..+var avoidinnerHTML = false; // set true if assigning to innerHTML gives error+var displaystyle = true; // puts limits above and below large operators+var showasciiformulaonhover = true; // helps students learn ASCIIMath+var decimalsign = "."; // change to "," if you like, beware of `(1,2)`!+var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters+var AMdocumentId = "wikitext" // PmWiki element containing math (default=body)+var checkforprocessasciimathinmoodle = false; // true for systems like Moodle+var dsvglocation = ""; // path to d.svg (blank if same as ASCIIMathML.js loc)++/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/++var isIE = document.createElementNS==null;+var noMathML = false, translated = false;++if (isIE) { // avoid adding MathPlayer info explicitly to each webpage+ document.write("<object id=\"mathplayer\"\+ classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");+ document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");+}++// Add a stylesheet, replacing any previous custom stylesheet (adapted from TW)+function setStylesheet(s) {+ var id = "AMMLcustomStyleSheet";+ var n = document.getElementById(id);+ if(document.createStyleSheet) {+ // Test for IE's non-standard createStyleSheet method+ if(n)+ n.parentNode.removeChild(n);+ // This failed without the + document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd"," <style id='" + id + "'>" + s + "</style>");+ } else {+ if(n) {+ n.replaceChild(document.createTextNode(s),n.firstChild);+ } else {+ n = document.createElement("style");+ n.type = "text/css";+ n.id = id;+ n.appendChild(document.createTextNode(s));+ document.getElementsByTagName("head")[0].appendChild(n);+ }+ }+}++setStylesheet("#AMMLcloseDiv \{font-size:0.8em; padding-top:1em; color:#014\}\n#AMMLwarningBox \{position:absolute; width:100%; top:0; left:0; z-index:200; text-align:center; font-size:1em; font-weight:bold; padding:0.5em 0 0.5em 0; color:#ffc; background:#c30\}");++function init(){+ var msg, warnings = new Array();+ if (document.getElementById==null){+ alert("This webpage requires a recent browser such as Mozilla Firefox/Netscape 7+ or Internet Explorer 6+ with MathPlayer and Adobe SVGviewer");+ return null;+ }+ if (checkForMathML && (msg = checkMathML())) warnings.push(msg);+ if (checkIfSVGavailable && (msg = checkSVG())) warnings.push(msg);+ if (warnings.length>0) displayWarnings(warnings);+ if (!noMathML) initSymbols();+ return true;+}++function checkMathML(){+ if (navigator.appName.slice(0,8)=="Netscape") + if (navigator.appVersion.slice(0,1)>="5") noMathML = null;+ else noMathML = true;+ else if (navigator.appName.slice(0,9)=="Microsoft")+ try {+ var ActiveX = new ActiveXObject("MathPlayer.Factory.1");+ noMathML = null;+ } catch (e) {+ noMathML = true;+ }+ else noMathML = true;+//noMathML = true; //uncomment to check+ if (noMathML && notifyIfNoMathML) {+ var msg = "To view the ASCIIMathML notation use Internet Explorer + MathPlayer or Mozilla Firefox 2.0 or later.";+ if (alertIfNoMathML)+ alert(msg);+ else return msg;+ }+}++function hideWarning(){+ var body = document.getElementsByTagName("body")[0];+ body.removeChild(document.getElementById('AMMLwarningBox'));+ body.onclick = null;+}++function displayWarnings(warnings) {+ var i, frag, nd = createElementXHTML("div");+ var body = document.getElementsByTagName("body")[0];+ body.onclick=hideWarning;+ nd.id = 'AMMLwarningBox';+ for (i=0; i<warnings.length; i++) {+ frag = createElementXHTML("div");+ frag.appendChild(document.createTextNode(warnings[i]));+ frag.style.paddingBottom = "1.0em";+ nd.appendChild(frag);+ }+ nd.appendChild(createElementXHTML("p"));+ nd.appendChild(document.createTextNode("For instructions see the "));+ var an = createElementXHTML("a");+ an.appendChild(document.createTextNode("ASCIIMathML"));+ an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html");+ nd.appendChild(an);+ nd.appendChild(document.createTextNode(" homepage"));+ an = createElementXHTML("div");+ an.id = 'AMMLcloseDiv';+ an.appendChild(document.createTextNode('(click anywhere to close this warning)'));+ nd.appendChild(an);+ var body = document.getElementsByTagName("body")[0];+ body.insertBefore(nd,body.childNodes[0]);+}++function translate(spanclassAM) {+ if (!translated) { // run this only once+ translated = true;+ var body = document.getElementsByTagName("body")[0];+ var processN = document.getElementById(AMdocumentId);+ if (translateLaTeX) LMprocessNode((processN!=null?processN:body));+ if (translateASCIIMath) AMprocessNode((processN!=null?processN:body), false, spanclassAM);+ }+}++function createElementXHTML(t) {+ if (isIE) return document.createElement(t);+ else return document.createElementNS("http://www.w3.org/1999/xhtml",t);+}++function createMmlNode(t,frag) {+ if (isIE) var node = document.createElement("m:"+t);+ else var node = document.createElementNS("http://www.w3.org/1998/Math/MathML",t);+ if (frag) node.appendChild(frag);+ return node;+}++// character lists for Mozilla/Netscape fonts+var AMcal = [0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];+var AMfrk = [0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];+var AMbbb = [0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];++var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,+ RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,+ LEFTRIGHT = 9, TEXT = 10, BIG = 11, LONG = 12, STRETCHY = 13,+ MATRIX = 14;; // token types++var AMquote = {input:"\"", tag:"mtext", output:"mbox", tex:null, ttype:TEXT};++var AMsymbols = [+//some greek symbols+{input:"alpha", tag:"mi", output:"\u03B1", tex:null, ttype:CONST},+{input:"beta", tag:"mi", output:"\u03B2", tex:null, ttype:CONST},+{input:"chi", tag:"mi", output:"\u03C7", tex:null, ttype:CONST},+{input:"delta", tag:"mi", output:"\u03B4", tex:null, ttype:CONST},+{input:"Delta", tag:"mo", output:"\u0394", tex:null, ttype:CONST},+{input:"epsi", tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST},+{input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST},+{input:"eta", tag:"mi", output:"\u03B7", tex:null, ttype:CONST},+{input:"gamma", tag:"mi", output:"\u03B3", tex:null, ttype:CONST},+{input:"Gamma", tag:"mo", output:"\u0393", tex:null, ttype:CONST},+{input:"iota", tag:"mi", output:"\u03B9", tex:null, ttype:CONST},+{input:"kappa", tag:"mi", output:"\u03BA", tex:null, ttype:CONST},+{input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},+{input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},+{input:"mu", tag:"mi", output:"\u03BC", tex:null, ttype:CONST},+{input:"nu", tag:"mi", output:"\u03BD", tex:null, ttype:CONST},+{input:"omega", tag:"mi", output:"\u03C9", tex:null, ttype:CONST},+{input:"Omega", tag:"mo", output:"\u03A9", tex:null, ttype:CONST},+{input:"phi", tag:"mi", output:"\u03C6", tex:null, ttype:CONST},+{input:"varphi", tag:"mi", output:"\u03D5", tex:null, ttype:CONST},+{input:"Phi", tag:"mo", output:"\u03A6", tex:null, ttype:CONST},+{input:"pi", tag:"mi", output:"\u03C0", tex:null, ttype:CONST},+{input:"Pi", tag:"mo", output:"\u03A0", tex:null, ttype:CONST},+{input:"psi", tag:"mi", output:"\u03C8", tex:null, ttype:CONST},+{input:"Psi", tag:"mi", output:"\u03A8", tex:null, ttype:CONST},+{input:"rho", tag:"mi", output:"\u03C1", tex:null, ttype:CONST},+{input:"sigma", tag:"mi", output:"\u03C3", tex:null, ttype:CONST},+{input:"Sigma", tag:"mo", output:"\u03A3", tex:null, ttype:CONST},+{input:"tau", tag:"mi", output:"\u03C4", tex:null, ttype:CONST},+{input:"theta", tag:"mi", output:"\u03B8", tex:null, ttype:CONST},+{input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST},+{input:"Theta", tag:"mo", output:"\u0398", tex:null, ttype:CONST},+{input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST},+{input:"xi", tag:"mi", output:"\u03BE", tex:null, ttype:CONST},+{input:"Xi", tag:"mo", output:"\u039E", tex:null, ttype:CONST},+{input:"zeta", tag:"mi", output:"\u03B6", tex:null, ttype:CONST},++//binary operation symbols+//{input:"-", tag:"mo", output:"\u0096", tex:null, ttype:CONST},+{input:"*", tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST},+{input:"**", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST},+{input:"//", tag:"mo", output:"/", tex:null, ttype:CONST},+{input:"\\\\", tag:"mo", output:"\\", tex:"backslash", ttype:CONST},+{input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST},+{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST},+{input:"-:", tag:"mo", output:"\u00F7", tex:"divide", ttype:CONST},+{input:"@", tag:"mo", output:"\u2218", tex:"circ", ttype:CONST},+{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST},+{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST},+{input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST},+{input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER},+{input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER},+{input:"^^", tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST},+{input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER},+{input:"vv", tag:"mo", output:"\u2228", tex:"vee", ttype:CONST},+{input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER},+{input:"nn", tag:"mo", output:"\u2229", tex:"cap", ttype:CONST},+{input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER},+{input:"uu", tag:"mo", output:"\u222A", tex:"cup", ttype:CONST},+{input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER},++//binary relation symbols+{input:"!=", tag:"mo", output:"\u2260", tex:"ne", ttype:CONST},+{input:":=", tag:"mo", output:":=", tex:null, ttype:CONST},+{input:"lt", tag:"mo", output:"<", tex:null, ttype:CONST},+{input:"<=", tag:"mo", output:"\u2264", tex:"le", ttype:CONST},+{input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST},+{input:">=", tag:"mo", output:"\u2265", tex:"ge", ttype:CONST},+{input:"geq", tag:"mo", output:"\u2265", tex:null, ttype:CONST},+{input:"-<", tag:"mo", output:"\u227A", tex:"prec", ttype:CONST},+{input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST},+{input:">-", tag:"mo", output:"\u227B", tex:"succ", ttype:CONST},+{input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST},+{input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST},+{input:"in", tag:"mo", output:"\u2208", tex:null, ttype:CONST},+{input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST},+{input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST},+{input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST},+{input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST},+{input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST},+{input:"-=", tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST},+{input:"~=", tag:"mo", output:"\u2245", tex:"cong", ttype:CONST},+{input:"~~", tag:"mo", output:"\u2248", tex:"approx", ttype:CONST},+{input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST},++//logical symbols+{input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE},+{input:"or", tag:"mtext", output:"or", tex:null, ttype:SPACE},+{input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST},+{input:"=>", tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST},+{input:"if", tag:"mo", output:"if", tex:null, ttype:SPACE},+{input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST},+{input:"AA", tag:"mo", output:"\u2200", tex:"forall", ttype:CONST},+{input:"EE", tag:"mo", output:"\u2203", tex:"exists", ttype:CONST},+{input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST},+{input:"TT", tag:"mo", output:"\u22A4", tex:"top", ttype:CONST},+{input:"|--", tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST},+{input:"|==", tag:"mo", output:"\u22A8", tex:"models", ttype:CONST},++//grouping brackets+{input:"(", tag:"mo", output:"(", tex:null, ttype:LEFTBRACKET},+{input:")", tag:"mo", output:")", tex:null, ttype:RIGHTBRACKET},+{input:"[", tag:"mo", output:"[", tex:null, ttype:LEFTBRACKET},+{input:"]", tag:"mo", output:"]", tex:null, ttype:RIGHTBRACKET},+{input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET},+{input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET},+{input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT},+//{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},+{input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET},+{input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET},+{input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET},+{input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET},+{input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true},+{input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true},++//miscellaneous symbols+{input:"int", tag:"mo", output:"\u222B", tex:null, ttype:CONST},+{input:"dx", tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION},+{input:"dy", tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION},+{input:"dz", tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION},+{input:"dt", tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION},+{input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST},+{input:"del", tag:"mo", output:"\u2202", tex:"partial", ttype:CONST},+{input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST},+{input:"+-", tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST},+{input:"O/", tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST},+{input:"oo", tag:"mo", output:"\u221E", tex:"infty", ttype:CONST},+{input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST},+{input:"...", tag:"mo", output:"...", tex:"ldots", ttype:CONST},+{input:":.", tag:"mo", output:"\u2234", tex:"therefore", ttype:CONST},+{input:"/_", tag:"mo", output:"\u2220", tex:"angle", ttype:CONST},+{input:"\\ ", tag:"mo", output:"\u00A0", tex:null, ttype:CONST},+{input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST},+{input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST},+{input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST},+{input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST},+{input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST},+{input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST},+{input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST},+{input:"|__", tag:"mo", output:"\u230A", tex:"lfloor", ttype:CONST},+{input:"__|", tag:"mo", output:"\u230B", tex:"rfloor", ttype:CONST},+{input:"|~", tag:"mo", output:"\u2308", tex:"lceiling", ttype:CONST},+{input:"~|", tag:"mo", output:"\u2309", tex:"rceiling", ttype:CONST},+{input:"CC", tag:"mo", output:"\u2102", tex:null, ttype:CONST},+{input:"NN", tag:"mo", output:"\u2115", tex:null, ttype:CONST},+{input:"QQ", tag:"mo", output:"\u211A", tex:null, ttype:CONST},+{input:"RR", tag:"mo", output:"\u211D", tex:null, ttype:CONST},+{input:"ZZ", tag:"mo", output:"\u2124", tex:null, ttype:CONST},+{input:"f", tag:"mi", output:"f", tex:null, ttype:UNARY, func:true},+{input:"g", tag:"mi", output:"g", tex:null, ttype:UNARY, func:true},++//standard functions+{input:"lim", tag:"mo", output:"lim", tex:null, ttype:UNDEROVER},+{input:"Lim", tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER},+{input:"sin", tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true},+{input:"cos", tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true},+{input:"tan", tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true},+{input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true},+{input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true},+{input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true},+{input:"cot", tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true},+{input:"sec", tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true},+{input:"csc", tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true},+{input:"log", tag:"mo", output:"log", tex:null, ttype:UNARY, func:true},+{input:"ln", tag:"mo", output:"ln", tex:null, ttype:UNARY, func:true},+{input:"det", tag:"mo", output:"det", tex:null, ttype:UNARY, func:true},+{input:"dim", tag:"mo", output:"dim", tex:null, ttype:CONST},+{input:"mod", tag:"mo", output:"mod", tex:null, ttype:CONST},+{input:"gcd", tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true},+{input:"lcm", tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true},+{input:"lub", tag:"mo", output:"lub", tex:null, ttype:CONST},+{input:"glb", tag:"mo", output:"glb", tex:null, ttype:CONST},+{input:"min", tag:"mo", output:"min", tex:null, ttype:UNDEROVER},+{input:"max", tag:"mo", output:"max", tex:null, ttype:UNDEROVER},++//arrows+{input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST},+{input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST},+{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST},+{input:"->", tag:"mo", output:"\u2192", tex:"to", ttype:CONST},+{input:">->", tag:"mo", output:"\u21A3", tex:"rightarrowtail", ttype:CONST},+{input:"->>", tag:"mo", output:"\u21A0", tex:"twoheadrightarrow", ttype:CONST},+{input:">->>", tag:"mo", output:"\u2916", tex:"twoheadrightarrowtail", ttype:CONST},+{input:"|->", tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST},+{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST},+{input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST},+{input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST},+{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST},+{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST},+//commands with argument+{input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY},+{input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY},+{input:"frac", tag:"mfrac", output:"/", tex:null, ttype:BINARY},+{input:"/", tag:"mfrac", output:"/", tex:null, ttype:INFIX},+{input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},+{input:"_", tag:"msub", output:"_", tex:null, ttype:INFIX},+{input:"^", tag:"msup", output:"^", tex:null, ttype:INFIX},+{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true},+{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true},+{input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true},+{input:"dot", tag:"mover", output:".", tex:null, ttype:UNARY, acc:true},+{input:"ddot", tag:"mover", output:"..", tex:null, ttype:UNARY, acc:true},+{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true},+{input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT},+{input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT},+AMquote,+{input:"bb", tag:"mstyle", atname:"fontweight", atval:"bold", output:"bb", tex:null, ttype:UNARY},+{input:"mathbf", tag:"mstyle", atname:"fontweight", atval:"bold", output:"mathbf", tex:null, ttype:UNARY},+{input:"sf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY},+{input:"mathsf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY},+{input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb},+{input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb},+{input:"cc", tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal},+{input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal},+{input:"tt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"tt", tex:null, ttype:UNARY},+{input:"mathtt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY},+{input:"fr", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk},+{input:"mathfrak", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk}+];++function compareNames(s1,s2) {+ if (s1.input > s2.input) return 1+ else return -1;+}++var AMnames = []; //list of input symbols++function initSymbols() {+ var texsymbols = [], i;+ for (i=0; i<AMsymbols.length; i++)+ if (AMsymbols[i].tex) + texsymbols[texsymbols.length] = {input:AMsymbols[i].tex, + tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype};+ AMsymbols = AMsymbols.concat(texsymbols);+ refreshSymbols();+}++function refreshSymbols(){+ var i;+ AMsymbols.sort(compareNames);+ for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;+ LMsymbols.sort(compareNames);+ for (i=0; i<LMsymbols.length; i++) LMnames[i] = LMsymbols[i].input;+}++function define(oldstr,newstr) {+ if(oldstr.substr(0,1)=="\\")+ LMsymbols = LMsymbols.concat([{input:oldstr, tag:"mo", output:newstr,+ ttype:DEFINITION}]);+ else+ AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr, + tex:null, ttype:DEFINITION}]);+ refreshSymbols(); // this may be a problem if many symbols are defined!+}++function AMremoveCharsAndBlanks(str,n) {+//remove n characters and any following blanks+ var st;+ if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ") + st = str.slice(n+1);+ else st = str.slice(n);+ for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);+ return st.slice(i);+}++function position(arr, str, n) { +// return position >=n where str appears or would be inserted+// assumes arr is sorted+ if (n==0) {+ var h,m;+ n = -1;+ h = arr.length;+ while (n+1<h) {+ m = (n+h) >> 1;+ if (arr[m]<str) n = m; else h = m;+ }+ return h;+ } else+ for (var i=n; i<arr.length && arr[i]<str; i++);+ return i; // i=arr.length || arr[i]>=str+}++function AMgetSymbol(str) {+//return maximal initial substring of str that appears in names+//return null if there is none+ var k = 0; //new pos+ var j = 0; //old pos+ var mk; //match pos+ var st;+ var tagst;+ var match = "";+ var more = true;+ for (var i=1; i<=str.length && more; i++) {+ st = str.slice(0,i); //initial substring of length i+ j = k;+ k = position(AMnames, st, j);+ if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){+ match = AMnames[k];+ mk = k;+ i = match.length;+ }+ more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];+ }+ AMpreviousSymbol=AMcurrentSymbol;+ if (match!=""){+ AMcurrentSymbol=AMsymbols[mk].ttype;+ return AMsymbols[mk]; + }+// if str[0] is a digit or - return maxsubstring of digits.digits+ AMcurrentSymbol=CONST;+ k = 1;+ st = str.slice(0,1);+ var integ = true;+ while ("0"<=st && st<="9" && k<=str.length) {+ st = str.slice(k,k+1);+ k++;+ }+ if (st == decimalsign) {+ st = str.slice(k,k+1);+ if ("0"<=st && st<="9") {+ integ = false;+ k++;+ while ("0"<=st && st<="9" && k<=str.length) {+ st = str.slice(k,k+1);+ k++;+ }+ }+ }+ if ((integ && k>1) || k>2) {+ st = str.slice(0,k-1);+ tagst = "mn";+ } else {+ k = 2;+ st = str.slice(0,1); //take 1 character+ tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");+ }+ if (st=="-" && AMpreviousSymbol==INFIX) {+ AMcurrentSymbol = INFIX; //trick "/" into recognizing "-" on second parse+ return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};+ }+ return {input:st, tag:tagst, output:st, ttype:CONST};+}++function AMremoveBrackets(node) {+ var st;+ if (node.nodeName=="mrow") {+ st = node.firstChild.firstChild.nodeValue;+ if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild);+ }+ if (node.nodeName=="mrow") {+ st = node.lastChild.firstChild.nodeValue;+ if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild);+ }+}++/*Parsing ASCII math expressions with the following grammar+v ::= [A-Za-z] | greek letters | numbers | other constant symbols+u ::= sqrt | text | bb | other unary symbols for font commands+b ::= frac | root | stackrel binary symbols+l ::= ( | [ | { | (: | {: left brackets+r ::= ) | ] | } | :) | :} right brackets+S ::= v | lEr | uS | bSS Simple expression+I ::= S_S | S^S | S_S^S | S Intermediate expression+E ::= IE | I/I Expression+Each terminal symbol is translated into a corresponding mathml node.*/++var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;++function AMparseSexpr(str) { //parses str and returns [node,tailstr]+ var symbol, node, result, i, st,// rightvert = false,+ newFrag = document.createDocumentFragment();+ str = AMremoveCharsAndBlanks(str,0);+ symbol = AMgetSymbol(str); //either a token or a bracket or empty+ if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {+ return [null,str];+ }+ if (symbol.ttype == DEFINITION) {+ str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length); + symbol = AMgetSymbol(str);+ }+ switch (symbol.ttype) { case UNDEROVER:+ case CONST:+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + return [createMmlNode(symbol.tag, //its a constant+ document.createTextNode(symbol.output)),str];+ case LEFTBRACKET: //read (expr+)+ AMnestingDepth++;+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + result = AMparseExpr(str,true);+ AMnestingDepth--;+ if (typeof symbol.invisible == "boolean" && symbol.invisible) + node = createMmlNode("mrow",result[0]);+ else {+ node = createMmlNode("mo",document.createTextNode(symbol.output));+ node = createMmlNode("mrow",node);+ node.appendChild(result[0]);+ }+ return [node,result[1]];+ case TEXT:+ if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);+ if (str.charAt(0)=="{") i=str.indexOf("}");+ else if (str.charAt(0)=="(") i=str.indexOf(")");+ else if (str.charAt(0)=="[") i=str.indexOf("]");+ else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1;+ else i = 0;+ if (i==-1) i = str.length;+ st = str.slice(1,i);+ if (st.charAt(0) == " ") {+ node = createMmlNode("mspace");+ node.setAttribute("width","1ex");+ newFrag.appendChild(node);+ }+ newFrag.appendChild(+ createMmlNode(symbol.tag,document.createTextNode(st)));+ if (st.charAt(st.length-1) == " ") {+ node = createMmlNode("mspace");+ node.setAttribute("width","1ex");+ newFrag.appendChild(node);+ }+ str = AMremoveCharsAndBlanks(str,i+1);+ return [createMmlNode("mrow",newFrag),str];+ case UNARY:+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + result = AMparseSexpr(str);+ if (result[0]==null) return [createMmlNode(symbol.tag,+ document.createTextNode(symbol.output)),str];+ if (typeof symbol.func == "boolean" && symbol.func) { // functions hack+ st = str.charAt(0);+ if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {+ return [createMmlNode(symbol.tag,+ document.createTextNode(symbol.output)),str];+ } else {+ node = createMmlNode("mrow",+ createMmlNode(symbol.tag,document.createTextNode(symbol.output)));+ node.appendChild(result[0]);+ return [node,result[1]];+ }+ }+ AMremoveBrackets(result[0]);+ if (symbol.input == "sqrt") { // sqrt+ return [createMmlNode(symbol.tag,result[0]),result[1]];+ } else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent+ node = createMmlNode(symbol.tag,result[0]);+ node.appendChild(createMmlNode("mo",document.createTextNode(symbol.output)));+ return [node,result[1]];+ } else { // font change command+ if (!isIE && typeof symbol.codes != "undefined") {+ for (i=0; i<result[0].childNodes.length; i++)+ if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {+ st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:+ result[0].childNodes[i].firstChild.nodeValue);+ var newst = [];+ for (var j=0; j<st.length; j++)+ if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst ++ String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);+ else newst = newst + st.charAt(j);+ if (result[0].nodeName=="mi")+ result[0]=createMmlNode("mo").+ appendChild(document.createTextNode(newst));+ else result[0].replaceChild(createMmlNode("mo").+ appendChild(document.createTextNode(newst)),+ result[0].childNodes[i]);+ }+ }+ node = createMmlNode(symbol.tag,result[0]);+ node.setAttribute(symbol.atname,symbol.atval);+ return [node,result[1]];+ }+ case BINARY:+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + result = AMparseSexpr(str);+ if (result[0]==null) return [createMmlNode("mo",+ document.createTextNode(symbol.input)),str];+ AMremoveBrackets(result[0]);+ var result2 = AMparseSexpr(result[1]);+ if (result2[0]==null) return [createMmlNode("mo",+ document.createTextNode(symbol.input)),str];+ AMremoveBrackets(result2[0]);+ if (symbol.input=="root" || symbol.input=="stackrel") + newFrag.appendChild(result2[0]);+ newFrag.appendChild(result[0]);+ if (symbol.input=="frac") newFrag.appendChild(result2[0]);+ return [createMmlNode(symbol.tag,newFrag),result2[1]];+ case INFIX:+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + return [createMmlNode("mo",document.createTextNode(symbol.output)),str];+ case SPACE:+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + node = createMmlNode("mspace");+ node.setAttribute("width","1ex");+ newFrag.appendChild(node);+ newFrag.appendChild(+ createMmlNode(symbol.tag,document.createTextNode(symbol.output)));+ node = createMmlNode("mspace");+ node.setAttribute("width","1ex");+ newFrag.appendChild(node);+ return [createMmlNode("mrow",newFrag),str];+ case LEFTRIGHT:+// if (rightvert) return [null,str]; else rightvert = true;+ AMnestingDepth++;+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + result = AMparseExpr(str,false);+ AMnestingDepth--;+ var st = "";+ if (result[0].lastChild!=null)+ st = result[0].lastChild.firstChild.nodeValue;+ if (st == "|") { // its an absolute value subterm+ node = createMmlNode("mo",document.createTextNode(symbol.output));+ node = createMmlNode("mrow",node);+ node.appendChild(result[0]);+ return [node,result[1]];+ } else { // the "|" is a \mid so use unicode 2223 (divides) for spacing+ node = createMmlNode("mo",document.createTextNode("\u2223"));+ node = createMmlNode("mrow",node);+ return [node,str];+ }+ default:+//alert("default");+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + return [createMmlNode(symbol.tag, //its a constant+ document.createTextNode(symbol.output)),str];+ }+}++function AMparseIexpr(str) {+ var symbol, sym1, sym2, node, result, underover;+ str = AMremoveCharsAndBlanks(str,0);+ sym1 = AMgetSymbol(str);+ result = AMparseSexpr(str);+ node = result[0];+ str = result[1];+ symbol = AMgetSymbol(str);+ if (symbol.ttype == INFIX && symbol.input != "/") {+ str = AMremoveCharsAndBlanks(str,symbol.input.length);+// if (symbol.input == "/") result = AMparseIexpr(str); else ...+ result = AMparseSexpr(str);+ if (result[0] == null) // show box in place of missing argument+ result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));+ else AMremoveBrackets(result[0]);+ str = result[1];+// if (symbol.input == "/") AMremoveBrackets(node);+ if (symbol.input == "_") {+ sym2 = AMgetSymbol(str);+ underover = (sym1.ttype == UNDEROVER);+ if (sym2.input == "^") {+ str = AMremoveCharsAndBlanks(str,sym2.input.length);+ var res2 = AMparseSexpr(str);+ AMremoveBrackets(res2[0]);+ str = res2[1];+ node = createMmlNode((underover?"munderover":"msubsup"),node);+ node.appendChild(result[0]);+ node.appendChild(res2[0]);+ node = createMmlNode("mrow",node); // so sum does not stretch+ } else {+ node = createMmlNode((underover?"munder":"msub"),node);+ node.appendChild(result[0]);+ }+ } else {+ node = createMmlNode(symbol.tag,node);+ node.appendChild(result[0]);+ }+ }+ return [node,str];+}++function AMparseExpr(str,rightbracket) {+ var symbol, node, result, i, nodeList = [],+ newFrag = document.createDocumentFragment();+ do {+ str = AMremoveCharsAndBlanks(str,0);+ result = AMparseIexpr(str);+ node = result[0];+ str = result[1];+ symbol = AMgetSymbol(str);+ if (symbol.ttype == INFIX && symbol.input == "/") {+ str = AMremoveCharsAndBlanks(str,symbol.input.length);+ result = AMparseIexpr(str);+ if (result[0] == null) // show box in place of missing argument+ result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));+ else AMremoveBrackets(result[0]);+ str = result[1];+ AMremoveBrackets(node);+ node = createMmlNode(symbol.tag,node);+ node.appendChild(result[0]);+ newFrag.appendChild(node);+ symbol = AMgetSymbol(str);+ } + else if (node!=undefined) newFrag.appendChild(node);+ } while ((symbol.ttype != RIGHTBRACKET && + (symbol.ttype != LEFTRIGHT || rightbracket)+ || AMnestingDepth == 0) && symbol!=null && symbol.output!="");+ if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {+// if (AMnestingDepth > 0) AMnestingDepth--;+ var len = newFrag.childNodes.length;+ if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&+ newFrag.childNodes[len-2].nodeName == "mo" &&+ newFrag.childNodes[len-2].firstChild.nodeValue == ",") { //matrix+ var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;+ if (right==")" || right=="]") {+ var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;+ if (left=="(" && right==")" && symbol.output != "}" || + left=="[" && right=="]") {+ var pos = []; // positions of commas+ var matrix = true;+ var m = newFrag.childNodes.length;+ for (i=0; matrix && i<m; i=i+2) {+ pos[i] = [];+ node = newFrag.childNodes[i];+ if (matrix) matrix = node.nodeName=="mrow" && + (i==m-1 || node.nextSibling.nodeName=="mo" && + node.nextSibling.firstChild.nodeValue==",")&&+ node.firstChild.firstChild.nodeValue==left &&+ node.lastChild.firstChild.nodeValue==right;+ if (matrix) + for (var j=0; j<node.childNodes.length; j++)+ if (node.childNodes[j].firstChild.nodeValue==",")+ pos[i][pos[i].length]=j;+ if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;+ }+ if (matrix) {+ var row, frag, n, k, table = document.createDocumentFragment();+ for (i=0; i<m; i=i+2) {+ row = document.createDocumentFragment();+ frag = document.createDocumentFragment();+ node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>+ n = node.childNodes.length;+ k = 0;+ node.removeChild(node.firstChild); //remove (+ for (j=1; j<n-1; j++) {+ if (typeof pos[i][k] != "undefined" && j==pos[i][k]){+ node.removeChild(node.firstChild); //remove ,+ row.appendChild(createMmlNode("mtd",frag));+ k++;+ } else frag.appendChild(node.firstChild);+ }+ row.appendChild(createMmlNode("mtd",frag));+ if (newFrag.childNodes.length>2) {+ newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>+ newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>+ }+ table.appendChild(createMmlNode("mtr",row));+ }+ node = createMmlNode("mtable",table);+ if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left");+ newFrag.replaceChild(node,newFrag.firstChild);+ }+ }+ }+ }+ str = AMremoveCharsAndBlanks(str,symbol.input.length);+ if (typeof symbol.invisible != "boolean" || !symbol.invisible) {+ node = createMmlNode("mo",document.createTextNode(symbol.output));+ newFrag.appendChild(node);+ }+ }+ return [newFrag,str];+}++function parseMath(str,latex) {+ var frag, node;+ AMnestingDepth = 0;+ frag = latex ? LMparseExpr(str.replace(/^\s+/g,""),false,false)[0] : AMparseExpr(str.replace(/^\s+/g,""),false)[0];+ node = createMmlNode("mstyle",frag);+ node.setAttribute("mathcolor",mathcolor);+ node.setAttribute("fontfamily",mathfontfamily);+ node.setAttribute("mathsize",mathfontsize);+ if (displaystyle) node.setAttribute("displaystyle","true");+ node = createMmlNode("math",node);+ if (showasciiformulaonhover) //fixed by djhsu so newline+ node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko+ return node;+}++function strarr2docFrag(arr, linebreaks, latex) {+ var newFrag=document.createDocumentFragment();+ var expr = false;+ for (var i=0; i<arr.length; i++) {+ if (expr) newFrag.appendChild(parseMath(arr[i],latex));+ else {+ var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);+ newFrag.appendChild(createElementXHTML("span").+ appendChild(document.createTextNode(arri[0])));+ for (var j=1; j<arri.length; j++) {+ newFrag.appendChild(createElementXHTML("p"));+ newFrag.appendChild(createElementXHTML("span").+ appendChild(document.createTextNode(arri[j])));+ }+ }+ expr = !expr;+ }+ return newFrag;+}++function AMautomathrec(str) {+//formula is a space (or start of str) followed by a maximal sequence of *two* or more tokens, possibly separated by runs of digits and/or space.+//tokens are single letters (except a, A, I) and ASCIIMathML tokens+ var texcommand = "\\\\[a-zA-Z]+|\\\\\\s|";+ var ambigAMtoken = "\\b(?:oo|lim|ln|int|oint|del|grad|aleph|prod|prop|sinh|cosh|tanh|cos|sec|pi|tt|fr|sf|sube|supe|sub|sup|det|mod|gcd|lcm|min|max|vec|ddot|ul|chi|eta|nu|mu)(?![a-z])|";+ var englishAMtoken = "\\b(?:sum|ox|log|sin|tan|dim|hat|bar|dot)(?![a-z])|";+ var secondenglishAMtoken = "|\\bI\\b|\\bin\\b|\\btext\\b"; // took if and or not out+ var simpleAMtoken = "NN|ZZ|QQ|RR|CC|TT|AA|EE|sqrt|dx|dy|dz|dt|xx|vv|uu|nn|bb|cc|csc|cot|alpha|beta|delta|Delta|epsilon|gamma|Gamma|kappa|lambda|Lambda|omega|phi|Phi|Pi|psi|Psi|rho|sigma|Sigma|tau|theta|Theta|xi|Xi|zeta"; // uuu nnn?+ var letter = "[a-zA-HJ-Z](?=(?:[^a-zA-Z]|$|"+ambigAMtoken+englishAMtoken+simpleAMtoken+"))|";+ var token = letter+texcommand+"\\d+|[-()[\\]{}+=*&^_%\\\@/<>,\\|!:;'~]|\\.(?!(?:\x20|$))|"+ambigAMtoken+englishAMtoken+simpleAMtoken;+ var re = new RegExp("(^|\\s)((("+token+")\\s?)(("+token+secondenglishAMtoken+")\\s?)+)([,.?]?(?=\\s|$))","g");+ str = str.replace(re," `$2`$7");+ var arr = str.split(AMdelimiter1);+ var re1 = new RegExp("(^|\\s)([b-zB-HJ-Z+*<>]|"+texcommand+ambigAMtoken+simpleAMtoken+")(\\s|\\n|$)","g");+ var re2 = new RegExp("(^|\\s)([a-z]|"+texcommand+ambigAMtoken+simpleAMtoken+")([,.])","g"); // removed |\d+ for now+ for (i=0; i<arr.length; i++) //single nonenglish tokens+ if (i%2==0) {+ arr[i] = arr[i].replace(re1," `$2`$3");+ arr[i] = arr[i].replace(re2," `$2`$3");+ arr[i] = arr[i].replace(/([{}[\]])/,"`$1`");+ }+ str = arr.join(AMdelimiter1);+ str = str.replace(/((^|\s)\([a-zA-Z]{2,}.*?)\)`/g,"$1`)"); //fix parentheses+ str = str.replace(/`(\((a\s|in\s))(.*?[a-zA-Z]{2,}\))/g,"$1`$3"); //fix parentheses+ str = str.replace(/\sin`/g,"` in");+ str = str.replace(/`(\(\w\)[,.]?(\s|\n|$))/g,"$1`");+ str = str.replace(/`([0-9.]+|e.g|i.e)`(\.?)/gi,"$1$2");+ str = str.replace(/`([0-9.]+:)`/g,"$1");+ return str;+}++function processNodeR(n, linebreaks,latex) {+ var mtch, str, arr, frg, i;+ if (n.childNodes.length == 0) {+ if ((n.nodeType!=8 || linebreaks) &&+ n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&+ n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" /*&&+ n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE"*/) {+ str = n.nodeValue;+ if (!(str == null)) {+ str = str.replace(/\r\n\r\n/g,"\n\n");+ str = str.replace(/\x20+/g," ");+ str = str.replace(/\s*\r\n/g," ");+ if(latex) {+// DELIMITERS:+ mtch = (str.indexOf("\$")==-1 ? false : true);+ str = str.replace(/([^\\])\$/g,"$1 \$");+ str = str.replace(/^\$/," \$"); // in case \$ at start of string+ arr = str.split(" \$");+ for (i=0; i<arr.length; i++)+ arr[i]=arr[i].replace(/\\\$/g,"\$");+ } else {+ mtch = false;+ str = str.replace(new RegExp(AMescape1, "g"),+ function(){mtch = true; return "AMescape1"});+ str = str.replace(/\\?end{?a?math}?/i,+ function(){automathrecognize = false; mtch = true; return ""});+ str = str.replace(/amath\b|\\begin{a?math}/i,+ function(){automathrecognize = true; mtch = true; return ""});+ arr = str.split(AMdelimiter1);+ if (automathrecognize)+ for (i=0; i<arr.length; i++)+ if (i%2==0) arr[i] = AMautomathrec(arr[i]);+ str = arr.join(AMdelimiter1);+ arr = str.split(AMdelimiter1);+ for (i=0; i<arr.length; i++) // this is a problem ************+ arr[i]=arr[i].replace(/AMescape1/g,AMdelimiter1);+ }+ if (arr.length>1 || mtch) {+ if (!noMathML) {+ frg = strarr2docFrag(arr,n.nodeType==8,latex);+ var len = frg.childNodes.length;+ n.parentNode.replaceChild(frg,n);+ return len-1;+ } else return 0;+ }+ }+ } else return 0;+ } else if (n.nodeName!="math") {+ for (i=0; i<n.childNodes.length; i++)+ i += processNodeR(n.childNodes[i], linebreaks,latex);+ }+ return 0;+}++function AMprocessNode(n, linebreaks, spanclassAM) {+ var frag,st;+ if (spanclassAM!=null) {+ frag = document.getElementsByTagName("span")+ for (var i=0;i<frag.length;i++)+ if (frag[i].className == "AM") + processNodeR(frag[i],linebreaks,false);+ } else {+ try {+ st = n.innerHTML; // look for AMdelimiter on page+ } catch(err) {}+//alert(st)+ if (st==null || /amath\b|\\begin{a?math}/i.test(st) ||+ st.indexOf(AMdelimiter1+" ")!=-1 || st.slice(-1)==AMdelimiter1 ||+ st.indexOf(AMdelimiter1+"<")!=-1 || st.indexOf(AMdelimiter1+"\n")!=-1) {+ processNodeR(n,linebreaks,false);+ }+ }+/* if (isIE) { //needed to match size and font of formula to surrounding text+ frag = document.getElementsByTagName('math');+ for (var i=0;i<frag.length;i++) frag[i].update() //What is this?+ }*/+}++/*+LaTeXMathML.js+==============++Version 1.1, July 20, 2007 (c) modifications by Peter Jipsen++(changes: renamed global variables from AM... to LM... so that+LaTeXMathML and ASCIIMathML can be used simultaneously)++Previous header notice:+This file (Version 1.0), is due to Douglas Woodall, June 2006.+It contains JavaScript functions to convert (most simple) LaTeX+math notation to Presentation MathML. It was obtained by+downloading the file ASCIIMathML.js from+ http://www1.chapman.edu/~jipsen/mathml/asciimathdownload/+and modifying it so that it carries out ONLY those conversions+that would be carried out in LaTeX. A description of the original+file, with examples, can be found at+ www1.chapman.edu/~jipsen/mathml/asciimath.html+ ASCIIMathML: Math on the web for everyone++Here is the header notice from the original file:++ASCIIMathML.js+==============+This file contains JavaScript functions to convert ASCII math notation+to Presentation MathML. The conversion is done while the (X)HTML page+loads, and should work with Firefox/Mozilla/Netscape 7+ and Internet+Explorer 6+MathPlayer (http://www.dessci.com/en/products/mathplayer/).+Just add the next line to your (X)HTML page with this file in the same folder:+<script type="text/javascript" src="ASCIIMathML.js"></script>+This is a convenient and inexpensive solution for authoring MathML.++Version 1.4.7 Dec 15, 2005, (c) Peter Jipsen http://www.chapman.edu/~jipsen+Latest version at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML.js+For changes see http://www.chapman.edu/~jipsen/mathml/asciimathchanges.txt+If you use it on a webpage, please send the URL to jipsen@chapman.edu++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU Lesser General Public License as published by+the Free Software Foundation; either version 2.1 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 Lesser+General Public License (at http://www.gnu.org/license/lgpl.html)+for more details.++LaTeXMathML.js (ctd)+==============++Content between $...$ and $$...$$ is converted by this part of the file+*/++// all further global variables start with "LM"++// Commented out by DRW to prevent 1/2 turning into a 2-line fraction+// LMdiv = {input:"/", tag:"mfrac", output:"/", ttype:INFIX},+// Commented out by DRW so that " prints literally in equations+// LMquote = {input:"\"", tag:"mtext", output:"mbox", ttype:TEXT};++var LMsymbols = [+//Greek letters+{input:"\\alpha", tag:"mi", output:"\u03B1", ttype:CONST},+{input:"\\beta", tag:"mi", output:"\u03B2", ttype:CONST},+{input:"\\gamma", tag:"mi", output:"\u03B3", ttype:CONST},+{input:"\\delta", tag:"mi", output:"\u03B4", ttype:CONST},+{input:"\\epsilon", tag:"mi", output:"\u03B5", ttype:CONST},+{input:"\\varepsilon", tag:"mi", output:"\u025B", ttype:CONST},+{input:"\\zeta", tag:"mi", output:"\u03B6", ttype:CONST},+{input:"\\eta", tag:"mi", output:"\u03B7", ttype:CONST},+{input:"\\theta", tag:"mi", output:"\u03B8", ttype:CONST},+{input:"\\vartheta", tag:"mi", output:"\u03D1", ttype:CONST},+{input:"\\iota", tag:"mi", output:"\u03B9", ttype:CONST},+{input:"\\kappa", tag:"mi", output:"\u03BA", ttype:CONST},+{input:"\\lambda", tag:"mi", output:"\u03BB", ttype:CONST},+{input:"\\mu", tag:"mi", output:"\u03BC", ttype:CONST},+{input:"\\nu", tag:"mi", output:"\u03BD", ttype:CONST},+{input:"\\xi", tag:"mi", output:"\u03BE", ttype:CONST},+{input:"\\pi", tag:"mi", output:"\u03C0", ttype:CONST},+{input:"\\varpi", tag:"mi", output:"\u03D6", ttype:CONST},+{input:"\\rho", tag:"mi", output:"\u03C1", ttype:CONST},+{input:"\\varrho", tag:"mi", output:"\u03F1", ttype:CONST},+{input:"\\varsigma", tag:"mi", output:"\u03C2", ttype:CONST},+{input:"\\sigma", tag:"mi", output:"\u03C3", ttype:CONST},+{input:"\\tau", tag:"mi", output:"\u03C4", ttype:CONST},+{input:"\\upsilon", tag:"mi", output:"\u03C5", ttype:CONST},+{input:"\\phi", tag:"mi", output:"\u03C6", ttype:CONST},+{input:"\\varphi", tag:"mi", output:"\u03D5", ttype:CONST},+{input:"\\chi", tag:"mi", output:"\u03C7", ttype:CONST},+{input:"\\psi", tag:"mi", output:"\u03C8", ttype:CONST},+{input:"\\omega", tag:"mi", output:"\u03C9", ttype:CONST},+{input:"\\Gamma", tag:"mo", output:"\u0393", ttype:CONST},+{input:"\\Delta", tag:"mo", output:"\u0394", ttype:CONST},+{input:"\\Theta", tag:"mo", output:"\u0398", ttype:CONST},+{input:"\\Lambda", tag:"mo", output:"\u039B", ttype:CONST},+{input:"\\Xi", tag:"mo", output:"\u039E", ttype:CONST},+{input:"\\Pi", tag:"mo", output:"\u03A0", ttype:CONST},+{input:"\\Sigma", tag:"mo", output:"\u03A3", ttype:CONST},+{input:"\\Upsilon", tag:"mo", output:"\u03A5", ttype:CONST},+{input:"\\Phi", tag:"mo", output:"\u03A6", ttype:CONST},+{input:"\\Psi", tag:"mo", output:"\u03A8", ttype:CONST},+{input:"\\Omega", tag:"mo", output:"\u03A9", ttype:CONST},++//fractions+{input:"\\frac12", tag:"mo", output:"\u00BD", ttype:CONST},+{input:"\\frac14", tag:"mo", output:"\u00BC", ttype:CONST},+{input:"\\frac34", tag:"mo", output:"\u00BE", ttype:CONST},+{input:"\\frac13", tag:"mo", output:"\u2153", ttype:CONST},+{input:"\\frac23", tag:"mo", output:"\u2154", ttype:CONST},+{input:"\\frac15", tag:"mo", output:"\u2155", ttype:CONST},+{input:"\\frac25", tag:"mo", output:"\u2156", ttype:CONST},+{input:"\\frac35", tag:"mo", output:"\u2157", ttype:CONST},+{input:"\\frac45", tag:"mo", output:"\u2158", ttype:CONST},+{input:"\\frac16", tag:"mo", output:"\u2159", ttype:CONST},+{input:"\\frac56", tag:"mo", output:"\u215A", ttype:CONST},+{input:"\\frac18", tag:"mo", output:"\u215B", ttype:CONST},+{input:"\\frac38", tag:"mo", output:"\u215C", ttype:CONST},+{input:"\\frac58", tag:"mo", output:"\u215D", ttype:CONST},+{input:"\\frac78", tag:"mo", output:"\u215E", ttype:CONST},++//binary operation symbols+{input:"\\pm", tag:"mo", output:"\u00B1", ttype:CONST},+{input:"\\mp", tag:"mo", output:"\u2213", ttype:CONST},+{input:"\\triangleleft",tag:"mo", output:"\u22B2", ttype:CONST},+{input:"\\triangleright",tag:"mo",output:"\u22B3", ttype:CONST},+{input:"\\cdot", tag:"mo", output:"\u22C5", ttype:CONST},+{input:"\\star", tag:"mo", output:"\u22C6", ttype:CONST},+{input:"\\ast", tag:"mo", output:"\u002A", ttype:CONST},+{input:"\\times", tag:"mo", output:"\u00D7", ttype:CONST},+{input:"\\div", tag:"mo", output:"\u00F7", ttype:CONST},+{input:"\\circ", tag:"mo", output:"\u2218", ttype:CONST},+//{input:"\\bullet", tag:"mo", output:"\u2219", ttype:CONST},+{input:"\\bullet", tag:"mo", output:"\u2022", ttype:CONST},+{input:"\\oplus", tag:"mo", output:"\u2295", ttype:CONST},+{input:"\\ominus", tag:"mo", output:"\u2296", ttype:CONST},+{input:"\\otimes", tag:"mo", output:"\u2297", ttype:CONST},+{input:"\\bigcirc", tag:"mo", output:"\u25CB", ttype:CONST},+{input:"\\oslash", tag:"mo", output:"\u2298", ttype:CONST},+{input:"\\odot", tag:"mo", output:"\u2299", ttype:CONST},+{input:"\\land", tag:"mo", output:"\u2227", ttype:CONST},+{input:"\\wedge", tag:"mo", output:"\u2227", ttype:CONST},+{input:"\\lor", tag:"mo", output:"\u2228", ttype:CONST},+{input:"\\vee", tag:"mo", output:"\u2228", ttype:CONST},+{input:"\\cap", tag:"mo", output:"\u2229", ttype:CONST},+{input:"\\cup", tag:"mo", output:"\u222A", ttype:CONST},+{input:"\\sqcap", tag:"mo", output:"\u2293", ttype:CONST},+{input:"\\sqcup", tag:"mo", output:"\u2294", ttype:CONST},+{input:"\\uplus", tag:"mo", output:"\u228E", ttype:CONST},+{input:"\\amalg", tag:"mo", output:"\u2210", ttype:CONST},+{input:"\\bigtriangleup",tag:"mo",output:"\u25B3", ttype:CONST},+{input:"\\bigtriangledown",tag:"mo",output:"\u25BD", ttype:CONST},+{input:"\\dag", tag:"mo", output:"\u2020", ttype:CONST},+{input:"\\dagger", tag:"mo", output:"\u2020", ttype:CONST},+{input:"\\ddag", tag:"mo", output:"\u2021", ttype:CONST},+{input:"\\ddagger", tag:"mo", output:"\u2021", ttype:CONST},+{input:"\\lhd", tag:"mo", output:"\u22B2", ttype:CONST},+{input:"\\rhd", tag:"mo", output:"\u22B3", ttype:CONST},+{input:"\\unlhd", tag:"mo", output:"\u22B4", ttype:CONST},+{input:"\\unrhd", tag:"mo", output:"\u22B5", ttype:CONST},+++//BIG Operators+{input:"\\sum", tag:"mo", output:"\u2211", ttype:UNDEROVER},+{input:"\\prod", tag:"mo", output:"\u220F", ttype:UNDEROVER},+{input:"\\bigcap", tag:"mo", output:"\u22C2", ttype:UNDEROVER},+{input:"\\bigcup", tag:"mo", output:"\u22C3", ttype:UNDEROVER},+{input:"\\bigwedge", tag:"mo", output:"\u22C0", ttype:UNDEROVER},+{input:"\\bigvee", tag:"mo", output:"\u22C1", ttype:UNDEROVER},+{input:"\\bigsqcap", tag:"mo", output:"\u2A05", ttype:UNDEROVER},+{input:"\\bigsqcup", tag:"mo", output:"\u2A06", ttype:UNDEROVER},+{input:"\\coprod", tag:"mo", output:"\u2210", ttype:UNDEROVER},+{input:"\\bigoplus", tag:"mo", output:"\u2A01", ttype:UNDEROVER},+{input:"\\bigotimes", tag:"mo", output:"\u2A02", ttype:UNDEROVER},+{input:"\\bigodot", tag:"mo", output:"\u2A00", ttype:UNDEROVER},+{input:"\\biguplus", tag:"mo", output:"\u2A04", ttype:UNDEROVER},+{input:"\\int", tag:"mo", output:"\u222B", ttype:CONST},+{input:"\\oint", tag:"mo", output:"\u222E", ttype:CONST},++//binary relation symbols+{input:":=", tag:"mo", output:":=", ttype:CONST},+{input:"\\lt", tag:"mo", output:"<", ttype:CONST},+{input:"\\gt", tag:"mo", output:">", ttype:CONST},+{input:"\\ne", tag:"mo", output:"\u2260", ttype:CONST},+{input:"\\neq", tag:"mo", output:"\u2260", ttype:CONST},+{input:"\\le", tag:"mo", output:"\u2264", ttype:CONST},+{input:"\\leq", tag:"mo", output:"\u2264", ttype:CONST},+{input:"\\leqslant", tag:"mo", output:"\u2264", ttype:CONST},+{input:"\\ge", tag:"mo", output:"\u2265", ttype:CONST},+{input:"\\geq", tag:"mo", output:"\u2265", ttype:CONST},+{input:"\\geqslant", tag:"mo", output:"\u2265", ttype:CONST},+{input:"\\equiv", tag:"mo", output:"\u2261", ttype:CONST},+{input:"\\ll", tag:"mo", output:"\u226A", ttype:CONST},+{input:"\\gg", tag:"mo", output:"\u226B", ttype:CONST},+{input:"\\doteq", tag:"mo", output:"\u2250", ttype:CONST},+{input:"\\prec", tag:"mo", output:"\u227A", ttype:CONST},+{input:"\\succ", tag:"mo", output:"\u227B", ttype:CONST},+{input:"\\preceq", tag:"mo", output:"\u227C", ttype:CONST},+{input:"\\succeq", tag:"mo", output:"\u227D", ttype:CONST},+{input:"\\subset", tag:"mo", output:"\u2282", ttype:CONST},+{input:"\\supset", tag:"mo", output:"\u2283", ttype:CONST},+{input:"\\subseteq", tag:"mo", output:"\u2286", ttype:CONST},+{input:"\\supseteq", tag:"mo", output:"\u2287", ttype:CONST},+{input:"\\sqsubset", tag:"mo", output:"\u228F", ttype:CONST},+{input:"\\sqsupset", tag:"mo", output:"\u2290", ttype:CONST},+{input:"\\sqsubseteq", tag:"mo", output:"\u2291", ttype:CONST},+{input:"\\sqsupseteq", tag:"mo", output:"\u2292", ttype:CONST},+{input:"\\sim", tag:"mo", output:"\u223C", ttype:CONST},+{input:"\\simeq", tag:"mo", output:"\u2243", ttype:CONST},+{input:"\\approx", tag:"mo", output:"\u2248", ttype:CONST},+{input:"\\cong", tag:"mo", output:"\u2245", ttype:CONST},+{input:"\\Join", tag:"mo", output:"\u22C8", ttype:CONST},+{input:"\\bowtie", tag:"mo", output:"\u22C8", ttype:CONST},+{input:"\\in", tag:"mo", output:"\u2208", ttype:CONST},+{input:"\\ni", tag:"mo", output:"\u220B", ttype:CONST},+{input:"\\owns", tag:"mo", output:"\u220B", ttype:CONST},+{input:"\\propto", tag:"mo", output:"\u221D", ttype:CONST},+{input:"\\vdash", tag:"mo", output:"\u22A2", ttype:CONST},+{input:"\\dashv", tag:"mo", output:"\u22A3", ttype:CONST},+{input:"\\models", tag:"mo", output:"\u22A8", ttype:CONST},+{input:"\\perp", tag:"mo", output:"\u22A5", ttype:CONST},+{input:"\\smile", tag:"mo", output:"\u2323", ttype:CONST},+{input:"\\frown", tag:"mo", output:"\u2322", ttype:CONST},+{input:"\\asymp", tag:"mo", output:"\u224D", ttype:CONST},+{input:"\\notin", tag:"mo", output:"\u2209", ttype:CONST},++//matrices+{input:"\\begin{eqnarray}", output:"X", ttype:MATRIX, invisible:true},+{input:"\\begin{array}", output:"X", ttype:MATRIX, invisible:true},+{input:"\\\\", output:"}&{", ttype:DEFINITION},+{input:"\\end{eqnarray}", output:"}}", ttype:DEFINITION},+{input:"\\end{array}", output:"}}", ttype:DEFINITION},++//grouping and literal brackets -- ieval is for IE+{input:"\\big", tag:"mo", output:"X", atval:"1.2", ieval:"2.2", ttype:BIG},+{input:"\\Big", tag:"mo", output:"X", atval:"1.6", ieval:"2.6", ttype:BIG},+{input:"\\bigg", tag:"mo", output:"X", atval:"2.2", ieval:"3.2", ttype:BIG},+{input:"\\Bigg", tag:"mo", output:"X", atval:"2.9", ieval:"3.9", ttype:BIG},+{input:"\\left", tag:"mo", output:"X", ttype:LEFTBRACKET},+{input:"\\right", tag:"mo", output:"X", ttype:RIGHTBRACKET},+{input:"{", output:"{", ttype:LEFTBRACKET, invisible:true},+{input:"}", output:"}", ttype:RIGHTBRACKET, invisible:true},++{input:"(", tag:"mo", output:"(", atval:"1", ttype:STRETCHY},+{input:"[", tag:"mo", output:"[", atval:"1", ttype:STRETCHY},+{input:"\\lbrack", tag:"mo", output:"[", atval:"1", ttype:STRETCHY},+{input:"\\{", tag:"mo", output:"{", atval:"1", ttype:STRETCHY},+{input:"\\lbrace", tag:"mo", output:"{", atval:"1", ttype:STRETCHY},+{input:"\\langle", tag:"mo", output:"\u2329", atval:"1", ttype:STRETCHY},+{input:"\\lfloor", tag:"mo", output:"\u230A", atval:"1", ttype:STRETCHY},+{input:"\\lceil", tag:"mo", output:"\u2308", atval:"1", ttype:STRETCHY},++// rtag:"mi" causes space to be inserted before a following sin, cos, etc.+// (see function LMparseExpr() )+{input:")", tag:"mo",output:")", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"]", tag:"mo",output:"]", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\rbrack",tag:"mo",output:"]", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\}", tag:"mo",output:"}", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\rbrace",tag:"mo",output:"}", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\rangle",tag:"mo",output:"\u232A", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\rfloor",tag:"mo",output:"\u230B", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\rceil", tag:"mo",output:"\u2309", rtag:"mi",atval:"1",ttype:STRETCHY},++// "|", "\\|", "\\vert" and "\\Vert" modified later: lspace = rspace = 0em+{input:"|", tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},+{input:"\\|", tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},+{input:"\\vert", tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},+{input:"\\Vert", tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},+{input:"\\mid", tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},+{input:"\\parallel", tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},+{input:"/", tag:"mo", output:"/", atval:"1.01", ttype:STRETCHY},+{input:"\\backslash", tag:"mo", output:"\u2216", atval:"1", ttype:STRETCHY},+{input:"\\setminus", tag:"mo", output:"\\", ttype:CONST},++//miscellaneous symbols+{input:"\\!", tag:"mspace", atname:"width", atval:"-0.167em", ttype:SPACE},+{input:"\\,", tag:"mspace", atname:"width", atval:"0.167em", ttype:SPACE},+{input:"\\>", tag:"mspace", atname:"width", atval:"0.222em", ttype:SPACE},+{input:"\\:", tag:"mspace", atname:"width", atval:"0.222em", ttype:SPACE},+{input:"\\;", tag:"mspace", atname:"width", atval:"0.278em", ttype:SPACE},+{input:"~", tag:"mspace", atname:"width", atval:"0.333em", ttype:SPACE},+{input:"\\quad", tag:"mspace", atname:"width", atval:"1em", ttype:SPACE},+{input:"\\qquad", tag:"mspace", atname:"width", atval:"2em", ttype:SPACE},+//{input:"{}", tag:"mo", output:"\u200B", ttype:CONST}, // zero-width+{input:"\\prime", tag:"mo", output:"\u2032", ttype:CONST},+{input:"'", tag:"mo", output:"\u02B9", ttype:CONST},+{input:"''", tag:"mo", output:"\u02BA", ttype:CONST},+{input:"'''", tag:"mo", output:"\u2034", ttype:CONST},+{input:"''''", tag:"mo", output:"\u2057", ttype:CONST},+{input:"\\ldots", tag:"mo", output:"\u2026", ttype:CONST},+{input:"\\cdots", tag:"mo", output:"\u22EF", ttype:CONST},+{input:"\\vdots", tag:"mo", output:"\u22EE", ttype:CONST},+{input:"\\ddots", tag:"mo", output:"\u22F1", ttype:CONST},+{input:"\\forall", tag:"mo", output:"\u2200", ttype:CONST},+{input:"\\exists", tag:"mo", output:"\u2203", ttype:CONST},+{input:"\\Re", tag:"mo", output:"\u211C", ttype:CONST},+{input:"\\Im", tag:"mo", output:"\u2111", ttype:CONST},+{input:"\\aleph", tag:"mo", output:"\u2135", ttype:CONST},+{input:"\\hbar", tag:"mo", output:"\u210F", ttype:CONST},+{input:"\\ell", tag:"mo", output:"\u2113", ttype:CONST},+{input:"\\wp", tag:"mo", output:"\u2118", ttype:CONST},+{input:"\\emptyset", tag:"mo", output:"\u2205", ttype:CONST},+{input:"\\infty", tag:"mo", output:"\u221E", ttype:CONST},+{input:"\\surd", tag:"mo", output:"\\sqrt{}", ttype:DEFINITION},+{input:"\\partial", tag:"mo", output:"\u2202", ttype:CONST},+{input:"\\nabla", tag:"mo", output:"\u2207", ttype:CONST},+{input:"\\triangle", tag:"mo", output:"\u25B3", ttype:CONST},+{input:"\\therefore", tag:"mo", output:"\u2234", ttype:CONST},+{input:"\\angle", tag:"mo", output:"\u2220", ttype:CONST},+//{input:"\\\\ ", tag:"mo", output:"\u00A0", ttype:CONST},+{input:"\\diamond", tag:"mo", output:"\u22C4", ttype:CONST},+//{input:"\\Diamond", tag:"mo", output:"\u25CA", ttype:CONST},+{input:"\\Diamond", tag:"mo", output:"\u25C7", ttype:CONST},+{input:"\\neg", tag:"mo", output:"\u00AC", ttype:CONST},+{input:"\\lnot", tag:"mo", output:"\u00AC", ttype:CONST},+{input:"\\bot", tag:"mo", output:"\u22A5", ttype:CONST},+{input:"\\top", tag:"mo", output:"\u22A4", ttype:CONST},+{input:"\\square", tag:"mo", output:"\u25AB", ttype:CONST},+{input:"\\Box", tag:"mo", output:"\u25A1", ttype:CONST},+{input:"\\wr", tag:"mo", output:"\u2240", ttype:CONST},++//standard functions+//Note UNDEROVER *must* have tag:"mo" to work properly+{input:"\\arccos", tag:"mi", output:"arccos", ttype:UNARY, func:true},+{input:"\\arcsin", tag:"mi", output:"arcsin", ttype:UNARY, func:true},+{input:"\\arctan", tag:"mi", output:"arctan", ttype:UNARY, func:true},+{input:"\\arg", tag:"mi", output:"arg", ttype:UNARY, func:true},+{input:"\\cos", tag:"mi", output:"cos", ttype:UNARY, func:true},+{input:"\\cosh", tag:"mi", output:"cosh", ttype:UNARY, func:true},+{input:"\\cot", tag:"mi", output:"cot", ttype:UNARY, func:true},+{input:"\\coth", tag:"mi", output:"coth", ttype:UNARY, func:true},+{input:"\\csc", tag:"mi", output:"csc", ttype:UNARY, func:true},+{input:"\\deg", tag:"mi", output:"deg", ttype:UNARY, func:true},+{input:"\\det", tag:"mi", output:"det", ttype:UNARY, func:true},+{input:"\\dim", tag:"mi", output:"dim", ttype:UNARY, func:true}, //CONST?+{input:"\\exp", tag:"mi", output:"exp", ttype:UNARY, func:true},+{input:"\\gcd", tag:"mi", output:"gcd", ttype:UNARY, func:true}, //CONST?+{input:"\\hom", tag:"mi", output:"hom", ttype:UNARY, func:true},+{input:"\\inf", tag:"mo", output:"inf", ttype:UNDEROVER},+{input:"\\ker", tag:"mi", output:"ker", ttype:UNARY, func:true},+{input:"\\lg", tag:"mi", output:"lg", ttype:UNARY, func:true},+{input:"\\lim", tag:"mo", output:"lim", ttype:UNDEROVER},+{input:"\\liminf", tag:"mo", output:"liminf", ttype:UNDEROVER},+{input:"\\limsup", tag:"mo", output:"limsup", ttype:UNDEROVER},+{input:"\\ln", tag:"mi", output:"ln", ttype:UNARY, func:true},+{input:"\\log", tag:"mi", output:"log", ttype:UNARY, func:true},+{input:"\\max", tag:"mo", output:"max", ttype:UNDEROVER},+{input:"\\min", tag:"mo", output:"min", ttype:UNDEROVER},+{input:"\\Pr", tag:"mi", output:"Pr", ttype:UNARY, func:true},+{input:"\\sec", tag:"mi", output:"sec", ttype:UNARY, func:true},+{input:"\\sin", tag:"mi", output:"sin", ttype:UNARY, func:true},+{input:"\\sinh", tag:"mi", output:"sinh", ttype:UNARY, func:true},+{input:"\\sup", tag:"mo", output:"sup", ttype:UNDEROVER},+{input:"\\tan", tag:"mi", output:"tan", ttype:UNARY, func:true},+{input:"\\tanh", tag:"mi", output:"tanh", ttype:UNARY, func:true},++//arrows+{input:"\\gets", tag:"mo", output:"\u2190", ttype:CONST},+{input:"\\leftarrow", tag:"mo", output:"\u2190", ttype:CONST},+{input:"\\to", tag:"mo", output:"\u2192", ttype:CONST},+{input:"\\rightarrow", tag:"mo", output:"\u2192", ttype:CONST},+{input:"\\leftrightarrow", tag:"mo", output:"\u2194", ttype:CONST},+{input:"\\uparrow", tag:"mo", output:"\u2191", ttype:CONST},+{input:"\\downarrow", tag:"mo", output:"\u2193", ttype:CONST},+{input:"\\updownarrow", tag:"mo", output:"\u2195", ttype:CONST},+{input:"\\Leftarrow", tag:"mo", output:"\u21D0", ttype:CONST},+{input:"\\Rightarrow", tag:"mo", output:"\u21D2", ttype:CONST},+{input:"\\Leftrightarrow", tag:"mo", output:"\u21D4", ttype:CONST},+{input:"\\iff", tag:"mo", output:"~\\Longleftrightarrow~", ttype:DEFINITION},+{input:"\\Uparrow", tag:"mo", output:"\u21D1", ttype:CONST},+{input:"\\Downarrow", tag:"mo", output:"\u21D3", ttype:CONST},+{input:"\\Updownarrow", tag:"mo", output:"\u21D5", ttype:CONST},+{input:"\\mapsto", tag:"mo", output:"\u21A6", ttype:CONST},+{input:"\\longleftarrow", tag:"mo", output:"\u2190", ttype:LONG},+{input:"\\longrightarrow", tag:"mo", output:"\u2192", ttype:LONG},+{input:"\\longleftrightarrow", tag:"mo", output:"\u2194", ttype:LONG},+{input:"\\Longleftarrow", tag:"mo", output:"\u21D0", ttype:LONG},+{input:"\\Longrightarrow", tag:"mo", output:"\u21D2", ttype:LONG},+{input:"\\implies", tag:"mo", output:"\u21D2", ttype:LONG},+{input:"\\Longleftrightarrow", tag:"mo", output:"\u21D4", ttype:LONG},+{input:"\\longmapsto", tag:"mo", output:"\u21A6", ttype:CONST},+ // disaster if LONG++//commands with argument++{input:"\\sqrt", tag:"msqrt", output:"sqrt", ttype:UNARY},+{input:"\\root", tag:"mroot", output:"root", ttype:BINARY},+{input:"\\frac", tag:"mfrac", output:"/", ttype:BINARY},+{input:"\\stackrel", tag:"mover", output:"stackrel", ttype:BINARY},+{input:"\\atop", tag:"mfrac", output:"", ttype:INFIX},+{input:"\\choose", tag:"mfrac", output:"", ttype:INFIX},+{input:"_", tag:"msub", output:"_", ttype:INFIX},+{input:"^", tag:"msup", output:"^", ttype:INFIX},+{input:"\\mathrm", tag:"mtext", output:"text", ttype:TEXT},+{input:"\\mbox", tag:"mtext", output:"mbox", ttype:TEXT},++//diacritical marks+{input:"\\acute", tag:"mover", output:"\u00B4", ttype:UNARY, acc:true},+//{input:"\\acute", tag:"mover", output:"\u0317", ttype:UNARY, acc:true},+//{input:"\\acute", tag:"mover", output:"\u0301", ttype:UNARY, acc:true},+//{input:"\\grave", tag:"mover", output:"\u0300", ttype:UNARY, acc:true},+//{input:"\\grave", tag:"mover", output:"\u0316", ttype:UNARY, acc:true},+{input:"\\grave", tag:"mover", output:"\u0060", ttype:UNARY, acc:true},+{input:"\\breve", tag:"mover", output:"\u02D8", ttype:UNARY, acc:true},+{input:"\\check", tag:"mover", output:"\u02C7", ttype:UNARY, acc:true},+{input:"\\dot", tag:"mover", output:".", ttype:UNARY, acc:true},+{input:"\\ddot", tag:"mover", output:"..", ttype:UNARY, acc:true},+//{input:"\\ddot", tag:"mover", output:"\u00A8", ttype:UNARY, acc:true},+{input:"\\mathring", tag:"mover", output:"\u00B0", ttype:UNARY, acc:true},+{input:"\\vec", tag:"mover", output:"\u20D7", ttype:UNARY, acc:true},+{input:"\\overrightarrow",tag:"mover",output:"\u20D7", ttype:UNARY, acc:true},+{input:"\\overleftarrow",tag:"mover", output:"\u20D6", ttype:UNARY, acc:true},+{input:"\\hat", tag:"mover", output:"\u005E", ttype:UNARY, acc:true},+{input:"\\widehat", tag:"mover", output:"\u0302", ttype:UNARY, acc:true},+{input:"\\tilde", tag:"mover", output:"~", ttype:UNARY, acc:true},+//{input:"\\tilde", tag:"mover", output:"\u0303", ttype:UNARY, acc:true},+{input:"\\widetilde", tag:"mover", output:"\u02DC", ttype:UNARY, acc:true},+{input:"\\bar", tag:"mover", output:"\u203E", ttype:UNARY, acc:true},+{input:"\\overbrace", tag:"mover", output:"\u23B4", ttype:UNARY, acc:true},+{input:"\\overline", tag:"mover", output:"\u00AF", ttype:UNARY, acc:true},+{input:"\\underbrace", tag:"munder", output:"\u23B5", ttype:UNARY, acc:true},+{input:"\\underline", tag:"munder", output:"\u00AF", ttype:UNARY, acc:true},+//{input:"underline", tag:"munder", output:"\u0332", ttype:UNARY, acc:true},++//typestyles and fonts+{input:"\\displaystyle",tag:"mstyle",atname:"displaystyle",atval:"true", ttype:UNARY},+{input:"\\textstyle",tag:"mstyle",atname:"displaystyle",atval:"false", ttype:UNARY},+{input:"\\scriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"1", ttype:UNARY},+{input:"\\scriptscriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"2", ttype:UNARY},+{input:"\\textrm", tag:"mstyle", output:"\\mathrm", ttype: DEFINITION},+{input:"\\mathbf", tag:"mstyle", atname:"mathvariant", atval:"bold", ttype:UNARY},+{input:"\\textbf", tag:"mstyle", atname:"mathvariant", atval:"bold", ttype:UNARY},+{input:"\\mathit", tag:"mstyle", atname:"mathvariant", atval:"italic", ttype:UNARY},+{input:"\\textit", tag:"mstyle", atname:"mathvariant", atval:"italic", ttype:UNARY},+{input:"\\mathtt", tag:"mstyle", atname:"mathvariant", atval:"monospace", ttype:UNARY},+{input:"\\texttt", tag:"mstyle", atname:"mathvariant", atval:"monospace", ttype:UNARY},+{input:"\\mathsf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", ttype:UNARY},+{input:"\\mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", ttype:UNARY, codes:AMbbb},+{input:"\\mathcal",tag:"mstyle", atname:"mathvariant", atval:"script", ttype:UNARY, codes:AMcal},+{input:"\\mathfrak",tag:"mstyle",atname:"mathvariant", atval:"fraktur",ttype:UNARY, codes:AMfrk}+];++var LMnames = []; //list of input symbols++function LMremoveCharsAndBlanks(str,n) {+//remove n characters and any following blanks+ var st;+ st = str.slice(n);+ for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);+ return st.slice(i);+}++function LMgetSymbol(str) {+//return maximal initial substring of str that appears in names+//return null if there is none+ var k = 0; //new pos+ var j = 0; //old pos+ var mk; //match pos+ var st;+ var tagst;+ var match = "";+ var more = true;+ for (var i=1; i<=str.length && more; i++) {+ st = str.slice(0,i); //initial substring of length i+ j = k;+ k = position(LMnames, st, j);+ if (k<LMnames.length && str.slice(0,LMnames[k].length)==LMnames[k]){+ match = LMnames[k];+ mk = k;+ i = match.length;+ }+ more = k<LMnames.length && str.slice(0,LMnames[k].length)>=LMnames[k];+ }+ LMpreviousSymbol=LMcurrentSymbol;+ if (match!=""){+ LMcurrentSymbol=LMsymbols[mk].ttype;+ return LMsymbols[mk];+ }+ LMcurrentSymbol=CONST;+ k = 1;+ st = str.slice(0,1); //take 1 character+ if ("0"<=st && st<="9") tagst = "mn";+ else tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");+/*+// Commented out by DRW (not fully understood, but probably to do with+// use of "/" as an INFIX version of "\\frac", which we don't want):+//}+//if (st=="-" && LMpreviousSymbol==INFIX) {+// LMcurrentSymbol = INFIX; //trick "/" into recognizing "-" on second parse+// return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};+//}+*/+ return {input:st, tag:tagst, output:st, ttype:CONST};+}+++/*Parsing ASCII math expressions with the following grammar+v ::= [A-Za-z] | greek letters | numbers | other constant symbols+u ::= sqrt | text | bb | other unary symbols for font commands+b ::= frac | root | stackrel binary symbols+l ::= { | \left left brackets+r ::= } | \right right brackets+S ::= v | lEr | uS | bSS Simple expression+I ::= S_S | S^S | S_S^S | S Intermediate expression+E ::= IE | I/I Expression+Each terminal symbol is translated into a corresponding mathml node.*/++var LMpreviousSymbol,LMcurrentSymbol;++function LMparseSexpr(str) { //parses str and returns [node,tailstr,(node)tag]+ var symbol, node, result, result2, i, st,// rightvert = false,+ newFrag = document.createDocumentFragment();+ str = LMremoveCharsAndBlanks(str,0);+ symbol = LMgetSymbol(str); //either a token or a bracket or empty+ if (symbol == null || symbol.ttype == RIGHTBRACKET)+ return [null,str,null];+ if (symbol.ttype == DEFINITION) {+ str = symbol.output+LMremoveCharsAndBlanks(str,symbol.input.length);+ symbol = LMgetSymbol(str);+ if (symbol == null || symbol.ttype == RIGHTBRACKET)+ return [null,str,null];+ }+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ switch (symbol.ttype) {+ case SPACE:+ node = createMmlNode(symbol.tag);+ node.setAttribute(symbol.atname,symbol.atval);+ return [node,str,symbol.tag];+ case UNDEROVER:+ if (isIE) {+ if (symbol.input.substr(0,4) == "\\big") { // botch for missing symbols+ str = "\\"+symbol.input.substr(4)+str; // make \bigcup = \cup etc.+ symbol = LMgetSymbol(str);+ symbol.ttype = UNDEROVER;+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ }+ }+ return [createMmlNode(symbol.tag,+ document.createTextNode(symbol.output)),str,symbol.tag];+ case CONST:+ var output = symbol.output;+ if (isIE) {+ if (symbol.input == "'")+ output = "\u2032";+ else if (symbol.input == "''")+ output = "\u2033";+ else if (symbol.input == "'''")+ output = "\u2033\u2032";+ else if (symbol.input == "''''")+ output = "\u2033\u2033";+ else if (symbol.input == "\\square")+ output = "\u25A1"; // same as \Box+ else if (symbol.input.substr(0,5) == "\\frac") {+ // botch for missing fractions+ var denom = symbol.input.substr(6,1);+ if (denom == "5" || denom == "6") {+ str = symbol.input.replace(/\\frac/,"\\frac ")+str;+ return [node,str,symbol.tag];+ }+ }+ }+ node = createMmlNode(symbol.tag,document.createTextNode(output));+ return [node,str,symbol.tag];+ case LONG: // added by DRW+ node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));+ node.setAttribute("minsize","1.5");+ node.setAttribute("maxsize","1.5");+ node = createMmlNode("mover",node);+ node.appendChild(createMmlNode("mspace"));+ return [node,str,symbol.tag];+ case STRETCHY: // added by DRW+ if (isIE && symbol.input == "\\backslash")+ symbol.output = "\\"; // doesn't expand, but then nor does "\u2216"+ node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));+ if (symbol.input == "|" || symbol.input == "\\vert" ||+ symbol.input == "\\|" || symbol.input == "\\Vert") {+ node.setAttribute("lspace","0em");+ node.setAttribute("rspace","0em");+ }+ node.setAttribute("maxsize",symbol.atval); // don't allow to stretch here+ if (symbol.rtag != null)+ return [node,str,symbol.rtag];+ else+ return [node,str,symbol.tag];+ case BIG: // added by DRW+ var atval = symbol.atval;+ if (isIE)+ atval = symbol.ieval;+ symbol = LMgetSymbol(str);+ if (symbol == null)+ return [null,str,null];+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));+ if (isIE) { // to get brackets to expand+ var space = createMmlNode("mspace");+ space.setAttribute("height",atval+"ex");+ node = createMmlNode("mrow",node);+ node.appendChild(space);+ } else { // ignored in IE+ node.setAttribute("minsize",atval);+ node.setAttribute("maxsize",atval);+ }+ return [node,str,symbol.tag];+ case LEFTBRACKET: //read (expr+)+ if (symbol.input == "\\left") { // left what?+ symbol = LMgetSymbol(str);+ if (symbol != null) {+ if (symbol.input == ".")+ symbol.invisible = true;+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ }+ }+ result = LMparseExpr(str,true,false);+ if (symbol==null ||+ (typeof symbol.invisible == "boolean" && symbol.invisible))+ node = createMmlNode("mrow",result[0]);+ else {+ node = createMmlNode("mo",document.createTextNode(symbol.output));+ node = createMmlNode("mrow",node);+ node.appendChild(result[0]);+ }+ return [node,result[1],result[2]];+ case MATRIX: //read (expr+)+ if (symbol.input == "\\begin{array}") {+ var mask = "";+ symbol = LMgetSymbol(str);+ str = LMremoveCharsAndBlanks(str,0);+ if (symbol == null)+ mask = "l";+ else {+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ if (symbol.input != "{")+ mask = "l";+ else do {+ symbol = LMgetSymbol(str);+ if (symbol != null) {+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ if (symbol.input != "}")+ mask = mask+symbol.input;+ }+ } while (symbol != null && symbol.input != "" && symbol.input != "}");+ }+ result = LMparseExpr("{"+str,true,true);+// if (result[0]==null) return [createMmlNode("mo",+// document.createTextNode(symbol.input)),str];+ node = createMmlNode("mtable",result[0]);+ mask = mask.replace(/l/g,"left ");+ mask = mask.replace(/r/g,"right ");+ mask = mask.replace(/c/g,"center ");+ node.setAttribute("columnalign",mask);+ node.setAttribute("displaystyle","false");+ if (isIE)+ return [node,result[1],null];+// trying to get a *little* bit of space around the array+// (IE already includes it)+ var lspace = createMmlNode("mspace");+ lspace.setAttribute("width","0.167em");+ var rspace = createMmlNode("mspace");+ rspace.setAttribute("width","0.167em");+ var node1 = createMmlNode("mrow",lspace);+ node1.appendChild(node);+ node1.appendChild(rspace);+ return [node1,result[1],null];+ } else { // eqnarray+ result = LMparseExpr("{"+str,true,true);+ node = createMmlNode("mtable",result[0]);+ if (isIE)+ node.setAttribute("columnspacing","0.25em"); // best in practice?+ else+ node.setAttribute("columnspacing","0.167em"); // correct (but ignored?)+ node.setAttribute("columnalign","right center left");+ node.setAttribute("displaystyle","true");+ node = createMmlNode("mrow",node);+ return [node,result[1],null];+ }+ case TEXT:+ if (str.charAt(0)=="{") i=str.indexOf("}");+ else i = 0;+ if (i==-1)+ i = str.length;+ st = str.slice(1,i);+ if (st.charAt(0) == " ") {+ node = createMmlNode("mspace");+ node.setAttribute("width","0.33em"); // was 1ex+ newFrag.appendChild(node);+ }+ newFrag.appendChild(+ createMmlNode(symbol.tag,document.createTextNode(st)));+ if (st.charAt(st.length-1) == " ") {+ node = createMmlNode("mspace");+ node.setAttribute("width","0.33em"); // was 1ex+ newFrag.appendChild(node);+ }+ str = LMremoveCharsAndBlanks(str,i+1);+ return [createMmlNode("mrow",newFrag),str,null];+ case UNARY:+ result = LMparseSexpr(str);+ if (result[0]==null) return [createMmlNode(symbol.tag,+ document.createTextNode(symbol.output)),str];+ if (typeof symbol.func == "boolean" && symbol.func) { // functions hack+ st = str.charAt(0);+// if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {+ if (st=="^" || st=="_" || st==",") {+ return [createMmlNode(symbol.tag,+ document.createTextNode(symbol.output)),str,symbol.tag];+ } else {+ node = createMmlNode("mrow",+ createMmlNode(symbol.tag,document.createTextNode(symbol.output)));+ if (isIE) {+ var space = createMmlNode("mspace");+ space.setAttribute("width","0.167em");+ node.appendChild(space);+ }+ node.appendChild(result[0]);+ return [node,result[1],symbol.tag];+ }+ }+ if (symbol.input == "\\sqrt") { // sqrt+ if (isIE) { // set minsize, for \surd+ var space = createMmlNode("mspace");+ space.setAttribute("height","1.2ex");+ space.setAttribute("width","0em"); // probably no effect+ node = createMmlNode(symbol.tag,result[0])+// node.setAttribute("minsize","1"); // ignored+// node = createMmlNode("mrow",node); // hopefully unnecessary+ node.appendChild(space);+ return [node,result[1],symbol.tag];+ } else+ return [createMmlNode(symbol.tag,result[0]),result[1],symbol.tag];+ } else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent+ node = createMmlNode(symbol.tag,result[0]);+ var output = symbol.output;+ if (isIE) {+ if (symbol.input == "\\hat")+ output = "\u0302";+ else if (symbol.input == "\\widehat")+ output = "\u005E";+ else if (symbol.input == "\\bar")+ output = "\u00AF";+ else if (symbol.input == "\\grave")+ output = "\u0300";+ else if (symbol.input == "\\tilde")+ output = "\u0303";+ }+ var node1 = createMmlNode("mo",document.createTextNode(output));+ if (symbol.input == "\\vec" || symbol.input == "\\check")+ // don't allow to stretch+ node1.setAttribute("maxsize","1.2");+ // why doesn't "1" work? \vec nearly disappears in firefox+ if (isIE && symbol.input == "\\bar")+ node1.setAttribute("maxsize","0.5");+ if (symbol.input == "\\underbrace" || symbol.input == "\\underline")+ node1.setAttribute("accentunder","true");+ else+ node1.setAttribute("accent","true");+ node.appendChild(node1);+ if (symbol.input == "\\overbrace" || symbol.input == "\\underbrace")+ node.ttype = UNDEROVER;+ return [node,result[1],symbol.tag];+ } else { // font change or displaystyle command+ if (!isIE && typeof symbol.codes != "undefined") {+ for (i=0; i<result[0].childNodes.length; i++)+ if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {+ st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:+ result[0].childNodes[i].firstChild.nodeValue);+ var newst = [];+ for (var j=0; j<st.length; j++)+ if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst ++ String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);+ else newst = newst + st.charAt(j);+ if (result[0].nodeName=="mi")+ result[0]=createMmlNode("mo").+ appendChild(document.createTextNode(newst));+ else result[0].replaceChild(createMmlNode("mo").+ appendChild(document.createTextNode(newst)),result[0].childNodes[i]);+ }+ }+ node = createMmlNode(symbol.tag,result[0]);+ node.setAttribute(symbol.atname,symbol.atval);+ if (symbol.input == "\\scriptstyle" ||+ symbol.input == "\\scriptscriptstyle")+ node.setAttribute("displaystyle","false");+ return [node,result[1],symbol.tag];+ }+ case BINARY:+ result = LMparseSexpr(str);+ if (result[0]==null) return [createMmlNode("mo",+ document.createTextNode(symbol.input)),str,null];+ result2 = LMparseSexpr(result[1]);+ if (result2[0]==null) return [createMmlNode("mo",+ document.createTextNode(symbol.input)),str,null];+ if (symbol.input=="\\root" || symbol.input=="\\stackrel")+ newFrag.appendChild(result2[0]);+ newFrag.appendChild(result[0]);+ if (symbol.input=="\\frac") newFrag.appendChild(result2[0]);+ return [createMmlNode(symbol.tag,newFrag),result2[1],symbol.tag];+ case INFIX:+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ return [createMmlNode("mo",document.createTextNode(symbol.output)),+ str,symbol.tag];+ default:+ return [createMmlNode(symbol.tag, //its a constant+ document.createTextNode(symbol.output)),str,symbol.tag];+ }+}++function LMparseIexpr(str) {+ var symbol, sym1, sym2, node, result, tag, underover;+ str = LMremoveCharsAndBlanks(str,0);+ sym1 = LMgetSymbol(str);+ result = LMparseSexpr(str);+ node = result[0];+ str = result[1];+ tag = result[2];+ symbol = LMgetSymbol(str);+ if (symbol.ttype == INFIX) {+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ result = LMparseSexpr(str);+ if (result[0] == null) // show box in place of missing argument+ result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));+ str = result[1];+ tag = result[2];+ if (symbol.input == "_" || symbol.input == "^") {+ sym2 = LMgetSymbol(str);+ tag = null; // no space between x^2 and a following sin, cos, etc.+// This is for \underbrace and \overbrace+ underover = ((sym1.ttype == UNDEROVER) || (node.ttype == UNDEROVER));+// underover = (sym1.ttype == UNDEROVER);+ if (symbol.input == "_" && sym2.input == "^") {+ str = LMremoveCharsAndBlanks(str,sym2.input.length);+ var res2 = LMparseSexpr(str);+ str = res2[1];+ tag = res2[2]; // leave space between x_1^2 and a following sin etc.+ node = createMmlNode((underover?"munderover":"msubsup"),node);+ node.appendChild(result[0]);+ node.appendChild(res2[0]);+ } else if (symbol.input == "_") {+ node = createMmlNode((underover?"munder":"msub"),node);+ node.appendChild(result[0]);+ } else {+ node = createMmlNode((underover?"mover":"msup"),node);+ node.appendChild(result[0]);+ }+ node = createMmlNode("mrow",node); // so sum does not stretch+ } else {+ node = createMmlNode(symbol.tag,node);+ if (symbol.input == "\\atop" || symbol.input == "\\choose")+ node.setAttribute("linethickness","0ex");+ node.appendChild(result[0]);+ if (symbol.input == "\\choose")+ node = createMmlNode("mfenced",node);+ }+ }+ return [node,str,tag];+}++function LMparseExpr(str,rightbracket,matrix) {+ var symbol, node, result, i, tag,+ newFrag = document.createDocumentFragment();+ do {+ str = LMremoveCharsAndBlanks(str,0);+ result = LMparseIexpr(str);+ node = result[0];+ str = result[1];+ tag = result[2];+ symbol = LMgetSymbol(str);+ if (node!=undefined) {+ if ((tag == "mn" || tag == "mi") && symbol!=null &&+ typeof symbol.func == "boolean" && symbol.func) {+ // Add space before \sin in 2\sin x or x\sin x+ var space = createMmlNode("mspace");+ space.setAttribute("width","0.167em");+ node = createMmlNode("mrow",node);+ node.appendChild(space);+ }+ newFrag.appendChild(node);+ }+ } while ((symbol.ttype != RIGHTBRACKET)+ && symbol!=null && symbol.output!="");+ tag = null;+ if (symbol.ttype == RIGHTBRACKET) {+ if (symbol.input == "\\right") { // right what?+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ symbol = LMgetSymbol(str);+ if (symbol != null && symbol.input == ".")+ symbol.invisible = true;+ if (symbol != null)+ tag = symbol.rtag;+ }+ if (symbol!=null)+ str = LMremoveCharsAndBlanks(str,symbol.input.length); // ready to return+ var len = newFrag.childNodes.length;+ if (matrix &&+ len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&+ newFrag.childNodes[len-2].nodeName == "mo" &&+ newFrag.childNodes[len-2].firstChild.nodeValue == "&") { //matrix+ var pos = []; // positions of ampersands+ var m = newFrag.childNodes.length;+ for (i=0; matrix && i<m; i=i+2) {+ pos[i] = [];+ node = newFrag.childNodes[i];+ for (var j=0; j<node.childNodes.length; j++)+ if (node.childNodes[j].firstChild.nodeValue=="&")+ pos[i][pos[i].length]=j;+ }+ var row, frag, n, k, table = document.createDocumentFragment();+ for (i=0; i<m; i=i+2) {+ row = document.createDocumentFragment();+ frag = document.createDocumentFragment();+ node = newFrag.firstChild; // <mrow> -&-&...&-&- </mrow>+ n = node.childNodes.length;+ k = 0;+ for (j=0; j<n; j++) {+ if (typeof pos[i][k] != "undefined" && j==pos[i][k]){+ node.removeChild(node.firstChild); //remove &+ row.appendChild(createMmlNode("mtd",frag));+ k++;+ } else frag.appendChild(node.firstChild);+ }+ row.appendChild(createMmlNode("mtd",frag));+ if (newFrag.childNodes.length>2) {+ newFrag.removeChild(newFrag.firstChild); //remove <mrow> </mrow>+ newFrag.removeChild(newFrag.firstChild); //remove <mo>&</mo>+ }+ table.appendChild(createMmlNode("mtr",row));+ }+ return [table,str];+ }+ if (typeof symbol.invisible != "boolean" || !symbol.invisible) {+ node = createMmlNode("mo",document.createTextNode(symbol.output));+ newFrag.appendChild(node);+ }+ }+ return [newFrag,str,tag];+}++var tcnt = 0, dcnt = 0; //theorem and definition counters++function simpleLaTeXformatting(st) {+ st = st.replace(/\$\$((.|\n)*?)\$\$/g,"<p align=\"center\">$\\displaystyle{$1}$</p>");+ st = st.replace(/\\begin{(theorem|lemma|proposition|corollary)}((.|\n)*?)\\end{\1}/g,function(r,s,t){tcnt++; return "<b>"+s.charAt(0).toUpperCase()+s.slice(1)+" "+tcnt+".</b> <i>"+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")+"</i>"});+ st = st.replace(/\\begin{(definition|example|remark|problem|exercise|conjecture|solution)}((.|\n)*?)\\end{\1}/g,function(r,s,t){dcnt++; return "<b>"+s.charAt(0).toUpperCase()+s.slice(1)+" "+dcnt+".</b> "+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")});+ st = st.replace(/\\begin{proof}((.|\n)*?)\\end{proof}/g,function(s,t){return "<i>Proof:</i> "+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")+" □"});+ st = st.replace(/\\emph{(.*?)}/g,"<em>$1</em>");+ st = st.replace(/\\textbf{(.*?)}/g,"<b>$1</b>");+ st = st.replace(/\\cite{(.*?)}/g,"[$1]");+ st = st.replace(/\\chapter{(.*?)}/g,"<h2>$1</h2>");+ st = st.replace(/\\section{(.*?)}(\s*<\/?(br|p)\s?\/?>)?/g,"<h3>$1</h3>");+ st = st.replace(/\\subsection{((.|\n)*?)}/g,"<h4>$1</h4>");+ st = st.replace(/\\begin{itemize}(\s*<\/?(br|p)\s?\/?>)?/g,"<ul>");+ st = st.replace(/\\item\s((.|\n)*?)(?=(\\item|\\end))/g,"<li>$1</li>");+ st = st.replace(/\\end{itemize}(\s*<\/?(br|p)\s?\/?>)?/g,"</ul>");+ st = st.replace(/\\begin{enumerate}(\s*<\/?(br|p)\s?\/?>)?/g,"<ol>");+ st = st.replace(/\\end{enumerate}(\s*<\/?(br|p)\s?\/?>)?/g,"</ol>");+ st = st.replace(/\\item\[(.*?)]{(.*?)}/g,"<dt>$1</dt><dd>$2</dd>");+ st = st.replace(/\\begin{description}/g,"<dl>");+ st = st.replace(/\\end{description}/g,"</dl>");+ st = st.replace(/\\newline\b/g,"<br/>");+ st = st.replace(/\\newpage\b/g,"<br style=\"page-break-after:always;\">");+ st = st.replace(/\\par\b/g,"<p> </p>");+ st = st.replace(/\\bigskip/g,"<p style=\"margin-bottom:0.5in\"> </p>");+ st = st.replace(/\\medskip/g,"<p style=\"margin-bottom:0.3in\"> </p>");+ st = st.replace(/\\smallskip/g,"<p style=\"margin-bottom:0.15in\"> </p>");+ st = st.replace(/\\begin{center}((.|\n)*?)\\end{center}/g,"<center>$1</center>");+ return st+}++function ASCIIandgraphformatting(st) {+ st = st.replace(/<sup>(.*?)<\/sup>(\s|(\S))/gi,"^{$1} $3");+//st = st.replace(/<\/?font.*?>/gi,""); // do this only in amath...endamath+ st = st.replace(/(Proof:)/g,"<i>$1</i>");+ st = st.replace(/QED/g," □");+ st = st.replace(/(\\?end{?a?math}?)/ig,"<span></span>$1");+ st = st.replace(/(\bamath\b|\\begin{a?math})/ig,"<span></span>$1");+ st = st.replace(/([>\n])(Theorem|Lemma|Proposition|Corollary|Definition|Example|Remark|Problem|Exercise|Conjecture|Solution)(:|\W\W?(\w|\s|-|\.)*?\W?:)/g,"$1<b>$2$3</b>");+ st = st.replace(/<embed\s+class\s?=\s?"?ASCIIsvg"?/gi,"<embed class=\"ASCIIsvg\" src=\""+dsvglocation+"d.svg\" wmode=\"transparent\"");+ st = st.replace(/(?:\\begin{a?graph}|\bagraph|\(:graph\s)((.|\n)*?)(?:\\end{a?graph}|enda?graph|:\))/g,function(s,t){return "<table><tr><td><div class=\"ASCIIsvg\"><embed class=\"ASCIIsvg\" src=\""+dsvglocation+"d.svg\" wmode=\"transparent\" script=\'"+t.replace(/<\/?(br|p|pre)\s?\/?>/gi,"\n")+"\'/></div></td></tr></table>"});+ st = st.replace(/insertASCIIMathCalculator/g,"<div class=\"ASCIIMathCalculator\"></div>");+//alert(dsvglocation)+ return st+}++function LMprocessNode(n) {+ var frag,st;+ try {+ st = n.innerHTML;+ } catch(err) {}+ var am = /amath\b|graph/i.test(st);+ if ((st==null || st.indexOf("\$ ")!=-1 || st.indexOf("\$<")!=-1 || + st.indexOf("\\begin")!=-1 || am || st.slice(-1)=="$" ||+ st.indexOf("\$\n")!=-1)&& !/edit-content|HTMLArea|wikiedit|wpTextbox1/.test(st)){+ if (!avoidinnerHTML && translateLaTeXformatting) + st = simpleLaTeXformatting(st);+ if (st!=null && am && !avoidinnerHTML) {+ st = ASCIIandgraphformatting(st);+ }+ st = st.replace(/%7E/g,"~"); // else PmWiki has url issues+//alert(st)+ if (!avoidinnerHTML) n.innerHTML = st;+ processNodeR(n,false,true);+ }+/* if (isIE) { //needed to match size and font of formula to surrounding text+ frag = document.getElementsByTagName('math');+ for (var i=0;i<frag.length;i++) frag[i].update() //is this really needed?+ }*/+}++/* ASCIIsvg.js+==============+JavaScript routines to dynamically generate Scalable Vector Graphics+using a mathematical xy-coordinate system (y increases upwards) and+very intuitive JavaScript commands (no programming experience required).+ASCIIsvg.js is good for learning math and illustrating online math texts.+Works with Internet Explorer+Adobe SVGviewer and SVG enabled Mozilla/Firefox.++Ver 1.2.9 July 31, 2007 (c) Peter Jipsen http://www.chapman.edu/~jipsen+Latest version at http://math.chapman.edu/~jipsen/math/pub/ASCIIsvg.js+If you use it on a webpage, please send the URL to jipsen@chapman.edu++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU Lesser General Public License as published by+the Free Software Foundation; either version 2.1 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 Lesser+General Public License (at http://www.gnu.org/license/lgpl.html) +for more details.*/++// you can change these+var checkIfSVGavailable = true;+var notifyIfNoSVG = true;+var alertIfNoSVG = false;+var noSVG = false;++// global defaults used if not specified by graph (you can change these)+var defaultwidth = 300; defaultheight = 200; // in pixels+var defaultxmin = -5.5; defaultxmax = 5.5; // in usercoords+var defaultborder = 0; border = defaultborder; // in pixel+var defaultstrokewidth = "1"; // default line width in pixel+var defaultstroke = "blue"; // default line color+var defaultstrokeopacity = 1; // transparent = 0, solid =1+var defaultstrokedasharray = null; // "10,10" gives 10px long dashes+var defaultfill = "none"; // default fill color+var defaultfillopacity = 1; // transparent = 0, solid =1+var defaultfontstyle = "normal"; // default text shape normal|italic|inherit+var defaultfontfamily = "times"; // default font times|ariel|helvetica|...+var defaultfontsize = "16"; // default size (scaled automatically)+var defaultfontweight = "normal";// normal|bold|bolder|lighter|100|...|900+var defaultfontstroke = "none"; // default font outline color+var defaultfontfill = "none"; // default font color+var defaultmarker = "none"; // "dot" | "arrow" | "+" | "-" | "|"+var defaultendpoints = ""; // "c-d" where c is <|o|* and d is >|o|*++// global values used for all pictures (you can change these)+var showcoordinates = true;+var markerstrokewidth = "1";+var markerstroke = "black";+var markerfill = "yellow";+var markersize = 4;+var arrowfill = stroke;+var dotradius = 4;+var ticklength = 4;+var axesstroke = "black";+var gridstroke = "grey";+var backgroundstyle = "fill-opacity:0; fill:white";+var singlelettersitalic = true;++// internal variables (probably no need to change these)+var picturepos = null; // position of picture relative to top of HTML page+var xunitlength; // in pixels, used to convert to user coordinates+var yunitlength; // in pixels+var origin = [0,0]; // in pixels (default is bottom left corner)+var above = "above"; // shorthands (to avoid typing quotes)+var below = "below";+var left = "left";+var right = "right";+var aboveleft = "aboveleft";+var aboveright = "aboveright";+var belowleft = "belowleft";+var belowright = "belowright";+var xmin, xmax, ymin, ymax, xscl, yscl, + xgrid, ygrid, xtick, ytick, initialized;+var strokewidth, strokedasharray, stroke, fill, strokeopacity, fillopacity;+var fontstyle, fontfamily, fontsize, fontweight, fontstroke, fontfill;+var marker, endpoints, dynamic = {};+var picture, svgpicture, doc, width, height;+var isIE = document.createElementNS==null;++//this is not used! var cpi = "\u03C0", ctheta = "\u03B8"; // character for pi, theta+var log = function(x) { return ln(x)/ln(10) };+var pi = Math.PI, e = Math.E, ln = Math.log, sqrt = Math.sqrt;+var floor = Math.floor, ceil = Math.ceil, abs = Math.abs;+var sin = Math.sin, cos = Math.cos, tan = Math.tan;+var arcsin = Math.asin, arccos = Math.acos, arctan = Math.atan;+var sec = function(x) { return 1/Math.cos(x) };+var csc = function(x) { return 1/Math.sin(x) };+var cot = function(x) { return 1/Math.tan(x) };+var arcsec = function(x) { return arccos(1/x) };+var arccsc = function(x) { return arcsin(1/x) };+var arccot = function(x) { return arctan(1/x) };+var sinh = function(x) { return (Math.exp(x)-Math.exp(-x))/2 };+var cosh = function(x) { return (Math.exp(x)+Math.exp(-x))/2 };+var tanh = + function(x) { return (Math.exp(x)-Math.exp(-x))/(Math.exp(x)+Math.exp(-x)) };+var sech = function(x) { return 1/cosh(x) };+var csch = function(x) { return 1/sinh(x) };+var coth = function(x) { return 1/tanh(x) };+var arcsinh = function(x) { return ln(x+Math.sqrt(x*x+1)) };+var arccosh = function(x) { return ln(x+Math.sqrt(x*x-1)) };+var arctanh = function(x) { return ln((1+x)/(1-x))/2 };+var sech = function(x) { return 1/cosh(x) };+var csch = function(x) { return 1/sinh(x) };+var coth = function(x) { return 1/tanh(x) };+var arcsech = function(x) { return arccosh(1/x) };+var arccsch = function(x) { return arcsinh(1/x) };+var arccoth = function(x) { return arctanh(1/x) };+var sign = function(x) { return (x==0?0:(x<0?-1:1)) };++function factorial(x,n) { // Factorial function+ if (n==null) n=1;+ if (Math.abs(x-Math.round(x*1000000)/1000000)<1e-15)+ x = Math.round(x*1000000)/1000000;+ if (x-Math.floor(x)!=0) return NaN;+ for (var i=x-n; i>0; i-=n) x*=i;+ return (x<0?NaN:(x==0?1:x));+}++function C(x,k) { // Binomial coefficient function+ var res=1;+ for (var i=0; i<k; i++) res*=(x-i)/(k-i);+ return res;+}++function chop(x,n) { // Truncate decimal number to n places after decimal point+ if (n==null) n=0;+ return Math.floor(x*Math.pow(10,n))/Math.pow(10,n);+}++function ran(a,b,n) { // Generate random number in [a,b] with n digits after .+ if (n==null) n=0;+ return chop((b+Math.pow(10,-n)-a)*Math.random()+a,n);+}++function myCreateElementSVG(t) {+ if (isIE) return doc.createElement(t);+ else return doc.createElementNS("http://www.w3.org/2000/svg",t);+}++function getElementsByClass(container, tagName, clsName){+ var list = new Array(0);+ var collection = container.getElementsByTagName(tagName);+ for(var i = 0; i < collection.length; i++)+ if(collection[i].className.slice(0,clsName.length)==clsName)+ list[list.length] = collection[i];+ return list;+}++function showobj(obj) {+ var st="", i;+ for (i in obj) + st += (obj.getAttribute(i)==null?"":" "+i+":"+obj.getAttribute(i));+ return st;+}++function findPos(obj) { // top-left corner of obj on HTML page in pixel+ var curleft = curtop = 0;+ if (obj.offsetParent) {+ curleft = obj.offsetLeft+ curtop = obj.offsetTop+ while (obj = obj.offsetParent) {+ curleft += obj.offsetLeft+ curtop += obj.offsetTop+//alert(showobj(obj)+[curleft,curtop])+ }+ }+ return [curleft,curtop];+}++function checkSVG(){+ if (navigator.appName.slice(0,8)=="Netscape") + if (window['SVGElement']) noSVG = null;+ else noSVG = true;+ else if (navigator.appName.slice(0,9)=="Microsoft")+ try {+ var oSVG=eval("new ActiveXObject('Adobe.SVGCtl.3');");+ noSVG = null;+ } catch (e) {+ noSVG = true;+ }+ else if (navigator.appName.slice(0,5)=="Opera") // works only for 9.50b1+ noSVG = null;+ else noSVG = true;+//noSVG = true; //uncomment to check+ if (noSVG && notifyIfNoSVG) {+ var msg = "To view the ASCIIsvg images use Internet Explorer + Adobe SVGviewer or Mozilla Firefox 2.0 or later."+ if (alertIfNoSVG)+ alert(msg);+ else return msg;+ }+}++function setText(st,id) { // add text to an existing node with given id+ var node = document.getElementById(id);+ if (node!=null)+ if (node.childNodes.length!=0) node.childNodes[0].nodeValue = st;+ else node.appendChild(document.createTextNode(st));+}++function getX(evt) { // return mouse x-coord in user coordinate system+ var svgroot = evt.target.parentNode;+ pos = findPos(svgroot.parentNode);+ return (evt.clientX+(isIE?0:window.pageXOffset)-pos[0]-svgroot.getAttribute("ox"))/parseFloat(svgroot.getAttribute("xunitlength"));+}++function getY(evt) { // return mouse y-coord in user coordinate system+ var svgroot = evt.target.parentNode;+ pos = findPos(svgroot.parentNode);+//alert(showobj(svgroot)+svgroot.getAttribute("mytop"))+ return (svgroot.getAttribute("height")-svgroot.getAttribute("oy")-(evt.clientY+(isIE?0:window.pageYOffset)-pos[1]))/parseFloat(svgroot.getAttribute("yunitlength"));+}++function translateandeval(src) { //modify user input to JavaScript syntax+ var errstr;+ // replace plot(f(x),...) with plot("f(x)",...) + src = src.replace(/plot\(\x20*([^\"f\[][^\n\r;]+?)\,/g,"plot\(\"$1\",");+ src = src.replace(/plot\(\x20*([^\"f\[][^\n\r;]+)\)/g,"plot(\"$1\")");++ // replace (expr,expr) by [expr,expr] where expr has no (,) in it+ src = src.replace(/([=[(,]\x20*)\(([-a-z0-9./+*]+?),([-a-z0-9./+*]+?)\)/g,"$1[$2,$3]");+//alert(src)+ // insert * between digit and letter e.g. 2x --> 2*x+ src = src.replace(/([0-9])([a-df-zA-Z]|e^)/g,"$1*$2");+ src = src.replace(/\)([\(0-9a-zA-Z])/g,"\)*$1");++ try {+ with (Math) eval(src); // here the svgpicture object is created+ } catch(err) {+ if (err!="wait") {+//alert(dsvglocation)+ if (typeof err=="object") + errstr = err.name+" "+err.message+" "+err.number+" "+err.description;+ else errstr = err;+ alert(errstr+"\n"+src)+ }+ }+}++var lastSlot = 0;++function drawPictures() { // main routine; called after webpage has loaded+ var src, id, dsvg, nd, node, ht, index, cols, arr, i, node2;+ var ASbody = document.getElementsByTagName("body")[0];+ pictures = getElementsByClass(ASbody,"embed","ASCIIsvg");+ var len = pictures.length;+ if(len==0) return;+ for (index = lastSlot; index < len+lastSlot; index++) {+ width = null; height = null; + xmin = null; xmax = null; ymin = null; ymax = null;+ xscl = null; xgrid = null; yscl = null; ygrid = null;+ initialized = false;+ picture = pictures[index-lastSlot]; // current picture object+ src = picture.getAttribute("script"); // get the ASCIIsvg code+ if (src==null) src = "";+ // insert "axes()" if not present ******** experimental+ if (!/axes\b|initPicture/.test(src)) {+ var i = 0;+ while (/((yscl|ymax|ymin|xscl|xmax|xmin|\bwidth|\bheight)\s*=\s*-?\d*(\d\.|\.\d|\d)\d*\s*;?)/.test(src.slice(i))) i++;+ src = (i==0?"axes(); "+src: src.slice(0,i)+src.slice(i).replace(/((scl|max|min|idth|eight)\s*=\s*-?\d*(\d\.|\.\d|\d)\d*\s*;?)/,"$1\naxes();"));+ }+ ht = picture.getAttribute("height");+ if (isIE) {+ picture.setAttribute("wmode","transparent");+//alert("*"+picture.getAttribute("src")+dsvglocation);+//adding d.svg dynamically greates problems in IE...+// if (picture.getAttribute("src")=="") picture.setAttribute("src",dsvglocation+"d.svg");+ }+ if (document.getElementById("picture"+(index+1)+"mml")==null) {+ picture.parentNode.style.position = "relative";+ node = createElementXHTML("div");+ node.style.position = "absolute";+ node.style.top = "0px";+ node.style.left = "0px";+ node.setAttribute("id","picture"+(index+1)+"mml");+ picture.parentNode.insertBefore(node,picture.nextSibling);+ }+ if (ht==null) ht ="";+// if (ht!="") defaultborder = 25;+ if (ht=="" || src=="") + if (document.getElementById("picture"+(index+1)+"input")==null) {+ node = createElementXHTML("textarea");+ arr = src.split("\n");+ cols = 0;+ for (i=0;i<arr.length;i++) cols = Math.max(cols,arr[i].length);+ node.setAttribute("rows",Math.min(10,arr.length)+1);+ node.setAttribute("cols",Math.max(Math.min(60,cols),20)+5);+// node.setAttribute("style","display:block");+ if (isIE) src = src.replace(/([^\r])\n/g,"$1\r");+ node.appendChild(document.createTextNode(src));+ if (src.indexOf("showcode()")==-1) node.style.display = "none";+ node.setAttribute("id","picture"+(index+1)+"input");+ picture.parentNode.insertBefore(node,picture.nextSibling);+ picture.parentNode.insertBefore(createElementXHTML("br"),node);+ node2 = createElementXHTML("button");+ node2.setAttribute("id","picture"+(index+1)+"button");+ if (isIE) node2.onclick = function() {updatePicture(this)};+ else node2.setAttribute("onclick","updatePicture(this)");+ node2.appendChild(document.createTextNode("Update"));+ if (src.indexOf("showcode()")==-1) node2.style.display = "none";+ picture.parentNode.insertBefore(node2,node);+// picture.parentNode.insertBefore(document.createTextNode("ASCII"),node);+ picture.parentNode.insertBefore(createElementXHTML("br"),node);+ } else src = document.getElementById("picture"+(index+1)+"input").value;+ id = picture.getAttribute("id");+ dsvg = picture.getAttribute("src");+ if (id == null || id == "") {+ id = "picture"+(index+1);+ picture.setAttribute("id",id);+ }+ translateandeval(src);+ }+ lastSlot+=len;+}++function setdefaults() { //called before each graph is evaluated+ strokewidth = defaultstrokewidth;+ stroke = defaultstroke;+ strokeopacity = defaultstrokeopacity;+ strokedasharray = defaultstrokedasharray;+ fill = defaultfill;+ fillopacity = defaultfillopacity;+ fontstyle = defaultfontstyle;+ fontfamily = defaultfontfamily;+ fontsize = defaultfontsize;+ fontweight = defaultfontweight;+ fontstroke = defaultfontstroke;+ fontfill = defaultfontfill;+ marker = defaultmarker;+ endpoints = defaultendpoints;+}++function switchTo(id) { // used by dynamic code to select appropriate graph+ if (id==undefined) return;+ var name = id;+ if (typeof name!="string") name = id.target.parentNode.getAttribute("name");+ picture = document.getElementById(name);+ width = picture.getAttribute("width")-0;+ height = picture.getAttribute("height")-0;+ setdefaults();+ if ((picture.nodeName == "EMBED" || picture.nodeName == "embed") && isIE) {+ svgpicture = picture.getSVGDocument().getElementById("root");+ doc = picture.getSVGDocument();+ } else {+ svgpicture = picture;+ doc = document;+ }+ xunitlength = parseFloat(svgpicture.getAttribute("xunitlength"));+ yunitlength = parseFloat(svgpicture.getAttribute("yunitlength"));+ xmin = parseFloat(svgpicture.getAttribute("xmin"));+ xmax = parseFloat(svgpicture.getAttribute("xmax"));+ ymin = parseFloat(svgpicture.getAttribute("ymin"));+ ymax = parseFloat(svgpicture.getAttribute("ymax"));+ origin = [svgpicture.getAttribute("ox")-0,svgpicture.getAttribute("oy")-0];+}++function updatePicture(obj) {+ var node, src, id, top, left;+ if (typeof obj=="object") id = obj.id.slice(0,-6);+ else id = (typeof obj=="string"?obj:"picture"+(obj+1));+ src = document.getElementById(id+"input").value;+ xmin = null; xmax = null; ymin = null; ymax = null;+ xscl = null; xgrid = null; yscl = null; ygrid = null;+ initialized = false;+ picture = document.getElementById(id);+ translateandeval(src)+}++function changepicturesize(evt,factor) {+ var obj = evt.target;+ var name = obj.parentNode.getAttribute("name");+ var pic = document.getElementById(name);+ var src = document.getElementById(name+"input").value;+ if (!/height/.test(src)) src = "height=0; "+src;+ if (!/width/.test(src)) src = "width=0; "+src;+ src = src.replace(/width\s*=\s*\d+/,"width="+(factor*(pic.getAttribute("width")-0)));+ src = src.replace(/height\s*=\s*\d+/,"height="+(factor*(pic.getAttribute("height")-0)));+ document.getElementById(name+"input").value = src;+//alert(getKey(evt.keycode))+ updatePicture(name);+}++function zoom(evt,factor) {+ switchTo(evt);+ var obj = evt.target;+ var name = obj.parentNode.getAttribute("name");+ var pic = document.getElementById(name);+ var src = document.getElementById(name+"input").value;+ var xlen = (xmax-xmin)/2;+ var ylen = (ymax-ymin)/2;+ var xcen = getX(evt), ycen = getY(evt);+ if (!/ymax/.test(src)) src = "ymax=0; "+src;+ if (!/ymin/.test(src)) src = "ymin=0; "+src;+ if (!/xmax/.test(src)) src = "xmax=0; "+src;+ if (!/xmin/.test(src)) src = "xmin=0; "+src;+ src = src.replace(/xmin\s*=\s*[-\d.e]+/,"xmin="+(xcen-factor*xlen));+ src = src.replace(/xmax\s*=\s*[-\d.e]+/,"xmax="+(xcen+factor*xlen));+ src = src.replace(/ymin\s*=\s*[-\d.e]+/,"ymin="+(ycen-factor*ylen));+ src = src.replace(/ymax\s*=\s*[-\d.e]+/,"ymax="+(ycen+factor*ylen));+ document.getElementById(name+"input").value = src;+ updatePicture(name);+}++var sinceFirstClick = 0; // ondblclick simulation from +var dblClkTimer; // http://www.enja.org/david/?cat=13 Thanks!+function timer() {+ if(sinceFirstClick<60) {+ sinceFirstClick++;+ setTimeout("timer()",10);+ } else {+ clearTimeout(dblClkTimer);+ dblClkTimer = "";+ }+}+function mClick(evt) {+ if(sinceFirstClick!=0) {+ if(sinceFirstClick <= 40) {+ if (evt.shiftKey) {+ if (evt.altKey) changepicturesize(evt,2);+ else zoom(evt,.5);+ } else if (evt.altKey) zoom(evt,2);//changepicturesize(evt,.5);+ else showHideCode(evt); // do this on dblclick+ clearTimeout(dblClkTimer);+ dblClkTimer = "";+ } else {+ clearTimeout(dblClkTimer);+ sinceFirstClick = 0;+ dblClkTimer = setTimeout("timer()",10);+ } + } else {+ sinceFirstClick = 0;+ dblClkTimer = setTimeout("timer()",10);+ }+}++function showHideCode(evt) { // called by onclick event+// if (evt.getDetail()==2) {//getDetail unfortunately not in Firefox+ var obj=evt.target;+ var name = obj.parentNode.getAttribute("name");+ var node = document.getElementById(name+"input");+ node.style.display = (node.style.display == "none"?"":"none");+ var node = document.getElementById(name+"button");+ node.style.display = (node.style.display == "none"?"":"none");+// }+}++function showcode() {} // do nothing++function setBorder(x) { border = x } //deprecate++function initPicture(x_min,x_max,y_min,y_max) { // set up the graph+// usually called by axes() or noaxes(), but can be used directly+ if (!initialized) {+ setdefaults();+ initialized = true;+ if (x_min!=null) xmin = x_min;+ if (x_max!=null) xmax = x_max;+ if (y_min!=null) ymin = y_min;+ if (y_max!=null) ymax = y_max;+ if (xmin==null) xmin = defaultxmin;+ if (xmax==null) xmax = defaultxmax;+ if (typeof xmin != "number" || typeof xmax != "number" || xmin >= xmax) + alert("Picture requires at least two numbers: xmin < xmax");+ else if (y_max != null && (typeof y_min != "number" || + typeof y_max != "number" || y_min >= y_max))+ alert("initPicture(xmin,xmax,ymin,ymax) requires numbers ymin < ymax");+ else {+ if (width==null) {+ width = picture.getAttribute("width");+ if (width==null || width=="") width=defaultwidth;+ }+ picture.setAttribute("width",width);+ if (height==null) { + height = picture.getAttribute("height");+ if (height==null || height=="") height=defaultheight;+ }+ picture.setAttribute("height",height);+ xunitlength = (width-2*border)/(xmax-xmin);+ yunitlength = xunitlength;+//alert(xmin+" "+xmax+" "+ymin+" "+ymax)+ if (ymin==null) {+ origin = [-xmin*xunitlength+border,height/2];+ ymin = -(height-2*border)/(2*yunitlength);+ ymax = -ymin;+ } else {+ if (ymax!=null) yunitlength = (height-2*border)/(ymax-ymin);+ else ymax = (height-2*border)/yunitlength + ymin;+ origin = [-xmin*xunitlength+border,-ymin*yunitlength+border];+ }+ if (isIE) {+ if (picture.FULLSCREEN==undefined) {+ setTimeout('drawPictures()',50);+ throw "wait";+ }+ svgpicture = picture.getSVGDocument().getElementById("root");+ if (svgpicture==null) {+ setTimeout('drawPictures()',50);+ throw "wait";+ }+ svgpicture = picture.getSVGDocument().getElementById("root");+ while (svgpicture.childNodes.length>0) + svgpicture.removeChild(svgpicture.lastChild); + svgpicture.setAttribute("width",width);+ svgpicture.setAttribute("height",height);+ svgpicture.setAttribute("name",picture.getAttribute("id"));+ doc = picture.getSVGDocument();+ } else {+ var qnode = document.createElementNS("http://www.w3.org/2000/svg","svg");+ qnode.setAttribute("id",picture.getAttribute("id"));+ qnode.setAttribute("name",picture.getAttribute("id"));+// qnode.setAttribute("style","display:inline");+ qnode.setAttribute("width",picture.getAttribute("width"));+ qnode.setAttribute("height",picture.getAttribute("height"));+ picturepos = findPos(picture);+// qnode.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink");+ if (picture.parentNode!=null) {+ picture.parentNode.replaceChild(qnode,picture);+ } else {+ svgpicture.parentNode.replaceChild(qnode,svgpicture);+ }+ svgpicture = qnode;+ doc = document;+ }+ var nd = document.getElementById(picture.getAttribute("id")+"mml");+ if (nd!=null) // clear out MathML layer+ while (nd.childNodes.length>0) nd.removeChild(nd.lastChild); + svgpicture.setAttribute("xunitlength",xunitlength);+ svgpicture.setAttribute("yunitlength",yunitlength);+ svgpicture.setAttribute("xmin",xmin);+ svgpicture.setAttribute("xmax",xmax);+ svgpicture.setAttribute("ymin",ymin);+ svgpicture.setAttribute("ymax",ymax);+ svgpicture.setAttribute("ox",origin[0]);+ svgpicture.setAttribute("oy",origin[1]);+ var node = myCreateElementSVG("rect");+ node.setAttribute("x","0");+ node.setAttribute("y","0");+ node.setAttribute("width",width);+ node.setAttribute("height",height);+ node.setAttribute("style",backgroundstyle);+ svgpicture.appendChild(node);+ svgpicture.setAttribute("onmousemove","displayCoord(evt)");+ svgpicture.setAttribute("onmouseout","removeCoord(evt)");+ svgpicture.setAttribute("onclick","mClick(evt)");+ node = myCreateElementSVG("text"); // used for displayCoord+ node.appendChild(doc.createTextNode(" "));+ node.setAttribute("id","coords");+ svgpicture.appendChild(node);+ node = myCreateElementSVG("text"); // used for text display+ node.appendChild(doc.createTextNode(" "));+ node.setAttribute("id","coords");+ svgpicture.appendChild(node);+ border = defaultborder;+ }+ }+}++//////////////////////////user graphics commands start/////////////////////////++function line(p,q,id,endpts) { // segment connecting points p,q (coordinates in units)+ var node;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("path");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("d","M"+(p[0]*xunitlength+origin[0])+","++ (height-p[1]*yunitlength-origin[1])+" "++ (q[0]*xunitlength+origin[0])+","+(height-q[1]*yunitlength-origin[1]));+ node.setAttribute("stroke-width", strokewidth);+ if (strokedasharray!=null) + node.setAttribute("stroke-dasharray", strokedasharray);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+ if (marker=="dot" || marker=="arrowdot") {+ ASdot(p,markersize,markerstroke,markerfill);+ if (marker=="arrowdot") arrowhead(p,q);+ ASdot(q,markersize,markerstroke,markerfill);+ } else if (marker=="arrow") arrowhead(p,q);+ if (endpts==null && endpoints!="") endpts = endpoints;+ if (endpts!=null) {+ if (endpts.indexOf("<-") != -1) arrowhead(q,p);+ if (endpts.indexOf("o-") != -1) dot(p, "open");+ if (endpts.indexOf("*-") != -1) dot(p, "closed");+ if (endpts.indexOf("->") != -1) arrowhead(p,q);+ if (endpts.indexOf("-o") != -1) dot(q, "open");+ if (endpts.indexOf("-*") != -1) dot(q, "closed");+ }+}++function path(plist,id,c,endpts) {+ if (c==null) c="";+ var node, st, i;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("path");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ if (typeof plist == "string") st = plist;+ else {+ st = "M";+ st += (plist[0][0]*xunitlength+origin[0])+","++ (height-plist[0][1]*yunitlength-origin[1])+" "+c;+ for (i=1; i<plist.length; i++)+ st += (plist[i][0]*xunitlength+origin[0])+","++ (height-plist[i][1]*yunitlength-origin[1])+" ";+ }+ node.setAttribute("d", st);+ node.setAttribute("stroke-width", strokewidth);+ if (strokedasharray!=null) + node.setAttribute("stroke-dasharray", strokedasharray);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+ if (marker=="dot" || marker=="arrowdot")+ for (i=0; i<plist.length; i++)+ if (c!="C" && c!="T" || i!=1 && i!=2)+ ASdot(plist[i],markersize,markerstroke,markerfill);+ if (endpts==null && endpoints!="") endpts = endpoints;+ if (endpts!=null) {+ if (endpts.indexOf("<-") != -1) arrowhead(plist[1],plist[0]);+ if (endpts.indexOf("o-") != -1) dot(plist[0], "open");+ if (endpts.indexOf("*-") != -1) dot(plist[0], "closed");+ if (endpts.indexOf("->") != -1) arrowhead(plist[plist.length-2],plist[plist.length-1]);+ if (endpts.indexOf("-o") != -1) dot(plist[plist.length-1], "open");+ if (endpts.indexOf("-*") != -1) dot(plist[plist.length-1], "closed");+ }+}++function curve(plist,id,endpts) {+ path(plist,id,"T",endpts);+}++function vector(p,q,id) {+ line(p,q,id,"","->");+}++function circle(center,radius,id) { // coordinates in units+ var node;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("circle");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("cx",center[0]*xunitlength+origin[0]);+ node.setAttribute("cy",height-center[1]*yunitlength-origin[1]);+ node.setAttribute("r",radius*xunitlength);+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+}++function loop(p,d,id) { +// d is a direction vector e.g. [1,0] means loop starts in that direction+ if (d==null) d=[1,0];+ path([p,[p[0]+d[0],p[1]+d[1]],[p[0]-d[1],p[1]+d[0]],p],id,"C");+ if (marker=="arrow" || marker=="arrowdot") + arrowhead([p[0]+Math.cos(1.4)*d[0]-Math.sin(1.4)*d[1],+ p[1]+Math.sin(1.4)*d[0]+Math.cos(1.4)*d[1]],p);+}++function arc(start,end,radius,id,largearc) { // coordinates in units+ var node, v;+//alert([fill, stroke, origin, xunitlength, yunitlength, height])+ if (id!=null) node = doc.getElementById(id);+ if (largearc==null) largearc=0;+ if (radius==null) {+ v=[end[0]-start[0],end[1]-start[1]];+ radius = Math.sqrt(v[0]*v[0]+v[1]*v[1]);+ }+ if (node==null) {+ node = myCreateElementSVG("path");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("d","M"+(start[0]*xunitlength+origin[0])+","++ (height-start[1]*yunitlength-origin[1])+" A"+radius*xunitlength+","++ radius*yunitlength+" 0 "+largearc+",0 "+(end[0]*xunitlength+origin[0])+","++ (height-end[1]*yunitlength-origin[1]));+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+ if (marker=="arrow" || marker=="arrowdot") {+ u = [(end[1]-start[1])/4,(start[0]-end[0])/4];+ v = [(end[0]-start[0])/2,(end[1]-start[1])/2];+//alert([u,v])+ v = [start[0]+v[0]+u[0],start[1]+v[1]+u[1]];+ } else v=[start[0],start[1]];+ if (marker=="dot" || marker=="arrowdot") {+ ASdot(start,markersize,markerstroke,markerfill);+ if (marker=="arrowdot") arrowhead(v,end);+ ASdot(end,markersize,markerstroke,markerfill);+ } else if (marker=="arrow") arrowhead(v,end);+}++function sector(center,start,end,id) { // center,start,end should be isoceles+ var rx = start[0]-center[0], ry = start[1]-center[1];+ arc(start,end,Math.sqrt(rx*rx+ry*ry),id+"arc");+ path([end,center,start],id+"path");+}++function ellipse(center,rx,ry,id) { // coordinates in units+ var node;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("ellipse");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("cx",center[0]*xunitlength+origin[0]);+ node.setAttribute("cy",height-center[1]*yunitlength-origin[1]);+ node.setAttribute("rx",rx*xunitlength);+ node.setAttribute("ry",ry*yunitlength);+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+}++function triangle(p,q,r,id) {+ path([p,q,r,p],id)+}++function rect(p,q,id,rx,ry) { // opposite corners in units, rounded by radii+ var node;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("rect");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("x",p[0]*xunitlength+origin[0]);+ node.setAttribute("y",height-q[1]*yunitlength-origin[1]);+ node.setAttribute("width",(q[0]-p[0])*xunitlength);+ node.setAttribute("height",(q[1]-p[1])*yunitlength);+ if (rx!=null) node.setAttribute("rx",rx*xunitlength);+ if (ry!=null) node.setAttribute("ry",ry*yunitlength);+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+}++function text(p,st,pos,id,fontsty) {+ var dnode, node, dx = 0, dy = fontsize/3, str = st.toString();+ if (/(`|\$)/.test(str)) { // layer for ASCIIMathML and LaTeXMathML+ dnode = document.getElementById(svgpicture.getAttribute("name")+"mml");+ if (dnode!=null) {+ if (id!=null) node = document.getElementById(id);+ if (node==null) {+//alert(dnode.childNodes.length)+ node = createElementXHTML("div");+ node.setAttribute("id", id);+ node.style.position = "absolute";+ dnode.appendChild(node);+ }+ while (node.childNodes.length>0) node.removeChild(node.lastChild); + node.appendChild(document.createTextNode(str));+ if (/`/.test(str)) AMprocessNode(node); else LMprocessNode(node);+ dx = -node.offsetWidth/2;+ dy = -node.offsetHeight/2;+ if (pos!=null) {+ if (/above/.test(pos)) dy = -node.offsetHeight;+ if (/below/.test(pos)) dy = 0;+ if (/right/.test(pos)) dx = 0;+ if ( /left/.test(pos)) dx = -node.offsetWidth;+ }+ node.style.left = ""+(p[0]*xunitlength+origin[0]+dx)+"px";+ node.style.top = ""+(height-p[1]*yunitlength-origin[1]+dy)+"px";+ }+ return p;+ }+ var textanchor = "middle"; // regular text goes into SVG+ if (pos!=null) {+ if (/above/.test(pos)) dy = -fontsize/2;+ if (/below/.test(pos)) dy = fontsize-0;+ if (/right/.test(pos)) {textanchor = "start"; dx = fontsize/4;}+ if ( /left/.test(pos)) {textanchor = "end"; dx = -fontsize/4;}+ }+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("text");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ node.appendChild(doc.createTextNode(str));+ }+ while (node.childNodes.length>1) node.removeChild(node.lastChild); + node.lastChild.nodeValue = "\xA0"+str+"\xA0";+ node.setAttribute("x",p[0]*xunitlength+origin[0]+dx);+ node.setAttribute("y",height-p[1]*yunitlength-origin[1]+dy);+ node.setAttribute("font-style",(fontsty!=null?fontsty:+ (str.search(/^[a-zA-Z]$/)!=-1?"italic":fontstyle)));+ node.setAttribute("font-family",fontfamily);+ node.setAttribute("font-size",fontsize);+ node.setAttribute("font-weight",fontweight);+ node.setAttribute("text-anchor",textanchor);+ if (fontstroke!="none") node.setAttribute("stroke",fontstroke);+ if (fontfill!="none") node.setAttribute("fill",fontfill);+ return p;+}++function mtext(p,st,pos,fontsty,fontsz) { // method for updating text on an svg+// "this" is the text object or the svgpicture object+ var textanchor = "middle";+ var dx = 0; var dy = fontsize/3;+ if (pos!=null) {+ if (pos.slice(0,5)=="above") dy = -fontsize/2;+ if (pos.slice(0,5)=="below") dy = fontsize-0;+ if (pos.slice(0,5)=="right" || pos.slice(5,10)=="right") {+ textanchor = "start";+ dx = fontsize/2;+ }+ if (pos.slice(0,4)=="left" || pos.slice(5,9)=="left") {+ textanchor = "end";+ dx = -fontsize/2;+ }+ }+ var node = this;+ if (this.nodeName=="svg") {+ node = myCreateElementSVG("text");+ this.appendChild(node);+ node.appendChild(doc.createTextNode(st));+ }+ node.lastChild.nodeValue = st;+ node.setAttribute("x",p[0]+dx);+ node.setAttribute("y",p[1]+dy);+ node.setAttribute("font-style",(fontsty!=null?fontsty:fontstyle));+ node.setAttribute("font-family",fontfamily);+ node.setAttribute("font-size",(fontsz!=null?fontsz:fontsize));+ node.setAttribute("font-weight",fontweight);+ node.setAttribute("text-anchor",textanchor);+ if (fontstroke!="none") node.setAttribute("stroke",fontstroke);+ if (fontfill!="none") node.setAttribute("fill",fontfill);+}++function image(imgurl,p,w,h,id) { // not working yet+ var node;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("image");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("x",p[0]*xunitlength+origin[0]);+ node.setAttribute("y",height-p[1]*yunitlength-origin[1]);+ node.setAttribute("width",w);+ node.setAttribute("height",h);+ node.setAttribute("xlink:href", imgurl);+}++function ASdot(center,radius,s,f) { // coordinates in units, radius in pixel+ if (s==null) s = stroke; if (f==null) f = fill;+ var node = myCreateElementSVG("circle");+ node.setAttribute("cx",center[0]*xunitlength+origin[0]);+ node.setAttribute("cy",height-center[1]*yunitlength-origin[1]);+ node.setAttribute("r",radius);+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", s);+ node.setAttribute("fill", f);+ svgpicture.appendChild(node);+}++function dot(center, typ, label, pos, id) {+ var node;+ var cx = center[0]*xunitlength+origin[0];+ var cy = height-center[1]*yunitlength-origin[1];+ if (id!=null) node = doc.getElementById(id);+ if (typ=="+" || typ=="-" || typ=="|") {+ if (node==null) {+ node = myCreateElementSVG("path");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ if (typ=="+") {+ node.setAttribute("d",+ " M "+(cx-ticklength)+" "+cy+" L "+(cx+ticklength)+" "+cy++ " M "+cx+" "+(cy-ticklength)+" L "+cx+" "+(cy+ticklength));+ node.setAttribute("stroke-width", .5);+ node.setAttribute("stroke", axesstroke);+ } else {+ if (typ=="-") node.setAttribute("d",+ " M "+(cx-ticklength)+" "+cy+" L "+(cx+ticklength)+" "+cy);+ else node.setAttribute("d",+ " M "+cx+" "+(cy-ticklength)+" L "+cx+" "+(cy+ticklength));+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ }+ } else {+ if (node==null) {+ node = myCreateElementSVG("circle");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("cx",cx);+ node.setAttribute("cy",cy);+ node.setAttribute("r",dotradius);+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", (typ=="open"?"white":+ (typ=="closed"?stroke:markerfill)));+ }+ if (label!=null) + text(center,label,(pos==null?"below":pos),(id==null?id:id+"label"))+}++point = dot; //alternative name++function arrowhead(p,q) { // draw arrowhead at q (in units) add size param+ var up;+ var v = [p[0]*xunitlength+origin[0],height-p[1]*yunitlength-origin[1]];+ var w = [q[0]*xunitlength+origin[0],height-q[1]*yunitlength-origin[1]];+ var u = [w[0]-v[0],w[1]-v[1]];+ var d = Math.sqrt(u[0]*u[0]+u[1]*u[1]);+ if (d > 0.00000001) {+ u = [u[0]/d, u[1]/d];+ up = [-u[1],u[0]];+ var node = myCreateElementSVG("path");+ node.setAttribute("d","M "+(w[0]-15*u[0]-4*up[0])+" "++ (w[1]-15*u[1]-4*up[1])+" L "+(w[0]-3*u[0])+" "+(w[1]-3*u[1])+" L "++ (w[0]-15*u[0]+4*up[0])+" "+(w[1]-15*u[1]+4*up[1])+" z");+ node.setAttribute("stroke-width", markerstrokewidth);+ node.setAttribute("stroke", stroke); /*was markerstroke*/+ node.setAttribute("fill", stroke); /*was arrowfill*/+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+ svgpicture.appendChild(node); + }+}++function chopZ(st) {+ var k = st.indexOf(".");+ if (k==-1) return st;+ for (var i=st.length-1; i>k && st.charAt(i)=="0"; i--);+ if (i==k) i--;+ return st.slice(0,i+1);+}++function grid(dx,dy) { // for backward compatibility+ axes(dx,dy,null,dx,dy)+}++function noaxes() {+ if (!initialized) initPicture();+}++function axes(dx,dy,labels,gdx,gdy) {+//xscl=x is equivalent to xtick=x; xgrid=x; labels=true;+ var x, y, ldx, ldy, lx, ly, lxp, lyp, pnode, st;+ if (!initialized) initPicture();+ if (typeof dx=="string") { labels = dx; dx = null; }+ if (typeof dy=="string") { gdx = dy; dy = null; }+ if (xscl!=null) {dx = xscl; gdx = xscl; labels = dx}+ if (yscl!=null) {dy = yscl; gdy = yscl}+ if (xtick!=null) {dx = xtick}+ if (ytick!=null) {dy = ytick}+ dx = (dx==null?xunitlength:dx*xunitlength);+ dy = (dy==null?dx:dy*yunitlength);+ fontsize = Math.min(dx/2,dy/2,16); //alert(fontsize)+ ticklength = fontsize/4;+ if (xgrid!=null) gdx = xgrid;+ if (ygrid!=null) gdy = ygrid;+ if (gdx!=null) {+ gdx = (typeof gdx=="string"?dx:gdx*xunitlength);+ gdy = (gdy==null?dy:gdy*yunitlength);+ pnode = myCreateElementSVG("path");+ st="";+ for (x = origin[0]; x<width; x = x+gdx)+ st += " M"+x+",0"+" "+x+","+height;+ for (x = origin[0]-gdx; x>0; x = x-gdx)+ st += " M"+x+",0"+" "+x+","+height;+ for (y = height-origin[1]; y<height; y = y+gdy)+ st += " M0,"+y+" "+width+","+y;+ for (y = height-origin[1]-gdy; y>0; y = y-gdy)+ st += " M0,"+y+" "+width+","+y;+ pnode.setAttribute("d",st);+ pnode.setAttribute("stroke-width", .5);+ pnode.setAttribute("stroke", gridstroke);+ pnode.setAttribute("fill", fill);+ svgpicture.appendChild(pnode);+ }+ pnode = myCreateElementSVG("path");+ st="M0,"+(height-origin[1])+" "+width+","++ (height-origin[1])+" M"+origin[0]+",0 "+origin[0]+","+height;+ for (x = origin[0]+dx; x<width; x = x+dx)+ st += " M"+x+","+(height-origin[1]+ticklength)+" "+x+","++ (height-origin[1]-ticklength);+ for (x = origin[0]-dx; x>0; x = x-dx)+ st += " M"+x+","+(height-origin[1]+ticklength)+" "+x+","++ (height-origin[1]-ticklength);+ for (y = height-origin[1]+dy; y<height; y = y+dy)+ st += " M"+(origin[0]+ticklength)+","+y+" "+(origin[0]-ticklength)+","+y;+ for (y = height-origin[1]-dy; y>0; y = y-dy)+ st += " M"+(origin[0]+ticklength)+","+y+" "+(origin[0]-ticklength)+","+y;+ if (labels!=null) with (Math) {+ ldx = dx/xunitlength;+ ldy = dy/yunitlength;+ lx = (xmin>0 || xmax<0?xmin:0);+ ly = (ymin>0 || ymax<0?ymin:0);+ lxp = (ly==0?"below":"above");+ lyp = (lx==0?"left":"right");+ var ddx = floor(1.1-log(ldx)/log(10))+1;+ var ddy = floor(1.1-log(ldy)/log(10))+1;+ for (x = ldx; x<=xmax; x = x+ldx)+ text([x,ly],chopZ(x.toFixed(ddx)),lxp);+ for (x = -ldx; xmin<=x; x = x-ldx)+ text([x,ly],chopZ(x.toFixed(ddx)),lxp);+ for (y = ldy; y<=ymax; y = y+ldy)+ text([lx,y],chopZ(y.toFixed(ddy)),lyp);+ for (y = -ldy; ymin<=y; y = y-ldy)+ text([lx,y],chopZ(y.toFixed(ddy)),lyp);+ }+ fontsize = defaultfontsize;+ pnode.setAttribute("d",st);+ pnode.setAttribute("stroke-width", .5);+ pnode.setAttribute("stroke", axesstroke);+ pnode.setAttribute("fill", fill);+ pnode.setAttribute("stroke-opacity", strokeopacity);+ pnode.setAttribute("fill-opacity", fillopacity);+ svgpicture.appendChild(pnode);+}++function mathjs(st) {+ //translate a math formula to js function notation+ // a^b --> pow(a,b)+ // na --> n*a+ // (...)d --> (...)*d+ // n! --> factorial(n)+ // sin^-1 --> arcsin etc.+ //while ^ in string, find term on left and right+ //slice and concat new formula string+ st = st.replace(/\s/g,"");+ if (st.indexOf("^-1")!=-1) {+ st = st.replace(/sin\^-1/g,"arcsin");+ st = st.replace(/cos\^-1/g,"arccos");+ st = st.replace(/tan\^-1/g,"arctan");+ st = st.replace(/sec\^-1/g,"arcsec");+ st = st.replace(/csc\^-1/g,"arccsc");+ st = st.replace(/cot\^-1/g,"arccot");+ st = st.replace(/sinh\^-1/g,"arcsinh");+ st = st.replace(/cosh\^-1/g,"arccosh");+ st = st.replace(/tanh\^-1/g,"arctanh");+ st = st.replace(/sech\^-1/g,"arcsech");+ st = st.replace(/csch\^-1/g,"arccsch");+ st = st.replace(/coth\^-1/g,"arccoth");+ }+ st = st.replace(/^e$/g,"(Math.E)");+ st = st.replace(/^e([^a-zA-Z])/g,"(Math.E)$1");+ st = st.replace(/([^a-zA-Z])e/g,"$1(Math.E)");+// st = st.replace(/([^a-zA-Z])e([^a-zA-Z])/g,"$1(Math.E)$2");+ st = st.replace(/([0-9])([\(a-zA-Z])/g,"$1*$2");+ st = st.replace(/\)([\(0-9a-zA-Z])/g,"\)*$1");+ var i,j,k, ch, nested;+ while ((i=st.indexOf("^"))!=-1) {+ //find left argument+ if (i==0) return "Error: missing argument";+ j = i-1;+ ch = st.charAt(j);+ if (ch>="0" && ch<="9") {// look for (decimal) number+ j--;+ while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;+ if (ch==".") {+ j--;+ while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;+ }+ } else if (ch==")") {// look for matching opening bracket and function name+ nested = 1;+ j--;+ while (j>=0 && nested>0) {+ ch = st.charAt(j);+ if (ch=="(") nested--;+ else if (ch==")") nested++;+ j--;+ }+ while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")+ j--;+ } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable+ j--;+ while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")+ j--;+ } else { + return "Error: incorrect syntax in "+st+" at position "+j;+ }+ //find right argument+ if (i==st.length-1) return "Error: missing argument";+ k = i+1;+ ch = st.charAt(k);+ if (ch>="0" && ch<="9" || ch=="-") {// look for signed (decimal) number+ k++;+ while (k<st.length && (ch=st.charAt(k))>="0" && ch<="9") k++;+ if (ch==".") {+ k++;+ while (k<st.length && (ch=st.charAt(k))>="0" && ch<="9") k++;+ }+ } else if (ch=="(") {// look for matching closing bracket and function name+ nested = 1;+ k++;+ while (k<st.length && nested>0) {+ ch = st.charAt(k);+ if (ch=="(") nested++;+ else if (ch==")") nested--;+ k++;+ }+ } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable+ k++;+ while (k<st.length && (ch=st.charAt(k))>="a" && ch<="z" ||+ ch>="A" && ch<="Z") k++;+ } else { + return "Error: incorrect syntax in "+st+" at position "+k;+ }+ st = st.slice(0,j+1)+"Math.pow("+st.slice(j+1,i)+","+st.slice(i+1,k)+")"++ st.slice(k);+ }+ while ((i=st.indexOf("!"))!=-1) {+ //find left argument+ if (i==0) return "Error: missing argument";+ j = i-1;+ ch = st.charAt(j);+ if (ch>="0" && ch<="9") {// look for (decimal) number+ j--;+ while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;+ if (ch==".") {+ j--;+ while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;+ }+ } else if (ch==")") {// look for matching opening bracket and function name+ nested = 1;+ j--;+ while (j>=0 && nested>0) {+ ch = st.charAt(j);+ if (ch=="(") nested--;+ else if (ch==")") nested++;+ j--;+ }+ while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")+ j--;+ } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable+ j--;+ while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")+ j--;+ } else { + return "Error: incorrect syntax in "+st+" at position "+j;+ }+ st = st.slice(0,j+1)+"factorial("+st.slice(j+1,i)+")"+st.slice(i+1);+ }+ return st;+}++function plot(fun,x_min,x_max,points,id,endpts) {+ var pth = [];+ var f = function(x) { return x }, g = fun;+ var name = null;+ if (typeof fun=="string") + eval("g = function(x){ with(Math) return "+mathjs(fun)+" }");+ else if (typeof fun=="object") {+ eval("f = function(t){ with(Math) return "+mathjs(fun[0])+" }");+ eval("g = function(t){ with(Math) return "+mathjs(fun[1])+" }");+ }+ if (typeof x_min=="string") { name = x_min; x_min = xmin }+ else name = id;+ var min = (x_min==null?xmin:x_min);+ var max = (x_max==null?xmax:x_max);+ var inc = max-min-0.000001*(max-min);+ inc = (points==null?inc/200:inc/points);+ var gt;+//alert(typeof g(min))+ for (var t = min; t <= max; t += inc) {+ gt = g(t);+ if (!(isNaN(gt)||Math.abs(gt)=="Infinity")) pth[pth.length] = [f(t), gt];+ }+ path(pth,name,null,endpts);+ return pth;+}++// make polar plot++// make Riemann sums++function slopefield(fun,dx,dy) {+ var g = fun;+ if (typeof fun=="string") + eval("g = function(x,y){ with(Math) return "+mathjs(fun)+" }");+ var gxy,x,y,u,v,dz;+ if (dx==null) dx=1;+ if (dy==null) dy=1;+ dz = Math.sqrt(dx*dx+dy*dy)/6;+ var x_min = Math.ceil(xmin/dx);+ var y_min = Math.ceil(ymin/dy);+ for (x = x_min; x <= xmax; x += dx)+ for (y = y_min; y <= ymax; y += dy) {+ gxy = g(x,y);+ if (!isNaN(gxy)) {+ if (Math.abs(gxy)=="Infinity") {u = 0; v = dz;}+ else {u = dz/Math.sqrt(1+gxy*gxy); v = gxy*u;}+ line([x-u,y-v],[x+u,y+v]);+ }+ }+}++///////////////////////user graphics commands end here/////////////////////////++function show_props(obj) {+ var result = "";+ for (var i=0; i< obj.childNodes.length; i++)+ result += obj.childNodes.item(i) + "\n";+ return result;+}++function displayCoord(evt) {+ if (showcoordinates) {+ var svgroot = evt.target.parentNode;+ var nl = svgroot.childNodes;+ for (var i=0; i<nl.length && nl.item(i).nodeName!="text"; i++);+ var cnode = nl.item(i);+ cnode.mtext = mtext;+ cnode.mtext([svgroot.getAttribute("width")-(-7),svgroot.getAttribute("height")-7],"("+getX(evt).toFixed(2)+", "+getY(evt).toFixed(2)+")", "left", "", "11");+/* var dnode = nl.item(i+1);+ dnode.mtext = mtext;+ dnode.mtext([0,svgroot.getAttribute("height")-6],"Try (shift/alt)-dblclick", "right", "", "8");+*/ }+}++function removeCoord(evt) {+ var svgroot = evt.target.parentNode;+ var nl = svgroot.childNodes;+ for (var i=0; i<nl.length && nl.item(i).nodeName!="text"; i++);+ var cnode = nl.item(i);+ cnode.mtext = mtext;+ cnode.mtext([svgroot.getAttribute("width")-0,svgroot.getAttribute("height")-0],"", "aboveleft", "");+/* var dnode = nl.item(i+1);+ dnode.mtext = mtext;+ dnode.mtext([0,svgroot.getAttribute("height")-0],"", "aboveright", "");+*/}++function initASCIIMathCalculators(li) {+ var i;+ for (i=0; i<li.length; i++) {+ li[i].innerHTML = calcstr;+ AMprocessNode(li[i]);+ }+ li = document.getElementsByTagName("textarea");+ var st;+ for (i=0; i<li.length; i++) {+ st = li[i].getAttribute("onkeyup");+ if (st!=null) eval(String(st).replace(/function anonymous\(\)/,""));+ }+}++function calculate(inputId,outputId) {+ var str = document.getElementById(inputId).value;+ var err = "";+ var ind = str.lastIndexOf("\n");+ if (ind==str.length-1) str = str.slice(0,ind);+ str = str.slice(str.lastIndexOf("\n")+1);+ try {+ var res = eval(mathjs(str));+ } catch(e) {+ err = "syntax incomplete";+ }+ if (!isNaN(res) && res!="Infinity") + str = "`"+str+" =` "+(Math.abs(res-Math.round(res*1000000)/1000000)<1e-15?Math.round(res*1000000)/1000000:res)+err; + else if (str!="") str = "`"+str+"` = undefined"; //debug:+mathjs(str);+ var outnode = document.getElementById(outputId);+ var n = outnode.childNodes.length;+ for (var i=0; i<n; i++)+ outnode.removeChild(outnode.firstChild);+ outnode.appendChild(document.createTextNode(str));+ AMprocessNode(outnode);+}++function append(st){+ document.getElementById('in').value+=st;+ calculate('in','out');+ document.getElementById('in').scrollTop = 1000;+ document.getElementById('in').focus();+}++function clearTextArea(){+ document.getElementById('in').value="";+ calculate('in','out');+ document.getElementById('in').focus();+}++var calcstr = "<table align=\"center\">\n<tr><th>\nASCIIMath Scientific Calculator\n</th></tr>\n<tr><td>\nClick in the box to use your keyboard or use the buttons\n</td></tr>\n<tr><td>\n<textarea id=\"in\" rows=\"3\" cols=\"40\" onkeyup=\"calculate('in','out')\"></textarea></td></tr>\n<tr><td height=\"50\">Result: <span id=\"out\"></span></td></tr>\n</table>\n<table align=\"center\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody align=\"center\">\n<tr>\n<td colspan=\"4\">\n<button onclick=\"append('sin^-1(')\"><font size=2>`sin^-1`</font></button><button onclick=\"append('cos^-1(')\"><font size=2>`cos^-1`</font></button><button onclick=\"append('tan^-1(')\"><font size=2>`tan^-1`</font></button></td>\n<td><button onclick=\"clearTextArea()\"> `C` </button></td>\n\n</tr>\n<tr>\n<td><button onclick=\"append('pi')\"> `pi` </button></td>\n<td><button onclick=\"append('sin(')\"> `sin`</button></td>\n<td><button onclick=\"append('cos(')\"> `cos`</button></td>\n<td><button onclick=\"append('tan(')\"> `tan`</button></td>\n<td><button onclick=\"append('^')\">`x^y`</button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('!')\"> `!` </button></td>\n\n<td><button onclick=\"append('(')\"><font size=2> `(` </font></button></td>\n<td><button onclick=\"append(')')\"><font size=2> `)` </font></button></td>\n<td><button onclick=\"append('sqrt(')\"><font size=2>`sqrt({::}^\ )`</font></button></td>\n<td><button onclick=\"append('/')\"> `-:\ `</button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('log(')\">`log`</button></td>\n<td><button onclick=\"append('7')\"> `7` </button></td>\n<td><button onclick=\"append('8')\"> `8` </button></td>\n\n<td><button onclick=\"append('9')\"> `9` </button></td>\n<td><button onclick=\"append('*')\"> `times` </button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('ln(')\"> `ln` </button></td>\n<td><button onclick=\"append('4')\"> `4` </button></td>\n<td><button onclick=\"append('5')\"> `5` </button></td>\n<td><button onclick=\"append('6')\"> `6` </button></td>\n\n<td><button onclick=\"append('-')\"> `-{::}` </button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('e')\"> `e` </button></td>\n<td><button onclick=\"append('1')\"> `1` </button></td>\n<td><button onclick=\"append('2')\"> `2` </button></td>\n<td><button onclick=\"append('3')\"> `3` </button></td>\n<td><button onclick=\"append('+')\"> `+{::}` </button></td>\n\n</tr>\n<tr>\n<td> <!--button onclick=\"append('pi')\"> `pi` </button--></td>\n<td><button onclick=\"append('0')\"> `0` </button></td>\n<td><button onclick=\"append('.')\"> `.` </button></td>\n<td><button onclick=\"append('\\n')\"> `\"ent\"`</button></td>\n</tr>\n</tbody>\n</table>";++// GO1.1 Generic onload by Brothercake+// http://www.brothercake.com/+//onload function (replaces the onload="translate()" in the <body> tag)+function generic()+{+ if(!init()) return;+ if (translateOnLoad) {+ var nd = document.getElementById("processasciimathinmoodle");+ if (nd!=null) dsvglocation = nd.className;+ if (nd!=null || !checkforprocessasciimathinmoodle) {+ translate();+ if (!noSVG && translateASCIIsvg) drawPictures();+ }+ var li = getElementsByClass(document,"div","ASCIIMathCalculator");+ if (!noMathML && li.length>0) initASCIIMathCalculators(li);+ }+};+//setup onload function+if(typeof window.addEventListener != 'undefined')+{+ //.. gecko, safari, konqueror and standard+ window.addEventListener('load', generic, false);+}+else if(typeof document.addEventListener != 'undefined')+{+ //.. opera 7+ document.addEventListener('load', generic, false);+}+else if(typeof window.attachEvent != 'undefined')+{+ //.. win/ie+ window.attachEvent('onload', generic);+}+//** remove this condition to degrade older browsers+else+{+ //.. mac/ie5 and anything else that gets this far+ //if there's an existing onload function+ if(typeof window.onload == 'function')+ {+ //store it+ var existing = onload;+ //add new onload handler+ window.onload = function()+ {+ //call existing onload function+ existing();+ //call generic onload function+ generic();+ };+ }+ else+ {+ //setup onload function+ window.onload = generic;+ }+}
+ templates/DefaultHeaders.hs view
@@ -0,0 +1,52 @@+{-+Copyright (C) 2006-7 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.DefaultHeaders+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Default headers for Pandoc writers.+-}+module Text.Pandoc.Writers.DefaultHeaders (+ defaultLaTeXHeader,+ defaultConTeXtHeader,+ defaultDocbookHeader,+ defaultS5Header,+ defaultRTFHeader+ ) where+import Text.Pandoc.Writers.S5++defaultLaTeXHeader :: String+defaultLaTeXHeader = "@LaTeXHeader@"++defaultConTeXtHeader :: String+defaultConTeXtHeader = "@ConTeXtHeader@"++defaultDocbookHeader :: String+defaultDocbookHeader = "@DocbookHeader@"++defaultS5Header :: String+defaultS5Header = s5Meta ++ s5CSS ++ s5Javascript++defaultRTFHeader :: String+defaultRTFHeader = "@RTFHeader@"
+ templates/Makefile view
@@ -0,0 +1,20 @@+VPATH := ..+PROCESSOR := ./fillTemplates.pl+TARGETS := Text/Pandoc/ASCIIMathML.hs \+ Text/Pandoc/Writers/S5.hs \+ Text/Pandoc/Writers/DefaultHeaders.hs++all: $(TARGETS)++Text/Pandoc/ASCIIMathML.hs: ASCIIMathML.hs $(PROCESSOR) ASCIIMathML.js+ perl $(PROCESSOR) $@ $(VPATH)++Text/Pandoc/Writers/S5.hs: S5.hs $(PROCESSOR) ui/default/*+ perl $(PROCESSOR) $@ $(VPATH)++Text/Pandoc/Writers/DefaultHeaders.hs: DefaultHeaders.hs $(PROCESSOR) headers/*+ perl $(PROCESSOR) $@ $(VPATH)++.PHONY: clean+clean:+ cd $(VPATH); rm -f $(TARGETS)
+ templates/S5.hs view
@@ -0,0 +1,133 @@+{-+Copyright (C) 2006-7 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.S5+ Copyright : Copyright (C) 2006-7 John MacFarlane+ License : GNU GPL, version 2 or above ++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Definitions for creation of S5 powerpoint-like HTML.+(See <http://meyerweb.com/eric/tools/s5/>.)+-}+module Text.Pandoc.Writers.S5 (+ -- * Strings+ s5Meta,+ s5Javascript,+ s5CSS,+ s5Links,+ -- * Functions+ writeS5,+ writeS5String,+ insertS5Structure+ ) where+import Text.Pandoc.Shared ( joinWithSep, WriterOptions )+import Text.Pandoc.Writers.HTML ( writeHtml, writeHtmlString )+import Text.Pandoc.Definition+import Text.XHtml.Strict++s5Meta :: String+s5Meta = "<!-- configuration parameters -->\n<meta name=\"defaultView\" content=\"slideshow\" />\n<meta name=\"controlVis\" content=\"hidden\" />\n"++s5Javascript :: String+s5Javascript = "<script type=\"text/javascript\">\n@slides.js@</script>\n" ++s5CoreCSS :: String+s5CoreCSS = "@s5-core.css@"++s5FramingCSS :: String+s5FramingCSS = "@framing.css@"++s5PrettyCSS :: String+s5PrettyCSS = "@pretty.css@"++s5OperaCSS :: String+s5OperaCSS = "@opera.css@"++s5OutlineCSS :: String+s5OutlineCSS = "@outline.css@"++s5PrintCSS :: String+s5PrintCSS = "@print.css@"++s5CSS :: String+s5CSS = "<style type=\"text/css\" media=\"projection\" id=\"slideProj\">\n" ++ s5CoreCSS ++ "\n" ++ s5FramingCSS ++ "\n" ++ s5PrettyCSS ++ "\n</style>\n<style type=\"text/css\" media=\"projection\" id=\"operaFix\">\n" ++ s5OperaCSS ++ "\n</style>\n<style type=\"text/css\" media=\"screen\" id=\"outlineStyle\">\n" ++ s5OutlineCSS ++ "\n</style>\n<style type=\"text/css\" media=\"print\" id=\"slidePrint\">\n" ++ s5PrintCSS ++ "\n</style>\n"++s5Links :: String+s5Links = "<!-- style sheet links -->\n<link rel=\"stylesheet\" href=\"ui/default/slides.css\" type=\"text/css\" media=\"projection\" id=\"slideProj\" />\n<link rel=\"stylesheet\" href=\"ui/default/outline.css\" type=\"text/css\" media=\"screen\" id=\"outlineStyle\" />\n<link rel=\"stylesheet\" href=\"ui/default/print.css\" type=\"text/css\" media=\"print\" id=\"slidePrint\" />\n<link rel=\"stylesheet\" href=\"ui/default/opera.css\" type=\"text/css\" media=\"projection\" id=\"operaFix\" />\n<!-- S5 JS -->\n<script src=\"ui/default/slides.js\" type=\"text/javascript\"></script>\n"++-- | Converts Pandoc document to an S5 HTML presentation (Html structure).+writeS5 :: WriterOptions -> Pandoc -> Html+writeS5 options = (writeHtml options) . insertS5Structure++-- | Converts Pandoc document to an S5 HTML presentation (string).+writeS5String :: WriterOptions -> Pandoc -> String+writeS5String options = (writeHtmlString options) . insertS5Structure++-- | Inserts HTML needed for an S5 presentation (e.g. around slides).+layoutDiv :: [Inline] -- ^ Title of document (for header or footer)+ -> String -- ^ Date of document (for header or footer)+ -> [Block] -- ^ List of block elements returned+layoutDiv title date = [(RawHtml "<div class=\"layout\">\n<div id=\"controls\"></div>\n<div id=\"currentSlide\"></div>\n<div id=\"header\"></div>\n<div id=\"footer\">\n"), (Header 1 [Str date]), (Header 2 title), (RawHtml "</div>\n</div>\n")]++presentationStart = RawHtml "<div class=\"presentation\">\n\n"++presentationEnd = RawHtml "</div>\n"++slideStart = RawHtml "<div class=\"slide\">\n"++slideEnd = RawHtml "</div>\n"++-- | Returns 'True' if block is a Header 1.+isH1 :: Block -> Bool+isH1 (Header 1 _) = True+isH1 _ = False ++-- | Insert HTML around sections to make individual slides.+insertSlides :: Bool -> [Block] -> [Block]+insertSlides beginning blocks = + let (beforeHead, rest) = break isH1 blocks in+ if (null rest) then + if beginning then+ beforeHead + else+ beforeHead ++ [slideEnd]+ else+ if beginning then+ beforeHead ++ + slideStart:(head rest):(insertSlides False (tail rest))+ else+ beforeHead ++ + slideEnd:slideStart:(head rest):(insertSlides False (tail rest)) ++-- | Insert blocks into 'Pandoc' for slide structure.+insertS5Structure :: Pandoc -> Pandoc+insertS5Structure (Pandoc meta []) = Pandoc meta []+insertS5Structure (Pandoc (Meta title authors date) blocks) = + let slides = insertSlides True blocks + firstSlide = if not (null title)+ then [slideStart, (Header 1 title), + (Header 3 [Str (joinWithSep ", " authors)]),+ (Header 4 [Str date]), slideEnd]+ else []+ newBlocks = (layoutDiv title date) ++ presentationStart:firstSlide +++ slides ++ [presentationEnd]+ in Pandoc (Meta title authors date) newBlocks
+ templates/fillTemplates.pl view
@@ -0,0 +1,131 @@+#!/usr/bin/env perl+# Fills templates with haskell-escaped strings slurped from input files.+# Takes two arguments, the first specifying the pathname of the target+# relative to the root directory, the second specifying the root directory+# (defaulting to ..). The template is assumed to have the same base name+# as the target and to reside in the templates subdirectory of the root+# directory.++use strict;+use warnings;++# Utility routines:++sub slurp {+ open FILE, $_[0] or die "couldn't open file '$_[0]': $!";+ my $contents = do { local $/; <FILE>;};+ close FILE;+ return $contents;+}++sub escape_for_haskell {+ my ($contents) = @_;++ $contents =~ s/\\/\\\\/g;+ $contents =~ s/\t/\\t/g;+ $contents =~ s/"/\\"/g;+ $contents =~ s/\n/\\n/g;+ return $contents;+}++# Template processors.++my %processor = (+ # --------------------------------------------------------------------------+ 'Text/Pandoc/Writers/S5.hs' => {+ # --------------------------------------------------------------------------+ proc => sub {+ my ($template) = @_;++ my (@files) = qw(slides.js s5-core.css framing.css pretty.css + opera.css outline.css print.css);++ foreach my $file (@files) {+ my $replacement = escape_for_haskell(slurp "templates/ui/default/$file");+ my $escapedfile = $file;+ $escapedfile =~ s/\./\\./g;+ $template =~ s/\@$escapedfile\@/$replacement/;+ } + return $template;+ },+ },+ # --------------------------------------------------------------------------+ 'Text/Pandoc/ASCIIMathML.hs' => {+ # --------------------------------------------------------------------------+ proc => sub {+ my ($template) = @_;++ my $script = escape_for_haskell(slurp "templates/ASCIIMathML.js"); + my $acknowledgements =+ " ASCIIMathML.js - copyright Peter Jipsen,".+ " released under the GPL\\nSee ".+ "http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ ";+ $script =~ s/\/\*.*?\*\//\/\*$acknowledgements\*\//g; # strip comments+ $template =~ s/\@ASCIIMathML\.js@/$script/;++ return $template;+ },+ },+ # --------------------------------------------------------------------------+ 'Text/Pandoc/Writers/DefaultHeaders.hs' => {+ # --------------------------------------------------------------------------+ proc => sub {+ my ($template) = @_;++ my (@headers) = split(/\s/,`ls templates/headers`);+ foreach my $header (@headers) {+ my ($replacement) = escape_for_haskell(slurp "templates/headers/$header");+ $template =~ s/\@$header\@/$replacement/;+ }+ + return $template;+ },+ },+ # --------------------------------------------------------------------------+ # 'foo/bar/baz' => {+ # --------------------------------------------------------------------------+ # template => 'optional-template-filename-defaults-to-baz'+ # proc => sub {+ # my ($template) = @_;+ # # Process.+ # return $template;+ # },+ #},+);++# Main.++my $target = shift @ARGV;+if (!defined $target || !length $target) {+ print STDERR "Available targets:\n\n" . join "\n", keys %processor;+ die "\n\nYou must supply a target!\n";+}++die "No processor exists for '$target'!\n" if ! exists $processor{$target};++my $rootdir = shift @ARGV || '..';+chdir $rootdir or die "Couldn't chdir to '$rootdir': $!";++my $template;+if (exists $processor{$target}->{template}) {+ $template = $processor{$target}->{template};+}+else {+ ($template = $target) =~ s!.*/+!!;+}+$template = "templates/$template";+die "No template exists for '$target'!\n" if ! -f "$template";++open OUTFILE, ">$target" or die "couldn't open file '$target': $!";+print OUTFILE <<END;+----------------------------------------------------+-- Do not edit this file by hand. Edit +-- '$template'+-- and run $0 $target+----------------------------------------------------++END++print OUTFILE $processor{$target}->{proc}->(slurp($template));+print OUTFILE "\n";+close OUTFILE;
+ templates/headers/ConTeXtHeader view
@@ -0,0 +1,67 @@+\enableregime[utf] % use UTF-8++\setupcolors[state=start]+\setupinteraction[state=start, color=middleblue] % needed for hyperlinks++\setuppapersize[letter][letter] % use letter paper+\setuplayout[width=middle, backspace=1.5in, cutspace=1.5in,+ height=middle, header=0.75in, footer=0.75in] % page layout+\setuppagenumbering[location={footer,center}] % number pages+\setupbodyfont[11pt] % 11pt font+\setupwhitespace[medium] % inter-paragraph spacing++\setuphead[section][style=\tfc]+\setuphead[subsection][style=\tfb]+\setuphead[subsubsection][style=\bf]++% define title block commands+\unprotect+\def\doctitle#1{\gdef\@title{#1}}+\def\author#1{\gdef\@author{#1}}+\def\date#1{\gdef\@date{#1}}+\date{\currentdate} % Default to today unless specified otherwise.+\def\maketitle{%+ \startalignment[center]+ \blank[2*big]+ {\tfd \@title}+ \blank[3*medium]+ {\tfa \@author}+ \blank[2*medium]+ {\tfa \@date}+ \blank[3*medium]+ \stopalignment}+\protect++% define descr (for definition lists)+\definedescription[descr][+ headstyle=bold,style=normal,align=left,location=hanging,+ width=broad,margin=1cm]++% define defaults for bulleted lists +\setupitemize[1][symbol=1][indentnext=no]+\setupitemize[2][symbol=2][indentnext=no]+\setupitemize[3][symbol=3][indentnext=no]+\setupitemize[4][symbol=4][indentnext=no]++\setupthinrules[width=15em] % width of horizontal rules++% for block quotations+\unprotect++\startvariables all+blockquote: blockquote+\stopvariables++\definedelimitedtext+[\v!blockquote][\v!quotation]++\setupdelimitedtext+[\v!blockquote]+[\c!left=,+\c!right=,+before={\blank[medium]},+after={\blank[medium]},+]++\protect+
+ templates/headers/DocbookHeader view
@@ -0,0 +1,3 @@+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+ templates/headers/LaTeXHeader view
@@ -0,0 +1,5 @@+\documentclass{article}+\usepackage[mathletters]{ucs}+\usepackage[utf8x]{inputenc}+\setlength{\parindent}{0pt}+\setlength{\parskip}{6pt plus 2pt minus 1pt}
+ templates/headers/RTFHeader view
@@ -0,0 +1,4 @@+{\rtf1\ansi\deff0{\fonttbl{\f0 \fswiss Helvetica;}{\f1 Courier;}}+{\colortbl;\red255\green0\blue0;\red0\green0\blue255;}+\widowctrl\hyphauto+
+ templates/headers/S5Header view
@@ -0,0 +1,3 @@+<!-- configuration parameters -->+<meta name="defaultView" content="slideshow" />+<meta name="controlVis" content="hidden" />
+ templates/ui/default/blank.gif view
binary file changed (absent → 49 bytes)
+ templates/ui/default/bodybg.gif view
binary file changed (absent → 10119 bytes)
+ templates/ui/default/framing.css view
@@ -0,0 +1,23 @@+/* The following styles size, place, and layer the slide components.+ Edit these if you want to change the overall slide layout.+ The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */++/* target = 1024x768 */++div#header, div#footer, .slide {width: 100%; top: 0; left: 0;}+div#header {top: 0; height: 3em; z-index: 1;}+div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;}+.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;}+div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;}+div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;+ margin: 0;}+#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;}+html>body #currentSlide {position: fixed;}++/*+div#header {background: #FCC;}+div#footer {background: #CCF;}+div#controls {background: #BBD;}+div#currentSlide {background: #FFC;}+*/
+ templates/ui/default/iepngfix.htc view
@@ -0,0 +1,42 @@+<public:component> +<public:attach event="onpropertychange" onevent="doFix()" /> + +<script> + +// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com +// Free usage permitted as long as this notice remains intact. + +// This must be a path to a blank image. That's all the configuration you need here. +var blankImg = 'ui/default/blank.gif'; + +var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; + +function filt(s, m) { + if (filters[f]) { + filters[f].enabled = s ? true : false; + if (s) with (filters[f]) { src = s; sizingMethod = m } + } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; +} + +function doFix() { + if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || + (event && !/(background|src)/.test(event.propertyName))) return; + + if (tagName == 'IMG') { + if ((/\.png$/i).test(src)) { + filt(src, 'image'); // was 'scale' + src = blankImg; + } else if (src.indexOf(blankImg) < 0) filt(); + } else if (style.backgroundImage) { + if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { + var s = RegExp.$1; + style.backgroundImage = ''; + filt(s, 'crop'); + } else filt(); + } +} + +doFix(); + +</script> +</public:component>
+ templates/ui/default/opera.css view
@@ -0,0 +1,7 @@+/* DO NOT CHANGE THESE unless you really want to break Opera Show */+.slide {+ visibility: visible !important;+ position: static !important;+ page-break-before: always;+}+#slide0 {page-break-before: avoid;}
+ templates/ui/default/outline.css view
@@ -0,0 +1,15 @@+/* don't change this unless you want the layout stuff to show up in the outline view! */++.layout div, #footer *, #controlForm * {display: none;}+#footer, #controls, #controlForm, #navLinks, #toggle {+ display: block; visibility: visible; margin: 0; padding: 0;}+#toggle {float: right; padding: 0.5em;}+html>body #toggle {position: fixed; top: 0; right: 0;}++/* making the outline look pretty-ish */++#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;}+#slide0 h1 {padding-top: 1.5em;}+.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em;+ border-top: 1px solid #888; border-bottom: 1px solid #AAA;}+#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;}
+ templates/ui/default/pretty.css view
@@ -0,0 +1,86 @@+/* Following are the presentation styles -- edit away! */++body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2em;}+:link, :visited {text-decoration: none; color: #00C;}+#controls :active {color: #88A !important;}+#controls :focus {outline: 1px dotted #227;}+h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;}+ul, pre {margin: 0; line-height: 1em;}+html, body {margin: 0; padding: 0;}++blockquote, q {font-style: italic;}+blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;}+blockquote p {margin: 0;}+blockquote i {font-style: normal;}+blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;}+blockquote b i {font-style: italic;}++kbd {font-weight: bold; font-size: 1em;}+sup {font-size: smaller; line-height: 1px;}++.slide code {padding: 2px 0.25em; font-weight: bold; color: #533;}+.slide code.bad, code del {color: red;}+.slide code.old {color: silver;}+.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;}+.slide pre code {display: block;}+.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;}+.slide li {margin-top: 0.75em; margin-right: 0;}+.slide ul ul {line-height: 1;}+.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;}+.slide img.leader {display: block; margin: 0 auto;}++div#header, div#footer {background: #005; color: #AAB;+ font-family: Verdana, Helvetica, sans-serif;}+div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat;+ line-height: 1px;}+div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;}+#footer h1, #footer h2 {display: block; padding: 0 1em;}+#footer h2 {font-style: italic;}++div.long {font-size: 0.75em;}+.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1;+ margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap;+ font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize;+ color: #DDE; background: #005;}+.slide h3 {font-size: 130%;}+h1 abbr {font-variant: small-caps;}++div#controls {position: absolute; left: 50%; bottom: 0;+ width: 50%;+ text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;}+html>body div#controls {position: fixed; padding: 0 0 1em 0;+ top: auto;}+div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;+ margin: 0; padding: 0;}+#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #005; border: none; color: #779; + cursor: pointer;}+#controls #navList {height: 1em;}+#controls #navList #jumplist {position: absolute; bottom: 0; right: 0; background: #DDD; color: #227;}++#currentSlide {text-align: center; font-size: 0.5em; color: #449;}++#slide0 {padding-top: 3.5em; font-size: 90%;}+#slide0 h1 {position: static; margin: 1em 0 0; padding: 0;+ font: bold 2em Helvetica, sans-serif; white-space: normal;+ color: #000; background: transparent;}+#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;}+#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;}+#slide0 h4 {margin-top: 0; font-size: 1em;}++ul.urls {list-style: none; display: inline; margin: 0;}+.urls li {display: inline; margin: 0;}+.note {display: none;}+.external {border-bottom: 1px dotted gray;}+html>body .external {border-bottom: none;}+.external:after {content: " \274F"; font-size: smaller; color: #77B;}++.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;}+img.incremental {visibility: hidden;}+.slide .current {color: #B02;}+++/* diagnostics++li:after {content: " [" attr(class) "]"; color: #F88;}+ */
+ templates/ui/default/print.css view
@@ -0,0 +1,24 @@+/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */+.slide, ul {page-break-inside: avoid; visibility: visible !important;}+h1 {page-break-after: avoid;}++body {font-size: 12pt; background: white;}+* {color: black;}++#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}+#slide0 h3 {margin: 0; padding: 0;}+#slide0 h4 {margin: 0 0 0.5em; padding: 0;}+#slide0 {margin-bottom: 3em;}++h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}+.extra {background: transparent !important;}+div.extra, pre.extra, .example {font-size: 10pt; color: #333;}+ul.extra a {font-weight: bold;}+p.example {display: none;}++#header {display: none;}+#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}+#footer h2, #controls {display: none;}++/* The following rule keeps the layout stuff out of print. Remove at your own risk! */+.layout, .layout * {display: none !important;}
+ templates/ui/default/s5-core.css view
@@ -0,0 +1,9 @@+/* Do not edit or override these styles! The system will likely break if you do. */++div#header, div#footer, div#controls, .slide {position: absolute;}+html>body div#header, html>body div#footer, + html>body div#controls, html>body .slide {position: fixed;}+.handout {display: none;}+.layout {display: block;}+.slide, .hideme, .incremental {visibility: hidden;}+#slide0 {visibility: visible;}
+ templates/ui/default/slides.css view
@@ -0,0 +1,3 @@+@import url(s5-core.css); /* required to make the slide show run at all */+@import url(framing.css); /* sets basic placement and size of slide components */+@import url(pretty.css); /* stuff that makes the slides look better than blah */
+ templates/ui/default/slides.js view
@@ -0,0 +1,553 @@+// S5 v1.1 slides.js -- released into the Public Domain+//+// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code!++var undef;+var slideCSS = '';+var snum = 0;+var smax = 1;+var incpos = 0;+var number = undef;+var s5mode = true;+var defaultView = 'slideshow';+var controlVis = 'visible';++var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0;+var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0;+var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0;++function hasClass(object, className) {+ if (!object.className) return false;+ return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1);+}++function hasValue(object, value) {+ if (!object) return false;+ return (object.search('(^|\\s)' + value + '(\\s|$)') != -1);+}++function removeClass(object,className) {+ if (!object) return;+ object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2);+}++function addClass(object,className) {+ if (!object || hasClass(object, className)) return;+ if (object.className) {+ object.className += ' '+className;+ } else {+ object.className = className;+ }+}++function GetElementsWithClassName(elementName,className) {+ var allElements = document.getElementsByTagName(elementName);+ var elemColl = new Array();+ for (var i = 0; i< allElements.length; i++) {+ if (hasClass(allElements[i], className)) {+ elemColl[elemColl.length] = allElements[i];+ }+ }+ return elemColl;+}++function isParentOrSelf(element, id) {+ if (element == null || element.nodeName=='BODY') return false;+ else if (element.id == id) return true;+ else return isParentOrSelf(element.parentNode, id);+}++function nodeValue(node) {+ var result = "";+ if (node.nodeType == 1) {+ var children = node.childNodes;+ for (var i = 0; i < children.length; ++i) {+ result += nodeValue(children[i]);+ } + }+ else if (node.nodeType == 3) {+ result = node.nodeValue;+ }+ return(result);+}++function slideLabel() {+ var slideColl = GetElementsWithClassName('*','slide');+ var list = document.getElementById('jumplist');+ smax = slideColl.length;+ for (var n = 0; n < smax; n++) {+ var obj = slideColl[n];++ var did = 'slide' + n.toString();+ obj.setAttribute('id',did);+ if (isOp) continue;++ var otext = '';+ var menu = obj.firstChild;+ if (!menu) continue; // to cope with empty slides+ while (menu && menu.nodeType == 3) {+ menu = menu.nextSibling;+ }+ if (!menu) continue; // to cope with slides with only text nodes++ var menunodes = menu.childNodes;+ for (var o = 0; o < menunodes.length; o++) {+ otext += nodeValue(menunodes[o]);+ }+ list.options[list.length] = new Option(n + ' : ' + otext, n);+ }+}++function currentSlide() {+ var cs;+ if (document.getElementById) {+ cs = document.getElementById('currentSlide');+ } else {+ cs = document.currentSlide;+ }+ cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>';+ if (snum == 0) {+ cs.style.visibility = 'hidden';+ } else {+ cs.style.visibility = 'visible';+ }+}++function go(step) {+ if (document.getElementById('slideProj').disabled || step == 0) return;+ var jl = document.getElementById('jumplist');+ var cid = 'slide' + snum;+ var ce = document.getElementById(cid);+ if (incrementals[snum].length > 0) {+ for (var i = 0; i < incrementals[snum].length; i++) {+ removeClass(incrementals[snum][i], 'current');+ removeClass(incrementals[snum][i], 'incremental');+ }+ }+ if (step != 'j') {+ snum += step;+ lmax = smax - 1;+ if (snum > lmax) snum = lmax;+ if (snum < 0) snum = 0;+ } else+ snum = parseInt(jl.value);+ var nid = 'slide' + snum;+ var ne = document.getElementById(nid);+ if (!ne) {+ ne = document.getElementById('slide0');+ snum = 0;+ }+ if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;}+ if (incrementals[snum].length > 0 && incpos == 0) {+ for (var i = 0; i < incrementals[snum].length; i++) {+ if (hasClass(incrementals[snum][i], 'current'))+ incpos = i + 1;+ else+ addClass(incrementals[snum][i], 'incremental');+ }+ }+ if (incrementals[snum].length > 0 && incpos > 0)+ addClass(incrementals[snum][incpos - 1], 'current');+ ce.style.visibility = 'hidden';+ ne.style.visibility = 'visible';+ jl.selectedIndex = snum;+ currentSlide();+ number = 0;+}++function goTo(target) {+ if (target >= smax || target == snum) return;+ go(target - snum);+}++function subgo(step) {+ if (step > 0) {+ removeClass(incrementals[snum][incpos - 1],'current');+ removeClass(incrementals[snum][incpos], 'incremental');+ addClass(incrementals[snum][incpos],'current');+ incpos++;+ } else {+ incpos--;+ removeClass(incrementals[snum][incpos],'current');+ addClass(incrementals[snum][incpos], 'incremental');+ addClass(incrementals[snum][incpos - 1],'current');+ }+}++function toggle() {+ var slideColl = GetElementsWithClassName('*','slide');+ var slides = document.getElementById('slideProj');+ var outline = document.getElementById('outlineStyle');+ if (!slides.disabled) {+ slides.disabled = true;+ outline.disabled = false;+ s5mode = false;+ fontSize('1em');+ for (var n = 0; n < smax; n++) {+ var slide = slideColl[n];+ slide.style.visibility = 'visible';+ }+ } else {+ slides.disabled = false;+ outline.disabled = true;+ s5mode = true;+ fontScale();+ for (var n = 0; n < smax; n++) {+ var slide = slideColl[n];+ slide.style.visibility = 'hidden';+ }+ slideColl[snum].style.visibility = 'visible';+ }+}++function showHide(action) {+ var obj = GetElementsWithClassName('*','hideme')[0];+ switch (action) {+ case 's': obj.style.visibility = 'visible'; break;+ case 'h': obj.style.visibility = 'hidden'; break;+ case 'k':+ if (obj.style.visibility != 'visible') {+ obj.style.visibility = 'visible';+ } else {+ obj.style.visibility = 'hidden';+ }+ break;+ }+}++// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/)+function keys(key) {+ if (!key) {+ key = event;+ key.which = key.keyCode;+ }+ if (key.which == 84) {+ toggle();+ return;+ }+ if (s5mode) {+ switch (key.which) {+ case 10: // return+ case 13: // enter+ if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;+ if (key.target && isParentOrSelf(key.target, 'controls')) return;+ if(number != undef) {+ goTo(number);+ break;+ }+ case 32: // spacebar+ case 34: // page down+ case 39: // rightkey+ case 40: // downkey+ if(number != undef) {+ go(number);+ } else if (!incrementals[snum] || incpos >= incrementals[snum].length) {+ go(1);+ } else {+ subgo(1);+ }+ break;+ case 33: // page up+ case 37: // leftkey+ case 38: // upkey+ if(number != undef) {+ go(-1 * number);+ } else if (!incrementals[snum] || incpos <= 0) {+ go(-1);+ } else {+ subgo(-1);+ }+ break;+ case 36: // home+ goTo(0);+ break;+ case 35: // end+ goTo(smax-1);+ break;+ case 67: // c+ showHide('k');+ break;+ }+ if (key.which < 48 || key.which > 57) {+ number = undef;+ } else {+ if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return;+ if (key.target && isParentOrSelf(key.target, 'controls')) return;+ number = (((number != undef) ? number : 0) * 10) + (key.which - 48);+ }+ }+ return false;+}++function clicker(e) {+ number = undef;+ var target;+ if (window.event) {+ target = window.event.srcElement;+ e = window.event;+ } else target = e.target;+ if (target.getAttribute('href') != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true;+ if (!e.which || e.which == 1) {+ if (!incrementals[snum] || incpos >= incrementals[snum].length) {+ go(1);+ } else {+ subgo(1);+ }+ }+}++function findSlide(hash) {+ var target = null;+ var slides = GetElementsWithClassName('*','slide');+ for (var i = 0; i < slides.length; i++) {+ var targetSlide = slides[i];+ if ( (targetSlide.name && targetSlide.name == hash)+ || (targetSlide.id && targetSlide.id == hash) ) {+ target = targetSlide;+ break;+ }+ }+ while(target != null && target.nodeName != 'BODY') {+ if (hasClass(target, 'slide')) {+ return parseInt(target.id.slice(5));+ }+ target = target.parentNode;+ }+ return null;+}++function slideJump() {+ if (window.location.hash == null) return;+ var sregex = /^#slide(\d+)$/;+ var matches = sregex.exec(window.location.hash);+ var dest = null;+ if (matches != null) {+ dest = parseInt(matches[1]);+ } else {+ dest = findSlide(window.location.hash.slice(1));+ }+ if (dest != null)+ go(dest - snum);+}++function fixLinks() {+ var thisUri = window.location.href;+ thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length);+ var aelements = document.getElementsByTagName('A');+ for (var i = 0; i < aelements.length; i++) {+ var a = aelements[i].href;+ var slideID = a.match('\#slide[0-9]{1,2}');+ if ((slideID) && (slideID[0].slice(0,1) == '#')) {+ var dest = findSlide(slideID[0].slice(1));+ if (dest != null) {+ if (aelements[i].addEventListener) {+ aelements[i].addEventListener("click", new Function("e",+ "if (document.getElementById('slideProj').disabled) return;" ++ "go("+dest+" - snum); " ++ "if (e.preventDefault) e.preventDefault();"), true);+ } else if (aelements[i].attachEvent) {+ aelements[i].attachEvent("onclick", new Function("",+ "if (document.getElementById('slideProj').disabled) return;" ++ "go("+dest+" - snum); " ++ "event.returnValue = false;"));+ }+ }+ }+ }+}++function externalLinks() {+ if (!document.getElementsByTagName) return;+ var anchors = document.getElementsByTagName('a');+ for (var i=0; i<anchors.length; i++) {+ var anchor = anchors[i];+ if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) {+ anchor.target = '_blank';+ addClass(anchor,'external');+ }+ }+}++function createControls() {+ var controlsDiv = document.getElementById("controls");+ if (!controlsDiv) return;+ var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"';+ var hideDiv, hideList = '';+ if (controlVis == 'hidden') {+ hideDiv = hider;+ } else {+ hideList = hider;+ }+ controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' ++ '<div id="navLinks">' ++ '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' ++ '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' ++ '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' ++ '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' ++ '<\/div><\/form>';+ if (controlVis == 'hidden') {+ var hidden = document.getElementById('navLinks');+ } else {+ var hidden = document.getElementById('jumplist');+ }+ addClass(hidden,'hideme');+}++function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers+ if (!s5mode) return false;+ var vScale = 22; // both yield 32 (after rounding) at 1024x768+ var hScale = 32; // perhaps should auto-calculate based on theme's declared value?+ if (window.innerHeight) {+ var vSize = window.innerHeight;+ var hSize = window.innerWidth;+ } else if (document.documentElement.clientHeight) {+ var vSize = document.documentElement.clientHeight;+ var hSize = document.documentElement.clientWidth;+ } else if (document.body.clientHeight) {+ var vSize = document.body.clientHeight;+ var hSize = document.body.clientWidth;+ } else {+ var vSize = 700; // assuming 1024x768, minus chrome and such+ var hSize = 1024; // these do not account for kiosk mode or Opera Show+ }+ var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale));+ fontSize(newSize + 'px');+ if (isGe) { // hack to counter incremental reflow bugs+ var obj = document.getElementsByTagName('body')[0];+ obj.style.display = 'none';+ obj.style.display = 'block';+ }+}++function fontSize(value) {+ if (!(s5ss = document.getElementById('s5ss'))) {+ if (!isIE) {+ document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style'));+ s5ss.setAttribute('media','screen, projection');+ s5ss.setAttribute('id','s5ss');+ } else {+ document.createStyleSheet();+ document.s5ss = document.styleSheets[document.styleSheets.length - 1];+ }+ }+ if (!isIE) {+ while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild);+ s5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}'));+ } else {+ document.s5ss.addRule('body','font-size: ' + value + ' !important;');+ }+}++function notOperaFix() {+ slideCSS = document.getElementById('slideProj').href;+ var slides = document.getElementById('slideProj');+ var outline = document.getElementById('outlineStyle');+ slides.setAttribute('media','screen');+ outline.disabled = true;+ if (isGe) {+ slides.setAttribute('href','null'); // Gecko fix+ slides.setAttribute('href',slideCSS); // Gecko fix+ }+ if (isIE && document.styleSheets && document.styleSheets[0]) {+ document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)');+ document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)');+ document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)');+ }+}++function getIncrementals(obj) {+ var incrementals = new Array();+ if (!obj) + return incrementals;+ var children = obj.childNodes;+ for (var i = 0; i < children.length; i++) {+ var child = children[i];+ if (hasClass(child, 'incremental')) {+ if (child.nodeName == 'OL' || child.nodeName == 'UL') {+ removeClass(child, 'incremental');+ for (var j = 0; j < child.childNodes.length; j++) {+ if (child.childNodes[j].nodeType == 1) {+ addClass(child.childNodes[j], 'incremental');+ }+ }+ } else {+ incrementals[incrementals.length] = child;+ removeClass(child,'incremental');+ }+ }+ if (hasClass(child, 'show-first')) {+ if (child.nodeName == 'OL' || child.nodeName == 'UL') {+ removeClass(child, 'show-first');+ if (child.childNodes[isGe].nodeType == 1) {+ removeClass(child.childNodes[isGe], 'incremental');+ }+ } else {+ incrementals[incrementals.length] = child;+ }+ }+ incrementals = incrementals.concat(getIncrementals(child));+ }+ return incrementals;+}++function createIncrementals() {+ var incrementals = new Array();+ for (var i = 0; i < smax; i++) {+ incrementals[i] = getIncrementals(document.getElementById('slide'+i));+ }+ return incrementals;+}++function defaultCheck() {+ var allMetas = document.getElementsByTagName('meta');+ for (var i = 0; i< allMetas.length; i++) {+ if (allMetas[i].name == 'defaultView') {+ defaultView = allMetas[i].content;+ }+ if (allMetas[i].name == 'controlVis') {+ controlVis = allMetas[i].content;+ }+ }+}++// Key trap fix, new function body for trap()+function trap(e) {+ if (!e) {+ e = event;+ e.which = e.keyCode;+ }+ try {+ modifierKey = e.ctrlKey || e.altKey || e.metaKey;+ }+ catch(e) {+ modifierKey = false;+ }+ return modifierKey || e.which == 0;+}++function startup() {+ defaultCheck();+ if (!isOp) + createControls();+ slideLabel();+ fixLinks();+ externalLinks();+ fontScale();+ if (!isOp) {+ notOperaFix();+ incrementals = createIncrementals();+ slideJump();+ if (defaultView == 'outline') {+ toggle();+ }+ document.onkeyup = keys;+ document.onkeypress = trap;+ document.onclick = clicker;+ }+}++window.onload = startup;+window.onresize = function(){setTimeout('fontScale()', 50);}
tests/latex-reader.native view
@@ -274,13 +274,13 @@ , BulletList [ [ Para [TeX "\\cite[22-23]{smith.1899}"] ] , [ Para [TeX "\\doublespacing"] ]- , [ Para [TeX "$2+2=4$"] ]- , [ Para [TeX "$x \\in y$"] ]- , [ Para [TeX "$\\alpha \\wedge \\omega$"] ]- , [ Para [TeX "$223$"] ]- , [ Para [TeX "$p$",Str "-",Str "Tree"] ]- , [ Para [TeX "$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}$"] ]- , [ Para [Str "Here",Apostrophe,Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,TeX "$\\alpha + \\omega \\times x^2$",Str "."] ] ]+ , [ Para [Math "2+2=4"] ]+ , [ Para [Math "x \\in y"] ]+ , [ Para [Math "\\alpha \\wedge \\omega"] ]+ , [ Para [Math "223"] ]+ , [ Para [Math "p",Str "-",Str "Tree"] ]+ , [ Para [Math "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"] ]+ , [ Para [Str "Here",Apostrophe,Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Math "\\alpha + \\omega \\times x^2",Str "."] ] ] , Para [Str "These",Space,Str "shouldn",Apostrophe,Str "t",Space,Str "be",Space,Str "math:"] , BulletList [ [ Para [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code "$e = mc^2$",Str "."] ]
tests/rst-reader.native view
@@ -1,7 +1,8 @@ Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite",Str ":",Space,Str "Subtitle"] ["John MacFarlane","Anonymous"] "July 17, 2006")-[ BlockQuote- [ Para [Strong [Str "Revision"],Str ":",Space,Str "3"] ]-+[ DefinitionList+ [ ([Str "Revision"],+ [ Plain [Str "3"] ]+ ) ] , Header 1 [Str "Level",Space,Str "one",Space,Str "header"] , Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber's",Space,Str "markdown",Space,Str "test",Space,Str "suite."] , Header 2 [Str "Level",Space,Str "two",Space,Str "header"]@@ -41,7 +42,7 @@ , CodeBlock "---- (should be four hyphens)\n\nsub status {\n print \"working\";\n}" , CodeBlock "this code block is indented by one tab" , Para [Str "And",Str ":"]-, CodeBlock " this block is indented by two tabs\n\n These should not be escaped: \\$ \\\\ \\> \\[ \\{"+, CodeBlock "this block is indented by two tabs\n\nThese should not be escaped: \\$ \\\\ \\> \\[ \\{" , Header 1 [Str "Lists"] , Header 2 [Str "Unordered"] , Para [Str "Asterisks",Space,Str "tight",Str ":"]@@ -156,6 +157,27 @@ ([Str "term",Space,Str "with",Space,Emph [Str "emphasis"]], [ Para [Str "Definition",Space,Str "3."] ] ) ]+, Header 1 [Str "Field",Space,Str "Lists"]+, DefinitionList+ [ ([Str "address"],+ [ Plain [Str "61",Space,Str "Main",Space,Str "St."] ]+ ),+ ([Str "city"],+ [ Plain [Emph [Str "Nowhere"],Str ",",Space,Str "MA,",Space,Str "USA"] ]+ ),+ ([Str "phone"],+ [ Plain [Str "123",Str "-",Str "4567"] ]+ ) ]+, DefinitionList+ [ ([Str "address"],+ [ Plain [Str "61",Space,Str "Main",Space,Str "St."] ]+ ),+ ([Str "city"],+ [ Plain [Emph [Str "Nowhere"],Str ",",Space,Str "MA,",Space,Str "USA"] ]+ ),+ ([Str "phone"],+ [ Plain [Str "123",Str "-",Str "4567"] ]+ ) ] , Header 1 [Str "HTML",Space,Str "Blocks"] , Para [Str "Simple",Space,Str "block",Space,Str "on",Space,Str "one",Space,Str "line",Str ":"] , RawHtml "<div>foo</div>\n"@@ -207,5 +229,6 @@ , Header 1 [Str "Images"] , Para [Str "From",Space,Str "\"Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune\"",Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(1902)",Str ":"] , Plain [Image [Str "image"] ("lalune.jpg","")]+, Plain [Image [Str "Voyage dans la Lune"] ("lalune.jpg","Voyage dans la Lune")] , Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",Space,Image [Str "movie"] ("movie.jpg",""),Space,Str "icon."] ]
tests/rst-reader.rst view
@@ -256,6 +256,19 @@ term with *emphasis* Definition 3. +Field Lists+===========++ :address: 61 Main St.+ :city: *Nowhere*, MA,+ USA+ :phone: 123-4567++:address: 61 Main St.+:city: *Nowhere*, MA,+ USA+:phone: 123-4567+ HTML Blocks =========== @@ -381,6 +394,10 @@ From "Voyage dans la Lune" by Georges Melies (1902): .. image:: lalune.jpg++.. image:: lalune.jpg+ :height: 2343+ :alt: Voyage dans la Lune Here is a movie |movie| icon.
tests/s5.basic.html view
@@ -780,7 +780,33 @@ >Math</h1 ><ul ><li- >$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</li+ ><span class="math"+ >\frac{<em+ >d</em+ >}{<em+ >dx</em+ >}<em+ >f</em+ >(<em+ >x</em+ >)=\lim<sub+ ><em+ >h</em+ > → 0</sub+ >\frac{<em+ >f</em+ >(<em+ >x</em+ >+<em+ >h</em+ >)-<em+ >f</em+ >(<em+ >x</em+ >)}{<em+ >h</em+ >}</span+ ></li ></ul ></div> </div>
tests/s5.fancy.html view
@@ -12,872 +12,3191 @@ /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */ -var checkForMathML = true; // check if browser can display MathML-var notifyIfNoMathML = true; // display note if no MathML capability-var alertIfNoMathML = false; // show alert box if no MathML capability-var mathcolor = ""; // change it to "" (to inherit) or any other color-var mathfontfamily = "serif"; // change to "" to inherit (works in IE) - // or another family (e.g. "arial")-var displaystyle = true; // puts limits above and below large operators-var showasciiformulaonhover = true; // helps students learn ASCIIMath-var decimalsign = "."; // change to "," if you like, beware of `(1,2)`!-var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters-var AMdelimiter2 = "$", AMescape2 = "\\\\\\$", AMdelimiter2regexp = "\\$";-var doubleblankmathdelimiter = false; // if true, x+1 is equal to `x+1`- // for IE this works only in <!-- -->-//var separatetokens;// has been removed (email me if this is a problem)-var isIE = document.createElementNS==null;--if (document.getElementById==null) - alert("This webpage requires a recent browser such as\-\nMozilla/Netscape 7+ or Internet Explorer 6+MathPlayer")--// all further global variables start with "AM"--function AMcreateElementXHTML(t) {- if (isIE) return document.createElement(t);- else return document.createElementNS("http://www.w3.org/1999/xhtml",t);-}--function AMnoMathMLNote() {- var nd = AMcreateElementXHTML("h3");- nd.setAttribute("align","center")- nd.appendChild(AMcreateElementXHTML("p"));- nd.appendChild(document.createTextNode("To view the "));- var an = AMcreateElementXHTML("a");- an.appendChild(document.createTextNode("ASCIIMathML"));- an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html");- nd.appendChild(an);- nd.appendChild(document.createTextNode(" notation use Internet Explorer 6+")); - an = AMcreateElementXHTML("a");- an.appendChild(document.createTextNode("MathPlayer"));- an.setAttribute("href","http://www.dessci.com/en/products/mathplayer/download.htm");- nd.appendChild(an);- nd.appendChild(document.createTextNode(" or Netscape/Mozilla/Firefox"));- nd.appendChild(AMcreateElementXHTML("p"));- return nd;-}--function AMisMathMLavailable() {- var regex = /KHTML/; /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL-See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */- if (navigator.appName.slice(0,8)=="Netscape")- if (navigator.appVersion.slice(0,1)>="5" && !regex.test(navigator.userAgent)) return null;- else return AMnoMathMLNote();- else if (navigator.appName.slice(0,9)=="Microsoft")- try {- var ActiveX = new ActiveXObject("MathPlayer.Factory.1");- return null;- } catch (e) {- return AMnoMathMLNote();- }- else return AMnoMathMLNote();-}--// character lists for Mozilla/Netscape fonts-var AMcal = [0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];-var AMfrk = [0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];-var AMbbb = [0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];--var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4, - RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,- LEFTRIGHT = 9, TEXT = 10; // token types--var AMsqrt = {input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY},- AMroot = {input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY},- AMfrac = {input:"frac", tag:"mfrac", output:"/", tex:null, ttype:BINARY},- AMdiv = {input:"/", tag:"mfrac", output:"/", tex:null, ttype:INFIX},- AMover = {input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},- AMsub = {input:"_", tag:"msub", output:"_", tex:null, ttype:INFIX},- AMsup = {input:"^", tag:"msup", output:"^", tex:null, ttype:INFIX},- AMtext = {input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT},- AMmbox = {input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT},- AMquote = {input:"\"", tag:"mtext", output:"mbox", tex:null, ttype:TEXT};--var AMsymbols = [-//some greek symbols-{input:"alpha", tag:"mi", output:"\u03B1", tex:null, ttype:CONST},-{input:"beta", tag:"mi", output:"\u03B2", tex:null, ttype:CONST},-{input:"chi", tag:"mi", output:"\u03C7", tex:null, ttype:CONST},-{input:"delta", tag:"mi", output:"\u03B4", tex:null, ttype:CONST},-{input:"Delta", tag:"mo", output:"\u0394", tex:null, ttype:CONST},-{input:"epsi", tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST},-{input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST},-{input:"eta", tag:"mi", output:"\u03B7", tex:null, ttype:CONST},-{input:"gamma", tag:"mi", output:"\u03B3", tex:null, ttype:CONST},-{input:"Gamma", tag:"mo", output:"\u0393", tex:null, ttype:CONST},-{input:"iota", tag:"mi", output:"\u03B9", tex:null, ttype:CONST},-{input:"kappa", tag:"mi", output:"\u03BA", tex:null, ttype:CONST},-{input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},-{input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},-{input:"mu", tag:"mi", output:"\u03BC", tex:null, ttype:CONST},-{input:"nu", tag:"mi", output:"\u03BD", tex:null, ttype:CONST},-{input:"omega", tag:"mi", output:"\u03C9", tex:null, ttype:CONST},-{input:"Omega", tag:"mo", output:"\u03A9", tex:null, ttype:CONST},-{input:"phi", tag:"mi", output:"\u03C6", tex:null, ttype:CONST},-{input:"varphi", tag:"mi", output:"\u03D5", tex:null, ttype:CONST},-{input:"Phi", tag:"mo", output:"\u03A6", tex:null, ttype:CONST},-{input:"pi", tag:"mi", output:"\u03C0", tex:null, ttype:CONST},-{input:"Pi", tag:"mo", output:"\u03A0", tex:null, ttype:CONST},-{input:"psi", tag:"mi", output:"\u03C8", tex:null, ttype:CONST},-{input:"Psi", tag:"mi", output:"\u03A8", tex:null, ttype:CONST},-{input:"rho", tag:"mi", output:"\u03C1", tex:null, ttype:CONST},-{input:"sigma", tag:"mi", output:"\u03C3", tex:null, ttype:CONST},-{input:"Sigma", tag:"mo", output:"\u03A3", tex:null, ttype:CONST},-{input:"tau", tag:"mi", output:"\u03C4", tex:null, ttype:CONST},-{input:"theta", tag:"mi", output:"\u03B8", tex:null, ttype:CONST},-{input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST},-{input:"Theta", tag:"mo", output:"\u0398", tex:null, ttype:CONST},-{input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST},-{input:"xi", tag:"mi", output:"\u03BE", tex:null, ttype:CONST},-{input:"Xi", tag:"mo", output:"\u039E", tex:null, ttype:CONST},-{input:"zeta", tag:"mi", output:"\u03B6", tex:null, ttype:CONST},--//binary operation symbols-{input:"*", tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST},-{input:"**", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST},-{input:"//", tag:"mo", output:"/", tex:null, ttype:CONST},-{input:"\\\\", tag:"mo", output:"\\", tex:"backslash", ttype:CONST},-{input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST},-{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST},-{input:"-:", tag:"mo", output:"\u00F7", tex:"divide", ttype:CONST},-{input:"@", tag:"mo", output:"\u2218", tex:"circ", ttype:CONST},-{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST},-{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST},-{input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST},-{input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER},-{input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER},-{input:"^^", tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST},-{input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER},-{input:"vv", tag:"mo", output:"\u2228", tex:"vee", ttype:CONST},-{input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER},-{input:"nn", tag:"mo", output:"\u2229", tex:"cap", ttype:CONST},-{input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER},-{input:"uu", tag:"mo", output:"\u222A", tex:"cup", ttype:CONST},-{input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER},--//binary relation symbols-{input:"!=", tag:"mo", output:"\u2260", tex:"ne", ttype:CONST},-{input:":=", tag:"mo", output:":=", tex:null, ttype:CONST},-{input:"lt", tag:"mo", output:"<", tex:null, ttype:CONST},-{input:"<=", tag:"mo", output:"\u2264", tex:"le", ttype:CONST},-{input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST},-{input:">=", tag:"mo", output:"\u2265", tex:"ge", ttype:CONST},-{input:"geq", tag:"mo", output:"\u2265", tex:null, ttype:CONST},-{input:"-<", tag:"mo", output:"\u227A", tex:"prec", ttype:CONST},-{input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST},-{input:">-", tag:"mo", output:"\u227B", tex:"succ", ttype:CONST},-{input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST},-{input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST},-{input:"in", tag:"mo", output:"\u2208", tex:null, ttype:CONST},-{input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST},-{input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST},-{input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST},-{input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST},-{input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST},-{input:"-=", tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST},-{input:"~=", tag:"mo", output:"\u2245", tex:"cong", ttype:CONST},-{input:"~~", tag:"mo", output:"\u2248", tex:"approx", ttype:CONST},-{input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST},--//logical symbols-{input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE},-{input:"or", tag:"mtext", output:"or", tex:null, ttype:SPACE},-{input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST},-{input:"=>", tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST},-{input:"if", tag:"mo", output:"if", tex:null, ttype:SPACE},-{input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST},-{input:"AA", tag:"mo", output:"\u2200", tex:"forall", ttype:CONST},-{input:"EE", tag:"mo", output:"\u2203", tex:"exists", ttype:CONST},-{input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST},-{input:"TT", tag:"mo", output:"\u22A4", tex:"top", ttype:CONST},-{input:"|--", tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST},-{input:"|==", tag:"mo", output:"\u22A8", tex:"models", ttype:CONST},--//grouping brackets-{input:"(", tag:"mo", output:"(", tex:null, ttype:LEFTBRACKET},-{input:")", tag:"mo", output:")", tex:null, ttype:RIGHTBRACKET},-{input:"[", tag:"mo", output:"[", tex:null, ttype:LEFTBRACKET},-{input:"]", tag:"mo", output:"]", tex:null, ttype:RIGHTBRACKET},-{input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET},-{input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET},-{input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT},-//{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},-{input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET},-{input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET},-{input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET},-{input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET},-{input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true},-{input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true},--//miscellaneous symbols-{input:"int", tag:"mo", output:"\u222B", tex:null, ttype:CONST},-{input:"dx", tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION},-{input:"dy", tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION},-{input:"dz", tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION},-{input:"dt", tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION},-{input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST},-{input:"del", tag:"mo", output:"\u2202", tex:"partial", ttype:CONST},-{input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST},-{input:"+-", tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST},-{input:"O/", tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST},-{input:"oo", tag:"mo", output:"\u221E", tex:"infty", ttype:CONST},-{input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST},-{input:"...", tag:"mo", output:"...", tex:"ldots", ttype:CONST},-{input:":.", tag:"mo", output:"\u2234", tex:"therefore", ttype:CONST},-{input:"/_", tag:"mo", output:"\u2220", tex:"angle", ttype:CONST},-{input:"\\ ", tag:"mo", output:"\u00A0", tex:null, ttype:CONST},-{input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST},-{input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST},-{input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST},-{input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST},-{input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST},-{input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST},-{input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST},-{input:"|__", tag:"mo", output:"\u230A", tex:"lfloor", ttype:CONST},-{input:"__|", tag:"mo", output:"\u230B", tex:"rfloor", ttype:CONST},-{input:"|~", tag:"mo", output:"\u2308", tex:"lceiling", ttype:CONST},-{input:"~|", tag:"mo", output:"\u2309", tex:"rceiling", ttype:CONST},-{input:"CC", tag:"mo", output:"\u2102", tex:null, ttype:CONST},-{input:"NN", tag:"mo", output:"\u2115", tex:null, ttype:CONST},-{input:"QQ", tag:"mo", output:"\u211A", tex:null, ttype:CONST},-{input:"RR", tag:"mo", output:"\u211D", tex:null, ttype:CONST},-{input:"ZZ", tag:"mo", output:"\u2124", tex:null, ttype:CONST},-{input:"f", tag:"mi", output:"f", tex:null, ttype:UNARY, func:true},-{input:"g", tag:"mi", output:"g", tex:null, ttype:UNARY, func:true},--//standard functions-{input:"lim", tag:"mo", output:"lim", tex:null, ttype:UNDEROVER},-{input:"Lim", tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER},-{input:"sin", tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true},-{input:"cos", tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true},-{input:"tan", tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true},-{input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true},-{input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true},-{input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true},-{input:"cot", tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true},-{input:"sec", tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true},-{input:"csc", tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true},-{input:"log", tag:"mo", output:"log", tex:null, ttype:UNARY, func:true},-{input:"ln", tag:"mo", output:"ln", tex:null, ttype:UNARY, func:true},-{input:"det", tag:"mo", output:"det", tex:null, ttype:UNARY, func:true},-{input:"dim", tag:"mo", output:"dim", tex:null, ttype:CONST},-{input:"mod", tag:"mo", output:"mod", tex:null, ttype:CONST},-{input:"gcd", tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true},-{input:"lcm", tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true},-{input:"lub", tag:"mo", output:"lub", tex:null, ttype:CONST},-{input:"glb", tag:"mo", output:"glb", tex:null, ttype:CONST},-{input:"min", tag:"mo", output:"min", tex:null, ttype:UNDEROVER},-{input:"max", tag:"mo", output:"max", tex:null, ttype:UNDEROVER},--//arrows-{input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST},-{input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST},-{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST},-{input:"->", tag:"mo", output:"\u2192", tex:"to", ttype:CONST},-{input:"|->", tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST},-{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST},-{input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST},-{input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST},-{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST},-{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST},--//commands with argument-AMsqrt, AMroot, AMfrac, AMdiv, AMover, AMsub, AMsup,-{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true},-{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true},-{input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true},-{input:"dot", tag:"mover", output:".", tex:null, ttype:UNARY, acc:true},-{input:"ddot", tag:"mover", output:"..", tex:null, ttype:UNARY, acc:true},-{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true},-AMtext, AMmbox, AMquote,-{input:"bb", tag:"mstyle", atname:"fontweight", atval:"bold", output:"bb", tex:null, ttype:UNARY},-{input:"mathbf", tag:"mstyle", atname:"fontweight", atval:"bold", output:"mathbf", tex:null, ttype:UNARY},-{input:"sf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY},-{input:"mathsf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY},-{input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb},-{input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb},-{input:"cc", tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal},-{input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal},-{input:"tt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"tt", tex:null, ttype:UNARY},-{input:"mathtt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY},-{input:"fr", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk},-{input:"mathfrak", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk}-];--function compareNames(s1,s2) {- if (s1.input > s2.input) return 1- else return -1;-}--var AMnames = []; //list of input symbols--function AMinitSymbols() {- var texsymbols = [], i;- for (i=0; i<AMsymbols.length; i++)- if (AMsymbols[i].tex) - texsymbols[texsymbols.length] = {input:AMsymbols[i].tex, - tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype};- AMsymbols = AMsymbols.concat(texsymbols);- AMsymbols.sort(compareNames);- for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;-}--var AMmathml = "http://www.w3.org/1998/Math/MathML";--function AMcreateElementMathML(t) {- if (isIE) return document.createElement("m:"+t);- else return document.createElementNS(AMmathml,t);-}--function AMcreateMmlNode(t,frag) {-// var node = AMcreateElementMathML(name);- if (isIE) var node = document.createElement("m:"+t);- else var node = document.createElementNS(AMmathml,t);- node.appendChild(frag);- return node;-}--function newcommand(oldstr,newstr) {- AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr, - tex:null, ttype:DEFINITION}]);-}--function AMremoveCharsAndBlanks(str,n) {-//remove n characters and any following blanks- var st;- if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ") - st = str.slice(n+1);- else st = str.slice(n);- for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);- return st.slice(i);-}--function AMposition(arr, str, n) { -// return position >=n where str appears or would be inserted-// assumes arr is sorted- if (n==0) {- var h,m;- n = -1;- h = arr.length;- while (n+1<h) {- m = (n+h) >> 1;- if (arr[m]<str) n = m; else h = m;- }- return h;- } else- for (var i=n; i<arr.length && arr[i]<str; i++);- return i; // i=arr.length || arr[i]>=str-}--function AMgetSymbol(str) {-//return maximal initial substring of str that appears in names-//return null if there is none- var k = 0; //new pos- var j = 0; //old pos- var mk; //match pos- var st;- var tagst;- var match = "";- var more = true;- for (var i=1; i<=str.length && more; i++) {- st = str.slice(0,i); //initial substring of length i- j = k;- k = AMposition(AMnames, st, j);- if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){- match = AMnames[k];- mk = k;- i = match.length;- }- more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];- }- AMpreviousSymbol=AMcurrentSymbol;- if (match!=""){- AMcurrentSymbol=AMsymbols[mk].ttype;- return AMsymbols[mk]; - }-// if str[0] is a digit or - return maxsubstring of digits.digits- AMcurrentSymbol=CONST;- k = 1;- st = str.slice(0,1);- var integ = true;- while ("0"<=st && st<="9" && k<=str.length) {- st = str.slice(k,k+1);- k++;- }- if (st == decimalsign) {- st = str.slice(k,k+1);- if ("0"<=st && st<="9") {- integ = false;- k++;- while ("0"<=st && st<="9" && k<=str.length) {- st = str.slice(k,k+1);- k++;- }- }- }- if ((integ && k>1) || k>2) {- st = str.slice(0,k-1);- tagst = "mn";- } else {- k = 2;- st = str.slice(0,1); //take 1 character- tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");- }- if (st=="-" && AMpreviousSymbol==INFIX) {- AMcurrentSymbol = INFIX; //trick "/" into recognizing "-" on second parse- return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};- }- return {input:st, tag:tagst, output:st, ttype:CONST};-}--function AMremoveBrackets(node) {- var st;- if (node.nodeName=="mrow") {- st = node.firstChild.firstChild.nodeValue;- if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild);- }- if (node.nodeName=="mrow") {- st = node.lastChild.firstChild.nodeValue;- if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild);- }-}--/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL-See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */--var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;--function AMparseSexpr(str) { //parses str and returns [node,tailstr]- var symbol, node, result, i, st,// rightvert = false,- newFrag = document.createDocumentFragment();- str = AMremoveCharsAndBlanks(str,0);- symbol = AMgetSymbol(str); //either a token or a bracket or empty- if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {- return [null,str];- }- if (symbol.ttype == DEFINITION) {- str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length); - symbol = AMgetSymbol(str);- }- switch (symbol.ttype) {- case UNDEROVER:- case CONST:- str = AMremoveCharsAndBlanks(str,symbol.input.length); - return [AMcreateMmlNode(symbol.tag, //its a constant- document.createTextNode(symbol.output)),str];- case LEFTBRACKET: //read (expr+)- AMnestingDepth++;- str = AMremoveCharsAndBlanks(str,symbol.input.length); - result = AMparseExpr(str,true);- AMnestingDepth--;- if (typeof symbol.invisible == "boolean" && symbol.invisible) - node = AMcreateMmlNode("mrow",result[0]);- else {- node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));- node = AMcreateMmlNode("mrow",node);- node.appendChild(result[0]);- }- return [node,result[1]];- case TEXT:- if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);- if (str.charAt(0)=="{") i=str.indexOf("}");- else if (str.charAt(0)=="(") i=str.indexOf(")");- else if (str.charAt(0)=="[") i=str.indexOf("]");- else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1;- else i = 0;- if (i==-1) i = str.length;- st = str.slice(1,i);- if (st.charAt(0) == " ") {- node = AMcreateElementMathML("mspace");- node.setAttribute("width","1ex");- newFrag.appendChild(node);- }- newFrag.appendChild(- AMcreateMmlNode(symbol.tag,document.createTextNode(st)));- if (st.charAt(st.length-1) == " ") {- node = AMcreateElementMathML("mspace");- node.setAttribute("width","1ex");- newFrag.appendChild(node);- }- str = AMremoveCharsAndBlanks(str,i+1);- return [AMcreateMmlNode("mrow",newFrag),str];- case UNARY:- str = AMremoveCharsAndBlanks(str,symbol.input.length); - result = AMparseSexpr(str);- if (result[0]==null) return [AMcreateMmlNode(symbol.tag,- document.createTextNode(symbol.output)),str];- if (typeof symbol.func == "boolean" && symbol.func) { // functions hack- st = str.charAt(0);- if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {- return [AMcreateMmlNode(symbol.tag,- document.createTextNode(symbol.output)),str];- } else {- node = AMcreateMmlNode("mrow",- AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));- node.appendChild(result[0]);- return [node,result[1]];- }- }- AMremoveBrackets(result[0]);- if (symbol.input == "sqrt") { // sqrt- return [AMcreateMmlNode(symbol.tag,result[0]),result[1]];- } else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent- node = AMcreateMmlNode(symbol.tag,result[0]);- node.appendChild(AMcreateMmlNode("mo",document.createTextNode(symbol.output)));- return [node,result[1]];- } else { // font change command- if (!isIE && typeof symbol.codes != "undefined") {- for (i=0; i<result[0].childNodes.length; i++)- if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {- st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:- result[0].childNodes[i].firstChild.nodeValue);- var newst = [];- for (var j=0; j<st.length; j++)- if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst +- String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);- else newst = newst + st.charAt(j);- if (result[0].nodeName=="mi")- result[0]=AMcreateElementMathML("mo").- appendChild(document.createTextNode(newst));- else result[0].replaceChild(AMcreateElementMathML("mo").- appendChild(document.createTextNode(newst)),result[0].childNodes[i]);- }- }- node = AMcreateMmlNode(symbol.tag,result[0]);- node.setAttribute(symbol.atname,symbol.atval);- return [node,result[1]];- }- case BINARY:- str = AMremoveCharsAndBlanks(str,symbol.input.length); - result = AMparseSexpr(str);- if (result[0]==null) return [AMcreateMmlNode("mo",- document.createTextNode(symbol.input)),str];- AMremoveBrackets(result[0]);- var result2 = AMparseSexpr(result[1]);- if (result2[0]==null) return [AMcreateMmlNode("mo",- document.createTextNode(symbol.input)),str];- AMremoveBrackets(result2[0]);- if (symbol.input=="root" || symbol.input=="stackrel") - newFrag.appendChild(result2[0]);- newFrag.appendChild(result[0]);- if (symbol.input=="frac") newFrag.appendChild(result2[0]);- return [AMcreateMmlNode(symbol.tag,newFrag),result2[1]];- case INFIX:- str = AMremoveCharsAndBlanks(str,symbol.input.length); - return [AMcreateMmlNode("mo",document.createTextNode(symbol.output)),str];- case SPACE:- str = AMremoveCharsAndBlanks(str,symbol.input.length); - node = AMcreateElementMathML("mspace");- node.setAttribute("width","1ex");- newFrag.appendChild(node);- newFrag.appendChild(- AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));- node = AMcreateElementMathML("mspace");- node.setAttribute("width","1ex");- newFrag.appendChild(node);- return [AMcreateMmlNode("mrow",newFrag),str];- case LEFTRIGHT:-// if (rightvert) return [null,str]; else rightvert = true;- AMnestingDepth++;- str = AMremoveCharsAndBlanks(str,symbol.input.length); - result = AMparseExpr(str,false);- AMnestingDepth--;- var st = "";- if (result[0].lastChild!=null)- st = result[0].lastChild.firstChild.nodeValue;- if (st == "|") { // its an absolute value subterm- node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));- node = AMcreateMmlNode("mrow",node);- node.appendChild(result[0]);- return [node,result[1]];- } else { // the "|" is a \mid- node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));- node = AMcreateMmlNode("mrow",node);- return [node,str];- }- default:-//alert("default");- str = AMremoveCharsAndBlanks(str,symbol.input.length); - return [AMcreateMmlNode(symbol.tag, //its a constant- document.createTextNode(symbol.output)),str];- }-}--function AMparseIexpr(str) {- var symbol, sym1, sym2, node, result, underover;- str = AMremoveCharsAndBlanks(str,0);- sym1 = AMgetSymbol(str);- result = AMparseSexpr(str);- node = result[0];- str = result[1];- symbol = AMgetSymbol(str);- if (symbol.ttype == INFIX && symbol.input != "/") {- str = AMremoveCharsAndBlanks(str,symbol.input.length);-// if (symbol.input == "/") result = AMparseIexpr(str); else ...- result = AMparseSexpr(str);- if (result[0] == null) // show box in place of missing argument- result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1"));- else AMremoveBrackets(result[0]);- str = result[1];-// if (symbol.input == "/") AMremoveBrackets(node);- if (symbol.input == "_") {- sym2 = AMgetSymbol(str);- underover = (sym1.ttype == UNDEROVER);- if (sym2.input == "^") {- str = AMremoveCharsAndBlanks(str,sym2.input.length);- var res2 = AMparseSexpr(str);- AMremoveBrackets(res2[0]);- str = res2[1];- node = AMcreateMmlNode((underover?"munderover":"msubsup"),node);- node.appendChild(result[0]);- node.appendChild(res2[0]);- node = AMcreateMmlNode("mrow",node); // so sum does not stretch- } else {- node = AMcreateMmlNode((underover?"munder":"msub"),node);- node.appendChild(result[0]);- }- } else {- node = AMcreateMmlNode(symbol.tag,node);- node.appendChild(result[0]);- }- }- return [node,str];-}--function AMparseExpr(str,rightbracket) {- var symbol, node, result, i, nodeList = [],- newFrag = document.createDocumentFragment();- do {- str = AMremoveCharsAndBlanks(str,0);- result = AMparseIexpr(str);- node = result[0];- str = result[1];- symbol = AMgetSymbol(str);- if (symbol.ttype == INFIX && symbol.input == "/") {- str = AMremoveCharsAndBlanks(str,symbol.input.length);- result = AMparseIexpr(str);- if (result[0] == null) // show box in place of missing argument- result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1"));- else AMremoveBrackets(result[0]);- str = result[1];- AMremoveBrackets(node);- node = AMcreateMmlNode(symbol.tag,node);- node.appendChild(result[0]);- newFrag.appendChild(node);- symbol = AMgetSymbol(str);- } - else if (node!=undefined) newFrag.appendChild(node);- } while ((symbol.ttype != RIGHTBRACKET && - (symbol.ttype != LEFTRIGHT || rightbracket)- || AMnestingDepth == 0) && symbol!=null && symbol.output!="");- if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {-// if (AMnestingDepth > 0) AMnestingDepth--;- var len = newFrag.childNodes.length;- if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&- newFrag.childNodes[len-2].nodeName == "mo" &&- newFrag.childNodes[len-2].firstChild.nodeValue == ",") { //matrix- var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;- if (right==")" || right=="]") {- var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;- if (left=="(" && right==")" && symbol.output != "}" || - left=="[" && right=="]") {- var pos = []; // positions of commas- var matrix = true;- var m = newFrag.childNodes.length;- for (i=0; matrix && i<m; i=i+2) {- pos[i] = [];- node = newFrag.childNodes[i];- if (matrix) matrix = node.nodeName=="mrow" && - (i==m-1 || node.nextSibling.nodeName=="mo" && - node.nextSibling.firstChild.nodeValue==",")&&- node.firstChild.firstChild.nodeValue==left &&- node.lastChild.firstChild.nodeValue==right;- if (matrix) - for (var j=0; j<node.childNodes.length; j++)- if (node.childNodes[j].firstChild.nodeValue==",")- pos[i][pos[i].length]=j;- if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;- }- if (matrix) {- var row, frag, n, k, table = document.createDocumentFragment();- for (i=0; i<m; i=i+2) {- row = document.createDocumentFragment();- frag = document.createDocumentFragment();- node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>- n = node.childNodes.length;- k = 0;- node.removeChild(node.firstChild); //remove (- for (j=1; j<n-1; j++) {- if (typeof pos[i][k] != "undefined" && j==pos[i][k]){- node.removeChild(node.firstChild); //remove ,- row.appendChild(AMcreateMmlNode("mtd",frag));- k++;- } else frag.appendChild(node.firstChild);- }- row.appendChild(AMcreateMmlNode("mtd",frag));- if (newFrag.childNodes.length>2) {- newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>- newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>- }- table.appendChild(AMcreateMmlNode("mtr",row));- }- node = AMcreateMmlNode("mtable",table);- if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left");- newFrag.replaceChild(node,newFrag.firstChild);- }- }- }- }- str = AMremoveCharsAndBlanks(str,symbol.input.length);- if (typeof symbol.invisible != "boolean" || !symbol.invisible) {- node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));- newFrag.appendChild(node);- }- }- return [newFrag,str];-}--function AMparseMath(str) {- var result, node = AMcreateElementMathML("mstyle");- if (mathcolor != "") node.setAttribute("mathcolor",mathcolor);- if (displaystyle) node.setAttribute("displaystyle","true");- if (mathfontfamily != "") node.setAttribute("fontfamily",mathfontfamily);- AMnestingDepth = 0;- node.appendChild(AMparseExpr(str.replace(/^\s+/g,""),false)[0]);- node = AMcreateMmlNode("math",node);- if (showasciiformulaonhover) //fixed by djhsu so newline- node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko- if (mathfontfamily != "" && (isIE || mathfontfamily != "serif")) {- var fnode = AMcreateElementXHTML("font");- fnode.setAttribute("face",mathfontfamily);- fnode.appendChild(node);- return fnode;- }- return node;-}--function AMstrarr2docFrag(arr, linebreaks) {- var newFrag=document.createDocumentFragment();- var expr = false;- for (var i=0; i<arr.length; i++) {- if (expr) newFrag.appendChild(AMparseMath(arr[i]));- else {- var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);- newFrag.appendChild(AMcreateElementXHTML("span").- appendChild(document.createTextNode(arri[0])));- for (var j=1; j<arri.length; j++) {- newFrag.appendChild(AMcreateElementXHTML("p"));- newFrag.appendChild(AMcreateElementXHTML("span").- appendChild(document.createTextNode(arri[j])));- }- }- expr = !expr;- }- return newFrag;-}--function AMprocessNodeR(n, linebreaks) {- var mtch, str, arr, frg, i;- if (n.childNodes.length == 0) {- if ((n.nodeType!=8 || linebreaks) &&- n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&- n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" &&- n.parentNode.nodeName!="code" && n.parentNode.nodeName!="CODE" && /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL-See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */- n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE") {- str = n.nodeValue;- if (!(str == null)) {- str = str.replace(/\r\n\r\n/g,"\n\n");- if (doubleblankmathdelimiter) {- str = str.replace(/\x20\x20\./g," "+AMdelimiter1+".");- str = str.replace(/\x20\x20,/g," "+AMdelimiter1+",");- str = str.replace(/\x20\x20/g," "+AMdelimiter1+" ");- }- str = str.replace(/\x20+/g," ");- str = str.replace(/\s*\r\n/g," ");- mtch = false;- str = str.replace(new RegExp(AMescape2, "g"),- function(st){mtch=true;return "AMescape2"});- str = str.replace(new RegExp(AMescape1, "g"),- function(st){mtch=true;return "AMescape1"});- str = str.replace(new RegExp(AMdelimiter2regexp, "g"),AMdelimiter1);- arr = str.split(AMdelimiter1);- for (i=0; i<arr.length; i++)- arr[i]=arr[i].replace(/AMescape2/g,AMdelimiter2).- replace(/AMescape1/g,AMdelimiter1);- if (arr.length>1 || mtch) {- if (checkForMathML) {- checkForMathML = false;- var nd = AMisMathMLavailable();- AMnoMathML = nd != null;- if (AMnoMathML && notifyIfNoMathML) - if (alertIfNoMathML)- alert("To view the ASCIIMathML notation use Internet Explorer 6 +\nMathPlayer (free from www.dessci.com)\n\- or Firefox/Mozilla/Netscape");- else AMbody.insertBefore(nd,AMbody.childNodes[0]);- }- if (!AMnoMathML) {- frg = AMstrarr2docFrag(arr,n.nodeType==8);- var len = frg.childNodes.length;- n.parentNode.replaceChild(frg,n);- return len-1;- } else return 0;- }- }- } else return 0;- } else if (n.nodeName!="math") {- for (i=0; i<n.childNodes.length; i++)- i += AMprocessNodeR(n.childNodes[i], linebreaks);- }- return 0;-}--function AMprocessNode(n, linebreaks, spanclassAM) {- var frag,st;- if (spanclassAM!=null) {- frag = document.getElementsByTagName("span")- for (var i=0;i<frag.length;i++)- if (frag[i].className == "AM")- AMprocessNodeR(frag[i],linebreaks);- } else {- try {- st = n.innerHTML;- } catch(err) {}- if (st==null || - st.indexOf(AMdelimiter1)!=-1 || st.indexOf(AMdelimiter2)!=-1) - AMprocessNodeR(n,linebreaks);- }- if (isIE) { //needed to match size and font of formula to surrounding text- frag = document.getElementsByTagName('math');- for (var i=0;i<frag.length;i++) frag[i].update()- }-}--var AMbody;-var AMnoMathML = false, AMtranslated = false;--function translate(spanclassAM) {- if (!AMtranslated) { // run this only once- AMtranslated = true;- AMinitSymbols();- AMbody = document.getElementsByTagName("body")[0];- AMprocessNode(AMbody, false, spanclassAM);- }-}--if (isIE) { // avoid adding MathPlayer info explicitly to each webpage- document.write("<object id=\"mathplayer\"\- classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");- document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");-}--// GO1.1 Generic onload by Brothercake -// http://www.brothercake.com/-//onload function (replaces the onload="translate()" in the <body> tag)-function generic()-{- translate();+var mathcolor = ""; // change it to "" (to inherit) or another color+var mathfontsize = "1em"; // change to e.g. 1.2em for larger math+var mathfontfamily = "serif"; // change to "" to inherit (works in IE) + // or another family (e.g. "arial")+var automathrecognize = false; // writing "amath" on page makes this true+var checkForMathML = true; // check if browser can display MathML+var notifyIfNoMathML = true; // display note at top if no MathML capability+var alertIfNoMathML = false; // show alert box if no MathML capability+var translateOnLoad = true; // set to false to do call translators from js +var translateLaTeX = true; // false to preserve $..$, $$..$$+var translateLaTeXformatting = true; // false to preserve \emph,\begin{},\end{}+var translateASCIIMath = true; // false to preserve `..`+var translateASCIIsvg = true; // false to preserve agraph.., \begin{graph}..+var avoidinnerHTML = false; // set true if assigning to innerHTML gives error+var displaystyle = true; // puts limits above and below large operators+var showasciiformulaonhover = true; // helps students learn ASCIIMath+var decimalsign = "."; // change to "," if you like, beware of `(1,2)`!+var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters+var AMdocumentId = "wikitext" // PmWiki element containing math (default=body)+var checkforprocessasciimathinmoodle = false; // true for systems like Moodle+var dsvglocation = ""; // path to d.svg (blank if same as ASCIIMathML.js loc)++/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */++var isIE = document.createElementNS==null;+var noMathML = false, translated = false;++if (isIE) { // avoid adding MathPlayer info explicitly to each webpage+ document.write("<object id=\"mathplayer\"\+ classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");+ document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");+}++// Add a stylesheet, replacing any previous custom stylesheet (adapted from TW)+function setStylesheet(s) {+ var id = "AMMLcustomStyleSheet";+ var n = document.getElementById(id);+ if(document.createStyleSheet) {+ // Test for IE's non-standard createStyleSheet method+ if(n)+ n.parentNode.removeChild(n);+ // This failed without the + document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd"," <style id='" + id + "'>" + s + "</style>");+ } else {+ if(n) {+ n.replaceChild(document.createTextNode(s),n.firstChild);+ } else {+ n = document.createElement("style");+ n.type = "text/css";+ n.id = id;+ n.appendChild(document.createTextNode(s));+ document.getElementsByTagName("head")[0].appendChild(n);+ }+ }+}++setStylesheet("#AMMLcloseDiv \{font-size:0.8em; padding-top:1em; color:#014\}\n#AMMLwarningBox \{position:absolute; width:100%; top:0; left:0; z-index:200; text-align:center; font-size:1em; font-weight:bold; padding:0.5em 0 0.5em 0; color:#ffc; background:#c30\}");++function init(){+ var msg, warnings = new Array();+ if (document.getElementById==null){+ alert("This webpage requires a recent browser such as Mozilla Firefox/Netscape 7+ or Internet Explorer 6+ with MathPlayer and Adobe SVGviewer");+ return null;+ }+ if (checkForMathML && (msg = checkMathML())) warnings.push(msg);+ if (checkIfSVGavailable && (msg = checkSVG())) warnings.push(msg);+ if (warnings.length>0) displayWarnings(warnings);+ if (!noMathML) initSymbols();+ return true;+}++function checkMathML(){+ if (navigator.appName.slice(0,8)=="Netscape") + if (navigator.appVersion.slice(0,1)>="5") noMathML = null;+ else noMathML = true;+ else if (navigator.appName.slice(0,9)=="Microsoft")+ try {+ var ActiveX = new ActiveXObject("MathPlayer.Factory.1");+ noMathML = null;+ } catch (e) {+ noMathML = true;+ }+ else noMathML = true;+//noMathML = true; //uncomment to check+ if (noMathML && notifyIfNoMathML) {+ var msg = "To view the ASCIIMathML notation use Internet Explorer + MathPlayer or Mozilla Firefox 2.0 or later.";+ if (alertIfNoMathML)+ alert(msg);+ else return msg;+ }+}++function hideWarning(){+ var body = document.getElementsByTagName("body")[0];+ body.removeChild(document.getElementById('AMMLwarningBox'));+ body.onclick = null;+}++function displayWarnings(warnings) {+ var i, frag, nd = createElementXHTML("div");+ var body = document.getElementsByTagName("body")[0];+ body.onclick=hideWarning;+ nd.id = 'AMMLwarningBox';+ for (i=0; i<warnings.length; i++) {+ frag = createElementXHTML("div");+ frag.appendChild(document.createTextNode(warnings[i]));+ frag.style.paddingBottom = "1.0em";+ nd.appendChild(frag);+ }+ nd.appendChild(createElementXHTML("p"));+ nd.appendChild(document.createTextNode("For instructions see the "));+ var an = createElementXHTML("a");+ an.appendChild(document.createTextNode("ASCIIMathML"));+ an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html");+ nd.appendChild(an);+ nd.appendChild(document.createTextNode(" homepage"));+ an = createElementXHTML("div");+ an.id = 'AMMLcloseDiv';+ an.appendChild(document.createTextNode('(click anywhere to close this warning)'));+ nd.appendChild(an);+ var body = document.getElementsByTagName("body")[0];+ body.insertBefore(nd,body.childNodes[0]);+}++function translate(spanclassAM) {+ if (!translated) { // run this only once+ translated = true;+ var body = document.getElementsByTagName("body")[0];+ var processN = document.getElementById(AMdocumentId);+ if (translateLaTeX) LMprocessNode((processN!=null?processN:body));+ if (translateASCIIMath) AMprocessNode((processN!=null?processN:body), false, spanclassAM);+ }+}++function createElementXHTML(t) {+ if (isIE) return document.createElement(t);+ else return document.createElementNS("http://www.w3.org/1999/xhtml",t);+}++function createMmlNode(t,frag) {+ if (isIE) var node = document.createElement("m:"+t);+ else var node = document.createElementNS("http://www.w3.org/1998/Math/MathML",t);+ if (frag) node.appendChild(frag);+ return node;+}++// character lists for Mozilla/Netscape fonts+var AMcal = [0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];+var AMfrk = [0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];+var AMbbb = [0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];++var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,+ RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,+ LEFTRIGHT = 9, TEXT = 10, BIG = 11, LONG = 12, STRETCHY = 13,+ MATRIX = 14;; // token types++var AMquote = {input:"\"", tag:"mtext", output:"mbox", tex:null, ttype:TEXT};++var AMsymbols = [+//some greek symbols+{input:"alpha", tag:"mi", output:"\u03B1", tex:null, ttype:CONST},+{input:"beta", tag:"mi", output:"\u03B2", tex:null, ttype:CONST},+{input:"chi", tag:"mi", output:"\u03C7", tex:null, ttype:CONST},+{input:"delta", tag:"mi", output:"\u03B4", tex:null, ttype:CONST},+{input:"Delta", tag:"mo", output:"\u0394", tex:null, ttype:CONST},+{input:"epsi", tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST},+{input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST},+{input:"eta", tag:"mi", output:"\u03B7", tex:null, ttype:CONST},+{input:"gamma", tag:"mi", output:"\u03B3", tex:null, ttype:CONST},+{input:"Gamma", tag:"mo", output:"\u0393", tex:null, ttype:CONST},+{input:"iota", tag:"mi", output:"\u03B9", tex:null, ttype:CONST},+{input:"kappa", tag:"mi", output:"\u03BA", tex:null, ttype:CONST},+{input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},+{input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},+{input:"mu", tag:"mi", output:"\u03BC", tex:null, ttype:CONST},+{input:"nu", tag:"mi", output:"\u03BD", tex:null, ttype:CONST},+{input:"omega", tag:"mi", output:"\u03C9", tex:null, ttype:CONST},+{input:"Omega", tag:"mo", output:"\u03A9", tex:null, ttype:CONST},+{input:"phi", tag:"mi", output:"\u03C6", tex:null, ttype:CONST},+{input:"varphi", tag:"mi", output:"\u03D5", tex:null, ttype:CONST},+{input:"Phi", tag:"mo", output:"\u03A6", tex:null, ttype:CONST},+{input:"pi", tag:"mi", output:"\u03C0", tex:null, ttype:CONST},+{input:"Pi", tag:"mo", output:"\u03A0", tex:null, ttype:CONST},+{input:"psi", tag:"mi", output:"\u03C8", tex:null, ttype:CONST},+{input:"Psi", tag:"mi", output:"\u03A8", tex:null, ttype:CONST},+{input:"rho", tag:"mi", output:"\u03C1", tex:null, ttype:CONST},+{input:"sigma", tag:"mi", output:"\u03C3", tex:null, ttype:CONST},+{input:"Sigma", tag:"mo", output:"\u03A3", tex:null, ttype:CONST},+{input:"tau", tag:"mi", output:"\u03C4", tex:null, ttype:CONST},+{input:"theta", tag:"mi", output:"\u03B8", tex:null, ttype:CONST},+{input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST},+{input:"Theta", tag:"mo", output:"\u0398", tex:null, ttype:CONST},+{input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST},+{input:"xi", tag:"mi", output:"\u03BE", tex:null, ttype:CONST},+{input:"Xi", tag:"mo", output:"\u039E", tex:null, ttype:CONST},+{input:"zeta", tag:"mi", output:"\u03B6", tex:null, ttype:CONST},++//binary operation symbols+//{input:"-", tag:"mo", output:"\u0096", tex:null, ttype:CONST},+{input:"*", tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST},+{input:"**", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST},+{input:"//", tag:"mo", output:"/", tex:null, ttype:CONST},+{input:"\\\\", tag:"mo", output:"\\", tex:"backslash", ttype:CONST},+{input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST},+{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST},+{input:"-:", tag:"mo", output:"\u00F7", tex:"divide", ttype:CONST},+{input:"@", tag:"mo", output:"\u2218", tex:"circ", ttype:CONST},+{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST},+{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST},+{input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST},+{input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER},+{input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER},+{input:"^^", tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST},+{input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER},+{input:"vv", tag:"mo", output:"\u2228", tex:"vee", ttype:CONST},+{input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER},+{input:"nn", tag:"mo", output:"\u2229", tex:"cap", ttype:CONST},+{input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER},+{input:"uu", tag:"mo", output:"\u222A", tex:"cup", ttype:CONST},+{input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER},++//binary relation symbols+{input:"!=", tag:"mo", output:"\u2260", tex:"ne", ttype:CONST},+{input:":=", tag:"mo", output:":=", tex:null, ttype:CONST},+{input:"lt", tag:"mo", output:"<", tex:null, ttype:CONST},+{input:"<=", tag:"mo", output:"\u2264", tex:"le", ttype:CONST},+{input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST},+{input:">=", tag:"mo", output:"\u2265", tex:"ge", ttype:CONST},+{input:"geq", tag:"mo", output:"\u2265", tex:null, ttype:CONST},+{input:"-<", tag:"mo", output:"\u227A", tex:"prec", ttype:CONST},+{input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST},+{input:">-", tag:"mo", output:"\u227B", tex:"succ", ttype:CONST},+{input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST},+{input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST},+{input:"in", tag:"mo", output:"\u2208", tex:null, ttype:CONST},+{input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST},+{input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST},+{input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST},+{input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST},+{input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST},+{input:"-=", tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST},+{input:"~=", tag:"mo", output:"\u2245", tex:"cong", ttype:CONST},+{input:"~~", tag:"mo", output:"\u2248", tex:"approx", ttype:CONST},+{input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST},++//logical symbols+{input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE},+{input:"or", tag:"mtext", output:"or", tex:null, ttype:SPACE},+{input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST},+{input:"=>", tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST},+{input:"if", tag:"mo", output:"if", tex:null, ttype:SPACE},+{input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST},+{input:"AA", tag:"mo", output:"\u2200", tex:"forall", ttype:CONST},+{input:"EE", tag:"mo", output:"\u2203", tex:"exists", ttype:CONST},+{input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST},+{input:"TT", tag:"mo", output:"\u22A4", tex:"top", ttype:CONST},+{input:"|--", tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST},+{input:"|==", tag:"mo", output:"\u22A8", tex:"models", ttype:CONST},++//grouping brackets+{input:"(", tag:"mo", output:"(", tex:null, ttype:LEFTBRACKET},+{input:")", tag:"mo", output:")", tex:null, ttype:RIGHTBRACKET},+{input:"[", tag:"mo", output:"[", tex:null, ttype:LEFTBRACKET},+{input:"]", tag:"mo", output:"]", tex:null, ttype:RIGHTBRACKET},+{input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET},+{input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET},+{input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT},+//{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},+{input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET},+{input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET},+{input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET},+{input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET},+{input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true},+{input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true},++//miscellaneous symbols+{input:"int", tag:"mo", output:"\u222B", tex:null, ttype:CONST},+{input:"dx", tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION},+{input:"dy", tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION},+{input:"dz", tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION},+{input:"dt", tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION},+{input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST},+{input:"del", tag:"mo", output:"\u2202", tex:"partial", ttype:CONST},+{input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST},+{input:"+-", tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST},+{input:"O/", tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST},+{input:"oo", tag:"mo", output:"\u221E", tex:"infty", ttype:CONST},+{input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST},+{input:"...", tag:"mo", output:"...", tex:"ldots", ttype:CONST},+{input:":.", tag:"mo", output:"\u2234", tex:"therefore", ttype:CONST},+{input:"/_", tag:"mo", output:"\u2220", tex:"angle", ttype:CONST},+{input:"\\ ", tag:"mo", output:"\u00A0", tex:null, ttype:CONST},+{input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST},+{input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST},+{input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST},+{input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST},+{input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST},+{input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST},+{input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST},+{input:"|__", tag:"mo", output:"\u230A", tex:"lfloor", ttype:CONST},+{input:"__|", tag:"mo", output:"\u230B", tex:"rfloor", ttype:CONST},+{input:"|~", tag:"mo", output:"\u2308", tex:"lceiling", ttype:CONST},+{input:"~|", tag:"mo", output:"\u2309", tex:"rceiling", ttype:CONST},+{input:"CC", tag:"mo", output:"\u2102", tex:null, ttype:CONST},+{input:"NN", tag:"mo", output:"\u2115", tex:null, ttype:CONST},+{input:"QQ", tag:"mo", output:"\u211A", tex:null, ttype:CONST},+{input:"RR", tag:"mo", output:"\u211D", tex:null, ttype:CONST},+{input:"ZZ", tag:"mo", output:"\u2124", tex:null, ttype:CONST},+{input:"f", tag:"mi", output:"f", tex:null, ttype:UNARY, func:true},+{input:"g", tag:"mi", output:"g", tex:null, ttype:UNARY, func:true},++//standard functions+{input:"lim", tag:"mo", output:"lim", tex:null, ttype:UNDEROVER},+{input:"Lim", tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER},+{input:"sin", tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true},+{input:"cos", tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true},+{input:"tan", tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true},+{input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true},+{input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true},+{input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true},+{input:"cot", tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true},+{input:"sec", tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true},+{input:"csc", tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true},+{input:"log", tag:"mo", output:"log", tex:null, ttype:UNARY, func:true},+{input:"ln", tag:"mo", output:"ln", tex:null, ttype:UNARY, func:true},+{input:"det", tag:"mo", output:"det", tex:null, ttype:UNARY, func:true},+{input:"dim", tag:"mo", output:"dim", tex:null, ttype:CONST},+{input:"mod", tag:"mo", output:"mod", tex:null, ttype:CONST},+{input:"gcd", tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true},+{input:"lcm", tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true},+{input:"lub", tag:"mo", output:"lub", tex:null, ttype:CONST},+{input:"glb", tag:"mo", output:"glb", tex:null, ttype:CONST},+{input:"min", tag:"mo", output:"min", tex:null, ttype:UNDEROVER},+{input:"max", tag:"mo", output:"max", tex:null, ttype:UNDEROVER},++//arrows+{input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST},+{input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST},+{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST},+{input:"->", tag:"mo", output:"\u2192", tex:"to", ttype:CONST},+{input:">->", tag:"mo", output:"\u21A3", tex:"rightarrowtail", ttype:CONST},+{input:"->>", tag:"mo", output:"\u21A0", tex:"twoheadrightarrow", ttype:CONST},+{input:">->>", tag:"mo", output:"\u2916", tex:"twoheadrightarrowtail", ttype:CONST},+{input:"|->", tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST},+{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST},+{input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST},+{input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST},+{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST},+{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST},+//commands with argument+{input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY},+{input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY},+{input:"frac", tag:"mfrac", output:"/", tex:null, ttype:BINARY},+{input:"/", tag:"mfrac", output:"/", tex:null, ttype:INFIX},+{input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},+{input:"_", tag:"msub", output:"_", tex:null, ttype:INFIX},+{input:"^", tag:"msup", output:"^", tex:null, ttype:INFIX},+{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true},+{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true},+{input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true},+{input:"dot", tag:"mover", output:".", tex:null, ttype:UNARY, acc:true},+{input:"ddot", tag:"mover", output:"..", tex:null, ttype:UNARY, acc:true},+{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true},+{input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT},+{input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT},+AMquote,+{input:"bb", tag:"mstyle", atname:"fontweight", atval:"bold", output:"bb", tex:null, ttype:UNARY},+{input:"mathbf", tag:"mstyle", atname:"fontweight", atval:"bold", output:"mathbf", tex:null, ttype:UNARY},+{input:"sf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY},+{input:"mathsf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY},+{input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb},+{input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb},+{input:"cc", tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal},+{input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal},+{input:"tt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"tt", tex:null, ttype:UNARY},+{input:"mathtt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY},+{input:"fr", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk},+{input:"mathfrak", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk}+];++function compareNames(s1,s2) {+ if (s1.input > s2.input) return 1+ else return -1;+}++var AMnames = []; //list of input symbols++function initSymbols() {+ var texsymbols = [], i;+ for (i=0; i<AMsymbols.length; i++)+ if (AMsymbols[i].tex) + texsymbols[texsymbols.length] = {input:AMsymbols[i].tex, + tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype};+ AMsymbols = AMsymbols.concat(texsymbols);+ refreshSymbols();+}++function refreshSymbols(){+ var i;+ AMsymbols.sort(compareNames);+ for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;+ LMsymbols.sort(compareNames);+ for (i=0; i<LMsymbols.length; i++) LMnames[i] = LMsymbols[i].input;+}++function define(oldstr,newstr) {+ if(oldstr.substr(0,1)=="\\")+ LMsymbols = LMsymbols.concat([{input:oldstr, tag:"mo", output:newstr,+ ttype:DEFINITION}]);+ else+ AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr, + tex:null, ttype:DEFINITION}]);+ refreshSymbols(); // this may be a problem if many symbols are defined!+}++function AMremoveCharsAndBlanks(str,n) {+//remove n characters and any following blanks+ var st;+ if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ") + st = str.slice(n+1);+ else st = str.slice(n);+ for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);+ return st.slice(i);+}++function position(arr, str, n) { +// return position >=n where str appears or would be inserted+// assumes arr is sorted+ if (n==0) {+ var h,m;+ n = -1;+ h = arr.length;+ while (n+1<h) {+ m = (n+h) >> 1;+ if (arr[m]<str) n = m; else h = m;+ }+ return h;+ } else+ for (var i=n; i<arr.length && arr[i]<str; i++);+ return i; // i=arr.length || arr[i]>=str+}++function AMgetSymbol(str) {+//return maximal initial substring of str that appears in names+//return null if there is none+ var k = 0; //new pos+ var j = 0; //old pos+ var mk; //match pos+ var st;+ var tagst;+ var match = "";+ var more = true;+ for (var i=1; i<=str.length && more; i++) {+ st = str.slice(0,i); //initial substring of length i+ j = k;+ k = position(AMnames, st, j);+ if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){+ match = AMnames[k];+ mk = k;+ i = match.length;+ }+ more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];+ }+ AMpreviousSymbol=AMcurrentSymbol;+ if (match!=""){+ AMcurrentSymbol=AMsymbols[mk].ttype;+ return AMsymbols[mk]; + }+// if str[0] is a digit or - return maxsubstring of digits.digits+ AMcurrentSymbol=CONST;+ k = 1;+ st = str.slice(0,1);+ var integ = true;+ while ("0"<=st && st<="9" && k<=str.length) {+ st = str.slice(k,k+1);+ k++;+ }+ if (st == decimalsign) {+ st = str.slice(k,k+1);+ if ("0"<=st && st<="9") {+ integ = false;+ k++;+ while ("0"<=st && st<="9" && k<=str.length) {+ st = str.slice(k,k+1);+ k++;+ }+ }+ }+ if ((integ && k>1) || k>2) {+ st = str.slice(0,k-1);+ tagst = "mn";+ } else {+ k = 2;+ st = str.slice(0,1); //take 1 character+ tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");+ }+ if (st=="-" && AMpreviousSymbol==INFIX) {+ AMcurrentSymbol = INFIX; //trick "/" into recognizing "-" on second parse+ return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};+ }+ return {input:st, tag:tagst, output:st, ttype:CONST};+}++function AMremoveBrackets(node) {+ var st;+ if (node.nodeName=="mrow") {+ st = node.firstChild.firstChild.nodeValue;+ if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild);+ }+ if (node.nodeName=="mrow") {+ st = node.lastChild.firstChild.nodeValue;+ if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild);+ }+}++/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */++var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;++function AMparseSexpr(str) { //parses str and returns [node,tailstr]+ var symbol, node, result, i, st,// rightvert = false,+ newFrag = document.createDocumentFragment();+ str = AMremoveCharsAndBlanks(str,0);+ symbol = AMgetSymbol(str); //either a token or a bracket or empty+ if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {+ return [null,str];+ }+ if (symbol.ttype == DEFINITION) {+ str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length); + symbol = AMgetSymbol(str);+ }+ switch (symbol.ttype) { case UNDEROVER:+ case CONST:+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + return [createMmlNode(symbol.tag, //its a constant+ document.createTextNode(symbol.output)),str];+ case LEFTBRACKET: //read (expr+)+ AMnestingDepth++;+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + result = AMparseExpr(str,true);+ AMnestingDepth--;+ if (typeof symbol.invisible == "boolean" && symbol.invisible) + node = createMmlNode("mrow",result[0]);+ else {+ node = createMmlNode("mo",document.createTextNode(symbol.output));+ node = createMmlNode("mrow",node);+ node.appendChild(result[0]);+ }+ return [node,result[1]];+ case TEXT:+ if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);+ if (str.charAt(0)=="{") i=str.indexOf("}");+ else if (str.charAt(0)=="(") i=str.indexOf(")");+ else if (str.charAt(0)=="[") i=str.indexOf("]");+ else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1;+ else i = 0;+ if (i==-1) i = str.length;+ st = str.slice(1,i);+ if (st.charAt(0) == " ") {+ node = createMmlNode("mspace");+ node.setAttribute("width","1ex");+ newFrag.appendChild(node);+ }+ newFrag.appendChild(+ createMmlNode(symbol.tag,document.createTextNode(st)));+ if (st.charAt(st.length-1) == " ") {+ node = createMmlNode("mspace");+ node.setAttribute("width","1ex");+ newFrag.appendChild(node);+ }+ str = AMremoveCharsAndBlanks(str,i+1);+ return [createMmlNode("mrow",newFrag),str];+ case UNARY:+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + result = AMparseSexpr(str);+ if (result[0]==null) return [createMmlNode(symbol.tag,+ document.createTextNode(symbol.output)),str];+ if (typeof symbol.func == "boolean" && symbol.func) { // functions hack+ st = str.charAt(0);+ if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {+ return [createMmlNode(symbol.tag,+ document.createTextNode(symbol.output)),str];+ } else {+ node = createMmlNode("mrow",+ createMmlNode(symbol.tag,document.createTextNode(symbol.output)));+ node.appendChild(result[0]);+ return [node,result[1]];+ }+ }+ AMremoveBrackets(result[0]);+ if (symbol.input == "sqrt") { // sqrt+ return [createMmlNode(symbol.tag,result[0]),result[1]];+ } else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent+ node = createMmlNode(symbol.tag,result[0]);+ node.appendChild(createMmlNode("mo",document.createTextNode(symbol.output)));+ return [node,result[1]];+ } else { // font change command+ if (!isIE && typeof symbol.codes != "undefined") {+ for (i=0; i<result[0].childNodes.length; i++)+ if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {+ st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:+ result[0].childNodes[i].firstChild.nodeValue);+ var newst = [];+ for (var j=0; j<st.length; j++)+ if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst ++ String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);+ else newst = newst + st.charAt(j);+ if (result[0].nodeName=="mi")+ result[0]=createMmlNode("mo").+ appendChild(document.createTextNode(newst));+ else result[0].replaceChild(createMmlNode("mo").+ appendChild(document.createTextNode(newst)),+ result[0].childNodes[i]);+ }+ }+ node = createMmlNode(symbol.tag,result[0]);+ node.setAttribute(symbol.atname,symbol.atval);+ return [node,result[1]];+ }+ case BINARY:+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + result = AMparseSexpr(str);+ if (result[0]==null) return [createMmlNode("mo",+ document.createTextNode(symbol.input)),str];+ AMremoveBrackets(result[0]);+ var result2 = AMparseSexpr(result[1]);+ if (result2[0]==null) return [createMmlNode("mo",+ document.createTextNode(symbol.input)),str];+ AMremoveBrackets(result2[0]);+ if (symbol.input=="root" || symbol.input=="stackrel") + newFrag.appendChild(result2[0]);+ newFrag.appendChild(result[0]);+ if (symbol.input=="frac") newFrag.appendChild(result2[0]);+ return [createMmlNode(symbol.tag,newFrag),result2[1]];+ case INFIX:+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + return [createMmlNode("mo",document.createTextNode(symbol.output)),str];+ case SPACE:+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + node = createMmlNode("mspace");+ node.setAttribute("width","1ex");+ newFrag.appendChild(node);+ newFrag.appendChild(+ createMmlNode(symbol.tag,document.createTextNode(symbol.output)));+ node = createMmlNode("mspace");+ node.setAttribute("width","1ex");+ newFrag.appendChild(node);+ return [createMmlNode("mrow",newFrag),str];+ case LEFTRIGHT:+// if (rightvert) return [null,str]; else rightvert = true;+ AMnestingDepth++;+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + result = AMparseExpr(str,false);+ AMnestingDepth--;+ var st = "";+ if (result[0].lastChild!=null)+ st = result[0].lastChild.firstChild.nodeValue;+ if (st == "|") { // its an absolute value subterm+ node = createMmlNode("mo",document.createTextNode(symbol.output));+ node = createMmlNode("mrow",node);+ node.appendChild(result[0]);+ return [node,result[1]];+ } else { // the "|" is a \mid so use unicode 2223 (divides) for spacing+ node = createMmlNode("mo",document.createTextNode("\u2223"));+ node = createMmlNode("mrow",node);+ return [node,str];+ }+ default:+//alert("default");+ str = AMremoveCharsAndBlanks(str,symbol.input.length); + return [createMmlNode(symbol.tag, //its a constant+ document.createTextNode(symbol.output)),str];+ }+}++function AMparseIexpr(str) {+ var symbol, sym1, sym2, node, result, underover;+ str = AMremoveCharsAndBlanks(str,0);+ sym1 = AMgetSymbol(str);+ result = AMparseSexpr(str);+ node = result[0];+ str = result[1];+ symbol = AMgetSymbol(str);+ if (symbol.ttype == INFIX && symbol.input != "/") {+ str = AMremoveCharsAndBlanks(str,symbol.input.length);+// if (symbol.input == "/") result = AMparseIexpr(str); else ...+ result = AMparseSexpr(str);+ if (result[0] == null) // show box in place of missing argument+ result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));+ else AMremoveBrackets(result[0]);+ str = result[1];+// if (symbol.input == "/") AMremoveBrackets(node);+ if (symbol.input == "_") {+ sym2 = AMgetSymbol(str);+ underover = (sym1.ttype == UNDEROVER);+ if (sym2.input == "^") {+ str = AMremoveCharsAndBlanks(str,sym2.input.length);+ var res2 = AMparseSexpr(str);+ AMremoveBrackets(res2[0]);+ str = res2[1];+ node = createMmlNode((underover?"munderover":"msubsup"),node);+ node.appendChild(result[0]);+ node.appendChild(res2[0]);+ node = createMmlNode("mrow",node); // so sum does not stretch+ } else {+ node = createMmlNode((underover?"munder":"msub"),node);+ node.appendChild(result[0]);+ }+ } else {+ node = createMmlNode(symbol.tag,node);+ node.appendChild(result[0]);+ }+ }+ return [node,str];+}++function AMparseExpr(str,rightbracket) {+ var symbol, node, result, i, nodeList = [],+ newFrag = document.createDocumentFragment();+ do {+ str = AMremoveCharsAndBlanks(str,0);+ result = AMparseIexpr(str);+ node = result[0];+ str = result[1];+ symbol = AMgetSymbol(str);+ if (symbol.ttype == INFIX && symbol.input == "/") {+ str = AMremoveCharsAndBlanks(str,symbol.input.length);+ result = AMparseIexpr(str);+ if (result[0] == null) // show box in place of missing argument+ result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));+ else AMremoveBrackets(result[0]);+ str = result[1];+ AMremoveBrackets(node);+ node = createMmlNode(symbol.tag,node);+ node.appendChild(result[0]);+ newFrag.appendChild(node);+ symbol = AMgetSymbol(str);+ } + else if (node!=undefined) newFrag.appendChild(node);+ } while ((symbol.ttype != RIGHTBRACKET && + (symbol.ttype != LEFTRIGHT || rightbracket)+ || AMnestingDepth == 0) && symbol!=null && symbol.output!="");+ if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {+// if (AMnestingDepth > 0) AMnestingDepth--;+ var len = newFrag.childNodes.length;+ if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&+ newFrag.childNodes[len-2].nodeName == "mo" &&+ newFrag.childNodes[len-2].firstChild.nodeValue == ",") { //matrix+ var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;+ if (right==")" || right=="]") {+ var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;+ if (left=="(" && right==")" && symbol.output != "}" || + left=="[" && right=="]") {+ var pos = []; // positions of commas+ var matrix = true;+ var m = newFrag.childNodes.length;+ for (i=0; matrix && i<m; i=i+2) {+ pos[i] = [];+ node = newFrag.childNodes[i];+ if (matrix) matrix = node.nodeName=="mrow" && + (i==m-1 || node.nextSibling.nodeName=="mo" && + node.nextSibling.firstChild.nodeValue==",")&&+ node.firstChild.firstChild.nodeValue==left &&+ node.lastChild.firstChild.nodeValue==right;+ if (matrix) + for (var j=0; j<node.childNodes.length; j++)+ if (node.childNodes[j].firstChild.nodeValue==",")+ pos[i][pos[i].length]=j;+ if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;+ }+ if (matrix) {+ var row, frag, n, k, table = document.createDocumentFragment();+ for (i=0; i<m; i=i+2) {+ row = document.createDocumentFragment();+ frag = document.createDocumentFragment();+ node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>+ n = node.childNodes.length;+ k = 0;+ node.removeChild(node.firstChild); //remove (+ for (j=1; j<n-1; j++) {+ if (typeof pos[i][k] != "undefined" && j==pos[i][k]){+ node.removeChild(node.firstChild); //remove ,+ row.appendChild(createMmlNode("mtd",frag));+ k++;+ } else frag.appendChild(node.firstChild);+ }+ row.appendChild(createMmlNode("mtd",frag));+ if (newFrag.childNodes.length>2) {+ newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>+ newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>+ }+ table.appendChild(createMmlNode("mtr",row));+ }+ node = createMmlNode("mtable",table);+ if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left");+ newFrag.replaceChild(node,newFrag.firstChild);+ }+ }+ }+ }+ str = AMremoveCharsAndBlanks(str,symbol.input.length);+ if (typeof symbol.invisible != "boolean" || !symbol.invisible) {+ node = createMmlNode("mo",document.createTextNode(symbol.output));+ newFrag.appendChild(node);+ }+ }+ return [newFrag,str];+}++function parseMath(str,latex) {+ var frag, node;+ AMnestingDepth = 0;+ frag = latex ? LMparseExpr(str.replace(/^\s+/g,""),false,false)[0] : AMparseExpr(str.replace(/^\s+/g,""),false)[0];+ node = createMmlNode("mstyle",frag);+ node.setAttribute("mathcolor",mathcolor);+ node.setAttribute("fontfamily",mathfontfamily);+ node.setAttribute("mathsize",mathfontsize);+ if (displaystyle) node.setAttribute("displaystyle","true");+ node = createMmlNode("math",node);+ if (showasciiformulaonhover) //fixed by djhsu so newline+ node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko+ return node;+}++function strarr2docFrag(arr, linebreaks, latex) {+ var newFrag=document.createDocumentFragment();+ var expr = false;+ for (var i=0; i<arr.length; i++) {+ if (expr) newFrag.appendChild(parseMath(arr[i],latex));+ else {+ var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);+ newFrag.appendChild(createElementXHTML("span").+ appendChild(document.createTextNode(arri[0])));+ for (var j=1; j<arri.length; j++) {+ newFrag.appendChild(createElementXHTML("p"));+ newFrag.appendChild(createElementXHTML("span").+ appendChild(document.createTextNode(arri[j])));+ }+ }+ expr = !expr;+ }+ return newFrag;+}++function AMautomathrec(str) {+//formula is a space (or start of str) followed by a maximal sequence of *two* or more tokens, possibly separated by runs of digits and/or space.+//tokens are single letters (except a, A, I) and ASCIIMathML tokens+ var texcommand = "\\\\[a-zA-Z]+|\\\\\\s|";+ var ambigAMtoken = "\\b(?:oo|lim|ln|int|oint|del|grad|aleph|prod|prop|sinh|cosh|tanh|cos|sec|pi|tt|fr|sf|sube|supe|sub|sup|det|mod|gcd|lcm|min|max|vec|ddot|ul|chi|eta|nu|mu)(?![a-z])|";+ var englishAMtoken = "\\b(?:sum|ox|log|sin|tan|dim|hat|bar|dot)(?![a-z])|";+ var secondenglishAMtoken = "|\\bI\\b|\\bin\\b|\\btext\\b"; // took if and or not out+ var simpleAMtoken = "NN|ZZ|QQ|RR|CC|TT|AA|EE|sqrt|dx|dy|dz|dt|xx|vv|uu|nn|bb|cc|csc|cot|alpha|beta|delta|Delta|epsilon|gamma|Gamma|kappa|lambda|Lambda|omega|phi|Phi|Pi|psi|Psi|rho|sigma|Sigma|tau|theta|Theta|xi|Xi|zeta"; // uuu nnn?+ var letter = "[a-zA-HJ-Z](?=(?:[^a-zA-Z]|$|"+ambigAMtoken+englishAMtoken+simpleAMtoken+"))|";+ var token = letter+texcommand+"\\d+|[-()[\\]{}+=*&^_%\\\@/<>,\\|!:;'~]|\\.(?!(?:\x20|$))|"+ambigAMtoken+englishAMtoken+simpleAMtoken;+ var re = new RegExp("(^|\\s)((("+token+")\\s?)(("+token+secondenglishAMtoken+")\\s?)+)([,.?]?(?=\\s|$))","g");+ str = str.replace(re," `$2`$7");+ var arr = str.split(AMdelimiter1);+ var re1 = new RegExp("(^|\\s)([b-zB-HJ-Z+*<>]|"+texcommand+ambigAMtoken+simpleAMtoken+")(\\s|\\n|$)","g");+ var re2 = new RegExp("(^|\\s)([a-z]|"+texcommand+ambigAMtoken+simpleAMtoken+")([,.])","g"); // removed |\d+ for now+ for (i=0; i<arr.length; i++) //single nonenglish tokens+ if (i%2==0) {+ arr[i] = arr[i].replace(re1," `$2`$3");+ arr[i] = arr[i].replace(re2," `$2`$3");+ arr[i] = arr[i].replace(/([{}[\]])/,"`$1`");+ }+ str = arr.join(AMdelimiter1);+ str = str.replace(/((^|\s)\([a-zA-Z]{2,}.*?)\)`/g,"$1`)"); //fix parentheses+ str = str.replace(/`(\((a\s|in\s))(.*?[a-zA-Z]{2,}\))/g,"$1`$3"); //fix parentheses+ str = str.replace(/\sin`/g,"` in");+ str = str.replace(/`(\(\w\)[,.]?(\s|\n|$))/g,"$1`");+ str = str.replace(/`([0-9.]+|e.g|i.e)`(\.?)/gi,"$1$2");+ str = str.replace(/`([0-9.]+:)`/g,"$1");+ return str;+}++function processNodeR(n, linebreaks,latex) {+ var mtch, str, arr, frg, i;+ if (n.childNodes.length == 0) {+ if ((n.nodeType!=8 || linebreaks) &&+ n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&+ n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */) {+ str = n.nodeValue;+ if (!(str == null)) {+ str = str.replace(/\r\n\r\n/g,"\n\n");+ str = str.replace(/\x20+/g," ");+ str = str.replace(/\s*\r\n/g," ");+ if(latex) {+// DELIMITERS:+ mtch = (str.indexOf("\$")==-1 ? false : true);+ str = str.replace(/([^\\])\$/g,"$1 \$");+ str = str.replace(/^\$/," \$"); // in case \$ at start of string+ arr = str.split(" \$");+ for (i=0; i<arr.length; i++)+ arr[i]=arr[i].replace(/\\\$/g,"\$");+ } else {+ mtch = false;+ str = str.replace(new RegExp(AMescape1, "g"),+ function(){mtch = true; return "AMescape1"});+ str = str.replace(/\\?end{?a?math}?/i,+ function(){automathrecognize = false; mtch = true; return ""});+ str = str.replace(/amath\b|\\begin{a?math}/i,+ function(){automathrecognize = true; mtch = true; return ""});+ arr = str.split(AMdelimiter1);+ if (automathrecognize)+ for (i=0; i<arr.length; i++)+ if (i%2==0) arr[i] = AMautomathrec(arr[i]);+ str = arr.join(AMdelimiter1);+ arr = str.split(AMdelimiter1);+ for (i=0; i<arr.length; i++) // this is a problem ************+ arr[i]=arr[i].replace(/AMescape1/g,AMdelimiter1);+ }+ if (arr.length>1 || mtch) {+ if (!noMathML) {+ frg = strarr2docFrag(arr,n.nodeType==8,latex);+ var len = frg.childNodes.length;+ n.parentNode.replaceChild(frg,n);+ return len-1;+ } else return 0;+ }+ }+ } else return 0;+ } else if (n.nodeName!="math") {+ for (i=0; i<n.childNodes.length; i++)+ i += processNodeR(n.childNodes[i], linebreaks,latex);+ }+ return 0;+}++function AMprocessNode(n, linebreaks, spanclassAM) {+ var frag,st;+ if (spanclassAM!=null) {+ frag = document.getElementsByTagName("span")+ for (var i=0;i<frag.length;i++)+ if (frag[i].className == "AM") + processNodeR(frag[i],linebreaks,false);+ } else {+ try {+ st = n.innerHTML; // look for AMdelimiter on page+ } catch(err) {}+//alert(st)+ if (st==null || /amath\b|\\begin{a?math}/i.test(st) ||+ st.indexOf(AMdelimiter1+" ")!=-1 || st.slice(-1)==AMdelimiter1 ||+ st.indexOf(AMdelimiter1+"<")!=-1 || st.indexOf(AMdelimiter1+"\n")!=-1) {+ processNodeR(n,linebreaks,false);+ }+ }+/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */+}++/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */++// all further global variables start with "LM"++// Commented out by DRW to prevent 1/2 turning into a 2-line fraction+// LMdiv = {input:"/", tag:"mfrac", output:"/", ttype:INFIX},+// Commented out by DRW so that " prints literally in equations+// LMquote = {input:"\"", tag:"mtext", output:"mbox", ttype:TEXT};++var LMsymbols = [+//Greek letters+{input:"\\alpha", tag:"mi", output:"\u03B1", ttype:CONST},+{input:"\\beta", tag:"mi", output:"\u03B2", ttype:CONST},+{input:"\\gamma", tag:"mi", output:"\u03B3", ttype:CONST},+{input:"\\delta", tag:"mi", output:"\u03B4", ttype:CONST},+{input:"\\epsilon", tag:"mi", output:"\u03B5", ttype:CONST},+{input:"\\varepsilon", tag:"mi", output:"\u025B", ttype:CONST},+{input:"\\zeta", tag:"mi", output:"\u03B6", ttype:CONST},+{input:"\\eta", tag:"mi", output:"\u03B7", ttype:CONST},+{input:"\\theta", tag:"mi", output:"\u03B8", ttype:CONST},+{input:"\\vartheta", tag:"mi", output:"\u03D1", ttype:CONST},+{input:"\\iota", tag:"mi", output:"\u03B9", ttype:CONST},+{input:"\\kappa", tag:"mi", output:"\u03BA", ttype:CONST},+{input:"\\lambda", tag:"mi", output:"\u03BB", ttype:CONST},+{input:"\\mu", tag:"mi", output:"\u03BC", ttype:CONST},+{input:"\\nu", tag:"mi", output:"\u03BD", ttype:CONST},+{input:"\\xi", tag:"mi", output:"\u03BE", ttype:CONST},+{input:"\\pi", tag:"mi", output:"\u03C0", ttype:CONST},+{input:"\\varpi", tag:"mi", output:"\u03D6", ttype:CONST},+{input:"\\rho", tag:"mi", output:"\u03C1", ttype:CONST},+{input:"\\varrho", tag:"mi", output:"\u03F1", ttype:CONST},+{input:"\\varsigma", tag:"mi", output:"\u03C2", ttype:CONST},+{input:"\\sigma", tag:"mi", output:"\u03C3", ttype:CONST},+{input:"\\tau", tag:"mi", output:"\u03C4", ttype:CONST},+{input:"\\upsilon", tag:"mi", output:"\u03C5", ttype:CONST},+{input:"\\phi", tag:"mi", output:"\u03C6", ttype:CONST},+{input:"\\varphi", tag:"mi", output:"\u03D5", ttype:CONST},+{input:"\\chi", tag:"mi", output:"\u03C7", ttype:CONST},+{input:"\\psi", tag:"mi", output:"\u03C8", ttype:CONST},+{input:"\\omega", tag:"mi", output:"\u03C9", ttype:CONST},+{input:"\\Gamma", tag:"mo", output:"\u0393", ttype:CONST},+{input:"\\Delta", tag:"mo", output:"\u0394", ttype:CONST},+{input:"\\Theta", tag:"mo", output:"\u0398", ttype:CONST},+{input:"\\Lambda", tag:"mo", output:"\u039B", ttype:CONST},+{input:"\\Xi", tag:"mo", output:"\u039E", ttype:CONST},+{input:"\\Pi", tag:"mo", output:"\u03A0", ttype:CONST},+{input:"\\Sigma", tag:"mo", output:"\u03A3", ttype:CONST},+{input:"\\Upsilon", tag:"mo", output:"\u03A5", ttype:CONST},+{input:"\\Phi", tag:"mo", output:"\u03A6", ttype:CONST},+{input:"\\Psi", tag:"mo", output:"\u03A8", ttype:CONST},+{input:"\\Omega", tag:"mo", output:"\u03A9", ttype:CONST},++//fractions+{input:"\\frac12", tag:"mo", output:"\u00BD", ttype:CONST},+{input:"\\frac14", tag:"mo", output:"\u00BC", ttype:CONST},+{input:"\\frac34", tag:"mo", output:"\u00BE", ttype:CONST},+{input:"\\frac13", tag:"mo", output:"\u2153", ttype:CONST},+{input:"\\frac23", tag:"mo", output:"\u2154", ttype:CONST},+{input:"\\frac15", tag:"mo", output:"\u2155", ttype:CONST},+{input:"\\frac25", tag:"mo", output:"\u2156", ttype:CONST},+{input:"\\frac35", tag:"mo", output:"\u2157", ttype:CONST},+{input:"\\frac45", tag:"mo", output:"\u2158", ttype:CONST},+{input:"\\frac16", tag:"mo", output:"\u2159", ttype:CONST},+{input:"\\frac56", tag:"mo", output:"\u215A", ttype:CONST},+{input:"\\frac18", tag:"mo", output:"\u215B", ttype:CONST},+{input:"\\frac38", tag:"mo", output:"\u215C", ttype:CONST},+{input:"\\frac58", tag:"mo", output:"\u215D", ttype:CONST},+{input:"\\frac78", tag:"mo", output:"\u215E", ttype:CONST},++//binary operation symbols+{input:"\\pm", tag:"mo", output:"\u00B1", ttype:CONST},+{input:"\\mp", tag:"mo", output:"\u2213", ttype:CONST},+{input:"\\triangleleft",tag:"mo", output:"\u22B2", ttype:CONST},+{input:"\\triangleright",tag:"mo",output:"\u22B3", ttype:CONST},+{input:"\\cdot", tag:"mo", output:"\u22C5", ttype:CONST},+{input:"\\star", tag:"mo", output:"\u22C6", ttype:CONST},+{input:"\\ast", tag:"mo", output:"\u002A", ttype:CONST},+{input:"\\times", tag:"mo", output:"\u00D7", ttype:CONST},+{input:"\\div", tag:"mo", output:"\u00F7", ttype:CONST},+{input:"\\circ", tag:"mo", output:"\u2218", ttype:CONST},+//{input:"\\bullet", tag:"mo", output:"\u2219", ttype:CONST},+{input:"\\bullet", tag:"mo", output:"\u2022", ttype:CONST},+{input:"\\oplus", tag:"mo", output:"\u2295", ttype:CONST},+{input:"\\ominus", tag:"mo", output:"\u2296", ttype:CONST},+{input:"\\otimes", tag:"mo", output:"\u2297", ttype:CONST},+{input:"\\bigcirc", tag:"mo", output:"\u25CB", ttype:CONST},+{input:"\\oslash", tag:"mo", output:"\u2298", ttype:CONST},+{input:"\\odot", tag:"mo", output:"\u2299", ttype:CONST},+{input:"\\land", tag:"mo", output:"\u2227", ttype:CONST},+{input:"\\wedge", tag:"mo", output:"\u2227", ttype:CONST},+{input:"\\lor", tag:"mo", output:"\u2228", ttype:CONST},+{input:"\\vee", tag:"mo", output:"\u2228", ttype:CONST},+{input:"\\cap", tag:"mo", output:"\u2229", ttype:CONST},+{input:"\\cup", tag:"mo", output:"\u222A", ttype:CONST},+{input:"\\sqcap", tag:"mo", output:"\u2293", ttype:CONST},+{input:"\\sqcup", tag:"mo", output:"\u2294", ttype:CONST},+{input:"\\uplus", tag:"mo", output:"\u228E", ttype:CONST},+{input:"\\amalg", tag:"mo", output:"\u2210", ttype:CONST},+{input:"\\bigtriangleup",tag:"mo",output:"\u25B3", ttype:CONST},+{input:"\\bigtriangledown",tag:"mo",output:"\u25BD", ttype:CONST},+{input:"\\dag", tag:"mo", output:"\u2020", ttype:CONST},+{input:"\\dagger", tag:"mo", output:"\u2020", ttype:CONST},+{input:"\\ddag", tag:"mo", output:"\u2021", ttype:CONST},+{input:"\\ddagger", tag:"mo", output:"\u2021", ttype:CONST},+{input:"\\lhd", tag:"mo", output:"\u22B2", ttype:CONST},+{input:"\\rhd", tag:"mo", output:"\u22B3", ttype:CONST},+{input:"\\unlhd", tag:"mo", output:"\u22B4", ttype:CONST},+{input:"\\unrhd", tag:"mo", output:"\u22B5", ttype:CONST},+++//BIG Operators+{input:"\\sum", tag:"mo", output:"\u2211", ttype:UNDEROVER},+{input:"\\prod", tag:"mo", output:"\u220F", ttype:UNDEROVER},+{input:"\\bigcap", tag:"mo", output:"\u22C2", ttype:UNDEROVER},+{input:"\\bigcup", tag:"mo", output:"\u22C3", ttype:UNDEROVER},+{input:"\\bigwedge", tag:"mo", output:"\u22C0", ttype:UNDEROVER},+{input:"\\bigvee", tag:"mo", output:"\u22C1", ttype:UNDEROVER},+{input:"\\bigsqcap", tag:"mo", output:"\u2A05", ttype:UNDEROVER},+{input:"\\bigsqcup", tag:"mo", output:"\u2A06", ttype:UNDEROVER},+{input:"\\coprod", tag:"mo", output:"\u2210", ttype:UNDEROVER},+{input:"\\bigoplus", tag:"mo", output:"\u2A01", ttype:UNDEROVER},+{input:"\\bigotimes", tag:"mo", output:"\u2A02", ttype:UNDEROVER},+{input:"\\bigodot", tag:"mo", output:"\u2A00", ttype:UNDEROVER},+{input:"\\biguplus", tag:"mo", output:"\u2A04", ttype:UNDEROVER},+{input:"\\int", tag:"mo", output:"\u222B", ttype:CONST},+{input:"\\oint", tag:"mo", output:"\u222E", ttype:CONST},++//binary relation symbols+{input:":=", tag:"mo", output:":=", ttype:CONST},+{input:"\\lt", tag:"mo", output:"<", ttype:CONST},+{input:"\\gt", tag:"mo", output:">", ttype:CONST},+{input:"\\ne", tag:"mo", output:"\u2260", ttype:CONST},+{input:"\\neq", tag:"mo", output:"\u2260", ttype:CONST},+{input:"\\le", tag:"mo", output:"\u2264", ttype:CONST},+{input:"\\leq", tag:"mo", output:"\u2264", ttype:CONST},+{input:"\\leqslant", tag:"mo", output:"\u2264", ttype:CONST},+{input:"\\ge", tag:"mo", output:"\u2265", ttype:CONST},+{input:"\\geq", tag:"mo", output:"\u2265", ttype:CONST},+{input:"\\geqslant", tag:"mo", output:"\u2265", ttype:CONST},+{input:"\\equiv", tag:"mo", output:"\u2261", ttype:CONST},+{input:"\\ll", tag:"mo", output:"\u226A", ttype:CONST},+{input:"\\gg", tag:"mo", output:"\u226B", ttype:CONST},+{input:"\\doteq", tag:"mo", output:"\u2250", ttype:CONST},+{input:"\\prec", tag:"mo", output:"\u227A", ttype:CONST},+{input:"\\succ", tag:"mo", output:"\u227B", ttype:CONST},+{input:"\\preceq", tag:"mo", output:"\u227C", ttype:CONST},+{input:"\\succeq", tag:"mo", output:"\u227D", ttype:CONST},+{input:"\\subset", tag:"mo", output:"\u2282", ttype:CONST},+{input:"\\supset", tag:"mo", output:"\u2283", ttype:CONST},+{input:"\\subseteq", tag:"mo", output:"\u2286", ttype:CONST},+{input:"\\supseteq", tag:"mo", output:"\u2287", ttype:CONST},+{input:"\\sqsubset", tag:"mo", output:"\u228F", ttype:CONST},+{input:"\\sqsupset", tag:"mo", output:"\u2290", ttype:CONST},+{input:"\\sqsubseteq", tag:"mo", output:"\u2291", ttype:CONST},+{input:"\\sqsupseteq", tag:"mo", output:"\u2292", ttype:CONST},+{input:"\\sim", tag:"mo", output:"\u223C", ttype:CONST},+{input:"\\simeq", tag:"mo", output:"\u2243", ttype:CONST},+{input:"\\approx", tag:"mo", output:"\u2248", ttype:CONST},+{input:"\\cong", tag:"mo", output:"\u2245", ttype:CONST},+{input:"\\Join", tag:"mo", output:"\u22C8", ttype:CONST},+{input:"\\bowtie", tag:"mo", output:"\u22C8", ttype:CONST},+{input:"\\in", tag:"mo", output:"\u2208", ttype:CONST},+{input:"\\ni", tag:"mo", output:"\u220B", ttype:CONST},+{input:"\\owns", tag:"mo", output:"\u220B", ttype:CONST},+{input:"\\propto", tag:"mo", output:"\u221D", ttype:CONST},+{input:"\\vdash", tag:"mo", output:"\u22A2", ttype:CONST},+{input:"\\dashv", tag:"mo", output:"\u22A3", ttype:CONST},+{input:"\\models", tag:"mo", output:"\u22A8", ttype:CONST},+{input:"\\perp", tag:"mo", output:"\u22A5", ttype:CONST},+{input:"\\smile", tag:"mo", output:"\u2323", ttype:CONST},+{input:"\\frown", tag:"mo", output:"\u2322", ttype:CONST},+{input:"\\asymp", tag:"mo", output:"\u224D", ttype:CONST},+{input:"\\notin", tag:"mo", output:"\u2209", ttype:CONST},++//matrices+{input:"\\begin{eqnarray}", output:"X", ttype:MATRIX, invisible:true},+{input:"\\begin{array}", output:"X", ttype:MATRIX, invisible:true},+{input:"\\\\", output:"}&{", ttype:DEFINITION},+{input:"\\end{eqnarray}", output:"}}", ttype:DEFINITION},+{input:"\\end{array}", output:"}}", ttype:DEFINITION},++//grouping and literal brackets -- ieval is for IE+{input:"\\big", tag:"mo", output:"X", atval:"1.2", ieval:"2.2", ttype:BIG},+{input:"\\Big", tag:"mo", output:"X", atval:"1.6", ieval:"2.6", ttype:BIG},+{input:"\\bigg", tag:"mo", output:"X", atval:"2.2", ieval:"3.2", ttype:BIG},+{input:"\\Bigg", tag:"mo", output:"X", atval:"2.9", ieval:"3.9", ttype:BIG},+{input:"\\left", tag:"mo", output:"X", ttype:LEFTBRACKET},+{input:"\\right", tag:"mo", output:"X", ttype:RIGHTBRACKET},+{input:"{", output:"{", ttype:LEFTBRACKET, invisible:true},+{input:"}", output:"}", ttype:RIGHTBRACKET, invisible:true},++{input:"(", tag:"mo", output:"(", atval:"1", ttype:STRETCHY},+{input:"[", tag:"mo", output:"[", atval:"1", ttype:STRETCHY},+{input:"\\lbrack", tag:"mo", output:"[", atval:"1", ttype:STRETCHY},+{input:"\\{", tag:"mo", output:"{", atval:"1", ttype:STRETCHY},+{input:"\\lbrace", tag:"mo", output:"{", atval:"1", ttype:STRETCHY},+{input:"\\langle", tag:"mo", output:"\u2329", atval:"1", ttype:STRETCHY},+{input:"\\lfloor", tag:"mo", output:"\u230A", atval:"1", ttype:STRETCHY},+{input:"\\lceil", tag:"mo", output:"\u2308", atval:"1", ttype:STRETCHY},++// rtag:"mi" causes space to be inserted before a following sin, cos, etc.+// (see function LMparseExpr() )+{input:")", tag:"mo",output:")", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"]", tag:"mo",output:"]", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\rbrack",tag:"mo",output:"]", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\}", tag:"mo",output:"}", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\rbrace",tag:"mo",output:"}", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\rangle",tag:"mo",output:"\u232A", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\rfloor",tag:"mo",output:"\u230B", rtag:"mi",atval:"1",ttype:STRETCHY},+{input:"\\rceil", tag:"mo",output:"\u2309", rtag:"mi",atval:"1",ttype:STRETCHY},++// "|", "\\|", "\\vert" and "\\Vert" modified later: lspace = rspace = 0em+{input:"|", tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},+{input:"\\|", tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},+{input:"\\vert", tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},+{input:"\\Vert", tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},+{input:"\\mid", tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},+{input:"\\parallel", tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},+{input:"/", tag:"mo", output:"/", atval:"1.01", ttype:STRETCHY},+{input:"\\backslash", tag:"mo", output:"\u2216", atval:"1", ttype:STRETCHY},+{input:"\\setminus", tag:"mo", output:"\\", ttype:CONST},++//miscellaneous symbols+{input:"\\!", tag:"mspace", atname:"width", atval:"-0.167em", ttype:SPACE},+{input:"\\,", tag:"mspace", atname:"width", atval:"0.167em", ttype:SPACE},+{input:"\\>", tag:"mspace", atname:"width", atval:"0.222em", ttype:SPACE},+{input:"\\:", tag:"mspace", atname:"width", atval:"0.222em", ttype:SPACE},+{input:"\\;", tag:"mspace", atname:"width", atval:"0.278em", ttype:SPACE},+{input:"~", tag:"mspace", atname:"width", atval:"0.333em", ttype:SPACE},+{input:"\\quad", tag:"mspace", atname:"width", atval:"1em", ttype:SPACE},+{input:"\\qquad", tag:"mspace", atname:"width", atval:"2em", ttype:SPACE},+//{input:"{}", tag:"mo", output:"\u200B", ttype:CONST}, // zero-width+{input:"\\prime", tag:"mo", output:"\u2032", ttype:CONST},+{input:"'", tag:"mo", output:"\u02B9", ttype:CONST},+{input:"''", tag:"mo", output:"\u02BA", ttype:CONST},+{input:"'''", tag:"mo", output:"\u2034", ttype:CONST},+{input:"''''", tag:"mo", output:"\u2057", ttype:CONST},+{input:"\\ldots", tag:"mo", output:"\u2026", ttype:CONST},+{input:"\\cdots", tag:"mo", output:"\u22EF", ttype:CONST},+{input:"\\vdots", tag:"mo", output:"\u22EE", ttype:CONST},+{input:"\\ddots", tag:"mo", output:"\u22F1", ttype:CONST},+{input:"\\forall", tag:"mo", output:"\u2200", ttype:CONST},+{input:"\\exists", tag:"mo", output:"\u2203", ttype:CONST},+{input:"\\Re", tag:"mo", output:"\u211C", ttype:CONST},+{input:"\\Im", tag:"mo", output:"\u2111", ttype:CONST},+{input:"\\aleph", tag:"mo", output:"\u2135", ttype:CONST},+{input:"\\hbar", tag:"mo", output:"\u210F", ttype:CONST},+{input:"\\ell", tag:"mo", output:"\u2113", ttype:CONST},+{input:"\\wp", tag:"mo", output:"\u2118", ttype:CONST},+{input:"\\emptyset", tag:"mo", output:"\u2205", ttype:CONST},+{input:"\\infty", tag:"mo", output:"\u221E", ttype:CONST},+{input:"\\surd", tag:"mo", output:"\\sqrt{}", ttype:DEFINITION},+{input:"\\partial", tag:"mo", output:"\u2202", ttype:CONST},+{input:"\\nabla", tag:"mo", output:"\u2207", ttype:CONST},+{input:"\\triangle", tag:"mo", output:"\u25B3", ttype:CONST},+{input:"\\therefore", tag:"mo", output:"\u2234", ttype:CONST},+{input:"\\angle", tag:"mo", output:"\u2220", ttype:CONST},+//{input:"\\\\ ", tag:"mo", output:"\u00A0", ttype:CONST},+{input:"\\diamond", tag:"mo", output:"\u22C4", ttype:CONST},+//{input:"\\Diamond", tag:"mo", output:"\u25CA", ttype:CONST},+{input:"\\Diamond", tag:"mo", output:"\u25C7", ttype:CONST},+{input:"\\neg", tag:"mo", output:"\u00AC", ttype:CONST},+{input:"\\lnot", tag:"mo", output:"\u00AC", ttype:CONST},+{input:"\\bot", tag:"mo", output:"\u22A5", ttype:CONST},+{input:"\\top", tag:"mo", output:"\u22A4", ttype:CONST},+{input:"\\square", tag:"mo", output:"\u25AB", ttype:CONST},+{input:"\\Box", tag:"mo", output:"\u25A1", ttype:CONST},+{input:"\\wr", tag:"mo", output:"\u2240", ttype:CONST},++//standard functions+//Note UNDEROVER *must* have tag:"mo" to work properly+{input:"\\arccos", tag:"mi", output:"arccos", ttype:UNARY, func:true},+{input:"\\arcsin", tag:"mi", output:"arcsin", ttype:UNARY, func:true},+{input:"\\arctan", tag:"mi", output:"arctan", ttype:UNARY, func:true},+{input:"\\arg", tag:"mi", output:"arg", ttype:UNARY, func:true},+{input:"\\cos", tag:"mi", output:"cos", ttype:UNARY, func:true},+{input:"\\cosh", tag:"mi", output:"cosh", ttype:UNARY, func:true},+{input:"\\cot", tag:"mi", output:"cot", ttype:UNARY, func:true},+{input:"\\coth", tag:"mi", output:"coth", ttype:UNARY, func:true},+{input:"\\csc", tag:"mi", output:"csc", ttype:UNARY, func:true},+{input:"\\deg", tag:"mi", output:"deg", ttype:UNARY, func:true},+{input:"\\det", tag:"mi", output:"det", ttype:UNARY, func:true},+{input:"\\dim", tag:"mi", output:"dim", ttype:UNARY, func:true}, //CONST?+{input:"\\exp", tag:"mi", output:"exp", ttype:UNARY, func:true},+{input:"\\gcd", tag:"mi", output:"gcd", ttype:UNARY, func:true}, //CONST?+{input:"\\hom", tag:"mi", output:"hom", ttype:UNARY, func:true},+{input:"\\inf", tag:"mo", output:"inf", ttype:UNDEROVER},+{input:"\\ker", tag:"mi", output:"ker", ttype:UNARY, func:true},+{input:"\\lg", tag:"mi", output:"lg", ttype:UNARY, func:true},+{input:"\\lim", tag:"mo", output:"lim", ttype:UNDEROVER},+{input:"\\liminf", tag:"mo", output:"liminf", ttype:UNDEROVER},+{input:"\\limsup", tag:"mo", output:"limsup", ttype:UNDEROVER},+{input:"\\ln", tag:"mi", output:"ln", ttype:UNARY, func:true},+{input:"\\log", tag:"mi", output:"log", ttype:UNARY, func:true},+{input:"\\max", tag:"mo", output:"max", ttype:UNDEROVER},+{input:"\\min", tag:"mo", output:"min", ttype:UNDEROVER},+{input:"\\Pr", tag:"mi", output:"Pr", ttype:UNARY, func:true},+{input:"\\sec", tag:"mi", output:"sec", ttype:UNARY, func:true},+{input:"\\sin", tag:"mi", output:"sin", ttype:UNARY, func:true},+{input:"\\sinh", tag:"mi", output:"sinh", ttype:UNARY, func:true},+{input:"\\sup", tag:"mo", output:"sup", ttype:UNDEROVER},+{input:"\\tan", tag:"mi", output:"tan", ttype:UNARY, func:true},+{input:"\\tanh", tag:"mi", output:"tanh", ttype:UNARY, func:true},++//arrows+{input:"\\gets", tag:"mo", output:"\u2190", ttype:CONST},+{input:"\\leftarrow", tag:"mo", output:"\u2190", ttype:CONST},+{input:"\\to", tag:"mo", output:"\u2192", ttype:CONST},+{input:"\\rightarrow", tag:"mo", output:"\u2192", ttype:CONST},+{input:"\\leftrightarrow", tag:"mo", output:"\u2194", ttype:CONST},+{input:"\\uparrow", tag:"mo", output:"\u2191", ttype:CONST},+{input:"\\downarrow", tag:"mo", output:"\u2193", ttype:CONST},+{input:"\\updownarrow", tag:"mo", output:"\u2195", ttype:CONST},+{input:"\\Leftarrow", tag:"mo", output:"\u21D0", ttype:CONST},+{input:"\\Rightarrow", tag:"mo", output:"\u21D2", ttype:CONST},+{input:"\\Leftrightarrow", tag:"mo", output:"\u21D4", ttype:CONST},+{input:"\\iff", tag:"mo", output:"~\\Longleftrightarrow~", ttype:DEFINITION},+{input:"\\Uparrow", tag:"mo", output:"\u21D1", ttype:CONST},+{input:"\\Downarrow", tag:"mo", output:"\u21D3", ttype:CONST},+{input:"\\Updownarrow", tag:"mo", output:"\u21D5", ttype:CONST},+{input:"\\mapsto", tag:"mo", output:"\u21A6", ttype:CONST},+{input:"\\longleftarrow", tag:"mo", output:"\u2190", ttype:LONG},+{input:"\\longrightarrow", tag:"mo", output:"\u2192", ttype:LONG},+{input:"\\longleftrightarrow", tag:"mo", output:"\u2194", ttype:LONG},+{input:"\\Longleftarrow", tag:"mo", output:"\u21D0", ttype:LONG},+{input:"\\Longrightarrow", tag:"mo", output:"\u21D2", ttype:LONG},+{input:"\\implies", tag:"mo", output:"\u21D2", ttype:LONG},+{input:"\\Longleftrightarrow", tag:"mo", output:"\u21D4", ttype:LONG},+{input:"\\longmapsto", tag:"mo", output:"\u21A6", ttype:CONST},+ // disaster if LONG++//commands with argument++{input:"\\sqrt", tag:"msqrt", output:"sqrt", ttype:UNARY},+{input:"\\root", tag:"mroot", output:"root", ttype:BINARY},+{input:"\\frac", tag:"mfrac", output:"/", ttype:BINARY},+{input:"\\stackrel", tag:"mover", output:"stackrel", ttype:BINARY},+{input:"\\atop", tag:"mfrac", output:"", ttype:INFIX},+{input:"\\choose", tag:"mfrac", output:"", ttype:INFIX},+{input:"_", tag:"msub", output:"_", ttype:INFIX},+{input:"^", tag:"msup", output:"^", ttype:INFIX},+{input:"\\mathrm", tag:"mtext", output:"text", ttype:TEXT},+{input:"\\mbox", tag:"mtext", output:"mbox", ttype:TEXT},++//diacritical marks+{input:"\\acute", tag:"mover", output:"\u00B4", ttype:UNARY, acc:true},+//{input:"\\acute", tag:"mover", output:"\u0317", ttype:UNARY, acc:true},+//{input:"\\acute", tag:"mover", output:"\u0301", ttype:UNARY, acc:true},+//{input:"\\grave", tag:"mover", output:"\u0300", ttype:UNARY, acc:true},+//{input:"\\grave", tag:"mover", output:"\u0316", ttype:UNARY, acc:true},+{input:"\\grave", tag:"mover", output:"\u0060", ttype:UNARY, acc:true},+{input:"\\breve", tag:"mover", output:"\u02D8", ttype:UNARY, acc:true},+{input:"\\check", tag:"mover", output:"\u02C7", ttype:UNARY, acc:true},+{input:"\\dot", tag:"mover", output:".", ttype:UNARY, acc:true},+{input:"\\ddot", tag:"mover", output:"..", ttype:UNARY, acc:true},+//{input:"\\ddot", tag:"mover", output:"\u00A8", ttype:UNARY, acc:true},+{input:"\\mathring", tag:"mover", output:"\u00B0", ttype:UNARY, acc:true},+{input:"\\vec", tag:"mover", output:"\u20D7", ttype:UNARY, acc:true},+{input:"\\overrightarrow",tag:"mover",output:"\u20D7", ttype:UNARY, acc:true},+{input:"\\overleftarrow",tag:"mover", output:"\u20D6", ttype:UNARY, acc:true},+{input:"\\hat", tag:"mover", output:"\u005E", ttype:UNARY, acc:true},+{input:"\\widehat", tag:"mover", output:"\u0302", ttype:UNARY, acc:true},+{input:"\\tilde", tag:"mover", output:"~", ttype:UNARY, acc:true},+//{input:"\\tilde", tag:"mover", output:"\u0303", ttype:UNARY, acc:true},+{input:"\\widetilde", tag:"mover", output:"\u02DC", ttype:UNARY, acc:true},+{input:"\\bar", tag:"mover", output:"\u203E", ttype:UNARY, acc:true},+{input:"\\overbrace", tag:"mover", output:"\u23B4", ttype:UNARY, acc:true},+{input:"\\overline", tag:"mover", output:"\u00AF", ttype:UNARY, acc:true},+{input:"\\underbrace", tag:"munder", output:"\u23B5", ttype:UNARY, acc:true},+{input:"\\underline", tag:"munder", output:"\u00AF", ttype:UNARY, acc:true},+//{input:"underline", tag:"munder", output:"\u0332", ttype:UNARY, acc:true},++//typestyles and fonts+{input:"\\displaystyle",tag:"mstyle",atname:"displaystyle",atval:"true", ttype:UNARY},+{input:"\\textstyle",tag:"mstyle",atname:"displaystyle",atval:"false", ttype:UNARY},+{input:"\\scriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"1", ttype:UNARY},+{input:"\\scriptscriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"2", ttype:UNARY},+{input:"\\textrm", tag:"mstyle", output:"\\mathrm", ttype: DEFINITION},+{input:"\\mathbf", tag:"mstyle", atname:"mathvariant", atval:"bold", ttype:UNARY},+{input:"\\textbf", tag:"mstyle", atname:"mathvariant", atval:"bold", ttype:UNARY},+{input:"\\mathit", tag:"mstyle", atname:"mathvariant", atval:"italic", ttype:UNARY},+{input:"\\textit", tag:"mstyle", atname:"mathvariant", atval:"italic", ttype:UNARY},+{input:"\\mathtt", tag:"mstyle", atname:"mathvariant", atval:"monospace", ttype:UNARY},+{input:"\\texttt", tag:"mstyle", atname:"mathvariant", atval:"monospace", ttype:UNARY},+{input:"\\mathsf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", ttype:UNARY},+{input:"\\mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", ttype:UNARY, codes:AMbbb},+{input:"\\mathcal",tag:"mstyle", atname:"mathvariant", atval:"script", ttype:UNARY, codes:AMcal},+{input:"\\mathfrak",tag:"mstyle",atname:"mathvariant", atval:"fraktur",ttype:UNARY, codes:AMfrk}+];++var LMnames = []; //list of input symbols++function LMremoveCharsAndBlanks(str,n) {+//remove n characters and any following blanks+ var st;+ st = str.slice(n);+ for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);+ return st.slice(i);+}++function LMgetSymbol(str) {+//return maximal initial substring of str that appears in names+//return null if there is none+ var k = 0; //new pos+ var j = 0; //old pos+ var mk; //match pos+ var st;+ var tagst;+ var match = "";+ var more = true;+ for (var i=1; i<=str.length && more; i++) {+ st = str.slice(0,i); //initial substring of length i+ j = k;+ k = position(LMnames, st, j);+ if (k<LMnames.length && str.slice(0,LMnames[k].length)==LMnames[k]){+ match = LMnames[k];+ mk = k;+ i = match.length;+ }+ more = k<LMnames.length && str.slice(0,LMnames[k].length)>=LMnames[k];+ }+ LMpreviousSymbol=LMcurrentSymbol;+ if (match!=""){+ LMcurrentSymbol=LMsymbols[mk].ttype;+ return LMsymbols[mk];+ }+ LMcurrentSymbol=CONST;+ k = 1;+ st = str.slice(0,1); //take 1 character+ if ("0"<=st && st<="9") tagst = "mn";+ else tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");+/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */+ return {input:st, tag:tagst, output:st, ttype:CONST};+}+++/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */++var LMpreviousSymbol,LMcurrentSymbol;++function LMparseSexpr(str) { //parses str and returns [node,tailstr,(node)tag]+ var symbol, node, result, result2, i, st,// rightvert = false,+ newFrag = document.createDocumentFragment();+ str = LMremoveCharsAndBlanks(str,0);+ symbol = LMgetSymbol(str); //either a token or a bracket or empty+ if (symbol == null || symbol.ttype == RIGHTBRACKET)+ return [null,str,null];+ if (symbol.ttype == DEFINITION) {+ str = symbol.output+LMremoveCharsAndBlanks(str,symbol.input.length);+ symbol = LMgetSymbol(str);+ if (symbol == null || symbol.ttype == RIGHTBRACKET)+ return [null,str,null];+ }+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ switch (symbol.ttype) {+ case SPACE:+ node = createMmlNode(symbol.tag);+ node.setAttribute(symbol.atname,symbol.atval);+ return [node,str,symbol.tag];+ case UNDEROVER:+ if (isIE) {+ if (symbol.input.substr(0,4) == "\\big") { // botch for missing symbols+ str = "\\"+symbol.input.substr(4)+str; // make \bigcup = \cup etc.+ symbol = LMgetSymbol(str);+ symbol.ttype = UNDEROVER;+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ }+ }+ return [createMmlNode(symbol.tag,+ document.createTextNode(symbol.output)),str,symbol.tag];+ case CONST:+ var output = symbol.output;+ if (isIE) {+ if (symbol.input == "'")+ output = "\u2032";+ else if (symbol.input == "''")+ output = "\u2033";+ else if (symbol.input == "'''")+ output = "\u2033\u2032";+ else if (symbol.input == "''''")+ output = "\u2033\u2033";+ else if (symbol.input == "\\square")+ output = "\u25A1"; // same as \Box+ else if (symbol.input.substr(0,5) == "\\frac") {+ // botch for missing fractions+ var denom = symbol.input.substr(6,1);+ if (denom == "5" || denom == "6") {+ str = symbol.input.replace(/\\frac/,"\\frac ")+str;+ return [node,str,symbol.tag];+ }+ }+ }+ node = createMmlNode(symbol.tag,document.createTextNode(output));+ return [node,str,symbol.tag];+ case LONG: // added by DRW+ node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));+ node.setAttribute("minsize","1.5");+ node.setAttribute("maxsize","1.5");+ node = createMmlNode("mover",node);+ node.appendChild(createMmlNode("mspace"));+ return [node,str,symbol.tag];+ case STRETCHY: // added by DRW+ if (isIE && symbol.input == "\\backslash")+ symbol.output = "\\"; // doesn't expand, but then nor does "\u2216"+ node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));+ if (symbol.input == "|" || symbol.input == "\\vert" ||+ symbol.input == "\\|" || symbol.input == "\\Vert") {+ node.setAttribute("lspace","0em");+ node.setAttribute("rspace","0em");+ }+ node.setAttribute("maxsize",symbol.atval); // don't allow to stretch here+ if (symbol.rtag != null)+ return [node,str,symbol.rtag];+ else+ return [node,str,symbol.tag];+ case BIG: // added by DRW+ var atval = symbol.atval;+ if (isIE)+ atval = symbol.ieval;+ symbol = LMgetSymbol(str);+ if (symbol == null)+ return [null,str,null];+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));+ if (isIE) { // to get brackets to expand+ var space = createMmlNode("mspace");+ space.setAttribute("height",atval+"ex");+ node = createMmlNode("mrow",node);+ node.appendChild(space);+ } else { // ignored in IE+ node.setAttribute("minsize",atval);+ node.setAttribute("maxsize",atval);+ }+ return [node,str,symbol.tag];+ case LEFTBRACKET: //read (expr+)+ if (symbol.input == "\\left") { // left what?+ symbol = LMgetSymbol(str);+ if (symbol != null) {+ if (symbol.input == ".")+ symbol.invisible = true;+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ }+ }+ result = LMparseExpr(str,true,false);+ if (symbol==null ||+ (typeof symbol.invisible == "boolean" && symbol.invisible))+ node = createMmlNode("mrow",result[0]);+ else {+ node = createMmlNode("mo",document.createTextNode(symbol.output));+ node = createMmlNode("mrow",node);+ node.appendChild(result[0]);+ }+ return [node,result[1],result[2]];+ case MATRIX: //read (expr+)+ if (symbol.input == "\\begin{array}") {+ var mask = "";+ symbol = LMgetSymbol(str);+ str = LMremoveCharsAndBlanks(str,0);+ if (symbol == null)+ mask = "l";+ else {+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ if (symbol.input != "{")+ mask = "l";+ else do {+ symbol = LMgetSymbol(str);+ if (symbol != null) {+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ if (symbol.input != "}")+ mask = mask+symbol.input;+ }+ } while (symbol != null && symbol.input != "" && symbol.input != "}");+ }+ result = LMparseExpr("{"+str,true,true);+// if (result[0]==null) return [createMmlNode("mo",+// document.createTextNode(symbol.input)),str];+ node = createMmlNode("mtable",result[0]);+ mask = mask.replace(/l/g,"left ");+ mask = mask.replace(/r/g,"right ");+ mask = mask.replace(/c/g,"center ");+ node.setAttribute("columnalign",mask);+ node.setAttribute("displaystyle","false");+ if (isIE)+ return [node,result[1],null];+// trying to get a *little* bit of space around the array+// (IE already includes it)+ var lspace = createMmlNode("mspace");+ lspace.setAttribute("width","0.167em");+ var rspace = createMmlNode("mspace");+ rspace.setAttribute("width","0.167em");+ var node1 = createMmlNode("mrow",lspace);+ node1.appendChild(node);+ node1.appendChild(rspace);+ return [node1,result[1],null];+ } else { // eqnarray+ result = LMparseExpr("{"+str,true,true);+ node = createMmlNode("mtable",result[0]);+ if (isIE)+ node.setAttribute("columnspacing","0.25em"); // best in practice?+ else+ node.setAttribute("columnspacing","0.167em"); // correct (but ignored?)+ node.setAttribute("columnalign","right center left");+ node.setAttribute("displaystyle","true");+ node = createMmlNode("mrow",node);+ return [node,result[1],null];+ }+ case TEXT:+ if (str.charAt(0)=="{") i=str.indexOf("}");+ else i = 0;+ if (i==-1)+ i = str.length;+ st = str.slice(1,i);+ if (st.charAt(0) == " ") {+ node = createMmlNode("mspace");+ node.setAttribute("width","0.33em"); // was 1ex+ newFrag.appendChild(node);+ }+ newFrag.appendChild(+ createMmlNode(symbol.tag,document.createTextNode(st)));+ if (st.charAt(st.length-1) == " ") {+ node = createMmlNode("mspace");+ node.setAttribute("width","0.33em"); // was 1ex+ newFrag.appendChild(node);+ }+ str = LMremoveCharsAndBlanks(str,i+1);+ return [createMmlNode("mrow",newFrag),str,null];+ case UNARY:+ result = LMparseSexpr(str);+ if (result[0]==null) return [createMmlNode(symbol.tag,+ document.createTextNode(symbol.output)),str];+ if (typeof symbol.func == "boolean" && symbol.func) { // functions hack+ st = str.charAt(0);+// if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {+ if (st=="^" || st=="_" || st==",") {+ return [createMmlNode(symbol.tag,+ document.createTextNode(symbol.output)),str,symbol.tag];+ } else {+ node = createMmlNode("mrow",+ createMmlNode(symbol.tag,document.createTextNode(symbol.output)));+ if (isIE) {+ var space = createMmlNode("mspace");+ space.setAttribute("width","0.167em");+ node.appendChild(space);+ }+ node.appendChild(result[0]);+ return [node,result[1],symbol.tag];+ }+ }+ if (symbol.input == "\\sqrt") { // sqrt+ if (isIE) { // set minsize, for \surd+ var space = createMmlNode("mspace");+ space.setAttribute("height","1.2ex");+ space.setAttribute("width","0em"); // probably no effect+ node = createMmlNode(symbol.tag,result[0])+// node.setAttribute("minsize","1"); // ignored+// node = createMmlNode("mrow",node); // hopefully unnecessary+ node.appendChild(space);+ return [node,result[1],symbol.tag];+ } else+ return [createMmlNode(symbol.tag,result[0]),result[1],symbol.tag];+ } else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent+ node = createMmlNode(symbol.tag,result[0]);+ var output = symbol.output;+ if (isIE) {+ if (symbol.input == "\\hat")+ output = "\u0302";+ else if (symbol.input == "\\widehat")+ output = "\u005E";+ else if (symbol.input == "\\bar")+ output = "\u00AF";+ else if (symbol.input == "\\grave")+ output = "\u0300";+ else if (symbol.input == "\\tilde")+ output = "\u0303";+ }+ var node1 = createMmlNode("mo",document.createTextNode(output));+ if (symbol.input == "\\vec" || symbol.input == "\\check")+ // don't allow to stretch+ node1.setAttribute("maxsize","1.2");+ // why doesn't "1" work? \vec nearly disappears in firefox+ if (isIE && symbol.input == "\\bar")+ node1.setAttribute("maxsize","0.5");+ if (symbol.input == "\\underbrace" || symbol.input == "\\underline")+ node1.setAttribute("accentunder","true");+ else+ node1.setAttribute("accent","true");+ node.appendChild(node1);+ if (symbol.input == "\\overbrace" || symbol.input == "\\underbrace")+ node.ttype = UNDEROVER;+ return [node,result[1],symbol.tag];+ } else { // font change or displaystyle command+ if (!isIE && typeof symbol.codes != "undefined") {+ for (i=0; i<result[0].childNodes.length; i++)+ if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {+ st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:+ result[0].childNodes[i].firstChild.nodeValue);+ var newst = [];+ for (var j=0; j<st.length; j++)+ if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst ++ String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);+ else newst = newst + st.charAt(j);+ if (result[0].nodeName=="mi")+ result[0]=createMmlNode("mo").+ appendChild(document.createTextNode(newst));+ else result[0].replaceChild(createMmlNode("mo").+ appendChild(document.createTextNode(newst)),result[0].childNodes[i]);+ }+ }+ node = createMmlNode(symbol.tag,result[0]);+ node.setAttribute(symbol.atname,symbol.atval);+ if (symbol.input == "\\scriptstyle" ||+ symbol.input == "\\scriptscriptstyle")+ node.setAttribute("displaystyle","false");+ return [node,result[1],symbol.tag];+ }+ case BINARY:+ result = LMparseSexpr(str);+ if (result[0]==null) return [createMmlNode("mo",+ document.createTextNode(symbol.input)),str,null];+ result2 = LMparseSexpr(result[1]);+ if (result2[0]==null) return [createMmlNode("mo",+ document.createTextNode(symbol.input)),str,null];+ if (symbol.input=="\\root" || symbol.input=="\\stackrel")+ newFrag.appendChild(result2[0]);+ newFrag.appendChild(result[0]);+ if (symbol.input=="\\frac") newFrag.appendChild(result2[0]);+ return [createMmlNode(symbol.tag,newFrag),result2[1],symbol.tag];+ case INFIX:+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ return [createMmlNode("mo",document.createTextNode(symbol.output)),+ str,symbol.tag];+ default:+ return [createMmlNode(symbol.tag, //its a constant+ document.createTextNode(symbol.output)),str,symbol.tag];+ }+}++function LMparseIexpr(str) {+ var symbol, sym1, sym2, node, result, tag, underover;+ str = LMremoveCharsAndBlanks(str,0);+ sym1 = LMgetSymbol(str);+ result = LMparseSexpr(str);+ node = result[0];+ str = result[1];+ tag = result[2];+ symbol = LMgetSymbol(str);+ if (symbol.ttype == INFIX) {+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ result = LMparseSexpr(str);+ if (result[0] == null) // show box in place of missing argument+ result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));+ str = result[1];+ tag = result[2];+ if (symbol.input == "_" || symbol.input == "^") {+ sym2 = LMgetSymbol(str);+ tag = null; // no space between x^2 and a following sin, cos, etc.+// This is for \underbrace and \overbrace+ underover = ((sym1.ttype == UNDEROVER) || (node.ttype == UNDEROVER));+// underover = (sym1.ttype == UNDEROVER);+ if (symbol.input == "_" && sym2.input == "^") {+ str = LMremoveCharsAndBlanks(str,sym2.input.length);+ var res2 = LMparseSexpr(str);+ str = res2[1];+ tag = res2[2]; // leave space between x_1^2 and a following sin etc.+ node = createMmlNode((underover?"munderover":"msubsup"),node);+ node.appendChild(result[0]);+ node.appendChild(res2[0]);+ } else if (symbol.input == "_") {+ node = createMmlNode((underover?"munder":"msub"),node);+ node.appendChild(result[0]);+ } else {+ node = createMmlNode((underover?"mover":"msup"),node);+ node.appendChild(result[0]);+ }+ node = createMmlNode("mrow",node); // so sum does not stretch+ } else {+ node = createMmlNode(symbol.tag,node);+ if (symbol.input == "\\atop" || symbol.input == "\\choose")+ node.setAttribute("linethickness","0ex");+ node.appendChild(result[0]);+ if (symbol.input == "\\choose")+ node = createMmlNode("mfenced",node);+ }+ }+ return [node,str,tag];+}++function LMparseExpr(str,rightbracket,matrix) {+ var symbol, node, result, i, tag,+ newFrag = document.createDocumentFragment();+ do {+ str = LMremoveCharsAndBlanks(str,0);+ result = LMparseIexpr(str);+ node = result[0];+ str = result[1];+ tag = result[2];+ symbol = LMgetSymbol(str);+ if (node!=undefined) {+ if ((tag == "mn" || tag == "mi") && symbol!=null &&+ typeof symbol.func == "boolean" && symbol.func) {+ // Add space before \sin in 2\sin x or x\sin x+ var space = createMmlNode("mspace");+ space.setAttribute("width","0.167em");+ node = createMmlNode("mrow",node);+ node.appendChild(space);+ }+ newFrag.appendChild(node);+ }+ } while ((symbol.ttype != RIGHTBRACKET)+ && symbol!=null && symbol.output!="");+ tag = null;+ if (symbol.ttype == RIGHTBRACKET) {+ if (symbol.input == "\\right") { // right what?+ str = LMremoveCharsAndBlanks(str,symbol.input.length);+ symbol = LMgetSymbol(str);+ if (symbol != null && symbol.input == ".")+ symbol.invisible = true;+ if (symbol != null)+ tag = symbol.rtag;+ }+ if (symbol!=null)+ str = LMremoveCharsAndBlanks(str,symbol.input.length); // ready to return+ var len = newFrag.childNodes.length;+ if (matrix &&+ len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&+ newFrag.childNodes[len-2].nodeName == "mo" &&+ newFrag.childNodes[len-2].firstChild.nodeValue == "&") { //matrix+ var pos = []; // positions of ampersands+ var m = newFrag.childNodes.length;+ for (i=0; matrix && i<m; i=i+2) {+ pos[i] = [];+ node = newFrag.childNodes[i];+ for (var j=0; j<node.childNodes.length; j++)+ if (node.childNodes[j].firstChild.nodeValue=="&")+ pos[i][pos[i].length]=j;+ }+ var row, frag, n, k, table = document.createDocumentFragment();+ for (i=0; i<m; i=i+2) {+ row = document.createDocumentFragment();+ frag = document.createDocumentFragment();+ node = newFrag.firstChild; // <mrow> -&-&...&-&- </mrow>+ n = node.childNodes.length;+ k = 0;+ for (j=0; j<n; j++) {+ if (typeof pos[i][k] != "undefined" && j==pos[i][k]){+ node.removeChild(node.firstChild); //remove &+ row.appendChild(createMmlNode("mtd",frag));+ k++;+ } else frag.appendChild(node.firstChild);+ }+ row.appendChild(createMmlNode("mtd",frag));+ if (newFrag.childNodes.length>2) {+ newFrag.removeChild(newFrag.firstChild); //remove <mrow> </mrow>+ newFrag.removeChild(newFrag.firstChild); //remove <mo>&</mo>+ }+ table.appendChild(createMmlNode("mtr",row));+ }+ return [table,str];+ }+ if (typeof symbol.invisible != "boolean" || !symbol.invisible) {+ node = createMmlNode("mo",document.createTextNode(symbol.output));+ newFrag.appendChild(node);+ }+ }+ return [newFrag,str,tag];+}++var tcnt = 0, dcnt = 0; //theorem and definition counters++function simpleLaTeXformatting(st) {+ st = st.replace(/\$\$((.|\n)*?)\$\$/g,"<p align=\"center\">$\\displaystyle{$1}$</p>");+ st = st.replace(/\\begin{(theorem|lemma|proposition|corollary)}((.|\n)*?)\\end{\1}/g,function(r,s,t){tcnt++; return "<b>"+s.charAt(0).toUpperCase()+s.slice(1)+" "+tcnt+".</b> <i>"+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")+"</i>"});+ st = st.replace(/\\begin{(definition|example|remark|problem|exercise|conjecture|solution)}((.|\n)*?)\\end{\1}/g,function(r,s,t){dcnt++; return "<b>"+s.charAt(0).toUpperCase()+s.slice(1)+" "+dcnt+".</b> "+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")});+ st = st.replace(/\\begin{proof}((.|\n)*?)\\end{proof}/g,function(s,t){return "<i>Proof:</i> "+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")+" □"});+ st = st.replace(/\\emph{(.*?)}/g,"<em>$1</em>");+ st = st.replace(/\\textbf{(.*?)}/g,"<b>$1</b>");+ st = st.replace(/\\cite{(.*?)}/g,"[$1]");+ st = st.replace(/\\chapter{(.*?)}/g,"<h2>$1</h2>");+ st = st.replace(/\\section{(.*?)}(\s*<\/?(br|p)\s?\/?>)?/g,"<h3>$1</h3>");+ st = st.replace(/\\subsection{((.|\n)*?)}/g,"<h4>$1</h4>");+ st = st.replace(/\\begin{itemize}(\s*<\/?(br|p)\s?\/?>)?/g,"<ul>");+ st = st.replace(/\\item\s((.|\n)*?)(?=(\\item|\\end))/g,"<li>$1</li>");+ st = st.replace(/\\end{itemize}(\s*<\/?(br|p)\s?\/?>)?/g,"</ul>");+ st = st.replace(/\\begin{enumerate}(\s*<\/?(br|p)\s?\/?>)?/g,"<ol>");+ st = st.replace(/\\end{enumerate}(\s*<\/?(br|p)\s?\/?>)?/g,"</ol>");+ st = st.replace(/\\item\[(.*?)]{(.*?)}/g,"<dt>$1</dt><dd>$2</dd>");+ st = st.replace(/\\begin{description}/g,"<dl>");+ st = st.replace(/\\end{description}/g,"</dl>");+ st = st.replace(/\\newline\b/g,"<br/>");+ st = st.replace(/\\newpage\b/g,"<br style=\"page-break-after:always;\">");+ st = st.replace(/\\par\b/g,"<p> </p>");+ st = st.replace(/\\bigskip/g,"<p style=\"margin-bottom:0.5in\"> </p>");+ st = st.replace(/\\medskip/g,"<p style=\"margin-bottom:0.3in\"> </p>");+ st = st.replace(/\\smallskip/g,"<p style=\"margin-bottom:0.15in\"> </p>");+ st = st.replace(/\\begin{center}((.|\n)*?)\\end{center}/g,"<center>$1</center>");+ return st+}++function ASCIIandgraphformatting(st) {+ st = st.replace(/<sup>(.*?)<\/sup>(\s|(\S))/gi,"^{$1} $3");+//st = st.replace(/<\/?font.*?>/gi,""); // do this only in amath...endamath+ st = st.replace(/(Proof:)/g,"<i>$1</i>");+ st = st.replace(/QED/g," □");+ st = st.replace(/(\\?end{?a?math}?)/ig,"<span></span>$1");+ st = st.replace(/(\bamath\b|\\begin{a?math})/ig,"<span></span>$1");+ st = st.replace(/([>\n])(Theorem|Lemma|Proposition|Corollary|Definition|Example|Remark|Problem|Exercise|Conjecture|Solution)(:|\W\W?(\w|\s|-|\.)*?\W?:)/g,"$1<b>$2$3</b>");+ st = st.replace(/<embed\s+class\s?=\s?"?ASCIIsvg"?/gi,"<embed class=\"ASCIIsvg\" src=\""+dsvglocation+"d.svg\" wmode=\"transparent\"");+ st = st.replace(/(?:\\begin{a?graph}|\bagraph|\(:graph\s)((.|\n)*?)(?:\\end{a?graph}|enda?graph|:\))/g,function(s,t){return "<table><tr><td><div class=\"ASCIIsvg\"><embed class=\"ASCIIsvg\" src=\""+dsvglocation+"d.svg\" wmode=\"transparent\" script=\'"+t.replace(/<\/?(br|p|pre)\s?\/?>/gi,"\n")+"\'/></div></td></tr></table>"});+ st = st.replace(/insertASCIIMathCalculator/g,"<div class=\"ASCIIMathCalculator\"></div>");+//alert(dsvglocation)+ return st+}++function LMprocessNode(n) {+ var frag,st;+ try {+ st = n.innerHTML;+ } catch(err) {}+ var am = /amath\b|graph/i.test(st);+ if ((st==null || st.indexOf("\$ ")!=-1 || st.indexOf("\$<")!=-1 || + st.indexOf("\\begin")!=-1 || am || st.slice(-1)=="$" ||+ st.indexOf("\$\n")!=-1)&& !/edit-content|HTMLArea|wikiedit|wpTextbox1/.test(st)){+ if (!avoidinnerHTML && translateLaTeXformatting) + st = simpleLaTeXformatting(st);+ if (st!=null && am && !avoidinnerHTML) {+ st = ASCIIandgraphformatting(st);+ }+ st = st.replace(/%7E/g,"~"); // else PmWiki has url issues+//alert(st)+ if (!avoidinnerHTML) n.innerHTML = st;+ processNodeR(n,false,true);+ }+/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */+}++/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */++// you can change these+var checkIfSVGavailable = true;+var notifyIfNoSVG = true;+var alertIfNoSVG = false;+var noSVG = false;++// global defaults used if not specified by graph (you can change these)+var defaultwidth = 300; defaultheight = 200; // in pixels+var defaultxmin = -5.5; defaultxmax = 5.5; // in usercoords+var defaultborder = 0; border = defaultborder; // in pixel+var defaultstrokewidth = "1"; // default line width in pixel+var defaultstroke = "blue"; // default line color+var defaultstrokeopacity = 1; // transparent = 0, solid =1+var defaultstrokedasharray = null; // "10,10" gives 10px long dashes+var defaultfill = "none"; // default fill color+var defaultfillopacity = 1; // transparent = 0, solid =1+var defaultfontstyle = "normal"; // default text shape normal|italic|inherit+var defaultfontfamily = "times"; // default font times|ariel|helvetica|...+var defaultfontsize = "16"; // default size (scaled automatically)+var defaultfontweight = "normal";// normal|bold|bolder|lighter|100|...|900+var defaultfontstroke = "none"; // default font outline color+var defaultfontfill = "none"; // default font color+var defaultmarker = "none"; // "dot" | "arrow" | "+" | "-" | "|"+var defaultendpoints = ""; // "c-d" where c is <|o|* and d is >|o|*++// global values used for all pictures (you can change these)+var showcoordinates = true;+var markerstrokewidth = "1";+var markerstroke = "black";+var markerfill = "yellow";+var markersize = 4;+var arrowfill = stroke;+var dotradius = 4;+var ticklength = 4;+var axesstroke = "black";+var gridstroke = "grey";+var backgroundstyle = "fill-opacity:0; fill:white";+var singlelettersitalic = true;++// internal variables (probably no need to change these)+var picturepos = null; // position of picture relative to top of HTML page+var xunitlength; // in pixels, used to convert to user coordinates+var yunitlength; // in pixels+var origin = [0,0]; // in pixels (default is bottom left corner)+var above = "above"; // shorthands (to avoid typing quotes)+var below = "below";+var left = "left";+var right = "right";+var aboveleft = "aboveleft";+var aboveright = "aboveright";+var belowleft = "belowleft";+var belowright = "belowright";+var xmin, xmax, ymin, ymax, xscl, yscl, + xgrid, ygrid, xtick, ytick, initialized;+var strokewidth, strokedasharray, stroke, fill, strokeopacity, fillopacity;+var fontstyle, fontfamily, fontsize, fontweight, fontstroke, fontfill;+var marker, endpoints, dynamic = {};+var picture, svgpicture, doc, width, height;+var isIE = document.createElementNS==null;++//this is not used! var cpi = "\u03C0", ctheta = "\u03B8"; // character for pi, theta+var log = function(x) { return ln(x)/ln(10) };+var pi = Math.PI, e = Math.E, ln = Math.log, sqrt = Math.sqrt;+var floor = Math.floor, ceil = Math.ceil, abs = Math.abs;+var sin = Math.sin, cos = Math.cos, tan = Math.tan;+var arcsin = Math.asin, arccos = Math.acos, arctan = Math.atan;+var sec = function(x) { return 1/Math.cos(x) };+var csc = function(x) { return 1/Math.sin(x) };+var cot = function(x) { return 1/Math.tan(x) };+var arcsec = function(x) { return arccos(1/x) };+var arccsc = function(x) { return arcsin(1/x) };+var arccot = function(x) { return arctan(1/x) };+var sinh = function(x) { return (Math.exp(x)-Math.exp(-x))/2 };+var cosh = function(x) { return (Math.exp(x)+Math.exp(-x))/2 };+var tanh = + function(x) { return (Math.exp(x)-Math.exp(-x))/(Math.exp(x)+Math.exp(-x)) };+var sech = function(x) { return 1/cosh(x) };+var csch = function(x) { return 1/sinh(x) };+var coth = function(x) { return 1/tanh(x) };+var arcsinh = function(x) { return ln(x+Math.sqrt(x*x+1)) };+var arccosh = function(x) { return ln(x+Math.sqrt(x*x-1)) };+var arctanh = function(x) { return ln((1+x)/(1-x))/2 };+var sech = function(x) { return 1/cosh(x) };+var csch = function(x) { return 1/sinh(x) };+var coth = function(x) { return 1/tanh(x) };+var arcsech = function(x) { return arccosh(1/x) };+var arccsch = function(x) { return arcsinh(1/x) };+var arccoth = function(x) { return arctanh(1/x) };+var sign = function(x) { return (x==0?0:(x<0?-1:1)) };++function factorial(x,n) { // Factorial function+ if (n==null) n=1;+ if (Math.abs(x-Math.round(x*1000000)/1000000)<1e-15)+ x = Math.round(x*1000000)/1000000;+ if (x-Math.floor(x)!=0) return NaN;+ for (var i=x-n; i>0; i-=n) x*=i;+ return (x<0?NaN:(x==0?1:x));+}++function C(x,k) { // Binomial coefficient function+ var res=1;+ for (var i=0; i<k; i++) res*=(x-i)/(k-i);+ return res;+}++function chop(x,n) { // Truncate decimal number to n places after decimal point+ if (n==null) n=0;+ return Math.floor(x*Math.pow(10,n))/Math.pow(10,n);+}++function ran(a,b,n) { // Generate random number in [a,b] with n digits after .+ if (n==null) n=0;+ return chop((b+Math.pow(10,-n)-a)*Math.random()+a,n);+}++function myCreateElementSVG(t) {+ if (isIE) return doc.createElement(t);+ else return doc.createElementNS("http://www.w3.org/2000/svg",t);+}++function getElementsByClass(container, tagName, clsName){+ var list = new Array(0);+ var collection = container.getElementsByTagName(tagName);+ for(var i = 0; i < collection.length; i++)+ if(collection[i].className.slice(0,clsName.length)==clsName)+ list[list.length] = collection[i];+ return list;+}++function showobj(obj) {+ var st="", i;+ for (i in obj) + st += (obj.getAttribute(i)==null?"":" "+i+":"+obj.getAttribute(i));+ return st;+}++function findPos(obj) { // top-left corner of obj on HTML page in pixel+ var curleft = curtop = 0;+ if (obj.offsetParent) {+ curleft = obj.offsetLeft+ curtop = obj.offsetTop+ while (obj = obj.offsetParent) {+ curleft += obj.offsetLeft+ curtop += obj.offsetTop+//alert(showobj(obj)+[curleft,curtop])+ }+ }+ return [curleft,curtop];+}++function checkSVG(){+ if (navigator.appName.slice(0,8)=="Netscape") + if (window['SVGElement']) noSVG = null;+ else noSVG = true;+ else if (navigator.appName.slice(0,9)=="Microsoft")+ try {+ var oSVG=eval("new ActiveXObject('Adobe.SVGCtl.3');");+ noSVG = null;+ } catch (e) {+ noSVG = true;+ }+ else if (navigator.appName.slice(0,5)=="Opera") // works only for 9.50b1+ noSVG = null;+ else noSVG = true;+//noSVG = true; //uncomment to check+ if (noSVG && notifyIfNoSVG) {+ var msg = "To view the ASCIIsvg images use Internet Explorer + Adobe SVGviewer or Mozilla Firefox 2.0 or later."+ if (alertIfNoSVG)+ alert(msg);+ else return msg;+ }+}++function setText(st,id) { // add text to an existing node with given id+ var node = document.getElementById(id);+ if (node!=null)+ if (node.childNodes.length!=0) node.childNodes[0].nodeValue = st;+ else node.appendChild(document.createTextNode(st));+}++function getX(evt) { // return mouse x-coord in user coordinate system+ var svgroot = evt.target.parentNode;+ pos = findPos(svgroot.parentNode);+ return (evt.clientX+(isIE?0:window.pageXOffset)-pos[0]-svgroot.getAttribute("ox"))/parseFloat(svgroot.getAttribute("xunitlength"));+}++function getY(evt) { // return mouse y-coord in user coordinate system+ var svgroot = evt.target.parentNode;+ pos = findPos(svgroot.parentNode);+//alert(showobj(svgroot)+svgroot.getAttribute("mytop"))+ return (svgroot.getAttribute("height")-svgroot.getAttribute("oy")-(evt.clientY+(isIE?0:window.pageYOffset)-pos[1]))/parseFloat(svgroot.getAttribute("yunitlength"));+}++function translateandeval(src) { //modify user input to JavaScript syntax+ var errstr;+ // replace plot(f(x),...) with plot("f(x)",...) + src = src.replace(/plot\(\x20*([^\"f\[][^\n\r;]+?)\,/g,"plot\(\"$1\",");+ src = src.replace(/plot\(\x20*([^\"f\[][^\n\r;]+)\)/g,"plot(\"$1\")");++ // replace (expr,expr) by [expr,expr] where expr has no (,) in it+ src = src.replace(/([=[(,]\x20*)\(([-a-z0-9./+*]+?),([-a-z0-9./+*]+?)\)/g,"$1[$2,$3]");+//alert(src)+ // insert * between digit and letter e.g. 2x --> 2*x+ src = src.replace(/([0-9])([a-df-zA-Z]|e^)/g,"$1*$2");+ src = src.replace(/\)([\(0-9a-zA-Z])/g,"\)*$1");++ try {+ with (Math) eval(src); // here the svgpicture object is created+ } catch(err) {+ if (err!="wait") {+//alert(dsvglocation)+ if (typeof err=="object") + errstr = err.name+" "+err.message+" "+err.number+" "+err.description;+ else errstr = err;+ alert(errstr+"\n"+src)+ }+ }+}++var lastSlot = 0;++function drawPictures() { // main routine; called after webpage has loaded+ var src, id, dsvg, nd, node, ht, index, cols, arr, i, node2;+ var ASbody = document.getElementsByTagName("body")[0];+ pictures = getElementsByClass(ASbody,"embed","ASCIIsvg");+ var len = pictures.length;+ if(len==0) return;+ for (index = lastSlot; index < len+lastSlot; index++) {+ width = null; height = null; + xmin = null; xmax = null; ymin = null; ymax = null;+ xscl = null; xgrid = null; yscl = null; ygrid = null;+ initialized = false;+ picture = pictures[index-lastSlot]; // current picture object+ src = picture.getAttribute("script"); // get the ASCIIsvg code+ if (src==null) src = "";+ // insert "axes()" if not present ******** experimental+ if (!/axes\b|initPicture/.test(src)) {+ var i = 0;+ while (/((yscl|ymax|ymin|xscl|xmax|xmin|\bwidth|\bheight)\s*=\s*-?\d*(\d\.|\.\d|\d)\d*\s*;?)/.test(src.slice(i))) i++;+ src = (i==0?"axes(); "+src: src.slice(0,i)+src.slice(i).replace(/((scl|max|min|idth|eight)\s*=\s*-?\d*(\d\.|\.\d|\d)\d*\s*;?)/,"$1\naxes();"));+ }+ ht = picture.getAttribute("height");+ if (isIE) {+ picture.setAttribute("wmode","transparent");+//alert("*"+picture.getAttribute("src")+dsvglocation);+//adding d.svg dynamically greates problems in IE...+// if (picture.getAttribute("src")=="") picture.setAttribute("src",dsvglocation+"d.svg");+ }+ if (document.getElementById("picture"+(index+1)+"mml")==null) {+ picture.parentNode.style.position = "relative";+ node = createElementXHTML("div");+ node.style.position = "absolute";+ node.style.top = "0px";+ node.style.left = "0px";+ node.setAttribute("id","picture"+(index+1)+"mml");+ picture.parentNode.insertBefore(node,picture.nextSibling);+ }+ if (ht==null) ht ="";+// if (ht!="") defaultborder = 25;+ if (ht=="" || src=="") + if (document.getElementById("picture"+(index+1)+"input")==null) {+ node = createElementXHTML("textarea");+ arr = src.split("\n");+ cols = 0;+ for (i=0;i<arr.length;i++) cols = Math.max(cols,arr[i].length);+ node.setAttribute("rows",Math.min(10,arr.length)+1);+ node.setAttribute("cols",Math.max(Math.min(60,cols),20)+5);+// node.setAttribute("style","display:block");+ if (isIE) src = src.replace(/([^\r])\n/g,"$1\r");+ node.appendChild(document.createTextNode(src));+ if (src.indexOf("showcode()")==-1) node.style.display = "none";+ node.setAttribute("id","picture"+(index+1)+"input");+ picture.parentNode.insertBefore(node,picture.nextSibling);+ picture.parentNode.insertBefore(createElementXHTML("br"),node);+ node2 = createElementXHTML("button");+ node2.setAttribute("id","picture"+(index+1)+"button");+ if (isIE) node2.onclick = function() {updatePicture(this)};+ else node2.setAttribute("onclick","updatePicture(this)");+ node2.appendChild(document.createTextNode("Update"));+ if (src.indexOf("showcode()")==-1) node2.style.display = "none";+ picture.parentNode.insertBefore(node2,node);+// picture.parentNode.insertBefore(document.createTextNode("ASCII"),node);+ picture.parentNode.insertBefore(createElementXHTML("br"),node);+ } else src = document.getElementById("picture"+(index+1)+"input").value;+ id = picture.getAttribute("id");+ dsvg = picture.getAttribute("src");+ if (id == null || id == "") {+ id = "picture"+(index+1);+ picture.setAttribute("id",id);+ }+ translateandeval(src);+ }+ lastSlot+=len;+}++function setdefaults() { //called before each graph is evaluated+ strokewidth = defaultstrokewidth;+ stroke = defaultstroke;+ strokeopacity = defaultstrokeopacity;+ strokedasharray = defaultstrokedasharray;+ fill = defaultfill;+ fillopacity = defaultfillopacity;+ fontstyle = defaultfontstyle;+ fontfamily = defaultfontfamily;+ fontsize = defaultfontsize;+ fontweight = defaultfontweight;+ fontstroke = defaultfontstroke;+ fontfill = defaultfontfill;+ marker = defaultmarker;+ endpoints = defaultendpoints;+}++function switchTo(id) { // used by dynamic code to select appropriate graph+ if (id==undefined) return;+ var name = id;+ if (typeof name!="string") name = id.target.parentNode.getAttribute("name");+ picture = document.getElementById(name);+ width = picture.getAttribute("width")-0;+ height = picture.getAttribute("height")-0;+ setdefaults();+ if ((picture.nodeName == "EMBED" || picture.nodeName == "embed") && isIE) {+ svgpicture = picture.getSVGDocument().getElementById("root");+ doc = picture.getSVGDocument();+ } else {+ svgpicture = picture;+ doc = document;+ }+ xunitlength = parseFloat(svgpicture.getAttribute("xunitlength"));+ yunitlength = parseFloat(svgpicture.getAttribute("yunitlength"));+ xmin = parseFloat(svgpicture.getAttribute("xmin"));+ xmax = parseFloat(svgpicture.getAttribute("xmax"));+ ymin = parseFloat(svgpicture.getAttribute("ymin"));+ ymax = parseFloat(svgpicture.getAttribute("ymax"));+ origin = [svgpicture.getAttribute("ox")-0,svgpicture.getAttribute("oy")-0];+}++function updatePicture(obj) {+ var node, src, id, top, left;+ if (typeof obj=="object") id = obj.id.slice(0,-6);+ else id = (typeof obj=="string"?obj:"picture"+(obj+1));+ src = document.getElementById(id+"input").value;+ xmin = null; xmax = null; ymin = null; ymax = null;+ xscl = null; xgrid = null; yscl = null; ygrid = null;+ initialized = false;+ picture = document.getElementById(id);+ translateandeval(src)+}++function changepicturesize(evt,factor) {+ var obj = evt.target;+ var name = obj.parentNode.getAttribute("name");+ var pic = document.getElementById(name);+ var src = document.getElementById(name+"input").value;+ if (!/height/.test(src)) src = "height=0; "+src;+ if (!/width/.test(src)) src = "width=0; "+src;+ src = src.replace(/width\s*=\s*\d+/,"width="+(factor*(pic.getAttribute("width")-0)));+ src = src.replace(/height\s*=\s*\d+/,"height="+(factor*(pic.getAttribute("height")-0)));+ document.getElementById(name+"input").value = src;+//alert(getKey(evt.keycode))+ updatePicture(name);+}++function zoom(evt,factor) {+ switchTo(evt);+ var obj = evt.target;+ var name = obj.parentNode.getAttribute("name");+ var pic = document.getElementById(name);+ var src = document.getElementById(name+"input").value;+ var xlen = (xmax-xmin)/2;+ var ylen = (ymax-ymin)/2;+ var xcen = getX(evt), ycen = getY(evt);+ if (!/ymax/.test(src)) src = "ymax=0; "+src;+ if (!/ymin/.test(src)) src = "ymin=0; "+src;+ if (!/xmax/.test(src)) src = "xmax=0; "+src;+ if (!/xmin/.test(src)) src = "xmin=0; "+src;+ src = src.replace(/xmin\s*=\s*[-\d.e]+/,"xmin="+(xcen-factor*xlen));+ src = src.replace(/xmax\s*=\s*[-\d.e]+/,"xmax="+(xcen+factor*xlen));+ src = src.replace(/ymin\s*=\s*[-\d.e]+/,"ymin="+(ycen-factor*ylen));+ src = src.replace(/ymax\s*=\s*[-\d.e]+/,"ymax="+(ycen+factor*ylen));+ document.getElementById(name+"input").value = src;+ updatePicture(name);+}++var sinceFirstClick = 0; // ondblclick simulation from +var dblClkTimer; // http://www.enja.org/david/?cat=13 Thanks!+function timer() {+ if(sinceFirstClick<60) {+ sinceFirstClick++;+ setTimeout("timer()",10);+ } else {+ clearTimeout(dblClkTimer);+ dblClkTimer = "";+ }+}+function mClick(evt) {+ if(sinceFirstClick!=0) {+ if(sinceFirstClick <= 40) {+ if (evt.shiftKey) {+ if (evt.altKey) changepicturesize(evt,2);+ else zoom(evt,.5);+ } else if (evt.altKey) zoom(evt,2);//changepicturesize(evt,.5);+ else showHideCode(evt); // do this on dblclick+ clearTimeout(dblClkTimer);+ dblClkTimer = "";+ } else {+ clearTimeout(dblClkTimer);+ sinceFirstClick = 0;+ dblClkTimer = setTimeout("timer()",10);+ } + } else {+ sinceFirstClick = 0;+ dblClkTimer = setTimeout("timer()",10);+ }+}++function showHideCode(evt) { // called by onclick event+// if (evt.getDetail()==2) {//getDetail unfortunately not in Firefox+ var obj=evt.target;+ var name = obj.parentNode.getAttribute("name");+ var node = document.getElementById(name+"input");+ node.style.display = (node.style.display == "none"?"":"none");+ var node = document.getElementById(name+"button");+ node.style.display = (node.style.display == "none"?"":"none");+// }+}++function showcode() {} // do nothing++function setBorder(x) { border = x } //deprecate++function initPicture(x_min,x_max,y_min,y_max) { // set up the graph+// usually called by axes() or noaxes(), but can be used directly+ if (!initialized) {+ setdefaults();+ initialized = true;+ if (x_min!=null) xmin = x_min;+ if (x_max!=null) xmax = x_max;+ if (y_min!=null) ymin = y_min;+ if (y_max!=null) ymax = y_max;+ if (xmin==null) xmin = defaultxmin;+ if (xmax==null) xmax = defaultxmax;+ if (typeof xmin != "number" || typeof xmax != "number" || xmin >= xmax) + alert("Picture requires at least two numbers: xmin < xmax");+ else if (y_max != null && (typeof y_min != "number" || + typeof y_max != "number" || y_min >= y_max))+ alert("initPicture(xmin,xmax,ymin,ymax) requires numbers ymin < ymax");+ else {+ if (width==null) {+ width = picture.getAttribute("width");+ if (width==null || width=="") width=defaultwidth;+ }+ picture.setAttribute("width",width);+ if (height==null) { + height = picture.getAttribute("height");+ if (height==null || height=="") height=defaultheight;+ }+ picture.setAttribute("height",height);+ xunitlength = (width-2*border)/(xmax-xmin);+ yunitlength = xunitlength;+//alert(xmin+" "+xmax+" "+ymin+" "+ymax)+ if (ymin==null) {+ origin = [-xmin*xunitlength+border,height/2];+ ymin = -(height-2*border)/(2*yunitlength);+ ymax = -ymin;+ } else {+ if (ymax!=null) yunitlength = (height-2*border)/(ymax-ymin);+ else ymax = (height-2*border)/yunitlength + ymin;+ origin = [-xmin*xunitlength+border,-ymin*yunitlength+border];+ }+ if (isIE) {+ if (picture.FULLSCREEN==undefined) {+ setTimeout('drawPictures()',50);+ throw "wait";+ }+ svgpicture = picture.getSVGDocument().getElementById("root");+ if (svgpicture==null) {+ setTimeout('drawPictures()',50);+ throw "wait";+ }+ svgpicture = picture.getSVGDocument().getElementById("root");+ while (svgpicture.childNodes.length>0) + svgpicture.removeChild(svgpicture.lastChild); + svgpicture.setAttribute("width",width);+ svgpicture.setAttribute("height",height);+ svgpicture.setAttribute("name",picture.getAttribute("id"));+ doc = picture.getSVGDocument();+ } else {+ var qnode = document.createElementNS("http://www.w3.org/2000/svg","svg");+ qnode.setAttribute("id",picture.getAttribute("id"));+ qnode.setAttribute("name",picture.getAttribute("id"));+// qnode.setAttribute("style","display:inline");+ qnode.setAttribute("width",picture.getAttribute("width"));+ qnode.setAttribute("height",picture.getAttribute("height"));+ picturepos = findPos(picture);+// qnode.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink");+ if (picture.parentNode!=null) {+ picture.parentNode.replaceChild(qnode,picture);+ } else {+ svgpicture.parentNode.replaceChild(qnode,svgpicture);+ }+ svgpicture = qnode;+ doc = document;+ }+ var nd = document.getElementById(picture.getAttribute("id")+"mml");+ if (nd!=null) // clear out MathML layer+ while (nd.childNodes.length>0) nd.removeChild(nd.lastChild); + svgpicture.setAttribute("xunitlength",xunitlength);+ svgpicture.setAttribute("yunitlength",yunitlength);+ svgpicture.setAttribute("xmin",xmin);+ svgpicture.setAttribute("xmax",xmax);+ svgpicture.setAttribute("ymin",ymin);+ svgpicture.setAttribute("ymax",ymax);+ svgpicture.setAttribute("ox",origin[0]);+ svgpicture.setAttribute("oy",origin[1]);+ var node = myCreateElementSVG("rect");+ node.setAttribute("x","0");+ node.setAttribute("y","0");+ node.setAttribute("width",width);+ node.setAttribute("height",height);+ node.setAttribute("style",backgroundstyle);+ svgpicture.appendChild(node);+ svgpicture.setAttribute("onmousemove","displayCoord(evt)");+ svgpicture.setAttribute("onmouseout","removeCoord(evt)");+ svgpicture.setAttribute("onclick","mClick(evt)");+ node = myCreateElementSVG("text"); // used for displayCoord+ node.appendChild(doc.createTextNode(" "));+ node.setAttribute("id","coords");+ svgpicture.appendChild(node);+ node = myCreateElementSVG("text"); // used for text display+ node.appendChild(doc.createTextNode(" "));+ node.setAttribute("id","coords");+ svgpicture.appendChild(node);+ border = defaultborder;+ }+ }+}++//////////////////////////user graphics commands start/////////////////////////++function line(p,q,id,endpts) { // segment connecting points p,q (coordinates in units)+ var node;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("path");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("d","M"+(p[0]*xunitlength+origin[0])+","++ (height-p[1]*yunitlength-origin[1])+" "++ (q[0]*xunitlength+origin[0])+","+(height-q[1]*yunitlength-origin[1]));+ node.setAttribute("stroke-width", strokewidth);+ if (strokedasharray!=null) + node.setAttribute("stroke-dasharray", strokedasharray);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+ if (marker=="dot" || marker=="arrowdot") {+ ASdot(p,markersize,markerstroke,markerfill);+ if (marker=="arrowdot") arrowhead(p,q);+ ASdot(q,markersize,markerstroke,markerfill);+ } else if (marker=="arrow") arrowhead(p,q);+ if (endpts==null && endpoints!="") endpts = endpoints;+ if (endpts!=null) {+ if (endpts.indexOf("<-") != -1) arrowhead(q,p);+ if (endpts.indexOf("o-") != -1) dot(p, "open");+ if (endpts.indexOf("*-") != -1) dot(p, "closed");+ if (endpts.indexOf("->") != -1) arrowhead(p,q);+ if (endpts.indexOf("-o") != -1) dot(q, "open");+ if (endpts.indexOf("-*") != -1) dot(q, "closed");+ }+}++function path(plist,id,c,endpts) {+ if (c==null) c="";+ var node, st, i;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("path");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ if (typeof plist == "string") st = plist;+ else {+ st = "M";+ st += (plist[0][0]*xunitlength+origin[0])+","++ (height-plist[0][1]*yunitlength-origin[1])+" "+c;+ for (i=1; i<plist.length; i++)+ st += (plist[i][0]*xunitlength+origin[0])+","++ (height-plist[i][1]*yunitlength-origin[1])+" ";+ }+ node.setAttribute("d", st);+ node.setAttribute("stroke-width", strokewidth);+ if (strokedasharray!=null) + node.setAttribute("stroke-dasharray", strokedasharray);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+ if (marker=="dot" || marker=="arrowdot")+ for (i=0; i<plist.length; i++)+ if (c!="C" && c!="T" || i!=1 && i!=2)+ ASdot(plist[i],markersize,markerstroke,markerfill);+ if (endpts==null && endpoints!="") endpts = endpoints;+ if (endpts!=null) {+ if (endpts.indexOf("<-") != -1) arrowhead(plist[1],plist[0]);+ if (endpts.indexOf("o-") != -1) dot(plist[0], "open");+ if (endpts.indexOf("*-") != -1) dot(plist[0], "closed");+ if (endpts.indexOf("->") != -1) arrowhead(plist[plist.length-2],plist[plist.length-1]);+ if (endpts.indexOf("-o") != -1) dot(plist[plist.length-1], "open");+ if (endpts.indexOf("-*") != -1) dot(plist[plist.length-1], "closed");+ }+}++function curve(plist,id,endpts) {+ path(plist,id,"T",endpts);+}++function vector(p,q,id) {+ line(p,q,id,"","->");+}++function circle(center,radius,id) { // coordinates in units+ var node;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("circle");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("cx",center[0]*xunitlength+origin[0]);+ node.setAttribute("cy",height-center[1]*yunitlength-origin[1]);+ node.setAttribute("r",radius*xunitlength);+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+}++function loop(p,d,id) { +// d is a direction vector e.g. [1,0] means loop starts in that direction+ if (d==null) d=[1,0];+ path([p,[p[0]+d[0],p[1]+d[1]],[p[0]-d[1],p[1]+d[0]],p],id,"C");+ if (marker=="arrow" || marker=="arrowdot") + arrowhead([p[0]+Math.cos(1.4)*d[0]-Math.sin(1.4)*d[1],+ p[1]+Math.sin(1.4)*d[0]+Math.cos(1.4)*d[1]],p);+}++function arc(start,end,radius,id,largearc) { // coordinates in units+ var node, v;+//alert([fill, stroke, origin, xunitlength, yunitlength, height])+ if (id!=null) node = doc.getElementById(id);+ if (largearc==null) largearc=0;+ if (radius==null) {+ v=[end[0]-start[0],end[1]-start[1]];+ radius = Math.sqrt(v[0]*v[0]+v[1]*v[1]);+ }+ if (node==null) {+ node = myCreateElementSVG("path");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("d","M"+(start[0]*xunitlength+origin[0])+","++ (height-start[1]*yunitlength-origin[1])+" A"+radius*xunitlength+","++ radius*yunitlength+" 0 "+largearc+",0 "+(end[0]*xunitlength+origin[0])+","++ (height-end[1]*yunitlength-origin[1]));+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+ if (marker=="arrow" || marker=="arrowdot") {+ u = [(end[1]-start[1])/4,(start[0]-end[0])/4];+ v = [(end[0]-start[0])/2,(end[1]-start[1])/2];+//alert([u,v])+ v = [start[0]+v[0]+u[0],start[1]+v[1]+u[1]];+ } else v=[start[0],start[1]];+ if (marker=="dot" || marker=="arrowdot") {+ ASdot(start,markersize,markerstroke,markerfill);+ if (marker=="arrowdot") arrowhead(v,end);+ ASdot(end,markersize,markerstroke,markerfill);+ } else if (marker=="arrow") arrowhead(v,end);+}++function sector(center,start,end,id) { // center,start,end should be isoceles+ var rx = start[0]-center[0], ry = start[1]-center[1];+ arc(start,end,Math.sqrt(rx*rx+ry*ry),id+"arc");+ path([end,center,start],id+"path");+}++function ellipse(center,rx,ry,id) { // coordinates in units+ var node;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("ellipse");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("cx",center[0]*xunitlength+origin[0]);+ node.setAttribute("cy",height-center[1]*yunitlength-origin[1]);+ node.setAttribute("rx",rx*xunitlength);+ node.setAttribute("ry",ry*yunitlength);+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+}++function triangle(p,q,r,id) {+ path([p,q,r,p],id)+}++function rect(p,q,id,rx,ry) { // opposite corners in units, rounded by radii+ var node;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("rect");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("x",p[0]*xunitlength+origin[0]);+ node.setAttribute("y",height-q[1]*yunitlength-origin[1]);+ node.setAttribute("width",(q[0]-p[0])*xunitlength);+ node.setAttribute("height",(q[1]-p[1])*yunitlength);+ if (rx!=null) node.setAttribute("rx",rx*xunitlength);+ if (ry!=null) node.setAttribute("ry",ry*yunitlength);+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", fill);+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+}++function text(p,st,pos,id,fontsty) {+ var dnode, node, dx = 0, dy = fontsize/3, str = st.toString();+ if (/(`|\$)/.test(str)) { // layer for ASCIIMathML and LaTeXMathML+ dnode = document.getElementById(svgpicture.getAttribute("name")+"mml");+ if (dnode!=null) {+ if (id!=null) node = document.getElementById(id);+ if (node==null) {+//alert(dnode.childNodes.length)+ node = createElementXHTML("div");+ node.setAttribute("id", id);+ node.style.position = "absolute";+ dnode.appendChild(node);+ }+ while (node.childNodes.length>0) node.removeChild(node.lastChild); + node.appendChild(document.createTextNode(str));+ if (/`/.test(str)) AMprocessNode(node); else LMprocessNode(node);+ dx = -node.offsetWidth/2;+ dy = -node.offsetHeight/2;+ if (pos!=null) {+ if (/above/.test(pos)) dy = -node.offsetHeight;+ if (/below/.test(pos)) dy = 0;+ if (/right/.test(pos)) dx = 0;+ if ( /left/.test(pos)) dx = -node.offsetWidth;+ }+ node.style.left = ""+(p[0]*xunitlength+origin[0]+dx)+"px";+ node.style.top = ""+(height-p[1]*yunitlength-origin[1]+dy)+"px";+ }+ return p;+ }+ var textanchor = "middle"; // regular text goes into SVG+ if (pos!=null) {+ if (/above/.test(pos)) dy = -fontsize/2;+ if (/below/.test(pos)) dy = fontsize-0;+ if (/right/.test(pos)) {textanchor = "start"; dx = fontsize/4;}+ if ( /left/.test(pos)) {textanchor = "end"; dx = -fontsize/4;}+ }+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("text");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ node.appendChild(doc.createTextNode(str));+ }+ while (node.childNodes.length>1) node.removeChild(node.lastChild); + node.lastChild.nodeValue = "\xA0"+str+"\xA0";+ node.setAttribute("x",p[0]*xunitlength+origin[0]+dx);+ node.setAttribute("y",height-p[1]*yunitlength-origin[1]+dy);+ node.setAttribute("font-style",(fontsty!=null?fontsty:+ (str.search(/^[a-zA-Z]$/)!=-1?"italic":fontstyle)));+ node.setAttribute("font-family",fontfamily);+ node.setAttribute("font-size",fontsize);+ node.setAttribute("font-weight",fontweight);+ node.setAttribute("text-anchor",textanchor);+ if (fontstroke!="none") node.setAttribute("stroke",fontstroke);+ if (fontfill!="none") node.setAttribute("fill",fontfill);+ return p;+}++function mtext(p,st,pos,fontsty,fontsz) { // method for updating text on an svg+// "this" is the text object or the svgpicture object+ var textanchor = "middle";+ var dx = 0; var dy = fontsize/3;+ if (pos!=null) {+ if (pos.slice(0,5)=="above") dy = -fontsize/2;+ if (pos.slice(0,5)=="below") dy = fontsize-0;+ if (pos.slice(0,5)=="right" || pos.slice(5,10)=="right") {+ textanchor = "start";+ dx = fontsize/2;+ }+ if (pos.slice(0,4)=="left" || pos.slice(5,9)=="left") {+ textanchor = "end";+ dx = -fontsize/2;+ }+ }+ var node = this;+ if (this.nodeName=="svg") {+ node = myCreateElementSVG("text");+ this.appendChild(node);+ node.appendChild(doc.createTextNode(st));+ }+ node.lastChild.nodeValue = st;+ node.setAttribute("x",p[0]+dx);+ node.setAttribute("y",p[1]+dy);+ node.setAttribute("font-style",(fontsty!=null?fontsty:fontstyle));+ node.setAttribute("font-family",fontfamily);+ node.setAttribute("font-size",(fontsz!=null?fontsz:fontsize));+ node.setAttribute("font-weight",fontweight);+ node.setAttribute("text-anchor",textanchor);+ if (fontstroke!="none") node.setAttribute("stroke",fontstroke);+ if (fontfill!="none") node.setAttribute("fill",fontfill);+}++function image(imgurl,p,w,h,id) { // not working yet+ var node;+ if (id!=null) node = doc.getElementById(id);+ if (node==null) {+ node = myCreateElementSVG("image");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("x",p[0]*xunitlength+origin[0]);+ node.setAttribute("y",height-p[1]*yunitlength-origin[1]);+ node.setAttribute("width",w);+ node.setAttribute("height",h);+ node.setAttribute("xlink:href", imgurl);+}++function ASdot(center,radius,s,f) { // coordinates in units, radius in pixel+ if (s==null) s = stroke; if (f==null) f = fill;+ var node = myCreateElementSVG("circle");+ node.setAttribute("cx",center[0]*xunitlength+origin[0]);+ node.setAttribute("cy",height-center[1]*yunitlength-origin[1]);+ node.setAttribute("r",radius);+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", s);+ node.setAttribute("fill", f);+ svgpicture.appendChild(node);+}++function dot(center, typ, label, pos, id) {+ var node;+ var cx = center[0]*xunitlength+origin[0];+ var cy = height-center[1]*yunitlength-origin[1];+ if (id!=null) node = doc.getElementById(id);+ if (typ=="+" || typ=="-" || typ=="|") {+ if (node==null) {+ node = myCreateElementSVG("path");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ if (typ=="+") {+ node.setAttribute("d",+ " M "+(cx-ticklength)+" "+cy+" L "+(cx+ticklength)+" "+cy++ " M "+cx+" "+(cy-ticklength)+" L "+cx+" "+(cy+ticklength));+ node.setAttribute("stroke-width", .5);+ node.setAttribute("stroke", axesstroke);+ } else {+ if (typ=="-") node.setAttribute("d",+ " M "+(cx-ticklength)+" "+cy+" L "+(cx+ticklength)+" "+cy);+ else node.setAttribute("d",+ " M "+cx+" "+(cy-ticklength)+" L "+cx+" "+(cy+ticklength));+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ }+ } else {+ if (node==null) {+ node = myCreateElementSVG("circle");+ node.setAttribute("id", id);+ svgpicture.appendChild(node);+ }+ node.setAttribute("cx",cx);+ node.setAttribute("cy",cy);+ node.setAttribute("r",dotradius);+ node.setAttribute("stroke-width", strokewidth);+ node.setAttribute("stroke", stroke);+ node.setAttribute("fill", (typ=="open"?"white":+ (typ=="closed"?stroke:markerfill)));+ }+ if (label!=null) + text(center,label,(pos==null?"below":pos),(id==null?id:id+"label"))+}++point = dot; //alternative name++function arrowhead(p,q) { // draw arrowhead at q (in units) add size param+ var up;+ var v = [p[0]*xunitlength+origin[0],height-p[1]*yunitlength-origin[1]];+ var w = [q[0]*xunitlength+origin[0],height-q[1]*yunitlength-origin[1]];+ var u = [w[0]-v[0],w[1]-v[1]];+ var d = Math.sqrt(u[0]*u[0]+u[1]*u[1]);+ if (d > 0.00000001) {+ u = [u[0]/d, u[1]/d];+ up = [-u[1],u[0]];+ var node = myCreateElementSVG("path");+ node.setAttribute("d","M "+(w[0]-15*u[0]-4*up[0])+" "++ (w[1]-15*u[1]-4*up[1])+" L "+(w[0]-3*u[0])+" "+(w[1]-3*u[1])+" L "++ (w[0]-15*u[0]+4*up[0])+" "+(w[1]-15*u[1]+4*up[1])+" z");+ node.setAttribute("stroke-width", markerstrokewidth);+ node.setAttribute("stroke", stroke); /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */+ node.setAttribute("fill", stroke); /* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */+ node.setAttribute("stroke-opacity", strokeopacity);+ node.setAttribute("fill-opacity", fillopacity);+ svgpicture.appendChild(node); + }+}++function chopZ(st) {+ var k = st.indexOf(".");+ if (k==-1) return st;+ for (var i=st.length-1; i>k && st.charAt(i)=="0"; i--);+ if (i==k) i--;+ return st.slice(0,i+1);+}++function grid(dx,dy) { // for backward compatibility+ axes(dx,dy,null,dx,dy)+}++function noaxes() {+ if (!initialized) initPicture();+}++function axes(dx,dy,labels,gdx,gdy) {+//xscl=x is equivalent to xtick=x; xgrid=x; labels=true;+ var x, y, ldx, ldy, lx, ly, lxp, lyp, pnode, st;+ if (!initialized) initPicture();+ if (typeof dx=="string") { labels = dx; dx = null; }+ if (typeof dy=="string") { gdx = dy; dy = null; }+ if (xscl!=null) {dx = xscl; gdx = xscl; labels = dx}+ if (yscl!=null) {dy = yscl; gdy = yscl}+ if (xtick!=null) {dx = xtick}+ if (ytick!=null) {dy = ytick}+ dx = (dx==null?xunitlength:dx*xunitlength);+ dy = (dy==null?dx:dy*yunitlength);+ fontsize = Math.min(dx/2,dy/2,16); //alert(fontsize)+ ticklength = fontsize/4;+ if (xgrid!=null) gdx = xgrid;+ if (ygrid!=null) gdy = ygrid;+ if (gdx!=null) {+ gdx = (typeof gdx=="string"?dx:gdx*xunitlength);+ gdy = (gdy==null?dy:gdy*yunitlength);+ pnode = myCreateElementSVG("path");+ st="";+ for (x = origin[0]; x<width; x = x+gdx)+ st += " M"+x+",0"+" "+x+","+height;+ for (x = origin[0]-gdx; x>0; x = x-gdx)+ st += " M"+x+",0"+" "+x+","+height;+ for (y = height-origin[1]; y<height; y = y+gdy)+ st += " M0,"+y+" "+width+","+y;+ for (y = height-origin[1]-gdy; y>0; y = y-gdy)+ st += " M0,"+y+" "+width+","+y;+ pnode.setAttribute("d",st);+ pnode.setAttribute("stroke-width", .5);+ pnode.setAttribute("stroke", gridstroke);+ pnode.setAttribute("fill", fill);+ svgpicture.appendChild(pnode);+ }+ pnode = myCreateElementSVG("path");+ st="M0,"+(height-origin[1])+" "+width+","++ (height-origin[1])+" M"+origin[0]+",0 "+origin[0]+","+height;+ for (x = origin[0]+dx; x<width; x = x+dx)+ st += " M"+x+","+(height-origin[1]+ticklength)+" "+x+","++ (height-origin[1]-ticklength);+ for (x = origin[0]-dx; x>0; x = x-dx)+ st += " M"+x+","+(height-origin[1]+ticklength)+" "+x+","++ (height-origin[1]-ticklength);+ for (y = height-origin[1]+dy; y<height; y = y+dy)+ st += " M"+(origin[0]+ticklength)+","+y+" "+(origin[0]-ticklength)+","+y;+ for (y = height-origin[1]-dy; y>0; y = y-dy)+ st += " M"+(origin[0]+ticklength)+","+y+" "+(origin[0]-ticklength)+","+y;+ if (labels!=null) with (Math) {+ ldx = dx/xunitlength;+ ldy = dy/yunitlength;+ lx = (xmin>0 || xmax<0?xmin:0);+ ly = (ymin>0 || ymax<0?ymin:0);+ lxp = (ly==0?"below":"above");+ lyp = (lx==0?"left":"right");+ var ddx = floor(1.1-log(ldx)/log(10))+1;+ var ddy = floor(1.1-log(ldy)/log(10))+1;+ for (x = ldx; x<=xmax; x = x+ldx)+ text([x,ly],chopZ(x.toFixed(ddx)),lxp);+ for (x = -ldx; xmin<=x; x = x-ldx)+ text([x,ly],chopZ(x.toFixed(ddx)),lxp);+ for (y = ldy; y<=ymax; y = y+ldy)+ text([lx,y],chopZ(y.toFixed(ddy)),lyp);+ for (y = -ldy; ymin<=y; y = y-ldy)+ text([lx,y],chopZ(y.toFixed(ddy)),lyp);+ }+ fontsize = defaultfontsize;+ pnode.setAttribute("d",st);+ pnode.setAttribute("stroke-width", .5);+ pnode.setAttribute("stroke", axesstroke);+ pnode.setAttribute("fill", fill);+ pnode.setAttribute("stroke-opacity", strokeopacity);+ pnode.setAttribute("fill-opacity", fillopacity);+ svgpicture.appendChild(pnode);+}++function mathjs(st) {+ //translate a math formula to js function notation+ // a^b --> pow(a,b)+ // na --> n*a+ // (...)d --> (...)*d+ // n! --> factorial(n)+ // sin^-1 --> arcsin etc.+ //while ^ in string, find term on left and right+ //slice and concat new formula string+ st = st.replace(/\s/g,"");+ if (st.indexOf("^-1")!=-1) {+ st = st.replace(/sin\^-1/g,"arcsin");+ st = st.replace(/cos\^-1/g,"arccos");+ st = st.replace(/tan\^-1/g,"arctan");+ st = st.replace(/sec\^-1/g,"arcsec");+ st = st.replace(/csc\^-1/g,"arccsc");+ st = st.replace(/cot\^-1/g,"arccot");+ st = st.replace(/sinh\^-1/g,"arcsinh");+ st = st.replace(/cosh\^-1/g,"arccosh");+ st = st.replace(/tanh\^-1/g,"arctanh");+ st = st.replace(/sech\^-1/g,"arcsech");+ st = st.replace(/csch\^-1/g,"arccsch");+ st = st.replace(/coth\^-1/g,"arccoth");+ }+ st = st.replace(/^e$/g,"(Math.E)");+ st = st.replace(/^e([^a-zA-Z])/g,"(Math.E)$1");+ st = st.replace(/([^a-zA-Z])e/g,"$1(Math.E)");+// st = st.replace(/([^a-zA-Z])e([^a-zA-Z])/g,"$1(Math.E)$2");+ st = st.replace(/([0-9])([\(a-zA-Z])/g,"$1*$2");+ st = st.replace(/\)([\(0-9a-zA-Z])/g,"\)*$1");+ var i,j,k, ch, nested;+ while ((i=st.indexOf("^"))!=-1) {+ //find left argument+ if (i==0) return "Error: missing argument";+ j = i-1;+ ch = st.charAt(j);+ if (ch>="0" && ch<="9") {// look for (decimal) number+ j--;+ while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;+ if (ch==".") {+ j--;+ while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;+ }+ } else if (ch==")") {// look for matching opening bracket and function name+ nested = 1;+ j--;+ while (j>=0 && nested>0) {+ ch = st.charAt(j);+ if (ch=="(") nested--;+ else if (ch==")") nested++;+ j--;+ }+ while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")+ j--;+ } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable+ j--;+ while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")+ j--;+ } else { + return "Error: incorrect syntax in "+st+" at position "+j;+ }+ //find right argument+ if (i==st.length-1) return "Error: missing argument";+ k = i+1;+ ch = st.charAt(k);+ if (ch>="0" && ch<="9" || ch=="-") {// look for signed (decimal) number+ k++;+ while (k<st.length && (ch=st.charAt(k))>="0" && ch<="9") k++;+ if (ch==".") {+ k++;+ while (k<st.length && (ch=st.charAt(k))>="0" && ch<="9") k++;+ }+ } else if (ch=="(") {// look for matching closing bracket and function name+ nested = 1;+ k++;+ while (k<st.length && nested>0) {+ ch = st.charAt(k);+ if (ch=="(") nested++;+ else if (ch==")") nested--;+ k++;+ }+ } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable+ k++;+ while (k<st.length && (ch=st.charAt(k))>="a" && ch<="z" ||+ ch>="A" && ch<="Z") k++;+ } else { + return "Error: incorrect syntax in "+st+" at position "+k;+ }+ st = st.slice(0,j+1)+"Math.pow("+st.slice(j+1,i)+","+st.slice(i+1,k)+")"++ st.slice(k);+ }+ while ((i=st.indexOf("!"))!=-1) {+ //find left argument+ if (i==0) return "Error: missing argument";+ j = i-1;+ ch = st.charAt(j);+ if (ch>="0" && ch<="9") {// look for (decimal) number+ j--;+ while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;+ if (ch==".") {+ j--;+ while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;+ }+ } else if (ch==")") {// look for matching opening bracket and function name+ nested = 1;+ j--;+ while (j>=0 && nested>0) {+ ch = st.charAt(j);+ if (ch=="(") nested--;+ else if (ch==")") nested++;+ j--;+ }+ while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")+ j--;+ } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable+ j--;+ while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")+ j--;+ } else { + return "Error: incorrect syntax in "+st+" at position "+j;+ }+ st = st.slice(0,j+1)+"factorial("+st.slice(j+1,i)+")"+st.slice(i+1);+ }+ return st;+}++function plot(fun,x_min,x_max,points,id,endpts) {+ var pth = [];+ var f = function(x) { return x }, g = fun;+ var name = null;+ if (typeof fun=="string") + eval("g = function(x){ with(Math) return "+mathjs(fun)+" }");+ else if (typeof fun=="object") {+ eval("f = function(t){ with(Math) return "+mathjs(fun[0])+" }");+ eval("g = function(t){ with(Math) return "+mathjs(fun[1])+" }");+ }+ if (typeof x_min=="string") { name = x_min; x_min = xmin }+ else name = id;+ var min = (x_min==null?xmin:x_min);+ var max = (x_max==null?xmax:x_max);+ var inc = max-min-0.000001*(max-min);+ inc = (points==null?inc/200:inc/points);+ var gt;+//alert(typeof g(min))+ for (var t = min; t <= max; t += inc) {+ gt = g(t);+ if (!(isNaN(gt)||Math.abs(gt)=="Infinity")) pth[pth.length] = [f(t), gt];+ }+ path(pth,name,null,endpts);+ return pth;+}++// make polar plot++// make Riemann sums++function slopefield(fun,dx,dy) {+ var g = fun;+ if (typeof fun=="string") + eval("g = function(x,y){ with(Math) return "+mathjs(fun)+" }");+ var gxy,x,y,u,v,dz;+ if (dx==null) dx=1;+ if (dy==null) dy=1;+ dz = Math.sqrt(dx*dx+dy*dy)/6;+ var x_min = Math.ceil(xmin/dx);+ var y_min = Math.ceil(ymin/dy);+ for (x = x_min; x <= xmax; x += dx)+ for (y = y_min; y <= ymax; y += dy) {+ gxy = g(x,y);+ if (!isNaN(gxy)) {+ if (Math.abs(gxy)=="Infinity") {u = 0; v = dz;}+ else {u = dz/Math.sqrt(1+gxy*gxy); v = gxy*u;}+ line([x-u,y-v],[x+u,y+v]);+ }+ }+}++///////////////////////user graphics commands end here/////////////////////////++function show_props(obj) {+ var result = "";+ for (var i=0; i< obj.childNodes.length; i++)+ result += obj.childNodes.item(i) + "\n";+ return result;+}++function displayCoord(evt) {+ if (showcoordinates) {+ var svgroot = evt.target.parentNode;+ var nl = svgroot.childNodes;+ for (var i=0; i<nl.length && nl.item(i).nodeName!="text"; i++);+ var cnode = nl.item(i);+ cnode.mtext = mtext;+ cnode.mtext([svgroot.getAttribute("width")-(-7),svgroot.getAttribute("height")-7],"("+getX(evt).toFixed(2)+", "+getY(evt).toFixed(2)+")", "left", "", "11");+/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */ }+}++function removeCoord(evt) {+ var svgroot = evt.target.parentNode;+ var nl = svgroot.childNodes;+ for (var i=0; i<nl.length && nl.item(i).nodeName!="text"; i++);+ var cnode = nl.item(i);+ cnode.mtext = mtext;+ cnode.mtext([svgroot.getAttribute("width")-0,svgroot.getAttribute("height")-0],"", "aboveleft", "");+/* ASCIIMathML.js - copyright Peter Jipsen, released under the GPL+See http://www1.chapman.edu/~jipsen/mathml/asciimath.html/ */}++function initASCIIMathCalculators(li) {+ var i;+ for (i=0; i<li.length; i++) {+ li[i].innerHTML = calcstr;+ AMprocessNode(li[i]);+ }+ li = document.getElementsByTagName("textarea");+ var st;+ for (i=0; i<li.length; i++) {+ st = li[i].getAttribute("onkeyup");+ if (st!=null) eval(String(st).replace(/function anonymous\(\)/,""));+ }+}++function calculate(inputId,outputId) {+ var str = document.getElementById(inputId).value;+ var err = "";+ var ind = str.lastIndexOf("\n");+ if (ind==str.length-1) str = str.slice(0,ind);+ str = str.slice(str.lastIndexOf("\n")+1);+ try {+ var res = eval(mathjs(str));+ } catch(e) {+ err = "syntax incomplete";+ }+ if (!isNaN(res) && res!="Infinity") + str = "`"+str+" =` "+(Math.abs(res-Math.round(res*1000000)/1000000)<1e-15?Math.round(res*1000000)/1000000:res)+err; + else if (str!="") str = "`"+str+"` = undefined"; //debug:+mathjs(str);+ var outnode = document.getElementById(outputId);+ var n = outnode.childNodes.length;+ for (var i=0; i<n; i++)+ outnode.removeChild(outnode.firstChild);+ outnode.appendChild(document.createTextNode(str));+ AMprocessNode(outnode);+}++function append(st){+ document.getElementById('in').value+=st;+ calculate('in','out');+ document.getElementById('in').scrollTop = 1000;+ document.getElementById('in').focus();+}++function clearTextArea(){+ document.getElementById('in').value="";+ calculate('in','out');+ document.getElementById('in').focus();+}++var calcstr = "<table align=\"center\">\n<tr><th>\nASCIIMath Scientific Calculator\n</th></tr>\n<tr><td>\nClick in the box to use your keyboard or use the buttons\n</td></tr>\n<tr><td>\n<textarea id=\"in\" rows=\"3\" cols=\"40\" onkeyup=\"calculate('in','out')\"></textarea></td></tr>\n<tr><td height=\"50\">Result: <span id=\"out\"></span></td></tr>\n</table>\n<table align=\"center\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody align=\"center\">\n<tr>\n<td colspan=\"4\">\n<button onclick=\"append('sin^-1(')\"><font size=2>`sin^-1`</font></button><button onclick=\"append('cos^-1(')\"><font size=2>`cos^-1`</font></button><button onclick=\"append('tan^-1(')\"><font size=2>`tan^-1`</font></button></td>\n<td><button onclick=\"clearTextArea()\"> `C` </button></td>\n\n</tr>\n<tr>\n<td><button onclick=\"append('pi')\"> `pi` </button></td>\n<td><button onclick=\"append('sin(')\"> `sin`</button></td>\n<td><button onclick=\"append('cos(')\"> `cos`</button></td>\n<td><button onclick=\"append('tan(')\"> `tan`</button></td>\n<td><button onclick=\"append('^')\">`x^y`</button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('!')\"> `!` </button></td>\n\n<td><button onclick=\"append('(')\"><font size=2> `(` </font></button></td>\n<td><button onclick=\"append(')')\"><font size=2> `)` </font></button></td>\n<td><button onclick=\"append('sqrt(')\"><font size=2>`sqrt({::}^\ )`</font></button></td>\n<td><button onclick=\"append('/')\"> `-:\ `</button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('log(')\">`log`</button></td>\n<td><button onclick=\"append('7')\"> `7` </button></td>\n<td><button onclick=\"append('8')\"> `8` </button></td>\n\n<td><button onclick=\"append('9')\"> `9` </button></td>\n<td><button onclick=\"append('*')\"> `times` </button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('ln(')\"> `ln` </button></td>\n<td><button onclick=\"append('4')\"> `4` </button></td>\n<td><button onclick=\"append('5')\"> `5` </button></td>\n<td><button onclick=\"append('6')\"> `6` </button></td>\n\n<td><button onclick=\"append('-')\"> `-{::}` </button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('e')\"> `e` </button></td>\n<td><button onclick=\"append('1')\"> `1` </button></td>\n<td><button onclick=\"append('2')\"> `2` </button></td>\n<td><button onclick=\"append('3')\"> `3` </button></td>\n<td><button onclick=\"append('+')\"> `+{::}` </button></td>\n\n</tr>\n<tr>\n<td> <!--button onclick=\"append('pi')\"> `pi` </button--></td>\n<td><button onclick=\"append('0')\"> `0` </button></td>\n<td><button onclick=\"append('.')\"> `.` </button></td>\n<td><button onclick=\"append('\\n')\"> `\"ent\"`</button></td>\n</tr>\n</tbody>\n</table>";++// GO1.1 Generic onload by Brothercake+// http://www.brothercake.com/+//onload function (replaces the onload="translate()" in the <body> tag)+function generic()+{+ if(!init()) return;+ if (translateOnLoad) {+ var nd = document.getElementById("processasciimathinmoodle");+ if (nd!=null) dsvglocation = nd.className;+ if (nd!=null || !checkforprocessasciimathinmoodle) {+ translate();+ if (!noSVG && translateASCIIsvg) drawPictures();+ }+ var li = getElementsByClass(document,"div","ASCIIMathCalculator");+ if (!noMathML && li.length>0) initASCIIMathCalculators(li);+ } }; //setup onload function if(typeof window.addEventListener != 'undefined')
tests/s5.fragment.html view
@@ -10,6 +10,32 @@ >Math</h1 ><ul ><li- >$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</li+ ><span class="math"+ >\frac{<em+ >d</em+ >}{<em+ >dx</em+ >}<em+ >f</em+ >(<em+ >x</em+ >)=\lim<sub+ ><em+ >h</em+ > → 0</sub+ >\frac{<em+ >f</em+ >(<em+ >x</em+ >+<em+ >h</em+ >)-<em+ >f</em+ >(<em+ >x</em+ >)}{<em+ >h</em+ >}</span+ ></li ></ul >
tests/s5.inserts.html view
@@ -27,7 +27,33 @@ >Math</h1 ><ul ><li- >$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</li+ ><span class="math"+ >\frac{<em+ >d</em+ >}{<em+ >dx</em+ >}<em+ >f</em+ >(<em+ >x</em+ >)=\lim<sub+ ><em+ >h</em+ > → 0</sub+ >\frac{<em+ >f</em+ >(<em+ >x</em+ >+<em+ >h</em+ >)-<em+ >f</em+ >(<em+ >x</em+ >)}{<em+ >h</em+ >}</span+ ></li ></ul >STUFF INSERTED </body
tests/s5.native view
@@ -5,5 +5,5 @@ , [ Plain [Str "second",Space,Str "bullet"] ] ] , Header 1 [Str "Math"] , BulletList- [ [ Plain [TeX "$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}$"] ]+ [ [ Plain [Math "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"] ] ] ]
tests/tables.context view
@@ -133,4 +133,3 @@ \HL \stoptable -
tests/testsuite.native view
@@ -39,20 +39,6 @@ [ Para [Str "nested"] ] ] , Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1",Str "."]-, Para [Str "Box",Str "-",Str "style:"]-, BlockQuote- [ Para [Str "Example:"]- , CodeBlock "sub status {\n print \"working\";\n}" ]-, BlockQuote- [ OrderedList (1,Decimal,Period)- [ [ Plain [Str "do",Space,Str "laundry"] ]- , [ Plain [Str "take",Space,Str "out",Space,Str "the",Space,Str "trash"] ] ] ]-, Para [Str "Here",Apostrophe,Str "s",Space,Str "a",Space,Str "nested",Space,Str "one:"]-, BlockQuote- [ Para [Str "Joe",Space,Str "said:"]- , BlockQuote- [ Para [Str "Don",Apostrophe,Str "t",Space,Str "quote",Space,Str "me",Str "."] ]- ] , Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph",Str "."] , HorizontalRule , Header 1 [Str "Code",Space,Str "Blocks"]@@ -297,13 +283,13 @@ , BulletList [ [ Plain [TeX "\\cite[22-23]{smith.1899}"] ] , [ Plain [TeX "\\doublespacing"] ]- , [ Plain [TeX "$2+2=4$"] ]- , [ Plain [TeX "$x \\in y$"] ]- , [ Plain [TeX "$\\alpha \\wedge \\omega$"] ]- , [ Plain [TeX "$223$"] ]- , [ Plain [TeX "$p$",Str "-",Str "Tree"] ]- , [ Plain [TeX "$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}$"] ]- , [ Plain [Str "Here",Apostrophe,Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,TeX "$\\alpha + \\omega \\times x^2$",Str "."] ] ]+ , [ Plain [Math "2+2=4"] ]+ , [ Plain [Math "x \\in y"] ]+ , [ Plain [Math "\\alpha \\wedge \\omega"] ]+ , [ Plain [Math "223"] ]+ , [ Plain [Math "p",Str "-",Str "Tree"] ]+ , [ Plain [Math "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"] ]+ , [ Plain [Str "Here",Apostrophe,Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Math "\\alpha + \\omega \\times x^2",Str "."] ] ] , Para [Str "These",Space,Str "shouldn",Apostrophe,Str "t",Space,Str "be",Space,Str "math:"] , BulletList [ [ Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code "$e = mc^2$",Str "."] ]
tests/testsuite.txt view
@@ -78,31 +78,6 @@ This should not be a block quote: 2 > 1. -Box-style:--,-----| Example:-| -| sub status {-| print "working";-| }-`------,-----| 1. do laundry-| 2. take out the trash-`------Here's a nested one:--,-----| Joe said:-|-| ,-----| | Don't quote me.-| `-----`----- And a following paragraph. * * * *
tests/writer.context view
@@ -1,7 +1,7 @@ \enableregime[utf] % use UTF-8 \setupcolors[state=start]-\setupinteraction[state=start, color=middlered] % needed for hyperlinks+\setupinteraction[state=start, color=middleblue] % needed for hyperlinks \setuppapersize[letter][letter] % use letter paper \setuplayout[width=middle, backspace=1.5in, cutspace=1.5in,@@ -37,69 +37,77 @@ headstyle=bold,style=normal,align=left,location=hanging, width=broad,margin=1cm] -% define ltxitem (for bulleted lists) -\defineitemgroup[ltxitem][levels=4]-\setupitemgroup[ltxitem][1][1]-\setupitemgroup[ltxitem][2][2]-\setupitemgroup[ltxitem][3][3]-\setupitemgroup[ltxitem][4][4,packed]--% define ltxenum (for enumerated lists)-\defineitemgroup[ltxenum][levels=4]-\setupitemgroup[ltxenum][1][n]-\setupitemgroup[ltxenum][2][a]-\setupitemgroup[ltxenum][3][r]-\setupitemgroup[ltxenum][4][A,packed]+% define defaults for bulleted lists +\setupitemize[1][symbol=1][indentnext=no]+\setupitemize[2][symbol=2][indentnext=no]+\setupitemize[3][symbol=3][indentnext=no]+\setupitemize[4][symbol=4][indentnext=no] \setupthinrules[width=15em] % width of horizontal rules % for block quotations-\definestartstop [blockquote]- [before={\startnarrower\switchtobodyfont[11pt]- \whitespace\setupindenting[no]},- after={\stopnarrower\whitespace}]+\unprotect -\setupheads[sectionnumber=no, style=\bf]-\doctitle{Pandoc Test Suite}- \author{John MacFarlane \& Anonymous}- \date{July 17, 2006}+\startvariables all+blockquote: blockquote+\stopvariables +\definedelimitedtext+[\v!blockquote][\v!quotation]++\setupdelimitedtext+[\v!blockquote]+[\c!left=,+\c!right=,+before={\blank[medium]},+after={\blank[medium]},+]++\protect+ ++\doctitle{Pandoc Test Suite}+\author{John MacFarlane \& Anonymous}+\date{July 17, 2006} \starttext \maketitle -This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite.+This is a set of tests for pandoc. Most of them are adapted from+John Gruber's markdown test suite. \thinrule -\section{Headers}+\subject{Headers} -\subsection{Level 2 with an \useurl[1][/url][][embedded link]\from[1]}+\subsubject{Level 2 with an \useURL[1][/url][][embedded link]\from[1]} -\subsubsection{Level 3 with {\em emphasis}}+\subsubsubject{Level 3 with {\em emphasis}} -Level 4+\subsubsubsubject{Level 4} -Level 5+\subsubsubsubsubject{Level 5} -\section{Level 1}+\subject{Level 1} -\subsection{Level 2 with {\em emphasis}}+\subsubject{Level 2 with {\em emphasis}} -\subsubsection{Level 3}+\subsubsubject{Level 3} with no blank line -\subsection{Level 2}+\subsubject{Level 2} with no blank line \thinrule -\section{Paragraphs}+\subject{Paragraphs} Here's a regular paragraph. -In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item.+In Markdown 1.0.0 and earlier. Version 8. This line turns into a+list item. Because a hard-wrapped line in the middle of a paragraph+looked like a list item. Here's one with a bullet. * criminey. @@ -108,16 +116,17 @@ \thinrule -\section{Block Quotes}+\subject{Block Quotes} E-mail style: \startblockquote+ This is a block quote. It is pretty short. \stopblockquote- \startblockquote+ Code in a block quote: \starttyping@@ -125,64 +134,36 @@ print "working"; } \stoptyping+ A list: -\startitemize-\sym{1.} item one-\sym{2.} item two+\startitemize[n][stopper=.]+\item + item one+\item + item two \stopitemize+ Nested block quotes: \startblockquote-nested -\stopblockquote--\startblockquote nested \stopblockquote--\stopblockquote--This should not be a block quote: 2 \lettermore{} 1.--Box-style:- \startblockquote-Example: -\starttyping-sub status {- print "working";-}-\stoptyping-\stopblockquote+nested -\startblockquote-\startitemize-\sym{1.} do laundry-\sym{2.} take out the trash-\stopitemize \stopblockquote--Here's a nested one:--\startblockquote-Joe said:--\startblockquote-Don't quote me.- \stopblockquote--\stopblockquote+This should not be a block quote: 2 \lettermore{} 1. And a following paragraph. \thinrule -\section{Code Blocks}+\subject{Code Blocks} Code: @@ -195,6 +176,7 @@ this code block is indented by one tab \stoptyping+ And: \starttyping@@ -202,203 +184,299 @@ These should not be escaped: \$ \\ \> \[ \{ \stoptyping+ \thinrule -\section{Lists}+\subject{Lists} -\subsection{Unordered}+\subsubject{Unordered} Asterisks tight: -\startltxitem-\item asterisk 1-\item asterisk 2-\item asterisk 3-\stopltxitem+\startitemize+\item + asterisk 1+\item + asterisk 2+\item + asterisk 3+\stopitemize+ Asterisks loose: -\startltxitem-\item asterisk 1+\startitemize+\item + asterisk 1 -\item asterisk 2+\item + asterisk 2 -\item asterisk 3+\item + asterisk 3 -\stopltxitem+\stopitemize+ Pluses tight: -\startltxitem-\item Plus 1-\item Plus 2-\item Plus 3-\stopltxitem+\startitemize+\item + Plus 1+\item + Plus 2+\item + Plus 3+\stopitemize+ Pluses loose: -\startltxitem-\item Plus 1+\startitemize+\item + Plus 1 -\item Plus 2+\item + Plus 2 -\item Plus 3+\item + Plus 3 -\stopltxitem+\stopitemize+ Minuses tight: -\startltxitem-\item Minus 1-\item Minus 2-\item Minus 3-\stopltxitem+\startitemize+\item + Minus 1+\item + Minus 2+\item + Minus 3+\stopitemize+ Minuses loose: -\startltxitem-\item Minus 1+\startitemize+\item + Minus 1 -\item Minus 2+\item + Minus 2 -\item Minus 3+\item + Minus 3 -\stopltxitem-\subsection{Ordered}+\stopitemize +\subsubject{Ordered}+ Tight: -\startitemize-\sym{1.} First-\sym{2.} Second-\sym{3.} Third+\startitemize[n][stopper=.]+\item + First+\item + Second+\item + Third \stopitemize+ and: -\startitemize-\sym{1.} One-\sym{2.} Two-\sym{3.} Three+\startitemize[n][stopper=.]+\item + One+\item + Two+\item + Three \stopitemize+ Loose using tabs: -\startitemize-\sym{1.} First+\startitemize[n][stopper=.]+\item + First -\sym{2.} Second+\item + Second -\sym{3.} Third+\item + Third \stopitemize+ and using spaces: -\startitemize-\sym{1.} One+\startitemize[n][stopper=.]+\item + One -\sym{2.} Two+\item + Two -\sym{3.} Three+\item + Three \stopitemize+ Multiple paragraphs: -\startitemize-\sym{1.} Item 1, graf one.+\startitemize[n][stopper=.]+\item + Item 1, graf one. -Item 1. graf two. The quick brown fox jumped over the lazy dog's back.+ Item 1. graf two. The quick brown fox jumped over the lazy dog's+ back. -\sym{2.} Item 2.+\item + Item 2. -\sym{3.} Item 3.+\item + Item 3. \stopitemize-\subsection{Nested} -\startltxitem-\item Tab-\startltxitem-\item Tab-\startltxitem-\item Tab-\stopltxitem-\stopltxitem-\stopltxitem-Here's another:+\subsubject{Nested} \startitemize-\sym{1.} First-\sym{2.} Second:-\startltxitem-\item Fee-\item Fie-\item Foe-\stopltxitem-\sym{3.} Third+\item + Tab+ \startitemize+ \item + Tab+ \startitemize+ \item + Tab+ \stopitemize++ \stopitemize+ \stopitemize++Here's another:++\startitemize[n][stopper=.]+\item + First+\item + Second:+ \startitemize+ \item + Fee+ \item + Fie+ \item + Foe+ \stopitemize++\item + Third+\stopitemize+ Same thing but with paragraphs: -\startitemize-\sym{1.} First+\startitemize[n][stopper=.]+\item + First -\sym{2.} Second:+\item + Second: -\startltxitem-\item Fee-\item Fie-\item Foe-\stopltxitem-\sym{3.} Third+ \startitemize+ \item + Fee+ \item + Fie+ \item + Foe+ \stopitemize -\stopitemize-\subsection{Tabs and spaces}+\item + Third -\startltxitem-\item this is a list item indented with tabs+\stopitemize -\item this is a list item indented with spaces+\subsubject{Tabs and spaces} -\startltxitem-\item this is an example list item indented with tabs+\startitemize+\item + this is a list item indented with tabs -\item this is an example list item indented with spaces+\item + this is a list item indented with spaces -\stopltxitem-\stopltxitem-\subsection{Fancy list markers}+ \startitemize+ \item + this is an example list item indented with tabs -\startitemize[width=2em]-\sym{(2)} begins with 2-\sym{(3)} and now 3+ \item + this is an example list item indented with spaces -with a continuation+ \stopitemize -\startitemize[width=2em]-\sym{iv.} sublist with roman numerals, starting with 4-\sym{v.} more items-\startitemize[width=2em]-\sym{(A)} a subsublist-\sym{(B)} a subsublist \stopitemize-\stopitemize++\subsubject{Fancy list markers}++\startitemize[n][start=2,left=(,stopper=),width=2.0em]+\item + begins with 2+\item + and now 3++ with a continuation++ \startitemize[r][start=4,stopper=.,width=2.0em]+ \item + sublist with roman numerals, starting with 4+ \item + more items+ \startitemize[A][left=(,stopper=),width=2.0em]+ \item + a subsublist+ \item + a subsublist+ \stopitemize++ \stopitemize+ \stopitemize+ Nesting: -\startitemize-\sym{A.} Upper Alpha-\startitemize-\sym{I.} Upper Roman.-\startitemize[width=2em]-\sym{(6)} Decimal start with 6-\startitemize-\sym{c)} Lower alpha with paren-\stopitemize-\stopitemize-\stopitemize+\startitemize[A][stopper=.]+\item + Upper Alpha+ \startitemize[R][stopper=.]+ \item + Upper Roman.+ \startitemize[n][start=6,left=(,stopper=),width=2.0em]+ \item + Decimal start with 6+ \startitemize[a][start=3,stopper=)]+ \item + Lower alpha with paren+ \stopitemize++ \stopitemize++ \stopitemize+ \stopitemize+ Autonumbering: -\startltxenum-\item Autonumber.-\item More.-\startltxenum-\item Nested.-\stopltxenum-\stopltxenum+\startitemize[n]+\item + Autonumber.+\item + More.+ \startitemize[a]+ \item + Nested.+ \stopitemize++\stopitemize+ Should not be a list item: M.A. 2007@@ -407,36 +485,30 @@ \thinrule -\section{Definition Lists}+\subject{Definition Lists} Tight using spaces: \startdescr{apple} red fruit- \stopdescr \startdescr{orange} orange fruit- \stopdescr \startdescr{banana} yellow fruit- \stopdescr Tight using tabs: \startdescr{apple} red fruit- \stopdescr \startdescr{orange} orange fruit- \stopdescr \startdescr{banana} yellow fruit- \stopdescr Loose:@@ -444,17 +516,14 @@ \startdescr{apple} red fruit - \stopdescr \startdescr{orange} orange fruit - \stopdescr \startdescr{banana} yellow fruit - \stopdescr Multiple blocks with italics:@@ -464,7 +533,6 @@ contains seeds, crisp, pleasant to taste - \stopdescr \startdescr{{\em orange}} orange fruit@@ -472,15 +540,15 @@ \starttyping { orange code block } \stoptyping+ \startblockquote+ orange block quote \stopblockquote-- \stopdescr -\section{HTML Blocks}+\subject{HTML Blocks} Simple block on one line: @@ -503,11 +571,13 @@ foo </div> \stoptyping+ As should this: \starttyping <div>foo</div> \stoptyping+ Now, nested: foo@@ -520,6 +590,7 @@ \starttyping <!-- Comment --> \stoptyping+ Just plain comment, with trailing spaces on the line: Code:@@ -527,17 +598,18 @@ \starttyping <hr /> \stoptyping+ Hr's: \thinrule -\section{Inline Markup}+\subject{Inline Markup} This is {\em emphasized}, and so {\em is this}. This is {\bf strong}, and so {\bf is this}. -An {\em \useurl[2][/url][][emphasized link]\from[2]}.+An {\em \useURL[2][/url][][emphasized link]\from[2]}. {\bf {\em This is strong and em.}} @@ -547,7 +619,8 @@ So is {\bf {\em this}} word. -This is code: \type{>}, \type{$}, \type{\}, \type{\$}, \type{<html>}.+This is code: \type{>}, \type{$}, \type{\}, \type{\$},+\type{<html>}. \overstrikes{This is {\em strikeout}.} @@ -555,21 +628,27 @@ Subscripts: H\low{2}O, H\low{23}O, H\low{many of them}O. -These should not be superscripts or subscripts, because of the unescaped spaces: a\letterhat{}b c\letterhat{}d, a\lettertilde{}b c\lettertilde{}d.+These should not be superscripts or subscripts, because of the+unescaped spaces: a\letterhat{}b c\letterhat{}d, a\lettertilde{}b+c\lettertilde{}d. \thinrule -\section{Smart quotes, ellipses, dashes}+\subject{Smart quotes, ellipses, dashes} -\quotation{Hello,} said the spider. \quotation{\quote{Shelob} is my name.}+\quotation{Hello,} said the spider.+\quotation{\quote{Shelob} is my name.} \quote{A}, \quote{B}, and \quote{C} are letters. -\quote{Oak,} \quote{elm,} and \quote{beech} are names of trees. So is \quote{pine.}+\quote{Oak,} \quote{elm,} and \quote{beech} are names of trees. So+is \quote{pine.} -\quote{He said, \quotation{I want to go.}} Were you alive in the 70's?+\quote{He said, \quotation{I want to go.}} Were you alive in the+70's? -Here is some quoted \quote{\type{code}} and a \quotation{\useurl[3][http://example.com/?foo=1&bar=2][][quoted link]\from[3]}.+Here is some quoted \quote{\type{code}} and a+\quotation{\useURL[3][http://example.com/?foo=1&bar=2][][quoted link]\from[3]}. Some dashes: one---two---three---four---five. @@ -579,17 +658,23 @@ \thinrule -\section{Special Characters}+\subject{Special Characters} Here is some unicode: -\startltxitem-\item I hat: Î-\item o umlaut: ö-\item section: §-\item set membership: ∈-\item copyright: ©-\stopltxitem+\startitemize+\item + I hat: Î+\item + o umlaut: ö+\item + section: §+\item + set membership: ∈+\item + copyright: ©+\stopitemize+ AT\&T has an ampersand in their name. AT\&T is another way to write it.@@ -634,89 +719,102 @@ \thinrule -\section{Links}+\subject{Links} -\subsection{Explicit}+\subsubject{Explicit} -Just a \useurl[4][/url/][][URL]\from[4].+Just a \useURL[4][/url/][][URL]\from[4]. -\useurl[5][/url/][][URL and title]\from[5].+\useURL[5][/url/][][URL and title]\from[5]. -\useurl[6][/url/][][URL and title]\from[6].+\useURL[6][/url/][][URL and title]\from[6]. -\useurl[7][/url/][][URL and title]\from[7].+\useURL[7][/url/][][URL and title]\from[7]. -\useurl[8][/url/][][URL and title]\from[8]+\useURL[8][/url/][][URL and title]\from[8] -\useurl[9][/url/][][URL and title]\from[9]+\useURL[9][/url/][][URL and title]\from[9] -\useurl[10][/url/with_underscore][][with\letterunderscore{}underscore]\from[10]+\useURL[10][/url/with_underscore][][with\letterunderscore{}underscore]\from[10] -\useurl[11][mailto:nobody@nowhere.net][][Email link]\from[11]+\useURL[11][mailto:nobody@nowhere.net][][Email link]\from[11] -\useurl[12][][][Empty]\from[12].+\useURL[12][][][Empty]\from[12]. -\subsection{Reference}+\subsubject{Reference} -Foo \useurl[13][/url/][][bar]\from[13].+Foo \useURL[13][/url/][][bar]\from[13]. -Foo \useurl[14][/url/][][bar]\from[14].+Foo \useURL[14][/url/][][bar]\from[14]. -Foo \useurl[15][/url/][][bar]\from[15].+Foo \useURL[15][/url/][][bar]\from[15]. -With \useurl[16][/url/][][embedded [brackets]]\from[16].+With \useURL[16][/url/][][embedded [brackets]]\from[16]. -\useurl[17][/url/][][b]\from[17] by itself should be a link.+\useURL[17][/url/][][b]\from[17] by itself should be a link. -Indented \useurl[18][/url][][once]\from[18].+Indented \useURL[18][/url][][once]\from[18]. -Indented \useurl[19][/url][][twice]\from[19].+Indented \useURL[19][/url][][twice]\from[19]. -Indented \useurl[20][/url][][thrice]\from[20].+Indented \useURL[20][/url][][thrice]\from[20]. This should [not][] be a link. \starttyping [not]: /url \stoptyping-Foo \useurl[21][/url/][][bar]\from[21]. -Foo \useurl[22][/url/][][biz]\from[22].+Foo \useURL[21][/url/][][bar]\from[21]. -\subsection{With ampersands}+Foo \useURL[22][/url/][][biz]\from[22]. -Here's a \useurl[23][http://example.com/?foo=1&bar=2][][link with an ampersand in the URL]\from[23].+\subsubject{With ampersands} -Here's a link with an amersand in the link text: \useurl[24][http://att.com/][][AT\&T]\from[24].+Here's a+\useURL[23][http://example.com/?foo=1&bar=2][][link with an ampersand in the URL]\from[23]. -Here's an \useurl[25][/script?foo=1&bar=2][][inline link]\from[25].+Here's a link with an amersand in the link text:+\useURL[24][http://att.com/][][AT\&T]\from[24]. -Here's an \useurl[26][/script?foo=1&bar=2][][inline link in pointy braces]\from[26].+Here's an+\useURL[25][/script?foo=1&bar=2][][inline link]\from[25]. -\subsection{Autolinks}+Here's an+\useURL[26][/script?foo=1&bar=2][][inline link in pointy braces]\from[26]. -With an ampersand: \useurl[27][http://example.com/?foo=1&bar=2][][http://example.com/?foo=1\&bar=2]\from[27]+\subsubject{Autolinks} -\startltxitem-\item In a list?-\item \useurl[28][http://example.com/][][http://example.com/]\from[28]-\item It should.-\stopltxitem-An e-mail address: \useurl[29][mailto:nobody@nowhere.net][][nobody@nowhere.net]\from[29]+With an ampersand:+\useURL[27][http://example.com/?foo=1&bar=2][][http://example.com/?foo=1\&bar=2]\from[27] +\startitemize+\item + In a list?+\item + \useURL[28][http://example.com/][][http://example.com/]\from[28]+\item + It should.+\stopitemize++An e-mail address:+\useURL[29][mailto:nobody@nowhere.net][][nobody@nowhere.net]\from[29]+ \startblockquote-Blockquoted: \useurl[30][http://example.com/][][http://example.com/]\from[30] -\stopblockquote+Blockquoted:+\useURL[30][http://example.com/][][http://example.com/]\from[30] +\stopblockquote Auto-links should not occur here: \type{<http://example.com/>} \starttyping or here: <http://example.com/> \stoptyping+ \thinrule -\section{Images}+\subject{Images} From \quotation{Voyage dans la Lune} by Georges Melies (1902): @@ -726,7 +824,8 @@ {Voyage dans la Lune} {\externalfigure[lalune.jpg]} -Here is a movie \placefigure+Here is a movie+\placefigure [] [fig:movie] {}@@ -734,37 +833,43 @@ \thinrule -\section{Footnotes}--Here is a footnote reference,\footnote{Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.+\subject{Footnotes} -} and another.\footnote{Here's the long note. This one contains multiple blocks.+Here is a footnote reference,+\footnote{Here is the footnote. It can go anywhere after the footnote+reference. It need not be placed at the end of the document.}+and another.+\footnote{Here's the long note. This one contains multiple blocks. -Subsequent blocks are indented to show that they belong to the footnote (as with list items).+Subsequent blocks are indented to show that they belong to the+footnote (as with list items). \starttyping { <code> } \stoptyping-If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. -} This should {\em not} be a footnote reference, because it contains a space.[\letterhat{}my note] Here is an inline note.\footnote{This is {\em easier} to type. Inline notes may contain \useurl[31][http://google.com][][links]\from[31] and \type{]} verbatim characters, as well as [bracketed text].--}+If you want, you can indent every line, but you can also be lazy+and just indent the first line of each block.}+This should {\em not} be a footnote reference, because it contains+a space.[\letterhat{}my note] Here is an inline note.+\footnote{This is {\em easier} to type. Inline notes may contain+\useURL[31][http://google.com][][links]\from[31] and \type{]}+verbatim characters, as well as [bracketed text].} \startblockquote-Notes can go in quotes.\footnote{In quote. -}+Notes can go in quotes.+\footnote{In quote.} \stopblockquote--\startitemize-\sym{1.} And in list items.\footnote{In list.--}+\startitemize[n][stopper=.]+\item + And in list items.+ \footnote{In list.} \stopitemize-This paragraph should not be part of the note, as it is not indented. +This paragraph should not be part of the note, as it is not+indented. \stoptext
tests/writer.docbook view
@@ -125,46 +125,6 @@ This should not be a block quote: 2 > 1. </para> <para>- Box-style:- </para>- <blockquote>- <para>- Example:- </para>- <screen>-sub status {- print "working";-}-</screen>- </blockquote>- <blockquote>- <orderedlist numeration="arabic">- <listitem>- <para>- do laundry- </para>- </listitem>- <listitem>- <para>- take out the trash- </para>- </listitem>- </orderedlist>- </blockquote>- <para>- Here's a nested one:- </para>- <blockquote>- <para>- Joe said:- </para>- <blockquote>- <para>- Don't quote me.- </para>- </blockquote>- </blockquote>- <para> And a following paragraph. </para> </section>@@ -883,48 +843,46 @@ <itemizedlist> <listitem> <para>- <literal>\cite[22-23]{smith.1899}</literal> </para> </listitem> <listitem> <para>- <literal>\doublespacing</literal> </para> </listitem> <listitem> <para>- <literal>$2+2=4$</literal>+ 2+2=4 </para> </listitem> <listitem> <para>- <literal>$x \in y$</literal>+ <emphasis>x</emphasis> ∈ <emphasis>y</emphasis> </para> </listitem> <listitem> <para>- <literal>$\alpha \wedge \omega$</literal>+ α ∧ ω </para> </listitem> <listitem> <para>- <literal>$223$</literal>+ 223 </para> </listitem> <listitem> <para>- <literal>$p$</literal>-Tree+ <emphasis>p</emphasis>-Tree </para> </listitem> <listitem> <para>- <literal>$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</literal>+ \frac{<emphasis>d</emphasis>}{<emphasis>dx</emphasis>}<emphasis>f</emphasis>(<emphasis>x</emphasis>)=\lim<subscript><emphasis>h</emphasis> → 0</subscript>\frac{<emphasis>f</emphasis>(<emphasis>x</emphasis>+<emphasis>h</emphasis>)-<emphasis>f</emphasis>(<emphasis>x</emphasis>)}{<emphasis>h</emphasis>} </para> </listitem> <listitem> <para> Here's one that has a line break in it:- <literal>$\alpha + \omega \times x^2$</literal>.+ α+ω × <emphasis>x</emphasis><superscript>2</superscript>. </para> </listitem> </itemizedlist>@@ -954,11 +912,6 @@ Here's a LaTeX table: </para> <para>- <literal>\begin{tabular}{|l|l|}\hline-Animal & Number \\ \hline-Dog & 2 \\-Cat & 1 \\ \hline-\end{tabular}</literal> </para> </section> <section>
tests/writer.html view
@@ -105,37 +105,6 @@ ><p >This should not be a block quote: 2 > 1.</p ><p- >Box-style:</p- ><blockquote- ><p- >Example:</p- ><pre- ><code- >sub status {- print "working";-}-</code- ></pre- ></blockquote- ><blockquote- ><ol class="decimal"- ><li- >do laundry</li- ><li- >take out the trash</li- ></ol- ></blockquote- ><p- >Here’s a nested one:</p- ><blockquote- ><p- >Joe said:</p- ><blockquote- ><p- >Don’t quote me.</p- ></blockquote- ></blockquote- ><p >And a following paragraph.</p ><hr /><h1 id="code-blocks"@@ -758,23 +727,71 @@ >LaTeX</h1 ><ul ><li- >\cite[22-23]{smith.1899}</li+ ></li ><li- >\doublespacing</li+ ></li ><li- >$2+2=4$</li+ ><span class="math"+ >2+2=4</span+ ></li ><li- >$x \in y$</li+ ><span class="math"+ ><em+ >x</em+ > ∈ <em+ >y</em+ ></span+ ></li ><li- >$\alpha \wedge \omega$</li+ ><span class="math"+ >α ∧ ω</span+ ></li ><li- >$223$</li+ ><span class="math"+ >223</span+ ></li ><li- >$p$-Tree</li+ ><span class="math"+ ><em+ >p</em+ ></span+ >-Tree</li ><li- >$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</li+ ><span class="math"+ >\frac{<em+ >d</em+ >}{<em+ >dx</em+ >}<em+ >f</em+ >(<em+ >x</em+ >)=\lim<sub+ ><em+ >h</em+ > → 0</sub+ >\frac{<em+ >f</em+ >(<em+ >x</em+ >+<em+ >h</em+ >)-<em+ >f</em+ >(<em+ >x</em+ >)}{<em+ >h</em+ >}</span+ ></li ><li- >Here’s one that has a line break in it: $\alpha + \omega \times x^2$.</li+ >Here’s one that has a line break in it: <span class="math"+ >α+ω × <em+ >x</em+ ><sup+ >2</sup+ ></span+ >.</li ></ul ><p >These shouldn’t be math:</p@@ -797,11 +814,7 @@ ><p >Here’s a LaTeX table:</p ><p- >\begin{tabular}{|l|l|}\hline-Animal & Number \\ \hline-Dog & 2 \\-Cat & 1 \\ \hline-\end{tabular}</p+ ></p ><hr /><h1 id="special-characters" >Special Characters</h1@@ -1033,7 +1046,7 @@ ><img src="lalune.jpg" title="Voyage dans la Lune" alt="lalune" /></p ><p- >Here is a movie <img src="movie.jpg" title="" alt="movie"+ >Here is a movie <img src="movie.jpg" alt="movie" /> icon.</p ><hr /><h1 id="footnotes"
tests/writer.latex view
@@ -100,35 +100,6 @@ \end{quote} This should not be a block quote: 2 \textgreater{} 1. -Box-style:--\begin{quote}-Example:--\begin{verbatim}-sub status {- print "working";-}-\end{verbatim}-\end{quote}-\begin{quote}-\begin{enumerate}[1.]-\item - do laundry-\item - take out the trash-\end{enumerate}-\end{quote}-Here's a nested one:--\begin{quote}-Joe said:--\begin{quote}-Don't quote me.--\end{quote}-\end{quote} And a following paragraph. \begin{center}\rule{3in}{0.4pt}\end{center}@@ -791,12 +762,11 @@ \section{Footnotes} -Here is a footnote-reference,\footnote{ Here is the footnote. It can go anywhere after the footnote-reference. It need not be placed at the end of the document.-}-and-another.\footnote{ Here's the long note. This one contains multiple blocks.+Here is a footnote reference,%+\footnote{Here is the footnote. It can go anywhere after the footnote+reference. It need not be placed at the end of the document.}+and another.%+\footnote{Here's the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items).@@ -805,24 +775,22 @@ { <code> } \end{Verbatim} If you want, you can indent every line, but you can also be lazy-and just indent the first line of each block.-}+and just indent the first line of each block.} This should \emph{not} be a footnote reference, because it contains-a space.[\^{}my note] Here is an inline-note.\footnote{ This is \emph{easier} to type. Inline notes may contain+a space.[\^{}my note] Here is an inline note.%+\footnote{This is \emph{easier} to type. Inline notes may contain \href{http://google.com}{links} and \verb!]! verbatim characters,-as well as [bracketed text].-}+as well as [bracketed text].} \begin{quote}-Notes can go in quotes.\footnote{ In quote.-}+Notes can go in quotes.%+\footnote{In quote.} \end{quote} \begin{enumerate}[1.] \item - And in list items.\footnote{ In list.-}+ And in list items.%+ \footnote{In list.} \end{enumerate} This paragraph should not be part of the note, as it is not indented.
tests/writer.man view
@@ -72,34 +72,6 @@ .PP This should not be a block quote: 2 > 1\. .PP-Box-style:-.RS-.PP-Example:-.PP-\f[CR]- sub\ status\ {- \ \ \ \ print\ \"working\";- }-\f[]-.RE-.RS-.IP "1." 3-do laundry-.IP "2." 3-take out the trash-.RE-.PP-Here's a nested one:-.RS-.PP-Joe said:-.RS-.PP-Don't quote me\.-.RE-.RE-.PP And a following paragraph\. .PP * * * * *@@ -574,24 +546,22 @@ * * * * * .SH LaTeX .IP \[bu] 2-\\cite[22-23]{smith\.1899} .IP \[bu] 2-\\doublespacing .IP \[bu] 2-$2+2=4$+\f[B]2+2=4\f[] .IP \[bu] 2-$x\ \\in\ y$+\f[B]x\ \\in\ y\f[] .IP \[bu] 2-$\\alpha\ \\wedge\ \\omega$+\f[B]\\alpha\ \\wedge\ \\omega\f[] .IP \[bu] 2-$223$+\f[B]223\f[] .IP \[bu] 2-$p$-Tree+\f[B]p\f[]-Tree .IP \[bu] 2-$\\frac{d}{dx}f(x)=\\lim_{h\\to\ 0}\\frac{f(x+h)-f(x)}{h}$+\f[B]\\frac{d}{dx}f(x)=\\lim_{h\\to\ 0}\\frac{f(x+h)-f(x)}{h}\f[] .IP \[bu] 2 Here's one that has a line break in it:-$\\alpha\ +\ \\omega\ \\times\ x^2$\.+\f[B]\\alpha\ +\ \\omega\ \\times\ x^2\f[]\. .PP These shouldn't be math: .IP \[bu] 2@@ -604,11 +574,6 @@ .PP Here's a LaTeX table: .PP-\\begin{tabular}{|l|l|}\\hline-Animal\ &\ Number\ \\\\\ \\hline-Dog\ \ \ \ &\ 2\ \ \ \ \ \ \\\\-Cat\ \ \ \ &\ 1\ \ \ \ \ \ \\\\\ \\hline-\\end{tabular} .PP * * * * * .SH Special Characters
tests/writer.markdown view
@@ -74,23 +74,6 @@ This should not be a block quote: 2 > 1. -Box-style:--> Example:-> -> sub status {-> print "working";-> }--> 1. do laundry-> 2. take out the trash--Here's a nested one:--> Joe said:-> -> > Don't quote me.- And a following paragraph.
tests/writer.native view
@@ -39,20 +39,6 @@ [ Para [Str "nested"] ] ] , Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1",Str "."]-, Para [Str "Box",Str "-",Str "style:"]-, BlockQuote- [ Para [Str "Example:"]- , CodeBlock "sub status {\n print \"working\";\n}" ]-, BlockQuote- [ OrderedList (1,Decimal,Period)- [ [ Plain [Str "do",Space,Str "laundry"] ]- , [ Plain [Str "take",Space,Str "out",Space,Str "the",Space,Str "trash"] ] ] ]-, Para [Str "Here",Apostrophe,Str "s",Space,Str "a",Space,Str "nested",Space,Str "one:"]-, BlockQuote- [ Para [Str "Joe",Space,Str "said:"]- , BlockQuote- [ Para [Str "Don",Apostrophe,Str "t",Space,Str "quote",Space,Str "me",Str "."] ]- ] , Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph",Str "."] , HorizontalRule , Header 1 [Str "Code",Space,Str "Blocks"]@@ -297,13 +283,13 @@ , BulletList [ [ Plain [TeX "\\cite[22-23]{smith.1899}"] ] , [ Plain [TeX "\\doublespacing"] ]- , [ Plain [TeX "$2+2=4$"] ]- , [ Plain [TeX "$x \\in y$"] ]- , [ Plain [TeX "$\\alpha \\wedge \\omega$"] ]- , [ Plain [TeX "$223$"] ]- , [ Plain [TeX "$p$",Str "-",Str "Tree"] ]- , [ Plain [TeX "$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}$"] ]- , [ Plain [Str "Here",Apostrophe,Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,TeX "$\\alpha + \\omega \\times x^2$",Str "."] ] ]+ , [ Plain [Math "2+2=4"] ]+ , [ Plain [Math "x \\in y"] ]+ , [ Plain [Math "\\alpha \\wedge \\omega"] ]+ , [ Plain [Math "223"] ]+ , [ Plain [Math "p",Str "-",Str "Tree"] ]+ , [ Plain [Math "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"] ]+ , [ Plain [Str "Here",Apostrophe,Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Math "\\alpha + \\omega \\times x^2",Str "."] ] ] , Para [Str "These",Space,Str "shouldn",Apostrophe,Str "t",Space,Str "be",Space,Str "math:"] , BulletList [ [ Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code "$e = mc^2$",Str "."] ]
tests/writer.rst view
@@ -93,30 +93,6 @@ This should not be a block quote: 2 > 1. -Box-style:-- Example:-- ::-- sub status {- print "working";- }--- - 1. do laundry- 2. take out the trash---Here's a nested one:-- Joe said:-- Don't quote me.--- And a following paragraph. --------------@@ -155,52 +131,52 @@ Asterisks tight: -- asterisk 1-- asterisk 2-- asterisk 3+- asterisk 1+- asterisk 2+- asterisk 3 Asterisks loose: -- asterisk 1+- asterisk 1 -- asterisk 2+- asterisk 2 -- asterisk 3+- asterisk 3 Pluses tight: -- Plus 1-- Plus 2-- Plus 3+- Plus 1+- Plus 2+- Plus 3 Pluses loose: -- Plus 1+- Plus 1 -- Plus 2+- Plus 2 -- Plus 3+- Plus 3 Minuses tight: -- Minus 1-- Minus 2-- Minus 3+- Minus 1+- Minus 2+- Minus 3 Minuses loose: -- Minus 1+- Minus 1 -- Minus 2+- Minus 2 -- Minus 3+- Minus 3 Ordered@@ -243,10 +219,10 @@ Multiple paragraphs: -1. Item 1, graf one.+1. Item 1, graf one. - Item 1. graf two. The quick brown fox jumped over the lazy dog's- back.+ Item 1. graf two. The quick brown fox jumped over the lazy dog's+ back. 2. Item 2. @@ -257,11 +233,11 @@ ------ -- Tab- - - Tab- - - Tab+- Tab+ + - Tab+ + - Tab @@ -269,11 +245,11 @@ 1. First-2. Second:- - - Fee- - Fie- - Foe+2. Second:+ + - Fee+ - Fie+ - Foe 3. Third @@ -282,12 +258,12 @@ 1. First -2. Second:+2. Second: - - - Fee- - Fie- - Foe+ + - Fee+ - Fie+ - Foe 3. Third @@ -296,14 +272,14 @@ --------------- -- this is a list item indented with tabs+- this is a list item indented with tabs -- this is a list item indented with spaces+- this is a list item indented with spaces - - - this is an example list item indented with tabs+ + - this is an example list item indented with tabs - - this is an example list item indented with spaces+ - this is an example list item indented with spaces @@ -328,13 +304,13 @@ Nesting: -A. Upper Alpha- - I. Upper Roman.- - (6) Decimal start with 6- - c) Lower alpha with paren+A. Upper Alpha+ + I. Upper Roman.+ + (6) Decimal start with 6+ + c) Lower alpha with paren @@ -343,9 +319,9 @@ #. Autonumber.-#. More.- - #. Nested.+#. More.+ + #. Nested. Should not be a list item:@@ -642,36 +618,29 @@ ===== -- \cite[22-23]{smith.1899}-- \doublespacing-- $2+2=4$-- $x \in y$-- $\alpha \wedge \omega$-- $223$-- $p$-Tree-- $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$-- Here's one that has a line break in it:- $\alpha + \omega \times x^2$.+- +- +- $2+2=4$+- $x \in y$+- $\alpha \wedge \omega$+- $223$+- $p$-Tree+- $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$+- Here's one that has a line break in it:+ $\alpha + \omega \times x^2$. These shouldn't be math: -- To get the famous equation, write ``$e = mc^2$``.-- $22,000 is a *lot* of money. So is $34,000. (It worked if "lot"- is emphasized.)-- Escaped ``$``: $73 *this should be emphasized* 23$.+- To get the famous equation, write ``$e = mc^2$``.+- $22,000 is a *lot* of money. So is $34,000. (It worked if "lot"+ is emphasized.)+- Escaped ``$``: $73 *this should be emphasized* 23$. Here's a LaTeX table: -.. raw:: latex - \begin{tabular}{|l|l|}\hline- Animal & Number \\ \hline- Dog & 2 \\- Cat & 1 \\ \hline- \end{tabular}- -------------- Special Characters@@ -680,11 +649,11 @@ Here is some unicode: -- I hat: Î-- o umlaut: ö-- section: §-- set membership: ∈-- copyright: ©+- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: © AT&T has an ampersand in their name. @@ -802,9 +771,9 @@ With an ampersand: http://example.com/?foo=1&bar=2 -- In a list?-- http://example.com/-- It should.+- In a list?+- http://example.com/+- It should. An e-mail address: nobody@nowhere.net
tests/writer.rtf view
@@ -43,16 +43,6 @@ {\pard \ql \f0 \sa180 \li1440 \fi0 nested\par} {\pard \ql \f0 \sa180 \li1440 \fi0 nested\par} {\pard \ql \f0 \sa180 \li0 \fi0 This should not be a block quote: 2 > 1.\par}-{\pard \ql \f0 \sa180 \li0 \fi0 Box-style:\par}-{\pard \ql \f0 \sa180 \li720 \fi0 Example:\par}-{\pard \ql \f0 \sa180 \li720 \fi0 \f1 sub status \{\line- print "working";\line-\}\par}-{\pard \ql \f0 \sa0 \li1080 \fi-360 1.\tx360\tab do laundry\par}-{\pard \ql \f0 \sa0 \li1080 \fi-360 2.\tx360\tab take out the trash\sa180\par}-{\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's a nested one:\par}-{\pard \ql \f0 \sa180 \li720 \fi0 Joe said:\par}-{\pard \ql \f0 \sa180 \li1440 \fi0 Don\u8217't quote me.\par} {\pard \ql \f0 \sa180 \li0 \fi0 And a following paragraph.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Code Blocks\par}@@ -250,25 +240,21 @@ {\pard \ql \f0 \sa180 \li0 \fi0 Ellipses\u8230?and\u8230?and\u8230?.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 LaTeX\par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\cf1 \\cite[22-23]\{smith.1899\}\cf0 } \par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\cf1 \\doublespacing\cf0 } \par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\cf1 $2+2=4$\cf0 } \par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\cf1 $x \\in y$\cf0 } \par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\cf1 $\\alpha \\wedge \\omega$\cf0 } \par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\cf1 $223$\cf0 } \par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\cf1 $p$\cf0 } -Tree\par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\cf1 $\\frac\{d\}\{dx\}f(x)=\\lim_\{h\\to 0\}\\frac\{f(x+h)-f(x)\}\{h\}$\cf0 } \par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Here\u8217's one that has a line break in it: {\cf1 $\\alpha + \\omega \\times x^2$\cf0 } .\sa180\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab \par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab \par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab 2+2=4\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i x} \u8201?\u8712?\u8201?{\i y} \par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab \u945?\u8201?\u8743?\u8201?\u969?\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab 223\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i p} -Tree\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab \\frac\{{\i d} \}\{{\i dx} \}{\i f} ({\i x} )=\\lim{\sub {\i h} \u8201?\u8594?\u8201?0} \\frac\{{\i f} ({\i x} +{\i h} )-{\i f} ({\i x} )\}\{{\i h} \}\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Here\u8217's one that has a line break in it: \u945?+\u969?\u8201?\u215?\u8201?{\i x} {\super 2} .\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 These shouldn\u8217't be math:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab To get the famous equation, write {\f1 $e = mc^2$} .\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab $22,000 is a {\i lot} of money. So is $34,000. (It worked if \u8220"lot\u8221" is emphasized.)\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Escaped {\f1 $} : $73 {\i this should be emphasized} 23$.\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here\u8217's a LaTeX table:\par}-{\pard \ql \f0 \sa180 \li0 \fi0 {\cf1 \\begin\{tabular\}\{|l|l|\}\\hline-Animal & Number \\\\ \\hline-Dog & 2 \\\\-Cat & 1 \\\\ \\hline-\\end\{tabular\}\cf0 } \par}+{\pard \ql \f0 \sa180 \li0 \fi0 \par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 Special Characters\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here is some unicode:\par}
web/Makefile view
@@ -1,6 +1,6 @@-ALL := index.html README.html INSTALL.html examples.html pandoc1.html markdown2pdf1.html html2markdown1.html hsmarkdown1.html+ALL := index.html README.html INSTALL.html examples.html pandoc1.html markdown2pdf1.html html2markdown1.html hsmarkdown1.html html2x.html PANDOC_PATH ?= $(dir $(shell which pandoc))-MAKEPAGE = $(PANDOC_PATH)/pandoc -s -S -c pandoc.css -A footer.html+MAKEPAGE = $(PANDOC_PATH)/pandoc -s -S -H css -A footer.html all : $(ALL) .PHONY: clean@@ -15,23 +15,23 @@ do highlight -k monospace -u utf-8 --style emacs $$file > $$file.html; \ done -index.html : index.txt+index.html : index.txt css $(MAKEPAGE) --toc $< > $@ -README.html : README+README.html : README css $(MAKEPAGE) --toc $< > $@ -INSTALL.html : INSTALL+INSTALL.html : INSTALL css $(MAKEPAGE) --toc $< > $@ -%.html : %.txt+%.html : %.txt css $(MAKEPAGE) $< > $@ -%1.html : %.1+%1.html : %.1 groff -man -T html $< > $@ -%.html : %+%.html : % css $(MAKEPAGE) $< > $@ upload : - sitecopy --update macfarlane + make -C .. upload
+ web/css view
@@ -0,0 +1,8 @@+<link rel="stylesheet" type="text/css" href="pandoc.css" media="all" />+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">+</script>+<script type="text/javascript">+_uacct = "UA-2234613-4";+urchinTracker();+</script>+
web/demos view
@@ -5,70 +5,81 @@ 1. HTML fragment: -@ pandoc README -o example1.html+@ pandoc @@README@@ -o @@example1.html@@ 2. Standalone HTML file: -@ pandoc -s README -o example2.html+@ pandoc -s @@README@@ -o @@example2.html@@ 3. HTML with smart quotes, table of contents, CSS, and custom footer: -@ pandoc -s -S --toc -c pandoc.css -A footer.html README -o example3.html+@ pandoc -s -S --toc -c @@pandoc.css@@ -A @@footer.html@@ @@README@@ -o @@example3.html@@ 4. LaTeX: -@ pandoc -s README -o example4.tex+@ pandoc -s @@README@@ -o @@example4.tex@@ 5. From LaTeX to markdown: -@ pandoc -s example4.tex -o example5.text+@ pandoc -s @@example4.tex@@ -o @@example5.text@@ 6. reStructuredText: -@ pandoc -s -w rst --toc README -o example6.text+@ pandoc -s -w rst --toc @@README@@ -o @@example6.text@@ 7. Rich text format (RTF): -@ pandoc -s README -o example7.rtf +@ pandoc -s @@README@@ -o @@example7.rtf@@ 8. S5 HTML slide show (all in one file): -@ pandoc -s -m -i -w s5 S5DEMO -o example8.html+@ pandoc -s -m -i -w s5 @@S5DEMO@@ -o @@example8.html@@ 9. DocBook XML: -@ pandoc -s -S -w docbook README -o example9.db+@ pandoc -s -S -w docbook @@README@@ -o @@example9.db@@ Chunked XHTML via DocBook and [xmlto]: -@ xmlto xhtml -m config.xsl example9.db -o example9/+@ xmlto xhtml -m @@config.xsl@@ @@example9.db@@ -o @@example9/@@ 10. Man page: -@ pandoc -s -w man pandoc.1.md -o example10.1+@ pandoc -s -w man @@pandoc.1.md@@ -o @@example10.1@@ 11. ConTeXt: -@ pandoc -s -w context README -o example11.tex+@ pandoc -s -w context @@README@@ -o @@example11.tex@@ PDF via pandoc and ConTeXt's `texexec`: -@ texexec --pdf example11.tex --result example11.pdf+@ texexec --pdf @@example11.tex@@ # produces @@example11.pdf@@ 12. Converting a web page to markdown: -@ html2markdown http://www.gnu.org/software/make/ -o example12.text+@ html2markdown @@http://www.gnu.org/software/make/@@ -o @@example12.text@@ 13. From markdown to PDF: -@ markdown2pdf README -o example13.pdf+@ markdown2pdf @@README@@ -o @@example13.pdf@@ 14. PDF with numbered sections and a custom LaTeX header: -@ markdown2pdf -N -C myheader.tex README -o example14.pdf+@ markdown2pdf -N -C @@myheader.tex@@ @@README@@ -o @@example14.pdf@@ [xmlto]: http://cyberelk.net/tim/xmlto/ 15. A simple wiki program using [HAppS](http://happs.org) and pandoc: [pandocwiki](http://pandocwiki.googlecode.com/svn/trunk/)++16. A web application that converts web pages to any of eight different+ formats: [html2x](html2x.html).++17. TeX math in HTML:++@ pandoc @@math.txt@@ -s -o @@mathDefault.html@@+@ pandoc @@math.txt@@ -s -m -o @@mathAsciimathml.html@@+@ pandoc @@math.txt@@ -s --mimetex=/cgi-bin/mimetex.cgi -o @@mathMimetex.html@@+@ pandoc @@math.txt@@ -s --gladtex -o mathGladtex.htex+@ gladtex @@mathGladtex.htex@@ # produces @@mathGladtex.html@@
@@ -1,4 +1,4 @@ <div id="footer">- © 2006-2007 <a href="http://sophos.berkeley.edu/macfarlane/">John MacFarlane</a>+ © 2006-2007 <a href="http://johnmacfarlane.net/">John MacFarlane</a> </div>
+ web/html2x.txt view
@@ -0,0 +1,55 @@+% html2x++<form action="/cgi-bin/html2x.pl" method="get">+<p>+<label for="url">URL:</label>+<input type="text" size="60" name="url" value="http://johnmacfarlane.net/pandoc" /> +<input type="submit" value="Convert" />+</p>+<table>+<tr>+<th>Convert to:</th>+<th style="padding-left: 1em;">Bookmarklets<br/>(right-click, add bookmark)</th>+</tr>+<tr>+<td style="border-right: 1px solid gray; padding-right: 2em;">+<input type="radio" name="format" value="markdown" checked="checked" />Markdown<br/>+<input type="radio" name="format" value="markdown+" />Markdown with +<a href="/pandoc/README.html#pandocs-markdown-vs-standard-markdown">pandoc extensions</a><br/>+<input type="radio" name="format" value="rst" />reStructuredText<br/>+<input type="radio" name="format" value="docbook" />DocBook XML<br/>+<input type="radio" name="format" value="latex" />LaTeX<br/>+<input type="radio" name="format" value="context" />ConTeXt<br/>+<input type="radio" name="format" value="rtf" />Rich Text Format (RTF)<br/>+<input type="radio" name="format" value="man" />Groff man page+</td>+<td style="padding-left: 1em;">+- [2markdown]+- [2markdown+]+- [2rst]+- [2docbook]+- [2LaTeX]+- [2ConTeXt]+- [2RTF]+- [2man]+</td>+</table>+</form>++<center>+Powered by [pandoc]. Inspired by [the Asciinator].++</center>++[2markdown]: javascript:location.href='http://johnmacfarlane.net/cgi-bin/html2x.pl?format=markdown&url='+document.location.href;+[2markdown+]: javascript:location.href='http://johnmacfarlane.net/cgi-bin/html2x.pl?format=markdown+&url='+document.location.href;+[2rst]: javascript:location.href='http://johnmacfarlane.net/cgi-bin/html2x.pl?format=rst&url='+document.location.href;+[2docbook]: javascript:location.href='http://johnmacfarlane.net/cgi-bin/html2x.pl?format=docbook&url='+document.location.href;+[2LaTeX]: javascript:location.href='http://johnmacfarlane.net/cgi-bin/html2x.pl?format=latex&url='+document.location.href;+[2ConTeXt]: javascript:location.href='http://johnmacfarlane.net/cgi-bin/html2x.pl?format=context&url='+document.location.href;+[2RTF]: javascript:location.href='http://johnmacfarlane.net/cgi-bin/html2x.pl?format=rtf&url='+document.location.href;+[2man]: javascript:location.href='http://johnmacfarlane.net/cgi-bin/html2x.pl?format=man&url='+document.location.href;++[pandoc]: /pandoc/+[the Asciinator]: http://www.aaronsw.com/2002/html2text/+
web/index.txt.in view
@@ -20,7 +20,7 @@ - Unicode support. - Optional "smart" quotes, dashes, and ellipses. - Automatically generated tables of contents.-- [ASCIIMathML] support for equations in HTML.+- Support for displaying math in HTML. - Extensions to markdown syntax: + Document metadata (title, author, date). + Footnotes, tables, and definition lists.@@ -39,7 +39,8 @@ - Multi-platform: runs on Windows, MacOS X, Linux, Unix. - Free software, released under the [GPL]. -To see what pandoc can do, see the [demonstration page](examples.html).+To see what pandoc can do, see the [demonstration page](examples.html),+or [try pandoc on the web](/pandoc/try). # Documentation @@ -52,7 +53,7 @@ - [`hsmarkdown(1)`](hsmarkdown1.html) - [Library documentation](doc/index.html) (for Haskell programmers) - [Installation instructions](INSTALL.html)-- [Changelog](changelog)+- [Changelog](changelog.txt) # Downloads @@ -60,6 +61,8 @@ [INSTALL](INSTALL.html). Note that pandoc is in the [MacPorts], [Debian unstable], and [FreeBSD ports] repositories. Abhishek Dasgupta has also contributed an [Arch linux PKGBUILD script].+Starting with release 8.04 ("Hardy Heron"), pandoc will be included+in [Ubuntu linux]. - [Source tarball] - [Windows binary package]@@ -84,6 +87,27 @@ # News +- Version 0.45 released (December 9, 2007).++ + Many bug fixes and structural improvements. See [changelog] for+ full details.+ + Improved treatment of math. Math is now rendered using unicode+ by default in HTML, RTF, and DocBook output. For more accurate+ display of math in HTML, `--gladtex`, `--mimetex`, and `--asciimathml`+ options are provided. See the [User's Guide](README.html#math) for+ details.+ + Removed support for box-style block quotes in markdown.+ + More idiomatic ConTeXt output.+ + Text wrapping in ConTeXt and LaTeX output.+ + Pandoc now correctly handles all standard line endings+ (CR, LF, CRLF).+ + New `--no-wrap` option that disables line wrapping and minimizes+ whitespace in HTML output.+ + Build process is now compatible with both GHC 6.8 and GHC 6.6.+ GHC and GHC_PKG environment variables may be used to specify+ which version of the compiler to use, when multiple versions are+ installed.+ - Version 0.44 released (September 3, 2007). + Fixed bug in HTML writer: when `--toc` was used, anchors were put around@@ -109,54 +133,7 @@ + Markdown writer escapes paragraphs that begin like list items. + MacPorts Portfile now installs library as well as executable. + Added pandocwiki demonstration to the website.- -- Version 0.42 released (August 26, 2007). - + Fixes bugs in ordered list handling, LaTeX footnotes,- UTF8 in include files, and HTML tables. See [changelog] for details.- + Added new rule for enhanced ordered lists: capital letters- followed by periods must be separated from the list item by- two spaces, to avoid misinterpretation of initials. See- [README](README.html#lists) for details.- + Improved strict markdown compatibility.- + OSX packages are no longer supported. There were too many issues with- dynamic libraries. Instead, a MacPorts Portfile is now provided.- + Exposed Text.Pandoc.ASCIIMathML.--- Version 0.41 released (August 19, 2007).-- + Fixes bugs in the handling of ordered lists and raw HTML.- For details, see the [changelog].--- Version 0.4 released (August 15, 2007).-- For users:-- + New output formats: ConTeXt and groff man.- + Support for definition lists and tables.- + Support for superscript, subscript, and strikeout.- + Support for automatically generated tables of contents.- + Automatically generated unique identifiers in HTML headers.- + Enhanced ordered lists (start number and list number style- are now significant).- + Markdown links now printed as inline links by default,- unless `--reference-links` option is specified.- + Many bugs fixed.-- For programmers:-- + Added a Text.Pandoc module that exports the main functions- and data structures. Library documentation includes a sample- program using the library.-- Under the hood:-- + Refactored to avoid reliance on GHC's `Text.Regex`, which- is slow and does not support unicode.- + Removed Key and Note block elements and simplified parsers.- + Improved handling of character entities.- + HTML output is now generated using `Text.XHtml`.- # Disclaimer This is an early, "alpha" release. It carries no warranties of any@@ -166,7 +143,7 @@ [much faster]: http://code.google.com/p/pandoc/wiki/Benchmarks [ASCIIMathML]: http://www1.chapman.edu/~jipsen/mathml/asciimath.html -[John MacFarlane]: http://sophos.berkeley.edu/macfarlane/+[John MacFarlane]: http://johnmacfarlane.net/ [markdown]: http://daringfireball.net/projects/markdown/ [reStructuredText]: http://docutils.sourceforge.net/docs/ref/rst/introduction.html [S5]: http://meyerweb.com/eric/tools/s5/@@ -185,8 +162,9 @@ [Debian unstable]: http://packages.debian.org/unstable/text/pandoc [FreeBSD ports]: http://www.freshports.org/textproc/pandoc/ [Arch linux PKGBUILD script]: http://aur.archlinux.org/packages.php?do_Details=1&ID=12751&O=0&L=0&C=0&K=pandoc&SB=n&SO=a&PP=25&do_MyPackages=0&do_Orphans=0&SeB=nd-[MacPorts]: http://www.macports.org/+[Ubuntu linux]: http://www.ubuntu.com+[MacPorts]: http://db.macports.org/port/show/4218 [pandoc-announce]: http://groups.google.com/group/pandoc-announce [pandoc-discuss]: http://groups.google.com/group/pandoc-discuss-[changelog]: changelog+[changelog]: changelog.txt
+ web/math.txt view
@@ -0,0 +1,17 @@+% Pandoc math demos++$a^2 + b^2 = c^2$++$v(t) = v_0 + \frac{1}{2}at^2$++$\gamma = \frac{1}{\sqrt{1 - v^2/c^2}}$ ++$\exists x \forall y (Rxy \equiv Ryx)$++$p \wedge q \models p$++$\Box\diamond p\equiv\diamond p$++$\int_{0}^{1} x dx = \left[ \frac{1}{2}x^2 \right]_{0}^{1} = \frac{1}{2}$++$e^x = \sum_{n=0}^\infty \frac{x^n}{n!} = \lim_{n\rightarrow\infty} (1+x/n)^n$
web/mkdemos.pl view
@@ -14,13 +14,16 @@ my $firstchar = substr ($line,0,1); if ( $firstchar eq '@' ) { my $command = substr ($line,4);- print STDERR "$command";- system "$command";+ my $commandExec = $command;+ $commandExec =~ s/[#].*$//g; # strip off comments+ $commandExec =~ s/@@//g; # strip off hotlink markers+ print STDERR "$commandExec";+ system "$commandExec"; $line = $command; $line =~ s/-/\-/;- $line =~ s/ ([A-Za-z0-9_:\/]+(\.|\/)[a-zA-Z0-9.\/]*|README|S5DEMO)/ <a href="$1">$1<\/a>/g;- $line =~ s/-/\\-/g;- $line =~ s/^(.*)$/ <code>$1<\/code>/g; + $line =~ s/@@([^@]*)@@/<a href="$1">$1<\/a>/g;+ $line =~ s/-/\\-/g; # to prevent smart dashes!+ $line =~ s/^(.*)$/ <pre><code>$1<\/code><\/pre>/g; if ( $line =~ /(example\d+\.html)<\/a><\/code>/m ) { $line .= "\n (View [`$1` as a web page]($1).)\n"; }
+ wrappers/common.sh view
@@ -0,0 +1,43 @@+THIS=${0##*/}++NEWLINE='+'++err () { echo "$*" | fold -s -w ${COLUMNS:-110} >&2; }+errn () { printf "$*" | fold -s -w ${COLUMNS:-110} >&2; }++usage () {+ err "$1 - $2" # short description+ err "See the $1(1) man page for usage."+}++# Portable which(1).+pathfind () {+ oldifs="$IFS"; IFS=':'+ for _p in $PATH; do+ if [ -x "$_p/$*" ] && [ -f "$_p/$*" ]; then+ IFS="$oldifs"+ return 0+ fi+ done+ IFS="$oldifs"+ return 1+}++for p in pandoc $REQUIRED; do+ pathfind $p || {+ err "You need '$p' to use this program!"+ exit 1+ }+done++CONF=$(pandoc --dump-args "$@" 2>&1) || {+ errcode=$?+ echo "$CONF" | sed -e '/^pandoc \[OPTIONS\] \[FILES\]/,$d' >&2+ [ $errcode -eq 2 ] && usage "$THIS" "$SYNOPSIS"+ exit $errcode+}++OUTPUT=$(echo "$CONF" | sed -ne '1p')+ARGS=$(echo "$CONF" | sed -e '1d')+
+ wrappers/hsmarkdown.in view
@@ -0,0 +1,5 @@+#!/bin/sh+# hsmarkdown - intended as a drop-in replacement for Markdown.pl.+# Uses pandoc to convert from markdown to HTML, using --strict mode+# for maximum compatibility with official markdown syntax.+exec pandoc --from markdown --to html --strict -- "$@"
+ wrappers/html2markdown.in view
@@ -0,0 +1,162 @@+#!/bin/sh -e+# converts HTML from a URL, file, or stdin to markdown+# uses an available program to fetch URL and tidy to normalize it first++REQUIRED="tidy"+SYNOPSIS="converts HTML from a URL, file, or STDIN to markdown-formatted text."++### common.sh++grab_url_with () {+ url="${1:?internal error: grab_url_with: url required}"++ shift+ cmdline="$@"++ prog=+ prog_opts=+ if [ -n "$cmdline" ]; then+ eval "set -- $cmdline"+ prog=$1+ shift+ prog_opts="$@"+ fi++ if [ -z "$prog" ]; then+ # Locate a sensible web grabber (note the order).+ for p in wget lynx w3m curl links w3c; do+ if pathfind $p; then+ prog=$p+ break+ fi+ done++ [ -n "$prog" ] || {+ errn "$THIS: Couldn't find a program to fetch the file from URL "+ err "(e.g. wget, w3m, lynx, w3c, or curl)."+ return 1+ }+ else+ pathfind "$prog" || {+ err "$THIS: No such web grabber '$prog' found; aborting."+ return 1+ }+ fi++ # Setup proper base options for known grabbers.+ base_opts=+ case "$prog" in+ wget) base_opts="-O-" ;;+ lynx) base_opts="-source" ;;+ w3m) base_opts="-dump_source" ;;+ curl) base_opts="" ;;+ links) base_opts="-source" ;;+ w3c) base_opts="-n -get" ;;+ *) err "$THIS: unhandled web grabber '$prog'; hope it succeeds."+ esac++ err "$THIS: invoking '$prog $base_opts $prog_opts $url'..."+ eval "set -- $base_opts $prog_opts"+ $prog "$@" "$url"+}++# Parse command-line arguments+parse_arguments () {+ while [ $# -gt 0 ]; do+ case "$1" in+ --encoding=*)+ wholeopt="$1"+ # extract encoding from after =+ encoding="${wholeopt#*=}" ;;+ -e|--encoding|-encoding)+ shift+ encoding="$1" ;; + --grabber=*)+ wholeopt="$1"+ # extract encoding from after =+ grabber="\"${wholeopt#*=}\"" ;;+ -g|--grabber|-grabber)+ shift+ grabber="$1" ;; + *)+ if [ -z "$argument" ]; then+ argument="$1"+ else+ err "Warning: extra argument '$1' will be ignored."+ fi ;;+ esac+ shift+ done+}++argument=+encoding=+grabber=++oldifs="$IFS"+IFS=$NEWLINE+parse_arguments $ARGS+IFS="$oldifs"++inurl=+if [ -n "$argument" ] && ! [ -f "$argument" ]; then+ # Treat given argument as an URL.+ inurl="$argument"+fi++### tempdir.sh++if [ -n "$inurl" ]; then+ err "Attempting to fetch file from '$inurl'..."++ grabber_out=$THIS_TEMPDIR/grabber.out+ grabber_log=$THIS_TEMPDIR/grabber.log+ if ! grab_url_with "$inurl" "$grabber" 1>$grabber_out 2>$grabber_log; then+ errn "grab_url_with failed"+ if [ -f $grabber_log ]; then+ err " with the following error log."+ err+ cat >&2 $grabber_log+ else+ err .+ fi+ exit 1+ fi++ argument="$grabber_out"+fi++if [ -z "$encoding" ] && [ "x$argument" != "x" ]; then+ # Try to determine character encoding if not specified+ # and input is not STDIN.+ encoding=$(+ head "$argument" |+ LC_ALL=C tr 'A-Z' 'a-z' |+ sed -ne '/<meta .*content-type.*charset=/ {+ s/.*charset=["'\'']*\([-a-zA-Z0-9]*\).*["'\'']*/\1/p+ }'+ )+fi++if [ -n "$encoding" ] && pathfind iconv; then+ alias to_utf8='iconv -f "$encoding" -t utf-8'+else # assume UTF-8+ alias to_utf8='cat'+fi ++htmlinput=$THIS_TEMPDIR/htmlinput++if [ -z "$argument" ]; then+ to_utf8 > $htmlinput # read from STDIN+elif [ -f "$argument" ]; then+ to_utf8 "$argument" > $htmlinput # read from file+else+ err "File '$argument' not found."+ exit 1+fi++if ! cat $htmlinput | pandoc --ignore-args -r html -w markdown "$@" ; then+ err "Failed to parse HTML. Trying again with tidy..."+ tidy -q -asxhtml -utf8 $htmlinput | \+ pandoc --ignore-args -r html -w markdown "$@"+fi
+ wrappers/markdown2pdf.in view
@@ -0,0 +1,81 @@+#!/bin/sh -e++REQUIRED="pdflatex"+SYNOPSIS="converts markdown-formatted text to PDF, using pdflatex."++### common.sh++### tempdir.sh++texname=output+logfile=$THIS_TEMPDIR/log++pandoc -s -r markdown -w latex "$@" -o $THIS_TEMPDIR/$texname.tex++if [ "$OUTPUT" = "-" ]; then+ firstinfile="$(echo $ARGS | sed -ne '1p')"+ firstinfilebase="${firstinfile%.*}"+ destname="${firstinfilebase:-stdin}.pdf"+else+ destname="$OUTPUT"+fi++(+ origdir=$(pwd)+ cd $THIS_TEMPDIR+ TEXINPUTS=$origdir:$TEXINPUTS:+ export TEXINPUTS+ finished=no+ runs=0+ while [ $finished = "no" ]; do+ pdflatex -interaction=batchmode $texname.tex >/dev/null || {+ errcode=$?+ err "${THIS}: pdfLaTeX failed with error code $errcode"+ [ -f $texname.log ] && {+ err "${THIS}: error context:"+ sed -ne '/^!/,/^[[:space:]]*$/p' \+ -ne '/^[Ll]a[Tt]e[Xx] [Ww]arning/,/^[[:space:]]*$/p' \+ -ne '/^[Ee]rror/,/^[[:space:]]*$/p' $texname.log >&2+ if grep -q "File \`ucs.sty' not found" $texname.log; then+ err "${THIS}: Please install the 'unicode' package from CTAN:"+ err " http://www.ctan.org/tex-archive/macros/latex/contrib/unicode/"+ fi+ if grep -q "File \`ulem.sty' not found" $texname.log; then+ err "${THIS}: Please install the 'ulem' package from CTAN:"+ err " http://www.ctan.org/tex-archive/macros/latex/contrib/misc/ulem.sty"+ fi+ }+ exit $errcode+ }+ if [ $runs -lt 3 ] && + ((grep -q "LaTeX Warning: There were undefined references." $texname.log) ||+ (echo "$@" | grep -q -- "--toc\|--table-of-contents")); then+ runs=$(($runs + 1))+ if grep -q "LaTeX Warning:.*[Cc]itation" $texname.log; then+ bibtex $texname 2>&1 >bibtex.err+ if [ $runs -gt 2 ]; then+ if grep -q "error message" bibtex.err ||+ grep -q "Warning" bibtex.err; then+ cat bibtex.err >&2+ fi+ fi+ fi+ else+ finished=yes+ fi+ done+) || exit $?++is_target_exists=+if [ -f "$destname" ]; then+ is_target_exists=1+ mv "$destname" "$destname~" +fi++mv -f $THIS_TEMPDIR/$texname.pdf "$destname"++errn "Created $destname"+[ -z "$is_target_exists" ] || {+ errn " (previous file has been backed up as $destname~)"+}+err .
+ wrappers/tempdir.sh view
@@ -0,0 +1,18 @@+# As a security measure refuse to proceed if mktemp is not available.+pathfind mktemp || { err "Couldn't find 'mktemp'; aborting."; exit 1; }++# Avoid issues with /tmp directory on Windows/Cygwin +cygwin=+cygwin=$(uname | sed -ne '/^CYGWIN/p')+if [ -n "$cygwin" ]; then+ TMPDIR=.+ export TMPDIR+fi++THIS_TEMPDIR=+THIS_TEMPDIR="$(mktemp -d -t $THIS.XXXXXXXX)" || exit 1+readonly THIS_TEMPDIR++trap 'exitcode=$?+ [ -z "$THIS_TEMPDIR" ] || rm -rf "$THIS_TEMPDIR"+ exit $exitcode' 0 1 2 3 13 15